PrivacyPoolSDK is the client-side library that handles all cryptographic preparation for private transactions on Stellar/Soroban. It derives stealth addresses from wallet signatures, constructs private coins, builds Merkle witnesses, generates Groth16 proofs, and serializes everything into the byte format the PrivacyPoolsContract expects. The SDK does not communicate with the Arcane backend, manage audit cases, or touch auditor permissions — those responsibilities belong to the Arcane Auditing Portal.
Install
The SDK requires Node.js >=19.0.0 or a browser environment that exposes the Web Crypto API (
crypto.subtle). Older Node.js versions and environments without crypto.subtle are not supported.Initialize
Pass the WASM binary, circuit WASM, and proving key (zkey) to PrivacyPoolSDK.init(). In a browser application, fetch these files from your asset server:
PrivacyPoolSDK.init() is async and resolves to an initialized SDK instance. Hold on to this instance for the lifetime of your page or session — creating multiple instances is unnecessary.
SDK capabilities
Stealth addresses
Derive a deterministic
stpl1 Bech32 private address from a Stellar wallet signature. Share this address with depositors so they can encrypt coins to you.Coin creation
Generate new private coins, coins bound to a recipient via an ECDH shared secret, or coins for a deposit flow with a pre-shared hex secret.
Merkle witness
Read the current commitment tree from the contract and build the Merkle inclusion witness required for the ZK circuit.
Proof generation
Produce a Groth16 proof attesting to the validity of a withdrawal or general transaction without revealing private inputs.
Soroban serialization
Serialize a proof and public signals into the hex-encoded byte formats that
PrivacyPoolsContract.transact accepts.Nullifier helpers
Compute
nullifierHash = Poseidon(nullifier) off-chain to check whether a coin has already been spent.ECDH helpers
Generate ephemeral key pairs and compute ECDH shared secrets on the BabyJubJub curve for the deposit-side private address flow.
API reference
Stealth addresses
PrivacyPoolSDK.buildStealthAddressSignMessage(stellarAddress: string): string
Builds the message a user must sign with their Stellar wallet to derive their stealth address. This is a static method — you can call it before the SDK is initialized.
sdk.generateStealthAddressFromStellarSignature(signature: string): Promise<string>
Hashes the provided wallet signature with SHA-256, derives a BabyJubJub scalar, and encodes the resulting public point as a stpl1 Bech32 stealth address.
Coin creation
sdk.generateCoin(): Promise<Coin>
Generates a new private coin with a random nullifier and secret. Use this for the output side of a transfer or when the recipient will recover the coin out-of-band.
sdk.generateCoinWithSharedSecret(recipientStealthAddress: string): Promise<CoinWithEphemeral>
Generates a coin whose sharedSecret is derived from an ECDH exchange with the recipient’s stpl1 stealth address. The depositor’s ephemeral public key is stored on-chain alongside the commitment so the recipient can recover the coin.
sdk.generateCoinForDepositWithSharedHex(sharedSecretHex: string): Promise<Coin>
Generates a deposit coin from a pre-computed shared secret provided as a hex string. Use this when you have already performed the ECDH exchange externally.
Merkle witness
sdk.buildWithdrawMerkleWitness(params: WitnessParams): Promise<MerkleWitness>
Builds the Merkle inclusion proof for a coin you intend to spend. You must supply the full list of commitments currently stored in the contract (fetched via get_commitments()) and the tree depth (fetched via get_merkle_depth()).
Proof generation
sdk.proveWithdrawal(params: WithdrawalParams): Promise<ProofResult>
Generates a Groth16 proof for a withdrawal transaction — spending a private input coin and releasing funds to a public Stellar address.
sdk.proveTransaction(params: TransactionParams): Promise<ProofResult>
Generates a Groth16 proof for a general transaction with explicit control over input coins, output coins, and public deposit/withdrawal amounts.
Soroban serialization
sdk.proofToHex(proof: Proof): string
Serializes a Groth16 proof into the hex-encoded byte string expected by the proof_bytes argument of transact.
sdk.publicToHex(publicSignals: PublicSignals): string
Serializes public circuit signals into the hex-encoded byte string expected by the pub_signals_bytes argument of transact.
Nullifier helpers
sdk.calculateNullifierHash(nullifier: string): Promise<string>
Computes Poseidon(nullifier) and returns the nullifier hash as a decimal string. Use this to check whether a coin has already been spent before building a proof.
ECDH helpers
sdk.ecdhEphemeralPublicKeyFromScalarHex(scalarHex: string): Promise<EphemeralPublicKey>
Derives the BabyJubJub public key corresponding to a given ephemeral scalar (hex-encoded). Use this on the depositor side to produce the public key that gets stored on-chain with the commitment.
sdk.ecdhSharedKey(privateScalarHex: string, otherPublicKey: EphemeralPublicKey): Promise<SharedKey>
Computes the ECDH shared secret between a private scalar and a BabyJubJub public key. Use this on the recipient side to recover the shared secret from the depositor’s ephemeral public key stored on-chain.
What the SDK does NOT handle
PrivacyPoolSDK handles only the cryptographic and serialization steps on the client side. It does not:
- Manage disclosure cases or audit reports
- Control auditor permissions or case assignments
- Communicate with the Arcane backend APIs
- Index or interpret on-chain events
transact to the Soroban contract; Arcane handles everything that happens after the event is emitted.