A workbench for smart accounts. Sign in with a passkey, then poke at every trick the ERC-4337 / ERC-7702 / Kernel v3 stack has to offer.
Demo: coming soon — see DEPLOY.md
One Next.js app, 18 feature tabs, every one a single concept from account abstraction:
| # | Tab | What it shows | State |
|---|---|---|---|
| 1 | ECDSA account | Bare Kernel with an EOA owner | ready |
| 2 | Gasless transaction | ZeroDev paymaster sponsors gas | ready |
| 3 | Pay gas in ERC-20 | Paymaster pulls USDC to settle gas | wip |
| 4 | Batch transactions | N atomic calls in one UserOp | ready |
| 5 | Session keys | Permission validator with call / gas / rate / time | wip |
| 6 | Passkey-only account | Kernel whose only owner is a WebAuthn credential | wip |
| 7 | Multisig | Weighted multisig validator | wip |
| 8 | Guardian recovery | Recovery plugin with timelock | wip |
| 9 | Chain abstraction (CAB) | Spend cross-chain balances | parked |
| 10 | Sign & verify (ERC-1271) | Smart-account signatures verified on chain | ready |
| 11 | EIP-7702 upgrade | Promote an existing EOA in place | parked |
| 12 | Intents | Declarative cross-chain UX | wip |
| 13 | Magic address | One address, every chain | wip |
| 14 | ERC-7579 hooks | Spending limits / allowlists as pre-exec hooks | parked |
| 15 | Counterfactual deploy | Predict an address, deploy on first UserOp | ready |
| 16 | WalletConnect / EIP-5792 | Expose the smart account as a connectable wallet | parked |
| 17 | Multi-chain ECDSA | One signature, N chains, via a merkle root | parked |
| 18 | Kernel migration | In-place implementation upgrade | parked |
🟢 ready — works end-to-end, smoke-test target. 🟡 wip — scaffolded against the real SDK; not yet verified in browser. ⚫ parked — upstream SDK gap or needs external infra (Reown, off-chain server).
Sign in with one passkey. That same passkey:
- Signs every UserOperation on chain. ZeroDev's passkey validator verifies WebAuthn signatures inside the Kernel account. No EOA required.
- Cross-device by default if your platform syncs passkeys — iCloud Keychain, Google Password Manager, 1Password, Bitwarden. Sign in on a new device by typing the same label.
- Optionally derives an AES key (WebAuthn PRF extension) to wrap session keys at rest. Lazy: only triggered when you actually create a session key, never during onboarding.
No seed phrase. Nothing else to remember.
git clone <this-repo> smithy
cd smithy/aa-playground
# Peer-dep graph for the ZeroDev validator family needs this flag for now.
npm install --legacy-peer-deps
cp .env.example .env.local
# Edit .env.local — set NEXT_PUBLIC_ZERODEV_PROJECT_ID
# (Get one at https://dashboard.zerodev.app — enable Sepolia.)
npm run devOpen http://localhost:3000, type a label, hit create passkey →.
Browsers: Chrome / Edge 118+, Safari 18+, Firefox 129+. Localhost works without https; production needs a real domain.
src/
├── lib/
│ ├── chains.ts chain configs + ZeroDev RPC URL builder
│ ├── crypto/
│ │ ├── prf.ts WebAuthn PRF + HKDF → AES key derivation
│ │ └── encrypted-storage.ts AES-GCM wrapper over localStorage
│ ├── passkey/
│ │ └── passkey-context.tsx react context: passkey identity + unlock
│ └── zerodev/
│ ├── entryPoint.ts getEntryPoint("0.7") helper
│ ├── clients.ts public + paymaster + kernel client factory
│ ├── passkey-validator.ts builds the WebAuthn validator, caches keys
│ ├── account-context.tsx react context: smart account + chain
│ ├── userop-history.ts reads UserOperationEvent logs
│ └── session-keys.ts permission validator + persistence
├── components/
│ ├── ui.tsx button / field / tag / divider primitives
│ ├── tab-nav.tsx sidebar with the 18 features grouped
│ ├── tab-page.tsx shared tab header + state banner
│ ├── chain-switcher.tsx
│ ├── passkey-gate.tsx
│ ├── env-guard.tsx friendly setup screen if env is missing
│ └── tx-history.tsx
└── app/
├── layout.tsx root layout + Providers
├── providers.tsx EnvGuard → Passkey → Account
├── page.tsx onboarding (register / sign in)
└── (app)/ app shell wrapping all 18 tabs
├── layout.tsx
├── dashboard/
├── account/ {ecdsa, passkey, counterfactual}/
├── gas/ {gasless, erc20}/
├── tx/ {batch, session-keys, sign-verify, hooks}/
├── validators/ {multisig, multi-chain}/
├── recovery/ {guardian, chain-abstraction, intents, magic-address}/
└── advanced/ {eip7702, walletconnect, migration}/
- Next.js 16 (App Router, Turbopack, React 19.2)
- viem 2.x — typed Ethereum client
- ZeroDev SDK v5.5 — Kernel v3.1 accounts + hosted bundler / paymaster / passkey server
- WebAuthn / PRF — passkey signing + optional encryption-at-rest
- Tailwind v4 — styling
- Instrument Serif + Inter + JetBrains Mono — type
The 7 ⚫ parked tabs are explicitly v0.2. Reasons logged in BUGS.md. Headline parked items:
- Chain abstraction (CAB) —
@zerodev/cabv0.0.31 still rides on permissionless v0.1. Waiting on a v0.2 release. - ERC-7579 hooks — Hooks now attach to validators at construction. Need a
full
changeSudoValidatorflow that re-installs the sudo validator with the hook attached. - WalletConnect — needs a Reown project ID +
@walletconnect/web3wallet. - EIP-7702 — Sepolia upstream changes still in flight.
Once those clear, they get moved to 🟡 wip and smoke-tested.
| Command | Does |
|---|---|
npm run dev |
Dev server on http://localhost:3000 (Turbopack) |
npm run build |
Production build (used by check) |
npm run typecheck |
tsc --noEmit |
npm run check |
typecheck && build — the gate before commit / share |
npm run lint |
ESLint |
- DEPLOY.md — Vercel walkthrough + passkey domain caveats
- SMOKE_TEST.md — click-through runbook
- BUGS.md — living issue log
- LICENSE — MIT
MIT. Use it, fork it, take it apart.