# eth_getLogs 與代幣轉帳 API：ERC-20 轉帳歷史查詢

> Source: https://docs.blockvectra.com/zh-hant/guides/logs-vs-transfers/

對於錢包歷史記錄或 ERC-20 轉帳對帳，請從[代幣轉帳 API](https://blockvectra.com/en/data/transfers/) 開始。當你需要合約事件日誌時，請使用 `eth_getLogs`。開發者與 AI Agent 可透過相同的區塊鏈資料 API 查詢已索引的地址轉帳記錄。[錢包資產指南](https://docs.blockvectra.com/en/guides/wallet-assets/)結合了代幣餘額、轉帳歷史記錄與中繼資料；[Data API 參考](https://docs.blockvectra.com/en/api/data/)定義了請求參數與回應結構定義。

## 這篇指南協助你完成的任務

* [查詢合約事件日誌](#querying-logs-with-eth_getlogs)：在有界區塊範圍內透過帶驗證的 RPC 進行監控或日誌回填。
* [查詢已索引的 ERC-20 轉帳歷史記錄](#querying-transfers-with-the-data-api)：透過區塊鏈資料 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` 讀取（鏈清單見[支援的鏈](https://docs.blockvectra.com/en/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`。

透過 HTTP 呼叫 `eth_subscribe` 會回傳 `-32601 method not available`。在 `/v1/chains` 中 `ws` 為 `true` 的鏈上，可透過 WebSocket 使用 `eth_subscribe`（參見[支援的鏈](https://docs.blockvectra.com/en/chains/)）；否則，請在最新區塊上輪詢 `eth_getLogs`。

## Data API 轉帳端點提供的內容

這兩個端點需要不同的參數：

| 端點                                           | `standard`                                           | 區塊範圍                                                                                                                                              |
| -------------------------------------------- | ---------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
| `GET /{chain}/addresses/{address}/transfers` | 必填：`erc20` 或 `erc721`。`erc1155` 回傳 `422 no_coverage` | `from_block` 與 `to_block` 均為必填。結果按 `(block_number, log_index)` 降序排列。`direction`（`in`、`out` 或 `any`；預設 `any`）按方向過濾，`token` 可選填以將結果限制為單一合約。         |
| `GET /{chain}/tokens/{token}/transfers`      | 必填：`erc20`、`erc721` 或 `erc1155`                      | `from_block` 與 `to_block` 為選填。省略 `to_block` 時預設為 `as_of_block`；顯式傳入高於它的 `to_block` 或 `from_block` 會直接回傳硬錯誤 `409 not_indexed_yet`，沒有 `clamp` 規避機制。 |

### 分頁

兩個端點均採用鍵集分頁（keyset-paginated）：

* `limit` 預設為 50；高於 500 的值被限制為 500，且 `0` 或非整數回傳 `400 bad_request`。
* 僅在存在另一頁時才出現 `next_cursor`。在最後一頁上，該鍵完全不存在，絕非 `null`。
* 將回傳的值原樣傳回為 `cursor` 以取得下一頁。游標僅對簽發它的鏈、端點與查詢參數有效。

### 覆蓋範圍與最終性

Data API 轉帳從每條鏈的 `coverage.from_block` 到 `meta.as_of_block` 索引歷史代幣轉帳。有關提供該功能的鏈，請參閱[支援的鏈](https://docs.blockvectra.com/en/chains/)。

每個轉帳項目包含 `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`         | 涵蓋 `erc20`、`erc721` 與 `erc1155` 的代幣合約範圍查詢，具備選填範圍與游標分頁以取得完整結果集。                            |
| 即時監聽新事件     | `eth_subscribe`（WebSocket 鏈）/ `eth_getLogs`（輪詢） | 在支援的鏈上透過 WebSocket 訂閱新區塊頭或日誌，或輪詢近期區塊範圍。                                                   |

## 使用 eth\_getLogs 查詢日誌

**cURL**

```bash
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"
    }]
  }'
```


  **TypeScript**

```ts
const res = await fetch("https://api.blockvectra.com/v1/robinhood_mainnet", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "x-api-key": process.env.BLOCKVECTRA_API_KEY!,
  },
  body: JSON.stringify({
    jsonrpc: "2.0",
    id: 1,
    method: "eth_getLogs",
    params: [{
      address: "0x1111111111111111111111111111111111111111",
      fromBlock: "latest",
      toBlock: "latest",
    }],
  }),
});

const { result } = await res.json();
console.log(result);

// npx tsx example.mts
```


  **Python**

```python
import os
import requests

res = requests.post(
    "https://api.blockvectra.com/v1/robinhood_mainnet",
    headers={
        "Content-Type": "application/json",
        "x-api-key": os.environ["BLOCKVECTRA_API_KEY"],
    },
    json={
        "jsonrpc": "2.0",
        "id": 1,
        "method": "eth_getLogs",
        "params": [{
            "address": "0x1111111111111111111111111111111111111111",
            "fromBlock": "latest",
            "toBlock": "latest",
        }],
    },
)
res.raise_for_status()
print(res.json())
```


## 使用 Data API 查詢轉帳

**cURL**

```bash
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"
```


  **TypeScript**

```ts
let cursor: string | undefined;

do {
  const url = new URL(
    "https://api.blockvectra.com/v1/data/robinhood_mainnet/tokens/0x1111111111111111111111111111111111111111/transfers",
  );
  url.searchParams.set("standard", "erc20");
  if (cursor) url.searchParams.set("cursor", cursor);

  const res = await fetch(url, {
    headers: { "x-api-key": process.env.BLOCKVECTRA_API_KEY! },
  });
  const body = await res.json();
  console.log(body.data);
  cursor = body.next_cursor; // 最後一頁不存在該欄位
} while (cursor);

// npx tsx example.mts
```


  **Python**

```python
import os
import requests

url = "https://api.blockvectra.com/v1/data/robinhood_mainnet/tokens/0x1111111111111111111111111111111111111111/transfers"
cursor = None

while True:
    params = {"standard": "erc20"}
    if cursor:
        params["cursor"] = cursor
    res = requests.get(
        url,
        params=params,
        headers={"x-api-key": os.environ["BLOCKVECTRA_API_KEY"]},
    )
    res.raise_for_status()
    body = res.json()
    print(body["data"])
    cursor = body.get("next_cursor")  # 最後一頁不存在該欄位
    if not cursor:
        break
```


若改為按地址查詢，則 `from_block` 與 `to_block` 均為必填：

```bash
# 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 權重計費。下方權重讀取自平台方案 API：

**單次呼叫的 CU 權重**

| 方法 | 單次呼叫 CU |
| --- | --- |
| `eth_getLogs` | 30 |
| `data.address_transfers` | 25 |
| `data.token_transfers` | 25 |

有關目前的價格與儲值選項，請參閱[定價頁面](https://blockvectra.com/en/pricing/)。

## 下一步

* [瀏覽資料集目錄](https://blockvectra.com/en/data/)，查看 BlockVectra 索引的全部資料集。
* [查看免費方案與定價](https://blockvectra.com/en/pricing/#free)，確認你的帳戶包含的內容。
* [登入控制台](https://console.blockvectra.com/login/?next=%2Fkeys%2F)建立 API key。
