eth_getLogs 与代币转账 API:ERC-20 转账历史怎么查

查询合约事件日志用 eth_getLogs,已索引的 ERC-20 与 ERC-721 转账历史用代币转账 API,支持按地址或按代币合约读取,使用游标分页,超出覆盖范围时返回 422,已被裁剪的历史返回 4444。

查询钱包历史或核对 ERC-20 转账时,从代币转账 API开始;需要合约事件日志时使用 eth_getLogs。开发者与 AI Agent 可通过同一套链上数据 API 查询已索引的地址转账记录。钱包资产教程组合代币余额、转账历史与元数据,Data API 参考定义请求参数与响应格式。

这篇帮你完成什么任务

两种读取日志与转账的方式

eth_getLogs 是 JSON-RPC 方法,通过 JSON-RPC 端点返回区块日志。Data API 则通过两个按链划分的端点提供代币转账历史:

  • GET /{chain}/addresses/{address}/transfers——与某个地址相关的转账。
  • GET /{chain}/tokens/{token}/transfers——某个代币合约的转账。

两者使用同一个 API key,并按方法权重以 CU 计量(见下方权重表)。选哪一种,取决于数据有多新、是否需要指定区块窗口,以及如何翻页。

eth_getLogs 受到的限制

eth_getLogs 受公开的 GET /v1/chains 响应中逐链公布的各项限制约束:

  • 区块跨度:max_logs_block_range 是单次 eth_getLogs 请求允许跨越的最大区块数。该值因链而异——请从 GET /v1/chains 读取(链列表见支持的链),不要写死在代码里。超过该链上限时返回 JSON-RPC 错误 -32602 eth_getLogs block range too large(不计费)。
  • 节点同步:当某条链的节点未同步时,eth_getLogs 返回 -32010(不计费)。
  • 状态窗口:GET /v1/chains 中的 state_window_blocks 所描述的状态窗口只作用于状态类方法(如 eth_call、eth_getBalance),不作用于 eth_getLogs。
  • 节点历史裁剪:区块与日志查询不受状态窗口限制,但受节点保留历史的限制;已被裁剪的数据返回 4444 pruned history unavailable(不计费)。

过滤字段 fromBlock、toBlock 缺省或为 null 时按 latest 处理。

历史扫描超出单次请求范围时,按 eth_getLogs 分块查询指南 拆分包含两端的区块区间,并在当前分块成功后再推进。

通过 HTTP 调用 eth_subscribe 返回 -32601 method not available。在 /v1/chains 中 ws 为 true 的链上,可以通过 WebSocket 使用 eth_subscribe(见支持的链);其他情况请轮询 eth_getLogs 查询最新区块。

Data API 转账接口提供什么

两个端点的必填参数不同:

端点standard区块窗口
GET /{chain}/addresses/{address}/transfers必填:erc20 或 erc721。erc1155 返回 422 no_coveragefrom_block 与 to_block 均必填。结果按 (block_number, log_index) 降序排列。direction(in、out 或 any,默认 any)按方向过滤,token 可选,用于限定单个合约。
GET /{chain}/tokens/{token}/transfers必填:erc20、erc721 或 erc1155from_block 与 to_block 可选。缺省 to_block 时默认取 as_of_block;显式传入高于它的 to_block 或 from_block 会直接返回硬 409 not_indexed_yet,没有 clamp 逃逸。

分页

两个端点都使用游标分页(keyset pagination):

  • limit 默认 50;超过 500 会被收敛为 500,0 或非整数返回 400 bad_request。
  • 返回 limit 条记录的页面可能包含 next_cursor,即使已经没有更多记录。继续使用返回的游标,直到该字段缺失;最后一次读取可能返回空的 data 数组。没有游标时,该字段整个省略,不会返回 null。
  • 把返回的 next_cursor 原样作为 cursor 传回即可取下一页。游标只对签发它的链、端点和查询参数有效。

覆盖范围与最终性

对 GET /{chain}/tokens/{token}/transfers,覆盖范围按所请求 standard 对应的代币转账数据集计算,而不是只看链的起点。当该数据集有记录的构建覆盖起点更晚时,其下界可能高于链的 coverage.from_block。完全早于该下界的窗口返回 422 no_coverage;起点早于该下界、或未提供 from_block 的窗口,会按数据集实际提供的范围返回,并标记 meta.coverage = "partial"。meta.as_of_block 是已完整写入的最新区块(写入水位),并不证明从下界到它之间的每个区块都已索引。地址端点仍然要求同时提供 from_block 与 to_block;不要把这条代币端点的下界规则套用到所有转账路由。哪些链提供该数据集见支持的链。

在从旧到新的历史回填中,已回填尾部与实时起点之间的缺口不会被检测到:完全落在这个缺口里的窗口仍可能返回 200 和空 data 数组。HTTP 成功、空结果、遍历完所有游标,或单单一个覆盖字段,都不能证明整段范围完整。请对照预期数据或自己的核对结果验证完整性。

每条转账数据包含 token、standard、from、to、block_number、block_timestamp、tx_hash、tx_index、log_index。ERC-20 额外有 amount;ERC-721 额外有 token_id;ERC-1155 额外有 operator、token_id、value、batch_index。

该选哪一个

典型任务更适合理由
最近几百个区块的事件eth_getLogs只要区间不超过该链的 max_logs_block_range,一次请求即可覆盖最近一段区块。
某地址的历史转账GET /{chain}/addresses/{address}/transfers按地址维度查询,支持 from_block/to_block 窗口、direction 与 token 过滤,并用游标翻页;结果提供截至 as_of_block 的数据。
某代币的全部转账GET /{chain}/tokens/{token}/transfers按代币合约维度查询,standard 覆盖 erc20、erc721、erc1155,窗口可选,用游标分页遍历数据集实际提供的范围。
实时监听新事件eth_subscribe(WebSocket 链)/ eth_getLogs 轮询支持 WebSocket 的链订阅新区块头或日志;其他链对最新区块区间轮询。

用 eth_getLogs 查询日志

export BLOCKVECTRA_API_KEY=rgw_your_api_key

# fromBlock / toBlock 缺省时为 latest。跟进新事件时可显式指定最近区间,
# 并让跨度不超过该链的 max_logs_block_range。
curl -s "https://api.blockvectra.com/v1/robinhood_mainnet" \
  -H 'Content-Type: application/json' \
  -H "x-api-key: $BLOCKVECTRA_API_KEY" \
  -d '{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "eth_getLogs",
    "params": [{
      "address": "0x1111111111111111111111111111111111111111",
      "fromBlock": "latest",
      "toBlock": "latest"
    }]
  }'

用 Data API 查询转账

export BLOCKVECTRA_API_KEY=rgw_your_api_key

# 这里 from_block / to_block 可选;缺省 to_block 时默认取 as_of_block。
curl -s "https://api.blockvectra.com/v1/data/robinhood_mainnet/tokens/0x1111111111111111111111111111111111111111/transfers?standard=erc20" \
  -H "x-api-key: $BLOCKVECTRA_API_KEY"

若要按地址查询,from_block 与 to_block 均为必填:

# clamp=true 会把过宽的窗口、或高于 as_of_block 的 to_block 截断,
# 而不是返回 409。
curl -s "https://api.blockvectra.com/v1/data/robinhood_mainnet/addresses/0x1111111111111111111111111111111111111111/transfers?standard=erc20&from_block=0&to_block=73000000&direction=any&clamp=true" \
  -H "x-api-key: $BLOCKVECTRA_API_KEY"

单次调用的 CU

每个方法都按其 CU 权重计费。下方权重从平台计划接口读取:

单次调用的 CU 权重

方法单次调用 CU
eth_getLogs30
data.address_transfers25
data.token_transfers25

当前价格与充值方式见定价页。

按区块窗口估算调用次数与 CU

区块窗口包含两端:N = to_block - from_block + 1。如果每次范围请求最多覆盖 S 个区块,一次成功遍历至少需要 ceil(N / S) 次请求。例如 10,000,000 个区块、每次 5 个区块是 2,000,000 次请求;每次 10,000 个区块是 1,000 次。这些只是算术示例,不代表任意链或 provider 的上限承诺。

失败与重试会增加请求,结果大小限制也一样。缩小窗口不自动等于更省:调用次数变多可能抵消窗口变窄,而 CU 按每次调用的权重计费。已索引的转账按结果分页,不按区块数分页,因此一次遍历可能需要更多页,包括最后可能出现的空页;不要用区块数直接推算页数。把上方每次调用的权重乘以预期计费调用次数来估算 CU,当前价格见定价页。

下一步

最后更新:

本页目录