End-to-end guide: install @umbra-privacy/sdk, call getUmbraClient, register, deposit into encrypted balance, create a UTXO, scan with getClaimableUtxoScannerFunction, and claim.
For quick testing, generate an in-memory keypair. For production, see Wallet Adapters.
import { createInMemorySigner } from "@umbra-privacy/sdk";// Generate a random keypair (for testing only)const signer = await createInMemorySigner();console.log("Wallet address:", signer.address);
An in-memory keypair is ephemeral - it disappears when your process exits. Use a browser wallet or a persistent keypair for anything beyond local testing.
The Umbra program address differs between devnet and mainnet. The SDK resolves the correct address automatically based on the network parameter.
The first operation that requires the master seed (typically register() or deposit()) will prompt the user to sign a consent message. Subsequent operations reuse the cached seed without re-prompting.
Registration sets up your on-chain Umbra identity. This function can be called regardless of whether the user is already registered - it handles the full setup, including key rotation when keys have changed. That said, each call submits on-chain transactions with SOL costs, so in practice you should check whether the account is already registered before calling it.
import { getUserRegistrationFunction } from "@umbra-privacy/sdk";const register = getUserRegistrationFunction({ client });// This is where the wallet signing prompt appears for the first time.// The user signs once to derive the master seed; subsequent operations// reuse the cached seed without prompting again.const signatures = await register({ confidential: true, // enable encrypted balances anonymous: true, // enable mixer / anonymous transfers});console.log(`Registered in ${signatures.length} transaction(s)`);
Send tokens privately to a recipient by depositing them into the mixer. The recipient can later claim them with no on-chain link back to you as the sender.
UTXO creation requires a zkProver dependency for Groth16 proof generation. Install @umbra-privacy/web-zk-prover for the recommended browser-based prover - see ZK Provers for details.
As the recipient, scan the Merkle tree for UTXOs addressed to your X25519 key. The SDK attempts to decrypt each ciphertext and returns only those belonging to you.
import { getClaimableUtxoScannerFunction } from "@umbra-privacy/sdk";const fetchUtxos = getClaimableUtxoScannerFunction({ client });// Scan tree 0 from the start - pass your last seen index to resumeconst { received } = await fetchUtxos(0, 0);console.log("Received UTXOs:", received.length);
Present a ZK proof on-chain to burn the UTXO and receive the tokens. Claiming into an encrypted balance keeps the received amount private - no on-chain trace of who received what.