fix(xrpl): return string from dropsToXrp to preserve precision (#3316)#3341
fix(xrpl): return string from dropsToXrp to preserve precision (#3316)#3341achowdhry-ripple wants to merge 1 commit into
Conversation
`dropsToXrp` previously returned a JavaScript `number` via `.toNumber()`,
which silently lost precision for amounts approaching the XRP supply
(~10^17 drops). `xrpToDrops(dropsToXrp('9999999999999999'))` returned
`'9999999999999998'`, dropping one drop on the round-trip.
Return a base-10 decimal string from `dropsToXrp` (and from
`Client.getXrpBalance`, which forwards the value) so the full precision
of the input is preserved. Callers that need a JS number can wrap the
result in `Number(...)`.
BREAKING CHANGE: `dropsToXrp()` now returns `string` instead of `number`;
`Client.getXrpBalance()` now returns `Promise<string>`.
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (6)
WalkthroughThis PR resolves precision loss in XRP balance handling by changing ChangesXRP Conversion String Return Type
Estimated Code Review Effort🎯 2 (Simple) | ⏱️ ~12 minutes Possibly Related Issues
Suggested Reviewers
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Warning There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure. 🔧 ESLint
packages/xrpl/src/client/index.tsOops! Something went wrong! :( ESLint: 9.39.4 ESLint couldn't find an eslint.config.(js|mjs|cjs) file. From ESLint v9.0.0, the default configuration file is now eslint.config.js. https://eslint.org/docs/latest/use/configure/migration-guide If you still have problems after following the migration guide, please stop by packages/xrpl/src/utils/xrpConversion.tsOops! Something went wrong! :( ESLint: 9.39.4 ESLint couldn't find an eslint.config.(js|mjs|cjs) file. From ESLint v9.0.0, the default configuration file is now eslint.config.js. https://eslint.org/docs/latest/use/configure/migration-guide If you still have problems after following the migration guide, please stop by packages/xrpl/src/utils/getBalanceChanges.tsOops! Something went wrong! :( ESLint: 9.39.4 ESLint couldn't find an eslint.config.(js|mjs|cjs) file. From ESLint v9.0.0, the default configuration file is now eslint.config.js. https://eslint.org/docs/latest/use/configure/migration-guide If you still have problems after following the migration guide, please stop by
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
High Level Overview of Change
Fixes xrpl.js#3316.
dropsToXrp()now returns a base-10 decimalstringinstead of a JavaScriptnumber. The internal.toNumber()call is replaced with.toString(BASE_TEN).Client.getXrpBalance()(which forwards the value) now returnsPromise<string>instead ofPromise<number>.Client.getBalances()is updated for the new return type (the branch that pushes the XRP balance no longer needs a redundant.toString(), and the!== 0sentinel check becomes!== '0').getBalanceChanges()drops a now-redundant.toString()on the already-string XRP value.Existing
dropsToXrptests updated for the new return type; new regression test added per the issue:HISTORY.mdupdated underUnreleased > BREAKING CHANGES.Context of Change
dropsToXrpconverts a drops integer (≤ ~10^17 for the XRP total supply) into an XRP amount by dividing by 1,000,000. The old implementation called.toNumber()on the BigNumber result, coercing to IEEE-754 double. For amounts above ~9 billion XRP, the double cannot represent every drop exactly, so the conversion silently loses precision.Repro from the issue:
The fix is to return the BigNumber's exact base-10 string representation. Drops are at most 6 fractional digits of XRP, so the division terminates exactly within BigNumber's default precision and never produces exponential notation.
This is a breaking API change (return type
number→string), which is why it is grouped with the otherUnreleasedbreaking changes inHISTORY.md. Callers that rely on a JS number can wrap the result inNumber(...)— this is already done at the two internal call sites inWallet/fundWallet.ts.Type of Change
Did you update HISTORY.md?
Test Plan
dropsToXrp > round-trips large amounts without precision loss (issue #3316)directly exercises the regression case from the issue.dropsToXrptests were updated to assert against the new string return type (mechanical change — same values, now quoted).getXrpBalancemock test updated to assert the string return.getBalanceChangesfixture-driven tests are unchanged (the fixture already expected string values; the new code path produces the same strings).npm installis currently hitting the npm "Exit handler never called!" bug on my machine. Relying on CI; happy to push fixups if anything fails.