Skip to main content
Shielding (deposits) is temporarily paused. After StarkWare’s July 2026 STRK20 pool v2.0 upgrade, depositing into the shared privacy pool requires a screener attestation issued by StarkWare’s hosted proving service — Chipi is finalizing that access. Unshielding and private-balance reads work today; new shields will revert until access lands. Don’t ship a shield flow to production yet — we’ll announce on X (@hichipipay) the moment shielding is back on.
Production-proven engine (Chipi’s consumer wallet “Modo privado”, mainnet). Mental model for your users: checking/savings — visible money is for spending, private money is what they keep, invisible to everyone but them.

The five rules

  1. Key handling: privacy keys derive client-side from the user’s anchor (passkey encryptKey / PRF) and are never stored server-side. Cache the companion address, never the keys. Note the proving trust model below — it bounds what “private” may honestly mean in your copy.
  2. One passkey gesture per shield/unshield — that IS the security model. Set the expectation: “You confirm with your fingerprint or Face ID — the same as when you send money.”
  3. Browsers need a gateway proxy (gatewaySubmitUrl): the Starknet sequencer gateway has no CORS. Install the private-balance-card registry item to get the proxy route, or copy it from the example.
  4. Capture the StarkWare pool ToS at the user’s first shield.
  5. Fees: fixed 4 STRK per op, fronted by Chipi’s gas tank (metered per API key) — your user never holds STRK. Show it in USD via getShieldFee.

The trust model, honestly

Keys derive client-side and are never stored server-side — but STRK20’s delegated proving requires the pool spending key inside each proof request, so Chipi’s proving service (a private prover Chipi operates; the same model as StarkWare’s hosted prover) sees it per operation and must be trusted not to retain or use it. Privacy holds against the public — chain observers, other users — not against the proving operator. Do not tell your users “nobody, including Chipi, can see your balance.” Local proving is the roadmap item that removes this trust.

What is the “companion”?

Each user gets a lightweight standard account (the companion) as their pool identity, derived deterministically from their anchor and deployed automatically on first shield. You only supply a standard SNIP-6 account class hash (classHash, e.g. OpenZeppelin 0x061dac03…); everything else is handled. Why a companion instead of changing the account class: see our design write-up on the Starknet forum, and the Core SDK privacy page for the architecture.

Quickstart

Record every settled op in your own store — your ledger is the display source of truth (the chain won’t cleanly surface confidential moves). Failures never strand money: a failed shield parks funds in the companion and the next attempt sweeps them in; say “your money is safe” in error copy.

Multiple tokens

The pool holds any ERC-20, and the engine batches deposits:
  • Shielding N tokens costs ONE proof and ONE 4-STRK fee — batch with the core-level execShieldMany (mainnet-proven). The useShield hook is per-token by design; for a multi-token shield call the core engine directly.
  • Unshielding is per token (no unshieldMany yet): each withdrawal is its own proof and its own 4-STRK fee, and consecutive withdrawals must wait ~5–6 minutes for the prover’s view to catch up (they share the note channel). Run them sequentially, surface partial results honestly — what came back IS back, the rest stays private and retryable — and never call it a failure. Full pattern with the wait/refuel details on the Core SDK privacy page.
Product tip from Chipi’s wallet: apply a small per-token dust floor (~$0.25) before adding a coin to the batch, and SHOW excluded coins greyed out with the reason — a silently skipped token reads as lost money to the user. Full headless example (also the release smoke): examples/private-balance in the SDK repo; multi-token evidence: scripts/multi-token-smoke.mjs (S5). Agent skill: chipi-private-balances.