# eth_getLogs проти Token Transfers API: історія переказів ERC-20

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

Для історії гаманця або звірки переказів ERC-20 почніть із [Token Transfers API](https://blockvectra.com/en/data/transfers/). Використовуйте `eth_getLogs`, коли вам потрібні журнали подій контрактів. Розробники та AI-агенти можуть запитувати індексовані перекази адрес через той самий блокчейн-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`.

Виклик `eth_subscribe` через HTTP повертає `-32601 method not available`. У мережах, де `ws` має значення `true` у `/v1/chains`, метод `eth_subscribe` доступний через WebSocket (див. [Підтримувані мережі](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 pagination):

* `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 default to latest. Set an explicit recent range to follow
# new events, and keep its span within the chain's 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 are optional here; omitting to_block defaults to 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; // absent on the last page
} 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")  # absent on the last page
    if not cursor:
        break
```


Щоб натомість виконати запит за адресою, `from_block` та `to_block` є обов'язковими:

```bash
# clamp=true truncates a too-wide window, or a to_block above as_of_block,
# instead of returning 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.
