Skip to main content
@cloak.dev/sdk is the first-party SDK for the Cloak protocol. It is built on free functions (transact, transfer, partialWithdraw, fullWithdraw, swapWithChange), with wallet-adapter integration, a built-in scanner and note storage. Since 0.2.5 it is built on @solana/kit; @solana/web3.js is an optional peer dependency used only by the wallet-adapter bridge. One package covers every host: a web frontend or browser wallet, a Next.js or Node.js backend, and long-running server-side services. Proving, note handling and submission are the same everywhere; what changes is who signs. In a browser that is a connected wallet adapter, on a server it is a keypair you hold. Install (current release: @cloak.dev/sdk 0.2.5):
0.2.5 moved the SDK onto @solana/kit. connection is now a CloakRpc from createCloakRpc(rpcUrl) rather than a web3.js Connection, programId and other addresses are Kit Address strings rather than PublicKey instances, and depositorKeypair is a Kit KeyPairSigner. Browser apps on @solana/wallet-adapter keep working through signerFromWalletAdapter, which is why @solana/web3.js remains a peer dependency. Pages whose samples still show the pre-0.2.5 shape are being migrated; Solana Kit integration has the current wiring.

Shared runtime values

The last column says who supplies each value. Cloak hosts the program and the circuits bundle, and those two are the only values the SDK fills in on its own. Your RPC and your relayUrl are yours to pass, and there is no Cloak-hosted RPC to point at. The requirement is identical in a browser bundle and on Node: relayUrl is an option you pass, on every transact call, including shield, send and withdraw, and on the swap helpers. The SDK reads no environment variable for it, so exporting CLOAK_RELAY_URL in a Node process does nothing by itself; read that variable in your own code and pass the value as relayUrl if you like the convention. Omitting the option, or passing an empty string, throws Viewing key registration is mandatory: relayUrl is required. before the call touches the network. Every flow behaves that way, deposits included, and nothing falls back to another deployment.
enforceViewingKeyRegistration: false is the one option that changes this outcome, and it opens a privacy hazard. "" is the caller-signed direct-submission signal, and it only takes effect once enforcement is off, because the viewing-key gate fires first. With enforcement off and no relayUrl, omitted or passed as "", a transfer or withdrawal that carries a signer (depositorKeypair, or signTransaction plus depositorPublicKey) is signed and submitted by that signer instead of throwing: your own wallet broadcasts it, which publicly links the transfer or withdrawal to you. Leave the option at its default of true unless you have deliberately accepted that trade for a specific call. Deposits are the exception that is not a hazard: a deposit is always signed by the depositor and submitted directly, by design, because the funding wallet is public on the way in either way.
The circuits bundle 0.2.0 is the output of the trusted-setup ceremony that keys the deployed program, and it is the only bundle the program accepts. Hashes and the verification recipe are in Release notes.

Concepts to know first

Before you write code, skim the protocol primer:

Start building

  • Quickstart: minimal end-to-end SOL send.
  • Request authentication covers the signed sender that every flow except deposit carries, wired from a browser wallet adapter or from a server keypair. Read it before your first private send.
  • Code examples: send, swap, payroll, history. The snippets sign with a server keypair; a browser wallet signs the way request authentication describes.
  • API reference: the full exported surface, functions, classes and constants.