DOCUMENTATION

SDK Reference — @tracezero/sdk

A typed TypeScript client for the TraceZero relayer/gateway API, plus the authenticated usage telemetry that drives the live counter on the home page.

The client is a thin orchestration layer over the relayer’s HTTP contract (crates/relayer). It does not reimplement the protocol cryptography (blind signatures, Poseidon commitments, Groth16 proving, Tor routing) — you produce those (for example with the in-browser libraries in app/src/lib) and pass them in.

Install

npm install @tracezero/sdk

Client

import { TraceZeroClient } from "@tracezero/sdk";

const client = new TraceZeroClient({
  relayerUrl: "http://localhost:8080",
  telemetry: { counterUrl: "https://counter.tracezero.dev" }, // optional
});

Methods

MethodEndpointDescription
getInfo()GET /infoRSA public key, fee (bps), and the 7 denomination buckets.
purchaseCredits(req)POST /signSubmit a blinded token + payment proof → blind signature.
deposit(req, encryptedBody?)POST /depositSubmit a commitment. Pass a pre-encrypted body for Tor.
withdraw(req)POST /withdrawSubmit a Groth16 proof + public inputs with a timelock.
executeWithdrawal(nullifierHash)POST /withdraw/executeTrigger a pending timelocked withdrawal.
getMerkleProof(bucket, leaf)GET /proof/:b/:lInclusion proof used to build a withdrawal proof.
getPool(id) / getAllPools()GET /poolsPool / anonymity-set state.
getPendingWithdrawals()GET /withdraw/pendingThe timelock queue.
usageStats()counter GET /statsLive authenticated usage stats.

Denomination buckets

import { BUCKET_AMOUNTS, bucketIdForAmount, LAMPORTS_PER_SOL } from "@tracezero/sdk";
// [0.1, 0.5, 1, 5, 10, 50, 100] SOL, in lamports
bucketIdForAmount(1 * LAMPORTS_PER_SOL); // => 2

Authenticated usage telemetry

Every tracked call emits one Ed25519-signed event to the counter Worker. Each SDK install holds a random keypair — an anonymous identity, not a Solana wallet. The event is canonical JSON, signed with that key:

// signed payload (canonical, sorted keys)
{ "nonce": "<16-byte hex>", "op": "deposit", "pub": "<ed25519 pubkey hex>", "ts": 1700000000 }
// envelope POSTed to the counter
{ "payload": "<base64 of the bytes above>", "sig": "<ed25519 sig hex>", "pub": "<pubkey hex>" }

The Worker verifies the signature against the embedded pub and rejects replayed nonces. So the live counter can only move for real, distinct, authenticated usage — it cannot be inflated by unsigned or replayed requests, and users stay anonymous.

Opt out

new TraceZeroClient({
  relayerUrl: "http://localhost:8080",
  telemetry: { enabled: false }, // or simply omit `counterUrl`
});

Read the live aggregate

const stats = await client.usageStats();
// { total, byOp: { deposit, withdraw, ... }, uniqueUsers, updatedAt }

Verifying an event yourself

The same verification the Worker runs is exported, so you can audit the scheme:

import { buildSignedEvent, verifyEnvelope, ed25519 } from "@tracezero/sdk";

const { privateKey, publicKey } = await ed25519.generateKeypair();
const env = await buildSignedEvent("deposit", privateKey, ed25519.toHex(publicKey), 1700000000);
const { ok } = await verifyEnvelope(env); // true; tamper with env.sig or env.payload → false