
Wagmi CLI 的 sourcify 插件从 Sourcify 仓库自动拉取合约 ABI 并生成类型安全代码【免费下载链接】wagmiReactive primitives for Ethereum apps项目地址: https://gitcode.com/GitHub_Trending/wa/wagmisourcify是 Wagmi CLI 提供的一个代码生成插件用于从 Sourcify一个去中心化、开源的智能合约验证与元数据仓库按链 ID 与合约地址抓取已通过源码验证的合约 ABI并注入到 Wagmi CLI 的配置管线中。通过它你可以在wagmi.config.ts中仅声明合约名称与地址即可在wagmi generate时自动获取 ABI配合actions、react等插件生成类型安全的 VanillaJS actions 或 React Hooks免去手工维护 ABI 文件与跨链多地址配置的负担。插件定位在 Wagmi CLI 插件体系中的角色在 Wagmi CLI 中插件是注入合约配置contracts与生成代码run的核心机制。sourcify属于从外部来源获取 ABI这一类插件与etherscan、blockExplorer、fetch同族但数据源不同它依赖 Sourcify 的去中心化验证仓库而不是中心化的区块浏览器 API。在 site/cli/api/plugins.md 的插件列表中sourcify被描述为 Fetch ABIs from Sourcify from configurationcontracts即根据配置中的contracts声明逐个抓取 ABI。从源码实现packages/cli/src/plugins/sourcify.ts看它本身并不直接生成代码文件而是复用fetch插件的底层管线完成拉取 → 校验 → 缓存 → 输出ContractConfig[]的工作之后由actions、react等插件消费这些合约配置。安装与导入sourcify插件随wagmi/cli包一起发布通过wagmi/cli/plugins子路径导入import { sourcify } from wagmi/cli/plugins从 packages/cli/src/exports/plugins.ts 可以看到该子路径同时导出了SourcifyConfig类型与sourcify工厂函数export { type SourcifyConfig, sourcify } from ../plugins/sourcify.js基本用法声明合约并抓取 ABI在wagmi.config.ts中使用defineConfig注册插件并通过contracts数组声明需要抓取 ABI 的合约。最小可运行示例import { defineConfig } from wagmi/cli import { sourcify } from wagmi/cli/plugins export default defineConfig({ plugins: [ sourcify({ contracts: [ { name: deposit, address: 0x00000000219ab540356cbb839cbe05303d7705fa, }, ], }), ], })配置完成后运行wagmi generate命令对应实现见 packages/cli/src/commands/generate.tsCLI 会依次执行各插件的validate()、contracts()与run()。在generate的Resolving contracts阶段插件返回的合约配置会被合并进总合约列表随后由其他插件生成代码。注意chainId在SourcifyConfig中是必填项见下文上面的示例仅展示contracts的最小字段。实际使用时需要同时提供chainId否则 TypeScript 会提示缺失必填属性。Configuration 配置项详解插件配置类型为SourcifyConfig可从wagmi/cli/plugins导入import { type SourcifyConfig } from wagmi/cli/plugins其类型定义位于 packages/cli/src/plugins/sourcify.tsexport type SourcifyConfigchainId extends number { cacheDuration?: number | undefined chainId: (chainId extends ChainId ? chainId : never) | (ChainId {}) contracts: ComputeOmitContractConfigChainId, chainId, abi[] }下面逐一说明三个配置项。cacheDurationABI 缓存时长类型number | undefined作用ABI 缓存的有效时长毫秒。在缓存有效期内重复运行generate不会重新发起网络请求。默认值1_800_00030 分钟。import { defineConfig } from wagmi/cli import { sourcify } from wagmi/cli/plugins export default defineConfig({ plugins: [ sourcify({ cacheDuration: 300_000, // [!code focus] chainId: 100, contracts: [ { name: Deposit, address: 0x00000000219ab540356cbb839cbe05303d7705fa, }, ], }), ], })从底层实现看缓存逻辑由fetch插件承担packages/cli/src/plugins/fetch.ts缓存文件保存在~/.wagmi-cli/plugins/fetch/cache目录下见getCacheDir每个合约一个 JSON 文件内容包含{ abi, timestamp }缓存键默认由JSON.stringify(contract)生成getCacheKeysourcify未覆盖该默认实现读取时比较timestamp Date.now()命中则直接复用未命中则重新请求并在成功后写回缓存若网络请求失败会尝试回退读取过期缓存仍无可用数据才抛出错误请求超时默认5_000ms5 秒超时通过AbortController中断timeoutDuration配置。因此cacheDuration直接影响本地磁盘缓存的命中率与 ABI 的新鲜度值越大越省流量与请求延迟但合约升级后 ABI 更新越滞后。chainId抓取 ABI 的链 ID类型number作用指定从哪条链的 Sourcify 验证记录中抓取 ABI当address为对象多链部署时用chainId选取对应的地址。支持链列表见 Sourcify 官方 chains 文档。import { defineConfig } from wagmi/cli import { sourcify } from wagmi/cli/plugins export default defineConfig({ plugins: [ sourcify({ chainId: 100, // [!code focus] contracts: [ { name: Community, address: { 100: 0xC4c622862a8F548997699bE24EA4bc504e5cA865, 137: 0xC4c622862a8F548997699bE24EA4bc504e5cA865, }, }, ], }), ], })chainId的作用体现在两处地址归一化插件入口处若address是普通字符串会将其归一化为{ [chainId]: address }的对象形式packages/cli/src/plugins/sourcify.ts保证后续统一按对象取地址请求 URL 构造request回调中根据address类型解析出最终合约地址并拼接 Sourcify 的 REST API 地址packages/cli/src/plugins/sourcify.tsurl: https://sourcify.dev/server/v2/contract/${chainId}/${contractAddress}?fieldsabi即请求sourcify.dev的 v2 服务端接口按chainId 合约地址精确匹配验证记录并只取abi字段。需要注意的是chainId在类型层面被约束为 Sourcify 已支持的链。源码中以联合类型ChainId枚举了数百条受支持的链packages/cli/src/plugins/sourcify.ts覆盖 Ethereum Mainnet、Sepolia、Holesky、Hoodi、Gnosis、Polygon、Arbitrum、Optimism、Base、BNB Smart Chain、Linea、Scroll、zkSync 等主流网络及大量测试网/侧链。传入联合类型之外的数字会触发 TypeScript 编译错误从类型层面提前拦截不支持的目标链。若address对象中缺少所选chainId对应的地址运行时会抛出明确错误No address found for chainId X. Make sure chainId X is set as an address.contracts需要抓取 ABI 的合约列表类型{ name: string; address?: Address | Recordnumber, Address | undefined }[]作用声明要抓取 ABI 的合约。address可省略仅生成不含地址的 ABI 绑定可以是单个地址也可以是{ [chainId]: address }的多链映射。import { defineConfig } from wagmi/cli import { sourcify } from wagmi/cli/plugins export default defineConfig({ plugins: [ sourcify({ chainId: 100, contracts: [ // [!code focus] { // [!code focus] name: Deposit, // [!code focus] address: 0x00000000219ab540356cbb839cbe05303d7705fa, // [!code focus] }, // [!code focus] ], // [!code focus] }), ], })contracts的类型基于通用的ContractConfigpackages/cli/src/config.ts其中name合约名称必填将作为生成代码的标识符前缀address可选支持单地址字符串或按链 ID 索引的对象例如{ 1: 0x..., 5: 0x... }abi由插件自动填充因此在插件配置中通过OmitContractConfig, abi将其排除无需手动提供。插件最终会把抓取到的abi与合约的name、归一化后的address对象组装成完整的ContractConfig[]返回给 CLI 管线。测试快照packages/cli/src/plugins/snapshots/sourcify.test.ts.snap展示了实际产物形态单链地址被展开为{ 1: 0x... }对象多链地址则保留全部映射ABI 来自 Sourcify 返回的完整 JSON 数组。响应校验与错误处理fetch插件对 Sourcify 响应的解析逻辑packages/cli/src/plugins/sourcify.ts包含三层校验404 处理合约未在 Sourcify 仓库中找到时直接抛出Contract not found in Sourcify repository.结构校验使用 zod 对响应体做safeParseAsync响应必须是{ abi: Abi[] }结构SourcifyResponseschema解析失败则通过fromZodError抛出带Invalid response前缀的错误空 ABI 兜底即使响应合法但没有abi字段也会抛出contract not found。这些错误场景均有对应测试覆盖packages/cli/src/plugins/sourcify.test.ts测试使用 MSW 拦截https://sourcify.dev/server/v2/contract请求分别验证了单链合约成功抓取 ABI多链部署Gnosis 100 / Polygon 137 同一地址按chainId正确取址抓取未验证合约返回 404时抛出Contract not found in Sourcify repository.address对象缺少所选chainId键时抛出No address found for chainId 1. ...且在类型层面通过ts-expect-error验证了编译期约束。与下游代码生成插件串联sourcify只负责取 ABI最终代码由其他插件产出。典型组合是在同一plugins数组中追加actions或reactimport { defineConfig } from wagmi/cli import { actions, sourcify } from wagmi/cli/plugins export default defineConfig({ out: src/generated.ts, plugins: [ sourcify({ chainId: 100, contracts: [ { name: Community, address: 0xC4c622862a8F548997699bE24EA4bc504e5cA865 }, ], }), actions(), ], })此时generate的流程为sourcify插件通过contracts()产出合约配置 → CLI 汇总并解析每个合约的 ABI区分 read/write/event 函数→actions插件按合约名与函数名生成readContract、writeContract、simulateContract、watchContractEvent等类型安全动作packages/cli/src/plugins/actions.ts。这样合约在 Sourcify 上完成源码验证后你无需在仓库中维护 ABI 文件改动合约地址或新增多链部署只需更新contracts声明并重新运行wagmi generate。与同类插件的对比定位在 Wagmi CLI 的插件家族中sourcify与以下插件定位相近但数据源不同etherscanpackages/cli/src/plugins/etherscan.ts从 Etherscan v2 API 抓取 ABI需要apiKey支持代理合约实现地址解析tryFetchProxyImplementationblockExplorer面向支持?modulecontractactiongetabi的通用区块浏览器fetch通用底层插件sourcify正是构建在它之上的可直接用fetch对接任意返回 ABI 的网络资源。相比之下sourcify无需 API Key且数据来自 Sourcify 的去中心化验证仓库这对注重公开可验证性、希望减少中心化服务依赖的项目更友好代价是目标合约必须已在 Sourcify 上完成源码验证且受限于 Sourcify 支持的链列表。小结sourcify插件以极低的配置成本打通了Sourcify 验证仓库 → 本地类型安全合约代码的链路chainId决定数据来源与多链取址contracts声明目标合约cacheDuration控制 30 分钟默认缓存下的请求频率配合fetch底层的超时、缓存回退与 zod 响应校验构成了健壮的 ABI 获取管线。对于在 Sourcify 上已完成验证的合约项目它是比手写 ABI 更省心、比 Etherscan 方案更去中心化的选择。【免费下载链接】wagmiReactive primitives for Ethereum apps项目地址: https://gitcode.com/GitHub_Trending/wa/wagmi创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考