wagmi 自定义 Transport(custom)接入指南:为 Ethereum 应用配置任意 JSON-RPC Provider
【免费下载链接】wagmiReactive primitives for Ethereum apps项目地址: https://gitcode.com/GitHub_Trending/wa/wagmi
customTransport 允许在 wagmi 中绕过固定 URL 的 RPC 端点,直接传入一个符合 EIP-1193 规范的request函数来与任意 JSON-RPC API 通信,是实现钱包 Provider 适配、自定义 RPC 网关、测试替身与跨框架复用的关键入口。本文以 site/react/api/transports/custom.md(其正文来自共享文档 site/shared/transports/custom.md)为核心,结合 wagmi 源码与测试,完整讲解它的导入方式、配置参数、重试机制与在 React 环境下的实际用法。
Transport 在 wagmi 中的地位
在 wagmi 中,Transport 是连接链与客户端之间的桥梁。createConfig通过transports对象把每个chain.id映射到一个 Transport,从而决定该链上的读取、写入与合约调用请求走哪条网络通道:
export const config = createConfig({ chains: [mainnet], connectors: [injected()], transports: { [mainnet.id]: custom({ /* ... */ }), }, })wagmi 原生导出了三类 Transport,全部通过viem转发(见 packages/core/src/exports/index.ts 的export { custom, http, webSocket } from 'viem'):
http:通过固定的 HTTP URL 连接 RPC 端点;webSocket:通过 WebSocket 连接 RPC 端点;custom:通过自定义的 EIP-1193request函数连接,是本文主题。
同时 wagmi 还提供了fallback(packages/core/src/transports/fallback.ts)与unstable_connector(packages/core/src/transports/connector.ts)两个组合型 Transport,可与custom组合使用。在 React 包中,custom同样从@wagmi/core被重新导出(见 packages/react/src/exports/index.ts),因此 React、Core 用户使用完全一致的 API。
导入 custom Transport
在所有框架(React、Vue、Solid 或纯 Core)中,custom都可以直接从包顶层导入:
import { custom } from 'wagmi'对于仅使用 core 的场景,则从@wagmi/core导入:
import { custom } from '@wagmi/core'基本用法:在 createConfig 中注册自定义 RPC
最典型的用法是在createConfig的transports中,将某个链的 Transport 指定为custom,并传入一个request函数:
import { createConfig, custom, } from 'wagmi' import { mainnet } from 'wagmi/chains' import { customRpc } from './rpc' export const config = createConfig({ chains: [mainnet], connectors: [injected()], transports: { [mainnet.id]: custom({ async request({ method, params }) { const response = await customRpc.request(method, params) return response }, }), }, })其中./rpc中的customRpc可以是任意实现了request方法的 JSON-RPC 客户端,例如 ethers 的JsonRpcProvider、MetaMask 等注入式钱包的window.ethereum、测试网络的 stub,或经过包装的网关客户端。从源码结构看,custom本身不负责链的校验、连接管理或地址解析,它只负责把{ method, params }转发给你提供的request实现,因此它具有极强的通用性。
参数详解
provider(必填)
{ request({ method: string, params: unknown[] }): Promise<unknown> }
custom的第一个参数是一个 EIP-1193 规范的request函数。EIP-1193 定义了 Ethereum Provider 的标准接口,其核心就是request方法:接收一个 JSON-RPC 请求对象(method与可选的params),返回一个 Promise。任何符合该规范的 Provider(注入式钱包、钱包 SDK、本地节点封装等)都可以直接传入:
import { customRpc } from './rpc' const transport = custom({ async request({ method, params }) { const response = await customRpc.request(method, params) return response }, })key(可选)
string
Transport 的键,默认为"custom"。key在客户端创建时用于标识与查找对应的 Transport:
const transport = custom( provider, { key: 'windowProvider', }, )name(可选)
string
Transport 的名称,默认为"Ethereum Provider"。该名称主要用于日志与调试信息展示:
const transport = custom( provider, { name: 'Window Ethereum Provider', }, )retryCount(可选)
number
请求失败时的最大重试次数,默认为3。注意该参数是“最大重试次数”,即最多额外重试 3 次,总共最多发出 4 次请求:
const transport = custom(provider, { retryCount: 5, })retryDelay(可选)
number
重试之间的基础延迟(毫秒)。默认情况下 Transport 会采用指数退避策略,计算公式为~~(1 << count) * retryDelay,意味着重试间隔并非恒定值,而是随重试次数指数增长:
const transport = custom(provider, { retryDelay: 100, })结合源码理解:Transport 配置如何在链上落地
custom在 wagmi 中是一个透明转发自 viem 的 API,但理解它如何与 wagmi 的客户端体系协作,有助于在实际项目中排错与调优。
wagmi 自身实现的两个组合型 Transport 与custom遵循完全一致的配置协议,可作为对照参考。以 packages/core/src/transports/connector.ts 中的ConnectorTransportConfig为例,它定义了与custom相同的四个可选配置项:
export type ConnectorTransportConfig = { /** The key of the transport. */ key?: TransportConfig['key'] | undefined /** The name of the transport. */ name?: TransportConfig['name'] | undefined /** The max number of times to retry. */ retryCount?: TransportConfig['retryCount'] | undefined /** The base delay (in ms) between retries. */ retryDelay?: TransportConfig['retryDelay'] | undefined }其实现unstable_connector(packages/core/src/transports/connector.ts)展示了 Transport 的完整生命周期:
- 设置默认值:
key默认为'connector'、name默认为'Connector'; - 当客户端实际发起请求时,Transport 函数被调用,接收
chain与connectors等参数; - 通过
connectors.getState().find(...)找到目标连接器,调用其getProvider({ chainId })取得 Provider; - 对
eth_chainId进行带重试与超时(100ms)的探测,校验当前链与目标链一致,不一致则抛出ChainDisconnectedError; - 最终通过
createTransport组装出标准 Transport 对象,将key、name、retryCount、retryDelay一并下发。
可以推断,custom传入的request函数最终也会被 viem 的createTransport包装为同样的 Transport 结构,并应用相同的重试与超时策略。这意味着你为custom设置的retryCount/retryDelay会作用于其内部的每一次 JSON-RPC 请求,因此:
- 当你的自定义 Provider 偶发网络抖动时,
retryCount: 3(默认值)能提供基本的容错; - 若你的 Provider 对高并发请求敏感,可适当增大
retryDelay以拉长退避间隔,降低瞬时压力; - 若你的 Provider 自身已实现完整重试,可将
retryCount设为0关闭 wagmi 侧的重试,避免双重重试造成请求堆积。
常见应用场景
1. 适配注入式钱包 / 自定义 Provider
custom最常见的用途是把window.ethereum之类的 EIP-1193 Provider 包装为可用的 Transport,从而让应用既能使用 wagmi 的 connectors,又能直接通过底层 Provider 发起 JSON-RPC 调用。
2. 接入非标准 RPC 网关
当你的 RPC 端点需要签名、鉴权、限流等自定义逻辑时,http无法表达这些行为,此时用custom在request内部完成包装即可。
3. 测试替身与模拟
在单元测试中,可以传入一个返回固定响应或按方法分发的 mockrequest函数,从而在不依赖真实网络的情况下验证应用逻辑(可参考 packages/core/src/transports/fallback.test.ts 与 packages/core/src/transports/connector.test.ts 了解 wagmi 对 Transport 行为的测试方式)。
4. 与 fallback 组合实现多通道容灾
fallbackTransport 接受一组 Transport 并依次尝试,因此可以把custom与http、webSocket组合,形成“自定义通道优先、公共 RPC 兜底”的策略:
import { createConfig, custom, fallback, http } from 'wagmi' import { mainnet } from 'wagmi/chains' export const config = createConfig({ chains: [mainnet], transports: { [mainnet.id]: fallback([ custom({ /* 自定义网关 */ }), http('https://cloudflare-eth.com'), ]), }, })相关参考
- Transport 参考文档:site/shared/transports/custom.md、site/react/api/transports/custom.md、site/react/api/transports/http.md
- Core 源码导出:packages/core/src/exports/index.ts
- React 源码导出:packages/react/src/exports/index.ts
- 组合型 Transport 实现:packages/core/src/transports/fallback.ts、packages/core/src/transports/connector.ts
- 链与 Transport 配置示例:playgrounds/vite-react/wagmi.config.ts
【免费下载链接】wagmiReactive primitives for Ethereum apps项目地址: https://gitcode.com/GitHub_Trending/wa/wagmi
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考