wagmi getChainId 全解析:读取与监听当前链 ID 的底层实现与实战指南
2026/9/17 22:46:31 网站建设 项目流程

wagmi getChainId 全解析:读取与监听当前链 ID 的底层实现与实战指南

【免费下载链接】wagmiReactive primitives for Ethereum apps项目地址: https://gitcode.com/GitHub_Trending/wa/wagmi

本篇技术指南围绕 wagmi(Ethereum apps 响应式原语库)核心 actiongetChainId展开,讲解如何在@wagmi/core中读取当前链 ID、其返回类型的类型安全推导,以及config.state.chainId的更新机制与边界行为。阅读完本文,你将掌握getChainId的完整用法、它与createConfig/ 连接(connection)状态的关系,以及 React 侧useChainIdwatchChainId的配套监听方案。

getChainId 是什么

getChainId是 wagmi 提供的一个用于获取**当前链 ID(chain ID)**的 action。与链上 RPC 调用不同,它不发起任何网络请求,而是直接读取 WagmiConfig内部的全局状态,属于纯同步的内存操作。

官方文档对其定义只有一句话:Action for getting current chain ID,其完整实现位于 getChainId.ts:

export function getChainId<config extends Config>( config: config, ): GetChainIdReturnType<config> { return config.state.chainId }

可以看到,整个函数体只有一行:直接返回config.state.chainId。这是 wagmi 中结构最简单的 action 之一,其价值更多体现在类型系统与状态同步的配合上。

导入与基本用法

从 @wagmi/core 导入

import { getChainId } from '@wagmi/core'

getChainId及其返回类型GetChainIdReturnType通过 exports/actions.ts 作为公共 API 导出:

export { type GetChainIdReturnType, getChainId, } from '../actions/getChainId.js'

传递 config 调用

getChainId是函数式 action,需要显式传入通过createConfig创建的config实例:

import { getChainId } from '@wagmi/core' import { config } from './config' const chainId = getChainId(config)

对应的config示例(来自 site/snippets/core/config.ts):

import { createConfig, http } from '@wagmi/core' import { mainnet, sepolia } from '@wagmi/core/chains' export const config = createConfig({ chains: [mainnet, sepolia], transports: { [mainnet.id]: http(), [sepolia.id]: http(), }, })

上述配置声明了mainnet(链 ID 1)与sepolia(链 ID 11155111)两条链,因此getChainId(config)返回的类型会被推导为1 | 11155111的字面量联合类型(见下文“返回类型”)。

返回类型

getChainId的返回类型可独立导入:

import { type GetChainIdReturnType } from '@wagmi/core'

其类型定义为:

export type GetChainIdReturnType<config extends Config = Config> = config['chains'][number]['id']

即返回值类型被约束为createConfigchains参数中所有链 ID 的字面量联合。这带来两个类型安全收益:

  1. 穷尽性检查:对getChainId(config)的结果做switch分支时,TypeScript 能感知所有可能值;
  2. 跨 action 一致:该类型与switchChaingetClient等 action 使用同一套链 ID 字面量,避免手写number造成的拼写错误。

运行时层面,返回值为number类型——即config.state.chainId当前存储的数字值。

config.state.chainId 的来源与更新机制

getChainId读取的是config.state.chainId,而这一状态字段由createConfig维护。理解它的生命周期是正确使用getChainId的关键。

初始值:chains 数组的第一个链

在 createConfig.ts 中,getInitialStatechainId初始化为配置的第一条链:

function getInitialState(): State { return { chainId: chains.getState()[0].id, connections: new Map<string, Connection>(), current: null, status: 'disconnected', } }

因此在应用启动且尚未连接钱包时,getChainId(config)会返回chains[0].id。以上面的配置为例,即mainnet.id(1)。

连接后:跟随当前 connection 的链

当用户连接钱包后,connect 事件处理 会把data.chainId写入 connection 状态;同时createConfig默认开启的syncConnectedChain(默认true)会订阅当前 connection 的链变化,并在链已配置时同步更新config.state.chainId(见 createConfig.ts):

if (syncConnectedChain) store.subscribe( ({ connections, current }) => current ? connections.get(current)?.chainId : undefined, (chainId) => { const isChainConfigured = chains .getState() .some((x) => x.id === chainId) if (!isChainConfigured) return return store.setState((x) => ({ ...x, chainId: chainId ?? x.chainId, })) }, )

注意其中的守卫条件:只有目标链位于chains配置中,才会切换默认链;否则保持原值。

持久化时的合法性校验

config.state.chainId会随 zustandpersist中间件持久化到 storage,但恢复时会通过validatePersistedChainId校验持久化值是否仍属于已配置链,不合法则回退到默认链 ID(见 createConfig.ts):

function validatePersistedChainId(persistedState, defaultChainId) { return persistedState && 'chainId' in persistedState && typeof persistedState.chainId === 'number' && chains.getState().some((x) => x.id === persistedState.chainId) ? persistedState.chainId : defaultChainId }

这也印证了官方文档的提示:getChainId只会返回通过createConfigchains参数配置过的链 ID

边界行为:连接的链未在 Config 中配置

官方文档明确说明:

如果当前活动连接(connection)的chainId不属于你的 WagmiConfig中的任何一条链,getChainId将返回最后一个已配置的链 ID

这与上述syncConnectedChain订阅中的isChainConfigured守卫逻辑完全一致:未配置的链不会覆盖config.state.chainId,因此读取到的是“最近一次配置过的链 ID”,而不是连接钱包的链。

测试验证:状态如何影响返回值

getChainId.test.ts 用两个断言验证了该 action 的行为:

test('default', async () => { expect(getChainId(config)).toEqual(chain.mainnet.id) config.setState((x) => ({ ...x, chainId: chain.mainnet2.id })) expect(getChainId(config)).toEqual(chain.mainnet2.id) })
  • 初始状态下返回配置的首条链mainnet.id
  • 通过config.setState改写state.chainId后,getChainId立即返回新值。

这说明getChainId无副作用、读取即返回的纯函数,其正确性完全由config.state保证。

配套监听:watchChainId 与 useChainId

getChainId本身只做一次性读取。当链切换时(例如用户通过钱包切换网络),需要配合监听机制感知变化。

watchChainId(core 层)

watchChainId.ts 基于config.subscribe实现:

export function watchChainId<config extends Config>( config: config, parameters: WatchChainIdParameters<config>, ): WatchChainIdReturnType { const { onChange } = parameters return config.subscribe((state) => state.chainId, onChange) }

回调onChange(chainId, prevChainId)会在state.chainId变化时触发,返回值为取消订阅函数。

useChainId(React 层)

React 封装 useChainId.ts 结合useSyncExternalStorewatchChainId,实现链 ID 的响应式订阅:

return useSyncExternalStore( (onChange) => watchChainId(config, { onChange }), () => getChainId(config), () => getChainId(config), )

组件内直接调用useChainId()即可获得当前链 ID,并在链切换时自动触发重渲染——这正是 wagmi“Reactive primitives for Ethereum apps”定位在链元数据读取上的体现。Vue 与 Solid 等框架也提供对应的响应式封装。

常见场景小结

场景推荐 API说明
一次性读取当前链 IDgetChainId(config)同步、无网络请求
链切换时响应式更新watchChainId(config, { onChange })core 层订阅,返回退订函数
React 组件内响应式读取useChainId()基于useSyncExternalStore自动订阅
读取所有已配置链getChains(config)配合chains配置做链列表渲染

延伸阅读

  • createConfig:chainssyncConnectedChainstorage等参数共同决定config.state.chainId的初始值与更新规则;
  • getChains:获取config中配置的全部链对象;
  • switchChain:发起链切换,会联动更新config.state.chainId
  • 核心实现:getChainId.ts、createConfig.ts、useChainId.ts;
  • 测试用例:getChainId.test.ts。

理解getChainId的本质(读取config.state.chainId)与边界(仅返回已配置链 ID、未配置连接回退到最后配置值),能帮助你在多链 DApp 中准确判断“当前处于哪条链”,避免因链配置不完整导致的业务误判。

【免费下载链接】wagmiReactive primitives for Ethereum apps项目地址: https://gitcode.com/GitHub_Trending/wa/wagmi

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询