Amounts and precision
How V3 Custody stores and transmits amounts: smallest units (raw) and decimal representation, converted using the network's decimals.
To avoid floating-point rounding errors, amounts are tracked in the token's smallest indivisible unit (raw, an integer) and displayed in decimal form for humans. The token's decimals value bridges the two.
Raw and decimal
raw: an integer in the smallest units. Exact, with no floating point. For example, USDT on TRON hasdecimals = 6, so1 USDT = 1,000,000 raw.- decimal: the familiar representation, such as
"1350.00". decimals: the token's scale on the network:raw = decimal × 10^decimals.
| Token | decimals | decimal | raw |
|---|---|---|---|
| USDT (TRON) | 6 | 1.5 | 1500000 |
| ETH | 18 | 0.001 | 1000000000000000 |
In requests and responses
On input (for example, when creating a transfer), you pass a decimal amount, and the platform converts it using decimals. Responses include both representations. Balance checks are performed in raw.
| Field | Representation | Where it's used |
|---|---|---|
amount | raw (or decimal input, depending on the endpoint) | responses; input for some endpoints |
amountDecimal | decimal | responses |
relatedAmountRaw | raw | partial refunds |
Amount field names and meanings vary by endpoint (in some, amount is raw; in others, it's decimal input). See the API Reference for the exact semantics of a specific endpoint.
Why raw
Integer arithmetic in the smallest units eliminates floating-point drift: ledger entries net to exactly zero, and balances always match the ledger. For details, see Ledger (double-entry).
Integration recommendations
- Pass and store raw amounts as strings. Large values (for example, ETH's 18 decimal places) exceed JavaScript's safe integer range. Responses return amounts as strings (
"1350000000"). - Use decimal arithmetic libraries for conversion and display, not floating-point numbers.
Common mistakes
| Symptom | Cause |
|---|---|
| amounts are off by a few cents | floats used instead of integer or decimal arithmetic |
| precision loss or overflow in JS | raw stored as a number, not a string (ETH's 18 decimals exceed Number.MAX_SAFE_INTEGER) |
| amount is 10^decimals times too large or small | raw and decimal were mixed up on input |
amount treated the same everywhere | the field's semantics vary by endpoint; check the API Reference |
| wrong scale | the wrong token's decimals was used (USDT-TRON has 6, ETH has 18) |