@1delta/providers 0.0.51 → 0.0.53

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.mts CHANGED
@@ -8482,6 +8482,7 @@ declare function createMulticallRetry(customRpcs?: Record<string, string[]>): (c
8482
8482
  * @see multicallRetryUniversal
8483
8483
  */
8484
8484
  declare function multicallRetry(chain: string, calls: any[], abi: any, batchSize?: number, maxRetries?: number, providerId?: number, allowFailure?: boolean, overrdies?: Record<string, string[]>, logErrors?: boolean): Promise<any[]>;
8485
+ declare function createMulticallRetryUniversal(customRpcs?: Record<string, string[]>): (params: MulticallRetryParams) => Promise<any[]>;
8485
8486
  declare function multicallRetryUniversal({ chain, calls, abi, batchSize, maxRetries, providerId, allowFailure, overrdies, logErrors, }: MulticallRetryParams): Promise<any[]>;
8486
8487
 
8487
- export { DEFAULT_BATCH_SIZE, LIST_OVERRIDES, type MulticallRetryParams, createMulticallRetry, createTransport, customChains, deepCompare, filterHttpRpcs, getEvmChain, getEvmClient, getEvmClientUniversal, getEvmClientWithCustomRpcs, getEvmClientWithCustomRpcsUniversal, getTransport, isArray, katana, multicallRetry, multicallRetryUniversal, plasma, trimTrailingSlash, uniq };
8488
+ export { DEFAULT_BATCH_SIZE, LIST_OVERRIDES, type MulticallRetryParams, createMulticallRetry, createMulticallRetryUniversal, createTransport, customChains, deepCompare, filterHttpRpcs, getEvmChain, getEvmClient, getEvmClientUniversal, getEvmClientWithCustomRpcs, getEvmClientWithCustomRpcsUniversal, getTransport, isArray, katana, multicallRetry, multicallRetryUniversal, plasma, trimTrailingSlash, uniq };
package/dist/index.d.ts CHANGED
@@ -8482,6 +8482,7 @@ declare function createMulticallRetry(customRpcs?: Record<string, string[]>): (c
8482
8482
  * @see multicallRetryUniversal
8483
8483
  */
8484
8484
  declare function multicallRetry(chain: string, calls: any[], abi: any, batchSize?: number, maxRetries?: number, providerId?: number, allowFailure?: boolean, overrdies?: Record<string, string[]>, logErrors?: boolean): Promise<any[]>;
8485
+ declare function createMulticallRetryUniversal(customRpcs?: Record<string, string[]>): (params: MulticallRetryParams) => Promise<any[]>;
8485
8486
  declare function multicallRetryUniversal({ chain, calls, abi, batchSize, maxRetries, providerId, allowFailure, overrdies, logErrors, }: MulticallRetryParams): Promise<any[]>;
8486
8487
 
8487
- export { DEFAULT_BATCH_SIZE, LIST_OVERRIDES, type MulticallRetryParams, createMulticallRetry, createTransport, customChains, deepCompare, filterHttpRpcs, getEvmChain, getEvmClient, getEvmClientUniversal, getEvmClientWithCustomRpcs, getEvmClientWithCustomRpcsUniversal, getTransport, isArray, katana, multicallRetry, multicallRetryUniversal, plasma, trimTrailingSlash, uniq };
8488
+ export { DEFAULT_BATCH_SIZE, LIST_OVERRIDES, type MulticallRetryParams, createMulticallRetry, createMulticallRetryUniversal, createTransport, customChains, deepCompare, filterHttpRpcs, getEvmChain, getEvmClient, getEvmClientUniversal, getEvmClientWithCustomRpcs, getEvmClientWithCustomRpcsUniversal, getTransport, isArray, katana, multicallRetry, multicallRetryUniversal, plasma, trimTrailingSlash, uniq };
package/dist/index.js CHANGED
@@ -13453,6 +13453,7 @@ __export(index_exports, {
13453
13453
  DEFAULT_BATCH_SIZE: () => DEFAULT_BATCH_SIZE,
13454
13454
  LIST_OVERRIDES: () => LIST_OVERRIDES,
13455
13455
  createMulticallRetry: () => createMulticallRetry,
13456
+ createMulticallRetryUniversal: () => createMulticallRetryUniversal,
13456
13457
  createTransport: () => createTransport2,
13457
13458
  customChains: () => customChains,
13458
13459
  deepCompare: () => deepCompare,
@@ -24984,7 +24985,6 @@ var LIST_OVERRIDES = {
24984
24985
  "https://erpc.xdcrpc.com"
24985
24986
  ],
24986
24987
  [import_chain_registry2.Chain.ETHEREUM_MAINNET]: [
24987
- "https://eth.llamarpc.com",
24988
24988
  "https://api.zan.top/eth-mainnet",
24989
24989
  "https://rpc.flashbots.net/fast",
24990
24990
  "https://rpc.owlracle.info/eth/70d38ce1826c4a60bb2a8e05a6c8b20f",
@@ -24995,6 +24995,7 @@ var LIST_OVERRIDES = {
24995
24995
  "https://rpc.flashbots.net",
24996
24996
  "https://public-eth.nownodes.io",
24997
24997
  "https://ethereum-json-rpc.stakely.io",
24998
+ "https://eth.llamarpc.com",
24998
24999
  "https://eth.blockrazor.xyz",
24999
25000
  "https://eth.drpc.org",
25000
25001
  "https://ethereum.public.blockpi.network/v1/rpc/public",
@@ -25098,10 +25099,13 @@ var LIST_OVERRIDES = {
25098
25099
  "https://avax-rpc.gateway.pokt.network"
25099
25100
  ],
25100
25101
  [import_chain_registry2.Chain.CELO_MAINNET]: [
25102
+ "https://celo-mainnet.gateway.tatum.io",
25103
+ "https://celo-json-rpc.stakely.io",
25101
25104
  "https://forno.celo.org",
25102
25105
  "https://1rpc.io/celo",
25103
25106
  "https://celo.drpc.org",
25104
- "https://celo-rpc.publicnode.com"
25107
+ "https://celo-rpc.publicnode.com",
25108
+ "https://rpc.ankr.com/celo"
25105
25109
  ],
25106
25110
  [import_chain_registry2.Chain.BLAST]: [
25107
25111
  "https://rpc.blast.io",
@@ -25197,6 +25201,10 @@ var LIST_OVERRIDES = {
25197
25201
  "https://tac.therpc.io",
25198
25202
  "https://ws.rpc.tac.build"
25199
25203
  ],
25204
+ [import_chain_registry2.Chain.BOTANIX_MAINNET]: [
25205
+ "https://rpc.botanixlabs.com",
25206
+ "https://rpc.ankr.com/botanix_mainnet"
25207
+ ],
25200
25208
  [import_chain_registry2.Chain.UNICHAIN]: [
25201
25209
  "https://mainnet.unichain.org",
25202
25210
  "https://rpc.sentio.xyz/unichain-mainnet",
@@ -25341,17 +25349,52 @@ function getEvmClientWithCustomRpcsUniversal({
25341
25349
  }
25342
25350
 
25343
25351
  // src/multicall/multicall.ts
25344
- function isTransportError(e) {
25345
- const msg = e instanceof Error ? (e.message ?? "") + (e.details ?? "") : "";
25346
- return msg.includes("is not a constructor") || msg.includes("Dynamic require") || msg.includes("is not supported") || msg.includes("wrong json-rpc response") || msg.includes("there is neither result nor error");
25347
- }
25352
+ var HTTP_ERROR_CODES = /* @__PURE__ */ new Set([
25353
+ "ECONNRESET",
25354
+ "ECONNREFUSED",
25355
+ "ECONNABORTED",
25356
+ "ETIMEDOUT",
25357
+ "ENOTFOUND",
25358
+ "EPIPE",
25359
+ "EAI_AGAIN",
25360
+ "ERR_SOCKET_TIMEOUT",
25361
+ "UND_ERR_CONNECT_TIMEOUT",
25362
+ "UND_ERR_HEADERS_TIMEOUT",
25363
+ "UND_ERR_BODY_TIMEOUT",
25364
+ "UND_ERR_SOCKET"
25365
+ ]);
25366
+ var HTTP_ERROR_STRINGS = [
25367
+ "rate-limit",
25368
+ "Too Many Requests",
25369
+ "Bad gateway",
25370
+ "Service Unavailable",
25371
+ "<!DOCTYPE html>",
25372
+ "HTTP request failed",
25373
+ "fetch failed",
25374
+ "not whitelisted",
25375
+ "timed out",
25376
+ "timeout",
25377
+ "took too long",
25378
+ "socket hang up",
25379
+ "network error",
25380
+ "request aborted",
25381
+ "body exceeded",
25382
+ "CORS",
25383
+ "AbortError",
25384
+ "-32601",
25385
+ "-32005",
25386
+ "exceeded",
25387
+ "limit reached",
25388
+ "overloaded"
25389
+ ];
25348
25390
  function isHttpError(e) {
25349
25391
  const err = e;
25350
25392
  const code = err?.code ?? err?.cause?.code;
25351
- if (code === "ECONNRESET" || code === "ETIMEDOUT" || code === "ENOTFOUND")
25352
- return true;
25393
+ if (code && HTTP_ERROR_CODES.has(code)) return true;
25353
25394
  if (err?.status === 401 || err?.status === 429 || err?.status >= 500)
25354
25395
  return true;
25396
+ if (err?.name === "AbortError" || err?.cause?.name === "AbortError")
25397
+ return true;
25355
25398
  if (e instanceof BaseError2) {
25356
25399
  let current = e;
25357
25400
  while (current) {
@@ -25360,15 +25403,13 @@ function isHttpError(e) {
25360
25403
  const details = current.details ?? "";
25361
25404
  const message = current.message ?? "";
25362
25405
  const combined = `${message} ${details}`;
25363
- if (combined.includes("rate-limit") || combined.includes("Too Many Requests") || combined.includes("Bad gateway") || combined.includes("<!DOCTYPE html>") || combined.includes("HTTP request failed") || combined.includes("not whitelisted") || combined.includes("timed out") || combined.includes("timeout") || combined.includes("took too long") || combined.includes("-32601"))
25364
- return true;
25406
+ if (HTTP_ERROR_STRINGS.some((s) => combined.includes(s))) return true;
25365
25407
  current = current.cause ?? null;
25366
25408
  }
25367
25409
  }
25368
25410
  if (e instanceof Error) {
25369
25411
  const combined = `${e.message ?? ""} ${e.details ?? ""}`;
25370
- if (combined.includes("HTTP request failed") || combined.includes("fetch failed") || combined.includes("not whitelisted") || combined.includes("timed out") || combined.includes("timeout") || combined.includes("took too long") || combined.includes("-32601"))
25371
- return true;
25412
+ if (HTTP_ERROR_STRINGS.some((s) => combined.includes(s))) return true;
25372
25413
  }
25373
25414
  return false;
25374
25415
  }
@@ -25481,8 +25522,11 @@ function createMulticallRetry(customRpcs = LIST_OVERRIDES) {
25481
25522
  maxSkips
25482
25523
  );
25483
25524
  }
25484
- if ((isHttpError(e) || isTransportError(e)) && maxSkips > 0) {
25485
- if (logErrors) console.debug(e);
25525
+ if (maxSkips > 0) {
25526
+ if (logErrors) {
25527
+ const tag = isHttpError(e) ? "HTTP" : "unknown-transient";
25528
+ console.debug(`[multicall] ${tag} error on provider ${providerId}, skipping`, e);
25529
+ }
25486
25530
  return await multicallRetry2(
25487
25531
  chain,
25488
25532
  calls,
@@ -25543,6 +25587,21 @@ async function multicallRetry(chain, calls, abi2, batchSize = DEFAULT_BATCH_SIZE
25543
25587
  logErrors
25544
25588
  );
25545
25589
  }
25590
+ function createMulticallRetryUniversal(customRpcs = LIST_OVERRIDES) {
25591
+ return async function multicallRetryUniversal2(params) {
25592
+ return multicallRetryInternal(
25593
+ params.chain,
25594
+ params.calls,
25595
+ params.abi,
25596
+ params.batchSize,
25597
+ params.maxRetries,
25598
+ params.providerId,
25599
+ params.allowFailure,
25600
+ customRpcs,
25601
+ params.logErrors
25602
+ );
25603
+ };
25604
+ }
25546
25605
  async function multicallRetryUniversal({
25547
25606
  chain,
25548
25607
  calls,
@@ -25571,6 +25630,7 @@ async function multicallRetryUniversal({
25571
25630
  DEFAULT_BATCH_SIZE,
25572
25631
  LIST_OVERRIDES,
25573
25632
  createMulticallRetry,
25633
+ createMulticallRetryUniversal,
25574
25634
  createTransport,
25575
25635
  customChains,
25576
25636
  deepCompare,
package/dist/index.mjs CHANGED
@@ -11224,7 +11224,6 @@ var LIST_OVERRIDES = {
11224
11224
  "https://erpc.xdcrpc.com"
11225
11225
  ],
11226
11226
  [Chain2.ETHEREUM_MAINNET]: [
11227
- "https://eth.llamarpc.com",
11228
11227
  "https://api.zan.top/eth-mainnet",
11229
11228
  "https://rpc.flashbots.net/fast",
11230
11229
  "https://rpc.owlracle.info/eth/70d38ce1826c4a60bb2a8e05a6c8b20f",
@@ -11235,6 +11234,7 @@ var LIST_OVERRIDES = {
11235
11234
  "https://rpc.flashbots.net",
11236
11235
  "https://public-eth.nownodes.io",
11237
11236
  "https://ethereum-json-rpc.stakely.io",
11237
+ "https://eth.llamarpc.com",
11238
11238
  "https://eth.blockrazor.xyz",
11239
11239
  "https://eth.drpc.org",
11240
11240
  "https://ethereum.public.blockpi.network/v1/rpc/public",
@@ -11338,10 +11338,13 @@ var LIST_OVERRIDES = {
11338
11338
  "https://avax-rpc.gateway.pokt.network"
11339
11339
  ],
11340
11340
  [Chain2.CELO_MAINNET]: [
11341
+ "https://celo-mainnet.gateway.tatum.io",
11342
+ "https://celo-json-rpc.stakely.io",
11341
11343
  "https://forno.celo.org",
11342
11344
  "https://1rpc.io/celo",
11343
11345
  "https://celo.drpc.org",
11344
- "https://celo-rpc.publicnode.com"
11346
+ "https://celo-rpc.publicnode.com",
11347
+ "https://rpc.ankr.com/celo"
11345
11348
  ],
11346
11349
  [Chain2.BLAST]: [
11347
11350
  "https://rpc.blast.io",
@@ -11437,6 +11440,10 @@ var LIST_OVERRIDES = {
11437
11440
  "https://tac.therpc.io",
11438
11441
  "https://ws.rpc.tac.build"
11439
11442
  ],
11443
+ [Chain2.BOTANIX_MAINNET]: [
11444
+ "https://rpc.botanixlabs.com",
11445
+ "https://rpc.ankr.com/botanix_mainnet"
11446
+ ],
11440
11447
  [Chain2.UNICHAIN]: [
11441
11448
  "https://mainnet.unichain.org",
11442
11449
  "https://rpc.sentio.xyz/unichain-mainnet",
@@ -11581,17 +11588,52 @@ function getEvmClientWithCustomRpcsUniversal({
11581
11588
  }
11582
11589
 
11583
11590
  // src/multicall/multicall.ts
11584
- function isTransportError(e) {
11585
- const msg = e instanceof Error ? (e.message ?? "") + (e.details ?? "") : "";
11586
- return msg.includes("is not a constructor") || msg.includes("Dynamic require") || msg.includes("is not supported") || msg.includes("wrong json-rpc response") || msg.includes("there is neither result nor error");
11587
- }
11591
+ var HTTP_ERROR_CODES = /* @__PURE__ */ new Set([
11592
+ "ECONNRESET",
11593
+ "ECONNREFUSED",
11594
+ "ECONNABORTED",
11595
+ "ETIMEDOUT",
11596
+ "ENOTFOUND",
11597
+ "EPIPE",
11598
+ "EAI_AGAIN",
11599
+ "ERR_SOCKET_TIMEOUT",
11600
+ "UND_ERR_CONNECT_TIMEOUT",
11601
+ "UND_ERR_HEADERS_TIMEOUT",
11602
+ "UND_ERR_BODY_TIMEOUT",
11603
+ "UND_ERR_SOCKET"
11604
+ ]);
11605
+ var HTTP_ERROR_STRINGS = [
11606
+ "rate-limit",
11607
+ "Too Many Requests",
11608
+ "Bad gateway",
11609
+ "Service Unavailable",
11610
+ "<!DOCTYPE html>",
11611
+ "HTTP request failed",
11612
+ "fetch failed",
11613
+ "not whitelisted",
11614
+ "timed out",
11615
+ "timeout",
11616
+ "took too long",
11617
+ "socket hang up",
11618
+ "network error",
11619
+ "request aborted",
11620
+ "body exceeded",
11621
+ "CORS",
11622
+ "AbortError",
11623
+ "-32601",
11624
+ "-32005",
11625
+ "exceeded",
11626
+ "limit reached",
11627
+ "overloaded"
11628
+ ];
11588
11629
  function isHttpError(e) {
11589
11630
  const err = e;
11590
11631
  const code = err?.code ?? err?.cause?.code;
11591
- if (code === "ECONNRESET" || code === "ETIMEDOUT" || code === "ENOTFOUND")
11592
- return true;
11632
+ if (code && HTTP_ERROR_CODES.has(code)) return true;
11593
11633
  if (err?.status === 401 || err?.status === 429 || err?.status >= 500)
11594
11634
  return true;
11635
+ if (err?.name === "AbortError" || err?.cause?.name === "AbortError")
11636
+ return true;
11595
11637
  if (e instanceof BaseError) {
11596
11638
  let current = e;
11597
11639
  while (current) {
@@ -11600,15 +11642,13 @@ function isHttpError(e) {
11600
11642
  const details = current.details ?? "";
11601
11643
  const message = current.message ?? "";
11602
11644
  const combined = `${message} ${details}`;
11603
- if (combined.includes("rate-limit") || combined.includes("Too Many Requests") || combined.includes("Bad gateway") || combined.includes("<!DOCTYPE html>") || combined.includes("HTTP request failed") || combined.includes("not whitelisted") || combined.includes("timed out") || combined.includes("timeout") || combined.includes("took too long") || combined.includes("-32601"))
11604
- return true;
11645
+ if (HTTP_ERROR_STRINGS.some((s) => combined.includes(s))) return true;
11605
11646
  current = current.cause ?? null;
11606
11647
  }
11607
11648
  }
11608
11649
  if (e instanceof Error) {
11609
11650
  const combined = `${e.message ?? ""} ${e.details ?? ""}`;
11610
- if (combined.includes("HTTP request failed") || combined.includes("fetch failed") || combined.includes("not whitelisted") || combined.includes("timed out") || combined.includes("timeout") || combined.includes("took too long") || combined.includes("-32601"))
11611
- return true;
11651
+ if (HTTP_ERROR_STRINGS.some((s) => combined.includes(s))) return true;
11612
11652
  }
11613
11653
  return false;
11614
11654
  }
@@ -11721,8 +11761,11 @@ function createMulticallRetry(customRpcs = LIST_OVERRIDES) {
11721
11761
  maxSkips
11722
11762
  );
11723
11763
  }
11724
- if ((isHttpError(e) || isTransportError(e)) && maxSkips > 0) {
11725
- if (logErrors) console.debug(e);
11764
+ if (maxSkips > 0) {
11765
+ if (logErrors) {
11766
+ const tag = isHttpError(e) ? "HTTP" : "unknown-transient";
11767
+ console.debug(`[multicall] ${tag} error on provider ${providerId}, skipping`, e);
11768
+ }
11726
11769
  return await multicallRetry2(
11727
11770
  chain,
11728
11771
  calls,
@@ -11783,6 +11826,21 @@ async function multicallRetry(chain, calls, abi2, batchSize = DEFAULT_BATCH_SIZE
11783
11826
  logErrors
11784
11827
  );
11785
11828
  }
11829
+ function createMulticallRetryUniversal(customRpcs = LIST_OVERRIDES) {
11830
+ return async function multicallRetryUniversal2(params) {
11831
+ return multicallRetryInternal(
11832
+ params.chain,
11833
+ params.calls,
11834
+ params.abi,
11835
+ params.batchSize,
11836
+ params.maxRetries,
11837
+ params.providerId,
11838
+ params.allowFailure,
11839
+ customRpcs,
11840
+ params.logErrors
11841
+ );
11842
+ };
11843
+ }
11786
11844
  async function multicallRetryUniversal({
11787
11845
  chain,
11788
11846
  calls,
@@ -11810,6 +11868,7 @@ export {
11810
11868
  DEFAULT_BATCH_SIZE,
11811
11869
  LIST_OVERRIDES,
11812
11870
  createMulticallRetry,
11871
+ createMulticallRetryUniversal,
11813
11872
  createTransport2 as createTransport,
11814
11873
  customChains,
11815
11874
  deepCompare,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@1delta/providers",
3
- "version": "0.0.51",
3
+ "version": "0.0.53",
4
4
  "description": "",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
@@ -7,35 +7,63 @@ import { LIST_OVERRIDES } from '../rpc/rpcOverrides'
7
7
  import { getEvmClientWithCustomRpcsUniversal } from '../client/client'
8
8
  import { DEFAULT_BATCH_SIZE, deepCompare, isArray } from '../utils/utils'
9
9
 
10
- /** Return true if the error is a transport/environment issue (not an RPC or contract error) */
11
- function isTransportError(e: unknown): boolean {
12
- const msg =
13
- e instanceof Error ? (e.message ?? '') + ((e as any).details ?? '') : ''
14
- return (
15
- msg.includes('is not a constructor') ||
16
- msg.includes('Dynamic require') ||
17
- msg.includes('is not supported') ||
18
- msg.includes('wrong json-rpc response') ||
19
- msg.includes('there is neither result nor error')
20
- )
21
- }
10
+ /** Connection-level error codes that indicate a transport failure */
11
+ const HTTP_ERROR_CODES = new Set([
12
+ 'ECONNRESET',
13
+ 'ECONNREFUSED',
14
+ 'ECONNABORTED',
15
+ 'ETIMEDOUT',
16
+ 'ENOTFOUND',
17
+ 'EPIPE',
18
+ 'EAI_AGAIN',
19
+ 'ERR_SOCKET_TIMEOUT',
20
+ 'UND_ERR_CONNECT_TIMEOUT',
21
+ 'UND_ERR_HEADERS_TIMEOUT',
22
+ 'UND_ERR_BODY_TIMEOUT',
23
+ 'UND_ERR_SOCKET',
24
+ ])
25
+
26
+ /** Substrings in error messages that indicate an HTTP/transport failure */
27
+ const HTTP_ERROR_STRINGS = [
28
+ 'rate-limit',
29
+ 'Too Many Requests',
30
+ 'Bad gateway',
31
+ 'Service Unavailable',
32
+ '<!DOCTYPE html>',
33
+ 'HTTP request failed',
34
+ 'fetch failed',
35
+ 'not whitelisted',
36
+ 'timed out',
37
+ 'timeout',
38
+ 'took too long',
39
+ 'socket hang up',
40
+ 'network error',
41
+ 'request aborted',
42
+ 'body exceeded',
43
+ 'CORS',
44
+ 'AbortError',
45
+ '-32601',
46
+ '-32005',
47
+ 'exceeded',
48
+ 'limit reached',
49
+ 'overloaded',
50
+ ]
22
51
 
23
52
  /** Return true if the error is an HTTP-level failure (429, 502, 503, etc.) rather than a contract/RPC error */
24
53
  function isHttpError(e: unknown): boolean {
25
54
  // Check connection-level error codes on the error and its cause chain
26
55
  const err = e as any
27
56
  const code = err?.code ?? err?.cause?.code
28
- if (
29
- code === 'ECONNRESET' ||
30
- code === 'ETIMEDOUT' ||
31
- code === 'ENOTFOUND'
32
- )
33
- return true
57
+ if (code && HTTP_ERROR_CODES.has(code)) return true
34
58
 
35
59
  // Check numeric status on the error itself (non-BaseError cases)
36
60
  if (err?.status === 401 || err?.status === 429 || err?.status >= 500)
37
61
  return true
38
62
 
63
+ // Check error name (e.g. AbortError from fetch timeout)
64
+ if (err?.name === 'AbortError' || err?.cause?.name === 'AbortError')
65
+ return true
66
+
39
67
  // Walk the BaseError cause chain for status codes and detail strings
40
68
  if (e instanceof BaseError) {
41
69
  let current: any = e
@@ -45,19 +73,7 @@ function isHttpError(e: unknown): boolean {
45
73
  const details: string = current.details ?? ''
46
74
  const message: string = current.message ?? ''
47
75
  const combined = `${message} ${details}`
48
- if (
49
- combined.includes('rate-limit') ||
50
- combined.includes('Too Many Requests') ||
51
- combined.includes('Bad gateway') ||
52
- combined.includes('<!DOCTYPE html>') ||
53
- combined.includes('HTTP request failed') ||
54
- combined.includes('not whitelisted') ||
55
- combined.includes('timed out') ||
56
- combined.includes('timeout') ||
57
- combined.includes('took too long') ||
58
- combined.includes('-32601')
59
- )
60
- return true
76
+ if (HTTP_ERROR_STRINGS.some((s) => combined.includes(s))) return true
61
77
  current = current.cause ?? null
62
78
  }
63
79
  }
@@ -65,16 +81,7 @@ function isHttpError(e: unknown): boolean {
65
81
  // Fallback: check message + details as strings for non-BaseError errors
66
82
  if (e instanceof Error) {
67
83
  const combined = `${e.message ?? ''} ${(e as any).details ?? ''}`
68
- if (
69
- combined.includes('HTTP request failed') ||
70
- combined.includes('fetch failed') ||
71
- combined.includes('not whitelisted') ||
72
- combined.includes('timed out') ||
73
- combined.includes('timeout') ||
74
- combined.includes('took too long') ||
75
- combined.includes('-32601')
76
- )
77
- return true
84
+ if (HTTP_ERROR_STRINGS.some((s) => combined.includes(s))) return true
78
85
  }
79
86
 
80
87
  return false
@@ -256,10 +263,14 @@ export function createMulticallRetry(
256
263
  )
257
264
  }
258
265
 
259
- // Rate-limit (429) or transport/environment errors:
260
- // skip to next RPC without consuming a retry
261
- if ((isHttpError(e) || isTransportError(e)) && maxSkips > 0) {
262
- if (logErrors) console.debug(e)
266
+ // Any non-revert, non-OOG error is treated as transient (HTTP, transport,
267
+ // rate-limit, unknown RPC error). Skip to next RPC without consuming a
268
+ // retry only deterministic errors (revert, OOG) are handled above.
269
+ if (maxSkips > 0) {
270
+ if (logErrors) {
271
+ const tag = isHttpError(e) ? 'HTTP' : 'unknown-transient'
272
+ console.debug(`[multicall] ${tag} error on provider ${providerId}, skipping`, e)
273
+ }
263
274
  return await multicallRetry(
264
275
  chain,
265
276
  calls,
@@ -280,6 +291,7 @@ export function createMulticallRetry(
280
291
  return Array(calls.length).fill('0x')
281
292
  }
282
293
 
294
+ // Skips exhausted — consume a retry and rotate RPC
283
295
  if (logErrors) console.debug(e)
284
296
 
285
297
  return await multicallRetry(
@@ -350,6 +362,26 @@ export async function multicallRetry(
350
362
  )
351
363
  }
352
364
 
365
+ export function createMulticallRetryUniversal(
366
+ customRpcs: Record<string, string[]> = LIST_OVERRIDES,
367
+ ) {
368
+ return async function multicallRetryUniversal(
369
+ params: MulticallRetryParams,
370
+ ): Promise<any[]> {
371
+ return multicallRetryInternal(
372
+ params.chain,
373
+ params.calls,
374
+ params.abi,
375
+ params.batchSize,
376
+ params.maxRetries,
377
+ params.providerId,
378
+ params.allowFailure,
379
+ customRpcs,
380
+ params.logErrors,
381
+ )
382
+ }
383
+ }
384
+
353
385
  export async function multicallRetryUniversal({
354
386
  chain,
355
387
  calls,
@@ -61,7 +61,6 @@ export const LIST_OVERRIDES: Record<string, string[]> = {
61
61
  'https://erpc.xdcrpc.com',
62
62
  ],
63
63
  [Chain.ETHEREUM_MAINNET]: [
64
- 'https://eth.llamarpc.com',
65
64
  'https://api.zan.top/eth-mainnet',
66
65
  'https://rpc.flashbots.net/fast',
67
66
  'https://rpc.owlracle.info/eth/70d38ce1826c4a60bb2a8e05a6c8b20f',
@@ -72,6 +71,7 @@ export const LIST_OVERRIDES: Record<string, string[]> = {
72
71
  'https://rpc.flashbots.net',
73
72
  'https://public-eth.nownodes.io',
74
73
  'https://ethereum-json-rpc.stakely.io',
74
+ 'https://eth.llamarpc.com',
75
75
  'https://eth.blockrazor.xyz',
76
76
  'https://eth.drpc.org',
77
77
  'https://ethereum.public.blockpi.network/v1/rpc/public',
@@ -175,10 +175,13 @@ export const LIST_OVERRIDES: Record<string, string[]> = {
175
175
  'https://avax-rpc.gateway.pokt.network',
176
176
  ],
177
177
  [Chain.CELO_MAINNET]: [
178
+ 'https://celo-mainnet.gateway.tatum.io',
179
+ 'https://celo-json-rpc.stakely.io',
178
180
  'https://forno.celo.org',
179
181
  'https://1rpc.io/celo',
180
182
  'https://celo.drpc.org',
181
183
  'https://celo-rpc.publicnode.com',
184
+ 'https://rpc.ankr.com/celo',
182
185
  ],
183
186
  [Chain.BLAST]: [
184
187
  'https://rpc.blast.io',
@@ -274,6 +277,10 @@ export const LIST_OVERRIDES: Record<string, string[]> = {
274
277
  'https://tac.therpc.io',
275
278
  'https://ws.rpc.tac.build',
276
279
  ],
280
+ [Chain.BOTANIX_MAINNET]: [
281
+ 'https://rpc.botanixlabs.com',
282
+ 'https://rpc.ankr.com/botanix_mainnet',
283
+ ],
277
284
  [Chain.UNICHAIN]: [
278
285
  'https://mainnet.unichain.org',
279
286
  'https://rpc.sentio.xyz/unichain-mainnet',