ขีดจำกัดช่วงบล็อกของ eth_getLogs และการคิวรีแบบแบ่งส่วน
สำหรับ logs_range_too_large ให้อ่าน max_logs_block_range ของเชน แบ่งช่วงบล็อกแบบรวมจุดสิ้นสุดให้อยู่ภายในขีดจำกัดดังกล่าว และขยับต่อไปหลังจากที่ chunk ปัจจุบันทำงานสำเร็จแล้วเท่านั้น
คำตอบโดยตรง
คำขอ 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)] และขยับไปยังจุดสิ้นสุดของ chunk ก่อนหน้ารวมไปอีกหนึ่งหลังจากสำเร็จ
- ขั้นตอนแรก: รัน
curl -s "https://api.blockvectra.com/v1/chains"และอ่านmax_logs_block_range,methods.allowและmethods.denyของเชนเป้าหมาย - สำเร็จเมื่อ:
logs-minimal.mjsแสดงผลfromBlock,toBlockและอาร์เรย์resultของแต่ละ chunk ที่เสร็จสมบูรณ์จนถึง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;
}แต่ละบรรทัดที่แสดงผลคือ chunk ที่เสร็จสมบูรณ์ ข้อผิดพลาด HTTP หรือ JSON-RPC ใดๆ จะหยุดการทำงานของตัวอย่างโดยไม่ข้าม chunk ที่ล้มเหลว โปรดดูคำแนะนำเกี่ยวกับ batch และการจำกัดอัตราด้านล่างสำหรับการจัดการ 429
ขีดจำกัดช่วงบล็อกของ eth_getLogs
เมื่อเรียกใช้เมธอด JSON-RPC eth_getLogs ช่วงบล็อกของคำขอรายการเดียวจะคำนวณเป็น toBlock − fromBlock + 1 และไม่สามารถเกิน max_logs_block_range ที่ประกาศไว้ของเชนเป้าหมายได้
ขีดจำกัดนี้แตกต่างกันไปในแต่ละเชน พารามิเตอร์ของแต่ละเชนเผยแพร่ผ่าน endpoint สาธารณะ GET /v1/chains (เชนต่างๆ แสดงอยู่ใน เชนที่รองรับ) endpoint นี้ไม่ต้องยืนยันตัวตนและไม่มีการคิดค่าบริการ เมื่อพัฒนาแอปพลิเคชันฝั่งไคลเอนต์ ให้คิวรี endpoint นี้แบบไดนามิกขณะรันไทม์แทนที่จะฮาร์ดโค้ดขีดจำกัดช่วงบล็อกลงในโค้ดของคุณ
ฟิลด์ตัวกรอง fromBlock และ toBlock มีค่าเริ่มต้นเป็น latest เมื่อละเว้นหรือเป็น null
ขีดจำกัด eth_getLogs ของแต่ละเชน
นี่คือค่า max_logs_block_range ของแต่ละเชนที่เผยแพร่โดย GET /v1/chains ข้อความ "ไม่เผยแพร่" ไม่ได้หมายความว่าไม่จำกัด โปรดตรวจสอบ methods.allow และ methods.deny ก่อนเรียกใช้ด้วยเช่นกัน โดยที่ deny จะมีความสำคัญกว่า; ขีดจำกัดช่วงบล็อกจะแยกต่างหากจากขีดจำกัดจำนวนผลลัพธ์หรือระยะเวลาการคิวรี
| เชน | Slug เชน | max_logs_block_range (บล็อก) |
|---|---|---|
| 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 |
ข้อความข้อผิดพลาดทั่วไปตามตัวอักษร
แยกแยะช่วงบล็อก, จำนวนผลลัพธ์ และระยะเวลาการคิวรีออกจากกัน: รหัส 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> | ซอร์สโค้ด eth_getLogs ของ Erigon | <N> คือขีดจำกัดช่วงของโหนดนั้น; ให้ลดช่วงที่คิวรีลงก่อนส่งใหม่ |
query returns too many logs, narrow your filter: <N> | ซอร์สโค้ด eth_getLogs ของ Erigon | <N> คือขีดจำกัดผลลัพธ์ของโหนดนั้น; ให้ลดช่วงและจำกัด address และ topics ให้แคบลง บล็อกเดียวอาจยังคงต้องใช้ตัวกรองที่เจาะจงมากขึ้น |
ในเทมเพลตข้อความเหล่านี้ <N> จะถูกแทนที่ด้วยขีดจำกัดของ endpoint ข้อความจากบุคคลภายนอกจะอ้างอิงถึง endpoint และขีดจำกัดของตนเอง; สำนวนข้อความอาจแตกต่างกันตามเวอร์ชันของไคลเอนต์ สำหรับ 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)
ในคำขอแบบ batch ที่มีการเรียกหลายรายการ หากการเรียก eth_getLogs ใดเกินขีดจำกัดช่วงบล็อก รายการนั้นจะส่งกลับข้อผิดพลาด -32602 ข้างต้นและไม่คิดค่าบริการ
การดำเนินการคิวรีแบบแบ่งส่วน
ในการคิวรี log ในช่วงบล็อกขนาดใหญ่ อันดับแรกให้คิวรี max_logs_block_range ของเชนเป้าหมาย แบ่งช่วงเป้าหมายออกเป็น chunk ที่ต่อเนื่องกันขนาด [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"
}]
}'ข้อควรพิจารณาสำหรับคำขอแบบ Batch
หากคุณพิจารณาที่จะรวมการคิวรีแบบแบ่งส่วนหลายรายการไว้ในคำขอ JSON-RPC batch เดียว โปรดคำนึงถึงกฎของ batch และ burst capacity:
- ขีดจำกัดขนาดของ batch: คำขอแบบ batch รับได้ตั้งแต่ 1 ถึง 100 การเรียก การส่งมากกว่า 100 การเรียกจะถูกปฏิเสธด้วย HTTP 200 และรหัสข้อผิดพลาด
-32600 batch too large: max 100 calls(ไม่คิดค่าบริการ) - ความจุ burst ของคำขอเดี่ยว: หากผลรวมค่าน้ำหนัก CU ของการเรียกในหนึ่งคำขอเกินความจุ burst ของคีย์ (
burst_cu) คำขอจะถูกปฏิเสธด้วย HTTP 429-32022 request cost <N> CU exceeds burst capacity <M> CU(ไม่คิดค่าบริการ); ให้แยกออกเป็น batch ที่เล็กลง - ความจุใน bucket ไม่เพียงพอ: หากผลรวมของค่าน้ำหนักเต็มไม่เกินความจุ burst แต่ token bucket มีความจุที่ใช้ได้ไม่เพียงพอ บริการจะส่งกลับ HTTP 429 พร้อมรหัสข้อผิดพลาด
-32005 rate limit exceededและRetry-After; โปรดดู สิ่งที่ไม่คิดค่าบริการ: รหัสข้อผิดพลาดและกฎการเรียกเก็บเงิน สำหรับรายละเอียดการลองใหม่และการเรียกเก็บเงิน
ดังนั้น เมื่อดำเนินการคิวรี log ในปริมาณมาก จึงแนะนำให้ทำการคิวรีแบบแบ่งส่วนตามลำดับ; หากใช้ batch ให้รักษาจำนวนการเรียกต่อ batch ให้มีขนาดเล็กพอเพื่อให้ผลรวมของค่าน้ำหนักเต็มยังคงอยู่ภายในความจุ burst
คู่มือและกฎการเรียกเก็บเงินที่เกี่ยวข้อง
- ดู ข้อมูลอ้างอิงเมธอด eth_getLogs สำหรับพารามิเตอร์ตัวกรอง, ค่าส่งกลับ และค่าน้ำหนัก CU
- ดู ข้อมูลอ้างอิงข้อผิดพลาด logs_range_too_large สำหรับรายละเอียดข้อผิดพลาดและการดำเนินการที่แนะนำ
- สำหรับการเปรียบเทียบระหว่าง
eth_getLogsและ endpoints การโอนของ Data API (การโอนของแอดเดรสและการโอนโทเค็น) รวมถึงความแตกต่างด้านความครอบคลุมและความเป็นที่สิ้นสุด (finality) โปรดดู ข้อมูลโหนดล่าสุดเทียบกับประวัติที่ทำดัชนี: เมื่อใดควรใช้ eth_getLogs และเมื่อใดควรใช้ Transfers API - สำหรับรายละเอียดทั้งหมดเกี่ยวกับ compute unit (CU), การชำระบัญชีรายชั่วโมง และการตอบกลับข้อผิดพลาดที่ไม่คิดค่าบริการ โปรดดู สิ่งที่ไม่คิดค่าบริการ: รหัสข้อผิดพลาดและกฎการเรียกเก็บเงิน
ขั้นตอนถัดไป
- เลือกดูสารบบชุดข้อมูล เพื่อดูทุกชุดข้อมูลที่ BlockVectra ทำดัชนี
- ดูแผนบริการฟรีและราคา เพื่อตรวจสอบสิ่งที่บัญชีของคุณได้รับ
- เข้าสู่ระบบคอนโซล เพื่อสร้าง API key
อัปเดตล่าสุด:
Logs เทียบกับ Transfers API
เลือก eth_getLogs สำหรับ event log ของสัญญา หรือเลือก Token Transfers API สำหรับประวัติการโอน ERC-20 ที่ทำดัชนีไว้ เปรียบเทียบช่วงบล็อก, การแบ่งหน้า, ความครอบคลุม และความเป็นที่สิ้นสุด (finality)
การอ่านราคา CU
ตามอัตราที่เผยแพร่ในปัจจุบัน eth_call มีค่าใช้จ่าย 15 CU ต่อการเรียก หรือ $1.50 ต่อหนึ่งล้านการเรียกก่อนหักเครดิตฟรีที่มี โปรดดึงข้อมูล API แผนบริการปัจจุบันสำหรับการประมาณการปริมาณงานของคุณ