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

Distinga las ventanas de estado autenticadas, el historial sin clave y la amplitud de logs. Elija un bloque fijo para eth_call y diagnostique errores state_window.

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/chainsQué controlaQué comprobar
state_window_blocksHasta dónde pueden retroceder las lecturas de estado autenticadas como eth_call, eth_getBalance, eth_getCode y eth_getStorageAtCon 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_blocksReferencias históricas de bloques mediante la public.url sin claveUtilice 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_rangeEl número de bloques de una solicitud eth_getLogs autenticadaCuente 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 y GET /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.

CadenaSlug de la cadenaVentana 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 Onearb_mainnet6,0001,0001,000blocks, transactions, address_transactions, transfers, token_metadata, freshness
Basebase_mainnet10,0001,0001,000blocks, transactions, address_transactions, transfers, token_metadata, freshness
BNB Smart Chainbsc_mainnet1001001,000blocks, transactions, address_transactions, transfers, token_metadata, freshness
Ethereumeth_mainnet250,0001,0001,000blocks, transactions, address_transactions, transfers, token_metadata, freshness
Ethereum Sepoliaeth_sepoliaNo declarado1,0001,000blocks, transactions, address_transactions, transfers, token_metadata, freshness
HyperEVMhyperevm_mainnetNo declarado1,0001,000blocks, transactions, address_transactions, transfers, token_metadata, balances, holders, nfts, freshness
Polygonpolygon_mainnet1261261,000blocks, transactions, address_transactions, transfers, token_metadata, freshness
Robinhood Chainrobinhood_mainnet9009001,000blocks, transactions, address_transactions, transfers, token_metadata, balances, holders, nfts, dex_swaps, dex_prices, stocks, traces, freshness
Robinhood Chain Testnetrobinhood_testnet1,0231,0001,000Data API no disponible

GET /v1/chains · Muestreado (UTC):

GET /v1/status · Muestreado (UTC):

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:

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

Respuesta:

{
  "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.

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 para reconocer el fallo en lugar de depender de un número de ventana concreto del mensaje:

CampoValor o significado documentado
Estado HTTP200; revise el error JSON-RPC incluso cuando HTTP sea exitoso
error.code-32011
error.messageLos 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.reasonstate_window
error.data.docs_urlEnlace a la explicación de state_window en el catálogo de errores
error.data.retryablefalse: 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 requiere un rango cubierto; 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. 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.

Al elegir un proveedor para lecturas repetidas de contratos, compare los presupuestos diarios y de ciclo para lecturas EVM. 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 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. Los registros indexados no proporcionan ejecución histórica arbitraria de contratos ni implican que todas las cadenas tengan saldos históricos.

Última actualización:

En esta página