# Giới hạn phạm vi khối eth_getLogs và truy vấn theo phân đoạn

> Source: https://docs.blockvectra.com/vi/guides/getlogs-block-range/

## Câu trả lời trực tiếp

Một yêu cầu `eth_getLogs` đơn lẻ bị giới hạn ở `max_logs_block_range` của chuỗi mục tiêu từ [GET /v1/chains](https://api.blockvectra.com/v1/chains) (đối với HyperEVM, 1,000 khối), tính theo `toBlock − fromBlock + 1` khối. Vượt quá giới hạn này trả về HTTP 200, JSON-RPC `-32602` và `error.data.reason: logs_range_too_large`, với `retryable: false` (xem [danh mục lỗi](https://docs.blockvectra.com/en/errors/#logs_range_too_large)). Hãy chia nhỏ khoảng thành `[from, min(from + max − 1, end)]` và tiến lên sau điểm cuối của phân đoạn trước cộng một sau khi thành công.

Lưu mã này thành `logs-minimal.mjs`, đặt `BLOCKVECTRA_API_KEY`, địa chỉ hợp đồng `LOG_ADDRESS`, và một cửa sổ khối đã xác nhận trong `FROM_BLOCK` và `TO_BLOCK`, sau đó chạy `node logs-minimal.mjs` với Node.js 24 trở lên. Chọn một chuỗi bằng `CHAIN`; mặc định là `robinhood_mainnet`.

```js
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;
}
```

Mỗi dòng output là một phân đoạn đã hoàn thành. Bất kỳ lỗi HTTP hoặc JSON-RPC nào cũng sẽ dừng ví dụ mà không bỏ qua phân đoạn bị lỗi. Xem hướng dẫn về batch và giới hạn tốc độ bên dưới để xử lý lỗi 429.

## Giới hạn phạm vi khối eth\_getLogs

Khi gọi phương thức JSON-RPC `eth_getLogs`, khoảng khối của một yêu cầu đơn lẻ được tính là `toBlock − fromBlock + 1` và không thể vượt quá `max_logs_block_range` đã công bố của chuỗi mục tiêu.

Giới hạn này thay đổi tùy theo từng chuỗi. Các tham số theo từng chuỗi được công bố thông qua endpoint công khai `GET /v1/chains` (các chuỗi được liệt kê trên trang [Chuỗi được hỗ trợ](https://docs.blockvectra.com/en/chains/)). Endpoint này không yêu cầu xác thực và không tính phí. Khi phát triển ứng dụng client, hãy truy vấn endpoint này một cách động khi chạy thay vì hardcode các giới hạn phạm vi khối vào mã nguồn của bạn.

Các trường bộ lọc `fromBlock` và `toBlock` mặc định là `latest` khi bị bỏ qua hoặc là `null`.

## Giới hạn eth\_getLogs theo chuỗi

Đây là các giá trị `max_logs_block_range` của từng chuỗi được công bố bởi [GET /v1/chains](https://api.blockvectra.com/v1/chains). "Không công bố" không có nghĩa là không giới hạn. Đồng thời hãy kiểm tra `methods.allow` và `methods.deny` trước khi gọi, trong đó deny được ưu tiên; giới hạn khoảng khối tách biệt với số lượng kết quả hoặc giới hạn thời lượng truy vấn.

| Chuỗi | Slug chuỗi | max_logs_block_range (khối) |
| --- | --- | --- |
| Arbitrum One | `arb_mainnet` | 1,000 |
| Base | `base_mainnet` | 1,000 |
| BNB Smart Chain | `bsc_mainnet` | 1,000 |
| Ethereum | `eth_mainnet` | 1,000 |
| Ethereum Sepolia | `eth_sepolia` | 1,000 |
| HyperEVM | `hyperevm_mainnet` | 1,000 |
| Polygon | `polygon_mainnet` | 1,000 |
| Robinhood Chain | `robinhood_mainnet` | 1,000 |
| Robinhood Chain Testnet | `robinhood_testnet` | 1,000 |

## Thông báo lỗi thường gặp, nguyên văn

Phân biệt khoảng khối, số lượng kết quả và thời lượng truy vấn: cùng một mã JSON-RPC có thể mô tả các sự cố khác nhau.

| Nội dung lỗi / mã định danh                                                           | Nguồn                                                                                                                                                    | Cách xử lý                                                                                                                                       |
| ------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ |
| `eth_getLogs block range too large: max <N> blocks`; `-32602`; `logs_range_too_large` | [Danh mục lỗi BlockVectra](https://docs.blockvectra.com/en/errors/#logs_range_too_large)                                                                                             | `<N>` là `max_logs_block_range` của chuỗi; giảm khoảng khối trước khi gửi lại. Thử lại mà không thay đổi sẽ không giải quyết được vấn đề.        |
| `query block range exceeds server limit, narrow your filter: <N>`                     | [Mã nguồn Erigon eth\_getLogs](https://github.com/erigontech/erigon/blob/9e603d74f60c21ca793a03a7ce373de19aa3fdc7/rpc/jsonrpc/eth_receipts.go#L343-L347) | `<N>` là giới hạn phạm vi của nút đó; giảm khoảng truy vấn trước khi gửi lại.                                                                    |
| `query returns too many logs, narrow your filter: <N>`                                | [Mã nguồn Erigon eth\_getLogs](https://github.com/erigontech/erigon/blob/9e603d74f60c21ca793a03a7ce373de19aa3fdc7/rpc/jsonrpc/eth_receipts.go#L439-L442) | `<N>` là giới hạn kết quả của nút đó; giảm khoảng khối và thu hẹp `address` cùng `topics`. Một khối đơn lẻ vẫn có thể cần các bộ lọc cụ thể hơn. |

Trong các mẫu thông báo này, `<N>` được thay thế bằng giới hạn của endpoint. Thông báo từ bên thứ ba đề cập đến các endpoint và giới hạn riêng của họ; cách diễn đạt có thể khác nhau tùy theo phiên bản client. Đối với BlockVectra, hãy sử dụng `/v1/chains` và `error.data.reason`.

## Vượt quá giới hạn khoảng khối

Khi khoảng khối `toBlock − fromBlock + 1` của một yêu cầu đơn lẻ vượt quá `max_logs_block_range` của chuỗi, yêu cầu sẽ bị từ chối với HTTP 200 và một lỗi JSON-RPC:

* **Mã lỗi**: `-32602`
* **Thông báo lỗi**: `eth_getLogs block range too large: max <N> blocks`
* **Trạng thái thanh toán**: Không tính phí.

### Yêu cầu mẫu

Yêu cầu này chỉ vượt quá giới hạn nếu khoảng khối của nó lớn hơn `max_logs_block_range` hiện tại của chuỗi mục tiêu:

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

### Phản hồi mẫu

Ví dụ về phản hồi lỗi tương ứng:

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

Trong đó `<N>` là `max_logs_block_range` của chuỗi mục tiêu (được công bố qua `GET /v1/chains`).

Trong một yêu cầu batch chứa nhiều lệnh gọi, nếu một lệnh gọi `eth_getLogs` vượt quá giới hạn khoảng khối, mục cụ thể đó sẽ trả về lỗi `-32602` ở trên và không bị tính phí.

## Thực hiện truy vấn theo phân đoạn

Để truy vấn log qua một khoảng khối lớn, trước tiên hãy truy vấn `max_logs_block_range` của chuỗi mục tiêu, chia khoảng mục tiêu thành các phân đoạn liền kề gồm `[from, from + max - 1]`, và gửi các yêu cầu tuần tự đồng thời tổng hợp các kết quả.

Các ví dụ sau sử dụng `robinhood_mainnet` để minh họa các truy vấn theo phân đoạn:

**cURL**

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


  **TypeScript**

```ts
const CHAIN = "robinhood_mainnet";
const RPC_ENDPOINT = "https://api.blockvectra.com/v1/robinhood_mainnet";

// 1. Fetch max_logs_block_range from the public GET /v1/chains endpoint (unauthenticated, unbilled)
const chainsUrl = new URL("/v1/chains", RPC_ENDPOINT);
const chainsRes = await fetch(chainsUrl);
const { chains } = (await chainsRes.json()) as {
  chains: Array<{ chain: string; max_logs_block_range: number }>;
};

const targetChain = chains.find((c) => c.chain === CHAIN);
if (!targetChain) {
  throw new Error(`Chain ${CHAIN} not found`);
}

const maxRange = targetChain.max_logs_block_range;

// 2. Query chunks sequentially over [from, from + max - 1] and aggregate results (both endpoints inclusive)
const fromBlock = 0x45a2409;
const toBlock = 0x45a2900;

const allLogs: unknown[] = [];
let cur = fromBlock;

while (cur <= toBlock) {
  const chunkEnd = Math.min(cur + maxRange - 1, toBlock);

  const res = await fetch(RPC_ENDPOINT, {
    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: "0x" + cur.toString(16),
          toBlock: "0x" + chunkEnd.toString(16),
        },
      ],
    }),
  });

  const body = (await res.json()) as {
    result?: unknown[];
    error?: { code: number; message: string };
  };

  if (body.error) {
    throw new Error(`eth_getLogs error ${body.error.code}: ${body.error.message}`);
  }

  if (body.result) {
    allLogs.push(...body.result);
  }

  cur = chunkEnd + 1;
}

console.log(`Fetched ${allLogs.length} logs across blocks`);

// npx tsx example.mts
```


  **Python**

```python
import os
from urllib.parse import urljoin
import requests

CHAIN = "robinhood_mainnet"
RPC_ENDPOINT = "https://api.blockvectra.com/v1/robinhood_mainnet"

# 1. Fetch max_logs_block_range from the public GET /v1/chains endpoint (unauthenticated, unbilled)
chains_url = urljoin(RPC_ENDPOINT, "/v1/chains")
chains_res = requests.get(chains_url)
chains_res.raise_for_status()

chains = chains_res.json().get("chains", [])
target_chain = next((c for c in chains if c["chain"] == CHAIN), None)
if not target_chain:
    raise RuntimeError(f"Chain {CHAIN} not found")

max_range = target_chain["max_logs_block_range"]

# 2. Query chunks sequentially over [from, from + max - 1] and aggregate results (both endpoints inclusive)
from_block = 0x45a2409
to_block = 0x45a2900

all_logs: list = []
cur = from_block

while cur <= to_block:
    chunk_end = min(cur + max_range - 1, to_block)

    res = requests.post(
        RPC_ENDPOINT,
        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": hex(cur),
                    "toBlock": hex(chunk_end),
                }
            ],
        },
    )
    res.raise_for_status()
    body = res.json()

    if "error" in body:
        err = body["error"]
        raise RuntimeError(f"eth_getLogs error {err.get('code')}: {err.get('message')}")

    all_logs.extend(body.get("result", []))
    cur = chunk_end + 1

print(f"Fetched {len(all_logs)} logs across blocks")
```


## Những lưu ý khi gửi yêu cầu batch

Nếu bạn cân nhắc việc gom nhiều truy vấn theo phân đoạn vào một yêu cầu batch JSON-RPC đơn lẻ, hãy ghi nhớ các quy tắc về kích thước batch và dung lượng burst:

* **Giới hạn kích thước batch**: Yêu cầu batch chấp nhận từ 1 đến 100 lệnh gọi. Gửi nhiều hơn 100 lệnh gọi sẽ bị từ chối với HTTP 200 và mã lỗi `-32600 batch too large: max 100 calls` (không tính phí).
* **Dung lượng burst cho một yêu cầu đơn lẻ**: Nếu tổng trọng số CU của các lệnh gọi trong một yêu cầu vượt quá dung lượng burst của key (`burst_cu`), yêu cầu sẽ bị từ chối với HTTP 429 `-32022 request cost <N> CU exceeds burst capacity <M> CU` (không tính phí); hãy chia nhỏ nó thành các batch nhỏ hơn.
* **Dung lượng bucket không đủ**: Nếu tổng trọng số đầy đủ không vượt quá dung lượng burst nhưng bucket token thiếu dung lượng khả dụng cần thiết, dịch vụ sẽ trả về HTTP 429 với mã lỗi `-32005 rate limit exceeded` và `Retry-After`; xem [Những gì không bị tính phí: mã lỗi và quy tắc thanh toán](https://docs.blockvectra.com/en/guides/billing-rules/) để biết chi tiết về việc thử lại và tính phí.

Do đó, khi thực hiện các truy vấn log quy mô lớn, chúng tôi khuyến nghị sử dụng các truy vấn theo phân đoạn tuần tự; nếu dùng batch, hãy giữ số lượng lệnh gọi trên mỗi batch đủ nhỏ để tổng các trọng số đầy đủ vẫn nằm trong dung lượng burst.

## Các hướng dẫn liên quan và quy tắc thanh toán

* Xem [tài liệu tham khảo phương thức eth\_getLogs](https://docs.blockvectra.com/en/api/json-rpc/methods/eth_getLogs/) để biết các tham số bộ lọc, giá trị trả về và trọng số CU.
* Xem [tài liệu tham khảo lỗi logs\_range\_too\_large](https://docs.blockvectra.com/en/errors/#logs_range_too_large) để biết chi tiết lỗi và các hành động được khuyến nghị.
* Để so sánh giữa `eth_getLogs` và các endpoint transfers của Data API (chuyển giao của địa chỉ và chuyển giao token), bao gồm sự khác biệt về độ bao phủ và tính bất biến sau cùng, hãy xem [Dữ liệu nút gần đây so với lịch sử đã lập chỉ mục: khi nào nên dùng eth\_getLogs và khi nào nên dùng transfers API](https://docs.blockvectra.com/en/guides/logs-vs-transfers/).
* Để biết đầy đủ chi tiết về Compute Unit (CU), quyết toán hàng giờ và các phản hồi lỗi không bị tính phí, hãy xem [Những gì không bị tính phí: mã lỗi và quy tắc thanh toán](https://docs.blockvectra.com/en/guides/billing-rules/).

## Các bước tiếp theo

* [Khám phá danh mục bộ dữ liệu](https://blockvectra.com/en/data/) để xem mọi bộ dữ liệu mà BlockVectra lập chỉ mục.
* [Xem gói miễn phí và bảng giá](https://blockvectra.com/en/pricing/#free) để kiểm tra những gì tài khoản của bạn bao gồm.
* [Đăng nhập vào console](https://console.blockvectra.com/login/?next=%2Fkeys%2F) để tạo API key.
