@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 +2 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +74 -14
- package/dist/index.mjs +73 -14
- package/package.json +1 -1
- package/src/multicall/multicall.ts +77 -45
- package/src/rpc/rpcOverrides.ts +8 -1
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
|
-
|
|
25345
|
-
|
|
25346
|
-
|
|
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
|
|
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 (
|
|
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 (
|
|
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 (
|
|
25485
|
-
if (logErrors)
|
|
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
|
-
|
|
11585
|
-
|
|
11586
|
-
|
|
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
|
|
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 (
|
|
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 (
|
|
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 (
|
|
11725
|
-
if (logErrors)
|
|
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
|
@@ -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
|
-
/**
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
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
|
-
//
|
|
260
|
-
//
|
|
261
|
-
|
|
262
|
-
|
|
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,
|
package/src/rpc/rpcOverrides.ts
CHANGED
|
@@ -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',
|