Amounts & units
How Mainly represents SOL, lamports, and token amounts — always raw and human-readable together.
The problem we're fixing
Solana has no decimals on-chain. Everything is integers:
- SOL is stored as lamports: 1 SOL = 1,000,000,000 lamports.
- Tokens are stored as raw integer strings plus a separate
decimalsfield: USDC with"amount": "42000000"anddecimals: 6means 42 USDC. - Fees are lamports; priority fees are micro-lamports per compute unit.
Raw RPC returns only the integer forms, and mixing them up is the most common class of bug in Solana apps.
How Mainly represents amounts
Every amount in every response includes both forms. You never convert anything.
SOL amounts
{
"lamports": 1529000000,
"sol": 1.529
}Token amounts
{
"balance": {
"raw": "42000000",
"decimals": 6,
"ui": 42.0,
"uiString": "42"
}
}| Field | Type | Meaning |
|---|---|---|
raw | string | Exact on-chain integer amount. A string because token supplies overflow 64-bit floats. |
decimals | number | Decimal places for this mint. |
ui | number | raw / 10^decimals, as a float. Convenient for display. |
uiString | string | The same value as an exact decimal string. |
One rule to remember
Display with ui, do math with raw.
Floats lose precision above 2^53, and several popular tokens have supplies past
that. If you're summing balances, comparing amounts, or computing a payment,
use the raw strings with a big-integer library (BigInt in JavaScript).
ui and sol exist for rendering, logging, and debugging.
USD prices
Endpoints that return prices (like List wallet tokens)
include a price object:
{
"price": {
"usdPerToken": 1.0,
"usdTotal": 42.0
}
}Prices come from aggregated market data, are cached for up to 10 minutes, and are only present for tokens with verified market data. Treat them as estimates for display — not as an oracle for financial logic.