# Consultar el estado histórico EVM dentro de las ventanas compatibles

> Source: https://docs.blockvectra.com/es/guides/evm-historical-state/

El `eth_call` histórico depende de la ventana de estado de la cadena, no de su límite de rango de bloques de `eth_getLogs`. Compruebe la ventana de estado, el modo de autenticación del endpoint y el bloque de destino antes de leer un valor de contrato anterior.

## Tres límites históricos diferentes

| Campo de [GET /v1/chains](https://api.blockvectra.com/v1/chains) | Qué controla                                                                                                                            | Qué comprobar                                                                                                                                                         |
| ---------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `state_window_blocks`                                            | Hasta dónde pueden retroceder las lecturas de estado autenticadas como `eth_call`, `eth_getBalance`, `eth_getCode` y `eth_getStorageAt` | Con una cabecera `H` y una ventana declarada `W`, un bloque numerado anterior a `H − W` está fuera de la ventana. Compruebe también `methods.allow` y `methods.deny`. |
| `public.history_blocks`                                          | Referencias históricas de bloques mediante la `public.url` sin clave                                                                    | Utilice solo `public.methods`. Para lecturas de estado, se aplica el menor entre el historial público y la ventana de estado declarada.                               |
| `max_logs_block_range`                                           | El número de bloques de una solicitud `eth_getLogs` autenticada                                                                         | Cuente `toBlock − fromBlock + 1`. Una amplitud permitida no demuestra que estén disponibles el estado antiguo de contratos ni los logs antiguos.                      |

Estos límites se expresan en bloques, no en días. Una ventana de estado `null` o no declarada no demuestra cobertura de archivo. La disponibilidad de métodos sin clave es independiente de la disponibilidad de métodos autenticados: una amplitud de logs por sí sola no habilita `eth_getLogs` público.

## Comparar ventanas de estado por cadena

La tabla muestra las ventanas de estado publicadas, el historial sin clave, las amplitudes de logs y los conjuntos de datos de Data API declarados en la instantánea pública. Para una solicitud actual, vuelva a leer [GET /v1/chains](https://api.blockvectra.com/v1/chains) y [GET /v1/status](https://api.blockvectra.com/v1/status).

Los desarrolladores y agentes de IA deben verificar las ventanas de estado y los rangos de consulta de logs por separado. Una ventana de estado nula no establece cobertura de archivo histórico. El historial público se aplica únicamente a los métodos públicos declarados.

| Cadena | Slug de la cadena | Ventana de estado autenticada: state_window_blocks (bloques) | Historial sin clave: public.history_blocks (bloques) | Rango de consulta de logs autenticado: max_logs_block_range (bloques) | Conjuntos de datos de Data API declarados |
| --- | --- | --- | --- | --- | --- |
| Arbitrum One | `arb_mainnet` | 6,000 | 1,000 | 1,000 | blocks, transactions, address_transactions, transfers, token_metadata, freshness |
| Base | `base_mainnet` | 10,000 | 1,000 | 1,000 | blocks, transactions, address_transactions, transfers, token_metadata, freshness |
| BNB Smart Chain | `bsc_mainnet` | 100 | 100 | 1,000 | blocks, transactions, address_transactions, transfers, token_metadata, freshness |
| Ethereum | `eth_mainnet` | 250,000 | 1,000 | 1,000 | blocks, transactions, address_transactions, transfers, token_metadata, freshness |
| Ethereum Sepolia | `eth_sepolia` | No declarado | 1,000 | 1,000 | blocks, transactions, address_transactions, transfers, token_metadata, freshness |
| HyperEVM | `hyperevm_mainnet` | No declarado | 1,000 | 1,000 | blocks, transactions, address_transactions, transfers, token_metadata, balances, holders, nfts, freshness |
| Polygon | `polygon_mainnet` | 126 | 126 | 1,000 | blocks, transactions, address_transactions, transfers, token_metadata, freshness |
| Robinhood Chain | `robinhood_mainnet` | 900 | 900 | 1,000 | blocks, transactions, address_transactions, transfers, token_metadata, balances, holders, nfts, dex_swaps, dex_prices, stocks, traces, freshness |
| Robinhood Chain Testnet | `robinhood_testnet` | 1,023 | 1,000 | 1,000 | Data API no disponible |

[GET /v1/chains](https://api.blockvectra.com/v1/chains) · Muestreado (UTC): 2026-10-09

[GET /v1/status](https://api.blockvectra.com/v1/status) · Muestreado (UTC): 2026-10-09

## Elegir una etiqueta de bloque

Utilice `latest` para el valor actual. Para una comparación histórica, lea `eth_blockNumber` una vez y convierta un número de bloque elegido a una cantidad hexadecimal como `0x18efa2f`. Mantenga ese número fijo en cada llamada de la comparación; las llamadas repetidas a `latest` pueden utilizar bloques diferentes.

Para lecturas de estado, `earliest`, `safe` y `finalized` devuelven `-32011` según la política de ventana de estado. Elija en su lugar un número de bloque explícito dentro de la ventana declarada. La forma con hash de bloque no permite obtener historial adicional: las lecturas de estado sin clave la rechazan, y una solicitud autenticada sigue dependiendo del estado disponible.

Un número de bloque puede referirse a un bloque diferente tras una reorganización. Registre el hash del bloque con `eth_getBlockByNumber` si necesita identificar el bloque del resultado. Un número dentro de la ventana también requiere una cadena sincronizada y un contrato existente a esa altura.

## Leer un contrato en un bloque fijo

En Ethereum, WETH en `0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2` ofrece `decimals()` con el selector `0x313ce567`. Una llamada sin clave muestreada el 2026-10-08 (UTC) en el bloque `0x18efa2f` devolvió HTTP 200 con este resultado:

Solicitud a la `public.url` de la cadena:

```json
{
  "jsonrpc": "2.0",
  "id": 2,
  "method": "eth_call",
  "params": [
    { "to": "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", "data": "0x313ce567" },
    "0x18efa2f"
  ]
}
```

Respuesta:

```json
{
  "jsonrpc": "2.0",
  "id": 2,
  "result": "0x0000000000000000000000000000000000000000000000000000000000000012"
}
```

El entero codificado mediante ABI es 18. El resultado es un valor de decimales, no un saldo, y no demuestra disponibilidad en otras alturas. Ese bloque fijo acabará quedando fuera de una ventana acotada; utilice un bloque reciente cuando ejecute más adelante el ejemplo siguiente.

Guarde el ejemplo como `historical-state.mjs` y ejecute `node historical-state.mjs` con Node.js 24 o posterior y su variable de entorno `BLOCKVECTRA_API_KEY` establecida. Utiliza el endpoint autenticado, mantiene el mismo contrato y calldata, y compara `latest`, un bloque fijo reciente y un bloque fuera de la ventana autenticada publicada. Cada salida incluye el estado HTTP real y el body JSON-RPC; un HTTP 200 aún puede contener un error. Se detiene ante una respuesta inesperada en lugar de tratarla como una lectura exitosa.

```js
const key = process.env.BLOCKVECTRA_API_KEY;
if (!key) throw new Error('Set BLOCKVECTRA_API_KEY');
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 === 'eth_mainnet');
const matches = (method, pattern) => pattern.endsWith('*')
  ? method.startsWith(pattern.slice(0, -1)) : method === pattern;
if (!chain?.jsonrpc || !['eth_call', 'eth_blockNumber'].every(method =>
  chain.methods?.allow?.some(pattern => matches(method, pattern)) &&
  !chain.methods?.deny?.some(pattern => matches(method, pattern)))) {
  throw new Error('Required methods are unavailable');
}
const window = chain.state_window_blocks;
if (!Number.isSafeInteger(window) || window < 10) {
  throw new Error('This example needs a declared state window of at least 10 blocks');
}
const rpcUrl = new URL('./eth_mainnet', chainsUrl).href;
let id = 0;
async function rpc(method, params) {
  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: ++id, method, params }),
  });
  return { http: response.status, body: await response.json() };
}
const headResponse = await rpc('eth_blockNumber', []);
if (headResponse.http !== 200 || headResponse.body.error ||
    !/^0x[0-9a-f]+$/i.test(headResponse.body.result ?? '')) {
  throw new Error(`Cannot read head: ${JSON.stringify(headResponse)}`);
}
const head = BigInt(headResponse.body.result);
if (head <= BigInt(window)) throw new Error('Head is too low for an out-of-window block');
const hex = value => `0x${value.toString(16)}`;
const fixedBlock = hex(head - 10n);
const outsideBlock = hex(head - BigInt(window) - 1n);
const call = { to: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', data: '0x313ce567' };
for (const block of ['latest', fixedBlock, outsideBlock]) {
  const reply = await rpc('eth_call', [call, block]);
  console.log(JSON.stringify({ head: hex(head), block, ...reply }));
  if (block === outsideBlock) {
    if (reply.http !== 200 || reply.body.error?.code !== -32011 ||
        reply.body.error?.data?.reason !== 'state_window') {
      throw new Error('Expected state_window; inspect the actual response above');
    }
  } else if (reply.http !== 200 || reply.body.error ||
      reply.body.result !== '0x0000000000000000000000000000000000000000000000000000000000000012') {
    throw new Error('Expected the WETH decimals result; inspect the actual response above');
  }
}
```

La respuesta registrada arriba utiliza `public.url`; el script utiliza una API key. Para una lectura sin clave, tome la URL directamente de `public.url`, omita la clave y elija un bloque dentro de `public.history_blocks` y de la ventana de estado. Cambiar la autenticación puede cambiar el historial permitido, incluso para el mismo contrato y calldata.

## Diagnosticar un error fuera de la ventana

En el mismo endpoint sin clave, una llamada muestreada el 2026-10-08 (UTC) que cambió únicamente el bloque de destino a `0x18ef650` (y el ID de solicitud) devolvió HTTP 200 con `error.code: -32011`, `error.data.reason: state_window` y `error.data.retryable: false`. Su mensaje fue `block reference is outside the public history window`. Es un fallo de historial público; el endpoint autenticado tiene su propia ventana de estado.

Utilice estos campos de la [entrada de error state\_window](https://docs.blockvectra.com/en/errors/#state_window) para reconocer el fallo en lugar de depender de un número de ventana concreto del mensaje:

| Campo                  | Valor o significado documentado                                                                                                                                      |
| ---------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Estado HTTP            | `200`; revise el `error` JSON-RPC incluso cuando HTTP sea exitoso                                                                                                    |
| `error.code`           | `-32011`                                                                                                                                                             |
| `error.message`        | Los errores de ventana de estado autenticada describen el número de bloques más recientes compatibles; los errores de historial público pueden utilizar otro mensaje |
| `error.data.reason`    | `state_window`                                                                                                                                                       |
| `error.data.docs_url`  | Enlace a la explicación de `state_window` en el catálogo de errores                                                                                                  |
| `error.data.retryable` | `false`: enviar la misma solicitud más adelante no restaura el estado antiguo                                                                                        |

Elija un bloque numerado más reciente o utilice `latest` si la tarea necesita el valor actual. Reducir la amplitud de `eth_getLogs` no recupera el estado histórico de `eth_call`. Otros motivos de `-32011` requieren acciones diferentes: [range\_not\_indexed](https://docs.blockvectra.com/en/errors/#range_not_indexed) requiere un rango cubierto; [history\_not\_ready](https://docs.blockvectra.com/en/errors/#history_not_ready) permite reintentar cuando la indexación se pone al día. Revise `error.data.reason`, no solo el código numérico.

El estado subyacente también puede no estar disponible con `-32000`, o el historial de bloques puede haberse podado con `4444`; consulte el [catálogo de errores](https://docs.blockvectra.com/en/errors/). No reintente un bloque antiguo sin cambios ni suponga que una ventana declarada mayor garantiza todas las respuestas.

## Elegir la siguiente consulta

Para obtener una lista completa de comprobaciones de carga de trabajo y pruebas propias, comience con [Cómo elegir un proveedor RPC](https://docs.blockvectra.com/en/guides/choose-rpc-provider/).

Al elegir un proveedor para lecturas repetidas de contratos, [compare los presupuestos diarios y de ciclo para lecturas EVM](https://docs.blockvectra.com/en/guides/infura-alternative/). Compruebe primero los bloques históricos necesarios y después planifique la distribución diaria y la capacidad de procesamiento de la tarea; ajustarse a un presupuesto de créditos no demuestra cobertura de estado.

Al comparar proveedores para lecturas históricas, confirme primero que ambos puedan servir el bloque de destino. La [comparación de uso adicional de solicitudes full](https://docs.blockvectra.com/en/guides/chainstack-alternative/) compara los precios de RU adicionales con los costes por método, distingue la cuota incluida del uso adicional y explica las clases de facturación full y archive.

Para bloques, transacciones, transferencias u otros conjuntos de datos indexados anteriores, compruebe los conjuntos de datos de Data API declarados en la tabla y la [referencia de Data API](https://docs.blockvectra.com/en/api/data/). Los registros indexados no proporcionan ejecución histórica arbitraria de contratos ni implican que todas las cadenas tengan saldos históricos.

* [Referencia del método eth\_call](https://docs.blockvectra.com/en/api/json-rpc/methods/eth_call/) para los parámetros de llamada y la codificación de retorno.
* [Rango de bloques de eth\_getLogs y consultas por tramos](https://docs.blockvectra.com/en/guides/getlogs-block-range/) para el historial de logs de eventos.
* [Configuración de RPC personalizado de billeteras](https://docs.blockvectra.com/en/guides/wallet-custom-rpc/) para conexiones de billeteras y claves dedicadas.
* [Cadenas compatibles](https://docs.blockvectra.com/en/chains/) para la disponibilidad de redes y [precios CU](https://docs.blockvectra.com/en/guides/reading-cu-pricing/) para los costes de métodos.
