# HyperEVM RPC のレート制限とログバックフィル

> Source: https://docs.blockvectra.com/ja/guides/hyperevm-backfill/

## 要点

デフォルトの公式 HyperEVM 公開 RPC は、`eth_getLogs` クエリあたり 50 ブロックを許可します（出典：Hyperliquid 公式 [JSON-RPC ドキュメント](https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/hyperevm/json-rpc)）。BlockVectra では、認証付き `eth_getLogs` リクエストはクエリあたり最大 1,000 ブロック（[GET /v1/chains](https://api.blockvectra.com/v1/chains) の `hyperevm_mainnet.max_logs_block_range`、両端を含む）をカバーします。これを超える範囲は HTTP 200、JSON-RPC `-32602`、および `logs_range_too_large`（`retryable: false`）を返します（[エラーカタログ](https://docs.blockvectra.com/en/errors/#logs_range_too_large)を参照）。`[from, min(from + max − 1, end)]` に分割し、カーソルを保存し、成功後に末尾プラス 1 に進めて実行を再開します。公式公開 RPC の IP ごとのレート制限と BlockVectra のキー制限は、[公式公開 RPC のレート制限と 429](#official-public-rpc-rate-limits-and-429) および以下のサービスパラメータで個別に説明されています。

## このガイドで達成できること

* 認証付きメソッドを選択する前に、viem または ethers による公開読み取りで [HyperEVM RPC をテスト](#connect-with-viem-or-ethers) します。
* 返されたエラーに基づく再試行の判断とともに、HyperEVM の `eth_getLogs` 制限内で[有界なログウィンドウをバックフィル](#three-step-task-backfill-a-bounded-hyperevm-log-window) します。
* 返された対応範囲と鮮度のメタデータを確認しながら、キーを使用してインデックス化されたトランザクションと送金を通じて[アドレスのアクティビティを読み取り](#using-data-api-endpoints-instead-of-extensive-getlogs-scanning) ます。

<span id="bounded-log-backfill-task" />

## 3 ステップタスク：有界な HyperEVM ログウィンドウのバックフィル

キーなしで最新ブロックを読み取り、キーを作成して、有限のブロックウィンドウにわたるコントラクトのイベントログを取得します。

必要なコントラクトとブロックウィンドウを選択します。このタスクはその有界なウィンドウをカバーするものであり、完全なコントラクト履歴を保証するものではありません。

### 1. API key なしで最新ブロックを読み取る

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

JSON-RPC の `result` は十六進数の最新ブロック番号です。これは [GET /v1/chains](https://api.blockvectra.com/v1/chains) によって公開されている HyperEVM の `public.url` です。公開エンドポイントの `public.methods` には `eth_getLogs` は含まれていません。ステップ 3 にはキーが必要です。

### 2. API key を作成する

<div data-attribution-ref="docs-hyperevm-task">
  [このバックフィルのためのキーを作成します](https://console.blockvectra.com/login/?next=%2Fkeys%2F)。キーを作成し、`hyperevm_mainnet` で使用するためにダイアログに表示されたシークレットを保存します。

  ブラウザを使用しない HTTP 経由の AI エージェントの場合は、<a href="/en/guides/programmatic-signup/">プログラムによる登録ガイド</a> に従ってください。サンプルの `docs-signup` ではなく、ガイド URL の有効な `ref` を `POST /auth/siwe/login` の JSON ボディに渡します。利用できない場合は省略してください。ユーザーにチャットへキーを貼り付けるよう求めないでください。
</div>

### 3. キーを使用してログをバックフィルする

完全なスターターテンプレート：[blockvectra/hyperevm-backfill](https://github.com/blockvectra/hyperevm-backfill)

以下のスクリプトを `hyperevm-task.ts` として保存します。追加のパッケージなしで、Node.js 24 以降で動作します。`BLOCKVECTRA_API_KEY` を保存したキーに、`LOG_ADDRESS` を検査したいイベント発行コントラクトアドレスに設定します。キーはサーバーまたはローカルターミナルに保管してください。

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

デフォルトでは、スクリプトは最新の `max_logs_block_range` ブロック（ジェネシス付近ではそれ以下）を取得します。実行時に `/v1/chains` からその制限を読み取ります。別の有限なウィンドウを選択するには、実行前に `FROM_BLOCK` と `TO_BLOCK` の両方を十進数または `0x` 十六進数のブロック番号に設定します。これより大きなウィンドウは、公開された上限以下の連続したチャンクに分割されます。

```ts
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` の場合にのみ再試行され、リクエストごとに最大 4 回の試行、指数バックオフとジッター、および `Retry-After` の秒数または HTTP 日付のサポートが行われます。30 秒を超える待機が発生した場合、後で再実行できるようにスクリプトを停止します。ネットワーク障害、タイムアウト、不正な形式のレスポンス、および再試行不可能なエラーは直ちに停止します。スクリプトは、完全なバックフィルを報告することなく、異常終了します。

標準出力の各行には、1 つのチャンクの `fromBlock`、`toBlock`、および `result` 配列が含まれます。`result: []` は、そのチャンクに一致するログがなかったことを意味します。各ログの以下のフィールドを確認してください：

| フィールド                                             | 意味                                                           |
| ------------------------------------------------- | ------------------------------------------------------------ |
| `address`                                         | イベントを発行したコントラクト。                                             |
| `blockNumber`, `blockHash`                        | ログを含むブロック。番号は十六進数です。                                         |
| `transactionHash`, `transactionIndex`, `logIndex` | トランザクションおよびログの位置。インデックスは十六進数です。                              |
| `topics`, `data`                                  | インデックス付きイベント引数および ABI エンコードされた非インデックス引数。コントラクト ABI でデコードします。 |
| `removed`                                         | チェーンの再編成（reorg）によってログが削除されたかどうか。                             |

最新ブロックはファイナリティのマーカーではありません。安定した履歴ウィンドウが必要な場合は、アプリケーションで確認済みの `TO_BLOCK` を選択し、チェーンの再編成を処理してください。

`B = TO_BLOCK − FROM_BLOCK + 1` ブロックのウィンドウと公開制限 `L` に対して、チャンク数は `N = ceil(B / L)` です。[GET /v1/plans](https://console-api.blockvectra.com/v1/plans) から `eth_getLogs` と `eth_blockNumber` の `method_weights[].cu_weight` を読み取ります。スクリプトは標準エラー出力に見積もりを出力します：キー付きのヘッドルックアップを含めて `N × weight(eth_getLogs) + weight(eth_blockNumber)`。これには追加の呼び出しや課金対象の再試行は含まれません。精算については[請求ルール](https://docs.blockvectra.com/en/guides/billing-rules/)を参照してください。CU は返されるログの数ではなく、呼び出し回数に依存します。

**イベント配信：** 以下のチャンク分割 HTTP ポーリングを使用するか、[webhook push](https://docs.blockvectra.com/en/guides/webhook-push/) を使用して監視対象アドレスのイベントを HTTPS レシーバーに送信します。**GET /v1/push/chains で対応チェーン**と確認設定を確認できます。`x-api-key` で認証してください。Webhook 署名、重複排除、およびリプレイはそのガイドで説明されています。Webhook push は WebSocket サブスクリプション（`/v1/chains` の `ws` と `subscriptions`）とは別個の機能です。

## viem または ethers で接続する

| パラメータ / エンドポイント | 値 / テンプレート | 認証方式 |
|---|---|---|
| チェーン ID（EIP-155） | `999` | — |
| JSON-RPC（パスに API key を指定） | `POST https://api.blockvectra.com/v1/hyperevm_mainnet/{api_key}` | URL パスに API key を指定 |
| JSON-RPC（ヘッダーに API key を指定） | `POST https://api.blockvectra.com/v1/hyperevm_mainnet` | ヘッダー x-api-key: {api_key} |
| Data API ベース URL | `GET https://api.blockvectra.com/v1/data/hyperevm_mainnet/…` | ヘッダー x-api-key: {api_key} |
| 公開ステータス | `GET https://api.blockvectra.com/v1/status` | 認証不要（公開） |

開発者と AI エージェントは同じサーバー側設定を使用できます。Node.js 24 以降、viem 2 または ethers 6 を使用し、公開読み取りから始めます。キーが必要なメソッドについては、環境変数に `BLOCKVECTRA_API_KEY` を安全に設定してください。キーおよびキーを含む RPC URL は、ブラウザコード、ログ、およびバージョン管理から除外してください。

これを `network.mjs` として保存します。[GET /v1/chains](https://api.blockvectra.com/v1/chains) から `chain_id` とメソッドポリシーを読み取ります。キー不要の読み取りには、カタログの `public.url` と `public.methods` にリストされているメソッドのみを使用します。公開 HTTP の利用可能性は WebSocket アクセスを意味しません。

```js
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` を実行します。

```js
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` を実行します。

```js
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` であり、`methods.allow` に `eth_sendRawTransaction` がリストされていません。読み取りには BlockVectra を使用します。デプロイにはブロードキャストをサポートする RPC が必要です。`DEPLOY_RPC_URL` をそのプロバイダーの認証付き HTTP URL に設定します。BlockVectra のメソッドやログ範囲の制限と同じであるとは仮定しないでください。署名する前に選択したチェーン ID を確認してください。

```bash
: "${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 デプロイチュートリアル](https://docs.blockvectra.com/en/guides/deploy-contract/) に進んでください。デプロイヤーに EVM HYPE を入金し、大規模デプロイの前に以下のデュアルブロック要件を確認してください。

## HYPE、小型ブロック、および大規模デプロイ

[HyperEVM の公式ネットワークガイド](https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/hyperevm) は、HYPE をガスとして指定しており、18 桁の小数を持ちます（参照日：2026-10-07）。デプロイヤーが HyperEVM 上で HYPE を保持していることを確認してください。HyperCore の残高だけでは EVM ガスの残高にはなりません。資金を移動する際は、リンク先のネイティブ転送手順に従ってください。

[デュアルブロックガイド](https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/hyperevm/dual-block-architecture) では、高速な小型ブロック（small blocks）と、より大きなトランザクション向けの低速な大型ブロック（big blocks）について説明されています（参照日：2026-10-07）。まずデプロイガスを見積もってください。小型ブロックの予算を超えるデプロイの場合、デプロイヤーは既存の HyperCore ユーザーであり、Core アクション `{"type":"evmUserModify","usingBigBlocks":true}` に署名する必要があります。トランザクションのガス制限を大きく設定するだけでは、大型ブロックは選択されません。終了後は `usingBigBlocks=false` に戻して、小型ブロックに戻してください。

それらをサポートするプロバイダーでは、`eth_usingBigBlocks` を使用してアドレスモードを確認し、`eth_bigBlockGasPrice` で大型ブロックのベースフィーを確認します。[公式 JSON-RPC リファレンス](https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/hyperevm/json-rpc) にこれらのメソッドが記載されています（参照日：2026-10-07）。選択したプロバイダーのメソッドを確認してください。BlockVectra の場合は `/v1/chains` を使用します。上記の最小限のデプロイは小さなコントラクトを対象としており、Core アカウントモードは変更しません。

## HyperCore と HyperEVM データ

EVM RPC はコントラクト、receipt、およびログを提供します。HyperCore の取引データとアクションは Core API を使用します。コントラクトはプリコンパイルを通じて Core の状態を読み取り、CoreWriter を通じてアクションを送信できます。これらのパスを統合する際は、[公式インタラクションガイド](https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/hyperevm/interacting-with-hypercore) を使用してください（参照日：2026-10-07）。EVM ログは、Core のオーダーブックやポジションのクエリに代わるものではありません。

HyperEVM システムトランザクション（HyperCore から HyperEVM への転送など）は標準の `eth_getBlockByNumber` レスポンスには含まれず、公式 RPC を通じて `eth_getSystemTxsByBlockNumber` および `eth_getSystemTxsByBlockHash` 経由で個別に提供されます（[公式 JSON-RPC ドキュメント](https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/hyperevm/json-rpc) を参照、参照日：2026-10-07）。BlockVectra の HyperEVM ブロック、トランザクション、および Data API データには現在、システムトランザクションは含まれていません。システムトランザクションデータが必要な場合は、これら 2 つの公式 RPC メソッドを直接使用してください。

## 公式エラー 10055 の処理

[公式 HyperEVM ガイド](https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/hyperevm) では、`10055` を Core/EVM 境界エラーと定義しており、nonce、資金不足、ハッシュ重複、および低手数料による置き換え失敗が含まれます（参照日：2026-10-07）。復旧方法を決定する前に、ブロードキャスト RPC からのメッセージを確認してください：

* **Nonce：** `eth_getTransactionCount` を保留中のトランザクションと比較します。1 つのデプロイヤーからの送信を直列化し、次の nonce を調整します。
* **資金：** 送金額にガス代を加えた合計に対して、デプロイヤーの EVM HYPE 残高を確認します。
* **重複ハッシュ：** 別のトランザクションを送信する前に、既存のトランザクションと receipt を検索します。
* **置き換え手数料：** 既存の nonce と手数料を確認し、ブロードキャスターの置き換えポリシーを使用します。同じバイト列を繰り返しても手数料は引き上げられません。

`10055` だけでは盲目的な再試行を正当化することはできません。エラーとその復旧ガイダンスについては、[BlockVectra エラーリファレンス](https://docs.blockvectra.com/en/errors/) で個別に確認してください。

## 公式公開 RPC のレート制限と 429

Hyperliquid の公式[レート制限ドキュメント](https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/rate-limits-and-user-limits) では、`rpc.hyperliquid.xyz/evm` に対して IP ごとに 1 分あたり最大 100 件の EVM JSON-RPC リクエストが規定されています。その [JSON-RPC ドキュメント](https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/hyperevm/json-rpc) でも、`eth_getLogs` はクエリあたり 50 ブロック、最大 4 トピックに制限されています（参照日：2026-10-07）。

HTTP 429 が発生した場合はリクエストを一時停止し、まず `Retry-After`（秒数または HTTP 日付）に従ってください。存在しない場合は、ジッターを伴う指数バックオフと有界な再試行回数を使用し、同じ未完了のチャンクを再試行します。並行性とポーリング頻度を減らし、エンドポイントの制限内のチャンクにログクエリを分割します。チャンク分割だけではレート制限は解除されません。IP を共有するクライアントは、リクエストレートを協調させる必要があります。

BlockVectra のキー付きエンドポイントについては、公式公開 RPC のブロック範囲や毎分リクエスト数の制限を適用するのではなく、[GET /v1/chains](https://api.blockvectra.com/v1/chains) から `hyperevm_mainnet` の `max_logs_block_range`、`methods.allow`、および `methods.deny` を読み取ります。リクエストレートは、キーの `cu_per_sec`、`burst_cu`、および無料プランの呼び出し制限の対象となります（次のセクションを参照）。429 が発生した場合は、`error.data.reason` と `retryable` を確認してください。`request_exceeds_burst` の場合は、バックオフを伴う変更なしの再試行ではなく、より小さなリクエストに分割する必要があります。

## BlockVectra パラメータとサービスルール

BlockVectra は、JSON-RPC および REST Data API エンドポイントを介して HyperEVM メインネットを提供します：

1. **チェーンパラメータとログの制限**：
   `hyperevm_mainnet` の `GET /v1/chains` より：
   * **チェーン識別子（Slug）**：`hyperevm_mainnet`、チェーン ID `999`。
   * **`max_logs_block_range`**：`GET /v1/chains` の `max_logs_block_range` フィールドに準拠。単一の `eth_getLogs` リクエストはこのブロック数（`toBlock − fromBlock + 1`）以下をカバーする必要があります。この範囲を超えると、HTTP 200 と JSON-RPC エラーコード `-32602`（`eth_getLogs block range too large: max <N> blocks`）が返されます（課金対象外）。
   * **`state_window_blocks`**：`GET /v1/chains` の `state_window_blocks` フィールドに準拠。状態読み取り呼び出し（`eth_call` や `eth_getBalance` など）はこのフィールドで宣言された保持ウィンドウの対象となります（`null` の場合、ローリングウィンドウ制限なしで完全な状態が保持されます）。
   * **メソッドポリシー**：`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 には CU バケット（`cu_per_sec` 補充速度、`burst_cu` 容量 — デフォルトは 400 CU/s、バースト容量は 1,600 CU）があります。メソッドは Compute Unit（CU）重み付けによって計測されます。
   * **制限のアップグレード**：チャージ後、アカウント全体の毎秒呼び出し制限は解除されます。各キーには引き続き Compute Unit（CU）レートとバースト制限が適用されます。現在の料金と課金単位については、[料金ページ](https://blockvectra.com/en/pricing/)を参照してください。

## 過去のログのバックフィル：チャンク分割 eth\_getLogs と再試行ロジック

過去のログをクエリする場合、広い区間は対象チェーンの `max_logs_block_range` で区切られた連続したチャンクに分割する必要があります。クライアントの再試行戦略では、エラーレスポンス内の `retryable` フィールドを検査する必要があります。

### エラーレスポンスでの retryable の評価

BlockVectra では、JSON-RPC エラーオブジェクトに `reason`、`docs_url`、および `retryable`（ブール値）を含む `error.data` ペイロードが含まれます：

* **`retryable: true`**：サービス過負荷（`overloaded`）、無料プランの毎秒呼び出し制限（`free_plan_call_limit`）、ノード同期中（`node_syncing`）、アップストリーム利用不可（`upstream_unavailable`）などの一時的な状態。クライアントは、存在する場合は `Retry-After` ヘッダーを尊重するか、ジッターを伴う指数バックオフを適用する必要があります。
* **`retryable: false`**：ブロック範囲の上限超過（`-32602` / `logs_range_too_large`）、無効なパラメータ（`invalid_params`）、API key の欠落（`missing_api_key`）、リクエストがバースト容量を超過（`-32022` / `request_exceeds_burst`）などの非一時的なエラー。パラメータを調整せずに再試行しても成功しません。

以下は、API key が省略された場合に返されるレスポンスです：

```json
{
  "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
    }
  }
}
```

## 大規模な getLogs スキャンの代わりに Data API エンドポイントを使用する

アプリケーションが特定のブロックまたはアドレスのトランザクション履歴やトークンの移動を追跡する場合、`eth_getLogs` を介したスキャンでは、`max_logs_block_range` で区切られた連続したチャンククエリを発行し、生の Transfer イベントログを解析する必要があります。

BlockVectra Data API は、`hyperevm_mainnet` 向けに事前インデックス化された REST エンドポイントを提供し、カーソルベースのページネーションで最大 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`。

### レスポンス構造

レスポンスは標準のエンベロープスキーマを使用します：

* `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` が含まれます（ERC-20 の場合は `amount`、ERC-721 の場合は `token_id`）。
* `next_cursor`：後続のレコードが存在する場合に返される不透明なページネーショントークン（最後のページでは存在せず、`null` ではありません）。
* `meta`：`chain`、`chain_slug`、`chain_external_id`、`as_of_block`、`safe_block`、`finalized_block`、`coverage`（`full` または `partial`）、および `refreshed_at` を含むメタデータ。

### コード例：Data API クエリ

**cURL**

```bash
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"
```


  **TypeScript**

```ts
const apiKey = process.env.BLOCKVECTRA_API_KEY!;
const targetAddress = "0x2222222222222222222222222222222222222222";

let cursor: string | undefined;

do {
  const url = new URL(
    `https://api.blockvectra.com/v1/data/hyperevm_mainnet/addresses/${targetAddress}/transfers`,
  );
  url.searchParams.set("standard", "erc20");
  url.searchParams.set("from_block", "0");
  url.searchParams.set("to_block", "50000");
  url.searchParams.set("clamp", "true");
  if (cursor) {
    url.searchParams.set("cursor", cursor);
  }

  const res = await fetch(url, {
    headers: { "x-api-key": apiKey },
  });

  if (!res.ok) {
    throw new Error(`Data API HTTP ${res.status}`);
  }

  const body = (await res.json()) as {
    data: unknown[];
    next_cursor?: string;
  };

  console.log(`Fetched ${body.data.length} transfers`);
  cursor = body.next_cursor; // Loop terminates when cursor is absent
} while (cursor);
```


## リアルタイム追跡：新しいブロックのポーリング

HTTP トランスポートの場合、ポーリングによってブロックを追跡し、`max_logs_block_range` 内の連続したチャンクでイベントログを取得します。WebSocket は、`/v1/chains` が `ws=true` および必要な `subscriptions` エントリを報告している場合にのみ選択してください。HTTPS レシーバーへの配信には、[webhook push](https://docs.blockvectra.com/en/guides/webhook-push/) を使用します。

デプロイされた `Hello` コントラクトをテストするには、`LOG_ADDRESS` をそのアドレスに設定します。ブロードキャスト RPC を介して `ping()` を送信し、このページのバックフィルスクリプトを使用して receipt のブロックをバックフィルします。新しいイベントについては、最後に完了したチャンクから継続します。

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

### ポーリングフロー

1. 定期的な軽量呼び出しを `eth_blockNumber` に発行して、最新のチェーン先頭を検査します。
2. 返されたブロック番号を以前に処理された `lastSeenBlock` と比較します。
3. `currentBlock > lastSeenBlock` の場合、`[lastSeenBlock + 1, currentBlock]` を最大 `max_logs_block_range` のチャンクに分割します。各チャンクを正常に処理した後にのみ `lastSeenBlock` を永続化し、失敗した場合は未完了のチャンクを再試行します。`(blockHash, transactionHash, logIndex)` で重複排除し、再接続後に重複部分をリプレイして reorg を調整します。
4. viem の `watchBlockNumber` または `watchBlocks` は、HTTP トランスポート下でネイティブに HTTP ポーリングを実装しており、`pollingInterval` パラメータ（1000 ms など）によるカスタマイズが可能です。

### 有界なチャンクでのイベントログのポーリング

`network.mjs` と `viem-client.mjs` の横に `poll-logs.mjs` として保存します。`BLOCKVECTRA_API_KEY`、`LOG_ADDRESS`、および `FROM_BLOCK` を設定してから、`node poll-logs.mjs` を実行します。この有限のサンプルは、5 秒間隔で先頭を 12 回サンプリングし、すべての新しい範囲を順次チャンクでクエリします。エラーが発生した場合、失敗したチャンクを進める前にスクリプトを停止します。

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

各出力は完了したチャンクを記録します。再開するには、`FROM_BLOCK` をその `to + 1` に設定します。永続的なコンシューマーは、イベントとカーソルを一緒に保存し、重複排除し、上記で説明したように reorg を調整する必要があります。429 またはその他の再試行可能な障害については、同一の未完了チャンクに対して有界バックオフガイダンスを適用してください。

## 関連ガイド

* 公開 RPC URL、サポートされているメソッド、および現在の制限は、[HyperEVM チェーンページ](https://blockvectra.com/en/chains/hyperevm_mainnet/) で確認できます。
* `eth_getLogs` の範囲とチャンク分割アルゴリズムに関する完全なルールについては、[eth\_getLogs のブロック範囲制限と分割クエリ](https://docs.blockvectra.com/en/guides/getlogs-block-range/) を参照してください。
* `eth_getLogs` と Data API 送金の比較、`as_of_block` の境界の理解、および `safe_block` / `finalized_block` マーカーについては、[eth\_getLogs とインデックス済み送金：対応範囲とファイナリティ](https://docs.blockvectra.com/en/guides/logs-vs-transfers/) を参照してください。
* CU の計測、課金対象外のエラー、および再試行の詳細については、[課金対象外のもの：エラーコードと請求ルール](https://docs.blockvectra.com/en/guides/billing-rules/) を参照してください。

## 次のステップ

* [データセット一覧を見る](https://blockvectra.com/en/data/)と、BlockVectra がインデックス化しているすべてのデータセットを確認できます。
* [無料プランと料金を見る](https://blockvectra.com/en/pricing/#free)と、アカウントに含まれる内容を確認できます。
* [コンソールにログイン](https://console.blockvectra.com/login/?next=%2Fkeys%2F)して、API keyを作成します。
