# Límites de tasa de RPC de HyperEVM y recuperación de logs

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

## Respuesta directa

El RPC público oficial predeterminado de HyperEVM permite 50 bloques por consulta `eth_getLogs` (fuente: [documentación JSON-RPC](https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/hyperevm/json-rpc) oficial de Hyperliquid). En BlockVectra, las solicitudes autenticadas de `eth_getLogs` cubren hasta 1,000 bloques por consulta (`hyperevm_mainnet.max_logs_block_range` de [GET /v1/chains](https://api.blockvectra.com/v1/chains)), incluidos ambos extremos. Un intervalo más amplio devuelve HTTP 200, JSON-RPC `-32602` y `logs_range_too_large`, con `retryable: false` (consulte el [catálogo de errores](https://docs.blockvectra.com/en/errors/#logs_range_too_large)); divida en `[from, min(from + max − 1, end)]`, guarde su cursor y avance hasta el final más uno después de tener éxito para reanudar las ejecuciones. El límite de tasa por IP del RPC público oficial y los límites de clave de BlockVectra se describen por separado en [Límites de tasa del RPC público oficial y 429](#official-public-rpc-rate-limits-and-429) y en los parámetros del servicio a continuación.

## Tareas que esta guía le ayuda a completar

* [Probar el RPC de HyperEVM](#connect-with-viem-or-ethers) con una lectura pública usando viem o ethers antes de seleccionar métodos autenticados.
* [Recopilar un intervalo delimitado de logs](#three-step-task-backfill-a-bounded-hyperevm-log-window) dentro del límite de `eth_getLogs` de HyperEVM, con decisiones de reintento basadas en el error devuelto.
* [Leer la actividad de una dirección](#using-data-api-endpoints-instead-of-extensive-getlogs-scanning) a través de transacciones y transferencias indexadas con una clave, verificando la cobertura devuelta y los metadatos de actualización.

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

## Tarea en tres pasos: recopilar un intervalo delimitado de logs de HyperEVM

Lea el bloque más reciente sin una clave, cree una clave y luego recupere logs de eventos de un contrato en un intervalo finito de bloques.

Elija el contrato y el intervalo de bloques que necesita. Esta tarea cubre ese intervalo delimitado; no promete un historial completo del contrato.

### 1. Leer el bloque más reciente sin una 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":[]}'
```

El `result` de JSON-RPC es el número de bloque más reciente en hexadecimal. Esta es la `public.url` de HyperEVM publicada por [GET /v1/chains](https://api.blockvectra.com/v1/chains). Los `public.methods` del endpoint público no incluyen `eth_getLogs`; el paso 3 requiere una clave.

### 2. Crear una API key

<div data-attribution-ref="docs-hyperevm-task">
  [Cree una clave para esta recopilación](https://console.blockvectra.com/login/?next=%2Fkeys%2F). Cree una clave y guarde el secreto mostrado en el cuadro de diálogo para usarlo con `hyperevm_mainnet`.

  Para un Agente de IA que use HTTP sin navegador, siga la <a href="/en/guides/programmatic-signup/">Guía de registro programático</a>. Pase el `ref` válido de la URL de la guía en el cuerpo JSON de `POST /auth/siwe/login` en lugar del `docs-signup` del ejemplo; omítalo si no está disponible. No le pida al usuario que pegue la clave en el chat.
</div>

### 3. Recopilar logs con su clave

Plantilla de inicio completa: [blockvectra/hyperevm-backfill](https://github.com/blockvectra/hyperevm-backfill)

Guarde el siguiente script como `hyperevm-task.ts`. Se ejecuta con Node.js 24 o posterior, sin paquetes adicionales. Establezca `BLOCKVECTRA_API_KEY` con su clave guardada y `LOG_ADDRESS` con la dirección del contrato emisor que desea inspeccionar; mantenga la clave en su servidor o en una terminal local.

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

De forma predeterminada, el script recupera los `max_logs_block_range` bloques más recientes, o menos cerca del bloque génesis. Lee ese límite de `/v1/chains` en tiempo de ejecución. Para seleccionar otro intervalo finito, establezca tanto `FROM_BLOCK` como `TO_BLOCK` en números de bloque decimales o hexadecimales `0x` antes de ejecutar. Los intervalos más grandes se dividen en fragmentos consecutivos, cada uno como máximo igual al límite publicado.

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

Las solicitudes se ejecutan secuencialmente. Un error de JSON-RPC solo se reintenta cuando `error.data.retryable` es `true`, con un máximo de cuatro intentos por solicitud, retroceso exponencial con variación aleatoria (jitter) y compatibilidad con segundos o una fecha HTTP en `Retry-After`. Una espera superior a 30 segundos detiene el script para que pueda volver a ejecutarlo más tarde. Los fallos de red, los tiempos de espera agotados, las respuestas mal formadas y los errores no reintentables se detienen de inmediato; el script finaliza sin éxito en lugar de reportar una recopilación completa.

Cada línea de la salida estándar contiene el `fromBlock`, `toBlock` y el array `result` de un fragmento. `result: []` significa que no hay logs coincidentes en ese fragmento. Lea estos campos en cada log:

| Campo                                             | Significado                                                                                                              |
| ------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------ |
| `address`                                         | Contrato que emitió el evento.                                                                                           |
| `blockNumber`, `blockHash`                        | Bloque que contiene el log; el número está en hexadecimal.                                                               |
| `transactionHash`, `transactionIndex`, `logIndex` | Posición de la transacción y del log; los índices están en hexadecimal.                                                  |
| `topics`, `data`                                  | Argumentos indexados del evento y argumentos no indexados codificados según ABI; decodifíquelos con el ABI del contrato. |
| `removed`                                         | Si el log fue eliminado por una reorganización de la cadena.                                                             |

El bloque más reciente no es un marcador de finalidad. Si necesita un intervalo histórico estable, elija el `TO_BLOCK` confirmado de su aplicación y gestione las reorganizaciones de la cadena.

Para un intervalo de `B = TO_BLOCK − FROM_BLOCK + 1` bloques y un límite publicado `L`, el número de fragmentos es `N = ceil(B / L)`. Lea `method_weights[].cu_weight` para `eth_getLogs` y `eth_blockNumber` desde [GET /v1/plans](https://console-api.blockvectra.com/v1/plans). El script imprime una estimación en la salida de error estándar: `N × weight(eth_getLogs) + weight(eth_blockNumber)`, incluida su consulta del bloque más reciente con clave. Esto excluye llamadas adicionales y cualquier reintento facturable; consulte las [reglas de facturación](https://docs.blockvectra.com/en/guides/billing-rules/) para la liquidación. Las CU dependen de las llamadas, no del número de logs devueltos.

**Entrega de eventos:** Utilice el polling HTTP fragmentado a continuación, o envíe eventos de direcciones vigiladas a un receptor HTTPS con [push de webhook](https://docs.blockvectra.com/en/guides/webhook-push/). **GET /v1/push/chains enumera las cadenas compatibles** y la configuración de confirmación; autentíquese con `x-api-key`. Las firmas de webhook, la deduplicación y la reproducción se tratan en esa guía. El push de webhook es independiente de las suscripciones WebSocket (`ws` y `subscriptions` en `/v1/chains`).

## Conectar con viem o ethers

| Parámetro / Endpoint | Valor / Plantilla | Autenticación |
|---|---|---|
| Chain ID (EIP-155) | `999` | — |
| JSON-RPC (clave en la ruta) | `POST https://api.blockvectra.com/v1/hyperevm_mainnet/{api_key}` | API key en la ruta de la URL |
| JSON-RPC (clave en el encabezado) | `POST https://api.blockvectra.com/v1/hyperevm_mainnet` | Encabezado x-api-key: {api_key} |
| Base de Data API | `GET https://api.blockvectra.com/v1/data/hyperevm_mainnet/…` | Encabezado x-api-key: {api_key} |
| Estado público | `GET https://api.blockvectra.com/v1/status` | Sin autenticación (público) |

Los desarrolladores y Agentes de IA pueden usar la misma configuración del lado del servidor. Use Node.js 24 o posterior, viem 2 o ethers 6, y comience con lecturas públicas. Establezca `BLOCKVECTRA_API_KEY` de forma segura en el entorno para métodos con clave. Mantenga las claves y las URL de RPC que contengan claves fuera del código del navegador, los logs y el control de versiones.

Guarde esto como `network.mjs`. Lee `chain_id` y la política de métodos desde [GET /v1/chains](https://api.blockvectra.com/v1/chains). Para lecturas sin clave, use la `public.url` del catálogo y solo los métodos enumerados en `public.methods`; la disponibilidad pública de HTTP no implica acceso por 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');
```

Guarde como `viem-client.mjs`, instale con `npm install viem@2`, y luego ejecute `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());
```

Para ethers, guarde como `ethers-client.mjs`, instale con `npm install ethers@6`, y luego ejecute `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();
```

## Desplegar con Foundry o Hardhat

El catálogo actual de `hyperevm_mainnet` tiene `ws=false` y no incluye `eth_sendRawTransaction` en `methods.allow`. Utilice BlockVectra para lecturas; el despliegue requiere un RPC que admita difusión (broadcasting). Establezca `DEPLOY_RPC_URL` en la URL HTTP autenticada de ese proveedor. No asuma que comparte los límites de métodos o de intervalo de logs de BlockVectra. Verifique el chain ID seleccionado antes de firmar.

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

Continúe con el [tutorial compartido de despliegue con Foundry o Hardhat](https://docs.blockvectra.com/en/guides/deploy-contract/). Financie la cuenta de despliegue con HYPE de EVM y revise los requisitos de bloques duales a continuación antes de un despliegue grande.

## HYPE, bloques pequeños y despliegues grandes

La [guía oficial de red de HyperEVM](https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/hyperevm) identifica HYPE como gas, con 18 decimales (consultado: 2026-10-07). Asegúrese de que la cuenta de despliegue tenga HYPE en HyperEVM; un saldo en HyperCore por sí solo no es el saldo de gas de EVM. Siga las instrucciones enlazadas para transferencias nativas al transferir fondos.

La [guía de bloques duales](https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/hyperevm/dual-block-architecture) describe bloques pequeños rápidos y bloques grandes más lentos para transacciones mayores (consultado: 2026-10-07). Estime el gas de despliegue primero. Para despliegues que superen el presupuesto de bloques pequeños, la cuenta de despliegue debe ser un usuario existente de HyperCore y firmar la acción de Core `{"type":"evmUserModify","usingBigBlocks":true}`; establecer únicamente un límite de gas de transacción mayor no selecciona bloques grandes. Restaure `usingBigBlocks=false` después para volver a los bloques pequeños.

En un proveedor que los admita, use `eth_usingBigBlocks` para verificar el modo de la dirección y `eth_bigBlockGasPrice` para la tarifa base de bloques grandes. La [referencia oficial de JSON-RPC](https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/hyperevm/json-rpc) documenta estos métodos (consultado: 2026-10-07). Verifique los métodos del proveedor elegido; use `/v1/chains` para BlockVectra. El despliegue mínimo anterior está destinado a un contrato pequeño y no cambia el modo de la cuenta de Core.

## Datos de HyperCore y HyperEVM

El RPC de EVM proporciona contratos, recibos y logs. Los datos de negociación y las acciones de HyperCore utilizan la API de Core. Los contratos pueden leer el estado de Core mediante precompilaciones y enviar acciones a través de CoreWriter; utilice la [guía de interacción oficial](https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/hyperevm/interacting-with-hypercore) al integrar estas vías (consultado: 2026-10-07). Los logs de EVM no sustituyen las consultas del libro de órdenes ni de posiciones de Core.

Las transacciones del sistema de HyperEVM (como las transferencias de HyperCore a HyperEVM) no se incluyen en las respuestas estándar de `eth_getBlockByNumber` y el RPC oficial las proporciona por separado a través de `eth_getSystemTxsByBlockNumber` y `eth_getSystemTxsByBlockHash` (consulte la [documentación oficial de JSON-RPC](https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/hyperevm/json-rpc), consultado: 2026-10-07). Los datos de bloques, transacciones y Data API de HyperEVM de BlockVectra actualmente no incluyen transacciones del sistema; utilice estos dos métodos del RPC oficial directamente cuando requiera datos de transacciones del sistema.

## Gestionar el error oficial 10055

La [guía oficial de HyperEVM](https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/hyperevm) define `10055` como un error en el límite Core/EVM, que incluye fallos de nonce, fondos insuficientes, hash duplicado y reemplazo con tarifa insuficiente (consultado: 2026-10-07). Inspeccione el mensaje del RPC de difusión antes de decidir cómo recuperarse:

* **Nonce:** compare `eth_getTransactionCount` con sus transacciones pendientes; serialice los envíos desde una misma cuenta de despliegue y reconcilie su siguiente nonce.
* **Fondos:** verifique el saldo de HYPE de EVM de la cuenta de despliegue contra el valor más el costo del gas.
* **Hash duplicado:** busque la transacción y el recibo existentes antes de enviar otra transacción.
* **Tarifa de reemplazo:** verifique el nonce y la tarifa existentes, luego use la política de reemplazo del difusor; repetir los mismos bytes no aumenta la tarifa.

`10055` por sí solo no justifica reintentos a ciegas. Lea los errores y sus pautas de recuperación por separado en la [referencia de errores de BlockVectra](https://docs.blockvectra.com/en/errors/).

## Límites de tasa del RPC público oficial y 429

La [documentación oficial de límites de tasa](https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/rate-limits-and-user-limits) de Hyperliquid especifica un máximo de 100 solicitudes JSON-RPC de EVM por minuto por IP para `rpc.hyperliquid.xyz/evm`. Su [documentación de JSON-RPC](https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/hyperevm/json-rpc) también limita `eth_getLogs` a 50 bloques por consulta y hasta 4 topics. Consultado: 2026-10-07.

Ante un HTTP 429, pause las solicitudes y respete primero `Retry-After` (segundos o una fecha HTTP). Si no está presente, use retroceso exponencial con variación aleatoria (jitter) y un límite acotado de reintentos, reintentando el mismo fragmento inconcluso. Reduzca la concurrencia y la frecuencia de polling, y divida las consultas de logs en fragmentos dentro del límite del endpoint. La fragmentación por sí sola no elimina los límites de tasa; los clientes que comparten una IP deben coordinar su tasa de solicitudes.

Para el endpoint con clave de BlockVectra, lea `max_logs_block_range`, `methods.allow` y `methods.deny` de `hyperevm_mainnet` desde [GET /v1/chains](https://api.blockvectra.com/v1/chains) en lugar de aplicar el intervalo de bloques o el límite de solicitudes por minuto del RPC público oficial. La tasa de solicitudes está sujeta por separado al `cu_per_sec`, `burst_cu` de la clave y al límite de llamadas del plan gratuito (consulte la siguiente sección). Ante un 429, inspeccione `error.data.reason` y `retryable`; `request_exceeds_burst` requiere solicitudes más pequeñas en lugar de reintentos idénticos con retroceso.

## Parámetros y reglas de servicio de BlockVectra

BlockVectra ofrece HyperEVM mainnet a través de endpoints JSON-RPC y REST Data API:

1. **Parámetros de la cadena y límites de logs**:
   De `GET /v1/chains` para `hyperevm_mainnet`:
   * **Identificador de cadena (Slug)**: `hyperevm_mainnet`, Chain ID `999`.
   * **`max_logs_block_range`**: Determinado por el campo `max_logs_block_range` de `GET /v1/chains`. Una sola solicitud `eth_getLogs` puede abarcar como máximo esta cantidad de bloques (`toBlock − fromBlock + 1`). Superar este intervalo devuelve HTTP 200 con código de error JSON-RPC `-32602` (`eth_getLogs block range too large: max <N> blocks`), el cual no se factura.
   * **`state_window_blocks`**: Determinado por el campo `state_window_blocks` de `GET /v1/chains`. Las llamadas de lectura de estado (como `eth_call` y `eth_getBalance`) están sujetas a la ventana de retención declarada por este campo (cuando es `null`, se conserva el estado completo sin un límite de ventana móvil).
   * **Política de métodos**: Determinada por `methods.allow` y `methods.deny`. Se permiten los métodos EVM estándar (`eth_blockNumber`, `eth_getLogs`, `eth_call`, `eth_getBalance`, `eth_getBlockByNumber`, `eth_getTransactionReceipt`, etc.); se deniegan los métodos de filtrado y suscripción (`eth_subscribe`, `eth_unsubscribe`, `eth_newFilter`, `eth_newBlockFilter`), devolviendo `-32601` (no facturado).
2. **Límites de tasa del nivel gratuito y actualización**:
   De `GET /v1/plans`:
   * **`free.max_calls_per_sec`**: hasta 25 llamadas por segundo, compartidas entre todas las API keys de la cuenta, todas las cadenas y la Data API.
   * **Límites predeterminados de clave**: Cada API key tiene un depósito de CU (recarga `cu_per_sec`, capacidad `burst_cu` — los valores predeterminados son 400 CU/s y ráfaga de 1,600 CU). Los métodos se miden por pesos de Compute Units (CU).
   * **Actualización de límites**: Tras recargar, se elimina el límite de llamadas por segundo a nivel de cuenta; cada clave permanece sujeta a los límites de tasa y ráfaga de Compute Units (CU). Para conocer las tarifas actuales y las unidades de facturación, consulte la [página de Precios](https://blockvectra.com/en/pricing/).

## Recopilación de logs históricos: eth\_getLogs fragmentado y lógica de reintento

Al consultar logs históricos, los intervalos amplios deben dividirse en fragmentos contiguos acotados por el `max_logs_block_range` de la cadena de destino. Las estrategias de reintento del cliente deben inspeccionar el campo `retryable` dentro de las respuestas de error.

### Evaluación de retryable en respuestas de error

En BlockVectra, los objetos de error JSON-RPC incluyen una carga útil `error.data` que contiene `reason`, `docs_url` y `retryable` (booleano):

* **`retryable: true`**: Condiciones transitorias, incluida sobrecarga del servicio (`overloaded`), límite de llamadas por segundo del plan gratuito (`free_plan_call_limit`), sincronización de nodos (`node_syncing`) o upstream no disponible (`upstream_unavailable`). Los clientes deben respetar el encabezado `Retry-After` cuando esté presente o aplicar retroceso exponencial con variación aleatoria (jitter).
* **`retryable: false`**: Errores no transitorios, como intervalo de bloques que excede los límites (`-32602` / `logs_range_too_large`), parámetros no válidos (`invalid_params`), API key ausente (`missing_api_key`) o solicitud que supera la capacidad de ráfaga (`-32022` / `request_exceeds_burst`). Reintentar sin ajustar los parámetros no tendrá éxito.

A continuación se muestra la respuesta devuelta cuando se omite una 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
    }
  }
}
```

## Uso de endpoints de Data API en lugar del escaneo exhaustivo con getLogs

Cuando una aplicación rastrea el historial de transacciones o movimientos de tokens para una dirección específica, escanear a través de `eth_getLogs` requiere emitir consultas fragmentadas secuenciales limitadas por `max_logs_block_range` y analizar los logs de eventos Transfer sin procesar.

La Data API de BlockVectra proporciona endpoints REST preindexados para `hyperevm_mainnet`, admitiendo intervalos de hasta 100,000 bloques con paginación basada en cursores:

1. **Transacciones de dirección**: `GET /v1/data/hyperevm_mainnet/addresses/{address}/transactions`
   * Parámetros: `from_block` (obligatorio), `to_block` (obligatorio), `direction` (opcional: `from`, `to`, `any`, predeterminado `any`), `clamp` (cadena booleana opcional, predeterminado `false`; cuando se establece en `true`, los intervalos que exceden 100,000 bloques o superiores a `as_of_block` se truncan en lugar de devolver 409), `limit` (opcional, máx. 500), `cursor` (token de paginación).
2. **Transferencias de tokens de dirección**: `GET /v1/data/hyperevm_mainnet/addresses/{address}/transfers`
   * Parámetros: `standard` (obligatorio: `erc20` o `erc721`; `erc1155` no se puede consultar por dirección y devuelve `422 no_coverage`), `token` (filtro opcional por contrato de token), `from_block` (obligatorio), `to_block` (obligatorio), `direction` (opcional: `in`, `out`, `any`), `clamp` (opcional), `limit`, `cursor`.

### Estructura de la respuesta

Las respuestas utilizan estructuras de respuesta estándar:

* `data`: Array de registros. Las transacciones incluyen `hash`, `block_number`, `block_timestamp`, `from`, `to`, `value`, `tx_index`, `gas_limit`, `gas_used` y `status`. Las transferencias incluyen `token`, `standard`, `from`, `to`, `block_number`, `block_timestamp`, `tx_hash`, `tx_index` y `log_index` (`amount` para ERC-20, `token_id` para ERC-721).
* `next_cursor`: Token de paginación opaco devuelto cuando existen registros posteriores (ausente en la página final, no `null`).
* `meta`: Metadatos que contienen `chain`, `chain_slug`, `chain_external_id`, `as_of_block`, `safe_block`, `finalized_block`, `coverage` (`full` o `partial`) y `refreshed_at`.

### Ejemplo de código: consultas a 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);
```


## Seguimiento en tiempo real: polling de nuevos bloques

Para un transporte HTTP, rastree bloques mediante polling y obtenga logs de eventos en fragmentos consecutivos dentro de `max_logs_block_range`. Seleccione WebSocket únicamente cuando `/v1/chains` reporte `ws=true` y la entrada requerida en `subscriptions`. Para entrega a un receptor HTTPS, use [push de webhook](https://docs.blockvectra.com/en/guides/webhook-push/).

Para probar el contrato `Hello` desplegado, establezca `LOG_ADDRESS` en su dirección. Envíe `ping()` a través del RPC de difusión y luego recopile el bloque del recibo con el script de recopilación de esta página. Continúe desde el último fragmento completado para nuevos eventos.

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

### Flujo de polling

1. Emita llamadas periódicas ligeras a `eth_blockNumber` para inspeccionar la cabecera más reciente de la cadena.
2. Compare el número de bloque devuelto con el `lastSeenBlock` procesado anteriormente.
3. Si `currentBlock > lastSeenBlock`, divida `[lastSeenBlock + 1, currentBlock]` en fragmentos de como máximo `max_logs_block_range`. Persista `lastSeenBlock` únicamente tras procesar con éxito cada fragmento; ante fallos, reintente el fragmento inconcluso. Deduplique por `(blockHash, transactionHash, logIndex)` y vuelva a reproducir un solapamiento después de reconectarse para reconciliar reorgs.
4. `watchBlockNumber` o `watchBlocks` de viem implementa de forma nativa polling HTTP bajo un transporte HTTP, permitiendo la personalización mediante el parámetro `pollingInterval` (como 1000 ms).

### Polling de logs de eventos en fragmentos delimitados

Guarde como `poll-logs.mjs` junto a `network.mjs` y `viem-client.mjs`. Establezca `BLOCKVECTRA_API_KEY`, `LOG_ADDRESS` y `FROM_BLOCK`, luego ejecute `node poll-logs.mjs`. Este ejemplo finito muestrea la cabecera 12 veces, con intervalos de cinco segundos, y consulta cada nuevo rango en fragmentos secuenciales. Un error detiene el script antes de avanzar el fragmento fallido.

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

Cada salida registra un fragmento completado. Para reanudar, establezca `FROM_BLOCK` en su `to + 1`; los consumidores duraderos deben guardar los eventos y el cursor juntos, deduplicar y reconciliar reorgs como se describió anteriormente. Para 429 u otros fallos reintentables, aplique las pautas de retroceso acotado al mismo fragmento inconcluso.

## Guías relacionadas

* Encuentre la URL del RPC público, los métodos compatibles y los límites actuales en la [página de la cadena HyperEVM](https://blockvectra.com/en/chains/hyperevm_mainnet/).
* Para conocer las reglas completas sobre intervalos de `eth_getLogs` y algoritmos de fragmentación, consulte [Límites de rango de bloques de eth\_getLogs y consultas fragmentadas](https://docs.blockvectra.com/en/guides/getlogs-block-range/).
* Para comparar `eth_getLogs` frente a las transferencias de Data API, entender los límites de `as_of_block` y los marcadores `safe_block` / `finalized_block`, consulte [eth\_getLogs y transferencias indexadas: cobertura y finalidad](https://docs.blockvectra.com/en/guides/logs-vs-transfers/).
* Para detalles sobre la medición de CU, errores no facturados y reintentos, consulte [Qué no se factura: códigos de error y reglas de facturación](https://docs.blockvectra.com/en/guides/billing-rules/).

## Próximos pasos

* [Explore el directorio de conjuntos de datos](https://blockvectra.com/en/data/) para ver todos los conjuntos de datos indexados por BlockVectra.
* [Consulte el plan gratuito y los precios](https://blockvectra.com/en/pricing/#free) para comprobar lo que incluye su cuenta.
* [Inicie sesión en la consola](https://console.blockvectra.com/login/?next=%2Fkeys%2F) para crear una API key.
