> For AI agents: the documentation index is at https://sdk.nimbusprivacy.xyz/llms.txt, and every page is available as Markdown at its URL with .md appended.

# Balances (/helpers/balances)

`readBalances` reads the user's private balance from their device. It fetches nothing, so it
returns at once. It shows what the last [sync](https://sdk.nimbusprivacy.xyz/helpers/sync) left, so sync first when you need the
latest.

In this guide, Alice's app shows her USDC balance, with what is still settling beside it.

## Read the balance

```ts
import { readBalances, syncNoteStore } from "@umbra/nimbus-solana-web";

await syncNoteStore(session, {});
const balances = await readBalances(session, {});
```

Each `Balance` is what Alice holds of one token in one state:

- **`mint`** is the token's address. It is absent for a token the SDK's preset does not list.
- **`state`** says whether she can spend it, below.
- **`total`** is the amount, in the token's smallest unit.
- **`count`** is how many separate pieces make up the total.
- **`zone`** is `0`, unless you read with a `zone` option. Most apps never pass one.

A user who has not registered yet reads as an empty list.

## Each state

| `state`     | What it means                                                                            | What to show                                                                          |
| ----------- | ---------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------- |
| `available` | Alice can spend it now.                                                                  | Her balance.                                                                          |
| `pending`   | She received it, but it is not final on Solana yet, or not yet past the time it unlocks. | "Settling". It becomes available on its own.                                          |
| `reserved`  | A payment that has not finished is holding it.                                           | "In use". See [Reserved funds](https://sdk.nimbusprivacy.xyz/helpers/reserved-funds). |
| `expired`   | It passed the time it could be spent by.                                                 | "Expired". It can no longer be spent.                                                 |

Show `available` as the balance. A payment can only spend that part.

## One row per token

`readBalances` returns one entry per token and state. Most apps show one row per token, with the
spendable amount first. The example app groups them like this:

```ts
interface TokenBalance {
  mint: string;
  available: bigint;
  pending: bigint;
  reserved: bigint;
  expired: bigint;
}

function groupBalances(balances: readonly Balance[]): TokenBalance[] {
  const rows = new Map<string, TokenBalance>();
  for (const balance of balances) {
    if (balance.mint === undefined) continue;
    const row = rows.get(balance.mint) ?? {
      mint: balance.mint,
      available: 0n,
      pending: 0n,
      reserved: 0n,
      expired: 0n,
    };
    row[balance.state] += balance.total;
    rows.set(balance.mint, row);
  }
  return [...rows.values()];
}
```

## Show token names and logos

Amounts are integers in the token's smallest unit. Format them with the token's decimals, which
`sdk.mints` lists:

```ts
const usdc = sdk.mints.find(
  (entry) => entry.mint === "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
);

console.log(formatAmount(25_000_000n, usdc?.decimals ?? 0)); // "25"
```

[Tokens](https://sdk.nimbusprivacy.xyz/helpers/tokens) has `formatAmount` in full. The SDK carries no token names or logos.
The example app reads them from a token list it writes ahead of time. [Tokens](https://sdk.nimbusprivacy.xyz/helpers/tokens#names-and-logos)
shows how.

## Refresh after a sync

Read the balance again after each of these:

- **A sync you run.** See [Sync](https://sdk.nimbusprivacy.xyz/helpers/sync) for one that runs in the background.
- **A payment that returns.** Each payment syncs before it starts. A Private Send or withdrawal the
  SDK followed until it landed has synced again since.
- **A release** of [reserved funds](https://sdk.nimbusprivacy.xyz/helpers/reserved-funds).

A deposit lands in the private balance with the next sync, not at once. Sync before you read it
back.

## Next

- [Sync](https://sdk.nimbusprivacy.xyz/helpers/sync): Keep the device up to date with Solana.
- [History](https://sdk.nimbusprivacy.xyz/helpers/history): Show the user's past payments.
- [Private balances](https://sdk.nimbusprivacy.xyz/explainers/private-balance): Where the balance lives, and why the device syncs.
- [API reference](https://sdk.nimbusprivacy.xyz/reference/reads#readbalances): readBalances: its options and what it returns.


Last updated 21 October 2026
