Skip to main content
This walks through the smallest useful integration: a single-output SOL deposit submitted directly (user signs).

Prerequisites

  • Rust 1.80+ (edition 2024)
  • A funded Solana keypair (mainnet or a local validator)
  • A Solana RPC endpoint

Project setup

A SOL deposit end-to-end

What just happened

  1. Preflight (synchronous, pure): validated arity / balance / mint, classified the flow as Deposit, and padded inputs to the fixed 2-in/2-out arity.
  2. Viewing-key registration (skipped by default — flip require_viewing_key to enable): challenge + register with the payer signing the message.
  3. Merkle fetch: pulled the on-chain tree state via RPC and the commitment set via /commitments, falling back to a frontier proof if needed.
  4. Circuit input packing: 90 decimal-string signals, in the exact order the circom transaction circuit consumes.
  5. Proof generation: ark-circom + ark-groth16 emitted a 256-byte proof. Artifacts (wasm + zkey) cache under ~/Library/Caches/cloak-sdk/circuits/0.1.0/ on macOS, ~/.cache/cloak-sdk/circuits/0.1.0/ on Linux.
  6. Chain-note encryption: a single compact v2 note bound to the primary output commitment, encrypted under HKDF-derived AES-256-GCM.
  7. Direct submission: compiled a v0 transaction, signed with the payer, auto-created an ephemeral ALT if the tx exceeded 1232 bytes, retried on blockhash expiry and transient transport errors.
  8. Commitment reconciliation: best-effort poll against /commitments to fill output_indices.
All this is one transact(opts).await? call.

Chaining transactions

Thread the returned tree and ALTs into the next call to avoid repeating work:

Next steps

Core concepts

How UTXOs, proofs, and retries map to Rust types.

API reference

Full surface of TransactOptions, TransactResult, Relay, etc.

Error handling

Retry classification (RootNotFound / StaleProofState / BlockhashExpired).

Transaction flows

The on-chain protocol this SDK implements.