Balance and notes
How the app computes your private balance from the pool's notes, how it checks the indexer against the chain, and why it sometimes combines notes before a send or an unshield.
Your private balance is not a number stored anywhere. It is the sum of your notes: entries in the pool that each hold an amount of SOL, owned by your keys. Your vault finds them and adds them up, on your device, every time it syncs.
Notes
A note holds an amount, the owner key it belongs to and a random value. The pool stores only a hash of these, the commitment, in a Merkle tree, next to the note's contents encrypted to the owner's viewing key.
| You get a note when | It holds |
|---|---|
| You shield | The amount shielded |
Someone sends to your void address | The amount they sent |
| You send or unshield and the notes you spend hold more than needed | Your change |
| The app combines notes | The sum of two notes, less the relayer fee |
Spending a note publishes its nullifier, a value only your spending key can compute. The program records each nullifier once, so a note can never be spent twice, and nobody else can link the nullifier back to the note.
How the balance is computed
Every 15 seconds while the vault is unlocked, and after each of your transactions, the app syncs:
- New notes. It downloads from the indexer every note added since the last sync, all of them, not only yours.
- Spent markers. It downloads every nullifier the program has recorded.
- Check against the chain. It rebuilds the tree from those notes and looks for its root among the recent roots the program keeps on Solana. If the program holds that root, the app's view of the pool is complete and correct.
- Your notes. It tries your viewing key on every note's encrypted contents and keeps the ones that open and match their commitment.
- Unspent only. It drops the notes whose nullifier is among the spent markers, and adds up the rest.
Step 3 is what makes the indexer's data safe to prove against: an indexer that dropped or invented a note would give a root the program does not hold. And because the app downloads every note and every nullifier, the indexer cannot tell which ones are yours.
The home screen shows the result as your Private balance, with the number of notes behind it. The eye button hides and shows the figure.
Sync status
| Status | What it means |
|---|---|
| Synced | The app's tree matches a root the program holds. Every action is available. |
| Syncing | The first sync since unlocking is running. |
| Catching up | The program has notes the indexer has not served yet. The app waits and tries again. |
| Indexer out of step | The indexer's notes give a root the program does not hold. The app starts over from the first note and proves nothing against that data. |
| Cannot reach the pool | The indexer, the relayer or the Solana RPC did not answer. The app retries at the next sync. |
Shields, sends and unshields wait for Synced: the app builds a proof only against a root the program holds.
Activity
The activity list records what you did from this browser: Shielded, Sent privately, Unshielded and Combined notes, each with a link to its transaction. It is kept on this device only, because the chain cannot give it back: it is not restored with the vault, and notes you receive do not appear in it. Your balance always comes from the chain.
Combining notes
One transaction spends at most two notes. Every shield and every send you receive adds a note, so over time a balance can be spread over more notes than one transaction can spend.
When you send or unshield, the app first looks for the smallest single note that covers the amount plus the relayer fee, then for the smallest pair. If no two notes are enough, it combines notes first:
- Each merge is a private transfer to yourself. It spends two of your notes and creates one note with their sum, less one relayer fee. It pays no pool fee, and on the chain it looks like any other private transfer.
- The app combines your largest notes, only as many as the amount needs, smallest of those first.
- Merges run in rounds. The pairs in a round share no note, so the app proves them all against the same root and sends them together. It then waits for the indexer to show them spent before planning the next round.
- You see the cost first. Under the amount the app says Combines N note pairs first, and the review lists Combining notes first with the number of merges and the fee of each.
Once the merges are in, the app goes on with the send or unshield you confirmed. The activity list shows one Combined notes entry with the number of transactions and their total fee.
What Available and Max show
Available and Max show the most a single send or unshield can move right now: your largest notes, combined where needed, less the fee of each merge and the relayer fee of the final transaction. When your balance is in one or two notes, that is your balance less one relayer fee.
If the app sent the merges but the indexer had not shown them after about 90 seconds, it stops with the combined notes did not show up in time; try again in a minute. The merges that went through stay done: your balance is now in fewer notes, and the next attempt needs fewer merges.
Unshield
Take SOL out of your private balance to any Solana address. The recipient receives it from the pool, less the 0.5% exit fee.
Recovery
The recovery key restores your vault anywhere; the passphrase only unlocks it in one browser. What each one protects, what losing either means, and how to move to another device.