XRPLF / xrpl.js

A JavaScript/TypeScript API for interacting with the XRP Ledger in Node.js and the browser
https://xrpl.org/
1.2k stars 511 forks source link

Validation Error for Payments #829

Closed icemilo closed 6 years ago

icemilo commented 6 years ago

Hi there, There is one validation error which is very strange that I saw today. I was unable to find the cause for this error. There were two payments, but with same JSON object when preparing payment.

First payment object {"source":{"address":"*****x4K1tCcDxgPTyuqJY56sZcj8DtXvD","amount":{"value":"30","currency":"XRP"}},"destination":{"address":"*****Ju1Rvmbq476Y7PDnvnXUeERV9CxEQ","minAmount":{"value":"30","currency":"XRP"},"tag":49971277}}

Second payment object {"source":{"address":"*****x4K1tCcDxgPTyuqJY56sZcj8DtXvD","amount":{"value":"374","currency":"XRP"}},"destination":{"address":"*****Ju1Rvmbq476Y7PDnvnXUeERV9CxEQ","minAmount":{"value":"374","currency":"XRP"},"tag":51598344}}

First payment object threw the error instance.payment.destination is not exactly one from <destinationExactAdjustment>,<minAdjustment>

But the second payment object got through successfully. Please note that I masked the addresses for privacy and it is a proper XRP address.

Could I get some advice?

intelliot commented 6 years ago

Hi @icemilo ,

I don't see an issue with the JSON objects. If this error is reproducible, could you post an example of the code that you're using?

Thanks!

ghost commented 6 years ago

@intelliot:

const RippleAPI = require('ripple-lib').RippleAPI;
const api = new RippleAPI({server: 'wss://s.altnet.rippletest.net:51233'});

api.connect().then(() => {
  const address = 'rHFoRRShxJvxenoAbCsgZbfX9Qk9DQ7kG6';
  const payment = {
    'source': {
      'address': address,
      'maxAmount': {
        'value': 10,
        'currency': 'XRP'
      }
    },
    'destination': {
      'address': 'rJ17yYfU7yioRUsfXUdVJ6rE9at7mv2QJa',
      'maxAmount': {
        'value': 10,
        'currency': 'XRP'
      }
    }
  }
  api.preparePayment(address, payment, {}).then(prepared => {
    console.log(prepared);
  });
}).catch(console.error);

The above code gives me the same error:

[ValidationError(instance.payment.source is not exactly one from <sourceExactAdjustment>,<maxAdjustment>,instance.payment.destination is not exactly one from <destinationExactAdjustment>,<minAdjustment>)]

icemilo commented 6 years ago

Hi @intelliot, thanks for replying. We actually found out the cause for this issue where our address was wrong. The address got validated for the regular expression but could not decode using ripple-address-codec which was one of the validation steps. We found out that one of the alphabet in the address was not capitalized properly.

@Zelest Could you double check the address using ripple-address-codec library?

ghost commented 6 years ago

@icemilo I'm not sure I use ripple-address-codec correctly, but if I try to decode the address and encode it back again, it generates the same address. Which I assume is correct?

intelliot commented 6 years ago

@Zelest There are two issues with your code:

1) The value should be a string. In other words, you should use '10' (with quotes). 2) The property destination.maxAmount isn't part of the Payment spec. Perhaps you meant to use amount?

Here's your code with the above changes applied:

const RippleAPI = require('ripple-lib').RippleAPI;
const api = new RippleAPI({server: 'wss://s.altnet.rippletest.net:51233'});

api.connect().then(() => {
  const address = 'rHFoRRShxJvxenoAbCsgZbfX9Qk9DQ7kG6';
  const payment = {
    'source': {
      'address': address,
      'maxAmount': {
        'value': '10',
        'currency': 'XRP'
      }
    },
    'destination': {
      'address': 'rJ17yYfU7yioRUsfXUdVJ6rE9at7mv2QJa',
      'amount': {
        'value': '10',
        'currency': 'XRP'
      }
    }
  }
  api.preparePayment(address, payment, {}).then(prepared => {
    console.log(prepared);
  });
}).catch(console.error);

Does that work for you?

ghost commented 6 years ago

@intelliot Oh! You're absolutely right and the above code works just fine! Thanks a lot! Note to self, avoid trying to write code with a 103 degree fever. 🤒

intelliot commented 6 years ago

No problem! I'm glad to help, and I hope you feel better soon. I'll also have a look at making our documentation clearer :)

fedecaccia commented 4 years ago

@zelest There are two issues with your code:

1. The `value` should be a string. In other words, you should use `'10'` (with quotes).

2. The property `destination.maxAmount` isn't part of the [Payment spec](https://ripple.com/build/rippleapi/#payment). Perhaps you meant to use `amount`?

Here's your code with the above changes applied:

const RippleAPI = require('ripple-lib').RippleAPI;
const api = new RippleAPI({server: 'wss://s.altnet.rippletest.net:51233'});

api.connect().then(() => {
  const address = 'rHFoRRShxJvxenoAbCsgZbfX9Qk9DQ7kG6';
  const payment = {
    'source': {
      'address': address,
      'maxAmount': {
        'value': '10',
        'currency': 'XRP'
      }
    },
    'destination': {
      'address': 'rJ17yYfU7yioRUsfXUdVJ6rE9at7mv2QJa',
      'amount': {
        'value': '10',
        'currency': 'XRP'
      }
    }
  }
  api.preparePayment(address, payment, {}).then(prepared => {
    console.log(prepared);
  });
}).catch(console.error);

Does that work for you?

I tried it and that works, but when I tried to sign the payment, I get the following error: UnhandledPromiseRejectionWarning: ValidationError: instance.txJSON is not of a type(s) string

I signed it using api.sign(prepared, mySecret)