wagmi 核心 Action 详解:switchConnection 切换当前连接账户
2026/9/17 19:29:58 网站建设 项目流程

wagmi 核心 Action 详解:switchConnection 切换当前连接账户

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

switchConnection@wagmi/core提供的一个核心 Action,用于在已建立的多个连接(connection)之间切换"当前账户"。本文以 switchConnection 官方文档 为骨架,结合仓库源码深入讲解它的调用方式、参数与返回类型、底层实现原理、错误处理以及 TanStack Query 与 React Hook 的集成方式,帮助你准确掌握多账户场景下的连接切换能力。

一、switchConnection 是什么

在 wagmi 中,一个Config实例可以同时维护多个"连接"(connection),每个连接对应一个 Connector(如 MetaMask、WalletConnect)与一组账户。switchConnection的作用就是改变当前激活的连接,从而让后续以"当前账户"为基准的读取与交易操作切换到另一套账户上。

从源码看,它的核心逻辑非常精简,位于 packages/core/src/actions/switchConnection.ts:

export async function switchConnection<config extends Config>( config: config, parameters: SwitchConnectionParameters, ): Promise<SwitchConnectionReturnType<config>> { const { connector } = parameters const connection = config.state.connections.get(connector.uid) if (!connection) throw new ConnectorNotConnectedError() await config.storage?.setItem('recentConnectorId', connector.id) config.setState((x) => ({ ...x, current: connector.uid, })) return { accounts: connection.accounts, chainId: connection.chainId, } }

它并不负责发起新的钱包连接,而是从config.state.connections这个连接池中取出目标 connector 对应的连接,将其uid设为state.current,从而完成"当前账户"的切换。

二、导入与基本用法

1. 导入

switchConnection@wagmi/core顶层导出,可直接按需引入:

import { switchConnection } from '@wagmi/core'

对应的类型(参数、返回、错误)同样从@wagmi/core导出,将在后文逐一说明。

2. 标准用法

官方文档给出的典型场景是:先通过getConnections拿到当前 Config 上已建立的所有连接,再把其中一个连接对应的 connector 传给switchConnection

import { getConnections, switchConnection } from '@wagmi/core' import { config } from './config' const connections = getConnections(config) const result = await switchConnection(config, { connector: connections[0]?.connector, })

这里的config是一个通过createConfig创建的配置实例,仓库中对应的示例位于 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(), }, })

3. 为什么要配合 getConnections

switchConnection的参数是connector,而连接是按connector.uid索引的。getConnections会返回当前 Config 上全部已建立的连接(packages/core/src/actions/getConnections.ts):

export function getConnections(config: Config): GetConnectionsReturnType { const connections = [...config.state.connections.values()] if (config.state.status === 'reconnecting') return previousConnections if (deepEqual(previousConnections, connections)) return previousConnections previousConnections = connections return connections }

因此标准姿势就是"先getConnections枚举,再switchConnection指定其中一个",保证传入的 connector 一定处于已连接状态。

三、参数详解

SwitchConnectionParameters

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

该类型定义在 packages/core/src/actions/switchConnection.ts:

export type SwitchConnectionParameters = { connector: Connector }

connector

  • 类型Connector
  • 含义:要切换到的连接对应的 Connector 实例,即 Connector 中描述的对象。

一个实际的使用示例(文档原样):

import { getConnections, switchConnection } from '@wagmi/core' import { config } from './config' const connections = getConnections(config) const result = await switchConnection(config, { connector: connections[0]?.connector, // [!code focus] })

需要特别注意的是:connector必须是已经建立过连接的 connector。如果传入的连接并不存在于config.state.connections中,switchConnection会直接抛出ConnectorNotConnectedError(详见下文"错误处理"小节)。如果需要建立全新连接,应使用 connect 之类的 Action,而不是switchConnection

四、返回类型详解

SwitchConnectionReturnType

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

类型定义于 packages/core/src/actions/switchConnection.ts:

export type SwitchConnectionReturnType<config extends Config = Config> = { accounts: readonly [Address, ...Address[]] chainId: | config['chains'][number]['id'] | (number extends config['chains'][number]['id'] ? number : number & {}) }

accounts

  • 类型readonly [Address, ...Address[]]
  • 含义:目标 connector 连接上的账户地址列表,至少包含一个地址。它与getConnection返回的addresses一致,来源于连接建立时获取的账户集合。

chainId

  • 类型number
  • 含义:目标 connector 当前所在的链 ID。在类型层面,它会尽量收紧为config配置中声明的链 ID 联合类型;若 Config 未限定链集合,则退化为number

需要说明的是,accountschainId都是从已有连接中原样返回的(对应源码中的connection.accountsconnection.chainId),switchConnection本身不会发起网络请求去重新查询链与账户。

五、错误处理

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

该联合类型在 packages/core/src/actions/switchConnection.ts 中定义:

export type SwitchConnectionErrorType = | ConnectorNotConnectedErrorType | BaseError | ErrorType

ConnectorNotConnectedError

这是switchConnection最典型的失败场景:当传入的 connector 在config.state.connections中找不到对应连接时抛出。其定义位于 packages/core/src/errors/config.ts:

export type ConnectorNotConnectedErrorType = ConnectorNotConnectedError & { name: 'ConnectorNotConnectedError' } export class ConnectorNotConnectedError extends BaseError { override name = 'ConnectorNotConnectedError' constructor() { super('Connector not connected.') } }

即错误信息为Connector not connected.。因此在调用前建议先用getConnections校验目标 connector 是否已连接,避免依赖运行时抛错。

其他错误

  • BaseError:wagmi 内部所有错误的基类,涵盖连接过程中的通用异常;
  • ErrorType:用于承接任意未知错误(通常由 connector 内部抛出)。

实际开发中可结合getConnection(packages/core/src/actions/getConnection.ts)返回的status字段判断当前连接状态,再决定是否需要先connectswitchConnection

六、底层实现原理

switchConnection虽然只有十几行代码,但每一步都有明确的语义,值得逐一拆解:

  1. 校验连接存在config.state.connections.get(connector.uid)按 connector 的唯一标识uid在连接池中查找;找不到则抛ConnectorNotConnectedError
  2. 持久化最近使用的 connectorconfig.storage?.setItem('recentConnectorId', connector.id)会把本次切换的 connector 写入存储。这样在页面刷新或重新连接(reconnect)时,wagmi 可以优先恢复这个最近使用的连接,实现"记住上次使用的钱包"。
  3. 更新当前连接指针config.setStatestate.current更新为目标 connector 的uid,同时保留其余 state 字段。此后getConnection(config)会基于新的current返回对应连接与账户(getConnection 实现)。
  4. 返回切换结果:从已有连接对象中取出accountschainId返回,供调用方立即使用。

由于整个过程只涉及内存状态与一次可选的 storage 写入,不经过网络,switchConnection是同步语义下非常轻量的操作(函数本身为async以便与存储层衔接)。

七、与 TanStack Query 的集成

@wagmi/core/query提供了将switchConnection封装为 mutation 的工厂函数,位于 packages/core/src/query/switchConnection.ts:

export function switchConnectionMutationOptions<config extends Config, context>( config: config, options: SwitchConnectionOptions<config, context> = {}, ): SwitchConnectionMutationOptions<config> { return { ...(options.mutation as any), mutationFn(variables) { return switchConnection(config, variables) }, mutationKey: ['switchConnection'], } }

要点如下:

  • mutationFn直接调用核心 Action,因此语义与手写调用完全一致;
  • mutationKey固定为['switchConnection'],便于在 TanStack Query DevTools 中定位;
  • 同时导出了一组类型:SwitchConnectionData(返回类型)、SwitchConnectionVariables(参数类型)、SwitchConnectionMutate/SwitchConnectionMutateAsync(同步/异步触发函数类型)、SwitchConnectionErrorType(错误类型)。

官方文档中的标准导入方式如下:

import { type SwitchConnectionData, type SwitchConnectionVariables, type SwitchConnectionMutate, type SwitchConnectionMutateAsync, SwitchConnectionMutationOptions, } from '@wagmi/core/query'

八、React 中的 useSwitchConnection

在 React 侧,wagmi 提供了现成 Hook useSwitchConnection,内部正是基于上面的switchConnectionMutationOptions与 TanStack Query 的useMutation构建:

export function useSwitchConnection< config extends Config = ResolvedRegister['config'], context = unknown, >( parameters: UseSwitchConnectionParameters<config, context> = {}, ): UseSwitchConnectionReturnType<config, context> { const config = useConfig(parameters) const options = switchConnectionMutationOptions(config, parameters) const mutation = useMutation(options) ... }

值得注意的兼容性细节:该 Hook 的返回类型中保留了几个标记为@deprecated的别名(packages/react/src/hooks/useSwitchConnection.ts#L39-L48):

/** @deprecated use `useConnections` instead */ connectors: readonly Connector[] /** @deprecated use `mutate` instead */ switchAccount: SwitchConnectionMutate<config, context> /** @deprecated use `mutateAsync` instead */ switchAccountAsync: SwitchConnectionMutateAsync<config, context> /** @deprecated use `mutate` instead */ switchConnection: SwitchConnectionMutate<config, context> /** @deprecated use `mutateAsync` instead */ switchConnectionAsync: SwitchConnectionMutateAsync<config, context>

这说明了三个重要信息:

  1. 当前推荐的用法是直接使用mutate/mutateAsync触发切换,使用useConnections读取连接列表;
  2. 旧的switchAccountswitchConnection等字段仅为向后兼容保留,新代码不应再依赖;
  3. 触发时只需传入{ connector }变量即可,例如:
const { mutateAsync } = useSwitchConnection() await mutateAsync({ connector })

九、测试用例验证

仓库为switchConnection提供了完整的单元测试,见 packages/core/src/actions/switchConnection.test.ts,核心场景是"在多个已连接账户之间来回切换":

await connect(config, { connector: connector2 }) await connect(config, { connector: connector1 }) const address1 = getConnection(config).address await switchConnection(config, { connector: connector2 }) const address2 = getConnection(config).address expect(address2).toBeDefined() expect(address1).not.toBe(address2) await switchConnection(config, { connector: connector1 }) const address3 = getConnection(config).address expect(address3).toBeDefined() expect(address1).toBe(address3)

测试揭示了三个可以写进实战经验的行为:

  • switchConnection只会改变"当前账户",而不会断开其他连接——两个连接在切换后依然并存;
  • 切换后getConnection(config).address会立即反映新账户;
  • 切回原 connector 后,账户地址与切换前完全一致(address1 === address3),说明连接状态被完整保留。

十、典型应用场景小结

结合文档与源码,switchConnection最适合以下场景:

  • 多钱包/多账户 DApp:用户在界面上下拉选择"使用哪个账户操作",切换后所有依赖getConnection/useAccount的组件自动响应;
  • 记住最近使用:通过底层写入recentConnectorId的机制,配合连接恢复流程,让用户下次进入时自动回到上次使用的连接;
  • 作为 mutation 接入数据层:借助switchConnectionMutationOptionsuseSwitchConnection,将切换动作纳入 TanStack Query 的加载/错误状态管理。

需要再次强调的是:switchConnection只负责切换已存在的连接;如果目标 connector 尚未连接,应当先调用 connect,否则会得到ConnectorNotConnectedError。这一约束是使用该 Action 时最容易踩的坑,也是文档示例中坚持先getConnections再切换的根本原因。

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

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

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

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

立即咨询