Repository: ponder-sh/ponder
Pull request #1714 (2025-05-01 14:34:20)

`getLogsRetryRanges()` somnia


Patch:
diff --git a/.changeset/funny-crabs-shake.md b/.changeset/funny-crabs-shake.md
new file mode 100644
index 00000000..a0f0dea9
--- /dev/null
+++ b/.changeset/funny-crabs-shake.md
@@ -0,0 +1,5 @@
+---
+"@ponder/utils": patch
+---
+
+Updated eth_getLogs retry helper to support somnia chain.
diff --git a/packages/utils/src/getLogsRetryHelper.ts b/packages/utils/src/getLogsRetryHelper.ts
index 641779fa..ab7fb4d8 100644
--- a/packages/utils/src/getLogsRetryHelper.ts
+++ b/packages/utils/src/getLogsRetryHelper.ts
@@ -319,7 +319,7 @@ export const getLogsRetryHelper = ({
   }
 
   // arbitrum
-  match = sError.match(/logs matched by query exceeds limit of 10000/);
+  match = sError.match(/logs matched by query exceeds limit of \d+/);
   if (match !== null) {
     const ranges = chunk({
       params,
@@ -456,6 +456,25 @@ export const getLogsRetryHelper = ({
     } as const;
   }
 
+  // somnia
+  match = sError.match(/block range exceeds ([\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,


Test patch:
diff --git a/packages/utils/src/_test/somnia.test.ts b/packages/utils/src/_test/somnia.test.ts
new file mode 100644
index 00000000..bd42f863
--- /dev/null
+++ b/packages/utils/src/_test/somnia.test.ts
@@ -0,0 +1,67 @@
+import { RpcRequestError, numberToHex } from "viem";
+import { expect, test } from "vitest";
+import { getLogsRetryHelper } from "../getLogsRetryHelper.js";
+import { type Params, getRequest } from "./utils.js";
+
+const request = getRequest("https://dream-rpc.somnia.network");
+const fromBlock = 53_580_000n;
+const maxBlockRange = 1_000n;
+
+test(
+  "somnia success",
+  async () => {
+    const logs = await request({
+      method: "eth_getLogs",
+      params: [
+        {
+          fromBlock: numberToHex(fromBlock),
+          toBlock: numberToHex(fromBlock + maxBlockRange),
+        },
+      ],
+    });
+
+    expect(logs).toHaveLength(5616);
+  },
+  { timeout: 15_000 },
+);
+
+test(
+  "somnia 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(error).toBeInstanceOf(RpcRequestError);
+    expect(JSON.stringify(error)).includes("block range exceeds 1000");
+
+    const retry = getLogsRetryHelper({
+      params,
+      error,
+    });
+
+    expect(retry).toStrictEqual({
+      shouldRetry: true,
+      isSuggestedRange: true,
+      ranges: [
+        {
+          fromBlock: numberToHex(fromBlock),
+          toBlock: numberToHex(fromBlock + maxBlockRange),
+        },
+        {
+          fromBlock: numberToHex(fromBlock + maxBlockRange + 1n),
+          toBlock: numberToHex(fromBlock + maxBlockRange + 1n),
+        },
+      ],
+    });
+  },
+  { timeout: 15_000 },
+);