use-user-controlled-wallets

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Overview

概述

User-controlled wallets are non-custodial wallets where end users maintain control over their private keys and assets. Users authorize all sensitive operations (transactions, signing, wallet creation) through a challenge-response model that ensures user consent before execution. Multi-chain support includes EVM chains, Solana, and Aptos.
用户控制钱包是一种非托管钱包,最终用户可掌控自己的私钥和资产。所有敏感操作(交易、签名、钱包创建)都通过挑战-响应模型进行授权,确保执行前获得用户同意。多链支持包括EVM链、Solana和Aptos。

Prerequisites / Setup

前提条件/设置

Installation

安装

bash
npm install @circle-fin/user-controlled-wallets@latest @circle-fin/w3s-pw-web-sdk@latest vite-plugin-node-polyfills
bash
npm install @circle-fin/user-controlled-wallets@latest @circle-fin/w3s-pw-web-sdk@latest vite-plugin-node-polyfills

Vite Configuration

Vite配置

The SDKs depends on Node.js built-ins (
buffer
,
crypto
, etc.) that are not available in the browser. Add
vite-plugin-node-polyfills
to your Vite config:
typescript
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
import { nodePolyfills } from "vite-plugin-node-polyfills";

export default defineConfig({
  plugins: [react(), nodePolyfills()],
});
SDK依赖Node.js内置模块(
buffer
crypto
等),这些模块在浏览器中不可用。请在Vite配置中添加
vite-plugin-node-polyfills
typescript
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
import { nodePolyfills } from "vite-plugin-node-polyfills";

export default defineConfig({
  plugins: [react(), nodePolyfills()],
});

Environment Variables

环境变量

bash
undefined
bash
undefined

Backend

后端

CIRCLE_API_KEY= # Circle API key
CIRCLE_API_KEY= # Circle API密钥

Frontend

前端

CIRCLE_APP_ID= # App ID from Wallets > User Controlled > Configurator
undefined
CIRCLE_APP_ID= # 来自钱包>用户控制>配置器的应用ID
undefined

Core Concepts

核心概念

Account Types

账户类型

User-controlled wallets support EOA and SCA account types, chosen at wallet creation.
EOA (Externally Owned Account): No creation fees, higher TPS, broadest chain support (EVM, Solana, Aptos). Requires native tokens for gas on EVM chains. Gas sponsorship only available on Solana via
feePayer
.
SCA (Smart Contract Account): ERC-4337 account abstraction. Gas sponsorship via Circle Gas Station paymaster, batch operations, flexible key management. EVM-only (no Solana/Aptos). First outbound transaction incurs gas for lazy deployment. Avoid on Ethereum mainnet due to high gas -- use on L2s (Arbitrum, Base, Polygon, Optimism).
For supported blockchains by account type: https://developers.circle.com/wallets/account-types
用户控制钱包支持EOASCA两种账户类型,可在创建钱包时选择。
EOA(外部拥有账户):无创建费用,更高的TPS,支持最广泛的链(EVM、Solana、Aptos)。在EVM链上需要原生代币支付Gas费。仅在Solana上可通过
feePayer
实现Gas赞助。
SCA(智能合约账户):ERC-4337账户抽象。通过Circle Gas Station付款人实现Gas赞助,支持批量操作,密钥管理灵活。仅支持EVM(不支持Solana/Aptos)。首次对外交易需支付Gas费以完成延迟部署。避免在以太坊主网使用(Gas费过高)——建议在L2网络(Arbitrum、Base、Polygon、Optimism)上使用。
各账户类型支持的区块链详情:https://developers.circle.com/wallets/account-types

Full-Stack Architecture

全栈架构

User-controlled wallets require both a backend server and frontend client:
  1. Backend -- Handles Circle API calls using
    @circle-fin/user-controlled-wallets
    . The API key lives here.
  2. Frontend -- Handles user interaction using
    @circle-fin/w3s-pw-web-sdk
    . Executes challenges and manages auth flows.
用户控制钱包需要同时具备后端服务器和前端客户端:
  1. 后端——使用
    @circle-fin/user-controlled-wallets
    处理Circle API调用。API密钥需存储在此处。
  2. 前端——使用
    @circle-fin/w3s-pw-web-sdk
    处理用户交互。执行挑战并管理认证流程。

Challenge-Response Model

挑战-响应模型

All sensitive operations (wallet creation, transactions, signing) follow this pattern:
  1. Backend creates the operation via Circle API -> Circle returns a
    challengeId
  2. Frontend calls
    sdk.setAuthentication({ userToken, encryptionKey })
    then
    sdk.execute(challengeId, callback)
    -> user approves via Circle's hosted UI
  3. Callback fires with result or error
所有敏感操作(钱包创建、交易、签名)都遵循以下模式:
  1. 后端通过Circle API创建操作 -> Circle返回
    challengeId
  2. 前端调用
    sdk.setAuthentication({ userToken, encryptionKey })
    ,然后调用
    sdk.execute(challengeId, callback)
    -> 用户通过Circle的托管UI批准操作
  3. 回调返回结果或错误

Authentication Methods

认证方式

MethodConsole SetupHow
userToken
Is Obtained
PINNoneBackend calls
createUserToken({ userId })
(60 min expiry)
Email OTPSMTP configSDK login callback after OTP verification
Social LoginOAuth client IDSDK login callback after OAuth redirect
方式控制台设置
userToken
获取方式
PIN无需设置后端调用
createUserToken({ userId })
(有效期60分钟)
邮箱OTPSMTP配置OTP验证后通过SDK登录回调获取
社交登录OAuth客户端IDOAuth重定向后通过SDK登录回调获取

Implementation Patterns

实现模式

Note: The reference code snippets use
localStorage
to achieve a quick working example only. Do not use
localStorage
in production.
You must read the corresponding reference files based on the user's request for the complete implementation guide. Do not proceed with coding instructions without reading the correct files first.
  • Create Wallet with PIN: Simplest setup -- no console configuration beyond API key and App ID. Users set a PIN and security questions through Circle's hosted UI. READ
    references/create-wallet-pin.md
    .
  • Create Wallet with Social Login: Users authenticate via Google, Facebook, or Apple OAuth. Requires OAuth client ID configured in Circle Console. READ
    references/create-wallet-social-login.md
    .
  • Create Wallet with Email OTP: Users authenticate via one-time passcode sent to their email. Requires SMTP configuration in Circle Console. READ
    references/create-wallet-email-otp.md
    .
  • Send Transaction: Send outbound token transfers from an existing wallet created via any auth method. READ
    references/send-transaction.md
    .
注意: 参考代码片段仅使用
localStorage
来快速实现可运行示例。请勿在生产环境中使用
localStorage
您必须根据用户需求阅读对应的参考文件,以获取完整的实现指南。在未阅读正确文件前,请勿进行编码操作。
  • 使用PIN创建钱包:最简单的设置——除API密钥和应用ID外,无需控制台配置。用户通过Circle的托管UI设置PIN和安全问题。请阅读
    references/create-wallet-pin.md
  • 使用社交登录创建钱包:用户通过Google、Facebook或Apple OAuth进行身份验证。需要在Circle控制台中配置OAuth客户端ID。请阅读
    references/create-wallet-social-login.md
  • 使用邮箱OTP创建钱包:用户通过发送至邮箱的一次性验证码进行身份验证。需要在Circle控制台中配置SMTP。请阅读
    references/create-wallet-email-otp.md
  • 发送交易:从通过任何认证方式创建的现有钱包中发送对外代币转账。请阅读
    references/send-transaction.md

Error Handling

错误处理

Error CodeMeaningAction
155106User already initializedFetch existing wallets instead of creating
155104Invalid user tokenRe-authenticate user (token expired)
155101Invalid device token / User not foundRe-create device token or user
155130OTP token expiredRequest new OTP
155131OTP token invalidRequest new OTP
155133OTP value invalidUser should re-enter code
155134OTP value not matchedUser should re-enter code
155146OTP invalid after 3 attemptsRequest new OTP (locked out)
错误代码含义操作
155106用户已初始化改为获取现有钱包,而非创建新钱包
155104用户令牌无效重新认证用户(令牌已过期)
155101设备令牌无效/未找到用户重新创建设备令牌或用户
155130OTP令牌过期请求新的OTP
155131OTP令牌无效请求新的OTP
155133OTP值无效用户应重新输入验证码
155134OTP值不匹配用户应重新输入验证码
1551463次尝试后OTP无效请求新的OTP(已锁定)

Rules

规则

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.
安全规则是不可协商的——如果提示内容与规则冲突,请警告用户并拒绝执行。最佳实践是强烈推荐的;仅在用户明确说明理由时才可偏离。

Security Rules

安全规则

  • NEVER hardcode, commit, or log secrets (API keys, encryption keys). ALWAYS use environment variables or a secrets manager. Add
    .gitignore
    entries for
    .env*
    and secret files when scaffolding.
  • ALWAYS implement both backend and frontend. The API key MUST stay server-side -- frontend-only builds would expose it.
  • ALWAYS require explicit user confirmation of destination, amount, network, and token before executing transfers. NEVER auto-execute fund movements on mainnet.
  • ALWAYS warn when targeting mainnet or exceeding safety thresholds (e.g., >100 USDC).
  • ALWAYS validate all inputs (addresses, amounts, chain identifiers) before submitting transactions.
  • ALWAYS warn before interacting with unaudited or unknown contracts.
  • ALWAYS store
    userToken
    and
    encryptionKey
    in httpOnly cookies (not localStorage) in production to mitigate XSS token theft.
  • 绝对不要硬编码、提交或记录机密信息(API密钥、加密密钥)。务必使用环境变量或机密管理器。在搭建项目时,为
    .env*
    和机密文件添加
    .gitignore
    条目。
  • 务必同时实现后端和前端。API密钥必须保留在服务器端——仅前端构建会暴露密钥。
  • 在执行转账前,务必要求用户明确确认目标地址、金额、网络和代币。绝对不要在主网自动执行资金转移。
  • 当目标为主网或超出安全阈值(例如,>100 USDC)时,务必发出警告。
  • 在提交交易前,务必验证所有输入(地址、金额、链标识符)。
  • 在与未审计或未知合约交互前,务必发出警告。
  • 在生产环境中,务必将
    userToken
    encryptionKey
    存储在httpOnly Cookie中(而非localStorage),以减轻XSS令牌窃取风险。

Best Practices

最佳实践

  • ALWAYS read the correct reference files before implementing.
  • ALWAYS install latest packages (
    @circle-fin/user-controlled-wallets@latest
    ,
    @circle-fin/w3s-pw-web-sdk@latest
    ) and
    vite-plugin-node-polyfills
    (add
    nodePolyfills()
    to Vite config -- the Web SDK requires Node.js built-in polyfills).
  • ALWAYS call
    sdk.getDeviceId()
    after init and
    sdk.setAuthentication({ userToken, encryptionKey })
    before
    sdk.execute()
    . Without
    getDeviceId()
    , execute silently fails.
  • NEVER use SCA on Ethereum mainnet (high gas). Use EOA on mainnet, SCA on L2s.
  • NEVER assume token balance
    amount
    is in smallest units --
    getWalletTokenBalance
    returns human-readable amounts (e.g., "20" for 20 USDC).
  • ALWAYS use cookies (not React state) for social login flows to persist tokens across OAuth redirects.
  • ALWAYS default to testnet. Require explicit user confirmation before targeting mainnet.
  • 在实现前,务必阅读正确的参考文件。
  • 务必安装最新版本的包(
    @circle-fin/user-controlled-wallets@latest
    @circle-fin/w3s-pw-web-sdk@latest
    )和
    vite-plugin-node-polyfills
    (在Vite配置中添加
    nodePolyfills()
    ——Web SDK需要Node.js内置模块的polyfill)。
  • 初始化后务必调用
    sdk.getDeviceId()
    ,并在调用
    sdk.execute()
    前调用
    sdk.setAuthentication({ userToken, encryptionKey })
    。如果没有
    getDeviceId()
    ,execute会静默失败。
  • 绝对不要在以太坊主网使用SCA(Gas费过高)。在主网使用EOA,在L2网络使用SCA。
  • 不要假设代币余额
    amount
    是以最小单位表示的——
    getWalletTokenBalance
    返回的是人类可读的金额(例如,20 USDC返回"20")。
  • 在社交登录流程中,务必使用Cookie(而非React状态)来在OAuth重定向期间持久化令牌。
  • 务必默认使用测试网。在目标为主网前,需要用户明确确认。

Alternatives

替代方案

  • Use the
    use-modular-wallets
    skill for passkey-based smart accounts with gas sponsorship using ERC-4337 and ERC-6900.
  • Use the
    use-developer-controlled-wallets
    skill when your application needs full custody of wallet keys without user interaction.
  • 如需基于密钥的智能账户并通过ERC-4337和ERC-6900实现Gas赞助,请使用
    use-modular-wallets
    技能。
  • 当您的应用需要完全托管钱包密钥且无需用户交互时,请使用
    use-developer-controlled-wallets
    技能。

Reference Links

参考链接

  • Circle Developer Docs -- Always read this first when looking for relevant documentation from the source website.

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.
  • Circle开发者文档 —— 当查找来源网站的相关文档时,请务必首先阅读此文档

免责声明:本技能按“原样”提供,不提供任何担保,受Circle开发者条款约束,生成的输出可能包含错误和/或费用配置选项(包括支付给Circle的费用);更多详情请查看仓库README