zksdk Pools
zksdk lets you add a private-swap button to your DEX, wallet, or aggregator in an afternoon. Your user picks tokenIn / tokenOut, clicks once, and the trade lands on-chain against a shielded pool — the counterparties can't see who's on the other side, the amounts, or the route.
Overview
What this gets you
- Counterparty privacy on-chain. The DEX router sees an anonymous pool, not your user's address.
- Users don't need ETH in their wallet. Fees are paid in any token the broadcaster accepts — often the token being swapped, or USDC — and the broadcaster pays the actual ETH gas on-chain. One EIP-712 signature authorizes both the swap and the fee (
feeToken+feeAmountare first-class fields in the signed payload). - You're part of the anonymity set, not just a consumer of it. Every integrator who routes through the shared pool adds their users to the same crowd — your traffic hides in theirs, theirs hides in yours. Bring your users in and you make the pool stronger for everyone, including yourselves.
Cryptographic security. Groth16 proofs require a per-circuit trusted setup — Powers of Tau (universal, reusable across circuits) plus a Phase 2 contribution per circuit. v0.9 / v0.95 use a dev-phase ceremony suitable for testnet; v1.0 ships a public multi-party Phase 2 alongside the audit, so forging proofs would require collusion from every contributor. Partners deploying their own pool via
ShieldedPoolFactoryreuse the same.zkeyartifacts — no per-partner ceremony needed.
Where a feature needs a specific release it's marked inline (v0.95, v1.0, v1.x) — see the full Roadmap.
Four integration shapes
Add a "Swap Privately" button to your DEX, wallet, or aggregator. Four shapes, ordered by effort:
| Shape | Time to integrate | Your brand | Works with |
|---|---|---|---|
| Deep-link | 5 minutes (v0.95, hosted at app.zksdk.io) | Ours | Any pool (URL param) |
| Iframe widget | 1–2 hours (v0.95, hosted) · today if you self-deploy the Next.js app | Yours around ours | Any pool (URL param) |
SDK (@zksdk/privacy) | Half a day | Fully yours | Any pool — shared, contracts you own via ShieldedPoolFactory, or self deployed contracts |
| Self-host | Weeks today · days in v1.x | Fully yours | You run the full stack — your contracts, your broadcaster, your forked frontend |
Every shape lands the same on-chain private swap, through the same Groth16 verifier, using the same meta-tx broadcaster — your users never pay gas from their EOA and never submit a regular tx.
Shape ≠ pool choice. The four shapes above are about how the UI gets into your app. Which pool you route through — the shared one, your own
ShieldedPoolFactorydeployment, or another integrator's — is an independent decision. The SDK, iframe, and deep-link all accept any pool address. You can ship the SDK against your own contracts from day one, or start on the shared pool and graduate to your own later without rewriting integration code.
Shared pool vs your own pool
You pick what you swap against:
- Shared pool. Route through the pool that every integrator shares. Your users and every other partner's users land in the same anonymity set — the more partners plug in, the stronger the crowd gets for all of them. No infra on your side.
- Your own pool. Deploy via
ShieldedPoolFactoryand become a pool operator yourself. Your allowlist, your compliance module, your uptime. Your pool starts with just your users, and other integrators can route through it the same way you can route through anyone else's. Right call when you want to own the distribution, the compliance policy, or both.
Private swap happens in the user's browser — the spend key never leaves the device (a cryptographic requirement, not an implementation choice). That's why privateSwap isn't a REST endpoint. Everything else (pool admin, deposit/withdraw envelopes, audit, compliance) is — see the REST API.
Cold start handled for you. A user with no shielded balance in the target pool gets an inline "Shield to start" deposit step inside the widget. They deposit, the form flips to swap mode, no wiring on your end.