Interroger l'état historique de l'EVM dans les fenêtres prises en charge
Distinguez les fenêtres d'état authentifiées, l'historique sans clé et les plages de logs. Choisissez un bloc fixe pour eth_call et diagnostiquez les erreurs state_window.
eth_call historique dépend de la fenêtre d'état de la chaîne, et non de sa limite de plage de blocs eth_getLogs. Vérifiez la fenêtre d'état, le mode d'authentification de l'endpoint et le bloc cible avant de lire une valeur de contrat antérieure.
Trois limites d'historique différentes
| Champ dans GET /v1/chains | Ce qu'il contrôle | Ce qu'il faut vérifier |
|---|---|---|
state_window_blocks | Jusqu'où dans le passé les lectures d'état authentifiées telles que eth_call, eth_getBalance, eth_getCode et eth_getStorageAt peuvent interroger | Avec la tête H et la fenêtre déclarée W, un bloc numéroté antérieur à H − W se trouve en dehors de la fenêtre. Vérifiez également methods.allow et methods.deny. |
public.history_blocks | Références de blocs historiques via le public.url sans clé | Utilisez uniquement public.methods. Pour les lectures d'état, la plus petite valeur entre l'historique public et la fenêtre d'état déclarée s'applique. |
max_logs_block_range | Le nombre de blocs dans une seule requête eth_getLogs authentifiée | Comptez toBlock − fromBlock + 1. Une plage autorisée n'établit pas que l'état ancien du contrat ou les logs sont disponibles. |
Ces limites sont exprimées en blocs, et non en jours. Une fenêtre d'état null ou non déclarée n'établit pas une couverture d'archive. La disponibilité des méthodes sans clé est distincte de celle des méthodes authentifiées : une plage de logs à elle seule n'active pas eth_getLogs en accès public.
Comparer les fenêtres d'état par chaîne
Le tableau affiche les fenêtres d'état publiées, l'historique sans clé, les plages de logs et les jeux de données Data API déclarés à partir de l'instantané public. Pour une requête immédiate, lisez à nouveau GET /v1/chains et GET /v1/status.
Les développeurs et les agents IA doivent vérifier séparément les fenêtres d'état et les plages de requêtes de logs. Une fenêtre d'état null n'établit pas une couverture d'archive complète. L'historique public s'applique uniquement aux méthodes publiques déclarées.
| Chaîne | Slug de chaîne | Fenêtre d'état authentifiée : state_window_blocks (blocs) | Historique sans clé : public.history_blocks (blocs) | Plage de requêtes de logs authentifiée : max_logs_block_range (blocs) | Jeux de données Data API déclarés |
|---|---|---|---|---|---|
| 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 | Non déclaré | 1,000 | 1,000 | blocks, transactions, address_transactions, transfers, token_metadata, freshness |
| HyperEVM | hyperevm_mainnet | Non déclaré | 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 indisponible |
GET /v1/chains · Échantillonné (UTC):
GET /v1/status · Échantillonné (UTC):
Choisir un tag de bloc
Utilisez latest pour la valeur actuelle. Pour une comparaison historique, lisez eth_blockNumber une fois et convertissez le numéro de bloc choisi en une quantité hexadécimale telle que 0x18efa2f. Conservez ce numéro fixe pour chaque appel de la comparaison ; des appels latest répétés peuvent utiliser des blocs différents.
Pour les lectures d'état, earliest, safe et finalized renvoient -32011 selon la politique de fenêtre d'état. Choisissez plutôt un numéro de bloc explicite dans la fenêtre déclarée. L'utilisation d'un hash de bloc n'est pas un moyen d'obtenir un historique supplémentaire : les lectures d'état sans clé la rejettent, et une requête authentifiée dépend toujours de l'état disponible.
Un numéro de bloc peut faire référence à un bloc différent après une réorganisation. Enregistrez le hash du bloc avec eth_getBlockByNumber si vous devez identifier le bloc du résultat. Un numéro dans la fenêtre nécessite également une chaîne synchronisée et un contrat existant à cette hauteur.
Lecture de contrat à bloc fixe
Sur Ethereum, le WETH à l'adresse 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2 expose decimals() avec le sélecteur 0x313ce567. Un appel sans clé échantillonné le 2026-10-08 (UTC) au bloc 0x18efa2f a renvoyé HTTP 200 avec ce résultat :
Requête vers le public.url de la chaîne :
{
"jsonrpc": "2.0",
"id": 2,
"method": "eth_call",
"params": [
{ "to": "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", "data": "0x313ce567" },
"0x18efa2f"
]
}Réponse :
{
"jsonrpc": "2.0",
"id": 2,
"result": "0x0000000000000000000000000000000000000000000000000000000000000012"
}L'entier encodé en ABI est 18. Le résultat est une valeur de décimales, et non un solde, et n'établit pas la disponibilité à d'autres hauteurs. Ce bloc fixe sortira d'une fenêtre bornée au fil du temps ; utilisez un bloc récent lors de l'exécution ultérieure de l'exemple suivant.
Enregistrez l'exemple sous le nom historical-state.mjs et exécutez node historical-state.mjs avec Node.js 24 ou une version ultérieure et votre variable d'environnement BLOCKVECTRA_API_KEY définie. Il utilise l'endpoint authentifié, conserve le même contrat et calldata, et compare latest, un bloc récent fixe et un bloc en dehors de la fenêtre authentifiée publiée. Chaque sortie comprend le statut HTTP réel et le corps JSON-RPC ; un statut HTTP 200 peut toujours contenir une erreur. Il s'arrête en cas de réponse inattendue au lieu de la traiter comme une lecture réussie.
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 réponse enregistrée ci-dessus utilise public.url ; le script utilise une clé API. Pour effectuer une lecture sans clé, prenez l'URL directement depuis public.url, omettez la clé et choisissez un bloc situé dans public.history_blocks ainsi que dans la fenêtre d'état. Changer de mode d'authentification peut modifier l'historique autorisé, même pour le même contrat et calldata.
Diagnostiquer une erreur de fenêtre d'état dépassée
Sur le même endpoint sans clé, un appel échantillonné le 2026-10-08 (UTC) en changeant uniquement le bloc cible en 0x18ef650 (et l'ID de requête) a renvoyé HTTP 200 avec error.code: -32011, error.data.reason: state_window et error.data.retryable: false. Son message était block reference is outside the public history window. Il s'agit d'un échec lié à l'historique public ; l'endpoint authentifié possède sa propre fenêtre d'état.
Utilisez ces champs issus de l'entrée d'erreur state_window pour reconnaître l'échec plutôt que de vous fier à un numéro de fenêtre particulier dans le message :
| Champ | Valeur documentée ou signification |
|---|---|
| Statut HTTP | 200 ; inspectez l'error JSON-RPC même lorsque la requête HTTP réussit |
error.code | -32011 |
error.message | Les erreurs de fenêtre d'état authentifiée décrivent le nombre de blocs pris en charge les plus récents ; les erreurs d'historique public peuvent utiliser un message différent |
error.data.reason | state_window |
error.data.docs_url | Lien vers l'explication de state_window dans le catalogue des erreurs |
error.data.retryable | false : envoyer la même requête ultérieurement ne restaure pas l'état plus ancien |
Choisissez un bloc numéroté plus récent ou utilisez latest si la tâche nécessite la valeur actuelle. Réduire une plage eth_getLogs ne permet pas de récupérer l'état historique de eth_call. D'autres motifs associés à -32011 nécessitent des actions différentes : range_not_indexed exige une plage couverte ; history_not_ready permet de réessayer après le rattrapage de l'indexation. Inspectez error.data.reason, et pas seulement le code numérique.
L'état sous-jacent peut également être indisponible avec -32000, ou l'historique des blocs élagué avec 4444 ; consultez le catalogue des erreurs. Ne réessayez pas un bloc ancien sans modification et ne supposez pas qu'une fenêtre déclarée plus grande garantit chaque réponse.
Choisir la requête suivante
Pour une liste de contrôle complète de la charge de travail et des auto-tests, commencez par Comment choisir un fournisseur RPC.
Lors du choix d'un fournisseur pour des lectures de contrats répétées, comparez les budgets quotidiens et de cycle pour les lectures EVM. Vérifiez d'abord les blocs historiques requis, puis planifiez la répartition quotidienne et le débit de la tâche ; respecter un budget de crédits n'établit pas la couverture de l'état.
Lors de la comparaison de fournisseurs pour des lectures historiques, confirmez d'abord que les deux peuvent servir le bloc cible. La comparaison des dépassements de requête complète compare les prix des RU supplémentaires avec les coûts basés sur les méthodes, sépare le quota inclus de l'utilisation excédentaire et explique les classes de facturation complète et d'archive.
Pour les blocs, transactions, transferts ou autres jeux de données indexés plus anciens, consultez les jeux de données Data API déclarés dans le tableau et la référence de la Data API. Les enregistrements indexés ne fournissent pas d'exécution arbitraire de contrat historique et n'impliquent pas que chaque chaîne dispose de soldes historiques.
- Référence de la méthode eth_call pour les paramètres d'appel et l'encodage de retour.
- Plage de blocs eth_getLogs et requêtes découpées pour l'historique des logs d'événements.
- Configuration RPC personnalisée pour portefeuille pour les connexions de portefeuille et les clés dédiées.
- Chaînes prises en charge pour la disponibilité réseau et tarification en CU pour le coût des méthodes.
Dernière mise à jour :
Prix quotidiens DEX
Interrogez les prix OHLC et le VWAP quotidiens des DEX depuis la Data API, gérez les fractions rationnelles exactes en TypeScript et Python, et rattrapez efficacement les données historiques.
Forfait gratuit
Comprenez ce que couvre le forfait gratuit en fonction des poids réels des méthodes, avec des calculs basés sur les tâches et les options de mise à niveau.