ZeraLabs logo
WALLET

Architecture

Deployment stack, proof generation performance, Merkle sync, and monitoring

The ZERA stack runs on Cloudflare Workers (edge), Solana (on-chain programs), and Tauri (desktop). All deployments use semantic versioning with automated releases.

Deployment Architecture

┌─────────────────────────────────────────────────────┐
│ ZERA STACK │
├──────────────┬──────────────┬───────────────────────┤
│ Web Wallet │ Landing │ Web API │
│ (PWA) │ Site │ (REST) │
│ CF Workers │ CF Workers │ CF Workers │
│ TanStack │ TanStack │ Express + Prisma │
│ + Privy │ Start │ + Neon Postgres │
├──────────────┴──────────────┴───────────────────────┤
│ Solana Programs │
│ Shielded Pool: B83jSQx1CT1hPRBu...ZNeX │
│ Private Cash: ESQxpH9XkBQT6EVe...YsgF │
├─────────────────────────────────────────────────────┤
│ SDK (npm) │
│ @zera-labs/sdk — TypeScript SDK │
│ @zera-labs/mcp-server — AI agent tools │
│ zera-core — Rust crate │
│ zera-neon — napi-rs bindings │
└─────────────────────────────────────────────────────┘

Web Wallet Deployment

# Production deployment
pnpm build && pnpm wrangler deploy
# Staging (next branch — separate worker, doesn't touch prod)
pnpm build && pnpm wrangler deploy --env next
# Environment: Cloudflare Workers
# Worker name: zera-wallet-web (prod), zera-wallet-web-next (staging)
# CSP: nonce-based script injection via worker entry
# Security headers: injected at the edge
# Service worker: cached for offline PWA support
# Versioning: semantic, auto-released via GitHub Actions

SDK Publishing

# TypeScript SDK
cd packages/sdk
pnpm build # tsc + bundler
pnpm publish # → @zera-labs/sdk on npm
# MCP Server
cd packages/mcp-server
pnpm build && pnpm publish # → @zera-labs/mcp-server on npm
# Rust crate
cd crates/zera-core
cargo publish # → zera-core on crates.io
# Node native bindings
cd crates/zera-neon
pnpm build # napi-rs compile
pnpm publish # platform-specific binaries
# Requirements: Node >= 18, pnpm >= 9

Desktop Wallet (Tauri)

# Development
pnpm tauri dev
# Production build (platform-specific)
pnpm tauri build
# Outputs: .dmg (macOS), .msi (Windows), .AppImage (Linux)
# Stack:
# - Tauri 2 (Rust backend + webview frontend)
# - React 18 + Vite
# - Zustand + Immer state management
# - NFC via PC/SC (ACR122U, PN532)
# - OFAC screening via TRM Labs API
# - Keystore: Argon2id KDF + ChaCha20-Poly1305 encryption
# stored at $APPDATA/zera/wallet.enc

Solana Programs

# Build with Anchor
anchor build
# Deploy to devnet
anchor deploy --provider.cluster devnet
# Program IDs (mainnet)
# Shielded Pool: B83jSQx1CT1hPRBupinaJaEkCjrfeo6Ktncu31q3ZNeX
# Private Cash: ESQxpH9XkBQT6EVeWwAzTZD1e9NrLMrY8RPQ9SidYsgF
# Key accounts:
# - Pool Config PDA (per mint)
# - Merkle Tree PDA (per mint)
# - Vault PDA (token custody)
# - Fee Vault PDA (fee collection)
# - Nullifier PDAs (one per spent note)

Proof Generation Performance

Groth16 proof generation is the most expensive client-side operation. The SDK uses snarkjs groth16.fullProve() which runs entirely in the browser or Node.js:

// Performance characteristics (approximate)
Deposit proof: ~2-5 seconds (browser), ~1-2s (Node.js)
Withdraw proof: ~3-8 seconds (24-level Merkle witness)
Transfer proof: ~5-10 seconds (1-input, 2-output circuit)
// Optimization: preload circuit files
// WASM and zkey files are large — cache them aggressively
const wasmPath = '/circuits/withdraw.wasm' // ~2-5 MB
const zkeyPath = '/circuits/withdraw.zkey' // ~10-50 MB
// Circuit integrity verification (SHA-256)
// Always verify file hashes before proving to prevent
// supply-chain attacks on the circuit files

Poseidon Hashing

Poseidon X5 over BN254 is ZK-friendly by design — far fewer constraints than SHA-256 or Keccak inside a circuit:

// TypeScript: circomlibjs (JavaScript, ~0.1ms per hash)
import { poseidonHash, poseidonHash2 } from '@zera-labs/sdk/crypto'
// Rust: light-poseidon (native, ~10μs per hash)
// Available via napi-rs bindings in @zera-labs/neon
// Merkle tree insertion: 24 hashes (one per level)
// Commitment computation: 1 hash (8 inputs)
// Nullifier computation: 1 hash (2 inputs)
// For high-throughput scenarios, use the Rust bindings
// via zera-neon for ~10x speedup on Poseidon operations

Merkle Tree Sync

The TreeStateClient supports incremental sync — only fetch new leaves since your last checkpoint:

import { TreeStateClient } from '@zera-labs/sdk'
const client = new TreeStateClient({
rpcUrl: 'https://api.mainnet-beta.solana.com',
cacheEndpoint: 'https://api.zeralabs.org/merkle' // optional cache
})
// First sync: fetches all leaves from chain (or cache)
const leaves = await client.fetchAllLeaves()
// Incremental sync: only new leaves since last tx signature
const newLeaves = await client.fetchAllLeaves(false)
// Cache API returns Merkle snapshots stored in Cloudflare R2
// Falls back to direct RPC if cache is unavailable
// Root history buffer: 100 entries
// Allows concurrent transactions without root mismatch

On-Chain Verification

On-chain Groth16 verification is cheap — Solana's native alt_bn128 precompile handles the pairing check:

// Single Solana transaction includes:
// 1. Groth16 proof verification (alt_bn128 pairing)
// 2. Merkle tree leaf insertion (or nullifier PDA creation)
// 3. Token transfer (SPL token program)
// 4. Fee calculation and distribution
// Transaction cost: ~5,000 lamports (~$0.001)
// Finality: ~400ms (Solana slot time)
// Compute units: ~200,000-400,000 CU per proof verify
// Root history buffer holds 100 roots
// Concurrent deposits don't invalidate pending withdrawals

Web Wallet Optimizations

The browser wallet (wallet.zeralabs.org) uses several techniques to keep the UX fast:

// Service Worker caching for circuit files
// WASM and zkey files cached on first load
// Subsequent proof generations skip network fetch
// Real-time price feed via WebSocket
// wss://price.zeralabs.org/ws — no polling overhead
// Helius RPC proxy for optimized Solana queries
// DAS API for token metadata enrichment
// Transaction confirmation polling
// 90-second timeout, multiple confirmation strategies
// Polls every 2 seconds for payment status
// Brotli compression on all static assets (Vite plugin)
// Service worker pre-caches critical routes

Monitoring & Observability

# Web wallet: Sentry (error tracking + session replay)
# - Automatic user feedback collection on errors
# - Source maps uploaded on deploy
# - Performance tracing for proof generation
# Real-time pricing: WebSocket feed
# wss://price.zeralabs.org/ws
# RPC: Helius proxy for optimized Solana queries
# - DAS API for token metadata
# - Compressed account indexing
# - Transaction history with enrichment
# Merkle state cache: Cloudflare R2 + D1
# - Snapshots stored in R2 (object storage)
# - Index in D1 (SQLite at the edge)
# - Reduces direct RPC load for tree sync

More Developer Resources

Quick Start

Deposit in 15 lines with @zera-labs/sdk

SDK Reference

Complete function signatures, types, constants

Testing & Security

144 tests, invariants, OFAC screening