Register a user
Register your user once, on Solana, so they can deposit and receive private payments.
Registering is a one-time Solana transaction. It creates Alice's identity, the public record of her private account, and links her wallet to it.
Nobody can pay Alice privately until she registers. That includes deposits into her own private balance, from her wallet or anyone else's.
In this guide, Alice checks whether she is registered, then registers from the wallet she connected.
What's public
- Alice's wallet
- Her platform wallet
- Her identity, linked to both wallets
- A fingerprint of her encryption key
- Her keys
Her platform wallet is a second Solana address the SDK derives from her signature. It signs her deposits alongside her wallet. Registering links the two wallets in public, so anyone can tell they belong to one private account.
Registering reveals nothing about what Alice later holds or pays. What each operation shows explains each line.
Check first
session.registration says where Alice stood when the session opened. It never changes while the
session is open. To read where she stands now, call readRegistration:
import { } from "@umbra/nimbus-solana-web";
if (.. === "unregistered") {
const standing = await (, {}); if (. === "unregistered") ();
}session.registrationis current when the session opens. Use it to decide what to show first.readRegistrationasks Nimbus again. Use it afterregisterlands, or when another tab may have registered.
Register
Create a registration context from the session, then call register.
import {
,
,
} from "@umbra/nimbus-solana-web";
const = await ();
const = await (, {}, { });{}is the arguments, and there are none. The session says who registers.transactionVersionis what the wallet can sign. A registration fits one transaction at either version. See Connect a wallet.createRegistrationContextpicks the newest open pool. PasspoolIndexto choose another.
First the SDK builds a proof on the device and collects Nimbus's approval. That takes a few seconds. Then Alice's wallet asks her to approve one transaction.
That transaction registers her and links her wallet in one step. She pays its network fee from her wallet. Registering opens no new account on Solana, so there is no rent to pay.
Her wallet needs a little SOL for that fee. The SDK checks her balance before it builds the proof. A wallet without enough throws at once, so she never waits for a proof that cannot be sent.
Handle the result
register returns a result instead of throwing for anything your user can cause. Check its kind:
kind | What happened | What to do |
|---|---|---|
complete | Alice was registered already. Nothing was sent. | Carry on to her first deposit. |
submitted | The registration was sent to Solana. | Read where it ended up, below. |
declined | Alice rejected it in her wallet. Nothing was sent. | Let her try again. |
store-refused | This browser could not open her private account data. Nothing was sent. | Ask her to reload the page and try again. |
A submitted result carries the transaction's fate in result.submission.submission.kind:
kind | What it means |
|---|---|
landed | Done. Alice is registered. |
failed | It reached Solana and failed. Only the network fee was charged. |
expired or refused | It never reached Solana. Nothing changed, and it is safe to try again. |
unknown | The SDK stopped waiting before Solana decided. See A registration still settling. |
Here is the whole check in one function. TypeScript checks that it covers every case.
function (: ): string {
switch (.) {
case "complete":
return "You are registered.";
case "submitted":
switch (...) {
case "landed":
return "You are registered.";
case "failed":
return "Registration failed on Solana. Only the network fee was charged.";
case "expired":
case "refused":
return "Registration never reached Solana. Try again.";
case "unknown":
return "Registration is still pending.";
}
case "declined":
return "You declined to register in your wallet.";
case "store-refused":
return "This browser could not open your account data. Reload and try again.";
}
}Alice is registered when the result is complete, or submitted with a landed submission. She
can deposit straight away.
Show progress
Pass onProgress to tell Alice what is happening:
import { } from "@umbra/nimbus-solana-web";
await (, {}, { : () => (.) });The stages are prepared, endorsed, proved, signed, sent and confirmed. endorsed and
proved can arrive in either order. A registration with nothing left to send stops after
prepared. Show progress has a message for each stage.
Edge cases
Already registered
register checks first and sends only what is missing. If Alice is registered and her wallet is
linked, it returns complete. Her wallet never asks her to sign.
A registration still settling
A submission of kind unknown may still land until its blockhash expires. Do not call register
again straight away. Wait a minute, then call readRegistration. If it says unregistered, try
again.
A landed registration lets Alice deposit at once. Spending takes a little longer. Her private
balance can pay only once the registration is final on Solana and her device has synced. Until then,
a Private Send or a withdrawal is refused with not-registered.
Two tabs registering at once
register holds a lock for Alice's wallet for the whole call. The lock is shared by every tab of
your site in one browser. A second tab waits for the first to finish, then checks again. If the
first tab's registration landed and Nimbus has seen it, the second returns complete.
Common errors
These are thrown, not returned, because your app usually cannot fix them by asking the user.
| Error | Reason | Cause |
|---|---|---|
NimbusSolanaFlowError | binding-mismatched | Alice's wallet is already linked to a different platform wallet, such as one from another accountIndex. |
NimbusSolanaFlowError | standing-mismatched | A Nimbus service answered for another pool or a stale state. Try again later. |
NimbusSolanaFlowError | fee-payer-unfunded | Alice's wallet holds too little SOL for the network fee. Nothing was proved or sent. Ask her to add some. |
NimbusSolanaFlowError | transaction-unsendable | The transaction failed its check before sending. Nothing was signed. Try again. |
NimbusSolanaFlowError | transaction-altered | The wallet changed the transaction it was asked to sign. Nothing was sent. |
NimbusSdkError | service-unavailable | Solana or a Nimbus service could not be reached. Try again. |
NimbusSdkError | unauthorized | The session has no gateway token, or the gateway refused it. |
NimbusSdkError | wallet-unsupported | The wallet failed while signing. |
Handle errors shows one function that covers every error the SDK throws.
Options
| Option | Default | What it does |
|---|---|---|
transactionVersion | 1 | The transaction version the wallet signs. |
onProgress | none | Called at each stage of the registration. |
commitment | "confirmed" | "finalized" waits until the registration cannot be rolled back. |
priorityFeeLamports | 0n | A priority fee, in lamports, to land faster when Solana is busy. |
The API reference lists every option.
Next
Last updated