@1delta/providers 0.0.1

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/evm.d.ts ADDED
@@ -0,0 +1,115 @@
1
+ import { PublicClient } from "viem";
2
+ export declare const crossfi: {
3
+ blockExplorers: {
4
+ readonly default: {
5
+ readonly name: "Explorer";
6
+ readonly url: "https://xfiscan.com/";
7
+ };
8
+ };
9
+ blockTime?: number | undefined | undefined;
10
+ contracts?: {
11
+ [x: string]: import("viem").ChainContract | {
12
+ [sourceId: number]: import("viem").ChainContract | undefined;
13
+ } | undefined;
14
+ ensRegistry?: import("viem").ChainContract | undefined;
15
+ ensUniversalResolver?: import("viem").ChainContract | undefined;
16
+ multicall3?: import("viem").ChainContract | undefined;
17
+ universalSignatureVerifier?: import("viem").ChainContract | undefined;
18
+ } | undefined;
19
+ ensTlds?: readonly string[] | undefined;
20
+ id: 4158;
21
+ name: "CrossFi Mainet";
22
+ nativeCurrency: {
23
+ readonly decimals: 18;
24
+ readonly name: "XFI";
25
+ readonly symbol: "XFI";
26
+ };
27
+ rpcUrls: {
28
+ readonly default: {
29
+ readonly http: readonly ["https://rpc.mainnet.ms/"];
30
+ };
31
+ };
32
+ sourceId?: number | undefined | undefined;
33
+ testnet?: boolean | undefined | undefined;
34
+ custom?: Record<string, unknown> | undefined;
35
+ fees?: import("viem").ChainFees<undefined> | undefined;
36
+ formatters?: undefined;
37
+ serializers?: import("viem").ChainSerializers<undefined, import("viem").TransactionSerializable> | undefined;
38
+ };
39
+ export declare const botanix: {
40
+ blockExplorers: {
41
+ readonly default: {
42
+ readonly name: "Explorer";
43
+ readonly url: "https://botanixscan.io/";
44
+ };
45
+ };
46
+ blockTime?: number | undefined | undefined;
47
+ contracts: {
48
+ readonly multicall3: {
49
+ readonly address: "0xcA11bde05977b3631167028862bE2a173976CA11";
50
+ readonly blockCreated: 1;
51
+ };
52
+ };
53
+ ensTlds?: readonly string[] | undefined;
54
+ id: 3637;
55
+ name: "Botanix";
56
+ nativeCurrency: {
57
+ readonly decimals: 18;
58
+ readonly name: "BTC";
59
+ readonly symbol: "BTC";
60
+ };
61
+ rpcUrls: {
62
+ readonly default: {
63
+ readonly http: readonly ["https://rpc.ankr.com/botanix_mainnet", "https://rpc.botanixlabs.com"];
64
+ };
65
+ };
66
+ sourceId?: number | undefined | undefined;
67
+ testnet?: boolean | undefined | undefined;
68
+ custom?: Record<string, unknown> | undefined;
69
+ fees?: import("viem").ChainFees<undefined> | undefined;
70
+ formatters?: undefined;
71
+ serializers?: import("viem").ChainSerializers<undefined, import("viem").TransactionSerializable> | undefined;
72
+ };
73
+ export declare const GraphLinq: {
74
+ blockExplorers: {
75
+ readonly default: {
76
+ readonly name: "Explorer";
77
+ readonly url: "https://explorer.graphlinq.io";
78
+ };
79
+ };
80
+ blockTime?: number | undefined | undefined;
81
+ contracts?: {
82
+ [x: string]: import("viem").ChainContract | {
83
+ [sourceId: number]: import("viem").ChainContract | undefined;
84
+ } | undefined;
85
+ ensRegistry?: import("viem").ChainContract | undefined;
86
+ ensUniversalResolver?: import("viem").ChainContract | undefined;
87
+ multicall3?: import("viem").ChainContract | undefined;
88
+ universalSignatureVerifier?: import("viem").ChainContract | undefined;
89
+ } | undefined;
90
+ ensTlds?: readonly string[] | undefined;
91
+ id: 614;
92
+ name: "GraphLinq Chain";
93
+ nativeCurrency: {
94
+ readonly decimals: 18;
95
+ readonly name: "GLQ";
96
+ readonly symbol: "GLQ";
97
+ };
98
+ rpcUrls: {
99
+ readonly default: {
100
+ readonly http: readonly ["https://glq-dataseed.graphlinq.io"];
101
+ };
102
+ };
103
+ sourceId?: number | undefined | undefined;
104
+ testnet?: boolean | undefined | undefined;
105
+ custom?: Record<string, unknown> | undefined;
106
+ fees?: import("viem").ChainFees<undefined> | undefined;
107
+ formatters?: undefined;
108
+ serializers?: import("viem").ChainSerializers<undefined, import("viem").TransactionSerializable> | undefined;
109
+ };
110
+ export declare function getEvmClient(chain: string, rpcId?: number): PublicClient;
111
+ export declare function createMulticallRetry(customRpcs?: {
112
+ [chainId: string]: string[];
113
+ }): (chain: string, calls: any[], abi: any, batchSize?: number, maxRetries?: number, providerId?: number, allowFailure?: boolean) => Promise<any[]>;
114
+ export declare function multicallRetry(chain: string, calls: any[], abi: any, batchSize?: number, maxRetries?: number, providerId?: number): Promise<any[]>;
115
+ //# sourceMappingURL=evm.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"evm.d.ts","sourceRoot":"","sources":["../src/evm.ts"],"names":[],"mappings":"AAEA,OAAO,EAAyC,YAAY,EAAE,MAAM,MAAM,CAAA;AAkE1E,eAAO,MAAM,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAsBlB,CAAC;AAEH,eAAO,MAAM,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAwBlB,CAAC;AAGH,eAAO,MAAM,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAsBpB,CAAC;AA8MH,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,SAAI,GAAG,YAAY,CAmBnE;AAID,wBAAgB,oBAAoB,CAAC,UAAU,CAAC,EAAE;IAAE,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,CAAA;CAAE,IAEzE,OAAO,MAAM,EACb,OAAO,GAAG,EAAE,EACZ,KAAK,GAAG,EACR,kBAA8B,EAC9B,mBAAc,EACd,mBAAc,EACd,sBAAmB,oBA6B1B;AA0CD,wBAAsB,cAAc,CAChC,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,GAAG,EAAE,EACZ,GAAG,EAAE,GAAG,EACR,SAAS,SAAqB,EAC9B,UAAU,SAAI,EACd,UAAU,SAAI,kBAIjB"}
package/dist/evm.js ADDED
@@ -0,0 +1,363 @@
1
+ import { Chain, CHAIN_INFO } from "@1delta/asset-registry";
2
+ import { isArray, uniq } from "lodash";
3
+ import { createPublicClient, defineChain, http } from "viem";
4
+ import { mantle, mainnet, optimism, arbitrum, bsc, avalanche, taiko, metis, polygon, zksync, scroll, gnosis, base, blast, kaia, opBNB, fantom, sonic, linea, hemi, neonMainnet, degen, gravity, lightlinkPhoenix, plume, abstract, peaq, flowMainnet, soneium, goat, berachain, rootstock, ink, vanar, fuse, superposition, story, apeChain, telos, flare, aurora, kava, iota, coreDao, unichain, mode, xLayer, zircuit, corn, bob, manta, harmonyOne, celo, bitlayer, merlin, sei, iotex, bsquared, zetachain, ronin, inEVM, } from "viem/chains";
5
+ export const crossfi = defineChain({
6
+ id: 4158,
7
+ name: 'CrossFi Mainet',
8
+ nativeCurrency: {
9
+ decimals: 18,
10
+ name: 'XFI',
11
+ symbol: 'XFI',
12
+ },
13
+ rpcUrls: {
14
+ default: {
15
+ http: ['https://rpc.mainnet.ms/'],
16
+ },
17
+ },
18
+ blockExplorers: {
19
+ default: { name: 'Explorer', url: 'https://xfiscan.com/' },
20
+ },
21
+ // contracts: {
22
+ // multicall3: {
23
+ // address: "0xcA11bde05977b3631167028862bE2a173976CA11",
24
+ // blockCreated: 1,
25
+ // }
26
+ // }
27
+ });
28
+ export const botanix = defineChain({
29
+ id: 3637,
30
+ name: 'Botanix',
31
+ nativeCurrency: {
32
+ decimals: 18,
33
+ name: 'BTC',
34
+ symbol: 'BTC',
35
+ },
36
+ rpcUrls: {
37
+ default: {
38
+ http: [
39
+ "https://rpc.ankr.com/botanix_mainnet",
40
+ "https://rpc.botanixlabs.com"
41
+ ],
42
+ },
43
+ },
44
+ blockExplorers: {
45
+ default: { name: 'Explorer', url: 'https://botanixscan.io/' },
46
+ },
47
+ contracts: {
48
+ multicall3: {
49
+ address: "0xcA11bde05977b3631167028862bE2a173976CA11",
50
+ blockCreated: 1,
51
+ }
52
+ }
53
+ });
54
+ export const GraphLinq = defineChain({
55
+ id: 614,
56
+ name: 'GraphLinq Chain',
57
+ nativeCurrency: {
58
+ decimals: 18,
59
+ name: 'GLQ',
60
+ symbol: 'GLQ',
61
+ },
62
+ rpcUrls: {
63
+ default: {
64
+ http: ["https://glq-dataseed.graphlinq.io"],
65
+ },
66
+ },
67
+ blockExplorers: {
68
+ default: { name: 'Explorer', "url": "https://explorer.graphlinq.io", },
69
+ },
70
+ // contracts: {
71
+ // multicall3: {
72
+ // address: "0xcA11bde05977b3631167028862bE2a173976CA11",
73
+ // blockCreated: 1,
74
+ // }
75
+ // }
76
+ });
77
+ function getEvmChain(chain) {
78
+ switch (chain) {
79
+ case Chain.ARBITRUM_ONE:
80
+ return arbitrum;
81
+ case Chain.ETHEREUM_MAINNET:
82
+ return mainnet;
83
+ case Chain.MANTLE:
84
+ return mantle;
85
+ case Chain.BNB_SMART_CHAIN_MAINNET:
86
+ return bsc;
87
+ case Chain.OPBNB_MAINNET:
88
+ return opBNB;
89
+ case Chain.TAIKO_ALETHIA:
90
+ return taiko;
91
+ case Chain.AVALANCHE_C_CHAIN:
92
+ return avalanche;
93
+ case Chain.OP_MAINNET:
94
+ return optimism;
95
+ case Chain.METIS_ANDROMEDA_MAINNET:
96
+ return metis;
97
+ case Chain.POLYGON_MAINNET:
98
+ return polygon;
99
+ case Chain.ZKSYNC_MAINNET:
100
+ return zksync;
101
+ case Chain.SCROLL:
102
+ return scroll;
103
+ case Chain.GNOSIS:
104
+ return gnosis;
105
+ case Chain.BASE:
106
+ return base;
107
+ case Chain.BLAST:
108
+ return blast;
109
+ case Chain.KAIA_MAINNET:
110
+ return kaia;
111
+ case Chain.FANTOM_OPERA:
112
+ return fantom;
113
+ case Chain.SONIC_MAINNET:
114
+ return sonic;
115
+ case Chain.LINEA:
116
+ return linea;
117
+ case Chain.HEMI_NETWORK:
118
+ return {
119
+ ...hemi,
120
+ contracts: {
121
+ multicall3: {
122
+ address: "0xcA11bde05977b3631167028862bE2a173976CA11",
123
+ blockCreated: 1,
124
+ }
125
+ }
126
+ };
127
+ case Chain.NEON_EVM_MAINNET:
128
+ return neonMainnet;
129
+ case Chain.DEGEN_CHAIN:
130
+ return {
131
+ ...degen,
132
+ contracts: {
133
+ multicall3: {
134
+ address: "0xcA11bde05977b3631167028862bE2a173976CA11",
135
+ blockCreated: 1,
136
+ }
137
+ }
138
+ };
139
+ case Chain.GRAVITY_ALPHA_MAINNET:
140
+ return gravity;
141
+ case Chain.LIGHTLINK_PHOENIX_MAINNET:
142
+ return lightlinkPhoenix;
143
+ case Chain.PLUME_MAINNET:
144
+ return plume;
145
+ case Chain.ABSTRACT:
146
+ return abstract;
147
+ case Chain.PEAQ:
148
+ return peaq;
149
+ case Chain.EVM_ON_FLOW:
150
+ return flowMainnet;
151
+ case Chain.SONEIUM:
152
+ return soneium;
153
+ case Chain.GOAT_NETWORK:
154
+ return goat;
155
+ case Chain.BERACHAIN:
156
+ return berachain;
157
+ case Chain.ROOTSTOCK_MAINNET:
158
+ return rootstock;
159
+ case Chain.VANAR_MAINNET:
160
+ return vanar;
161
+ case Chain.INK:
162
+ return {
163
+ ...ink,
164
+ contracts: {
165
+ multicall3: {
166
+ address: "0xcA11bde05977b3631167028862bE2a173976CA11",
167
+ blockCreated: 1,
168
+ }
169
+ }
170
+ };
171
+ case Chain.FUSE_MAINNET:
172
+ return fuse;
173
+ case Chain.SUPERPOSITION:
174
+ return superposition;
175
+ case Chain.STORY:
176
+ return {
177
+ ...story,
178
+ contracts: {
179
+ multicall3: {
180
+ address: "0xcA11bde05977b3631167028862bE2a173976CA11",
181
+ blockCreated: 1,
182
+ }
183
+ }
184
+ };
185
+ case Chain.APECHAIN:
186
+ return apeChain;
187
+ case Chain.IOTEX_NETWORK_MAINNET:
188
+ return iotex;
189
+ case Chain.TELOS_EVM_MAINNET:
190
+ return telos;
191
+ case Chain.FLARE_MAINNET:
192
+ return flare;
193
+ case Chain.AURA_MAINNET:
194
+ return aurora;
195
+ case Chain.KAVA:
196
+ return kava;
197
+ case Chain.IOTA_EVM:
198
+ return iota;
199
+ case Chain.AURORA_MAINNET:
200
+ return aurora;
201
+ case Chain.UNICHAIN:
202
+ return unichain;
203
+ case Chain.CORE_BLOCKCHAIN_MAINNET:
204
+ return coreDao;
205
+ case Chain.MODE:
206
+ return mode;
207
+ case Chain.CORN:
208
+ return corn;
209
+ case Chain.BOB:
210
+ return bob;
211
+ case Chain.RONIN_MAINNET:
212
+ return ronin;
213
+ case Chain.MANTA_PACIFIC_MAINNET:
214
+ return manta;
215
+ case Chain.ZIRCUIT_MAINNET:
216
+ return zircuit;
217
+ case Chain.GRAPHLINQ_BLOCKCHAIN_MAINNET:
218
+ return GraphLinq;
219
+ case Chain.ZETACHAIN_MAINNET:
220
+ return zetachain;
221
+ case Chain.BITLAYER_MAINNET:
222
+ return bitlayer;
223
+ case Chain.CROSSFI_MAINNET:
224
+ return crossfi;
225
+ case Chain.INEVM_MAINNET:
226
+ return inEVM;
227
+ case Chain.B2_MAINNET:
228
+ return {
229
+ ...bsquared,
230
+ contracts: {
231
+ multicall3: {
232
+ address: "0xcA11bde05977b3631167028862bE2a173976CA11",
233
+ blockCreated: 1,
234
+ }
235
+ }
236
+ };
237
+ case Chain.SEI_NETWORK:
238
+ return sei;
239
+ case Chain.MERLIN_MAINNET:
240
+ return {
241
+ ...merlin,
242
+ contracts: {
243
+ multicall3: {
244
+ address: "0x46063722c010AF39E465d286B84936A12aFb81F0",
245
+ blockCreated: 1,
246
+ }
247
+ }
248
+ };
249
+ case Chain.X_LAYER_MAINNET:
250
+ return xLayer;
251
+ case Chain.CELO_MAINNET:
252
+ return celo;
253
+ case Chain.BOTANIX_MAINNET:
254
+ return botanix;
255
+ case Chain.HARMONY_MAINNET_SHARD_0:
256
+ return harmonyOne;
257
+ // case Chain.VANA:
258
+ // return vana
259
+ // case Chain.RARI_CHAIN_MAINNET:
260
+ // return rariChain
261
+ // case Chain.GLUE_MAINNET:
262
+ // return glue
263
+ default: throw new Error("Not in VIEM: " + chain);
264
+ }
265
+ }
266
+ const RPC_OVERRIDES = {
267
+ [Chain.FANTOM_OPERA]: "https://rpc.fantom.network",
268
+ [Chain.BNB_SMART_CHAIN_MAINNET]: "https://bsc-dataseed2.ninicoin.io",
269
+ [Chain.METIS_ANDROMEDA_MAINNET]: "https://andromeda.metis.io/?owner=1088",
270
+ [Chain.X_LAYER_MAINNET]: "https://xlayerrpc.okx.com",
271
+ };
272
+ function trimTrailingSlash(url) {
273
+ if (!url)
274
+ return undefined;
275
+ return url.endsWith('/') ? url.slice(0, -1) : url;
276
+ }
277
+ export function getEvmClient(chain, rpcId = 0) {
278
+ const chainInfo = getEvmChain(chain);
279
+ let rpc;
280
+ if (rpcId === 0)
281
+ rpc = chainInfo.rpcUrls.default.http[0];
282
+ else {
283
+ const rpcsChain = CHAIN_INFO[chain].rpc?.filter(a => !a.includes("wss://"));
284
+ const rpcs = chainInfo.rpcUrls.default.http.map(a => trimTrailingSlash(a));
285
+ const rpcsAdded = rpcsChain.map(a => trimTrailingSlash(a));
286
+ const allRpcs = uniq([...rpcs, ...rpcsAdded]);
287
+ rpc = allRpcs[rpcId];
288
+ }
289
+ return createPublicClient({
290
+ chain: chainInfo,
291
+ transport: http(RPC_OVERRIDES[chain] ??
292
+ rpc)
293
+ });
294
+ }
295
+ const DEFAULT_BATCH_SIZE = 4096;
296
+ export function createMulticallRetry(customRpcs) {
297
+ return async function multicallRetry(chain, calls, abi, batchSize = DEFAULT_BATCH_SIZE, maxRetries = 3, providerId = 0, allowFailure = true) {
298
+ try {
299
+ const provider = getEvmClientWithCustomRpcs(chain, providerId, customRpcs);
300
+ const abiIsArray = isArray(abi[0]);
301
+ const data = await provider.multicall({
302
+ batchSize: DEFAULT_BATCH_SIZE,
303
+ contracts: calls.map((call, i) => ({
304
+ abi: abiIsArray ? abi?.[i] : abi,
305
+ address: call.address,
306
+ functionName: call.name,
307
+ // @ts-ignore
308
+ args: call.args ?? call.params ?? [],
309
+ })),
310
+ allowFailure,
311
+ });
312
+ if (allowFailure) {
313
+ return data.map(({ result, status }) => status !== "success" ? '0x' : result);
314
+ }
315
+ return data;
316
+ }
317
+ catch (e) {
318
+ // error if max retries achieved
319
+ if (maxRetries === 0)
320
+ throw e;
321
+ console.log(e);
322
+ return await multicallRetry(chain, calls, abi, batchSize, maxRetries - 1, providerId + 1);
323
+ }
324
+ };
325
+ }
326
+ function getEvmClientWithCustomRpcs(chain, rpcId = 0, customRpcs) {
327
+ const chainInfo = getEvmChain(chain);
328
+ let rpc;
329
+ if (customRpcs && customRpcs[chain]) {
330
+ // Use custom RPC list if any (make sure that they are unique and valid)
331
+ const customRpcList = uniq(customRpcs[chain]
332
+ .filter(Boolean) // Remove empty ones
333
+ .filter(a => !a.includes("wss://")) // filter websocket ones (like the default impl)
334
+ .map(url => trimTrailingSlash(url))
335
+ .filter((url) => Boolean(url)) // Type-safe filter for defined URLs
336
+ );
337
+ if (customRpcList.length === 0) {
338
+ throw new Error(`No valid custom RPCs provided for chain ${chain}`);
339
+ }
340
+ rpc = customRpcList[rpcId % customRpcList.length];
341
+ }
342
+ else {
343
+ // Fallback to existing logic
344
+ if (rpcId === 0)
345
+ rpc = chainInfo.rpcUrls.default.http[0];
346
+ else {
347
+ const rpcsChain = CHAIN_INFO[chain].rpc?.filter(a => !a.includes("wss://"));
348
+ const rpcs = chainInfo.rpcUrls.default.http.map(a => trimTrailingSlash(a));
349
+ const rpcsAdded = rpcsChain.map(a => trimTrailingSlash(a));
350
+ const allRpcs = uniq([...rpcs, ...rpcsAdded]);
351
+ rpc = allRpcs[rpcId];
352
+ }
353
+ }
354
+ return createPublicClient({
355
+ chain: chainInfo,
356
+ transport: http(RPC_OVERRIDES[chain] ??
357
+ rpc)
358
+ });
359
+ }
360
+ export async function multicallRetry(chain, calls, abi, batchSize = DEFAULT_BATCH_SIZE, maxRetries = 3, providerId = 0) {
361
+ const defaultMulticallRetry = createMulticallRetry();
362
+ return defaultMulticallRetry(chain, calls, abi, batchSize, maxRetries, providerId);
363
+ }
@@ -0,0 +1,2 @@
1
+ export * from "./evm";
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,OAAO,CAAA"}
package/dist/index.js ADDED
@@ -0,0 +1 @@
1
+ export * from "./evm";
package/package.json ADDED
@@ -0,0 +1,23 @@
1
+ {
2
+ "name": "@1delta/providers",
3
+ "version": "0.0.1",
4
+ "description": "",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "exports": {
8
+ ".": {
9
+ "import": "./dist/index.js",
10
+ "types": "./dist/index.d.ts"
11
+ }
12
+ },
13
+ "keywords": [],
14
+ "author": "",
15
+ "license": "ISC",
16
+ "devDependencies": {
17
+ "typescript": "^5.8.3"
18
+ },
19
+ "scripts": {
20
+ "build": "tsc",
21
+ "test": "vitest"
22
+ }
23
+ }
package/src/evm.ts ADDED
@@ -0,0 +1,460 @@
1
+ import { Chain, CHAIN_INFO } from "@1delta/asset-registry"
2
+ import { isArray, uniq } from "lodash";
3
+ import { createPublicClient, defineChain, http, PublicClient } from "viem"
4
+ import {
5
+ mantle,
6
+ mainnet,
7
+ optimism,
8
+ arbitrum,
9
+ bsc,
10
+ avalanche,
11
+ taiko,
12
+ metis,
13
+ polygon,
14
+ zksync,
15
+ scroll,
16
+ gnosis,
17
+ base,
18
+ blast,
19
+ kaia,
20
+ opBNB,
21
+ fantom,
22
+ sonic,
23
+ linea,
24
+ hemi,
25
+ neonMainnet,
26
+ degen,
27
+ gravity,
28
+ lightlinkPhoenix,
29
+ plume,
30
+ abstract,
31
+ peaq,
32
+ flowMainnet,
33
+ soneium,
34
+ goat,
35
+ berachain,
36
+ rootstock,
37
+ ink,
38
+ vanar,
39
+ fuse,
40
+ superposition,
41
+ story,
42
+ apeChain,
43
+ telos,
44
+ flare,
45
+ aurora,
46
+ kava,
47
+ iota,
48
+ coreDao,
49
+ unichain,
50
+ mode,
51
+ xLayer,
52
+ zircuit,
53
+ corn,
54
+ bob,
55
+ manta,
56
+ harmonyOne,
57
+ celo,
58
+ bitlayer,
59
+ merlin,
60
+ sei,
61
+ iotex,
62
+ bsquared,
63
+ zetachain,
64
+ ronin,
65
+ inEVM,
66
+ } from "viem/chains"
67
+
68
+
69
+ export const crossfi = defineChain({
70
+ id: 4158,
71
+ name: 'CrossFi Mainet',
72
+ nativeCurrency: {
73
+ decimals: 18,
74
+ name: 'XFI',
75
+ symbol: 'XFI',
76
+ },
77
+ rpcUrls: {
78
+ default: {
79
+ http: ['https://rpc.mainnet.ms/'],
80
+ },
81
+ },
82
+ blockExplorers: {
83
+ default: { name: 'Explorer', url: 'https://xfiscan.com/' },
84
+ },
85
+ // contracts: {
86
+ // multicall3: {
87
+ // address: "0xcA11bde05977b3631167028862bE2a173976CA11",
88
+ // blockCreated: 1,
89
+ // }
90
+ // }
91
+ });
92
+
93
+ export const botanix = defineChain({
94
+ id: 3637,
95
+ name: 'Botanix',
96
+ nativeCurrency: {
97
+ decimals: 18,
98
+ name: 'BTC',
99
+ symbol: 'BTC',
100
+ },
101
+ rpcUrls: {
102
+ default: {
103
+ http: [
104
+ "https://rpc.ankr.com/botanix_mainnet",
105
+ "https://rpc.botanixlabs.com"],
106
+ },
107
+ },
108
+ blockExplorers: {
109
+ default: { name: 'Explorer', url: 'https://botanixscan.io/' },
110
+ },
111
+ contracts: {
112
+ multicall3: {
113
+ address: "0xcA11bde05977b3631167028862bE2a173976CA11",
114
+ blockCreated: 1,
115
+ }
116
+ }
117
+ });
118
+
119
+
120
+ export const GraphLinq = defineChain({
121
+ id: 614,
122
+ name: 'GraphLinq Chain',
123
+ nativeCurrency: {
124
+ decimals: 18,
125
+ name: 'GLQ',
126
+ symbol: 'GLQ',
127
+ },
128
+ rpcUrls: {
129
+ default: {
130
+ http: ["https://glq-dataseed.graphlinq.io"],
131
+ },
132
+ },
133
+ blockExplorers: {
134
+ default: { name: 'Explorer', "url": "https://explorer.graphlinq.io", },
135
+ },
136
+ // contracts: {
137
+ // multicall3: {
138
+ // address: "0xcA11bde05977b3631167028862bE2a173976CA11",
139
+ // blockCreated: 1,
140
+ // }
141
+ // }
142
+ });
143
+
144
+
145
+
146
+ function getEvmChain(chain: string) {
147
+ switch (chain) {
148
+ case Chain.ARBITRUM_ONE:
149
+ return arbitrum
150
+ case Chain.ETHEREUM_MAINNET:
151
+ return mainnet
152
+ case Chain.MANTLE:
153
+ return mantle
154
+ case Chain.BNB_SMART_CHAIN_MAINNET:
155
+ return bsc
156
+ case Chain.OPBNB_MAINNET:
157
+ return opBNB
158
+ case Chain.TAIKO_ALETHIA:
159
+ return taiko
160
+ case Chain.AVALANCHE_C_CHAIN:
161
+ return avalanche
162
+ case Chain.OP_MAINNET:
163
+ return optimism
164
+ case Chain.METIS_ANDROMEDA_MAINNET:
165
+ return metis
166
+ case Chain.POLYGON_MAINNET:
167
+ return polygon
168
+ case Chain.ZKSYNC_MAINNET:
169
+ return zksync
170
+ case Chain.SCROLL:
171
+ return scroll
172
+ case Chain.GNOSIS:
173
+ return gnosis
174
+ case Chain.BASE:
175
+ return base
176
+ case Chain.BLAST:
177
+ return blast
178
+ case Chain.KAIA_MAINNET:
179
+ return kaia
180
+ case Chain.FANTOM_OPERA:
181
+ return fantom
182
+ case Chain.SONIC_MAINNET:
183
+ return sonic
184
+ case Chain.LINEA:
185
+ return linea
186
+ case Chain.HEMI_NETWORK:
187
+ return {
188
+ ...hemi,
189
+ contracts: {
190
+ multicall3: {
191
+ address: "0xcA11bde05977b3631167028862bE2a173976CA11",
192
+ blockCreated: 1,
193
+ }
194
+ }
195
+ }
196
+ case Chain.NEON_EVM_MAINNET:
197
+ return neonMainnet
198
+ case Chain.DEGEN_CHAIN:
199
+ return {
200
+ ...degen,
201
+ contracts: {
202
+ multicall3: {
203
+ address: "0xcA11bde05977b3631167028862bE2a173976CA11",
204
+ blockCreated: 1,
205
+ }
206
+ }
207
+ }
208
+ case Chain.GRAVITY_ALPHA_MAINNET:
209
+ return gravity
210
+ case Chain.LIGHTLINK_PHOENIX_MAINNET:
211
+ return lightlinkPhoenix
212
+ case Chain.PLUME_MAINNET:
213
+ return plume
214
+ case Chain.ABSTRACT:
215
+ return abstract
216
+ case Chain.PEAQ:
217
+ return peaq
218
+ case Chain.EVM_ON_FLOW:
219
+ return flowMainnet
220
+ case Chain.SONEIUM:
221
+ return soneium
222
+ case Chain.GOAT_NETWORK:
223
+ return goat
224
+ case Chain.BERACHAIN:
225
+ return berachain
226
+ case Chain.ROOTSTOCK_MAINNET:
227
+ return rootstock
228
+ case Chain.VANAR_MAINNET:
229
+ return vanar
230
+ case Chain.INK:
231
+ return {
232
+ ...ink,
233
+ contracts: {
234
+ multicall3: {
235
+ address: "0xcA11bde05977b3631167028862bE2a173976CA11",
236
+ blockCreated: 1,
237
+ }
238
+ }
239
+ }
240
+ case Chain.FUSE_MAINNET:
241
+ return fuse
242
+ case Chain.SUPERPOSITION:
243
+ return superposition
244
+ case Chain.STORY:
245
+ return {
246
+ ...story,
247
+ contracts: {
248
+ multicall3: {
249
+ address: "0xcA11bde05977b3631167028862bE2a173976CA11",
250
+ blockCreated: 1,
251
+ }
252
+ }
253
+ }
254
+ case Chain.APECHAIN:
255
+ return apeChain
256
+ case Chain.IOTEX_NETWORK_MAINNET:
257
+ return iotex
258
+ case Chain.TELOS_EVM_MAINNET:
259
+ return telos
260
+ case Chain.FLARE_MAINNET:
261
+ return flare
262
+ case Chain.AURA_MAINNET:
263
+ return aurora
264
+ case Chain.KAVA:
265
+ return kava
266
+ case Chain.IOTA_EVM:
267
+ return iota
268
+ case Chain.AURORA_MAINNET:
269
+ return aurora
270
+ case Chain.UNICHAIN:
271
+ return unichain
272
+ case Chain.CORE_BLOCKCHAIN_MAINNET:
273
+ return coreDao
274
+ case Chain.MODE:
275
+ return mode
276
+ case Chain.CORN:
277
+ return corn
278
+ case Chain.BOB:
279
+ return bob
280
+ case Chain.RONIN_MAINNET:
281
+ return ronin
282
+ case Chain.MANTA_PACIFIC_MAINNET:
283
+ return manta
284
+ case Chain.ZIRCUIT_MAINNET:
285
+ return zircuit
286
+ case Chain.GRAPHLINQ_BLOCKCHAIN_MAINNET:
287
+ return GraphLinq
288
+ case Chain.ZETACHAIN_MAINNET:
289
+ return zetachain
290
+ case Chain.BITLAYER_MAINNET:
291
+ return bitlayer
292
+ case Chain.CROSSFI_MAINNET:
293
+ return crossfi
294
+ case Chain.INEVM_MAINNET:
295
+ return inEVM
296
+ case Chain.B2_MAINNET:
297
+ return {
298
+ ...bsquared,
299
+ contracts: {
300
+ multicall3: {
301
+ address: "0xcA11bde05977b3631167028862bE2a173976CA11",
302
+ blockCreated: 1,
303
+ }
304
+ }
305
+ }
306
+ case Chain.SEI_NETWORK:
307
+ return sei
308
+ case Chain.MERLIN_MAINNET:
309
+ return {
310
+ ...merlin,
311
+ contracts: {
312
+ multicall3: {
313
+ address: "0x46063722c010AF39E465d286B84936A12aFb81F0",
314
+ blockCreated: 1,
315
+ }
316
+ }
317
+ }
318
+ case Chain.X_LAYER_MAINNET:
319
+ return xLayer
320
+ case Chain.CELO_MAINNET:
321
+ return celo
322
+ case Chain.BOTANIX_MAINNET:
323
+ return botanix
324
+ case Chain.HARMONY_MAINNET_SHARD_0:
325
+ return harmonyOne
326
+ // case Chain.VANA:
327
+ // return vana
328
+ // case Chain.RARI_CHAIN_MAINNET:
329
+ // return rariChain
330
+ // case Chain.GLUE_MAINNET:
331
+ // return glue
332
+ default: throw new Error("Not in VIEM: " + chain)
333
+ }
334
+ }
335
+
336
+ const RPC_OVERRIDES: any = {
337
+ [Chain.FANTOM_OPERA]: "https://rpc.fantom.network",
338
+ [Chain.BNB_SMART_CHAIN_MAINNET]: "https://bsc-dataseed2.ninicoin.io",
339
+ [Chain.METIS_ANDROMEDA_MAINNET]: "https://andromeda.metis.io/?owner=1088",
340
+ [Chain.X_LAYER_MAINNET]: "https://xlayerrpc.okx.com",
341
+ }
342
+
343
+ function trimTrailingSlash(url?: string) {
344
+ if (!url) return undefined
345
+ return url.endsWith('/') ? url.slice(0, -1) : url;
346
+ }
347
+
348
+ export function getEvmClient(chain: string, rpcId = 0): PublicClient {
349
+ const chainInfo = getEvmChain(chain)
350
+ let rpc: string
351
+ if (rpcId === 0) rpc = chainInfo.rpcUrls.default.http[0]
352
+ else {
353
+ const rpcsChain = CHAIN_INFO[chain].rpc?.filter(a => !a.includes("wss://"))
354
+ const rpcs = chainInfo.rpcUrls.default.http.map(a => trimTrailingSlash(a))
355
+ const rpcsAdded = rpcsChain.map(a => trimTrailingSlash(a))
356
+ const allRpcs = uniq([...rpcs, ...rpcsAdded])
357
+ rpc = allRpcs[rpcId] as any
358
+ }
359
+ return createPublicClient({
360
+ chain: chainInfo as any,
361
+ transport: http(
362
+ RPC_OVERRIDES[chain] ??
363
+ rpc
364
+ )
365
+ }) as any
366
+
367
+ }
368
+
369
+ const DEFAULT_BATCH_SIZE = 4096;
370
+
371
+ export function createMulticallRetry(customRpcs?: { [chainId: string]: string[] }) {
372
+ return async function multicallRetry(
373
+ chain: string,
374
+ calls: any[],
375
+ abi: any,
376
+ batchSize = DEFAULT_BATCH_SIZE,
377
+ maxRetries = 3,
378
+ providerId = 0,
379
+ allowFailure = true,
380
+ ) {
381
+ try {
382
+ const provider = getEvmClientWithCustomRpcs(chain, providerId, customRpcs)
383
+ const abiIsArray = isArray(abi[0])
384
+ const data = await provider.multicall({
385
+ batchSize: DEFAULT_BATCH_SIZE,
386
+ contracts: calls.map((call, i) => ({
387
+ abi: abiIsArray ? abi?.[i] : abi,
388
+ address: call.address as any,
389
+ functionName: call.name,
390
+ // @ts-ignore
391
+ args: call.args ?? call.params ?? [],
392
+ })),
393
+ allowFailure,
394
+ })
395
+ if (allowFailure) {
396
+ return (data as any[]).map(
397
+ ({ result, status }: any) => status !== "success" ? '0x' : result
398
+ );
399
+ }
400
+ return data
401
+ } catch (e) {
402
+ // error if max retries achieved
403
+ if (maxRetries === 0) throw e
404
+ console.log(e)
405
+ return await multicallRetry(chain, calls, abi, batchSize, maxRetries - 1, providerId + 1)
406
+ }
407
+ }
408
+ }
409
+
410
+ function getEvmClientWithCustomRpcs(chain: string, rpcId = 0, customRpcs?: { [chainId: string]: string[] }): PublicClient {
411
+ const chainInfo = getEvmChain(chain)
412
+ let rpc: string
413
+
414
+ if (customRpcs && customRpcs[chain]) {
415
+ // Use custom RPC list if any (make sure that they are unique and valid)
416
+ const customRpcList = uniq(
417
+ customRpcs[chain]
418
+ .filter(Boolean) // Remove empty ones
419
+ .filter(a => !a.includes("wss://")) // filter websocket ones (like the default impl)
420
+ .map(url => trimTrailingSlash(url))
421
+ .filter((url): url is string => Boolean(url)) // Type-safe filter for defined URLs
422
+ )
423
+
424
+ if (customRpcList.length === 0) {
425
+ throw new Error(`No valid custom RPCs provided for chain ${chain}`)
426
+ }
427
+
428
+ rpc = customRpcList[rpcId % customRpcList.length]
429
+ } else {
430
+ // Fallback to existing logic
431
+ if (rpcId === 0) rpc = chainInfo.rpcUrls.default.http[0]
432
+ else {
433
+ const rpcsChain = CHAIN_INFO[chain].rpc?.filter(a => !a.includes("wss://"))
434
+ const rpcs = chainInfo.rpcUrls.default.http.map(a => trimTrailingSlash(a))
435
+ const rpcsAdded = rpcsChain.map(a => trimTrailingSlash(a))
436
+ const allRpcs = uniq([...rpcs, ...rpcsAdded])
437
+ rpc = allRpcs[rpcId] as any
438
+ }
439
+ }
440
+
441
+ return createPublicClient({
442
+ chain: chainInfo as any,
443
+ transport: http(
444
+ RPC_OVERRIDES[chain] ??
445
+ rpc
446
+ )
447
+ }) as any
448
+ }
449
+
450
+ export async function multicallRetry(
451
+ chain: string,
452
+ calls: any[],
453
+ abi: any,
454
+ batchSize = DEFAULT_BATCH_SIZE,
455
+ maxRetries = 3,
456
+ providerId = 0,
457
+ ) {
458
+ const defaultMulticallRetry = createMulticallRetry()
459
+ return defaultMulticallRetry(chain, calls, abi, batchSize, maxRetries, providerId)
460
+ }
package/src/index.ts ADDED
@@ -0,0 +1 @@
1
+ export * from "./evm"
package/tsconfig.json ADDED
@@ -0,0 +1,25 @@
1
+ {
2
+ "extends": "../../tsconfig.json",
3
+ "compilerOptions": {
4
+ "module": "ESNext", // Ensure ESM (ES Modules) output
5
+ "target": "ESNext", // Output code that targets the latest ES features
6
+ "moduleResolution": "node", // Use Node.js module resolution
7
+ "esModuleInterop": true, // For compatibility with commonjs
8
+ "outDir": "dist", // Specify output directory
9
+ "rootDir": "src", // Specify output directory
10
+ "declaration": true, // Generate .d.ts files
11
+ "declarationMap": true, // Generate declaration map files
12
+ "allowJs": true, // Allow JavaScript files to be included
13
+ "resolveJsonModule": true, // Allow importing JSON files
14
+ "skipLibCheck": true, // Skip type checking of all declaration files
15
+ "strict": true, // Enable strict type checking
16
+ "isolatedModules": true // Allow isolated module builds
17
+ },
18
+ "include": [
19
+ "src/*"
20
+ ], // Include all the TypeScript files in src/
21
+ "exclude": [
22
+ "node_modules",
23
+ "dist"
24
+ ] // Exclude node_modules and dist from being compiled
25
+ }