feat(keyring-api): return raw assets amount #426
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Description
This PR adds a new required
rawAmountfield to theBalanceStructandFungibleAssetAmountStructtypes in the keyring API. This field stores the raw blockchain balance without decimals applied, providing precision for calculations usingBigInt/BigNumber.Motivation
The Problem
When snaps return balance data via
keyring_getAccountBalances, theamountfield contains the human-readable value with decimals already applied (e.g.,"1.5"for 1.5 SOL). However, this causes two issues:Double division bug: If amount is already normalized ("1.5"), dividing by decimals again produces incorrect values
Precision loss: parseFloat() has limited precision (~15-17 significant digits), causing data loss for large numbers:
parseFloat("1000000000000000001"); // → 1000000000000000000 (last digit lost!)
parseFloat("1000000000000000001"); // → 1000000000000000000 (last digit lost!)
This PR
Add a rawAmount field that stores the exact blockchain value as a string:
{
amount: "1.5", // UI amount (backward compatible)
rawAmount: "1500000000", // Raw blockchain value (precise)
unit: "SOL"
}
{ amount: "1.5", // UI amount (backward compatible) rawAmount: "1500000000", // Raw blockchain value (precise) unit: "SOL"}
This enables:
Backward compatibility: Existing consumers continue using amount
Precision: New consumers use rawAmount with BigInt/BigNumber for exact calculations
Changes
@metamask/keyring-api
BalanceStruct - Used by keyring_getAccountBalances response:
export const BalanceStruct = object({ amount: StringNumberStruct, // Human-readable (e.g., "1.5") unit: string(), // Symbol (e.g., "SOL") rawAmount: string(), // NEW: Raw value (e.g., "1500000000")});
FungibleAssetAmountStruct - Used by AccountBalancesUpdated event and transaction assets:
Snap Updates (Solana, Tron, BTC)
Updated getAccountBalances to return both fields:
Breaking Change
This is a breaking change - all snaps implementing keyring_getAccountBalances must now return rawAmount. All snaps have been updated accordingly.
Testing
Updated unit tests for BalanceStruct validation
Updated type definition tests (*.test-d.ts)
Updated mock data in KeyringClient.test.ts and SnapKeyring.test.ts
Note
Breaking change: precise balances via
rawAmountrawAmountinBalanceandFungibleAssetAmount(balance.ts,asset.ts); keep human-readableamountfor compatibilityAssetStruct, transaction fee/participant examples, and docs to includerawAmount; refine comments for clarityrawAmountinAccountBalancesUpdatedpayloads; adjust validation and type tests (events.test-d.ts,balance.test(-d).ts,asset.test(-d).ts,transaction.test(-d).ts)rawAmount(SnapKeyring.test.ts,KeyringClient.test.ts)Written by Cursor Bugbot for commit 7b64a6a. This will update automatically on new commits. Configure here.