SDK API Reference
Complete API reference for @zkmix/sdk
SDK API Reference
This page documents every public class, method, and type exported by the @zkmix/sdk package.
ZKMix Class
The ZKMix class is the main entry point for all SDK operations. It manages connections, pool discovery, proof generation, and transaction submission.
Constructor
constructor(config: ZKMixConfig)Creates a new ZKMix instance.
Parameters:
interface ZKMixConfig {
/** Solana RPC connection */
connection: Connection;
/** Solana cluster identifier */
cluster: "mainnet-beta" | "devnet" | "localnet";
/** URL to the proving key file (required for browser proof generation) */
provingKeyUrl?: string;
/** URL to the WASM circuit file (required for browser proof generation) */
wasmUrl?: string;
/** Path to the proving key file (Node.js only) */
provingKeyPath?: string;
/** Path to the WASM circuit file (Node.js only) */
wasmPath?: string;
/** Override the default Mixer Program ID */
mixerProgramId?: PublicKey;
/** Override the default Verifier Program ID */
verifierProgramId?: PublicKey;
}Example:
import { Connection } from "@solana/web3.js";
import { ZKMix } from "@zkmix/sdk";
const zkmix = new ZKMix({
connection: new Connection("https://api.mainnet-beta.solana.com"),
cluster: "mainnet-beta",
});deposit()
async deposit(params: DepositParams): Promise<DepositResult>Deposits funds into a ZKMix pool. Generates a random commitment, builds and submits the deposit transaction, and returns a DepositNote that must be saved for later withdrawal.
Parameters:
interface DepositParams {
/** Wallet to sign the transaction and fund the deposit */
wallet: Keypair | WalletAdapter;
/** Token symbol ("SOL") or mint address for SPL tokens */
token: string | PublicKey;
/** Deposit amount in smallest units (lamports for SOL, base units for SPL) */
denomination: number | bigint;
/** Optional transaction configuration */
options?: TransactionOptions;
}
interface TransactionOptions {
/** Confirmation commitment level */
commitment?: "processed" | "confirmed" | "finalized";
/** Maximum number of retry attempts */
maxRetries?: number;
/** Whether to skip preflight simulation */
skipPreflight?: boolean;
/** Compute unit limit override */
computeUnits?: number;
/** Priority fee in microlamports per compute unit */
priorityFee?: number;
}Returns:
interface DepositResult {
/** The deposit note containing secret, nullifier, and metadata */
note: DepositNote;
/** The transaction signature */
txSignature: string;
/** The commitment hash inserted into the Merkle tree */
commitment: string;
/** The leaf index in the Merkle tree */
leafIndex: number;
/** The block time of the confirmed transaction */
blockTime: number;
}Errors:
| Error | Description |
|---|---|
PoolNotFoundError | No pool exists for the given token and denomination |
PoolInactiveError | The pool is currently paused |
InsufficientFundsError | Wallet balance is below the denomination |
TransactionError | The transaction failed on-chain |
Example:
const result = await zkmix.deposit({
wallet: myKeypair,
token: "SOL",
denomination: 1_000_000_000,
});
console.log(`Deposited! Leaf index: ${result.leafIndex}`);
// Save result.note.serialize() securelywithdraw()
async withdraw(params: WithdrawParams): Promise<WithdrawResult>Withdraws funds from a ZKMix pool. Fetches the Merkle tree, generates a zero-knowledge proof, and submits the withdrawal transaction either directly or through a relayer.
Parameters:
interface WithdrawParams {
/** The deposit note from a previous deposit */
deposit: DepositNote;
/** The recipient address for the withdrawn funds */
recipient: PublicKey;
/** Whether to use a relayer for gas-less withdrawal */
useRelayer?: boolean;
/** Specific relayer URL (overrides automatic selection) */
relayerUrl?: string;
/** Wallet to sign and pay for the transaction (required if useRelayer is false) */
wallet?: Keypair | WalletAdapter;
/** Optional transaction configuration */
options?: TransactionOptions;
}Returns:
interface WithdrawResult {
/** The transaction signature */
txSignature: string;
/** The nullifier hash that was spent */
nullifierHash: string;
/** The relayer fee paid (0 if no relayer was used) */
relayerFee: number;
/** The net amount received by the recipient */
amountReceived: number;
/** The block time of the confirmed transaction */
blockTime: number;
}Errors:
| Error | Description |
|---|---|
InvalidNoteError | The deposit note is malformed or corrupted |
NoteAlreadySpentError | This deposit has already been withdrawn |
ProofGenerationError | Failed to generate the ZK proof |
NoRelayerAvailableError | No relayer is available for this pool |
RelayerError | The relayer rejected the request or returned an error |
TransactionError | The transaction failed on-chain |
Example:
const result = await zkmix.withdraw({
deposit: savedNote,
recipient: freshAddress,
useRelayer: true,
});
console.log(`Withdrawn! Tx: ${result.txSignature}`);
console.log(`Amount received: ${result.amountReceived} lamports`);getDeposits()
async getDeposits(params: GetDepositsParams): Promise<DepositEvent[]>Fetches deposit events from a specific pool. This is useful for reconstructing the Merkle tree state, computing anonymity set sizes, or building analytics dashboards.
Parameters:
interface GetDepositsParams {
/** Token symbol or mint address */
token: string | PublicKey;
/** Pool denomination */
denomination: number | bigint;
/** Starting leaf index (inclusive, default: 0) */
fromIndex?: number;
/** Ending leaf index (exclusive, default: latest) */
toIndex?: number;
/** Maximum number of events to return */
limit?: number;
}Returns:
interface DepositEvent {
/** The commitment hash */
commitment: string;
/** The leaf index in the Merkle tree */
leafIndex: number;
/** Unix timestamp of the deposit */
timestamp: number;
/** Transaction signature */
txSignature: string;
}Example:
// Get the last 100 deposits to the SOL-1 pool
const deposits = await zkmix.getDeposits({
token: "SOL",
denomination: 1_000_000_000,
limit: 100,
});
console.log(`Found ${deposits.length} recent deposits`);
deposits.forEach((d) => {
console.log(` Leaf ${d.leafIndex}: ${d.commitment} at ${new Date(d.timestamp * 1000)}`);
});generateProof()
async generateProof(params: GenerateProofParams): Promise<ProofData>Generates a Groth16 zero-knowledge proof for a withdrawal without submitting a transaction. This is useful for advanced use cases where you want to construct the transaction yourself or submit the proof through a custom relayer integration.
Parameters:
interface GenerateProofParams {
/** The deposit note */
deposit: DepositNote;
/** The recipient address */
recipient: PublicKey;
/** The relayer fee (use 0 for direct withdrawals) */
relayerFee: number | bigint;
/** The Merkle tree state (fetched automatically if not provided) */
treeState?: MerkleTreeState;
}Returns:
interface ProofData {
/** The serialized proof */
proof: {
a: [string, string];
b: [[string, string], [string, string]];
c: [string, string];
};
/** The public inputs */
publicInputs: {
root: string;
nullifierHash: string;
recipient: string;
fee: string;
};
/** Time taken to generate the proof in milliseconds */
generationTime: number;
}Example:
// Generate proof without submitting
const proofData = await zkmix.generateProof({
deposit: savedNote,
recipient: freshAddress,
relayerFee: 3_000_000,
});
console.log(`Proof generated in ${proofData.generationTime}ms`);
console.log(`Root: ${proofData.publicInputs.root}`);
console.log(`Nullifier hash: ${proofData.publicInputs.nullifierHash}`);
// Submit the proof manually through a custom relayer
const response = await fetch("https://my-custom-relayer.com/relay", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
proof: proofData.proof,
...proofData.publicInputs,
poolAddress: poolAddress.toBase58(),
}),
});Utility Functions
getPools()
async getPools(): Promise<PoolInfo[]>Returns a list of all active ZKMix pools with their current state.
interface PoolInfo {
/** Pool account address */
address: PublicKey;
/** Token symbol */
token: string;
/** Token mint address */
tokenMint: PublicKey;
/** Denomination in smallest units */
denomination: bigint;
/** Human-readable denomination */
denominationFormatted: string;
/** Total number of deposits */
depositCount: number;
/** Number of withdrawals (spent nullifiers) */
withdrawalCount: number;
/** Current anonymity set size (deposits - withdrawals) */
anonymitySetSize: number;
/** Whether the pool is accepting deposits */
isActive: boolean;
/** Merkle tree capacity */
treeCapacity: number;
/** Current tree utilization (0.0 to 1.0) */
treeUtilization: number;
/** Vault balance in smallest units */
vaultBalance: bigint;
}Example:
const pools = await zkmix.getPools();
for (const pool of pools) {
console.log(`${pool.denominationFormatted} - ${pool.anonymitySetSize} deposits`);
}getPoolInfo()
async getPoolInfo(token: string | PublicKey, denomination: number | bigint): Promise<PoolInfo>Returns detailed information about a specific pool.
const info = await zkmix.getPoolInfo("SOL", 1_000_000_000);
console.log(`Anonymity set: ${info.anonymitySetSize}`);
console.log(`Vault balance: ${info.vaultBalance} lamports`);parseNote()
parseNote(noteString: string): DepositNoteDeserializes a deposit note from its string representation.
const note = zkmix.parseNote("zkmix-1.0-devnet-SOL-1000000000-0x3a4b...-0x9e0f...-42");
console.log(`Token: ${note.token}`);
console.log(`Denomination: ${note.denomination}`);
console.log(`Leaf index: ${note.leafIndex}`);isNoteSpent()
async isNoteSpent(note: DepositNote): Promise<boolean>Checks whether a deposit note has already been used for a withdrawal by querying the on-chain nullifier set.
const spent = await zkmix.isNoteSpent(savedNote);
if (spent) {
console.log("This deposit has already been withdrawn");
} else {
console.log("This deposit is still available for withdrawal");
}getRelayers()
async getRelayers(poolAddress?: PublicKey): Promise<RelayerInfo[]>Fetches available relayers from the on-chain registry. Optionally filters to relayers that support a specific pool.
interface RelayerInfo {
/** Relayer's Solana address */
address: PublicKey;
/** Relayer's HTTP endpoint */
url: string;
/** Fee percentage in basis points */
feePercentage: number;
/** Whether the relayer is currently active */
isActive: boolean;
/** Pools the relayer supports */
supportedPools: PublicKey[];
/** SOL staked by the relayer */
stake: bigint;
}Example:
const relayers = await zkmix.getRelayers();
console.log(`${relayers.length} relayers available`);
for (const relayer of relayers) {
console.log(` ${relayer.url} - ${relayer.feePercentage / 100}% fee`);
}verifyVaultIntegrity()
async verifyVaultIntegrity(token: string | PublicKey, denomination: number | bigint): Promise<VaultIntegrityResult>Verifies that a pool's vault balance matches the expected value based on deposit and withdrawal counts.
interface VaultIntegrityResult {
/** Whether the vault balance is correct */
isValid: boolean;
/** Expected vault balance */
expectedBalance: bigint;
/** Actual vault balance */
actualBalance: bigint;
/** Difference (0 if valid) */
difference: bigint;
}Example:
const integrity = await zkmix.verifyVaultIntegrity("SOL", 1_000_000_000);
if (integrity.isValid) {
console.log("Vault integrity verified");
} else {
console.error(
`Vault mismatch! Expected ${integrity.expectedBalance}, ` +
`got ${integrity.actualBalance}`
);
}DepositNote Class
The DepositNote class encapsulates all data needed to withdraw a deposit. It is returned by deposit() and consumed by withdraw().
Properties
class DepositNote {
/** The random secret (private, never shared) */
readonly secret: Uint8Array;
/** The random nullifier (private, never shared) */
readonly nullifier: Uint8Array;
/** The commitment hash (public, stored on-chain) */
readonly commitment: string;
/** The nullifier hash (public, revealed during withdrawal) */
readonly nullifierHash: string;
/** Token identifier */
readonly token: string;
/** Pool denomination */
readonly denomination: bigint;
/** Leaf index in the Merkle tree */
readonly leafIndex: number;
/** Network cluster */
readonly cluster: string;
}Methods
serialize()
serialize(): stringSerializes the deposit note to a compact string format for storage.
const noteString = note.serialize();
// "zkmix-1.0-devnet-SOL-1000000000-0x3a4b5c6d...-0x9e0f1a2b...-42"toJSON()
toJSON(): objectReturns a JSON-serializable representation of the note.
const json = note.toJSON();
// {
// version: "1.0",
// cluster: "devnet",
// token: "SOL",
// denomination: "1000000000",
// secret: "0x3a4b5c6d...",
// nullifier: "0x9e0f1a2b...",
// commitment: "0x1234abcd...",
// leafIndex: 42
// }