ขีดจำกัดอัตรา HyperEVM RPC และการดึงข้อมูล log ย้อนหลัง

บน BlockVectra คำขอ eth_getLogs ที่มีการยืนยันตัวตนของ HyperEVM ครอบคลุมสูงสุด 1,000 บล็อก โดยนับรวมจุดสิ้นสุดทั้งสองฝั่ง; ให้แบ่งช่วงเวลาที่ยาวขึ้นและบันทึกบล็อกล่าสุดที่เสร็จสมบูรณ์เพื่อกลับมาดำเนินการต่อ

คำตอบโดยตรง

HyperEVM public RPC อย่างเป็นทางการที่เป็นค่าเริ่มต้นอนุญาต 50 บล็อกต่อหนึ่งคิวรี eth_getLogs (แหล่งข้อมูล: เอกสาร JSON-RPC ทางการของ Hyperliquid) บน BlockVectra คำขอ eth_getLogs ที่มีการยืนยันตัวตนครอบคลุมสูงสุด 1,000 บล็อกต่อหนึ่งคิวรี (hyperevm_mainnet.max_logs_block_range จาก GET /v1/chains) โดยนับรวมจุดสิ้นสุดทั้งสองฝั่ง ช่วงที่กว้างกว่านี้จะส่งกลับ HTTP 200, JSON-RPC -32602 และ logs_range_too_large พร้อม retryable: false (ดู สารบัญข้อผิดพลาด); ให้แบ่งเป็น [from, min(from + max − 1, end)] บันทึกเคอร์เซอร์ของคุณ และขยับไปยังจุดสิ้นสุดบวกหนึ่งหลังจากสำเร็จเพื่อดำเนินการต่อ ขีดจำกัดอัตราต่อ IP ของ public RPC อย่างเป็นทางการและขีดจำกัดของคีย์ของ BlockVectra ได้รับการอธิบายแยกต่างหากใน ขีดจำกัดอัตราของ public RPC อย่างเป็นทางการและ 429 และพารามิเตอร์การให้บริการด้านล่าง

  • ขั้นตอนแรก: อ่านบล็อกล่าสุดโดยไม่ต้องใช้ API key โดยใช้คำสั่ง curl ด้านล่าง
  • สำเร็จเมื่อ: สคริปต์ดึงข้อมูลย้อนหลังแสดงผล fromBlock, toBlock และอาร์เรย์ result สำหรับทุก chunk ในช่วงที่คุณเลือก; อาร์เรย์ว่างหมายถึงไม่มี log ที่ตรงกันใน chunk นั้น

พารามิเตอร์ของเชนและตัวเลือกการเข้าถึง

งานที่คู่มือนี้ช่วยให้คุณทำสำเร็จ

งาน 3 ขั้นตอน: ดึงข้อมูล log ของ HyperEVM ย้อนหลังในช่วงที่จำกัดขอบเขต

อ่านบล็อกล่าสุดโดยไม่ต้องใช้คีย์, สร้างคีย์, จากนั้นดึง event log สำหรับสัญญาในช่วงบล็อกที่จำกัด

เลือกสัญญาและช่วงบล็อกที่คุณต้องการ งานนี้ครอบคลุมช่วงที่จำกัดนั้น; ไม่ได้รับประกันประวัติสัญญาที่สมบูรณ์ทั้งหมด

1. อ่านบล็อกล่าสุดโดยไม่ต้องใช้ API key

curl -sS "https://api.blockvectra.com/v1/hyperevm_mainnet/public" \
  -H 'Content-Type: application/json' \
  -d '{"jsonrpc":"2.0","id":1,"method":"eth_blockNumber","params":[]}'

result ของ JSON-RPC คือหมายเลขบล็อกล่าสุดในรูปแบบเลขฐานสิบหก นี่คือ public.url ของ HyperEVM ที่เผยแพร่โดย GET /v1/chains เมธอด public.methods ของ endpoint สาธารณะไม่ได้รวม eth_getLogs; ขั้นตอนที่ 3 จำเป็นต้องใช้คีย์

2. สร้าง API key

สร้างคีย์สำหรับการดึงข้อมูลย้อนหลังนี้ สร้างคีย์และบันทึก secret ที่แสดงในกล่องโต้ตอบไว้สำหรับใช้งานกับ hyperevm_mainnet

สำหรับ AI Agent ที่ใช้ HTTP โดยไม่มีเบราว์เซอร์ ให้ทำตาม คู่มือการลงทะเบียนแบบโปรแกรม ส่ง ref ที่ถูกต้องของ URL คู่มือใน JSON body ของ POST /auth/siwe/login แทนที่จะเป็น docs-signup ของตัวอย่าง; ละเว้นได้หากไม่มี อย่าขอให้ผู้ใช้แปะคีย์ลงในแชท

3. ดึงข้อมูล log ย้อนหลังด้วยคีย์ของคุณ

เทมเพลตเริ่มต้นฉบับสมบูรณ์: blockvectra/hyperevm-backfill

บันทึกสคริปต์ต่อไปนี้เป็น hyperevm-task.ts ซึ่งรันด้วย Node.js 24 ขึ้นไป โดยไม่ต้องมีแพ็กเกจเพิ่มเติม ตั้งค่า BLOCKVECTRA_API_KEY เป็นคีย์ที่คุณบันทึกไว้ และ LOG_ADDRESS เป็นแอดเดรสของสัญญาที่ส่งเหตุการณ์ที่คุณต้องการตรวจสอบ; เก็บรักษาคีย์ไว้บนเซิร์ฟเวอร์หรือในเทอร์มินัลภายในเครื่องของคุณ

export BLOCKVECTRA_API_KEY='replace-with-your-key'
export LOG_ADDRESS='replace-with-contract-address'
node hyperevm-task.ts

ตามค่าเริ่มต้น สคริปต์จะดึงบล็อกล่าสุดจำนวน max_logs_block_range บล็อก หรือน้อยกว่านั้นหากอยู่ใกล้กับบล็อกเริ่มต้น (genesis) สคริปต์จะอ่านขีดจำกัดนั้นจาก /v1/chains ขณะรันไทม์ หากต้องการเลือกช่วงที่จำกัดอื่น ให้ตั้งค่าทั้ง FROM_BLOCK และ TO_BLOCK เป็นหมายเลขบล็อกแบบฐานสิบหรือฐานสิบหกขึ้นต้นด้วย 0x ก่อนรัน ช่วงที่ใหญ่ขึ้นจะถูกแบ่งออกเป็น chunk ต่อเนื่องกัน โดยแต่ละ chunk จะมีขนาดไม่เกินขีดจำกัดที่ประกาศไว้

const apiKey = process.env.BLOCKVECTRA_API_KEY;
const address = process.env.LOG_ADDRESS;
if (!apiKey || apiKey === "replace-with-your-key") throw new Error("Set BLOCKVECTRA_API_KEY");
if (!address || !/^0x[0-9a-f]{40}$/i.test(address)) throw new Error("Set LOG_ADDRESS to a contract address");

const fromBlock = process.env.FROM_BLOCK;
const toBlock = process.env.TO_BLOCK;
if ((fromBlock !== undefined || toBlock !== undefined) && (!fromBlock || !toBlock)) {
  throw new Error("Set both FROM_BLOCK and TO_BLOCK");
}

const chainsUrl = "https://api.blockvectra.com/v1/chains";
const rpcUrl = new URL("./hyperevm_mainnet", chainsUrl).href;
async function readJson(url: string) {
  const response = await fetch(url, { signal: AbortSignal.timeout(15_000) });
  if (!response.ok) throw new Error(`Metadata HTTP ${response.status}`);
  return response.json();
}
const catalog = await readJson(chainsUrl);
const chain = catalog.chains.find((item: { chain: string }) => item.chain === "hyperevm_mainnet");
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");
}
if (!chain.methods.allow.includes("eth_getLogs") || chain.methods.deny.includes("eth_getLogs")) {
  throw new Error("eth_getLogs is unavailable on this chain");
}
const maxRange = BigInt(chain.max_logs_block_range);
const plans = await readJson("https://console-api.blockvectra.com/v1/plans");
function weight(method: string): bigint {
  const row = plans.method_weights.find((item: { method: string }) => item.method === method);
  if (!row || !Number.isSafeInteger(row.cu_weight) || row.cu_weight <= 0) {
    throw new Error(`Missing or invalid CU weight for ${method}`);
  }
  return BigInt(row.cu_weight);
}
const headWeight = weight("eth_blockNumber");
const logsWeight = weight("eth_getLogs");

type RpcBody = {
  result?: unknown;
  error?: { code: number; data?: { retryable?: boolean } };
};
async function rpc(method: string, params: unknown[]): Promise<unknown> {
  for (let attempt = 0; attempt < 4; attempt++) {
    const response = await fetch(rpcUrl, {
      method: "POST",
      redirect: "error",
      headers: { "Content-Type": "application/json", "x-api-key": apiKey! },
      body: JSON.stringify({ jsonrpc: "2.0", id: 1, method, params }),
      signal: AbortSignal.timeout(15_000),
    });
    const body = await response.json() as RpcBody;
    if (response.ok && !body.error && body.result !== undefined) return body.result;
    if (body.error?.data?.retryable !== true || attempt === 3) {
      throw new Error(`RPC failed: HTTP ${response.status}, code ${body.error?.code ?? "unknown"}`);
    }
    const retryAfter = response.headers.get("Retry-After");
    const delay = retryAfter === null ? 0 : /^\d+$/.test(retryAfter)
      ? Number(retryAfter) * 1000 : Date.parse(retryAfter) - Date.now();
    if (delay > 30_000) throw new Error("Retry-After exceeds 30 seconds; rerun later");
    const backoff = 1000 * 2 ** attempt + Math.random() * 250;
    await new Promise((resolve) => setTimeout(resolve, Math.max(backoff, Number.isFinite(delay) ? delay : 0)));
  }
  throw new Error("Retry limit reached");
}
function block(value: string): bigint {
  if (!/^(0x[0-9a-f]+|[0-9]+)$/i.test(value)) throw new Error("Invalid block number");
  return BigInt(value);
}
const head = await rpc("eth_blockNumber", []);
if (typeof head !== "string" || !/^0x[0-9a-f]+$/i.test(head)) throw new Error("Invalid chain head");
const latest = block(head);
const end = toBlock ? block(toBlock) : latest;
const start = fromBlock ? block(fromBlock)
  : end >= maxRange - 1n ? end - maxRange + 1n : 0n;
if (start > end || end > latest) throw new Error("Require 0 <= FROM_BLOCK <= TO_BLOCK <= latest");
const chunks = (end - start + maxRange) / maxRange;
console.error(`Window ${start}..${end}; chunks=${chunks}; estimated CU=${headWeight + chunks * logsWeight}`);

const hex = (value: bigint) => `0x${value.toString(16)}`;
for (let from = start; from <= end; from += maxRange) {
  const to = from + maxRange - 1n < end ? from + maxRange - 1n : end;
  const result = await rpc("eth_getLogs", [{ address, fromBlock: hex(from), toBlock: hex(to) }]);
  if (!Array.isArray(result)) throw new Error("Expected eth_getLogs result array");
  console.log(JSON.stringify({ fromBlock: hex(from), toBlock: hex(to), result }));
}

คำขอจะทำงานตามลำดับ ข้อผิดพลาด JSON-RPC จะได้รับการลองใหม่ก็ต่อเมื่อ error.data.retryable เป็น true โดยลองใหม่ได้สูงสุดสี่ครั้งต่อหนึ่งคำขอ พร้อม exponential backoff และ jitter รวมถึงรองรับ Retry-After ในรูปแบบวินาทีหรือวันที่ HTTP การรอที่นานกว่า 30 วินาทีจะหยุดการทำงานของสคริปต์เพื่อให้คุณสามารถรันใหม่ในภายหลัง ความล้มเหลวของเครือข่าย, การหมดเวลา, การตอบกลับที่ผิดรูปแบบ และข้อผิดพลาดที่ไม่สามารถลองใหม่ได้จะหยุดทำงานทันที; สคริปต์จะออกจากการทำงานแบบไม่สำเร็จแทนที่จะรายงานว่าการดึงข้อมูลย้อนหลังเสร็จสมบูรณ์

แต่ละบรรทัดที่แสดงผลบน standard output ประกอบด้วย fromBlock, toBlock และอาร์เรย์ result ของแต่ละ chunk โดยที่ result: [] หมายถึงไม่มี log ที่ตรงกันใน chunk นั้น ให้อ่านฟิลด์เหล่านี้ในแต่ละ log:

ฟิลด์ความหมาย
addressสัญญาที่ส่งเหตุการณ์ออกมา
blockNumber, blockHashบล็อกที่มี log; หมายเลขอยู่ในรูปแบบเลขฐานสิบหก
transactionHash, transactionIndex, logIndexตำแหน่งธุรกรรมและ log; ดัชนีอยู่ในรูปแบบเลขฐานสิบหก
topics, dataอาร์กิวเมนต์เหตุการณ์ที่ทำดัชนีและอาร์กิวเมนต์ที่ไม่ทำดัชนีซึ่งเข้ารหัสตาม ABI; ถอดรหัสด้วย ABI ของสัญญา
removedระบุว่า log ถูกลบออกเนื่องจากการจัดระเบียบเชนใหม่ (chain reorganization) หรือไม่

บล็อกล่าสุดไม่ใช่เครื่องหมายบอกความเป็นที่สิ้นสุด (finality) หากคุณต้องการช่วงประวัติที่เสถียร ให้เลือก TO_BLOCK ที่ได้รับการยืนยันแล้วของแอปพลิเคชันของคุณ และจัดการกับการจัดระเบียบเชนใหม่ (reorg)

สำหรับช่วงที่มีขนาด B = TO_BLOCK − FROM_BLOCK + 1 บล็อกและขีดจำกัดที่ประกาศไว้ L จำนวน chunk จะเป็น N = ceil(B / L) ให้อ่าน method_weights[].cu_weight สำหรับ eth_getLogs และ eth_blockNumber จาก GET /v1/plans สคริปต์จะพิมพ์ค่าประมาณการไปยัง standard error: N × weight(eth_getLogs) + weight(eth_blockNumber) รวมถึงการค้นหา head ที่ใช้คีย์ด้วย ซึ่งไม่รวมการเรียกเพิ่มเติมและการลองใหม่ที่คิดค่าบริการ; โปรดดู กฎการเรียกเก็บเงิน สำหรับการชำระบัญชี CU ขึ้นอยู่กับจำนวนการเรียก ไม่ใช่จำนวน log ที่ส่งกลับมา

การส่งมอบเหตุการณ์: ใช้การโพลล์ HTTP แบบแบ่งส่วนด้านล่าง หรือส่งเหตุการณ์ของแอดเดรสที่ติดตามไปยังตัวรับ HTTPS ด้วย webhook push โดย GET /v1/push/chains จะแสดงรายการเชนที่รองรับ และการตั้งค่าการยืนยัน; ยืนยันตัวตนด้วย x-api-key ลายเซ็น webhook, การขจัดข้อมูลซ้ำ และการเล่นซ้ำมีอธิบายอยู่ในคู่มือนั้น ทั้งนี้ Webhook push จะแยกต่างหากจากการสมัครสมาชิก WebSocket (ws และ subscriptions ใน /v1/chains)

เชื่อมต่อด้วย viem หรือ ethers

พารามิเตอร์ / เอนด์พอยต์ค่า / เทมเพลตการยืนยันตัวตน
Chain ID (EIP-155)999—
JSON-RPC (คีย์ในพาธ)POST https://api.blockvectra.com/v1/hyperevm_mainnet/{api_key}API key ในพาธ URL
JSON-RPC (คีย์ในส่วนหัว)POST https://api.blockvectra.com/v1/hyperevm_mainnetส่วนหัว x-api-key: {api_key}
ที่อยู่หลัก Data APIGET https://api.blockvectra.com/v1/data/hyperevm_mainnet/…ส่วนหัว x-api-key: {api_key}
สถานะสาธารณะGET https://api.blockvectra.com/v1/statusไม่ต้องยืนยันตัวตน (สาธารณะ)

นักพัฒนาและ AI Agent สามารถใช้การตั้งค่าฝั่งเซิร์ฟเวอร์เดียวกันได้ ใช้ Node.js 24 ขึ้นไป, viem 2 หรือ ethers 6 และเริ่มต้นด้วยการอ่านแบบสาธารณะ ตั้งค่า BLOCKVECTRA_API_KEY อย่างปลอดภัยในสภาพแวดล้อมสำหรับเมธอดที่ใช้คีย์ เก็บรักษาคีย์และ RPC URL ที่มีคีย์ให้พ้นจากโค้ดของเบราว์เซอร์, ล็อก และการควบคุมเวอร์ชัน

บันทึกไฟล์นี้เป็น network.mjs ซึ่งจะอ่าน chain_id และนโยบายเมธอดจาก GET /v1/chains สำหรับการอ่านแบบไม่ใช้คีย์ ให้ใช้ public.url ของสารบบและเฉพาะเมธอดที่ระบุไว้ใน public.methods; ความพร้อมใช้งานของ HTTP สาธารณะไม่ได้หมายความว่าสามารถเข้าถึง WebSocket ได้

const chainSlug = process.env.BLOCKVECTRA_CHAIN ?? 'hyperevm_mainnet';
const key = process.env.BLOCKVECTRA_API_KEY;
const catalogUrl = 'https://api.blockvectra.com/v1/chains';
const response = await fetch(catalogUrl, { signal: AbortSignal.timeout(15_000) });
if (!response.ok) throw new Error(`Chains HTTP ${response.status}`);
const catalog = await response.json();
export const chainInfo = catalog.chains.find(item => item.chain === chainSlug);
if (!chainInfo || !Number.isSafeInteger(chainInfo.chain_id) || chainInfo.chain_id <= 0) {
  throw new Error('Missing chain or chain_id');
}
export function allows(method) {
  const matches = pattern => pattern.endsWith('*')
    ? method.startsWith(pattern.slice(0, -1)) : pattern === method;
  if (!key) return (chainInfo.public?.methods ?? []).some(matches);
  return (chainInfo.methods?.allow ?? []).some(matches)
    && !(chainInfo.methods?.deny ?? []).some(matches);
}
if (!allows('eth_chainId')) throw new Error('eth_chainId is unavailable');
export const rpcUrl = key
  ? new URL(`./${chainSlug}/${encodeURIComponent(key)}`, catalogUrl).href
  : chainInfo.public?.url;
if (!rpcUrl) throw new Error('Public RPC is unavailable; set BLOCKVECTRA_API_KEY');

บันทึกเป็น viem-client.mjs, ติดตั้งด้วย npm install viem@2 แล้วรัน node viem-client.mjs

import { createPublicClient, defineChain, http } from 'viem';
import { chainInfo, rpcUrl } from './network.mjs';

export const chain = defineChain({
  id: chainInfo.chain_id,
  name: chainInfo.name,
  nativeCurrency: { name: 'HYPE', symbol: 'HYPE', decimals: 18 },
  rpcUrls: { default: { http: [rpcUrl] } },
});
export const client = createPublicClient({ chain, transport: http(rpcUrl) });
if (await client.getChainId() !== chain.id) throw new Error('RPC chain ID mismatch');
console.error(await client.getBlockNumber());

สำหรับ ethers ให้บันทึกเป็น ethers-client.mjs, ติดตั้งด้วย npm install ethers@6 แล้วรัน node ethers-client.mjs

import { JsonRpcProvider } from 'ethers';
import { chainInfo, rpcUrl } from './network.mjs';

const provider = new JsonRpcProvider(rpcUrl, chainInfo.chain_id, { batchMaxCount: 1 });
const network = await provider.getNetwork();
if (network.chainId !== BigInt(chainInfo.chain_id)) throw new Error('RPC chain ID mismatch');
console.log(await provider.getBlockNumber());
provider.destroy();

ดีพลอยด้วย Foundry หรือ Hardhat

สารบบ hyperevm_mainnet ปัจจุบันมี ws=false และไม่มี eth_sendRawTransaction ใน methods.allow ใช้ BlockVectra สำหรับการอ่าน; การดีพลอยจำเป็นต้องใช้ RPC ที่รองรับการบรอดแคสต์ ตั้งค่า DEPLOY_RPC_URL เป็น URL HTTP ที่ผ่านการยืนยันตัวตนของผู้ให้บริการรายนั้น อย่าสันนิษฐานว่าผู้ให้บริการรายอื่นจะมีขีดจำกัดเมธอดหรือช่วงของ log เหมือนกับ BlockVectra โปรดตรวจสอบ chain ID ที่เลือกก่อนลงนาม

: "${DEPLOY_RPC_URL:?Set a broadcasting RPC URL}"
export RPC_URL="$DEPLOY_RPC_URL"
export CHAIN_ID="$(node --input-type=module -e "import { chainInfo } from './network.mjs'; console.log(chainInfo.chain_id)")"

ดำเนินการต่อด้วย บทเรียนการดีพลอยด้วย Foundry หรือ Hardhat ที่ใช้ร่วมกัน เติม EVM HYPE ให้กับผู้ดีพลอยและตรวจสอบข้อกำหนด dual-block ด้านล่างก่อนทำการดีพลอยขนาดใหญ่

HYPE, บล็อกขนาดเล็ก และการดีพลอยขนาดใหญ่

คู่มือเครือข่ายอย่างเป็นทางการของ HyperEVM ระบุว่า HYPE เป็น gas โดยมีทศนิยม 18 ตำแหน่ง (เข้าถึงเมื่อ: 2026-10-07) ตรวจสอบให้แน่ใจว่าผู้ดีพลอยถือครอง HYPE บน HyperEVM; ยอดคงเหลือบน HyperCore เพียงอย่างเดียวไม่ใช่ยอด gas ของ EVM โปรดทำตามคำแนะนำการโอนแบบ native ตามลิงก์เมื่อย้ายเงินทุน

คู่มือ dual-block อธิบายถึงบล็อกขนาดเล็กที่รวดเร็วและบล็อกขนาดใหญ่ที่ช้ากว่าสำหรับธุรกรรมขนาดใหญ่ (เข้าถึงเมื่อ: 2026-10-07) ให้ประเมิน gas สำหรับการดีพลอยก่อน สำหรับการดีพลอยที่เกินงบประมาณบล็อกขนาดเล็ก ผู้ดีพลอยจะต้องเป็นผู้ใช้ HyperCore อยู่แล้ว และลงนามใน Core action {"type":"evmUserModify","usingBigBlocks":true}; การตั้งค่า gas limit ของธุรกรรมให้ใหญ่ขึ้นเพียงอย่างเดียวไม่ได้เป็นการเลือกบล็อกขนาดใหญ่ ให้กู้คืน usingBigBlocks=false ในภายหลังเพื่อกลับสู่บล็อกขนาดเล็ก

บนผู้ให้บริการที่รองรับ ให้ใช้ eth_usingBigBlocks เพื่อตรวจสอบโหมดแอดเดรส และใช้ eth_bigBlockGasPrice สำหรับ base fee ของบล็อกขนาดใหญ่ เอกสารอ้างอิง JSON-RPC อย่างเป็นทางการ มีเอกสารอธิบายเมธอดเหล่านี้ (เข้าถึงเมื่อ: 2026-10-07) ตรวจสอบเมธอดของผู้ให้บริการที่เลือก; ใช้ /v1/chains สำหรับ BlockVectra การดีพลอยขั้นต่ำด้านบนกำหนดเป้าหมายไปยังสัญญาขนาดเล็กและไม่ได้เปลี่ยนโหมดบัญชี Core

ข้อมูล HyperCore และ HyperEVM

EVM RPC ให้บริการสัญญา, ใบเสร็จ (receipt) และ log ส่วนข้อมูลการเทรดและการดำเนินการของ HyperCore จะใช้ Core API สัญญาอัจฉริยะสามารถอ่านสถานะ Core ผ่าน precompile และส่งการดำเนินการผ่าน CoreWriter; ใช้ คู่มือการโต้ตอบอย่างเป็นทางการ เมื่อผสานรวมเส้นทางเหล่านี้ (เข้าถึงเมื่อ: 2026-10-07) ทั้งนี้ EVM log ไม่สามารถแทนที่การคิวรี order book หรือโพซิชันของ Core ได้

ธุรกรรมระบบ (system transaction) ของ HyperEVM (เช่น การโอนจาก HyperCore ไปยัง HyperEVM) จะไม่รวมอยู่ในการตอบกลับ eth_getBlockByNumber มาตรฐาน และให้บริการแยกต่างหากโดย RPC อย่างเป็นทางการผ่าน eth_getSystemTxsByBlockNumber และ eth_getSystemTxsByBlockHash (ดู เอกสาร JSON-RPC อย่างเป็นทางการ, เข้าถึงเมื่อ: 2026-10-07) ในปัจจุบัน ข้อมูลบล็อก, ธุรกรรม และ Data API ของ HyperEVM บน BlockVectra ยังไม่รวมธุรกรรมระบบ; ให้ใช้สองเมธอด RPC ทางการนี้โดยตรงเมื่อต้องการข้อมูลธุรกรรมระบบ

การจัดการข้อผิดพลาดทางการ 10055

คู่มือ HyperEVM อย่างเป็นทางการ กำหนดว่า 10055 เป็นข้อผิดพลาดบริเวณรอยต่อ Core/EVM รวมถึงความล้มเหลวเกี่ยวกับ nonce, เงินทุนไม่เพียงพอ, แฮชซ้ำ และค่าธรรมเนียมการแทนที่ต่ำเกินไป (underpriced-replacement) (เข้าถึงเมื่อ: 2026-10-07) ตรวจสอบข้อความจาก RPC ที่บรอดแคสต์ก่อนตัดสินใจว่าจะกู้คืนอย่างไร:

  • Nonce: เปรียบเทียบ eth_getTransactionCount กับธุรกรรมที่รอดำเนินการของคุณ; จัดลำดับการส่งจากผู้ดีพลอยรายเดียวและกระทบยอด nonce ถัดไป
  • Funds: ตรวจสอบยอดคงเหลือ EVM HYPE ของผู้ดีพลอยเทียบกับมูลค่ารวมกับค่า gas
  • Duplicate hash: ค้นหาธุรกรรมและใบเสร็จที่มีอยู่ก่อนส่งธุรกรรมอื่น
  • Replacement fee: ตรวจสอบ nonce และค่าธรรมเนียมที่มีอยู่ จากนั้นใช้นโยบายการแทนที่ของผู้บรอดแคสต์; การส่งไบต์เดิมซ้ำไม่ได้เป็นการเพิ่มค่าธรรมเนียม

10055 เพียงอย่างเดียวไม่เพียงพอที่จะสุ่มลองใหม่โดยไม่ตรวจสอบ โปรดอ่านข้อผิดพลาดและคำแนะนำในการกู้คืนแยกต่างหากใน ข้อมูลอ้างอิงข้อผิดพลาด BlockVectra

ขีดจำกัดอัตราของ public RPC อย่างเป็นทางการและ 429

เอกสารการจำกัดอัตราอย่างเป็นทางการ ของ Hyperliquid ระบุไว้สูงสุด 100 คำขอ EVM JSON-RPC ต่อนาทีต่อ IP สำหรับ rpc.hyperliquid.xyz/evm ส่วน เอกสาร JSON-RPC ยังจำกัด eth_getLogs ไว้ที่ 50 บล็อกต่อหนึ่งคิวรีและไม่เกิน 4 topics เข้าถึงเมื่อ: 2026-10-07

เมื่อพบ HTTP 429 ให้หยุดส่งคำขอชั่วคราวและปฏิบัติตาม Retry-After ก่อนเป็นอันดับแรก (หน่วยเป็นวินาทีหรือวันที่ HTTP) หากไม่มี ให้ใช้ exponential backoff ร่วมกับ jitter และจำกัดจำนวนครั้งในการลองใหม่ โดยลองใหม่กับ chunk เดิมที่ยังไม่เสร็จสมบูรณ์ ลดการทำงานพร้อมกันและความถี่ในการโพลล์ และแบ่งการคิวรี log ออกเป็น chunk ให้อยู่ภายในขีดจำกัดของ endpoint การแบ่ง chunk เพียงอย่างเดียวไม่ได้ขจัดขีดจำกัดอัตราออกไป; ไคลเอนต์ที่ใช้ IP ร่วมกันจำเป็นต้องประสานอัตราคำขอของตน

สำหรับ endpoint ที่ใช้คีย์ของ BlockVectra ให้อ่าน max_logs_block_range, methods.allow และ methods.deny ของ hyperevm_mainnet จาก GET /v1/chains แทนที่จะนำช่วงบล็อกหรือขีดจำกัดคำขอต่อนาทีของ public RPC ทางการมาใช้ อัตราคำขอจะขึ้นอยู่กับ cu_per_sec, burst_cu ของคีย์ และขีดจำกัดการเรียกของแผนบริการฟรีแยกต่างหาก (ดูหัวข้อถัดไป) เมื่อพบ 429 ให้ตรวจสอบ error.data.reason และ retryable; request_exceeds_burst จำเป็นต้องส่งคำขอที่มีขนาดเล็กลงแทนที่จะลองใหม่แบบไม่เปลี่ยนแปลงค่าพร้อม backoff

พารามิเตอร์และกฎการให้บริการของ BlockVectra

BlockVectra ให้บริการ HyperEVM mainnet ผ่าน endpoints แบบ JSON-RPC และ REST Data API:

  1. พารามิเตอร์ของเชนและขีดจำกัดของ log: จาก GET /v1/chains สำหรับ hyperevm_mainnet:
    • ตัวระบุเชน (Slug): hyperevm_mainnet, Chain ID 999
    • max_logs_block_range: กำกับดูแลโดยฟิลด์ max_logs_block_range จาก GET /v1/chains คำขอ eth_getLogs รายการเดียวสามารถครอบคลุมบล็อกได้สูงสุดไม่เกินจำนวนนี้ (toBlock − fromBlock + 1) การส่งคำขอเกินกว่าช่วงนี้จะส่งกลับ HTTP 200 พร้อมรหัสข้อผิดพลาด JSON-RPC -32602 (eth_getLogs block range too large: max <N> blocks) ซึ่งไม่คิดค่าบริการ
    • state_window_blocks: กำกับดูแลโดยฟิลด์ state_window_blocks จาก GET /v1/chains การเรียกที่อ่านสถานะ (เช่น eth_call และ eth_getBalance) จะอยู่ภายใต้กรอบเวลาการเก็บรักษาที่ระบุไว้ในฟิลด์นี้ (เมื่อเป็น null สถานะเต็มจะถูกเก็บรักษาไว้โดยไม่มีขีดจำกัดแบบ rolling window)
    • นโยบายเมธอด: กำกับดูแลโดย methods.allow และ methods.deny เมธอด EVM มาตรฐาน (eth_blockNumber, eth_getLogs, eth_call, eth_getBalance, eth_getBlockByNumber, eth_getTransactionReceipt ฯลฯ) ได้รับอนุญาต; ส่วนเมธอดตัวกรองและการสมัครสมาชิก (eth_subscribe, eth_unsubscribe, eth_newFilter, eth_newBlockFilter) จะถูกปฏิเสธ โดยส่งกลับ -32601 (ไม่คิดค่าบริการ)
  2. ขีดจำกัดอัตราของระดับฟรีและการอัปเกรด: จาก GET /v1/plans:
    • free.max_calls_per_sec: สูงสุด 25 คำขอต่อวินาที แชร์ร่วมกันระหว่างทุกคีย์ในบัญชี ทุกเชน และ Data API
    • ขีดจำกัดเริ่มต้นของคีย์: แต่ละ API key มี bucket ของ CU (อัตราเติม cu_per_sec, ความจุ burst_cu — ค่าเริ่มต้นคือ 400 CU/s และ burst 1,600 CU) เมธอดต่างๆ จะถูกวัดปริมาณตามค่าน้ำหนัก Compute Unit (CU)
    • การอัปเกรดขีดจำกัด: หลังจากการเติมเงิน ขีดจำกัดคำขอต่อวินาทีของทั้งบัญชีจะถูกยกเลิก; แต่ละคีย์ยังคงอยู่ภายใต้อัตราและขีดจำกัด burst ของ Compute Unit (CU) สำหรับอัตราและหน่วยการเรียกเก็บเงินปัจจุบัน โปรดดู หน้าราคา

การดึงข้อมูล log ย้อนหลัง: eth_getLogs แบบแบ่งส่วนและตรรกะการลองใหม่

เมื่อทำการคิวรี log ย้อนหลัง ช่วงเวลาที่กว้างจะต้องถูกแบ่งออกเป็น chunk ต่อเนื่องกันซึ่งถูกจำกัดโดย max_logs_block_range ของเชนเป้าหมาย กลยุทธ์การลองใหม่ของไคลเอนต์ควรตรวจสอบฟิลด์ retryable ภายในการตอบกลับข้อผิดพลาด

การประเมิน retryable ในการตอบกลับข้อผิดพลาด

บน BlockVectra อ็อบเจกต์ข้อผิดพลาด JSON-RPC จะมีเพย์โหลด error.data ซึ่งประกอบด้วย reason, docs_url และ retryable (บูลีน):

  • retryable: true: สภาวะชั่วคราว รวมถึงบริการโอเวอร์โหลด (overloaded), ขีดจำกัดคำขอต่อวินาทีของแผนบริการฟรี (free_plan_call_limit), การซิงก์โหนด (node_syncing) หรืออัปสตรีมไม่พร้อมใช้งาน (upstream_unavailable) ไคลเอนต์ควรปฏิบัติตามส่วนหัว Retry-After เมื่อปรากฏ หรือใช้ exponential backoff ร่วมกับ jitter
  • retryable: false: ข้อผิดพลาดที่ไม่ใช่สภาวะชั่วคราว เช่น ช่วงบล็อกเกินขีดจำกัด (-32602 / logs_range_too_large), พารามิเตอร์ไม่ถูกต้อง (invalid_params), API key ขาดหายไป (missing_api_key) หรือคำขอเกินความจุ burst (-32022 / request_exceeds_burst) การลองใหม่โดยไม่ปรับพารามิเตอร์จะไม่ประสบความสำเร็จ

ด้านล่างนี้คือการตอบกลับที่ได้รับเมื่อไม่ได้ระบุ API key:

{
  "jsonrpc": "2.0",
  "id": null,
  "error": {
    "code": -32024,
    "message": "missing API key: send it in the request path (/v1/{chain}/<api_key>) or in the x-api-key header",
    "data": {
      "reason": "missing_api_key",
      "docs_url": "https://docs.blockvectra.com/en/errors/#missing_api_key",
      "retryable": false
    }
  }
}

การใช้ Data API endpoints แทนการสแกน getLogs ปริมาณมาก

เมื่อแอปพลิเคชันติดตามประวัติธุรกรรมหรือการเคลื่อนไหวของโทเค็นสำหรับแอดเดรสที่ระบุ การสแกนผ่าน eth_getLogs จะต้องส่งคำขอแบบแบ่งส่วนตามลำดับซึ่งถูกจำกัดโดย max_logs_block_range และต้องแยกวิเคราะห์ raw Transfer event logs

BlockVectra Data API มี REST endpoints ที่ทำดัชนีไว้ล่วงหน้าสำหรับ hyperevm_mainnet ซึ่งรองรับช่วงสูงสุดถึง 100,000 บล็อกพร้อมการแบ่งหน้าด้วยเคอร์เซอร์:

  1. ธุรกรรมของแอดเดรส: GET /v1/data/hyperevm_mainnet/addresses/{address}/transactions
    • พารามิเตอร์: from_block (จำเป็น), to_block (จำเป็น), direction (ไม่บังคับ: from, to, any, ค่าเริ่มต้น any), clamp (สตริงบูลีนไม่บังคับ, ค่าเริ่มต้น false; เมื่อตั้งค่าเป็น true ช่วงที่เกิน 100,000 บล็อกหรือสูงกว่า as_of_block จะถูกตัดทอนแทนที่จะส่งกลับ 409), limit (ไม่บังคับ, สูงสุด 500), cursor (โทเค็นการแบ่งหน้า)
  2. การโอนโทเค็นของแอดเดรส: GET /v1/data/hyperevm_mainnet/addresses/{address}/transfers
    • พารามิเตอร์: standard (จำเป็น: erc20 หรือ erc721; erc1155 ไม่สามารถคิวรีตามแอดเดรสได้และจะส่งกลับ 422 no_coverage), token (ตัวกรองสัญญาโทเค็นไม่บังคับ), from_block (จำเป็น), to_block (จำเป็น), direction (ไม่บังคับ: in, out, any), clamp (ไม่บังคับ), limit, cursor

โครงสร้างการตอบกลับ

การตอบกลับใช้ schema มาตรฐาน:

  • data: อาร์เรย์ของระเบียน ธุรกรรมประกอบด้วย hash, block_number, block_timestamp, from, to, value, tx_index, gas_limit, gas_used และ status การโอนประกอบด้วย token, standard, from, to, block_number, block_timestamp, tx_hash, tx_index และ log_index (amount สำหรับ ERC-20, token_id สำหรับ ERC-721)
  • next_cursor: โทเค็นการแบ่งหน้าแบบทึบแสง (opaque) ที่ส่งกลับมาเมื่อมีระเบียนถัดไป (ไม่มีในหน้าสุดท้าย ไม่ใช่ null)
  • meta: ข้อมูลเมทาดาตาประกอบด้วย chain, chain_slug, chain_external_id, as_of_block, safe_block, finalized_block, coverage (full หรือ partial) และ refreshed_at

ตัวอย่างโค้ด: การคิวรี Data API

export BLOCKVECTRA_API_KEY="rgw_your_api_key"

# 1. Query address transaction history (clamp=true prevents 409 errors)
curl -s "https://api.blockvectra.com/v1/data/hyperevm_mainnet/addresses/0x2222222222222222222222222222222222222222/transactions?from_block=0&to_block=50000&clamp=true" \
  -H "x-api-key: $BLOCKVECTRA_API_KEY"

# 2. Query address ERC-20 token transfers
curl -s "https://api.blockvectra.com/v1/data/hyperevm_mainnet/addresses/0x2222222222222222222222222222222222222222/transfers?standard=erc20&from_block=0&to_block=50000&clamp=true" \
  -H "x-api-key: $BLOCKVECTRA_API_KEY"

การติดตามแบบเรียลไทม์: การโพลล์บล็อกใหม่

สำหรับการรับส่งข้อมูลแบบ HTTP ให้ติดตามบล็อกด้วยการโพลล์และดึง event log ใน chunk ที่ต่อเนื่องกันภายใน max_logs_block_range เลือก WebSocket เฉพาะเมื่อ /v1/chains รายงาน ws=true และมีรายการ subscriptions ที่ต้องการ สำหรับการส่งข้อมูลไปยังตัวรับ HTTPS ให้ใช้ webhook push

หากต้องการทดสอบสัญญา Hello ที่ดีพลอยแล้ว ให้ตั้งค่า LOG_ADDRESS เป็นแอดเดรสของสัญญา ส่ง ping() ผ่าน RPC ที่บรอดแคสต์ จากนั้นดึงข้อมูลบล็อกของใบเสร็จย้อนหลังด้วยสคริปต์การดึงข้อมูลย้อนหลังในหน้านี้ ดำเนินการต่อจาก chunk ล่าสุดที่เสร็จสมบูรณ์สำหรับเหตุการณ์ใหม่

cast send "$CONTRACT_ADDRESS" "ping()" --rpc-url "$DEPLOY_RPC_URL" \
  --private-key "$DEPLOYER_PRIVATE_KEY"

โฟลว์การโพลล์

  1. ส่งคำขอแบบ lightweight ไปยัง eth_blockNumber เป็นระยะเพื่อตรวจสอบ block head ล่าสุดของเชน
  2. เปรียบเทียบหมายเลขบล็อกที่ส่งกลับมากับ lastSeenBlock ที่ประมวลผลก่อนหน้านี้
  3. หาก currentBlock > lastSeenBlock ให้แบ่ง [lastSeenBlock + 1, currentBlock] ออกเป็น chunk ที่มีขนาดไม่เกิน max_logs_block_range บันทึกค่า lastSeenBlock แบบถาวรหลังจากประมวลผลแต่ละ chunk สำเร็จแล้วเท่านั้น; หากล้มเหลว ให้ลองใหม่กับ chunk ที่ยังไม่เสร็จสมบูรณ์ กำจัดข้อมูลซ้ำซ้อนด้วย (blockHash, transactionHash, logIndex) และเล่นซ้ำช่วงที่ทับซ้อนกันหลังจากเชื่อมต่อใหม่เพื่อจัดการกับการจัดระเบียบเชนใหม่ (reorg)
  4. ฟังก์ชัน watchBlockNumber หรือ watchBlocks ของ viem ใช้วิธีการโพลล์ HTTP ภายใต้ transport แบบ HTTP โดยตรง ซึ่งช่วยให้สามารถปรับแต่งผ่านพารามิเตอร์ pollingInterval ได้ (เช่น 1,000 ms)

โพลล์ event logs ใน chunk ที่จำกัดขอบเขต

บันทึกเป็น poll-logs.mjs ไว้ข้าง network.mjs และ viem-client.mjs ตั้งค่า BLOCKVECTRA_API_KEY, LOG_ADDRESS และ FROM_BLOCK จากนั้นรัน node poll-logs.mjs ตัวอย่างจำกัดนี้จะสุ่มตรวจตัวอย่าง head 12 ครั้ง ห่างกันครั้งละห้าวินาที และคิวรีทุกช่วงใหม่ใน chunk ตามลำดับ หากเกิดข้อผิดพลาดจะหยุดการทำงานของสคริปต์ก่อนที่จะขยับผ่าน chunk ที่ล้มเหลว

import { isAddress } from 'viem';
import { client } from './viem-client.mjs';
import { chainInfo, allows } from './network.mjs';

const address = process.env.LOG_ADDRESS;
const start = process.env.FROM_BLOCK;
if (!address || !isAddress(address)) throw new Error('Set LOG_ADDRESS');
if (!/^(0x[0-9a-f]+|[0-9]+)$/i.test(start ?? '')) throw new Error('Set FROM_BLOCK');
if (!allows('eth_getLogs')) throw new Error('eth_getLogs requires an available keyed endpoint');
if (!Number.isSafeInteger(chainInfo.max_logs_block_range) || chainInfo.max_logs_block_range <= 0) {
  throw new Error('Invalid max_logs_block_range');
}
const max = BigInt(chainInfo.max_logs_block_range);
let from = BigInt(start);
for (let poll = 0; poll < 12; poll++) {
  const head = await client.getBlockNumber();
  while (from <= head) {
    const to = from + max - 1n < head ? from + max - 1n : head;
    const logs = await client.getLogs({ address, fromBlock: from, toBlock: to });
    console.log(JSON.stringify({ from: from.toString(), to: to.toString(), logs },
      (_, value) => typeof value === 'bigint' ? value.toString() : value));
    from = to + 1n;
  }
  if (poll < 11) await new Promise(resolve => setTimeout(resolve, 5_000));
}

ผลลัพธ์แต่ละรายการจะบันทึก chunk ที่เสร็จสมบูรณ์ หากต้องการดำเนินการต่อ ให้ตั้งค่า FROM_BLOCK เป็น to + 1 ของ chunk นั้น; consumer ที่ทนทานจะต้องบันทึกเหตุการณ์และเคอร์เซอร์ไว้ด้วยกัน, กำจัดข้อมูลซ้ำ และกระทบยอดการจัดระเบียบเชนใหม่ตามที่อธิบายไว้ข้างต้น สำหรับ 429 หรือความล้มเหลวอื่นๆ ที่สามารถลองใหม่ได้ ให้ใช้คำแนะนำ bounded-backoff กับ chunk เดิมที่ยังไม่เสร็จสมบูรณ์

ขั้นตอนถัดไป

อัปเดตล่าสุด:

ในหน้านี้

คำตอบโดยตรงงานที่คู่มือนี้ช่วยให้คุณทำสำเร็จงาน 3 ขั้นตอน: ดึงข้อมูล log ของ HyperEVM ย้อนหลังในช่วงที่จำกัดขอบเขต1. อ่านบล็อกล่าสุดโดยไม่ต้องใช้ API key2. สร้าง API key3. ดึงข้อมูล log ย้อนหลังด้วยคีย์ของคุณเชื่อมต่อด้วย viem หรือ ethersดีพลอยด้วย Foundry หรือ HardhatHYPE, บล็อกขนาดเล็ก และการดีพลอยขนาดใหญ่ข้อมูล HyperCore และ HyperEVMการจัดการข้อผิดพลาดทางการ 10055ขีดจำกัดอัตราของ public RPC อย่างเป็นทางการและ 429พารามิเตอร์และกฎการให้บริการของ BlockVectraการดึงข้อมูล log ย้อนหลัง: eth_getLogs แบบแบ่งส่วนและตรรกะการลองใหม่การประเมิน retryable ในการตอบกลับข้อผิดพลาดการใช้ Data API endpoints แทนการสแกน getLogs ปริมาณมากโครงสร้างการตอบกลับตัวอย่างโค้ด: การคิวรี Data APIการติดตามแบบเรียลไทม์: การโพลล์บล็อกใหม่โฟลว์การโพลล์โพลล์ event logs ใน chunk ที่จำกัดขอบเขตคู่มือที่เกี่ยวข้องขั้นตอนถัดไป