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

# Fees (/explainers/fees)

Every Solana transaction pays a network fee in SOL. A Nimbus payment can carry two more: a protocol
fee, and a tip for the relayer that sends it.

## The three fees

- **The protocol fee** is a share of the amount, paid in the token being moved. Governance sets the
  rates for each kind of payment and token. The SDK reads them when it prepares the payment.
- **The Solana network fee** is paid in SOL by whoever sends the transaction.
- **The relayer's tip** pays the relayer that sends a Private Send or a withdrawal. It is paid in the
  token being moved, and anyone can see it.

Change that comes back to your user pays no protocol fee. Neither does a merge, which only moves
value between your user's own notes.

## Who pays what

| Payment      | Protocol fee               | Network fee        | Relayer's tip         |
| ------------ | -------------------------- | ------------------ | --------------------- |
| Register     | None                       | Your user's wallet | None                  |
| Deposit      | From the amount, or on top | Your user's wallet | None by default       |
| Private Send | From the amount, or on top | The relayer        | The relayer's minimum |
| Withdraw     | From the amount, or on top | The relayer        | The relayer's minimum |

The relayer's minimum is zero while it sponsors payments. Otherwise it is the minimum its published
policy asks for. A withdrawal to a token account that does not exist yet also pays the relayer's
creation fee, unless the relayer creates it for free. You can offer more with the `submitterFee`
option.

## Deducted or added

By default, fees are **deducted**: they come out of `amount`. Pass `fees: "added"` to pay them on top
instead. Here is how that plays out for Alice, in USDC:

| Alice asks to    | With `fees: "deducted"`                                                                | With `fees: "added"`                                                                                              |
| ---------------- | -------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------- |
| Deposit 25 USDC  | 25 USDC leaves her wallet. Her private balance grows by 25 USDC less the protocol fee. | 25 USDC leaves her wallet, and her new note holds all 25. The fee comes from USDC already in her private balance. |
| Send Bob 10 USDC | Her balance drops by 10 USDC. Bob receives 10 USDC less the fees.                      | Bob receives exactly 10 USDC. Her balance drops by 10 USDC plus the fees.                                         |
| Withdraw 10 USDC | Her balance drops by 10 USDC. The address receives 10 USDC less the fees.              | The address receives exactly 10 USDC. Her balance drops by 10 USDC plus the fees.                                 |

With `added`, the private balance must cover the fees. If it cannot, a deposit throws
`amount-unfundable`. A Private Send or withdrawal returns `refused` with `insufficient`. Nothing is
sent either way.

The `prepared` progress stage carries the exact fees. You can show them while the proof runs.

A Token-2022 token may also keep a transfer fee of its own on the way into the pool. The protocol
fee applies to what arrives.

## Priority fees

When Solana is busy, a priority fee helps a transaction land sooner. Pass `priorityFeeLamports` to
`register`, `deposit` or `refundStrandedDeposit`. It is in lamports for the whole transaction, `0n`
by default, and your user's wallet pays it.

A Private Send or withdrawal takes no priority fee. The relayer sends it, so the relayer decides.

## Rent

Your user's first deposit of a token creates a token account for their platform wallet. Their wallet
pays that account's rent.

If a deposit ever needs a refund, `refundStrandedDeposit` can return that rent too. Pass
`closeTokenAccount: true` to close the emptied account.

## What this means for your app

- **Show the fee before your user commits,** or as soon as the `prepared` stage reports it.
- **Pick one fee mode** and say which in your UI. "You send 10, Bob gets 10" reads differently from
  "You send 10, Bob gets a little less".
- **Expect the tip to change.** It follows the relayer's policy, which can change.

* [The fee model](https://docs.nimbusprivacy.xyz/fees/fee-model): How the protocol computes its fee.
* [Show progress](https://sdk.nimbusprivacy.xyz/api-design/progress): Read the fees from the prepared stage.


Last updated 21 October 2026
