Ліміт діапазону блоків eth_getLogs та запити частинами

Для logs_range_too_large прочитайте max_logs_block_range мережі, розділіть інклюзивний інтервал блоків у межах цього ліміту та пересувайтеся вперед лише після успішного завершення поточної частини.

Пряма відповідь

Один запит eth_getLogs обмежений параметром max_logs_block_range цільової мережі з GET /v1/chains (для HyperEVM це 1,000 блоків), враховуючи toBlock − fromBlock + 1 блоків. Перевищення ліміту повертає HTTP 200, JSON-RPC -32602 та error.data.reason: logs_range_too_large із retryable: false (див. каталог помилок). Розділіть інтервал на [from, min(from + max − 1, end)] і після успішного виконання пересувайтеся до кінця попередньої частини плюс один.

  • Перший крок: виконайте curl -s "https://api.blockvectra.com/v1/chains" і прочитайте max_logs_block_range, methods.allow та methods.deny цільової мережі.
  • Готово, коли: logs-minimal.mjs виводить fromBlock, toBlock та масив result кожної завершеної частини аж до обраного вами TO_BLOCK без помилок HTTP чи JSON-RPC.

Параметри мережі та варіанти доступу.

Збережіть це як logs-minimal.mjs, встановіть BLOCKVECTRA_API_KEY, адресу контракту LOG_ADDRESS та підтверджене вікно блоків у FROM_BLOCK і TO_BLOCK, після чого запустіть node logs-minimal.mjs у Node.js 24 або новішої версії. Виберіть мережу за допомогою CHAIN; типово використовується robinhood_mainnet.

const { BLOCKVECTRA_API_KEY: key, LOG_ADDRESS: address, FROM_BLOCK, TO_BLOCK } = process.env;
if (!key || !/^0x[0-9a-f]{40}$/i.test(address ?? '')) throw new Error('Set BLOCKVECTRA_API_KEY and LOG_ADDRESS');
if (![FROM_BLOCK, TO_BLOCK].every(value => /^(0x[0-9a-f]+|[0-9]+)$/i.test(value ?? ''))) {
  throw new Error('Set FROM_BLOCK and TO_BLOCK to nonnegative block numbers');
}
const start = BigInt(FROM_BLOCK), end = BigInt(TO_BLOCK);
if (start > end) throw new Error('FROM_BLOCK must not exceed TO_BLOCK');
const chainSlug = process.env.CHAIN ?? 'robinhood_mainnet';
const chainsUrl = 'https://api.blockvectra.com/v1/chains';
const catalogResponse = await fetch(chainsUrl, { signal: AbortSignal.timeout(15_000) });
if (!catalogResponse.ok) throw new Error(`Chains HTTP ${catalogResponse.status}`);
const catalog = await catalogResponse.json();
const chain = catalog.chains.find(item => item.chain === chainSlug);
if (!chain || !Number.isSafeInteger(chain.max_logs_block_range) || chain.max_logs_block_range <= 0) {
  throw new Error('Missing or invalid max_logs_block_range');
}
const matches = pattern => pattern.endsWith('*') ? 'eth_getLogs'.startsWith(pattern.slice(0, -1)) : pattern === 'eth_getLogs';
if (!chain.methods?.allow?.some(matches) || chain.methods?.deny?.some(matches)) {
  throw new Error('eth_getLogs is unavailable on this chain');
}
const max = BigInt(chain.max_logs_block_range);
const rpcUrl = new URL(`./${chainSlug}`, chainsUrl).href;
const hex = value => `0x${value.toString(16)}`;
for (let from = start; from <= end;) {
  const to = from + max - 1n < end ? from + max - 1n : end;
  const response = await fetch(rpcUrl, {
    method: 'POST', redirect: 'error', signal: AbortSignal.timeout(15_000),
    headers: { 'Content-Type': 'application/json', 'x-api-key': key },
    body: JSON.stringify({ jsonrpc: '2.0', id: 1, method: 'eth_getLogs',
      params: [{ address, fromBlock: hex(from), toBlock: hex(to) }] }),
  });
  const body = await response.json();
  if (!response.ok || body.error || !Array.isArray(body.result)) {
    throw new Error(`RPC HTTP ${response.status}: ${JSON.stringify(body.error ?? 'Invalid result')}`);
  }
  console.log(JSON.stringify({ fromBlock: hex(from), toBlock: hex(to), result: body.result }));
  from = to + 1n;
}

Кожен рядок виводу — це завершена частина. Будь-яка помилка HTTP або JSON-RPC зупиняє виконання прикладу, не пропускаючи невдалу частину. Нижче див. рекомендації щодо пакетних запитів та обмеження швидкості для обробки 429.

Ліміти діапазону блоків eth_getLogs

Під час виклику методу JSON-RPC eth_getLogs діапазон блоків одного запиту обчислюється як toBlock − fromBlock + 1 і не може перевищувати опубліковане значення max_logs_block_range для цільової мережі.

Цей ліміт різниться залежно від мережі. Параметри для кожної мережі публікуються через загальнодоступний ендпоінт GET /v1/chains (мережі наведено на сторінці Підтримувані мережі). Цей ендпоінт не потребує автентифікації та не тарифікується. Під час розробки клієнтських застосунків динамічно запитуйте цей ендпоінт під час виконання замість жорсткого кодування лімітів діапазону блоків у вашому коді.

Якщо поля фільтра fromBlock та toBlock пропущено або вони мають значення null, типово використовується latest.

Ліміти eth_getLogs за мережами

Це значення max_logs_block_range для кожної мережі, опубліковані в GET /v1/chains. «Не опубліковано» не означає безлімітно. Також перед викликом перевіряйте methods.allow та methods.deny, причому deny має пріоритет; ліміт діапазону блоків існує окремо від лімітів кількості результатів або тривалості запиту.

МережаСлаг мережіmax_logs_block_range (блоків)
Arbitrum Onearb_mainnet1,000
Basebase_mainnet1,000
BNB Smart Chainbsc_mainnet1,000
Ethereumeth_mainnet1,000
Ethereum Sepoliaeth_sepolia1,000
HyperEVMhyperevm_mainnet1,000
Polygonpolygon_mainnet1,000
Robinhood Chainrobinhood_mainnet1,000
Robinhood Chain Testnetrobinhood_testnet1,000

Поширені повідомлення про помилки дослівно

Розрізняйте діапазон блоків, кількість результатів і тривалість запиту: один і той самий код JSON-RPC може описувати різні збої.

Текст / ідентифікатор помилкиДжерелоЩо робити
eth_getLogs block range too large: max <N> blocks; -32602; logs_range_too_largeКаталог помилок BlockVectra<N> — це max_logs_block_range мережі; зменшіть діапазон перед повторним надсиланням. Повторна спроба без змін не допоможе.
query block range exceeds server limit, narrow your filter: <N>Вихідний код Erigon eth_getLogs<N> — це ліміт діапазону цього вузла; зменшіть запитуваний інтервал перед повторним надсиланням.
query returns too many logs, narrow your filter: <N>Вихідний код Erigon eth_getLogs<N> — це ліміт результатів цього вузла; зменшіть інтервал та звузьте address і topics. Для одного блоку все одно можуть знадобитися точніші фільтри.

У цих шаблонах повідомлень <N> замінюється лімітом ендпоінта. Повідомлення сторонніх сервісів стосуються їхніх власних ендпоінтів та лімітів; формулювання можуть відрізнятися залежно від версії клієнта. Для BlockVectra використовуйте /v1/chains та error.data.reason.

Перевищення ліміту діапазону блоків

Коли діапазон блоків одного запиту toBlock − fromBlock + 1 перевищує max_logs_block_range мережі, запит відхиляється з HTTP 200 та помилкою JSON-RPC:

  • Код помилки: -32602
  • Повідомлення про помилку: eth_getLogs block range too large: max <N> blocks
  • Статус тарифікації: не тарифікується.

Приклад запиту

Цей запит перевищує ліміт лише в тому випадку, якщо його діапазон блоків більший за поточний max_logs_block_range цільової мережі:

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "eth_getLogs",
  "params": [
    {
      "fromBlock": "0x45a2409",
      "toBlock": "0x45a27f1"
    }
  ]
}

Приклад відповіді

Приклад відповідної відповіді з помилкою:

{
  "jsonrpc": "2.0",
  "id": 1,
  "error": {
    "code": -32602,
    "message": "eth_getLogs block range too large: max <N> blocks"
  }
}

Де <N> — це значення max_logs_block_range цільової мережі (опубліковане через GET /v1/chains).

У пакетному запиті, що містить кілька викликів, якщо виклик eth_getLogs перевищує ліміт діапазону блоків, саме цей елемент повертає наведену вище помилку -32602 і не тарифікується.

Виконання запитів частинами

Щоб отримати журнали за великий інтервал блоків, спочатку запитайте max_logs_block_range цільової мережі, розділіть цільовий інтервал на суміжні частини [from, from + max - 1] та надсилайте послідовні запити, об'єднуючи результати.

У наступних прикладах використовується robinhood_mainnet для демонстрації запитів частинами:

export BLOCKVECTRA_API_KEY="rgw_your_api_key"

# 1. Read max_logs_block_range from the public chains endpoint (unauthenticated, unbilled)
curl -s "https://api.blockvectra.com/v1/chains"

# 2. Make a single compliant request within the chain's max_logs_block_range (toBlock - fromBlock + 1)
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": "0x45a2409",
      "toBlock": "0x45a246c"
    }]
  }'

Особливості пакетних запитів

Якщо ви розглядаєте можливість об'єднання кількох запитів частинами в один пакетний запит JSON-RPC, пам'ятайте про правила розміру пакета та пікової пропускної здатності (burst capacity):

  • Ліміт розміру пакета: пакетні запити приймають від 1 до 100 викликів. Надсилання понад 100 викликів відхиляється з HTTP 200 та кодом помилки -32600 batch too large: max 100 calls (не тарифікується).
  • Пікова пропускна здатність одного запиту: якщо сумарна вага CU викликів в одному запиті перевищує пікову пропускну здатність ключа (burst_cu), запит відхиляється з HTTP 429 -32022 request cost <N> CU exceeds burst capacity <M> CU (не тарифікується); розділіть його на менші пакети.
  • Недостатня місткість кошика (bucket capacity): якщо сума повних ваг не перевищує пікову пропускну здатність, але в токен-кошику недостатньо доступної місткості, сервіс повертає HTTP 429 із кодом помилки -32005 rate limit exceeded та заголовком Retry-After; див. Що не тарифікується: коди помилок та правила тарифікації щодо повторних спроб і деталей тарифікації.

Таким чином, під час виконання масштабних запитів журналів рекомендуються послідовні запити частинами; якщо ви використовуєте пакетні запити, тримайте кількість викликів у пакеті достатньо малою, щоб сума повних ваг залишалася в межах пікової пропускної здатності.

Наступні кроки

Востаннє оновлено:

На цій сторінці