Skip to content
Registration

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

Anyone can see
  • Alice's wallet
  • Her platform wallet
  • Her identity, linked to both wallets
  • A fingerprint of her encryption key
Stays private
  • 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 (, {});
const standing: NimbusRegistrationStanding
if (. === "unregistered") (); }
  • session.registration is current when the session opens. Use it to decide what to show first.
  • readRegistration asks Nimbus again. Use it after register lands, 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.
  • transactionVersion is what the wallet can sign. A registration fits one transaction at either version. See Connect a wallet.
  • createRegistrationContext picks the newest open pool. Pass poolIndex to 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:

kindWhat happenedWhat to do
completeAlice was registered already. Nothing was sent.Carry on to her first deposit.
submittedThe registration was sent to Solana.Read where it ended up, below.
declinedAlice rejected it in her wallet. Nothing was sent.Let her try again.
store-refusedThis 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:

kindWhat it means
landedDone. Alice is registered.
failedIt reached Solana and failed. Only the network fee was charged.
expired or refusedIt never reached Solana. Nothing changed, and it is safe to try again.
unknownThe 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.

ErrorReasonCause
NimbusSolanaFlowErrorbinding-mismatchedAlice's wallet is already linked to a different platform wallet, such as one from another accountIndex.
NimbusSolanaFlowErrorstanding-mismatchedA Nimbus service answered for another pool or a stale state. Try again later.
NimbusSolanaFlowErrorfee-payer-unfundedAlice's wallet holds too little SOL for the network fee. Nothing was proved or sent. Ask her to add some.
NimbusSolanaFlowErrortransaction-unsendableThe transaction failed its check before sending. Nothing was signed. Try again.
NimbusSolanaFlowErrortransaction-alteredThe wallet changed the transaction it was asked to sign. Nothing was sent.
NimbusSdkErrorservice-unavailableSolana or a Nimbus service could not be reached. Try again.
NimbusSdkErrorunauthorizedThe session has no gateway token, or the gateway refused it.
NimbusSdkErrorwallet-unsupportedThe wallet failed while signing.

Handle errors shows one function that covers every error the SDK throws.

Options

OptionDefaultWhat it does
transactionVersion1The transaction version the wallet signs.
onProgressnoneCalled at each stage of the registration.
commitment"confirmed""finalized" waits until the registration cannot be rolled back.
priorityFeeLamports0nA priority fee, in lamports, to land faster when Solana is busy.

The API reference lists every option.

Next

Last updated

On this page