背景
EVM 开发者经常遇到的问题是”历史余额问题” —— 恢复某个 ERC-20、ERC-721 或 ERC-1155 代币账户到余额的完整映射。Solidity 不会追踪 mapping 中的键;值在对键进行哈希后存储到相应的存储槽中。因此,要恢复余额,常见策略是重放该代币的所有转账事件并计算滚动累加。 Envio HyperSync 是一个索引器,允许开发者在几秒钟内查询数百万个区块链事件。在本指南中,我们将使用来自 HyperSync 的数据重建代币的历史余额。前置条件
- Node.js 18+
- 从 envio.dev/app/api-tokens 获取的免费 HyperSync API 密钥
HyperSync 端点
| 网络 | URL |
|---|---|
| 测试网 | |
| 主网 |
组件
本指南概述如何重建三种最流行代币标准(ERC-20、ERC-721 和 ERC-1155)的余额。每种都使用一些通用组件,但需要不同的逻辑来组合出最终结果。查询 Transfer 事件
首先,让我们编写代码来查询合约的所有 Transfer 事件,并按适当的签名过滤。 ERC-20 和 ERC-721 使用下面的Transfer 事件,而 ERC-1155 使用 TransferSingle 和 TransferBatch 事件:
lib/signatures.ts
lib/hypersync.ts
字段选择
为了优化查询,我们只请求实际需要的字段。这可以减少响应大小并显著加快查询速度。不同代币标准将数据编码在不同的 topic 中: ERC-721(tokenId 位于 topic3):解析日志数据
现在我们有了原始事件数据,需要将其解析为可用的值。Topics 是 32 字节的十六进制字符串,其中地址左侧填充零,占据最后 20 字节:lib/parse.ts
注意:parseValue返回原始代币值作为bigint。ERC-20 代币具有decimals属性(通常为 18)—— 除以10n ** BigInt(decimals)以转换为人类可读的数量。
分页
HyperSync 返回分页结果以高效处理大型数据集。我们需要持续查询,直到next_block 为 undefined,以获取所有转账:
lib/paginate.ts
ERC-721 余额快照
对于 ERC-721,我们通过重放所有 Transfer 事件重建当前的持有状态。对于 NFT,每个 token ID 的最后一次转账决定了当前的所有者:app/api/snapshot/route.ts
ERC-20 余额快照
对于 ERC-20 代币,我们需要累加所有转账以计算当前余额。与 NFT 追踪所有权不同,ERC-20 余额需要为每个地址累加所有转入和转出的转账。 首先,用正确的字段选择查询 ERC-20 转账(topic1 为from,topic2 为 to,data 为值):
lib/erc20.ts
lib/erc20.ts
ERC-1155 余额快照
ERC-1155 代币与 ERC-20 和 ERC-721 的工作方式不同。它们将id 和 value 存储在 data 字段而不是 topic 中,需要更复杂的解析:
lib/erc1155.ts
查询多种事件类型
在处理 ERC-1155 代币时,我们可以通过在单个请求中同时查询 TransferSingle 和 TransferBatch 事件来优化:lib/multi-event.ts
topic0 路由:
获取最新区块
要验证您已同步所有可用数据,您可以检查当前链的高度:lib/height.ts
常见错误
1. 忘记分页
HyperSync 返回的是部分结果。请始终检查next_block:
2. 请求未使用的字段
每个字段都会增加响应大小。请显式指定:3. 使用库进行简单解析
HyperSync 返回原始十六进制。原生 BigInt 可以处理它:4. 未过滤已销毁的代币
地址0x000...000 表示已销毁:
API 参考
POST /query
查询事件日志。 请求体:
响应:
GET /height
获取当前链的高度。 响应:总结
Envio HyperSync 让您可以通过单个分页 API 查询 Monad 上任何合约的事件历史 —— 无需运行节点,也无需维护索引器。/query 端点接受 topic 和地址过滤器,/height 会给您当前链的高度。请查看完整 HyperSync 文档以了解更多查询类型和选项。
在此基础上,您可以扩展此模式以构建空投资格检查器、治理投票权快照或多代币组合追踪器。
后续步骤
- Envio 文档 - 完整的 HyperSync 文档
- API tokens - 获取您的免费 API 密钥

