> 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.

# Private balances (/explainers/private-balance)

On Solana, a token balance lives in a token account. Anyone can read its owner, its mint and its
amount. A private balance holds the same three facts, but only its owner can read them.

## A balance is a set of notes

A private balance is made of **notes**. Each note is like a small token account: it has an owner, a
token and an amount. Notes are stored on Solana, sealed so that only the owner's keys can open them.

A user's balance in a token is the sum of their notes in that token. Alice holds three USDC notes:

```mermaid
flowchart LR
a["Note: 10 USDC"] --> b(["Private balance: 25 USDC"])
c["Note: 10 USDC"] --> b
d["Note: 5 USDC"] --> b
```

*Alice's private balance in USDC is the sum of her three USDC notes.*

Nobody else can see these notes as Alice's. To an observer they are three sealed records among
everyone else's.

## Spending makes new notes

A payment never edits a note. It consumes some of the payer's notes and creates new ones.

Say Alice pays Bob 10 USDC. The SDK spends up to three of her largest notes in one payment, so here
it spends all three, 25 USDC in total. It creates two new notes: 10 USDC for Bob, and 15 USDC back to
Alice as change. Fees are left out to keep the sums simple.

Alice's balance is now one 15 USDC note. Bob's balance has gained a 10 USDC note.

## Why the device keeps a copy

Finding a user's notes takes their keys, and the keys stay in their browser. So the SDK finds the
notes on the device. It reads new pool activity, tries the user's keys on each new note, and keeps
the ones that open.

It stores what it finds in IndexedDB, one database per account. Every tab of your app shares it.
`readBalances` reads this copy and fetches nothing. Bringing the copy up to date is a
[sync](https://sdk.nimbusprivacy.xyz/explainers/sync).

## The states of a balance

`readBalances` returns one entry per token and state:

| State       | What it holds                                                                                                                                |
| ----------- | -------------------------------------------------------------------------------------------------------------------------------------------- |
| `available` | Notes your user can spend now.                                                                                                               |
| `pending`   | Notes not yet confirmed on Solana, or not yet past the slot they become spendable from.                                                      |
| `reserved`  | Notes a payment is spending. The payment may be running, stopped or sent and not yet settled. A deposit that merges notes reserves them too. |
| `expired`   | Notes past the last slot they could be spent in.                                                                                             |

A payment reserves every note it spends, change included. While Alice pays Bob 10 USDC, all 25 USDC
show as reserved. [Tabs and reserved funds](https://sdk.nimbusprivacy.xyz/explainers/reserved-funds) explains why.

## What this means for your app

- **Sync before you show a balance.** The copy is only as fresh as the last sync.
- **A new device starts empty.** It shows nothing until its first sync has read the user's notes back.
- **Show the states apart.** Show `available` as the balance, and `pending` and `reserved` beside it.

* [Keeping the device in sync](https://sdk.nimbusprivacy.xyz/explainers/sync): When to sync, and what a sync does.
* [Show balances](https://sdk.nimbusprivacy.xyz/helpers/balances): Read the private balance with readBalances.


Last updated 21 October 2026
