diff --git a/src/indexer.test.ts b/src/indexer.test.ts index 23713d7..ad158ff 100644 --- a/src/indexer.test.ts +++ b/src/indexer.test.ts @@ -462,6 +462,60 @@ describe("counter contract", () => { }); }); + test("lagBlocks config option", async () => { + const mockRpcClient = { + ...rpcClient, + getLastBlockNumber: vi.fn() + .mockResolvedValueOnce(4n) + .mockResolvedValueOnce(4n) + .mockResolvedValue(4n) + .mockResolvedValue(6n) + }; + + const indexer = createIndexer({ + chain: { + id: 1, + rpcClient: mockRpcClient, + lagBlocks: 2n, + }, + contracts: Contracts, + }); + + indexer.on("Counter:Increment", handleIncrement); + indexer.on("Counter:Decrement", handleDecrement); + + indexer.subscribeToContract({ + contract: "Counter", + address: "0x0000000000000000000000000000000000000001", + }); + + + let tryTwice: boolean; + indexer.on("progress", ({ currentBlock, targetBlock }) => { + console.log(currentBlock); + console.log(targetBlock); + + if (currentBlock == targetBlock && targetBlock == 4n){ + if (tryTwice){ + indexer.stop(); + } + tryTwice = true; + } + }); + + await new Promise((resolve) => { + indexer.on("stopped", () => { + resolve(); + expect(tryTwice).toBe(true); + }); + + indexer.watch(); + }); + + }); + + + test("resumable index with the same indexer instance", async () => { const indexer = createIndexer({ chain: { diff --git a/src/indexer.ts b/src/indexer.ts index fd12083..83d6b2d 100644 --- a/src/indexer.ts +++ b/src/indexer.ts @@ -38,6 +38,7 @@ export type Config, TContext = unknown> = { rpcClient: RpcClient; pollingIntervalMs?: number; maxBlockRange?: bigint; + lagBlocks?: bigint; // New field for lag indexing strategy }; context?: TContext; logLevel?: keyof typeof LogLevel; @@ -176,6 +177,11 @@ export function createIndexer< // latest is a moving target if (state.finalTargetBlock === "latest") { finalTargetBlock = await rpcClient.getLastBlockNumber(); + + // Apply lag if specified + if (config.chain.lagBlocks) { + finalTargetBlock = applyLag(finalTargetBlock); + } } else { finalTargetBlock = state.finalTargetBlock; } @@ -464,6 +470,14 @@ export function createIndexer< } } + // Helper function to apply lag + function applyLag(blockNumber: bigint): bigint { + if (config.chain.lagBlocks && blockNumber > BigInt(config.chain.lagBlocks)) { + return blockNumber - BigInt(config.chain.lagBlocks); + } + return 0n; + } + return Object.setPrototypeOf( { context: config.context, @@ -524,6 +538,11 @@ export function createIndexer< if (target === "latest") { targetBlock = await rpcClient.getLastBlockNumber(); + + // Apply lag if specified + if (config.chain.lagBlocks) { + targetBlock = applyLag(targetBlock); + } } else { targetBlock = target; }