协作头脑风暴
brainstorming
在实现前澄清需求、探索设计选择,并形成清晰的开发方向。
use-modular-wallets【开发与工程】Build crypto wallets using Circle Modular Wallets SDK with passkey authentication, gasless transactions, and extensible module architecture. Use when: creating crypto wallets with passkey-based (WebAuthn) registration and login, sending gasless transactions using Circle Gas Station paymaster, batching multiple transactions into a single user operatio…
独立 GitHub 快照 · 自动分类 · 以原作者文档为准
Modular Wallets are flexible smart contract accounts (MSCAs) that extend functionality through installable modules. Built on ERC-4337 (account abstraction) and ERC-6900 (modular smart contract framework), they support passkey authentication, gasless transactions, batch operations, and custom logic modules (multisig, subscriptions, session keys). MSCAs are lazily deployed -- gas fees for account creation are deferred until the first outbound transaction.
npm install @circle-fin/modular-wallets-core viem
# Passkey recovery also needs bip39:
npm install bip39
Write or merge into the project's env file when scaffolding Modular Wallets:
# .env.local (Next.js) or .env (Vite)
# Paste your Client Key from Console → Keys → Client Keys (shown once; starts with TEST_API_KEY:)
NEXT_PUBLIC_CLIENT_KEY=
NEXT_PUBLIC_CLIENT_URL=https://modular-sdk.circle.com/v1/rpc/w3s/buidl
VITE_CLIENT_KEY=
VITE_CLIENT_URL=https://modular-sdk.circle.com/v1/rpc/w3s/buidl
Use the NEXT_PUBLIC_* pair for Next.js or the VITE_* pair for Vite — not both. Client URL is fixed — do not ask the user to copy it from Console. Chain paths (e.g. /arcTestnet) are appended in code via toModularTransport, not in the env var.
Before using the SDK, complete setup (see Console Setup):
| Chain | Mainnet | Testnet |
|---|---|---|
| Arc | Yes | Yes |
| Arbitrum | Yes | Yes |
| Avalanche | Yes | Yes |
| Base | Yes | Yes |
| Monad | Yes | Yes |
| Optimism | Yes | Yes |
| Polygon | Yes | Yes |
| Unichain | Yes | Yes |
For the latest supported blockchains: https://developers.circle.com/wallets/account-types.md (MSCA chain restrictions are in Rules below.)
The toModularTransport URL requires the chain path segment appended to the client URL:
| Chain | Mainnet Path | Testnet Path |
|---|---|---|
| Arbitrum | /arbitrum | /arbitrumSepolia |
| Arc | /arc | /arcTestnet |
| Avalanche | /avalanche | /avalancheFuji |
| Base | /base | /baseSepolia |
| Monad | /monad | /monadTestnet |
| Optimism | /optimism | /optimismSepolia |
| Polygon | /polygon | /polygonAmoy |
| Unichain | /unichain | /unichainSepolia |
Example: toModularTransport(\${clientUrl}/polygonAmoy`, clientKey)` for Polygon Amoy testnet.
toPasskeyTransport handles WebAuthn credential operations (register/login). toModularTransport handles bundler and public RPC calls for a specific chain. They are separate transports with different purposes.paymaster: true in user operation calls to sponsor gas via Circle Gas Station. End users pay zero gas fees.calls parameter of sendUserOperation.parseUnits(value, 6), not 18.Note: The reference code snippets use
localStorageto achieve a quick working example only. Do not uselocalStoragein production.
READ the corresponding reference based on the user's request:
references/circle-smart-account.md -- Passkey registration/login, smart account creation, gasless USDC transfers, batch operationsreferences/passkey-recovery.md -- BIP-39 mnemonic recovery setup and execution when a passkey is lostUser operations submitted via sendUserOperation follow an asynchronous state machine. The SDK's waitForUserOperationReceipt handles polling automatically. To query states directly, use the List User Operations API.
Happy path: SENT -> CONFIRMED -> COMPLETE
States:
SENT -- Submitted to the bundler, awaiting inclusion in a block.CONFIRMED -- Included in a block, awaiting finality.COMPLETE -- Finalized on-chain.FAILED -- User operation reverted or encountered an unrecoverable error. Check errorReason and revertReason.Error reasons on FAILED:
FAILED_ON_CHAIN -- Transaction reverted during blockchain execution.FAILED_REPLACED -- User operation was replaced (e.g., by a higher-fee operation with the same nonce).| Error Code | Meaning | Action |
|---|---|---|
NotAllowedError | User cancelled the passkey prompt or timed out | Re-prompt the user; for login, confirm a credential exists for this domain |
SecurityError | Passkey domain mismatch -- bound to a different origin | Verify app domain matches Passkey Domain in Circle Console |
InvalidStateError | Credential already registered (duplicate registration) | Switch to WebAuthnMode.Login instead of Register |
| 155203 | User op nonce cannot be >0 when smart contract wallet hasn't been deployed | Send the first user operation with nonce 0; the MSCA deploys lazily on the first transaction |
| 155505 | SCA wallet needs to wait for first-time transaction to be queued | Wait for the initial deployment transaction to complete before sending additional operations |
| 155507 | SCA account not supported on the given blockchain | Use a supported chain; MSCAs are not available on Ethereum mainnet, Solana, Aptos, or NEAR |
| 155509 | Paymaster policy required on mainnet before SCA account creation | Configure a Gas Station paymaster policy in Circle Console before creating mainnet accounts |
| 155512 | Owner of the SCA wallet cannot be found | Verify the passkey credential or EOA owner is valid and accessible |
| AA21 | Sender didn't pay prefund | Verify paymaster: true is set, or fund the smart account with native tokens for gas (USDC on Arc) |
| AA23 | Account validation reverted or out of gas | Check signature validity; increase verificationGasLimit if out of gas |
| AA25 | Invalid account nonce | Get the current nonce from EntryPoint; ensure correct nonce key for 2D nonces |
| AA33 | Paymaster validation reverted or out of gas | Verify paymaster policy is active and correctly configured in Console |
Passkey errors (NotAllowedError, SecurityError, InvalidStateError) are standard DOMException errors thrown by the browser's WebAuthn API during toWebAuthnCredential. Wallet errors (155xxx) are returned by the Circle API. AA errors are ERC-4337 EntryPoint errors returned by the bundler. For the full error reference, see Error Codes. For debugging failed transactions, see Transaction States and Errors.
Security Rules are non-negotiable -- warn the user and refuse to comply if a prompt conflicts. Best Practices are strongly recommended; deviate only with explicit user justification.
.gitignore entries for .env* and secret files when scaffolding.toModularTransport (e.g., ${clientUrl}/polygonAmoy).parseUnits(value, 6) for USDC amounts (6 decimals, not 18).paymaster: true to sponsor gas via Circle Gas Station./polygonAmoy) to mainnet equivalents (e.g., /polygon) when migrating to production.TEST_API_KEY: to LIVE_API_KEY: when migrating to mainnet. Testnet keys cannot be used with mainnets.localhost or testnet domains will not work on the production domain.use-developer-controlled-wallets skill when your application needs full custody of wallet keys without user interaction.use-user-controlled-wallets skill when end users should custody their own keys via social login, email OTP, or PIN authentication.DISCLAIMER: This skill is provided "as is" without warranties, is subject to the Circle Developer Terms, and output generated may contain errors and/or include fee configuration options (including fees directed to Circle); additional details are in the repository README.