Wagmi React 实战:从零构建 Connect Wallet 钱包连接模块
Wagmi React 实战从零构建 Connect Wallet 钱包连接模块【免费下载链接】wagmiReactive primitives for Ethereum apps项目地址: https://gitcode.com/GitHub_Trending/wa/wagmi对于任何 DApp 而言让用户连接钱包是最基础也是最核心的能力——它使用户能够写入合约、签名消息、发送交易。本文基于 Wagmi 官方指南 connect-wallet.md 展开完整覆盖“使用第三方库”与“自己构建”两条路线先配置createConfig与连接器再用WagmiProvider注入响应式状态最后通过useConnect/useConnectors/useConnection/useDisconnect等 Hooks 拼装出完整的连接 UI。读完本文你能独立搭建一个支持浏览器钱包、WalletConnect、MetaMask 与 Safe 的钱包连接模块并理解每个 Hook 背后在wagmi/core中的真实调用链。方案选择第三方库 还是 自建模块官方指南给出的第一条路线是使用基于 Wagmi 构建的第三方 Connect Wallet 库例如ConnectKit、Dynamic、Privy等。这类库封装了钱包连接的所有边缘情况账号切换、链切换、连接恢复等并提供开箱即用的连接 UX适合希望快速上线的团队。如果你希望完全掌控 UI 与交互或需要更轻量的依赖则选择第二条路线使用 Wagmi 提供的 Hooks 自建模块。官方指南的结论是——接入浏览器钱包、WalletConnect 与 Coinbase Wallet 所需时间不足五分钟。下文按指南的五个步骤完整展开。步骤 1配置 WagmicreateConfig首先创建config.ts导出一个config对象import { http, createConfig } from wagmi import { base, mainnet, optimism } from wagmi/chains import { injected, metaMask, safe, walletConnect } from wagmi/connectors const projectId WALLETCONNECT_PROJECT_ID export const config createConfig({ chains: [mainnet, base], connectors: [ injected(), walletConnect({ projectId }), metaMask(), safe(), ], transports: { [mainnet.id]: http(), [base.id]: http(), }, })配置要点说明chains声明应用支持的链。示例使用 Mainnet 与 Base可按需替换为任意链。connectors声明钱包连接器。上例覆盖四类典型场景——injected()浏览器注入钱包如已安装插件注入的window.ethereum、walletConnect({ projectId })浏览器 移动端钱包、metaMask()MetaMask 专属连接器、safe()Safe 多签钱包。transports为每条链指定 RPC 传输方式此处统一使用http()。⚠️ WalletConnect 的projectId必须替换为你自己的 WalletConnect Project ID否则 WalletConnect 连接器无法工作。仓库中的 Vite React Playground 展示了更贴近生产的完整配置可以对照 playgrounds/vite-react/src/wagmi.ts它额外演示了三个进阶点// 通过环境变量注入 WalletConnect Project ID walletConnect({ projectId: import.meta.env.VITE_WC_PROJECT_ID, }), // 使用 idb-keyval 将 IndexedDB 作为持久化存储 storage: createStorage({ storage: indexedDBStorage, key: vite-react }), // 通过模块增强Module Augmentation获得全局类型推导 declare module wagmi { interface Register { config: typeof config } }其中declare module wagmi的Register增强值得注意一旦声明所有 Hook 与 Action 都会自动以你的config为类型上下文链 ID、连接器类型全部收窄不再需要显式传参。步骤 2用 Context Provider 包裹应用接下来把 React 应用包裹在 Wagmi 与 React Query 的 Provider 中使应用感知 Wagmi 的响应式状态与内存缓存// 1. Import modules import { QueryClient, QueryClientProvider } from tanstack/react-query import { WagmiProvider } from wagmi import { config } from ./config // 2. Set up a React Query client. const queryClient new QueryClient() function App() { // 3. Wrap app with Wagmi and React Query context. return ( WagmiProvider config{config} QueryClientProvider client{queryClient} {/* ... */} /QueryClientProvider /WagmiProvider ) }从源码看WagmiProviderpackages/react/src/context.ts做了两件事把config放入WagmiContext供所有 Hook 通过useConfig读取外层套了一个Hydrate组件配合initialState属性实现 SSR 状态水合。其 Props 为{ config, initialState?, reconnectOnMount? }reconnectOnMount控制应用重新挂载时是否自动重连钱包——这在 Next.js 等 SSR 场景下尤为重要。步骤 3展示钱包选项useConnectors useConnect创建WalletOptions组件展示所有连接器让用户选择钱包并连接。组件渲染的列表来自useConnectors点击时调用useConnect返回的connectimport { Connector, useConnect, useConnectors } from wagmi export function WalletOptions() { const { connect } useConnect() const connectors useConnectors() return connectors.map((connector) ( button key{connector.uid} onClick{() connect({ connector })} {connector.name} /button )) }这两个 Hook 的实现方式各有侧重均在 packages/react/src/hooksuseConnectorsuseConnectors.ts基于 React 18 的useSyncExternalStore订阅 core 的watchConnectors/getConnectors。它是纯查询型Hook连接器列表发生变化如钱包可用性检测完成时自动重渲染不涉及 mutation 状态。useConnectuseConnect.ts则是一个完整的mutation内部通过connectMutationOptions构造 TanStack Query 的useMutation。它除了返回标准的mutate/mutateAsync/isPending/error等字段外还有一个值得一提的细节——它会订阅 config 的 status 变化当连接从connected变为disconnected时自动调用mutation.reset()把 mutation 重置回 idle 状态避免断开重连后 UI 卡在失败态。两个 API 说明connect({ connector })的参数类型是类型安全的。core 层的ConnectParameterspackages/core/src/actions/connect.ts会从具体连接器推断出该连接器connect方法的专属参数——例如walletConnect()支持的showQrModal等选项都能被 IDE 自动补全版本提示从源码的类型定义看当前版本的useConnect返回值中connect/connectAsync字段已被标记deprecated官方建议迁移到语义更统一的mutate/mutateAsync。指南示例沿用了connect写法以保持兼容新代码可直接使用mutate。connect 底层做了什么useConnect最终落到 core 的connectActionpackages/core/src/actions/connect.ts#L95-L160。它的状态机流程是若传入的是连接器工厂函数如metaMask先通过config._internal.connectors.setup惰性实例化若该连接器已处于当前连接状态直接抛出ConnectorAlreadyConnectedError将全局状态置为status: connecting并 emitmessage: connectingawait connector.connect(...)真正发起钱包握手浏览器弹窗、QR 码等由连接器实现负责成功后挂载事件监听change/disconnect把{ accounts, chainId, connector }写入connectionsMap更新current与status: connected并把连接器 ID 持久化为recentConnectorId供下次自动重连若中途失败状态会回退已有连接则保持connected否则回到disconnected并把错误抛给 mutation 的error字段。ConnectErrorType同样值得了解connect.ts#L85-L92包含ConnectorAlreadyConnectedError、用户拒绝请求UserRejectedRequestError与 RPC 资源不可用ResourceUnavailableRpcError等便于在 mutation 的onError中做针对性提示。步骤 4展示连接信息useConnection / useEnsName / useEnsAvatar / useDisconnect连接成功后展示地址、ENS 名称与头像并提供断开按钮import { useConnection, useDisconnect, useEnsAvatar, useEnsName } from wagmi export function Connection() { const { address } useConnection() const { disconnect } useDisconnect() const { data: ensName } useEnsName({ address }) const { data: ensAvatar } useEnsAvatar({ name: ensName! }) return ( div {ensAvatar img altENS Avatar src{ensAvatar} /} {address div{ensName ? ${ensName} (${address}) : address}/div} button onClick{() disconnect()}Disconnect/button /div ) }各 Hook 的职责useConnection返回当前连接address/chainId/connector等。它的实现useConnection.ts基于useSyncExternalStoreWithTracked订阅watchConnection即对 config 中current连接做精准追踪——只有当前连接相关字段变化才触发渲染且getServerSnapshot与客户端快照一致SSR 安全useEnsName/useEnsAvatarTanStack Query 驱动的查询型 Hook按address/name作为查询参数缓存 ENS 解析结果地址未变化时不会重复请求useDisconnect同样是 mutation。值得注意的是它返回的connectors字段来自useConnections——当前版本已支持多连接config.state.connections是一个Map因此断开某个连接器后core 的disconnectActionpackages/core/src/actions/disconnect.ts#L21-L71会删除对应连接 → 若无剩余连接则回到disconnected否则自动把current切换到下一个连接而不会让整个应用失连。指南中还展示了一个进阶 UI 模式——在点击前预取 provider未就绪时禁用按钮connect-wallet.md 步骤 4 的wallet-options.tsxfunction WalletOption({ connector, onClick }: { connector: Connector; onClick: () void }) { const [ready, setReady] React.useState(false) React.useEffect(() { ;(async () { const provider await connector.getProvider() setReady(!!provider) })() }, [connector]) return ( button disabled{!ready} onClick{onClick} {connector.name} /button ) }connector.getProvider()会触发连接器的 provider 加载与可用性检测对于未安装的浏览器钱包provider 为undefined此时禁用按钮可以引导用户先安装插件体验更好。步骤 5接线到应用入口最后把两个组件按连接状态二选一渲染import { QueryClient, QueryClientProvider } from tanstack/react-query import { WagmiProvider, useConnection } from wagmi import { config } from ./config import { Connection } from ./connection import { WalletOptions } from ./wallet-options const queryClient new QueryClient() function ConnectWallet() { const { isConnected } useConnection() if (isConnected) return Connection / return WalletOptions / } function App() { return ( WagmiProvider config{config} QueryClientProvider client{queryClient} ConnectWallet / /QueryClientProvider /WagmiProvider ) }至此指南的五步全部完成。仓库内还有更丰富的组合示范可参考playgrounds/vite-react/src/App.tsx在Connection之外还演示了useConnectionEffect监听连接/断开事件的副作用 Hook、useConnections多连接列表、useSwitchConnection多连接间切换等playgrounds/next 与 playgrounds/nuxt同一套 Connect Wallet 模式在 Next.js / Nuxt SSR 环境下的完整落地含状态序列化与重连配置site/react/api/hooks所有 Hooks 的 API 参考文档目录。小结与延伸阅读关注点对应 API / 文件全局配置与连接器声明createConfigplaygrounds/vite-react/src/wagmi.tsProvider 与 SSR 水合WagmiProviderinitialState/reconnectOnMountpackages/react/src/context.ts展示钱包列表useConnectorspackages/react/src/hooks/useConnectors.ts发起连接mutationuseConnectpackages/react/src/hooks/useConnect.tscore Action 见 packages/core/src/actions/connect.ts当前连接状态useConnectionpackages/react/src/hooks/useConnection.ts断开 / 多连接切换useDisconnectcore Action 见 packages/core/src/actions/disconnect.ts几个容易踩坑的点最后再强调一次WalletConnect 必须配置真实的projectIduseConnect的错误处理应覆盖“用户拒绝”这一高频分支连接状态变化会自动重置 connect mutation因此 UI 层无需手动处理 stale 状态若需要生产级持久化可参照 Playground 用createStorage接入 IndexedDB。掌握这套“配置 → Provider → 列表 → 状态展示 → 接线”的模式后无论是自建模块还是评估第三方库的底层行为都有了清晰的源码坐标。【免费下载链接】wagmiReactive primitives for Ethereum apps项目地址: https://gitcode.com/GitHub_Trending/wa/wagmi创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
上一篇/下一篇内容由系统自动关联
返回资讯列表 →