xrpl.js
xrpl.js copied to clipboard
Bug when transfer small number of token use scientific notation
const send_token_tx = {
"TransactionType": "Payment",
"Account": from.address,
"Amount": {
"currency": tk_name,
"value": tk_amount, // <==
"issuer": tk_issuer
},
...
}
The value of 'Amount' can accept plain decimal "0.0000000000123456789123" and send Tx successfully.
But , if use scientific notation, such as (123456789123400e-26).toString()
or (1.000005678901234e-10).toString()
, alway raise error ValidationError: Serialized transaction does not match original txJSON. See error.data
.
As comparison, send big number use 1.012345678901234e+19
is ok.
I find the cause by another case that set trustline with a huge value (9e+51).toString()
.
In node_modules/xrpl/dist/npm/Wallet/index.js
file, inside checkTxSerialization()
function,
the decoded.LimitAmount.value
is '9000000000000000000000000000000000000000000000000000',
while the txCopy.LimitAmount.value
still is 9e+51
.
thus won't pass the equal check.
I believe it is the same root for (123456789123400e-26).toString()
or (1.000005678901234e-10).toString()
value
@code-brewer that is correct: we have a check in the serializer that ensures the serialized transaction is identical to the deserialized one, since any discrepancy could indicate a dangerous mismatch (i.e. you signed a transaction that isn't exactly what you expected).
Why do you want to provide numbers in scientific notation?
Is there a reason you can't use plain decimal (e.g. "0.0000000000123456789123")?
(Note: The cause of this error is the same as https://github.com/XRPLF/xrpl.js/issues/1553)
Because the doc https://xrpl.org/currency-formats.html#string-numbers
say we can use scientific notation, without state any limitation.
I try to use scientific notation because it is obvious to view power number. Then convert it to plain decimal by program.
Though (123456789123400e-26).toFixed(15).toString()
can get decimal 0.000000000001235
, while (1234567891234e+46).toFixed(15)
not work.
I still struggle to find a way to solve it.
If you look at the error data, you can see how the number is decoded by the deserializer. In the case of (1234567891234e+46)
, it decodes as:
'12345678912340000000000000000000000000000000000000000000000'
Thus, you can sign the transaction by specifying '12345678912340000000000000000000000000000000000000000000000' as the amount.
The reason we require this is that, due to rounding, we're not 100% confident that all possible numbers will encode in an expected manner. It's a safeguard to prevent people from assuming the rounding behavior of all possible numbers represented in scientific notation.
Does that help?
Sorry for late response.
I'm using third party big number lib to convert exponent data to plain decimal now. It can accept any large or small number.
Again, I want to repeat, the doc https://xrpl.org/currency-formats.html#string-numbers say we can use scientific notation, without state any limitation, this maybe a pitfall! Because it actually only success when number is not too big.
Thank you. Feel free to open a PR on xrpl-dev-portal to change that doc. However, I think the intent of the doc was to describe responses from rippled, not values that you specify when creating a transaction.