SDK & Integration
SDK: Privacy Pool notes
Working with fixed-denomination notes in code: create a PoolNote, derive its commitment and nullifier hash, build a withdrawal witness across the state and association trees, and prove it.
A PoolNote is the Profile B note: a (nullifier, secret) pair whose commitment = H(nullifier, secret). Both values are random F_p by default and are the only things you need to keep to withdraw.
Creating a note & depositing
import { PoolNote, toFixedHex } from "@shh/sdk";
import { ethers } from "ethers";
const note = new PoolNote(); // fresh nullifier + secret
const commitment = await note.commitment();
// deposit exactly the pool denomination
await pool.deposit(toFixedHex(commitment), { value: denomination });
// persist these — they are the funds:
save({ nullifier: note.nullifier, secret: note.secret });The PoolNote API
new PoolNote(nullifier?, secret?)- Both default to
randomField(). Pass saved values to reconstruct a note for withdrawal. note.commitment()Promise<bigint>—H(nullifier, secret), the deposited leaf.note.nullifierHash()Promise<bigint>—H(nullifier), published on withdraw to prevent double spend.
Building a withdrawal witness
buildPoolWithdrawInput is browser-safe — it produces the circuit input without proving. It needs both trees, the note, and the bound withdrawal parameters:
import { buildPoolWithdrawInput } from "@shh/sdk";
const { input, stateRoot, associationRoot, nullifierHash } =
await buildPoolWithdrawInput({
note,
stateTree, // MerkleTree of all deposited commitments
associationTree, // MerkleTree of ASP-approved commitments
recipient, // address as uint (bigint)
relayer, // bind the relayer (or 0n to self-submit)
fee,
refund,
});It looks up the commitment's index in both trees (throwing if it isn't approved), generates both Merkle proofs, and assembles every public and private signal the circuit expects.
Proving (Node)
import { generatePoolWithdraw } from "@shh/sdk/node";
const { proof, stateRoot, associationRoot, nullifierHash } =
await generatePoolWithdraw({
note, stateTree, associationTree,
recipient, relayer, fee, refund,
wasmPath: "build/poolWithdraw.wasm",
zkeyPath: "build/poolWithdraw.zkey",
});
// proof is already in Solidity (a, b, c) shape — see formatProofTo submit without paying gas yourself, hand the proof to the relayer.