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

# Tabs and reserved funds (/explainers/reserved-funds)

On Solana, if two transactions need the same lamports, only one succeeds. A private balance has the
same rule. A payment that loses that race wastes a proof and your user's time, so the SDK stops it
before it starts.

## Two tabs, one balance

Every tab of your app shares one copy of the private balance. Two tabs could pick the same notes for
two payments at once.

To prevent that, a payment **reserves** its notes before it builds anything. Another payment, in
this tab or another, chooses among the notes left. `readBalances` counts reserved notes as
`reserved`.

A payment reserves every note it spends, change included. Paying 10 USDC from three notes worth 25
USDC reserves all 25.

Each running payment also holds a Web Lock named for it. The browser drops the lock when the tab
closes or crashes. That is how the SDK tells a running payment from a stopped one.

A running payment keeps its notes until it finishes. A stopped one keeps them until something frees
them, as below.

## Where a reserved payment stands

`listReservedSpends` lists every payment holding notes. Each has a `state`, and a `running` flag
that says whether some tab still holds its lock.

| `state`     | What it means                                 | What releasing it does                                                  |
| ----------- | --------------------------------------------- | ----------------------------------------------------------------------- |
| `unsent`    | Nothing has left the device.                  | Frees its notes at once.                                                |
| `sent`      | It may have reached the relayer or Solana.    | Stops new attempts. The notes free once it lands or can no longer land. |
| `releasing` | Released while a sent attempt may still land. | Nothing more. It is already waiting.                                    |

A sent payment keeps its notes until it settles. Spending them again meanwhile could race it.

A deposit can reserve notes too. A deposit merges up to three of your user's notes of that token
into its change, and reserves them until it settles. It is listed with `kind: "deposit"`.

## What frees reserved funds

- **Finishing.** A payment that lands spends its notes. Once a sync sees that, they leave the
  balance.
- **The next sync,** if the tab closed before sending anything. The payment is `unsent` and no tab
  holds its lock.
- **Your app's release button.** `releaseReservedNotes` releases what is not running. With
  `force: true` it releases a running payment too, which then fails at its next step.
- **A relayer's refusal.** A payment that comes back `relay-refused` never reached Solana, so its
  notes free at once.
- **Time,** for a sent payment that can no longer land. After a relay comes back `failed`, its notes
  stay reserved until its proof's window passes.

## What this means for your app

- **Show reserved funds apart from the available balance,** so the numbers add up.
- **Offer a release button** for payments that are not running.
- **Expect a quick retry to fail after `failed`.** Its notes may still be reserved. A retry after
  `relay-refused` can spend them at once.

* [Reserved funds](https://sdk.nimbusprivacy.xyz/helpers/reserved-funds): List and release what a payment holds.
* [Private balances](https://sdk.nimbusprivacy.xyz/explainers/private-balance): Every state a balance can be in.


Last updated 21 October 2026
