From 2ab396cc7f5ec4d16a6e76f7874948619a381bca Mon Sep 17 00:00:00 2001 From: Larry Lai Date: Sat, 14 Mar 2026 13:43:54 +0800 Subject: [PATCH] fix: tolerate missing historical state in indexer --- src/indexer/block.ts | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/src/indexer/block.ts b/src/indexer/block.ts index d799ffe..38e9e44 100644 --- a/src/indexer/block.ts +++ b/src/indexer/block.ts @@ -4,6 +4,11 @@ import { RpcClient } from './rpc.js'; import type { RpcBlock, RpcReceipt, RpcTransaction } from './types.js'; import { hexToBigIntString, hexToBuffer } from './utils.js'; +function isHistoricalStateError(error: unknown): boolean { + return error instanceof Error + && /Storage error|state|archive|histor/i.test(error.message); +} + export function parseHeight(hexValue: string): bigint { const parsed = hexToBigIntString(hexValue); if (!parsed) { @@ -110,8 +115,24 @@ async function upsertAccounts(client: PoolClient, addresses: string[], blockHeig export async function refreshAccountState( client: PoolClient, rpc: RpcClient, address: string, blockHex: string, blockHeight: bigint ): Promise { - const balanceHex = await rpc.callWithRetry('eth_getBalance', [address, blockHex]); - const nonceHex = await rpc.callWithRetry('eth_getTransactionCount', [address, blockHex]); + let balanceHex: string; + let nonceHex: string; + + try { + balanceHex = await rpc.callWithRetry('eth_getBalance', [address, blockHex]); + nonceHex = await rpc.callWithRetry('eth_getTransactionCount', [address, blockHex]); + } catch (error) { + if (!isHistoricalStateError(error)) { + throw error; + } + + console.warn( + `Historical state unavailable for ${address} at block ${blockHeight}; falling back to latest state` + ); + balanceHex = await rpc.callWithRetry('eth_getBalance', [address, 'latest']); + nonceHex = await rpc.callWithRetry('eth_getTransactionCount', [address, 'latest']); + } + const balance = hexToBigIntString(balanceHex) ?? '0'; const nonce = parseHeight(nonceHex).toString(10);