How a payment works
Every payment is prepared, approved, proved, sent and settled. Here is what each step does and what can stop it.
A Solana transfer is built, signed, sent and confirmed. A Nimbus payment adds two steps: a group of services approves it, and the browser proves it follows the pool's rules.
The five steps
This chart follows a Private Send, which a relayer sends for your user.
sequenceDiagram participant App as Your app participant SDK participant Services as Nimbus services participant Solana App->>SDK: transfer SDK->>SDK: prepare and reserve the notes SDK->>SDK: prove, in the browser SDK->>Services: approve and relay Services->>Solana: send the transaction SDK->>Services: follow until it lands SDK-->>App: relayed, with its settlement
Your app makes one call and gets one result. Each step in between works like this.
Prepare
The SDK syncs, picks the notes to spend and reserves them. It asks Nimbus's context service for what the proof needs. It stops here if the balance is too small or cannot cover the fees.
Approve
A committee of Nimbus services checks the payment and co-signs it. Solana accepts the payment only with their combined signature. If one refuses, the payment stops before anything is sent.
Prove
The browser builds a zero-knowledge proof that the payment follows the pool's rules. This takes most of a payment's time, and closing the tab stops it.
Send
Your user's wallet signs and the SDK sends it, or a relayer sends it. Your user can decline in the wallet, and a relayer can refuse.
Settle
The SDK waits for Solana to confirm the transaction. It checks every 1,000 milliseconds. It returns once the transaction lands or fails, or when it stops waiting.
For a deposit or registration, approval and proof run at the same time. For a Private Send or withdrawal, the committee approves as the relayer accepts the payment.
Who sends it
| Payment | Who signs | Who sends it to Solana |
|---|---|---|
| Register | Your user's wallet, then the SDK for their platform wallet | The SDK, from the browser |
| Deposit | Your user's wallet, then the SDK for their platform wallet | The SDK, from the browser |
| Private Send | Nobody on the device | A relayer |
| Withdraw | Nobody on the device | A relayer |
A relayer pays the Solana fee and appears as the signer. That keeps your user's wallet off their Private Sends and withdrawals.
How it settles
A relayed payment returns relayed with a settlement. The SDK checks on it up to 180 times.
settlement.kind | What it means |
|---|---|
landed | It landed, and the SDK synced the private balance after. |
failed | The relayer rejected it, gave it up, or it failed on Solana. |
pending | The SDK stopped waiting first. It may still land, and a later sync will tell. |
not-followed | You passed follow: false, so the SDK returned when the relayer accepted it. |
A transaction your user's wallet sent returns a TransactionSubmission. The SDK checks it up to 90 times.
kind | What it means |
|---|---|
landed | It landed without error. |
failed | It landed and failed. Only the network fee was charged. |
expired | Its blockhash expired first. It will never land. |
refused | The RPC would not forward it. It cannot land. |
unknown | The SDK stopped waiting first. It may still land. |
Confirmed or finalized
Solana reports a transaction as confirmed within seconds. It becomes finalized once it can no
longer be rolled back, some seconds later.
Payments wait for confirmed by default. Pass commitment: "finalized" when your app needs
certainty more than speed.
Merging
One payment spends at most three notes. The SDK always takes the three largest, so the rest of the balance gathers in the change.
When the three largest cannot cover a Private Send or withdrawal, the SDK merges first. Each merge
sends three notes back to your user as one, then waits for it to land. You see each merge as
merge-prepared, merge-relayed and merge-settled stages.
A merge pays the relayer's tip, but no protocol fee. If one fails, the result is merge-failed.
Merges that finished stay merged, so a retry needs fewer.
A deposit also merges up to three of your user's notes of that token into its change.
What this means for your app
- Show progress. A payment takes seconds, and most of it is the proof.
- Ask your user to keep the tab open until the payment returns.
- Read the settlement, not just the kind.
relayedmeans accepted, andlandedmeans done.
Last updated