Discover the holding accounts under the relevant token programs, group compatible balances by exact mint and sum their raw integers. Apply the mint’s decimals for display. Keep account restrictions, observation context and market valuation separate from the token quantity.

Query holding accounts rather than assuming one balance account

SOL lives as lamports in accounts. Fungible tokens use holding accounts managed by their token program. A wallet can control several holding accounts for the same mint, so checking only its expected associated token account can undercount.

getTokenAccountsByOwner accepts an authority address and a filter by mint or program ID. Its result lists matching token accounts with account data. In this method's name, owner refers to the token authority being queried; the account's base owner is the token program.

Choose the supported scope. A query for the original Token Program does not automatically discover every Token Extension Program holding. Metaplex Core assets and positions owned through programs require their own model.

For a known single holding account, getTokenAccountBalance returns its amount fields. Passing a wallet address in place of the token account does not turn it into a complete wallet portfolio query.

Identify what each returned account contains

Read the token account's mint, authority and amount, then verify its base program owner. The exact mint identifies the asset. A ticker or logo is display metadata and can be copied by another token.

Confirm decimals from the appropriate mint or a validated parsed result. Decimals determine how many base units make one display token. They do not change the raw quantity stored in the token account.

Suppose Alice controls accounts A and B for the same six-decimal mint. A has raw amount 1,234,567; B has 2,000,000. A third account uses a different mint with the same symbol. Sum A and B together, and keep the third mint separate.

For balances held inside a program position, determine which relationship makes the position attributable to the user. An authority-filter query alone cannot decode every DeFi claim.

Sum raw integers before formatting

The example total is 3,234,567 base units, displayed as 3.234567 tokens. Preserve the raw integer string from the API. JavaScript Number cannot exactly represent every integer that a token balance can contain.

This self-contained formatting example uses BigInt. It prints the full six-decimal amount without floating-point arithmetic.

const amounts = ["1234567", "2000000"];
const total = amounts.reduce((sum, value) => sum + BigInt(value), 0n);
const scale = 10n ** 6n;
const whole = total / scale;
const fraction = (total % scale).toString().padStart(6, "0");
console.log(`${whole}.${fraction}`); // 3.234567

Keep grouping and decimal validation outside this small example. A production function needs the actual validated decimals and error handling for malformed values. Format only after aggregation so rounded display values do not accumulate errors.

Preserve raw quantities in stored data. You can choose a shorter display later without losing the original amount.

Two six-decimal accounts make one quantity

Two six-decimal accounts make one quantity. Account A raw: 1,234,567. Account B raw: 2,000,000. Total raw: 3,234,567. At six decimals: 3.234567 tokens.
Chosen same-mint account amounts. A different mint with the same symbol is excluded.

Apply the mint’s display conversion after preserving the raw total

The six-decimal formatter above illustrates an ordinary unscaled token quantity. An extension-aware UI can require more information than decimals. Scaled UI Amount applies a mint-defined multiplier, while Interest Bearing uses its configured time-and-rate conversion. Neither operation requires new raw tokens to appear in each holding account.

Preserve the raw sum and record which mint conversion you applied. A fictional six-decimal holding of 1,000,000 raw units is one unscaled unit. A multiplier of two can display two adjusted units while the account's raw amount remains unchanged. A price feed quoted per unscaled unit must be converted consistently before valuing that adjusted display.

For historical reports, use the conversion appropriate to the observation context rather than today's display rule for every old record. Some conversion helpers use floating-point arithmetic, so do not assume an arbitrary UI-amount round trip recreates the same raw integer.

The token-program guide explains these optional features. Keep ordinary integer aggregation, spendability checks and product valuation as separate steps; a larger displayed quantity alone does not establish a deposit or an earned return.

A displayed amount is not permission to transfer it

A frozen token account or an extension can affect what actions succeed. Delegation, transfer hooks and other configured features can require extra interpretation. Read supported fields with the correct program-aware decoder.

A delegated allowance describes an authority's permitted action under program rules. It is not automatically a second separate asset balance to add to the portfolio.

Wrapped SOL needs special care. Its token amount and the native account's lamports reflect related representations, including an account reserve. Do not count the same backing SOL again as independent token wealth.

Show unsupported interpretation as unsupported. A parsed base amount can still be useful, but the product should not imply that every application can spend or accept it.

Preserve state context and price as separate observations

Save cluster, source, commitment, response context and fetch time. A series of account requests can observe different points as the chain changes. A minimum context constraint is not a historical snapshot selector.

To show currency value, multiply a suitable token quantity by a separately sourced price with its own unit and observation time. Missing price data leaves an unpriced quantity; it does not make the token balance zero.

For an LST, choose whether you display token units, a protocol conversion to underlying SOL or a market sale estimate. Those are different derived values. Label each method instead of silently replacing one with another.

Test multiple accounts per mint, absent ATAs, very large integers, unsupported extensions and unavailable prices. Those cases expose errors that a single ordinary balance cannot reveal.

Common questions

Can the same wallet have several accounts for one token?

Yes. An ATA is a canonical holding address, but other holding accounts can exist for the same mint and authority.

Should I add uiAmount values?

Use validated raw integers and decimals for exact aggregation. Rounded or floating-point display fields can lose precision.

Does no price mean no tokens?

No. Quantity and market valuation are separate observations.

Sources and documentation

Found an error or an outdated detail? Send a correction.