wagmi React 之 useStorageAt:读取指定地址存储槽(Storage Slot)值的完整指南
2026/9/17 18:26:29 网站建设 项目流程

wagmi React 之 useStorageAt:读取指定地址存储槽(Storage Slot)值的完整指南

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

useStorageAt是 wagmi 提供的 React Hook,用于读取指定合约地址在特定存储槽(storage slot)位置的值,返回值是一个 32 字节的十六进制字符串。本指南以该 Hook 的官方 API 文档为核心,结合本仓库中@wagmi/core的底层实现与测试用例,系统讲解useStorageAt的导入方式、全部参数、返回值结构、TanStack Query 集成方式及其背后的执行链路,帮助你在 React 应用中直接、可靠地读取链上原始存储数据。

Import

useStorageAtwagmi包导出,需要在'use client'环境下使用(服务端组件中不可直接调用):

import { useStorageAt } from 'wagmi'

从源码结构看,Hook 位于 packages/react/src/hooks/useStorageAt.ts,其文件首行为'use client',说明它是为客户端 React 环境设计的交互式 Hook。

Usage

最基础的用法只需提供address(合约地址)与slot(存储槽位):

import { useStorageAt } from 'wagmi' function App() { const result = useStorageAt({ address: '0xFBA3912Ca04dd458c843e2EE08967fC04f3579c2', slot: '0x0', }) }

该示例对应的最小运行环境配置见 site/snippets/react/config.ts,其中使用createConfig创建了包含mainnetsepolia两条链的配置,并通过http()提供默认 RPC 传输层:

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

在真实应用中,你还需要在组件树顶层挂载WagmiProvider(参考 site/react/api/WagmiProvider.md),使 Hook 能自动获取 Config。

Parameters

useStorageAt的参数类型为UseStorageAtParameters

import { type UseStorageAtParameters } from 'wagmi'

从 packages/react/src/hooks/useStorageAt.ts 可以看出,该类型是GetStorageAtOptions<config, selectData> & ConfigParameter<config>的组合:既包含链上查询参数,也包含 TanStack Query 参数与显式config参数。以下逐一说明。

address

Address | undefined

要读取存储的合约地址。注意:在 Hook 层该参数是可选的(未提供时查询不会执行),而在底层getStorageAtAction 中它是必填项。

import { useStorageAt } from 'wagmi' function App() { const result = useStorageAt({ address: '0xFBA3912Ca04dd458c843e2EE08967fC04f3579c2', // [!code focus] slot: '0x0', }) }

slot

Hex | undefined

要读取的存储位置,必须是以十六进制编码的值(如'0x0''0x1'等)。它对应 EVM 世界状态中keccak256布局下的存储槽序号。

import { useStorageAt } from 'wagmi' function App() { const result = useStorageAt({ address: '0xFBA3912Ca04dd458c843e2EE08967fC04f3579c2', slot: '0x0', // [!code focus] }) }

blockNumber

bigint | undefined

指定从某个区块高度读取存储。这对“历史状态查询”非常有用,例如在某一笔交易发生前的区块检查存储值:

import { useStorageAt } from 'wagmi' function App() { const result = useStorageAt({ address: '0xFBA3912Ca04dd458c843e2EE08967fC04f3579c2', blockNumber: 16280770n, // [!code focus] slot: '0x0', }) }

注意blockNumberblockTag互斥,二者不能同时传入。

blockTag

'latest' | 'earliest' | 'pending' | 'safe' | 'finalized' | undefined

指定以哪个区块标签作为读取基准。默认跟随 RPC 节点的latest语义;safefinalized适用于需要规避链重组(reorg)风险的场景:

import { useStorageAt } from 'wagmi' function App() { const result = useStorageAt({ address: '0xFBA3912Ca04dd458c843e2EE08967fC04f3579c2', blockTag: 'safe', // [!code focus] slot: '0x0', }) }

chainId

config['chains'][number]['id'] | undefined

指定查询所在链的 ID。未传时,Hook 会通过useChainId({ config })自动使用当前激活的链。下面的示例显式指定主网:

import { useStorageAt } from 'wagmi' import { mainnet } from '@wagmi/core/chains' function App() { const result = useStorageAt({ chainId: mainnet.id, // [!code focus] address: '0xFBA3912Ca04dd458c843e2EE08967fC04f3579c2', slot: '0x0', }) }

在 packages/react/src/hooks/useStorageAt.ts 的实现中可以看到,chainId的默认值是当前链 ID:chainId: parameters.chainId ?? chainId。测试用例 packages/react/src/hooks/useStorageAt.test.ts 验证了在 Optimism(chainId 10)上同一地址、同一槽位会返回全零值,说明同一存储槽在不同链上可能对应完全不同的数据,跨链查询时务必显式指定chainId

config

Config | undefined

指定要使用的Config实例,覆盖从最近的WagmiProvider中自动获取的配置(参见 site/react/api/createConfig.md)。适用于多配置并存或需要在 Provider 之外使用 Hook 的场景:

import { useStorageAt } from 'wagmi' import { config } from './config' // [!code focus] function App() { const result = useStorageAt({ config, // [!code focus] address: '0xFBA3912Ca04dd458c843e2EE08967fC04f3579c2', slot: '0x0', }) }

scopeKey

string | undefined

将缓存限定到给定上下文。具有相同scopeKey的 Hook 会共享同一份查询缓存;不同scopeKey则可隔离缓存,避免页面间数据串扰:

import { useStorageAt } from 'wagmi' import { config } from './config' function App() { const result = useStorageAt({ scopeKey: 'foo' // [!code focus] address: '0xFBA3912Ca04dd458c843e2EE08967fC04f3579c2', slot: '0x0', }) }

scopeKeyScopeKeyParameter定义,并在查询键(query key)中参与序列化,从而影响缓存的隔离粒度,见 packages/core/src/query/getStorageAt.ts。

query

UseQueryParameters | undefined

TanStack Query 的查询参数,用于控制查询行为。Wagmi 内部使用queryFnqueryKey完成请求,因此这两项不允许覆盖;其余参数均可按需传入。常见可用参数包括:

  • enabled: boolean | undefined:设为false可禁用查询自动执行,常用于依赖查询(Dependent Queries)。
  • gcTime: number | Infinity | undefined:未使用/不活跃缓存数据的存活时间,默认5 * 60 * 1000(5 分钟),SSR 期间为Infinity
  • initialData:查询尚未创建或缓存时用作初始数据(会被持久化到缓存)。
  • staleTime: number | Infinity | undefined:数据被判定为过期的时间,默认0;设为Infinity则永不视为过期。
  • refetchInterval:轮询刷新间隔(毫秒),可传函数按需计算。
  • refetchOnWindowFocus:窗口聚焦时是否在数据过期后重新拉取,默认true
  • retry:失败重试次数,默认客户端为3、服务端为0
  • select:对返回的data做变换,不影响缓存中存储的原始数据。
  • networkMode:网络模式,默认'online'
  • queryClient:指定自定义QueryClient,否则使用最近上下文中的实例。

完整的参数清单可参考 site/shared/query-options.md。

Return Type

useStorageAt的返回值类型为UseStorageAtReturnType,本质上是 TanStack Query 的UseQueryReturnType<GetStorageAtData, GetStorageAtErrorType>

import { type UseStorageAtReturnType } from 'wagmi'

其中GetStorageAtData即底层 Action 的返回类型GetStorageAtReturnType,也就是Hex——32 字节存储槽值的十六进制表示(详见 site/core/api/actions/getStorageAt.md)。

返回对象的核心字段(完整列表见 site/shared/query-result.md):

  • data: GetStorageAtData:最近一次成功解析的数据,默认undefined
  • dataUpdatedAt: number:最近一次查询状态变为'success'的时间戳。
  • error: null | GetStorageAtErrorType:查询抛出的错误对象,默认null
  • errorUpdatedAt / errorUpdateCount:错误时间戳与错误累计次数。
  • failureCount / failureReason:失败次数与最近一次失败原因。
  • fetchStatus: 'fetching' | 'idle' | 'paused':查询拉取状态。
  • isError / isPending / isSuccess:由status派生的布尔值。
  • isFetching / isRefetching / isLoading:拉取中、后台刷新中、首次加载中的布尔值。
  • isFetched / isFetchedAfterMount:是否已拉取过、是否在挂载后拉取过。
  • isLoadingError / isRefetchError:首次加载失败 / 刷新失败标记。
  • isPlaceholderData / isStale:是否为占位数据 / 数据是否过期。
  • refetch(options):手动重新拉取,cancelRefetch默认true
  • status: 'error' | 'pending' | 'success':查询整体状态。

测试快照 packages/react/src/hooks/useStorageAt.test.ts 展示了真实返回值示例:对0xFBA3912Ca04dd458c843e2EE08967fC04f3579c2地址的0x0槽位,成功返回"0x7761676d6900000000000000000000000000000000000000000000000000000a",同时queryKey序列化为["getStorageAt", { address, chainId: 1, slot }]

TanStack Query 集成

useStorageAt底层复用 TanStack Query v5 的查询机制,因此也可以直接使用底层的 query 构造函数,便于在组件外预取、序列化或构建 query key:

import { type GetStorageAtData, type GetStorageAtOptions, type GetStorageAtQueryFnData, type GetStorageAtQueryKey, getStorageAtQueryKey, getStorageAtQueryOptions, } from 'wagmi/query'

这些导出对应 packages/core/src/query/getStorageAt.ts 中的实现:

  • getStorageAtQueryKey(options):根据参数(过滤掉 query 相关字段)生成稳定且可序列化的查询键,形如['getStorageAt', { address, chainId, slot, ... }]
  • getStorageAtQueryOptions(config, options):生成完整的查询选项对象,其中queryFn负责调用getStorageAtAction;
  • GetStorageAtQueryKey / GetStorageAtQueryFnData / GetStorageAtData:配套的类型工具。

一个值得注意的实现细节是查询的启用条件(packages/core/src/query/getStorageAt.ts):

enabled: Boolean( options.address && options.slot && (options.query?.enabled ?? true), )

也就是说,只有当addressslot都已提供(且用户未显式禁用)时,查询才会真正发起。对应测试 packages/react/src/hooks/useStorageAt.test.ts 验证了在不传任何参数时 Hook 保持isPending、不会发请求;而addressundefined变为有值后,查询会自动触发并成功返回数据(见同一测试文件第 204-290 行)。这非常适合“地址异步加载后再读取存储”的典型场景。

Action 调用链与底层原理

useStorageAt是对核心 ActiongetStorageAt的响应式封装。其调用链如下:

  1. useStorageAt通过useConfig(parameters)获取 Config,通过useChainId({ config })解析当前链 ID;
  2. 调用getStorageAtQueryOptions组装 TanStack Query 选项;
  3. 查询触发后,queryFn调用@wagmi/coregetStorageAtAction(源码见 packages/core/src/actions/getStorageAt.ts);
  4. Action 内部根据chainId从 Config 取出对应客户端:config.getClient({ chainId }),再通过getAction(client, viem_getStorageAt, 'getStorageAt')复用 viem 的getStorageAtAction,最终调用 RPC 节点的eth_getStorageAt方法并返回 32 字节的Hex值。

这一分层结构意味着:Hook 层负责响应式状态与缓存管理,Action 层负责链交互与客户端解析,viem 层负责 RPC 协议细节,各层职责清晰、可独立测试与复用。如果你不需要 React 的响应式能力,也可以直接使用核心包:import { getStorageAt } from '@wagmi/core',并按 site/core/api/actions/getStorageAt.md 中的方式传入config与参数调用。

错误处理

当查询失败(如地址不存在、槽位越界、RPC 异常)时,error字段会携带类型为GetStorageAtErrorType的错误对象。该错误类型继承自 viem 的GetStorageAtErrorType(见 packages/core/src/actions/getStorageAt.ts),涵盖 RPC 请求、参数校验等常见错误类别。在组件中建议结合isErrorisPendingdata做完整的状态渲染:

function App() { const { data, isError, isLoading } = useStorageAt({ address: '0xFBA3912Ca04dd458c843e2EE08967fC04f3579c2', slot: '0x0', }) if (isLoading) return <div>Loading storage...</div> if (isError) return <div>Failed to read storage slot</div> return <div>Storage value: {data}</div> }

总结

useStorageAt是 wagmi React 中读取链上原始存储数据的标准入口:它把@wagmi/coregetStorageAtAction 与 TanStack Query 的缓存、重试、轮询、依赖查询等能力无缝整合,让开发者用最少的样板代码获取任意合约地址在任意存储槽位的值。掌握其addressslotblockNumberblockTagchainIdconfigscopeKeyquery参数,并理解其底层 Action 调用链与自动启用逻辑,即可在合约调试、存储布局分析、链上数据监控等场景中稳定落地。

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

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

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

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

立即咨询