Wagmi Connector 开发全指南从零创建并上架一个钱包连接器【免费下载链接】wagmiReactive primitives for Ethereum apps项目地址: https://gitcode.com/GitHub_Trending/wa/wagmi本篇指南以 Wagmi 仓库中的 creating-connectors.md 为核心脉络系统讲解在 Wagmi 中新建、测试并向上游贡献一个 Connector 的完整流程。你将掌握createConnector工厂函数的完整契约属性、方法、事件与配置参数、连接器的文件组织与导出规范、测试与文档要求以及从 changeset 到 Pull Request 的提交路径可直接套用于packages/connectors的实际开发。写在动手之前先沟通再编码Wagmi 是一个依赖赞助与赠款维持运转的开源项目维护第三方 Connector 需要持续投入时间与精力。因此文档在开篇就明确两点前置要求团队需要赞助 Wagmiwevm 赞助页这是 Connector 请求被接受的前提之一如有疑问可邮件联系devwevm.dev。动手写代码之前先创建 Connector Request 讨论在 GitHub Discussions 的connector-request分类下发起说明它解决的是对 Wagmi 用户重要或通用的使用场景并确认能得到 Wagmi 团队与 Connector 维护团队的支持避免投入大量精力后 Pull Request 被拒绝。同时文档明确警告并非所有 Connector 都会被 Wagmi 接受。判断标准包括用例的重要性、通用性、维护团队的响应能力等具体理由贯穿本文后续的每一步要求中。第 1 步准备本地开发环境先按照仓库的 贡献指南 搭建开发环境核心步骤包括使用git clone克隆仓库或使用gh repo clone wevm/wagmi确保安装node对应版本仓库package.json的devEngines字段声明了运行时版本并通过corepack enable启用 pnpm在仓库根目录执行pnpm install安装依赖pnpm 会自动链接各 workspace 包并配置 git hooks复制并填写.env环境变量其中包含链分叉 RPC 地址VITE_MAINNET_FORK_URL、VITE_OPTIMISM_FORK_URL与 WalletConnect 项目 ID*_WC_PROJECT_ID等供开发 playground 与测试套件使用。开发环境就绪后运行pnpm dev:next、pnpm dev:react、pnpm dev:vue、pnpm dev:nuxt等命令即可启动./playgrounds下的对应 playground 应用修改任意包源码如packages/connectors会自动热更新到 playground方便在真实 dApp 环境中验证 Connector。第 2 步创建 Connector 源文件在packages/connectors/src目录下新建一个以 Connector 命名的文件例如新增Foo就创建foo.ts。文件名要求camelCase 且尽量简短。从当前仓库的实际文件布局看packages/connectors/src下已经存在的 Connector 包括baseAccount.ts、coinbaseWallet.ts、metaMask.ts、safe.ts、walletConnect.ts以及从wagmi/core与wagmi/core/tempo重导出的injected、mock、tempoWallet见 packages/connectors/src/exports/index.ts。新文件应与之并列命名风格保持一致。第 3 步用createConnector搭建骨架所有 Connector 的根基都是wagmi/core导出的createConnector工厂函数。文档给出的最小骨架如下import { createConnector } from wagmi/core export type FooBarBazParameters {} export function fooBarBaz(parameters: FooBarBazParameters {}) { return createConnector((config) ({})) }注意三点约定函数名与文件名一致文件叫fooBarBaz.ts导出函数就叫fooBarBaz导出一个工厂函数它接收一个参数对象FooBarBazParameters默认{}返回createConnector的调用结果createConnector接收一个回调回调以config为参数内含chains、emitter、providers、storage等运行时配置详见下文「Parameters」返回 Connector 对象本身。从 packages/core/src/connectors/createConnector.ts 的源码可见createConnector的实现只是把回调原样返回一个恒等包装它的真正价值在于通过CreateConnectorFn类型对整个返回对象做强类型约束任何缺失的属性都会在编译期以类型错误的形式暴露出来。写好骨架后TypeScript 会立刻报出一个类似Type {} is missing the following properties...错误码 2740的类型错误提示你缺少哪些属性。这正是下一步要逐个补齐的内容。第 4 步补齐 Properties、Methods、Events 与 Parameters根据CreateConnectorFn的完整定义packages/core/src/connectors/createConnector.ts一个完整的 Connector 由四类成员构成文档逐类列出如下。Properties连接器静态属性属性必填说明icon否Connector 的可选图标 URLid是Connector 的唯一标识camelCase 且尽量简短例如fooBarBazname是人类可读的名称例如Foo Bar Bazrdns否可选的反向 DNS 标识用于在启用createConfig#multiInjectedProviderDiscovery时过滤重复的 EIP-6963 注入式 Provider以仓库中的 metaMask.ts 为真实范例return createConnectorProvider, Properties((config) ({ id: metaMaskSDK, name: MetaMask, rdns: [io.metamask, io.metamask.mobile], type: metaMask.type, // ... }))可以看到 MetaMask Connector 的rdns是字符串数组源码类型为string | readonly string[]覆盖桌面与移动端两个 Providertype属性则用模块级常量metaMask.type metaMask as const固定。type是CreateConnectorFn返回类型中的只读必填字段用于标识连接器种类。Methods连接器方法方法必填说明connect是连接 Connectordisconnect是断开 ConnectorgetAccounts是返回 Connector 当前连接的账户列表getChainId是返回 Connector 当前连接的链 IDgetProvider是返回底层 Provider 接口供 Connector 内部各处使用isAuthorized是返回 Connector 之前是否连接过且仍处于已授权状态setup否在 Connector 首次创建时运行的初始化逻辑switchChain否切换 Connector 的当前链此外CreateConnectorFn还允许可选的getClient用于返回 viemClient实例。connect的参数对象CreateConnectorFn源码定义包含chainId、isReconnecting与withCapabilities三个可选字段返回值固定为{ accounts, chainId }结构。Events内部事件订阅函数事件必填说明onAccountsChanged是订阅账户变更onChainChanged是订阅链变更onConnect是订阅连接事件onDisconnect是订阅断开事件onMessage否订阅 Provider 消息这些回调的职责是把底层 Provider 的事件转发给 Wagmi 的config.emitter从而同步 Connector 状态与Config。以 metaMask.ts 为例async onAccountsChanged(accounts) { config.emitter.emit(change, { accounts: accounts.map((x) getAddress(x)), }) }, onChainChanged(chain) { const chainId Number(chain) config.emitter.emit(change, { chainId }) }, async onConnect(connectInfo) { const accounts await this.getAccounts() if (accounts.length 0) return const chainId Number(connectInfo.chainId) config.emitter.emit(connect, { accounts, chainId }) }, async onDisconnect(error) { // 处理 MetaMask 的 code: 1013 特殊错误等待重连而不是直接断开 if (error (error as RpcError1013).code 1013) { const provider await this.getProvider() if (provider Boolean((await this.getAccounts()).length)) return } config.emitter.emit(disconnect) },ParameterscreateConnector回调注入的配置回调收到的config对象CreateConnectorFn的参数类型见 createConnector.ts包含以下字段chains用户配置的链列表类型为readonly [Chain, ...Chain[]]至少一条链。switchChain中常用它查找目标链并校验是否已配置emitter事件发射器用于把 Connector 状态同步到 WagmiConfig。可用事件共五类ConnectorEventMap定义于同一源码文件change连接的账户或链发生变化{ accounts?, chainId? }connectConnector 完成连接{ accounts, chainId }disconnectConnector 断开errorConnector 收到错误{ error }messageConnector 收到消息{ type, data? }providers与 Connector 的rdns匹配的已发现 EIP-6963 Provider 列表若multiInjectedProviderDiscovery被禁用或没有匹配的 Provider则为空数组storage用户可选配置的存储默认是对localStorage的封装。safe.ts的shimDisconnect功能正是利用config.storage?.setItem/getItem/removeItem(safe.disconnected)记录断开标记见 safe.tstransports源码中还有此可选字段链 ID 到Transport的映射。文档同时给出两条贯穿实现始终的 tip第三方 SDK 依赖纪律若 Connector 使用第三方 SDK它应依赖尽量少控制 bundle 体积、降低供应链攻击面、使用尽可能宽松的开源许可理想为 MIT且其package.json应声明sideEffects: false以最大化 tree-shaking 支持。地址一律校验和checksumConnector 返回或发出的所有地址值都必须使用 Viem 的getAddress工具做校验和格式化。仓库中几乎所有 Connector 都遵循此约定例如safe.ts中(await provider.request({ method: eth_accounts })).map(getAddress)。第 5 步导出 Connector在packages/connectors/src/exports/index.ts中按字母顺序导出新 Connectorexport { fooBarBaz } from ./fooBarBaz.js从 index.ts 的实际内容可以看到现有导出严格按字母序排列injected、mock、tempoWallet、baseAccount、coinbaseWallet、metaMask、safe、walletConnect以及version新增的fooBarBaz应插入到相应位置。第 6 步在 playground 中试跑并编写测试开发过程中可以借助 dev playgrounds 在真实 dApp 环境里验证 Connector 行为pnpm dev:next/pnpm dev:react/pnpm dev:vue等。文档对测试的要求是理想情况在connectorName.test.ts中编写真实单测最低要求若单测难以编写至少创建测试文件并包含指令式测试instruction tests覆盖以下三类场景如何连接 Connector如何断开 Connector如何切换 Connector 的当前链如适用。测试文件必须写清楚验证所需的一切信息例如需要安装的软件浏览器扩展、移动 App 等、需要交互或部署的智能合约等。从仓库现状看packages/connectors/src下的每个 Connector 都配有同名测试文件metaMask.test.ts、safe.test.ts、walletConnect.test.ts等。另外还要更新导出清单测试 packages/connectors/src/exports/index.test.ts——该文件用 Vitest 的toMatchInlineSnapshot断言导出键的完整集合新增 Connector 后必须同步更新快照可以手动改也可以直接运行pnpm test:update packages/connectors/src/exports/index.test.ts第 7 步把团队成员加入 CODEOWNERSConnector 必须被及时更新、持续维护生产环境用户才能放心依赖。Wagmi 核心团队会尽可能协助 Connector 跟上 Wagmi 的破坏性变更但依赖处理与 issue/discussion 响应是你所在团队的职责——若问题长期无人处理该 Connector 可能被从 Wagmi 中移除。为此需在 .github/CODEOWNERS 中为 Connector 至少登记一名团队成员格式如下/packages/connectors/src/fooBarBaz tmm jxom仓库现有的 CODEOWNERS 就为每个第三方 Connector 登记了对应生态团队例如/packages/connectors/src/metaMask wenfix ffmcgee725 jiexi adonesky1 chakra-guy /packages/connectors/src/safe DaniSomoza dasanra mikhailxyz yagopv /packages/connectors/src/walletConnect ganchoradkov glitch-txs ignaciosantise tomiir登记后涉及该 Connector 的 Pull Request、issue 等都会自动通知到对应维护者。第 8 步编写 Connector 文档Connector 需要配套文档。参考贡献指南的「Writing documentation」一节 启动文档站点运行pnpm docs:dev并添加所需页面。Wagmi 文档站位于./site使用 VitePress 构建site/shared/connectors/目录下已有baseAccount.md、coinbaseWallet.md、injected.md、metaMask.md、safe.md、tempoWallet.md、walletConnect.md等页面可作为新 Connector 文档的参照模板注意保持文档简洁、使用平实语言。第 9 步创建 changeset功能与测试就绪后运行以下命令创建 changesetpnpm changeset按文档要求该 changeset 应是对wagmi/connectors仓库的一个patch版本变更描述格式为Added [ConnectorName]例如Added Foo Bar Baz。changeset 决定了发布时的版本号与 CHANGELOG 文案变更描述用过去时态动词如Added/Fixed这是仓库贡献指南明确约定的命名规范。第 10 步提交 Pull Request一切就绪后按贡献指南的 Pull Request 提交规范创建 Pull Request使用祈使语气命名如Add something。合并后Connector 会进入 Wagmi 的未来版本发布。提交后 GitHub 会自动执行 lint、构建与测试若出现 ❌ 大多说明代码有 bug请通过 CI 日志排查。真实 Connector 源码速览createConnector的三种落地形态为了让上文的抽象契约更具体这里快速对照仓库中三个 Connector 的典型实现模式都可作为你编写新 Connector 的参考模板metaMask.ts基于metamask/connect-evmSDK 的完整实现。展示了SDK 实例懒加载 动态 import模式getInstance()内部使用await import(metamask/connect-evm)并按需创建客户端、错误归一化把UserRejectedRequestError、ResourceUnavailableRpcError映射为 viem 的错误类型、switchChain中利用addEthereumChainParameter与config.chains拼装wallet_switchEthereumChain所需的链配置以及isAuthorized中使用withRetry/withTimeout处理移动端 Provider 在页面加载时的 JSON-RPC 响应延迟。safe.ts展示了storageItem泛型的使用——createConnectorProvider, Properties, StorageItem中的StorageItem { safe.disconnected: true }为存储键提供了类型安全同时演示了shimDisconnect通过config.storage记录断开标记、switchChain可省略Safe 智能合约钱包仅存在于单链、以及通过window.parent ! window判断 iframe 环境Safe App 必须运行在 iframe 中的细节。walletConnect.ts基于walletconnect/ethereum-provider其参数类型通过OmitEthereumProviderOptions, ...精确剪裁 SDK 暴露面并额外定义了isNewChainsStale这样的 Wagmi 专属语义选项展示 Connector 如何在 SDK 之上封装 dApp 友好的配置接口。这三个文件连同各自的*.test.ts测试与site/shared/connectors/下的文档页构成了一份可运行的 Connector 参考实现集。按照本文的十步流程结合这些范例你就能完整走通从想法到上游合入的 Connector 开发全链路。【免费下载链接】wagmiReactive primitives for Ethereum apps项目地址: https://gitcode.com/GitHub_Trending/wa/wagmi创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考