diff --git a/.changeset/tricky-tigers-grow.md b/.changeset/tricky-tigers-grow.md new file mode 100644 index 000000000..ae09fd5ed --- /dev/null +++ b/.changeset/tricky-tigers-grow.md @@ -0,0 +1,5 @@ +--- +"@ponder/utils": patch +--- + +Added retry mechanism for publicnode. diff --git a/packages/utils/.env.example b/packages/utils/.env.example index b04cc012b..93f1423fd 100644 --- a/packages/utils/.env.example +++ b/packages/utils/.env.example @@ -11,4 +11,4 @@ RPC_URL_QUICKNODE_1=... RPC_URL_CHAINSTACK_1=... # Coinbase url -RPC_URL_COINBASE_8453=... \ No newline at end of file +RPC_URL_COINBASE_8453=... diff --git a/packages/utils/src/_test/publicnode.test.ts b/packages/utils/src/_test/publicnode.test.ts new file mode 100644 index 000000000..5b76be026 --- /dev/null +++ b/packages/utils/src/_test/publicnode.test.ts @@ -0,0 +1,58 @@ +import { numberToHex } from "viem"; +import { expect, test } from "vitest"; +import { getLogsRetryHelper } from "../getLogsRetryHelper.js"; +import { type Params, UNI, fromBlock, getRequest } from "./utils.js"; + +const request = getRequest("https://ethereum-rpc.publicnode.com"); +const maxBlockRange = 50_000n; + +test("publicnode success", async () => { + const logs = await request({ + method: "eth_getLogs", + params: [ + { + address: UNI, + fromBlock: numberToHex(fromBlock), + toBlock: numberToHex(fromBlock + maxBlockRange), + }, + ], + }); + + expect(logs).toHaveLength(203); +}); + +test("publicnode block range", async () => { + const params: Params = [ + { + fromBlock: numberToHex(fromBlock), + toBlock: numberToHex(fromBlock + maxBlockRange + 1n), + }, + ]; + + const error = await request({ + method: "eth_getLogs", + params, + }).catch((error) => error); + + expect(JSON.stringify(error)).includes("exceed maximum block range: 50000"); + + const retry = getLogsRetryHelper({ + params, + error: error, + }); + + expect(retry).toStrictEqual({ + isSuggestedRange: true, + shouldRetry: true, + ranges: [ + { + fromBlock: numberToHex(fromBlock), + toBlock: numberToHex(fromBlock + maxBlockRange), + }, + { + fromBlock: numberToHex(fromBlock + maxBlockRange + 1n), + toBlock: numberToHex(fromBlock + maxBlockRange + 1n), + }, + ], + }); +}); diff --git a/packages/utils/src/getLogsRetryHelper.ts b/packages/utils/src/getLogsRetryHelper.ts index d04046755..81e2e984a 100644 --- a/packages/utils/src/getLogsRetryHelper.ts +++ b/packages/utils/src/getLogsRetryHelper.ts @@ -338,6 +338,25 @@ export const getLogsRetryHelper = ({ } as const; } + // publicnode + match = sError.match(/maximum block range: ([\d,.]+)/); + if (match !== null) { + const ranges = chunk({ + params, + range: BigInt(match[1]!.replace(/[,.]/g, "")), + }); + + if (isRangeUnchanged(params, ranges)) { + return { shouldRetry: false } as const; + } + + return { + shouldRetry: true, + ranges, + isSuggestedRange: true, + } as const; + } + // No match found return { shouldRetry: false,