- 区块链
- 前端
- 认证鉴权
【免费下载链接】web3modal
The full stack toolkit to build onchain app UX
导读
本篇文章以 packages/cli/CHANGELOG.md 为主线,系统梳理 Reown AppKit CLI(@reown/appkit-cli)从 1.6.0 到 1.8.24 的版本演进脉络。你将从中掌握:CLI 脚手架的完整用法与底层实现(基于tiged的模板克隆)、Headless 无头模式的程序化连接 API、多链适配(EVM / Solana / Bitcoin / Stellar / TRON)、SIWE/SIWX 配置项,以及customRpcUrls、connectorTypeOrder、enableReconnect等高频初始化参数的源码级行为。读完即可在自己的 dApp 中按版本能力清单进行升级评估与参数调优。
一、CLI 工具本身:安装、运行与实现原理
1.1 包结构与命令入口
CLI 包位于 packages/cli,核心文件为:
- package.json:包名
@reown/appkit-cli,通过bin.appkit-cli注册命令行入口,依赖仅三个——figlet(ASCII 横幅)、inquirer(交互式提问)、tiged(GitHub 模板仓库拉取器)。 - index.js:程序入口,先打印
banner横幅,然后依次询问框架、项目名、连接库,最后克隆模板。 - utils.js:
checkDirectoryExists/generateRepoUrl/cloneRepository/runReactNativeCLI等核心逻辑。
1.2 安装与运行
按 packages/cli/README.md 的说明,本地开发可通过npm link全局注册命令:
npm install sudo npm link之后即可全局使用:
appkit-cli [project-name]也可以不安装直接运行:
npx appkit-cli交互流程(源自 index.js):
- 先选择框架:
Next.js/React/Vue/Javascript/React Native; - 若未在命令行传入项目名,则提示输入项目名,并校验目录是否已存在(存在则要求换名);
- 再选择连接库:
Wagmi/Ethers/Solana/Bitcoin/Multichain; - 拉取对应模板,输出后续三条命令:
cd <name>、npm install、npm run dev; - 提示前往 Reown Dashboard 创建个人
ProjectId(仅 localhost 环境可用)。
1.3 模板映射与克隆实现
utils.js 中的generateRepoUrl是模板映射的核心,例如:
Next.js+Wagmi→reown-com/appkit-web-examples/nextjs/next-wagmi-app-routerReact+Ethers→reown-com/appkit-web-examples/react/react-ethersVue+Solana→reown-com/appkit-web-examples/vue/vue-solanaJavascript+Bitcoin→reown-com/appkit-web-examples/javascript/javascript-bitcoin
克隆过程使用tiged(repoUrl, { disableCache: true, force: true })直接拉取示例模板;若选择 React Native,则委托给npx @reown/appkit-react-native-cli --no-banner(可通过appkit-cli my-rn-app传入项目名)。
这些模板仓库在 web3modal 仓库中也有对应实现,例如 examples/next-wagmi-app-router、examples/react-ethers、examples/vue-solana,可直接在仓库内查看模板的完整代码。
二、Headless 无头模式:程序化钱包连接的完整 API(1.8.19 ~ 1.8.24)
这是本版本区间最重要的能力升级方向:让非 React 宿主(例如@walletconnect/pay-appkit)无需引入任何 React Hook,也能完成钱包列表获取、搜索、分页、WalletConnect URI 读取与程序化连接。
2.1 实例级方法全家桶(1.8.19 引入)
根据 CHANGELOG 1.8.19 的记录,AppKit实例新增:
fetchWallets(options?):获取/搜索/分页钱包列表;getWalletList():读取当前钱包列表快照;subscribeWalletList(cb):订阅列表变化;getWalletConnectUri(options?):读取 WalletConnect URI;connectWallet(wallet, namespace?, options?):程序化连接(注入式 / API / 移动端 deeplink)。
这些方法在 appkit-base-client.ts 中逐一实现,并全部委托给 controllers 包中新增的HeadlessWalletUtil(HeadlessWalletUtil.ts)。从源码注释看,此前这套逻辑只存在于useAppKitWalletsReact Hook 内部,将其上提后,Hook 与客户端方法共享同一条经过测试的代码路径,避免了引入@reown/appkit-controllers可能解析到不同 valtio 单例的问题。
2.2 1.8.20:钱包列表选项扩展
fetchWallets()新增两个选项:
includePayOnly:默认过滤掉仅支持 WalletConnect Pay、但不兼容 v2 的钱包,开启后将其纳入列表;sort: 'wcpay':将支持 WalletConnect Pay 的钱包置顶。
对应类型定义见 HeadlessWalletUtil.ts 中的FetchWalletsOptions(page/search/entries/badge/include/exclude等字段均有 JSDoc 注释)。
2.3 1.8.22:URI 读取 API 与 Breaking Change
- 新增
getWalletConnectUri()与subscribeWalletConnectUri(),直接读取连接层状态,无需引入 React Hook; - 破坏性变更:原有的命令式预取方法
getWalletConnectUri()更名为prefetchWalletConnectUri(),把getWalletConnectUri让位给新的读取方法; - 同时新增
resetWalletConnectUri()与resetConnectingWallet()两个重置方法(1.8.22),分别透传HeadlessWalletUtil.resetWcUri()与resetConnectingWallet(),用于 QR 关闭或连接取消时清理状态。
2.4 1.8.24:pairing 过期时间透传与连接失败修复
1.8.24 重点修复了 Headless 宿主的两处痛点:
wcError不再“卡死”:此前wcError只有成功移动端 deeplink 或 headful 模式“try again”按钮才会被清除,导致一次失败后所有后续尝试都显示失败。现在每次新的connectWalletConnect尝试都会从干净的错误状态开始;- deeplink 前校验配对 URI:
ConnectionControllerUtil.onConnectMobile在没有 pairing URI 时是空操作,断开会清除它。现在connectWallet/useAppKitWallets的connect在缺少 URI 时通过ConnectionControllerUtil.assertWcUriForDeeplink直接 reject,宿主可先预取 URI 再重试,而不是干等一个永远不会触发的重定向。
同时在快照中透出wcPairingExpiry:getWalletConnectUri()现在返回{ wcUri, wcError, wcFetchingUri, wcPairingExpiry }。源码层面,ConnectionController.setUri每次都会把过期时间戳设为四分钟后(见 ConnectionController.ts 中state.wcPairingExpiry = CoreHelperUtil.getPairingExpiry()),scaffold-ui早已用它判断是否重连,这次只是补上了 Headless 侧的读取通道。这对“先取 URI、稍后再 deeplink”的宿主至关重要——配对有效期只有约 4 分钟,快照里再无其他字段能区分新鲜 URI 与失效 URI。
// 无头宿主典型用法(方法签名源自 HeadlessWalletUtil.ts) await appKit.prefetchWalletConnectUri() const { wcUri, wcError, wcFetchingUri, wcPairingExpiry } = appKit.getWalletConnectUri() const unsubscribe = appKit.subscribeWalletConnectUri(() => { const snapshot = appKit.getWalletConnectUri() // 渲染 QR 或发起 deeplink }) // 连接某个钱包(注入式 / API / 移动端 deeplink) await appKit.connectWallet(walletItem, 'eip155') // 关闭 QR 后清理 appKit.resetWalletConnectUri()从 HeadlessWalletUtil.ts 的connect实现可以看出连接分派逻辑:
- 钱包为注入式且存在对应 connector →
ConnectorControllerUtil.connectExternal; - 找不到 connector 但存在 fallback(按钱包 id / explorerId 匹配,如 Base Account 打开 Coinbase web 钱包)→
connectExternal; - 移动端:存在
mobile_link时先assertWcUriForDeeplink再onConnectMobile,否则走MobileWalletUtil.handleMobileDeeplinkRedirect; - 桌面端兜底:
connectWalletConnect({ cache: 'never' })。
三、多链能力扩展:Stellar 与 TRON 适配器(1.8.24 / 1.8.22)
3.1 Stellar 适配器正式加入(1.8.24)
1.8.24 通过新的@reown/appkit-adapter-stellar包加入 Stellar 支持:
- 网络:
stellar:pubnet与stellar:testnet; - RPC 方法:
stellar_signXDR、stellar_signAndSubmitXDR、stellar_signMessage、stellar_signAuthEntry; - 附带一个针对SEP-53签名的 SIWX verifier;
- 连接方式:仅支持 WalletConnect,无扩展钱包支持。
仓库中的实现位于 packages/adapters/stellar,核心类为 adapter.ts(StellarAdapter,namespace 为ConstantsUtil.CHAIN.STELLAR)与 StellarWalletConnectConnector.ts。从 adapter.ts 的signMessage实现看,签名经由 WalletConnect connector 的signMessage完成,而 XDR 类操作(signXDR/signAndSubmitXDR)走 connector 的另一条路径。
3.2 TRON 适配器修复与 v1 载荷格式(1.8.24 / 1.8.22)
1.8.24 修复了 TRON 连接在页面刷新时被静默清除的问题:当 TronLink 等钱包适配器在 boot 同步时仍处于readyState解析中,已存储的 TRON 连接会被抹掉。修复后TronAdapter.syncConnectors(见 packages/adapters/tron/src/adapter.ts)会等待 pending 的钱包适配器稳定后再做 boot 连接同步,但仅当该适配器确有已存储的 TRON 连接可恢复,避免给每次页面加载增加不必要的延迟,useAppKitAccount因此能正确 rehydrate。
1.8.22 修复了tron_signTransaction的载荷结构:connector 现在尊重钱包的tron_method_version会话属性——默认发送规范要求的旧版嵌套transaction.transaction结构,只有钱包在sessionProperties中声明tron_method_version: "v1"时才发送简化扁平结构。实现见 TronWalletConnectConnector.ts(判断逻辑为this.provider.session?.sessionProperties?.['tron_method_version'] === 'v1'),并有对应单测 TronWalletConnectConnector.test.ts 覆盖两种形状。
四、连接体验与钱包渲染修复(1.8.x 高频修复点)
4.1 Sign 模态框按钮溢出(1.8.24)
修复 Sign 模态框 Cancel/Sign 按钮在同时显示加载文案时渲染到模态框边界之外的问题——wui-button现在可作为 flex 子项收缩,超出时用省略号截断标签而非溢出自身边界。
4.2 默认钱包图标与下载 CTA(1.8.24)
- Sign In 消息请求中的默认钱包图标放大;
- “Don't have X?” 下载 CTA 不再强制把钱包名截断为 12 字符,而是显示完整钱包名。
4.3 SIWX 多链钱包签名竞态(1.8.24)
修复 Trust Wallet、SafePal 等多链钱包在消息创建与签名之间切换了活动 namespace时 SIWX 签名失败的问题(fix(siwx): resolve multichain wallet signing race condition)。
4.4 Coinbase 4100 错误自动恢复(1.8.23)
AppKit 自动恢复(auto-restore)会话后,Coinbase Wallet SDK provider 仍保留账户但内部授权丢失,直接调用.request()会得到 EIP-11934100("Must call 'eth_requestAccounts' before other methods")。1.8.23 在 provider 注册缝(syncProvider)中包装 Coinbase eip155 provider(以 connectorid为键——该 id 在 wagmi、ethers、ethers5 适配器间稳定),触发一次一次性恢复:
- 单次
eth_requestAccounts重新授权; - 在
eth_sendTransaction重试前重新断言活动链(避免握手重置 SDK 链后在错误网络上广播交易); - 只重试一次。
非4100错误、用户拒绝重新授权、非 Coinbase provider 均不受影响,且包装器按 provider 实例缓存以保证引用稳定。
4.5 coinbasePreference 选项回归修复(1.8.23)
修复coinbasePreference被忽略的问题:'all'与'eoaOnly'现在正确使用coinbaseWalletconnector(含 QR 码支持)而非始终使用baseAccount;'smartWalletOnly'使用baseAccount。(该回归由 PR #5269 引入。)
4.6 连接事件与最近钱包(1.8.6 ~ 1.8.5)
CONNECT_SUCCESS事件新增walletRank属性,并新增@appkit/recent_walletlocalStorage 键跟踪最近连接的钱包;- 用户拒绝连接时不再记录
CONNECT_ERROR,改为新的USER_REJECTED事件;拒绝交易时不再记录SEND_ERROR,改为SEND_REJECTED。
五、初始化配置项:从customRpcUrls到enableReconnect(1.7.x)
以下配置项虽来自 1.7.x,但仍是当前版本(1.8.x)初始化参数体系的基础,且都能在 OptionsController.ts 中找到对应状态字段。
5.1customRpcUrls:覆盖默认 RPC(1.7.1)
以 CAIP 网络 ID 为键、URL 数组为值覆盖网络默认 RPC:
const customRpcUrls = { 'eip155:1': [{ url: 'https://your-custom-mainnet-url.com' }], 'eip155:137': [{ url: 'https://your-custom-polygon-url.com' }] } const modal = createAppKit({ adapters: [...], networks: [...], projectId: 'project-id', customRpcUrls })若同时使用 Wagmi 适配器,需将同样的customRpcUrls传给new WagmiAdapter({ ... })。还可以为传输层传入 fetch 配置:
const customRpcUrls = { 'eip155:1': [ { url: 'https://your-custom-mainnet-url.com', config: { fetchOptions: { headers: { 'Content-Type': 'text/plain' } } } } ] }5.2enableReconnect:关闭自动重连(1.7.11)
createAppKit({ networks: [...], metadata: {...}, enableReconnect: false // 关闭初始化与页面加载时的自动重连 })1.7.15 还修复了enableReconnect: false时初始化不同步的问题。
5.3connectorTypeOrder:自定义连接器展示顺序(1.7.13)
const modal = createAppKit({ adapters: [], networks: [], projectId: 'YOUR_PROJECT_ID', features: { connectorTypeOrder: ['injected', 'walletConnect', 'recent'] } })数组顺序即展示顺序:上例中注入式钱包在前,随后是 WalletConnect,最后是最近钱包。底层实现在 ConnectorUtil.ts 的getConnectorTypeOrder:它会先按walletConnect/recent/injected(含 announced、multiChain)/featured/custom/external/recommended计算“已启用”类型集合,再把overriddenConnectors(即features.connectorTypeOrder)中启用的类型优先排列,其余类型按默认顺序补在后面。
5.4 其余常用开关
| 配置项 | 说明 | 引入版本 |
|---|---|---|
enableWalletGuide: false | 关闭社交/邮箱登录启用时的钱包引导页脚 | 1.6.0 |
enableAuthLogger: false | 关闭邮箱/社交登录日志(默认 true) | 1.6.3 |
enableNetworkSwitcher: false | 关闭模态框中的网络切换 | 1.7.2 |
enableEIP6963 | 控制 wagmi 适配器 EIP-6963 行为(曾修复其失效问题) | 1.7.11 |
registerWalletStandard | 自动将 WalletConnect relay connector 注册为 Wallet Standard 钱包 | 1.7.11 |
signOutOnDisconnect(SIWXConfig) | 断开连接时是否登出 | 1.7.12 |
六、SIWE / SIWX 与账户 API 演进
6.1 SIWErequired选项(1.6.4)
export const siweConfig = createSIWEConfig({ required: false, // 可选,默认 true getMessageParams: async () => { /* ... */ }, createMessage: ({ address, ...args }) => { /* ... */ }, getNonce: async () => { /* ... */ }, getSession: async () => { /* ... */ }, verifyMessage: async ({ message, signature }) => { /* ... */ }, signOut: async () => { /* ... */ } })required: true(默认)时,用户拒绝签名请求会断开钱包并关闭模态框;false时仅关闭模态框、不断开钱包。
6.2 账户状态 API
useAppKitAccount({ chainNamespace })支持按链获取账户状态(eip155/solana/bip122,1.6.9);useAppKitAccount返回embeddedWalletInfo(含user?.email等,1.6.4);appKit.getAccount公开方法(1.7.0);appKit.disconnect()不传参时断开所有 namespace,可传{ namespace: 'solana' }只断开指定链(1.7.1);- 新增
getDisabledCaipNetworks读取被禁用的 CAIP 网络(1.8.9)。
6.3 事件监听与取消订阅(1.8.17)
为 AppKit 事件监听器补充unsubscribe函数,避免重复监听造成回调堆积。
七、wallet-button 组件:多链 namespace 支持(1.7.17)
wallet-button 升级为多链支持,通过namespace属性区分链:
React 组件:
const wallets = [ { wallet: 'metamask', namespace: 'eip155', label: 'MetaMask EVM' }, { wallet: 'metamask', namespace: 'solana', label: 'MetaMask Solana' }, { wallet: 'phantom', namespace: 'bip122', label: 'Phantom Bitcoin' } ] wallets.map(({ wallet, namespace }) => ( <AppKitWalletButton key={`${wallet}-${namespace}`} wallet={wallet} namespace={namespace} /> ))React Hook:
const { data, error, isPending, isSuccess, isError, connect } = useAppKitWallet({ namespace: 'eip155', // 'solana' 或 'bip122' 用于其他链 onError: err => {}, onSuccess: data => {} }) <button onClick={() => connect('walletConnect')}>Open QR modal</button> <button onClick={() => connect('metamask')}>Connect to MetaMask</button>Vanilla JS:
<script type="module"> import '@reown/appkit-wallet-button' import { createAppKitWalletButton } from '@reown/appkit-wallet-button' const wallet = createAppKitWalletButton({ namespace: 'eip155' }) wallet.subscribeIsReady(({ isReady }) => { if (!isReady) return document.querySelectorAll('button[data-wallet]').forEach(button => { button.disabled = false button.onclick = () => wallet.connect(button.getAttribute('data-wallet')) }) }) </script> <appkit-wallet-button wallet="metamask" namespace="eip155"></appkit-wallet-button> <button>赞- 区块链
- 前端
- 认证鉴权
【免费下载链接】web3modal
The full stack toolkit to build onchain app UX
相关推荐
AReaL 中的 PPO/GRPO 算法家族:从 GRPO 到 DAPO、SAPO、GSPO 的配置切换与源码原理
AReaL 中的 PPO/GRPO 算法家族:从 GRPO 到 DAPO、SAPO、GSPO 的配置切换与源码原理 本文以 docs/en/algorithms
区块链前端认证鉴权Web3Modal AppKit 钱包按钮(@reown/appkit-wallet-button)完全指南:从 Web Component 到 React Hook 的多链连接实战
Web3Modal AppKit 钱包按钮(@reown/appkit wallet button)完全指南:从 Web Component 到 React H
区块链前端认证鉴权