Wallet Modes
WizPay supports two signing models. The mode determines who holds the signing key and where transaction construction happens.Mode Selection
The wallet mode is read fromtask.payload.walletMode by ExecutionRouterService:
walletMode is absent (all tasks created before the field was introduced), the system defaults to W3S. Zero breaking changes.
W3S (Custodial)
Circle Wallet-as-a-Service. The backend has signing authority. Signing model:- Backend holds a Circle API key and entity secret.
- The entity secret allows the backend to sign transactions on behalf of developer-controlled wallets.
- The user does not approve individual transactions.
- User authenticates (Google/Email) → receives Circle
userToken+encryptionKey. - Frontend sends
userTokento backend with each wallet operation. - Agent calls
CircleService.transfer()→ Circle signs and submits on-chain.
- Backend signs. No client-side signing.
userTokenrequired for wallet identification.walletIdrequired per operation.- Supports EVM (ARC-TESTNET, ETH-SEPOLIA) and Solana (SOLANA-DEVNET).
useMobileRecoverylistens tovisibilitychange,focus,pageshow, andonlineevents. On each trigger (throttled to prevent flooding) it callsrearmSdkForSessionto re-attach the current auth token to the SDK instance.ensureSessionReady()is called before every Circle-mode operation (transaction execution, bridge, typed data signing). If the session is stale, it re-arms the SDK and refreshes the wallet list before the operation proceeds.- If a Circle operation returns a recoverable session error (code
155706or an invalid-device code),withRecoveredSessioncallsensureSessionReadyand retries the operation exactly once. The retry is transparent to the caller.
PASSKEY (Client-Controlled)
Circle modular Account Abstraction wallet. The user holds the signing key. Signing model:- User authenticates with a WebAuthn passkey (biometric or hardware key).
- The backend has no signing authority over the user’s wallet.
- For operations requiring the user’s signature, the backend returns unsigned intents.
Characteristics:
- No Circle
userToken,tokenId, or W3S session credentials. - No
walletIdrequired. - Passkey AA wallets are EVM-only (ARC-TESTNET, ETH-SEPOLIA).
- Solana operations require client-side signing.
Comparison
External Signer Bridge
External browser wallets are not a thirdwalletMode. They are a bridge execution mode used when the source wallet is a connected EVM wallet or an injected Solana wallet.
- The browser executes the burn, attestation, and mint flow with public Circle bridge tooling.
- The backend still accepts a best-effort
POST /tasksaudit record for traceability. - These audit tasks require
walletAddressbut do not requirewalletId. - Solana support is provider-agnostic: any compatible injected Solana wallet can be used, not just Phantom.
NEXT_PUBLIC_CIRCLE_API_PROXY_ENABLED=trueenables the same-origin/api/circle/proxyfallback when the deployed Next.js runtime serves that route. When the flag is unset, bridge clients use direct Circle API requests only.- Production reverse proxies must route
/api/circle/proxyto the frontend Next.js app before any generic backend/api/rule; otherwise externalETH-SEPOLIA -> ARC-TESTNETtransfers can silently fall back to slow full-finality burns.
Isolation
TheExecutionRouterService is the only component aware of wallet modes.
- Agents do not check
walletMode. They receive tasks through the router and execute. - The orchestrator does not check
walletMode. It calls the execution router. - Workers do not check
walletMode. They call the orchestrator.
- Extend the
WalletModetype union intask.types.ts. - Add a case in
ExecutionRouterService.resolveWalletMode(). - Implement the engine service.