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
useStorageAt从wagmi包导出,需要在'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创建了包含mainnet与sepolia两条链的配置,并通过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', }) }注意blockNumber与blockTag互斥,二者不能同时传入。
blockTag
'latest' | 'earliest' | 'pending' | 'safe' | 'finalized' | undefined
指定以哪个区块标签作为读取基准。默认跟随 RPC 节点的latest语义;safe与finalized适用于需要规避链重组(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', }) }scopeKey由ScopeKeyParameter定义,并在查询键(query key)中参与序列化,从而影响缓存的隔离粒度,见 packages/core/src/query/getStorageAt.ts。
query
UseQueryParameters | undefined
TanStack Query 的查询参数,用于控制查询行为。Wagmi 内部使用queryFn与queryKey完成请求,因此这两项不允许覆盖;其余参数均可按需传入。常见可用参数包括:
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), )也就是说,只有当address与slot都已提供(且用户未显式禁用)时,查询才会真正发起。对应测试 packages/react/src/hooks/useStorageAt.test.ts 验证了在不传任何参数时 Hook 保持isPending、不会发请求;而address从undefined变为有值后,查询会自动触发并成功返回数据(见同一测试文件第 204-290 行)。这非常适合“地址异步加载后再读取存储”的典型场景。
Action 调用链与底层原理
useStorageAt是对核心 ActiongetStorageAt的响应式封装。其调用链如下:
useStorageAt通过useConfig(parameters)获取 Config,通过useChainId({ config })解析当前链 ID;- 调用
getStorageAtQueryOptions组装 TanStack Query 选项; - 查询触发后,
queryFn调用@wagmi/core的getStorageAtAction(源码见 packages/core/src/actions/getStorageAt.ts); - 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 请求、参数校验等常见错误类别。在组件中建议结合isError、isPending与data做完整的状态渲染:
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/core的getStorageAtAction 与 TanStack Query 的缓存、重试、轮询、依赖查询等能力无缝整合,让开发者用最少的样板代码获取任意合约地址在任意存储槽位的值。掌握其address、slot、blockNumber、blockTag、chainId、config、scopeKey与query参数,并理解其底层 Action 调用链与自动启用逻辑,即可在合约调试、存储布局分析、链上数据监控等场景中稳定落地。
【免费下载链接】wagmiReactive primitives for Ethereum apps项目地址: https://gitcode.com/GitHub_Trending/wa/wagmi
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考