@agglayer/sdk 0.1.0-beta.0

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.js ADDED
@@ -0,0 +1,1863 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ AggLayerSDK: () => AggLayerSDK,
24
+ SDK_MODES: () => SDK_MODES
25
+ });
26
+ module.exports = __toCommonJS(index_exports);
27
+
28
+ // src/native/chains/registry.ts
29
+ var ChainRegistry = class _ChainRegistry {
30
+ constructor() {
31
+ this.chains = /* @__PURE__ */ new Map();
32
+ this.viemChains = /* @__PURE__ */ new Map();
33
+ this.initializeDefaultChains();
34
+ }
35
+ static getInstance() {
36
+ if (!_ChainRegistry.instance) {
37
+ _ChainRegistry.instance = new _ChainRegistry();
38
+ }
39
+ return _ChainRegistry.instance;
40
+ }
41
+ initializeDefaultChains() {
42
+ this.registerChain({
43
+ chainId: 11155111,
44
+ networkId: 0,
45
+ name: "Ethereum Sepolia",
46
+ rpcUrl: "https://rpc.sepolia.org",
47
+ nativeCurrency: { name: "Sepolia Ether", symbol: "ETH", decimals: 18 },
48
+ blockExplorer: {
49
+ name: "Sepolia Etherscan",
50
+ url: "https://sepolia.etherscan.io"
51
+ },
52
+ bridgeAddress: "0x528e26b25a34a4A5d0dbDa1d57D318153d2ED582",
53
+ proofApiUrl: "https://api-gateway.polygon.technology/api/v3/proof/testnet/",
54
+ isTestnet: true
55
+ });
56
+ this.registerChain({
57
+ chainId: 2442,
58
+ networkId: 1,
59
+ name: "Polygon Cardona",
60
+ rpcUrl: "https://rpc.cardona.zkevm-rpc.com",
61
+ nativeCurrency: { name: "Ethereum", symbol: "ETH", decimals: 18 },
62
+ blockExplorer: {
63
+ name: "Cardona PolygonScan",
64
+ url: "https://cardona-zkevm.polygonscan.com"
65
+ },
66
+ bridgeAddress: "0x528e26b25a34a4A5d0dbDa1d57D318153d2ED582",
67
+ proofApiUrl: "https://api-gateway.polygon.technology/api/v3/proof/testnet/",
68
+ isTestnet: true
69
+ });
70
+ }
71
+ /**
72
+ * Register a new chain
73
+ */
74
+ registerChain(config) {
75
+ this.chains.set(config.chainId, config);
76
+ const viemChain = {
77
+ id: config.chainId,
78
+ name: config.name,
79
+ nativeCurrency: config.nativeCurrency,
80
+ rpcUrls: {
81
+ default: { http: [config.rpcUrl] }
82
+ }
83
+ };
84
+ this.viemChains.set(config.chainId, viemChain);
85
+ }
86
+ /**
87
+ * Get chain configuration by ID
88
+ */
89
+ getChain(chainId) {
90
+ const chain = this.chains.get(chainId);
91
+ if (!chain) {
92
+ throw new Error(
93
+ `Chain ${chainId} not found. Available chains: ${Array.from(this.chains.keys()).join(", ")}`
94
+ );
95
+ }
96
+ return chain;
97
+ }
98
+ /**
99
+ * Get chain configuration by network ID
100
+ */
101
+ getChainByNetworkId(networkId) {
102
+ const chain = Array.from(this.chains.values()).find(
103
+ (chain2) => chain2.networkId === networkId
104
+ );
105
+ if (!chain) {
106
+ throw new Error(
107
+ `Chain with network ID ${networkId} not found. Available network IDs: ${Array.from(
108
+ this.chains.values()
109
+ ).map((chain2) => chain2.networkId).filter(Boolean).join(", ")}`
110
+ );
111
+ }
112
+ return chain;
113
+ }
114
+ /**
115
+ * Get viem chain object by ID
116
+ */
117
+ getViemChain(chainId) {
118
+ const chain = this.viemChains.get(chainId);
119
+ if (!chain) {
120
+ throw new Error(
121
+ `Chain ${chainId} not found. Available chains: ${Array.from(this.viemChains.keys()).join(", ")}`
122
+ );
123
+ }
124
+ return chain;
125
+ }
126
+ /**
127
+ * Get all registered chain IDs
128
+ */
129
+ getSupportedChainIds() {
130
+ return Array.from(this.chains.keys());
131
+ }
132
+ /**
133
+ * Get all registered chains
134
+ */
135
+ getAllChains() {
136
+ return Array.from(this.chains.values());
137
+ }
138
+ /**
139
+ * Check if chain is supported
140
+ */
141
+ isChainSupported(chainId) {
142
+ return this.chains.has(chainId);
143
+ }
144
+ /**
145
+ * Check if chain is supported by network ID
146
+ */
147
+ isChainSupportedByNetworkId(networkId) {
148
+ return Array.from(this.chains.values()).some(
149
+ (chain) => chain.networkId === networkId
150
+ );
151
+ }
152
+ /**
153
+ * Get chains by type
154
+ */
155
+ getChainsByType(type) {
156
+ return Array.from(this.chains.values()).filter((chain) => {
157
+ if (type === "mainnet") {
158
+ return !chain.isTestnet && !chain.isLocal;
159
+ }
160
+ if (type === "testnet") {
161
+ return chain.isTestnet;
162
+ }
163
+ if (type === "local") {
164
+ return chain.isLocal;
165
+ }
166
+ return false;
167
+ });
168
+ }
169
+ /**
170
+ * Add custom RPC URL for existing chain
171
+ */
172
+ addCustomRpcUrl(chainId, rpcUrl) {
173
+ const chain = this.getChain(chainId);
174
+ const customChain = {
175
+ ...chain,
176
+ rpcUrl
177
+ };
178
+ this.registerChain(customChain);
179
+ }
180
+ };
181
+ var chainRegistry = ChainRegistry.getInstance();
182
+
183
+ // src/native/utils/validation.ts
184
+ var ValidationUtils = class {
185
+ /**
186
+ * Convert value to BigInt safely
187
+ */
188
+ static toBigInt(value) {
189
+ return BigInt(value.toString());
190
+ }
191
+ /**
192
+ * Validate Ethereum address format
193
+ */
194
+ static validateAddress(address, name = "Address") {
195
+ if (!address || !address.startsWith("0x") || address.length !== 42) {
196
+ throw new Error(`${name} must be a valid 0x-prefixed address`);
197
+ }
198
+ }
199
+ /**
200
+ * Validate amount (must be positive)
201
+ */
202
+ static validateAmount(amount, name = "Amount") {
203
+ const amountStr = amount.toString();
204
+ if (!amountStr || amountStr === "0" || this.toBigInt(amount) <= 0n) {
205
+ throw new Error(`${name} must be a positive value`);
206
+ }
207
+ }
208
+ /**
209
+ * Check if address is valid without throwing
210
+ */
211
+ static isValidAddress(address) {
212
+ return Boolean(address) && address.startsWith("0x") && address.length === 42;
213
+ }
214
+ /**
215
+ * Check if amount is valid without throwing
216
+ */
217
+ static isValidAmount(amount) {
218
+ try {
219
+ const amountStr = amount.toString();
220
+ return Boolean(amountStr) && amountStr !== "0" && this.toBigInt(amount) > 0n;
221
+ } catch {
222
+ return false;
223
+ }
224
+ }
225
+ /**
226
+ * Validate chain ID
227
+ */
228
+ static validateChainId(chainId) {
229
+ if (!Number.isInteger(chainId) || chainId <= 0) {
230
+ throw new Error("Chain ID must be a positive integer");
231
+ }
232
+ }
233
+ /**
234
+ * Validate RPC URL
235
+ */
236
+ static validateRpcUrl(rpcUrl) {
237
+ if (!rpcUrl || !rpcUrl.startsWith("http")) {
238
+ throw new Error("RPC URL must be a valid HTTP/HTTPS URL");
239
+ }
240
+ }
241
+ };
242
+
243
+ // src/native/base/contract.ts
244
+ var import_viem = require("viem");
245
+ var BaseContract = class {
246
+ constructor(config) {
247
+ const chain = chainRegistry.getViemChain(config.chainId);
248
+ this.client = (0, import_viem.createPublicClient)({
249
+ chain,
250
+ transport: (0, import_viem.http)(config.rpcUrl)
251
+ });
252
+ }
253
+ /**
254
+ * Get nonce for an address
255
+ */
256
+ async getNonce(address) {
257
+ if (!address) return void 0;
258
+ const nonceValue = await this.client.getTransactionCount({
259
+ address
260
+ });
261
+ return `0x${nonceValue.toString(16)}`;
262
+ }
263
+ /**
264
+ * Estimate gas for transaction
265
+ */
266
+ async estimateGas(data, to, from) {
267
+ const gasEstimate = await this.client.estimateGas({
268
+ account: from,
269
+ to,
270
+ data
271
+ });
272
+ return gasEstimate.toString();
273
+ }
274
+ };
275
+
276
+ // src/native/tokens/build.ts
277
+ var import_viem2 = require("viem");
278
+
279
+ // src/native/tokens/abi/erc20.ts
280
+ var erc20Abi = [
281
+ // Standard ERC20 functions
282
+ {
283
+ name: "approve",
284
+ type: "function",
285
+ stateMutability: "nonpayable",
286
+ inputs: [
287
+ { name: "spender", type: "address" },
288
+ { name: "amount", type: "uint256" }
289
+ ],
290
+ outputs: [{ name: "", type: "bool" }]
291
+ },
292
+ {
293
+ name: "transfer",
294
+ type: "function",
295
+ stateMutability: "nonpayable",
296
+ inputs: [
297
+ { name: "to", type: "address" },
298
+ { name: "amount", type: "uint256" }
299
+ ],
300
+ outputs: [{ name: "", type: "bool" }]
301
+ },
302
+ {
303
+ name: "transferFrom",
304
+ type: "function",
305
+ stateMutability: "nonpayable",
306
+ inputs: [
307
+ { name: "from", type: "address" },
308
+ { name: "to", type: "address" },
309
+ { name: "amount", type: "uint256" }
310
+ ],
311
+ outputs: [{ name: "", type: "bool" }]
312
+ },
313
+ {
314
+ name: "allowance",
315
+ type: "function",
316
+ stateMutability: "view",
317
+ inputs: [
318
+ { name: "owner", type: "address" },
319
+ { name: "spender", type: "address" }
320
+ ],
321
+ outputs: [{ name: "", type: "uint256" }]
322
+ },
323
+ {
324
+ name: "balanceOf",
325
+ type: "function",
326
+ stateMutability: "view",
327
+ inputs: [{ name: "account", type: "address" }],
328
+ outputs: [{ name: "", type: "uint256" }]
329
+ },
330
+ // Additional ERC20 functions
331
+ {
332
+ name: "name",
333
+ type: "function",
334
+ stateMutability: "view",
335
+ inputs: [],
336
+ outputs: [{ name: "", type: "string" }]
337
+ },
338
+ {
339
+ name: "symbol",
340
+ type: "function",
341
+ stateMutability: "view",
342
+ inputs: [],
343
+ outputs: [{ name: "", type: "string" }]
344
+ },
345
+ {
346
+ name: "decimals",
347
+ type: "function",
348
+ stateMutability: "view",
349
+ inputs: [],
350
+ outputs: [{ name: "", type: "uint8" }]
351
+ },
352
+ {
353
+ name: "totalSupply",
354
+ type: "function",
355
+ stateMutability: "view",
356
+ inputs: [],
357
+ outputs: [{ name: "", type: "uint256" }]
358
+ },
359
+ // Events
360
+ {
361
+ name: "Transfer",
362
+ type: "event",
363
+ inputs: [
364
+ { name: "from", type: "address", indexed: true },
365
+ { name: "to", type: "address", indexed: true },
366
+ { name: "value", type: "uint256", indexed: false }
367
+ ]
368
+ },
369
+ {
370
+ name: "Approval",
371
+ type: "event",
372
+ inputs: [
373
+ { name: "owner", type: "address", indexed: true },
374
+ { name: "spender", type: "address", indexed: true },
375
+ { name: "value", type: "uint256", indexed: false }
376
+ ]
377
+ }
378
+ ];
379
+
380
+ // src/native/tokens/build.ts
381
+ async function buildApprove(ctx, spender, amount, from) {
382
+ const data = (0, import_viem2.encodeFunctionData)({
383
+ abi: erc20Abi,
384
+ functionName: "approve",
385
+ args: [spender, amount]
386
+ });
387
+ const [nonce, gas] = await Promise.all([
388
+ ctx.getNonce(from),
389
+ ctx.estimateGas(data, from)
390
+ ]);
391
+ return {
392
+ from,
393
+ to: ctx.tokenAddress,
394
+ data,
395
+ gas,
396
+ nonce
397
+ };
398
+ }
399
+ async function buildTransfer(ctx, to, amount, from) {
400
+ const data = (0, import_viem2.encodeFunctionData)({
401
+ abi: erc20Abi,
402
+ functionName: "transfer",
403
+ args: [to, amount]
404
+ });
405
+ const [nonce, gas] = await Promise.all([
406
+ ctx.getNonce(from),
407
+ ctx.estimateGas(data, from)
408
+ ]);
409
+ return {
410
+ from,
411
+ to: ctx.tokenAddress,
412
+ data,
413
+ gas,
414
+ nonce
415
+ };
416
+ }
417
+ async function buildTransferFrom(ctx, fromAddress, to, amount, spender) {
418
+ const data = (0, import_viem2.encodeFunctionData)({
419
+ abi: erc20Abi,
420
+ functionName: "transferFrom",
421
+ args: [fromAddress, to, amount]
422
+ });
423
+ const [nonce, gas] = await Promise.all([
424
+ ctx.getNonce(spender),
425
+ ctx.estimateGas(data, spender)
426
+ ]);
427
+ return {
428
+ from: spender,
429
+ to: ctx.tokenAddress,
430
+ data,
431
+ gas,
432
+ nonce
433
+ };
434
+ }
435
+
436
+ // src/native/bridge/build.ts
437
+ var import_viem3 = require("viem");
438
+
439
+ // src/native/bridge/abi/bridge.ts
440
+ var bridgeAbi = [
441
+ {
442
+ inputs: [
443
+ { internalType: "uint32", name: "destinationNetwork", type: "uint32" },
444
+ { internalType: "address", name: "destinationAddress", type: "address" },
445
+ { internalType: "uint256", name: "amount", type: "uint256" },
446
+ { internalType: "address", name: "token", type: "address" },
447
+ { internalType: "bool", name: "forceUpdateGlobalExitRoot", type: "bool" },
448
+ { internalType: "bytes", name: "permitData", type: "bytes" }
449
+ ],
450
+ name: "bridgeAsset",
451
+ outputs: [],
452
+ stateMutability: "payable",
453
+ type: "function"
454
+ },
455
+ {
456
+ inputs: [
457
+ {
458
+ internalType: "bytes32[32]",
459
+ name: "smtProofLocalExitRoot",
460
+ type: "bytes32[32]"
461
+ },
462
+ {
463
+ internalType: "bytes32[32]",
464
+ name: "smtProofRollupExitRoot",
465
+ type: "bytes32[32]"
466
+ },
467
+ { internalType: "uint256", name: "globalIndex", type: "uint256" },
468
+ { internalType: "bytes32", name: "mainnetExitRoot", type: "bytes32" },
469
+ { internalType: "bytes32", name: "rollupExitRoot", type: "bytes32" },
470
+ { internalType: "uint32", name: "originNetwork", type: "uint32" },
471
+ { internalType: "address", name: "originTokenAddress", type: "address" },
472
+ { internalType: "uint32", name: "destinationNetwork", type: "uint32" },
473
+ { internalType: "address", name: "destinationAddress", type: "address" },
474
+ { internalType: "uint256", name: "amount", type: "uint256" },
475
+ { internalType: "bytes", name: "metadata", type: "bytes" }
476
+ ],
477
+ name: "claimAsset",
478
+ outputs: [],
479
+ stateMutability: "nonpayable",
480
+ type: "function"
481
+ },
482
+ {
483
+ inputs: [
484
+ { internalType: "uint32", name: "leafIndex", type: "uint32" },
485
+ { internalType: "uint32", name: "sourceBridgeNetwork", type: "uint32" }
486
+ ],
487
+ name: "isClaimed",
488
+ outputs: [{ internalType: "bool", name: "", type: "bool" }],
489
+ stateMutability: "view",
490
+ type: "function"
491
+ },
492
+ {
493
+ inputs: [
494
+ { internalType: "uint32", name: "originNetwork", type: "uint32" },
495
+ { internalType: "address", name: "originTokenAddress", type: "address" }
496
+ ],
497
+ name: "getTokenWrappedAddress",
498
+ outputs: [{ internalType: "address", name: "", type: "address" }],
499
+ stateMutability: "view",
500
+ type: "function"
501
+ },
502
+ {
503
+ inputs: [
504
+ { internalType: "uint32", name: "destinationNetwork", type: "uint32" },
505
+ { internalType: "address", name: "destinationAddress", type: "address" },
506
+ { internalType: "bool", name: "forceUpdateGlobalExitRoot", type: "bool" },
507
+ { internalType: "bytes", name: "permitData", type: "bytes" }
508
+ ],
509
+ name: "bridgeMessage",
510
+ outputs: [],
511
+ stateMutability: "payable",
512
+ type: "function"
513
+ },
514
+ {
515
+ inputs: [
516
+ {
517
+ internalType: "bytes32[32]",
518
+ name: "smtProofLocalExitRoot",
519
+ type: "bytes32[32]"
520
+ },
521
+ {
522
+ internalType: "bytes32[32]",
523
+ name: "smtProofRollupExitRoot",
524
+ type: "bytes32[32]"
525
+ },
526
+ { internalType: "uint256", name: "globalIndex", type: "uint256" },
527
+ { internalType: "bytes32", name: "mainnetExitRoot", type: "bytes32" },
528
+ { internalType: "bytes32", name: "rollupExitRoot", type: "bytes32" },
529
+ { internalType: "uint32", name: "originNetwork", type: "uint32" },
530
+ { internalType: "address", name: "originTokenAddress", type: "address" },
531
+ { internalType: "uint32", name: "destinationNetwork", type: "uint32" },
532
+ { internalType: "address", name: "destinationAddress", type: "address" },
533
+ { internalType: "uint256", name: "amount", type: "uint256" },
534
+ { internalType: "bytes", name: "metadata", type: "bytes" }
535
+ ],
536
+ name: "claimMessage",
537
+ outputs: [],
538
+ stateMutability: "nonpayable",
539
+ type: "function"
540
+ },
541
+ {
542
+ inputs: [
543
+ { internalType: "uint32", name: "originNetwork", type: "uint32" },
544
+ { internalType: "address", name: "originTokenAddress", type: "address" }
545
+ ],
546
+ name: "precalculatedWrapperAddress",
547
+ outputs: [{ internalType: "address", name: "", type: "address" }],
548
+ stateMutability: "view",
549
+ type: "function"
550
+ },
551
+ {
552
+ inputs: [
553
+ { internalType: "address", name: "wrappedToken", type: "address" }
554
+ ],
555
+ name: "wrappedTokenToTokenInfo",
556
+ outputs: [
557
+ { internalType: "uint32", name: "originNetwork", type: "uint32" },
558
+ { internalType: "address", name: "originTokenAddress", type: "address" }
559
+ ],
560
+ stateMutability: "view",
561
+ type: "function"
562
+ },
563
+ {
564
+ inputs: [],
565
+ name: "networkID",
566
+ outputs: [{ internalType: "uint32", name: "", type: "uint32" }],
567
+ stateMutability: "view",
568
+ type: "function"
569
+ },
570
+ {
571
+ anonymous: false,
572
+ inputs: [
573
+ {
574
+ indexed: false,
575
+ internalType: "uint8",
576
+ name: "leafType",
577
+ type: "uint8"
578
+ },
579
+ {
580
+ indexed: false,
581
+ internalType: "uint32",
582
+ name: "originNetwork",
583
+ type: "uint32"
584
+ },
585
+ {
586
+ indexed: false,
587
+ internalType: "address",
588
+ name: "originAddress",
589
+ type: "address"
590
+ },
591
+ {
592
+ indexed: false,
593
+ internalType: "uint32",
594
+ name: "destinationNetwork",
595
+ type: "uint32"
596
+ },
597
+ {
598
+ indexed: false,
599
+ internalType: "address",
600
+ name: "destinationAddress",
601
+ type: "address"
602
+ },
603
+ {
604
+ indexed: false,
605
+ internalType: "uint256",
606
+ name: "amount",
607
+ type: "uint256"
608
+ },
609
+ {
610
+ indexed: false,
611
+ internalType: "bytes",
612
+ name: "metadata",
613
+ type: "bytes"
614
+ },
615
+ {
616
+ indexed: false,
617
+ internalType: "uint32",
618
+ name: "depositCount",
619
+ type: "uint32"
620
+ }
621
+ ],
622
+ name: "BridgeEvent",
623
+ type: "event"
624
+ }
625
+ ];
626
+
627
+ // src/native/bridge/build.ts
628
+ async function buildBridgeAsset(ctx, destinationNetwork, destinationAddress, amount, token, forceUpdateGlobalExitRoot, permitData = "0x", from) {
629
+ const data = (0, import_viem3.encodeFunctionData)({
630
+ abi: bridgeAbi,
631
+ functionName: "bridgeAsset",
632
+ args: [
633
+ destinationNetwork,
634
+ destinationAddress,
635
+ amount,
636
+ token,
637
+ forceUpdateGlobalExitRoot,
638
+ permitData
639
+ ]
640
+ });
641
+ const [nonce, gas] = await Promise.all([
642
+ ctx.getNonce(from),
643
+ ctx.estimateGas(data, ctx.bridgeAddress, from)
644
+ ]);
645
+ return {
646
+ from,
647
+ to: ctx.bridgeAddress,
648
+ data,
649
+ gas,
650
+ nonce
651
+ };
652
+ }
653
+ async function buildClaimAsset(ctx, smtProofLocalExitRoot, smtProofRollupExitRoot, globalIndex, mainnetExitRoot, rollupExitRoot, originNetwork, originTokenAddress, destinationNetwork, destinationAddress, amount, metadata, from) {
654
+ const data = (0, import_viem3.encodeFunctionData)({
655
+ abi: bridgeAbi,
656
+ functionName: "claimAsset",
657
+ args: [
658
+ // @ts-ignore - Viem expects exact tuple types but we're passing arrays
659
+ smtProofLocalExitRoot,
660
+ // @ts-ignore - Viem expects exact tuple types but we're passing arrays
661
+ smtProofRollupExitRoot,
662
+ globalIndex,
663
+ mainnetExitRoot,
664
+ rollupExitRoot,
665
+ originNetwork,
666
+ originTokenAddress,
667
+ destinationNetwork,
668
+ destinationAddress,
669
+ amount,
670
+ metadata
671
+ ]
672
+ });
673
+ const [nonce, gas] = await Promise.all([
674
+ ctx.getNonce(from),
675
+ ctx.estimateGas(data, ctx.bridgeAddress, from)
676
+ ]);
677
+ return {
678
+ from,
679
+ to: ctx.bridgeAddress,
680
+ data,
681
+ gas,
682
+ nonce
683
+ };
684
+ }
685
+
686
+ // src/native/bridge/message.ts
687
+ var import_viem4 = require("viem");
688
+ async function buildBridgeMessage(ctx, destinationNetwork, destinationAddress, forceUpdateGlobalExitRoot, permitData = "0x", from) {
689
+ const data = (0, import_viem4.encodeFunctionData)({
690
+ abi: bridgeAbi,
691
+ functionName: "bridgeMessage",
692
+ args: [
693
+ destinationNetwork,
694
+ destinationAddress,
695
+ forceUpdateGlobalExitRoot,
696
+ permitData
697
+ ]
698
+ });
699
+ const [nonce, gas] = await Promise.all([
700
+ ctx.getNonce(from),
701
+ ctx.estimateGas(data, ctx.bridgeAddress, from)
702
+ ]);
703
+ return {
704
+ from,
705
+ to: ctx.bridgeAddress,
706
+ data,
707
+ gas,
708
+ nonce
709
+ };
710
+ }
711
+ async function buildClaimMessage(ctx, smtProofLocalExitRoot, smtProofRollupExitRoot, globalIndex, mainnetExitRoot, rollupExitRoot, originNetwork, originTokenAddress, destinationNetwork, destinationAddress, amount, metadata, from) {
712
+ const data = (0, import_viem4.encodeFunctionData)({
713
+ abi: bridgeAbi,
714
+ functionName: "claimMessage",
715
+ args: [
716
+ // @ts-ignore - Viem expects exact tuple types but we're passing arrays
717
+ smtProofLocalExitRoot,
718
+ // @ts-ignore - Viem expects exact tuple types but we're passing arrays
719
+ smtProofRollupExitRoot,
720
+ globalIndex,
721
+ mainnetExitRoot,
722
+ rollupExitRoot,
723
+ originNetwork,
724
+ originTokenAddress,
725
+ destinationNetwork,
726
+ destinationAddress,
727
+ amount,
728
+ metadata
729
+ ]
730
+ });
731
+ const [nonce, gas] = await Promise.all([
732
+ ctx.getNonce(from),
733
+ ctx.estimateGas(data, ctx.bridgeAddress, from)
734
+ ]);
735
+ return {
736
+ from,
737
+ to: ctx.bridgeAddress,
738
+ data,
739
+ gas,
740
+ nonce
741
+ };
742
+ }
743
+
744
+ // src/native/bridge/util.ts
745
+ var import_viem5 = require("viem");
746
+ var BridgeUtil = class _BridgeUtil {
747
+ constructor(client, proofApiUrl) {
748
+ this.BRIDGE_TOPIC = "0x501781209a1f8899323b96b4ef08b168df93e0a90c673d1e4cce39366cb62f9b";
749
+ this.client = client;
750
+ this.proofApiUrl = proofApiUrl;
751
+ }
752
+ /**
753
+ * Create BridgeUtil instance from network ID using chain registry
754
+ *
755
+ * @param sourceNetworkId - Network ID of the source network
756
+ * @returns BridgeUtil instance configured for the source network
757
+ */
758
+ static async fromNetworkId(sourceNetworkId) {
759
+ const chain = _BridgeUtil.findChain(sourceNetworkId);
760
+ if (!chain.proofApiUrl) {
761
+ throw new Error(
762
+ `No proof API URL configured for network ${sourceNetworkId}`
763
+ );
764
+ }
765
+ const sourceClient = (0, import_viem5.createPublicClient)({
766
+ transport: (0, import_viem5.http)(chain.rpcUrl)
767
+ });
768
+ return new _BridgeUtil(sourceClient, chain.proofApiUrl);
769
+ }
770
+ /**
771
+ * Find chain configuration by network ID
772
+ *
773
+ * @param sourceNetworkId - Network ID to search for
774
+ * @returns Chain configuration
775
+ * @throws Error if chain not found
776
+ */
777
+ static findChain(sourceNetworkId) {
778
+ try {
779
+ return chainRegistry.getChainByNetworkId(sourceNetworkId);
780
+ } catch {
781
+ const allChains = chainRegistry.getAllChains();
782
+ const availableNetworkIds = allChains.map((chain) => chain.networkId).filter(Boolean).join(", ");
783
+ throw new Error(
784
+ `Source network ${sourceNetworkId} not found in chain registry. Available network IDs: ${availableNetworkIds}`
785
+ );
786
+ }
787
+ }
788
+ /**
789
+ * Extract bridge event data from transaction receipt
790
+ */
791
+ async extractBridgeEvent(transactionHash, _networkId, bridgeIndex = 0) {
792
+ try {
793
+ const receipt = await this.client.getTransactionReceipt({
794
+ hash: transactionHash
795
+ });
796
+ const bridgeLogs = receipt.logs.filter(
797
+ (log2) => log2.topics[0] && log2.topics[0].toLowerCase() === this.BRIDGE_TOPIC.toLowerCase()
798
+ );
799
+ if (!bridgeLogs.length) {
800
+ throw new Error("No bridge event found in transaction receipt");
801
+ }
802
+ if (bridgeIndex >= bridgeLogs.length) {
803
+ throw new Error(
804
+ `Bridge index ${bridgeIndex} not found. Available indices: 0-${bridgeLogs.length - 1}`
805
+ );
806
+ }
807
+ const log = bridgeLogs[bridgeIndex];
808
+ if (!log) {
809
+ throw new Error("Bridge log not found");
810
+ }
811
+ const decoded = (0, import_viem5.decodeEventLog)({
812
+ abi: bridgeAbi,
813
+ data: log.data,
814
+ topics: log.topics
815
+ });
816
+ if (decoded.eventName !== "BridgeEvent") {
817
+ throw new Error("Invalid bridge event");
818
+ }
819
+ const args = decoded.args;
820
+ const {
821
+ originNetwork,
822
+ originAddress,
823
+ destinationNetwork,
824
+ destinationAddress,
825
+ amount,
826
+ metadata,
827
+ depositCount
828
+ } = args;
829
+ return {
830
+ originNetwork: Number(originNetwork),
831
+ originTokenAddress: originAddress,
832
+ destinationNetwork: Number(destinationNetwork),
833
+ destinationAddress,
834
+ amount,
835
+ metadata: metadata || "0x",
836
+ depositCount: Number(depositCount)
837
+ };
838
+ } catch (error) {
839
+ if (error instanceof Error) {
840
+ throw new Error(`Failed to extract bridge event: ${error.message}`);
841
+ }
842
+ throw new Error("Failed to extract bridge event: Unknown error");
843
+ }
844
+ }
845
+ /**
846
+ * Fetch merkle proof from Polygon's proof API
847
+ */
848
+ async fetchMerkleProof(networkId, depositCount) {
849
+ try {
850
+ const baseUrl = this.proofApiUrl.endsWith("/") ? this.proofApiUrl : `${this.proofApiUrl}/`;
851
+ const url = `${baseUrl}merkle-proof?networkId=${networkId}&depositCount=${depositCount}`;
852
+ const response = await fetch(url);
853
+ if (!response.ok) {
854
+ throw new Error(
855
+ `Failed to fetch merkle proof: ${response.statusText} (${response.status})`
856
+ );
857
+ }
858
+ const data = await response.json();
859
+ if (!data.proof) {
860
+ throw new Error("Invalid response format: missing proof data");
861
+ }
862
+ return data.proof;
863
+ } catch (error) {
864
+ if (error instanceof Error) {
865
+ throw new Error(`Failed to fetch merkle proof: ${error.message}`);
866
+ }
867
+ throw new Error("Failed to fetch merkle proof: Unknown error");
868
+ }
869
+ }
870
+ /**
871
+ * Compute global index from local index and network ID
872
+ */
873
+ computeGlobalIndex(indexLocal, sourceNetworkId) {
874
+ const MAINNET_FLAG = BigInt(2 ** 64);
875
+ if (BigInt(sourceNetworkId) === BigInt(0)) {
876
+ return BigInt(indexLocal) + MAINNET_FLAG;
877
+ } else {
878
+ return BigInt(indexLocal) + BigInt(sourceNetworkId - 1) * BigInt(2 ** 32);
879
+ }
880
+ }
881
+ /**
882
+ * Build claim payload from transaction hash (user-friendly method)
883
+ */
884
+ async buildPayloadForClaim(transactionHash, sourceNetworkId, bridgeIndex = 0) {
885
+ const bridgeEvent = await this.extractBridgeEvent(
886
+ transactionHash,
887
+ sourceNetworkId,
888
+ bridgeIndex
889
+ );
890
+ const proof = await this.fetchMerkleProof(
891
+ sourceNetworkId,
892
+ bridgeEvent.depositCount
893
+ );
894
+ const globalIndex = this.computeGlobalIndex(
895
+ bridgeEvent.depositCount,
896
+ sourceNetworkId
897
+ );
898
+ return {
899
+ smtProof: proof.merkle_proof,
900
+ smtProofRollup: proof.rollup_merkle_proof,
901
+ globalIndex: globalIndex.toString(),
902
+ mainnetExitRoot: proof.main_exit_root,
903
+ rollupExitRoot: proof.rollup_exit_root,
904
+ originNetwork: bridgeEvent.originNetwork,
905
+ originTokenAddress: bridgeEvent.originTokenAddress,
906
+ destinationNetwork: bridgeEvent.destinationNetwork,
907
+ destinationAddress: bridgeEvent.destinationAddress,
908
+ amount: bridgeEvent.amount,
909
+ metadata: bridgeEvent.metadata
910
+ };
911
+ }
912
+ /**
913
+ * Build claim asset parameters from transaction hash
914
+ */
915
+ async buildClaimAssetParams(transactionHash, sourceNetworkId, bridgeIndex = 0) {
916
+ const payload = await this.buildPayloadForClaim(
917
+ transactionHash,
918
+ sourceNetworkId,
919
+ bridgeIndex
920
+ );
921
+ return {
922
+ smtProofLocalExitRoot: payload.smtProof,
923
+ smtProofRollupExitRoot: payload.smtProofRollup,
924
+ globalIndex: BigInt(payload.globalIndex),
925
+ mainnetExitRoot: payload.mainnetExitRoot,
926
+ rollupExitRoot: payload.rollupExitRoot,
927
+ originNetwork: payload.originNetwork,
928
+ originTokenAddress: payload.originTokenAddress,
929
+ destinationNetwork: payload.destinationNetwork,
930
+ destinationAddress: payload.destinationAddress,
931
+ amount: payload.amount,
932
+ metadata: payload.metadata
933
+ };
934
+ }
935
+ /**
936
+ * Build claim message parameters from transaction hash
937
+ */
938
+ async buildClaimMessageParams(transactionHash, sourceNetworkId, bridgeIndex = 0) {
939
+ const payload = await this.buildPayloadForClaim(
940
+ transactionHash,
941
+ sourceNetworkId,
942
+ bridgeIndex
943
+ );
944
+ return {
945
+ smtProofLocalExitRoot: payload.smtProof,
946
+ smtProofRollupExitRoot: payload.smtProofRollup,
947
+ globalIndex: BigInt(payload.globalIndex),
948
+ mainnetExitRoot: payload.mainnetExitRoot,
949
+ rollupExitRoot: payload.rollupExitRoot,
950
+ originNetwork: payload.originNetwork,
951
+ originTokenAddress: payload.originTokenAddress,
952
+ destinationNetwork: payload.destinationNetwork,
953
+ destinationAddress: payload.destinationAddress,
954
+ amount: payload.amount,
955
+ metadata: payload.metadata
956
+ };
957
+ }
958
+ /**
959
+ * Get bridge event info from transaction hash
960
+ */
961
+ async getBridgeEventInfo(transactionHash, sourceNetworkId, bridgeIndex = 0) {
962
+ return this.extractBridgeEvent(
963
+ transactionHash,
964
+ sourceNetworkId,
965
+ bridgeIndex
966
+ );
967
+ }
968
+ };
969
+
970
+ // src/native/bridge/bridge.ts
971
+ var Bridge = class extends BaseContract {
972
+ constructor(config) {
973
+ super({ rpcUrl: config.rpcUrl, chainId: config.chainId });
974
+ this.bridgeAddress = config.bridgeAddress;
975
+ }
976
+ /**
977
+ * Build bridge asset transaction
978
+ */
979
+ async buildBridgeAsset(params, from) {
980
+ ValidationUtils.validateAddress(
981
+ params.destinationAddress,
982
+ "Destination address"
983
+ );
984
+ ValidationUtils.validateAddress(params.token, "Token address");
985
+ return buildBridgeAsset(
986
+ {
987
+ bridgeAddress: this.bridgeAddress,
988
+ estimateGas: (data, to, from2) => this.estimateGas(data, to, from2),
989
+ getNonce: (address) => this.getNonce(address)
990
+ },
991
+ params.destinationNetwork,
992
+ params.destinationAddress,
993
+ BigInt(params.amount),
994
+ params.token,
995
+ params.forceUpdateGlobalExitRoot,
996
+ params.permitData,
997
+ from
998
+ );
999
+ }
1000
+ /**
1001
+ * Build claim asset transaction
1002
+ */
1003
+ async buildClaimAsset(params, from) {
1004
+ ValidationUtils.validateAddress(
1005
+ params.originTokenAddress,
1006
+ "Origin token address"
1007
+ );
1008
+ ValidationUtils.validateAddress(
1009
+ params.destinationAddress,
1010
+ "Destination address"
1011
+ );
1012
+ return buildClaimAsset(
1013
+ {
1014
+ bridgeAddress: this.bridgeAddress,
1015
+ estimateGas: (data, to, from2) => this.estimateGas(data, to, from2),
1016
+ getNonce: (address) => this.getNonce(address)
1017
+ },
1018
+ params.smtProofLocalExitRoot,
1019
+ params.smtProofRollupExitRoot,
1020
+ params.globalIndex,
1021
+ params.mainnetExitRoot,
1022
+ params.rollupExitRoot,
1023
+ params.originNetwork,
1024
+ params.originTokenAddress,
1025
+ params.destinationNetwork,
1026
+ params.destinationAddress,
1027
+ params.amount,
1028
+ params.metadata,
1029
+ from
1030
+ );
1031
+ }
1032
+ /**
1033
+ * Check if bridge deposit is claimed
1034
+ */
1035
+ async isClaimed(params) {
1036
+ const result = await this.client.readContract({
1037
+ address: this.bridgeAddress,
1038
+ abi: bridgeAbi,
1039
+ functionName: "isClaimed",
1040
+ args: [params.leafIndex, params.sourceBridgeNetwork]
1041
+ });
1042
+ return result;
1043
+ }
1044
+ /**
1045
+ * Get wrapped token address
1046
+ */
1047
+ async getWrappedTokenAddress(params) {
1048
+ ValidationUtils.validateAddress(
1049
+ params.originTokenAddress,
1050
+ "Origin token address"
1051
+ );
1052
+ const result = await this.client.readContract({
1053
+ address: this.bridgeAddress,
1054
+ abi: bridgeAbi,
1055
+ functionName: "getTokenWrappedAddress",
1056
+ args: [params.originNetwork, params.originTokenAddress]
1057
+ });
1058
+ return result;
1059
+ }
1060
+ /**
1061
+ * Get network ID
1062
+ */
1063
+ async getNetworkId() {
1064
+ const result = await this.client.readContract({
1065
+ address: this.bridgeAddress,
1066
+ abi: bridgeAbi,
1067
+ functionName: "networkID",
1068
+ args: []
1069
+ });
1070
+ return Number(result);
1071
+ }
1072
+ /**
1073
+ * Get bridge contract address
1074
+ */
1075
+ getBridgeAddress() {
1076
+ return this.bridgeAddress;
1077
+ }
1078
+ /**
1079
+ * Build bridge message transaction
1080
+ */
1081
+ async buildBridgeMessage(params, from) {
1082
+ ValidationUtils.validateAddress(
1083
+ params.destinationAddress,
1084
+ "Destination address"
1085
+ );
1086
+ return buildBridgeMessage(
1087
+ {
1088
+ bridgeAddress: this.bridgeAddress,
1089
+ estimateGas: (data, to, from2) => this.estimateGas(data, to, from2),
1090
+ getNonce: (address) => this.getNonce(address)
1091
+ },
1092
+ params.destinationNetwork,
1093
+ params.destinationAddress,
1094
+ params.forceUpdateGlobalExitRoot,
1095
+ params.permitData || "0x",
1096
+ from
1097
+ );
1098
+ }
1099
+ /**
1100
+ * Build claim message transaction
1101
+ */
1102
+ async buildClaimMessage(params, from) {
1103
+ ValidationUtils.validateAddress(
1104
+ params.originTokenAddress,
1105
+ "Origin token address"
1106
+ );
1107
+ ValidationUtils.validateAddress(
1108
+ params.destinationAddress,
1109
+ "Destination address"
1110
+ );
1111
+ return buildClaimMessage(
1112
+ {
1113
+ bridgeAddress: this.bridgeAddress,
1114
+ estimateGas: (data, to, from2) => this.estimateGas(data, to, from2),
1115
+ getNonce: (address) => this.getNonce(address)
1116
+ },
1117
+ params.smtProofLocalExitRoot,
1118
+ params.smtProofRollupExitRoot,
1119
+ params.globalIndex,
1120
+ params.mainnetExitRoot,
1121
+ params.rollupExitRoot,
1122
+ params.originNetwork,
1123
+ params.originTokenAddress,
1124
+ params.destinationNetwork,
1125
+ params.destinationAddress,
1126
+ params.amount,
1127
+ params.metadata,
1128
+ from
1129
+ );
1130
+ }
1131
+ /**
1132
+ * Get precalculated wrapper address
1133
+ */
1134
+ async getPrecalculatedWrapperAddress(params) {
1135
+ ValidationUtils.validateAddress(
1136
+ params.originTokenAddress,
1137
+ "Origin token address"
1138
+ );
1139
+ const result = await this.client.readContract({
1140
+ address: this.bridgeAddress,
1141
+ abi: bridgeAbi,
1142
+ functionName: "precalculatedWrapperAddress",
1143
+ args: [params.originNetwork, params.originTokenAddress]
1144
+ });
1145
+ return result;
1146
+ }
1147
+ /**
1148
+ * Get origin token info from wrapped token
1149
+ */
1150
+ async getOriginTokenInfo(params) {
1151
+ ValidationUtils.validateAddress(
1152
+ params.wrappedToken,
1153
+ "Wrapped token address"
1154
+ );
1155
+ const result = await this.client.readContract({
1156
+ address: this.bridgeAddress,
1157
+ abi: bridgeAbi,
1158
+ functionName: "wrappedTokenToTokenInfo",
1159
+ args: [params.wrappedToken]
1160
+ });
1161
+ return result;
1162
+ }
1163
+ /**
1164
+ * Build claim asset transaction from bridge transaction hash
1165
+ *
1166
+ * @param transactionHash - Hash of the bridge transaction on the source network
1167
+ * @param sourceNetworkId - Network ID of the source network (where bridge tx happened)
1168
+ * @param bridgeIndex - Index of bridge event in transaction (default: 0)
1169
+ * @param from - From address for the claim transaction
1170
+ */
1171
+ async buildClaimAssetFromHash(transactionHash, sourceNetworkId, bridgeIndex = 0, from) {
1172
+ const bridgeUtil = await BridgeUtil.fromNetworkId(sourceNetworkId);
1173
+ const params = await bridgeUtil.buildClaimAssetParams(
1174
+ transactionHash,
1175
+ sourceNetworkId,
1176
+ bridgeIndex
1177
+ );
1178
+ return this.buildClaimAsset(params, from);
1179
+ }
1180
+ /**
1181
+ * Build claim message transaction from bridge transaction hash
1182
+ *
1183
+ * @param transactionHash - Hash of the bridge transaction on the source network
1184
+ * @param sourceNetworkId - Network ID of the source network (where bridge tx happened)
1185
+ * @param bridgeIndex - Index of bridge event in transaction (default: 0)
1186
+ * @param from - From address for the claim transaction
1187
+ */
1188
+ async buildClaimMessageFromHash(transactionHash, sourceNetworkId, bridgeIndex = 0, from) {
1189
+ const bridgeUtil = await BridgeUtil.fromNetworkId(sourceNetworkId);
1190
+ const params = await bridgeUtil.buildClaimMessageParams(
1191
+ transactionHash,
1192
+ sourceNetworkId,
1193
+ bridgeIndex
1194
+ );
1195
+ return this.buildClaimMessage(params, from);
1196
+ }
1197
+ /**
1198
+ * Get bridge event info from transaction hash
1199
+ *
1200
+ * @param transactionHash - Hash of the bridge transaction on the source network
1201
+ * @param sourceNetworkId - Network ID of the source network (where bridge tx happened)
1202
+ * @param bridgeIndex - Index of bridge event in transaction (default: 0)
1203
+ */
1204
+ async getBridgeEventInfo(transactionHash, sourceNetworkId, bridgeIndex = 0) {
1205
+ const bridgeUtil = await BridgeUtil.fromNetworkId(sourceNetworkId);
1206
+ return bridgeUtil.getBridgeEventInfo(
1207
+ transactionHash,
1208
+ sourceNetworkId,
1209
+ bridgeIndex
1210
+ );
1211
+ }
1212
+ };
1213
+
1214
+ // src/native/services/abi.ts
1215
+ var ABIS = {
1216
+ BRIDGE: bridgeAbi,
1217
+ ERC20: erc20Abi
1218
+ };
1219
+ function getAbi(contractType) {
1220
+ return ABIS[contractType];
1221
+ }
1222
+
1223
+ // src/native/tokens/erc20.ts
1224
+ var ERC20 = class extends BaseContract {
1225
+ constructor(config) {
1226
+ super({ rpcUrl: config.rpcUrl, chainId: config.chainId });
1227
+ this.tokenAddress = config.tokenAddress;
1228
+ this.config = config;
1229
+ }
1230
+ /**
1231
+ * Get ERC20 token balance in wei
1232
+ */
1233
+ async getBalance(address) {
1234
+ ValidationUtils.validateAddress(address, "Address");
1235
+ const balance = await this.client.readContract({
1236
+ address: this.tokenAddress,
1237
+ abi: getAbi("ERC20"),
1238
+ functionName: "balanceOf",
1239
+ args: [address]
1240
+ });
1241
+ return balance.toString();
1242
+ }
1243
+ /**
1244
+ * Get allowance in wei
1245
+ */
1246
+ async getAllowance(owner, spender) {
1247
+ ValidationUtils.validateAddress(owner, "Owner address");
1248
+ ValidationUtils.validateAddress(spender, "Spender address");
1249
+ try {
1250
+ const allowance = await this.client.readContract({
1251
+ address: this.tokenAddress,
1252
+ abi: getAbi("ERC20"),
1253
+ functionName: "allowance",
1254
+ args: [owner, spender]
1255
+ });
1256
+ return allowance.toString();
1257
+ } catch (error) {
1258
+ throw new Error(
1259
+ `Failed to get allowance: ${error instanceof Error ? error.message : "Unknown error"}`
1260
+ );
1261
+ }
1262
+ }
1263
+ /**
1264
+ * Build approve transaction
1265
+ */
1266
+ async buildApprove(spender, amount, from) {
1267
+ ValidationUtils.validateAddress(spender, "Spender address");
1268
+ ValidationUtils.validateAmount(amount, "Amount");
1269
+ return buildApprove(
1270
+ {
1271
+ tokenAddress: this.tokenAddress,
1272
+ estimateGas: (data, from2) => this.estimateGas(data, this.tokenAddress, from2),
1273
+ getNonce: (address) => this.getNonce(address)
1274
+ },
1275
+ spender,
1276
+ BigInt(amount),
1277
+ from
1278
+ );
1279
+ }
1280
+ /**
1281
+ * Build transfer transaction
1282
+ */
1283
+ async buildTransfer(to, amount, from) {
1284
+ ValidationUtils.validateAddress(to, "Recipient address");
1285
+ ValidationUtils.validateAmount(amount, "Amount");
1286
+ return buildTransfer(
1287
+ {
1288
+ tokenAddress: this.tokenAddress,
1289
+ estimateGas: (data, from2) => this.estimateGas(data, this.tokenAddress, from2),
1290
+ getNonce: (address) => this.getNonce(address)
1291
+ },
1292
+ to,
1293
+ BigInt(amount),
1294
+ from
1295
+ );
1296
+ }
1297
+ /**
1298
+ * Build transferFrom transaction
1299
+ */
1300
+ async buildTransferFrom(from, to, amount, spender) {
1301
+ ValidationUtils.validateAddress(from, "Owner address");
1302
+ ValidationUtils.validateAddress(to, "Recipient address");
1303
+ ValidationUtils.validateAmount(amount, "Amount");
1304
+ return buildTransferFrom(
1305
+ {
1306
+ tokenAddress: this.tokenAddress,
1307
+ estimateGas: (data, from2) => this.estimateGas(data, this.tokenAddress, from2),
1308
+ getNonce: (address) => this.getNonce(address)
1309
+ },
1310
+ from,
1311
+ to,
1312
+ BigInt(amount),
1313
+ spender
1314
+ );
1315
+ }
1316
+ /**
1317
+ * Bridge this token to another network
1318
+ */
1319
+ async bridgeTo(destinationNetwork, destinationAddress, amount, from, options = {}) {
1320
+ ValidationUtils.validateAddress(destinationAddress, "Destination address");
1321
+ ValidationUtils.validateAmount(amount, "Amount");
1322
+ const bridge = this.getBridge();
1323
+ return bridge.buildBridgeAsset(
1324
+ {
1325
+ destinationNetwork,
1326
+ destinationAddress,
1327
+ amount,
1328
+ token: this.tokenAddress,
1329
+ forceUpdateGlobalExitRoot: options.forceUpdateGlobalExitRoot ?? true,
1330
+ permitData: options.permitData || "0x"
1331
+ },
1332
+ from
1333
+ );
1334
+ }
1335
+ /**
1336
+ * Get wrapped version of this token on destination network
1337
+ */
1338
+ async getWrappedToken() {
1339
+ const bridge = this.getBridge();
1340
+ return bridge.getWrappedTokenAddress({
1341
+ originNetwork: this.config.chainId,
1342
+ originTokenAddress: this.tokenAddress
1343
+ });
1344
+ }
1345
+ /**
1346
+ * Claim asset from bridge transaction hash
1347
+ *
1348
+ * @param transactionHash - Hash of the bridge transaction on the source network
1349
+ * @param sourceNetworkId - Network ID of the source network (where bridge tx happened)
1350
+ * @param bridgeIndex - Index of bridge event in transaction (default: 0)
1351
+ * @param from - From address for the claim transaction
1352
+ */
1353
+ async claimAsset(transactionHash, sourceNetworkId, bridgeIndex = 0, from) {
1354
+ const bridge = this.getBridge();
1355
+ return bridge.buildClaimAssetFromHash(
1356
+ transactionHash,
1357
+ sourceNetworkId,
1358
+ bridgeIndex,
1359
+ from
1360
+ );
1361
+ }
1362
+ /**
1363
+ * Claim message from bridge transaction hash
1364
+ *
1365
+ * @param transactionHash - Hash of the bridge transaction on the source network
1366
+ * @param sourceNetworkId - Network ID of the source network (where bridge tx happened)
1367
+ * @param bridgeIndex - Index of bridge event in transaction (default: 0)
1368
+ * @param from - From address for the claim transaction
1369
+ */
1370
+ async claimMessage(transactionHash, sourceNetworkId, bridgeIndex = 0, from) {
1371
+ const bridge = this.getBridge();
1372
+ return bridge.buildClaimMessageFromHash(
1373
+ transactionHash,
1374
+ sourceNetworkId,
1375
+ bridgeIndex,
1376
+ from
1377
+ );
1378
+ }
1379
+ /**
1380
+ * Get bridge event info from transaction hash
1381
+ *
1382
+ * @param transactionHash - Hash of the bridge transaction on the source network
1383
+ * @param sourceNetworkId - Network ID of the source network (where bridge tx happened)
1384
+ * @param bridgeIndex - Index of bridge event in transaction (default: 0)
1385
+ */
1386
+ async getBridgeEventInfo(transactionHash, sourceNetworkId, bridgeIndex = 0) {
1387
+ const bridge = this.getBridge();
1388
+ return bridge.getBridgeEventInfo(
1389
+ transactionHash,
1390
+ sourceNetworkId,
1391
+ bridgeIndex
1392
+ );
1393
+ }
1394
+ getBridge() {
1395
+ const chain = chainRegistry.getChain(this.config.chainId);
1396
+ if (!chain.bridgeAddress) {
1397
+ throw new Error(
1398
+ `No bridge address configured for network ${this.config.chainId}`
1399
+ );
1400
+ }
1401
+ return new Bridge({
1402
+ bridgeAddress: chain.bridgeAddress,
1403
+ rpcUrl: this.config.rpcUrl,
1404
+ chainId: this.config.chainId
1405
+ });
1406
+ }
1407
+ };
1408
+
1409
+ // src/native/index.ts
1410
+ var import_viem6 = require("viem");
1411
+
1412
+ // src/constants.ts
1413
+ var NETWORKS = {
1414
+ SEPOLIA: 11155111,
1415
+ CARDONA: 2442
1416
+ };
1417
+ var DEFAULT_NETWORK = NETWORKS.SEPOLIA;
1418
+
1419
+ // src/native/index.ts
1420
+ var NativeClient = class {
1421
+ constructor(config) {
1422
+ this.config = config;
1423
+ this.defaultNetwork = this.config.defaultNetwork || DEFAULT_NETWORK;
1424
+ if (this.config.chains) {
1425
+ this.config.chains.forEach((chain) => {
1426
+ chainRegistry.registerChain(chain);
1427
+ });
1428
+ }
1429
+ if (this.config.customRpcUrls) {
1430
+ Object.entries(this.config.customRpcUrls).forEach(([chainId, rpcUrl]) => {
1431
+ chainRegistry.addCustomRpcUrl(Number(chainId), rpcUrl);
1432
+ });
1433
+ }
1434
+ }
1435
+ /**
1436
+ * Get network configuration from chain registry
1437
+ * @param networkId - The network ID (chain ID)
1438
+ * @returns Chain configuration
1439
+ */
1440
+ getNetwork(networkId) {
1441
+ return chainRegistry.getChain(networkId);
1442
+ }
1443
+ /**
1444
+ * Get all supported networks
1445
+ * @returns Array of network IDs
1446
+ */
1447
+ getSupportedNetworks() {
1448
+ return chainRegistry.getSupportedChainIds();
1449
+ }
1450
+ /**
1451
+ * Get default network ID
1452
+ * @returns Default network ID
1453
+ */
1454
+ getDefaultNetwork() {
1455
+ return this.defaultNetwork;
1456
+ }
1457
+ /**
1458
+ * Get chain registry for advanced usage
1459
+ */
1460
+ getChainRegistry() {
1461
+ return chainRegistry;
1462
+ }
1463
+ /**
1464
+ * Create an ERC20 instance for a specific token on a specific network
1465
+ * @param tokenAddress - The ERC20 token contract address
1466
+ * @param networkId - The network ID (optional, uses default if not provided)
1467
+ * @returns ERC20 instance
1468
+ */
1469
+ erc20(tokenAddress, networkId) {
1470
+ const network = this.getNetwork(networkId || this.defaultNetwork);
1471
+ return new ERC20({
1472
+ tokenAddress,
1473
+ rpcUrl: network.rpcUrl,
1474
+ chainId: network.chainId
1475
+ });
1476
+ }
1477
+ /**
1478
+ * Get native token balance in wei
1479
+ * @param address - The address to check balance for
1480
+ * @param networkId - The network ID (optional, uses default if not provided)
1481
+ * @returns Native token balance as string
1482
+ */
1483
+ async getNativeBalance(address, networkId) {
1484
+ ValidationUtils.validateAddress(address, "Address");
1485
+ const network = this.getNetwork(networkId || this.defaultNetwork);
1486
+ const client = (0, import_viem6.createPublicClient)({
1487
+ chain: {
1488
+ id: network.chainId,
1489
+ name: network.name,
1490
+ nativeCurrency: network.nativeCurrency,
1491
+ rpcUrls: {
1492
+ default: { http: [network.rpcUrl] },
1493
+ public: { http: [network.rpcUrl] }
1494
+ }
1495
+ },
1496
+ transport: (0, import_viem6.http)(network.rpcUrl)
1497
+ });
1498
+ const balance = await client.getBalance({ address });
1499
+ return balance.toString();
1500
+ }
1501
+ /**
1502
+ * Create a Bridge instance for a specific network
1503
+ * @param bridgeAddress - The bridge contract address
1504
+ * @param networkId - The network ID (optional, uses default if not provided)
1505
+ * @returns Bridge instance
1506
+ */
1507
+ bridge(bridgeAddress, networkId) {
1508
+ const network = this.getNetwork(networkId || this.defaultNetwork);
1509
+ return new Bridge({
1510
+ bridgeAddress,
1511
+ rpcUrl: network.rpcUrl,
1512
+ chainId: network.chainId
1513
+ });
1514
+ }
1515
+ };
1516
+
1517
+ // src/types/config.ts
1518
+ var SDK_MODES = {
1519
+ CORE: "CORE",
1520
+ NATIVE: "NATIVE"
1521
+ };
1522
+
1523
+ // src/core/utils/httpClient.ts
1524
+ var HttpClient = class {
1525
+ constructor(config) {
1526
+ this.config = {
1527
+ timeout: 3e4,
1528
+ retries: 3,
1529
+ retryDelay: 1e3,
1530
+ defaultHeaders: {
1531
+ "Content-Type": "application/json"
1532
+ },
1533
+ ...config
1534
+ };
1535
+ }
1536
+ async request(url, config) {
1537
+ const fullUrl = this.buildUrl(url);
1538
+ const requestConfig = this.buildRequestConfig(config);
1539
+ let lastError;
1540
+ for (let attempt = 0; attempt <= (this.config.retries ?? 3); attempt++) {
1541
+ try {
1542
+ const response = await this.makeRequest(fullUrl, requestConfig);
1543
+ return response;
1544
+ } catch (error) {
1545
+ lastError = error;
1546
+ if (attempt === (this.config.retries ?? 3) || !this.isRetryableError(error)) {
1547
+ break;
1548
+ }
1549
+ if (attempt < (this.config.retries ?? 3)) {
1550
+ await this.delay(
1551
+ (this.config.retryDelay ?? 1e3) * Math.pow(2, attempt)
1552
+ );
1553
+ }
1554
+ }
1555
+ }
1556
+ throw new Error(
1557
+ `Request failed after ${this.config.retries ?? 3} retries: ${lastError?.message ?? "Unknown error"}`
1558
+ );
1559
+ }
1560
+ async get(url, params) {
1561
+ const queryString = params ? this.buildQueryString(params) : "";
1562
+ const fullUrl = queryString ? `${url}?${queryString}` : url;
1563
+ return this.request(fullUrl, { method: "GET" });
1564
+ }
1565
+ async post(url, data, config) {
1566
+ return this.request(url, {
1567
+ method: "POST",
1568
+ body: data,
1569
+ ...config
1570
+ });
1571
+ }
1572
+ buildUrl(url) {
1573
+ if (url.startsWith("http://") || url.startsWith("https://")) {
1574
+ return url;
1575
+ }
1576
+ return `${this.config.baseUrl}${url.startsWith("/") ? url : `/${url}`}`;
1577
+ }
1578
+ buildRequestConfig(config) {
1579
+ const headers = new Headers(this.config.defaultHeaders);
1580
+ if (config.headers) {
1581
+ Object.entries(config.headers).forEach(([key, value]) => {
1582
+ headers.set(key, value);
1583
+ });
1584
+ }
1585
+ const requestConfig = {
1586
+ method: config.method,
1587
+ headers
1588
+ };
1589
+ if (config.body) {
1590
+ if (typeof config.body === "string") {
1591
+ requestConfig.body = config.body;
1592
+ } else {
1593
+ requestConfig.body = JSON.stringify(config.body);
1594
+ }
1595
+ }
1596
+ return requestConfig;
1597
+ }
1598
+ async makeRequest(url, config) {
1599
+ const controller = new AbortController();
1600
+ const timeoutId = setTimeout(() => controller.abort(), this.config.timeout);
1601
+ try {
1602
+ const response = await fetch(url, {
1603
+ ...config,
1604
+ signal: controller.signal
1605
+ });
1606
+ clearTimeout(timeoutId);
1607
+ if (!response.ok) {
1608
+ throw new Error(`HTTP ${response.status}: ${response.statusText}`);
1609
+ }
1610
+ let data;
1611
+ const contentType = response.headers.get("content-type");
1612
+ if (contentType?.includes("application/json")) {
1613
+ data = await response.json();
1614
+ } else {
1615
+ data = await response.text();
1616
+ }
1617
+ return {
1618
+ data,
1619
+ status: response.status,
1620
+ statusText: response.statusText,
1621
+ headers: response.headers,
1622
+ ok: response.ok
1623
+ };
1624
+ } catch (error) {
1625
+ clearTimeout(timeoutId);
1626
+ if (error instanceof Error && error.name === "AbortError") {
1627
+ throw new Error(`Request timeout after ${this.config.timeout}ms`);
1628
+ }
1629
+ throw error;
1630
+ }
1631
+ }
1632
+ buildQueryString(params) {
1633
+ const flattenedParams = this.flattenParams(params);
1634
+ return Object.entries(flattenedParams).filter(([, value]) => value !== void 0 && value !== null).map(
1635
+ ([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(String(value))}`
1636
+ ).join("&");
1637
+ }
1638
+ flattenParams(params, prefix = "") {
1639
+ const result = {};
1640
+ for (const [key, value] of Object.entries(params)) {
1641
+ const fullKey = prefix ? `${prefix}[${key}]` : key;
1642
+ if (value === void 0 || value === null) {
1643
+ continue;
1644
+ }
1645
+ if (Array.isArray(value)) {
1646
+ value.forEach((item, index) => {
1647
+ if (item !== void 0 && item !== null) {
1648
+ result[`${fullKey}[${index}]`] = String(item);
1649
+ }
1650
+ });
1651
+ } else if (typeof value === "object") {
1652
+ Object.assign(
1653
+ result,
1654
+ this.flattenParams(value, fullKey)
1655
+ );
1656
+ } else {
1657
+ result[fullKey] = String(value);
1658
+ }
1659
+ }
1660
+ return result;
1661
+ }
1662
+ isRetryableError(error) {
1663
+ if (error instanceof Error) {
1664
+ const message = error.message.toLowerCase();
1665
+ return message.includes("timeout") || message.includes("network") || message.includes("fetch");
1666
+ }
1667
+ return false;
1668
+ }
1669
+ delay(ms) {
1670
+ return new Promise((resolve) => setTimeout(resolve, ms));
1671
+ }
1672
+ };
1673
+
1674
+ // src/core/services/arcApi.ts
1675
+ var ArcApiService = class {
1676
+ constructor({ baseUrl, timeout }) {
1677
+ this.httpClient = new HttpClient({ baseUrl, timeout });
1678
+ }
1679
+ // responsible for both chains metadata and tokens
1680
+ async chains({
1681
+ withSupportedTokens = false,
1682
+ limit = 20,
1683
+ startAfter = 0,
1684
+ chainIds
1685
+ } = {}) {
1686
+ return this.httpClient.get("/metadata/chains", {
1687
+ withSupportedTokens,
1688
+ limit,
1689
+ startAfter,
1690
+ chainIds
1691
+ });
1692
+ }
1693
+ async routes(routesRequestParams) {
1694
+ return this.httpClient.post("/routes", routesRequestParams);
1695
+ }
1696
+ async buildTransaction(builtTransactionRequestBody) {
1697
+ return this.httpClient.post(
1698
+ "/build-transaction",
1699
+ builtTransactionRequestBody
1700
+ );
1701
+ }
1702
+ async transactions(transactionsRequestQueryParams) {
1703
+ return this.httpClient.get("/transactions", {
1704
+ transactionsRequestQueryParams
1705
+ });
1706
+ }
1707
+ };
1708
+
1709
+ // src/core/index.ts
1710
+ var CoreClient = class {
1711
+ constructor(config) {
1712
+ this.config = config;
1713
+ if (!this.config) {
1714
+ throw new Error("Config is required");
1715
+ }
1716
+ if (!this.config.apiBaseUrl) {
1717
+ throw new Error("API base URL is required");
1718
+ }
1719
+ const { apiBaseUrl, apiTimeout } = this.config;
1720
+ this.arcApiService = new ArcApiService({
1721
+ baseUrl: apiBaseUrl,
1722
+ timeout: apiTimeout ?? 3e4
1723
+ });
1724
+ }
1725
+ /**
1726
+ * Get all chains metadata from AggLayer API
1727
+ */
1728
+ async getAllChains() {
1729
+ const response = await this.arcApiService.chains();
1730
+ if (response.data.status === "success") {
1731
+ return response.data.data;
1732
+ }
1733
+ throw new Error(response.data.message);
1734
+ }
1735
+ /**
1736
+ * Get chain metadata by id from AggLayer API
1737
+ * @param ids - the ids of the chains to get metadata for
1738
+ */
1739
+ async getChainMetadataByChainIds(ids) {
1740
+ const response = await this.arcApiService.chains({ chainIds: ids });
1741
+ if (response.data.status === "success") {
1742
+ return response.data.data;
1743
+ }
1744
+ throw new Error(response.data.message);
1745
+ }
1746
+ /**
1747
+ * Get all tokens from AggLayer API
1748
+ */
1749
+ async getTokens() {
1750
+ const response = await this.arcApiService.chains({
1751
+ withSupportedTokens: true
1752
+ });
1753
+ if (response.data.status === "success") {
1754
+ return response.data.data;
1755
+ }
1756
+ throw new Error(response.data.message);
1757
+ }
1758
+ /**
1759
+ * Get chain data and tokens by AggLayer API
1760
+ * @param ids - the ids of the chains to get data and tokens for
1761
+ */
1762
+ async getChainDataAndTokensByChainIds(ids) {
1763
+ const response = await this.arcApiService.chains({
1764
+ chainIds: ids,
1765
+ withSupportedTokens: true
1766
+ });
1767
+ if (response.data.status === "success") {
1768
+ return response.data.data;
1769
+ }
1770
+ throw new Error(response.data.message);
1771
+ }
1772
+ /**
1773
+ * Get all routes from AggLayer API
1774
+ */
1775
+ async getRoutes(routesRequestParams) {
1776
+ const response = await this.arcApiService.routes(routesRequestParams);
1777
+ if (response.data.status === "success") {
1778
+ return response.data.data;
1779
+ }
1780
+ throw new Error(response.data.message);
1781
+ }
1782
+ /**
1783
+ * Build transaction from a step object
1784
+ */
1785
+ async buildTransaction(builtTransactionRequestBody) {
1786
+ const response = await this.arcApiService.buildTransaction(
1787
+ builtTransactionRequestBody
1788
+ );
1789
+ if (response.data.status === "success") {
1790
+ return response.data.data;
1791
+ }
1792
+ throw new Error(response.data.message);
1793
+ }
1794
+ /**
1795
+ * Get all transactions via web sockets
1796
+ */
1797
+ async getTransactions(transactionsRequestQueryParams) {
1798
+ const response = await this.arcApiService.transactions(
1799
+ transactionsRequestQueryParams
1800
+ );
1801
+ if (response.data.status === "success") {
1802
+ return response.data.data;
1803
+ }
1804
+ throw new Error(response.data.message);
1805
+ }
1806
+ };
1807
+
1808
+ // src/index.ts
1809
+ var AggLayerSDK = class {
1810
+ constructor(config) {
1811
+ this.config = config;
1812
+ if (!config.mode || config.mode && config.mode.length === 0) {
1813
+ this.config.mode = ["CORE"];
1814
+ }
1815
+ if (config.mode.includes(SDK_MODES.CORE)) {
1816
+ if (!this.config.core) {
1817
+ throw new Error("Core config is required");
1818
+ }
1819
+ this.core = new CoreClient(this.config.core);
1820
+ }
1821
+ if (this.config.mode?.includes(SDK_MODES.NATIVE)) {
1822
+ if (!this.config.native) {
1823
+ throw new Error("NATIVE config is required");
1824
+ }
1825
+ const nativeConfig = {
1826
+ defaultNetwork: this.config.native?.defaultNetwork || DEFAULT_NETWORK,
1827
+ ...this.config.native?.chains && {
1828
+ chains: this.config.native.chains
1829
+ },
1830
+ ...this.config.native?.customRpcUrls && {
1831
+ customRpcUrls: this.config.native.customRpcUrls
1832
+ }
1833
+ };
1834
+ this.native = new NativeClient(nativeConfig);
1835
+ }
1836
+ }
1837
+ /**
1838
+ * Get core submodule
1839
+ */
1840
+ getCore() {
1841
+ if (!this.core) {
1842
+ throw new Error('Core module not initialized. Add "core" to mode array.');
1843
+ }
1844
+ return this.core;
1845
+ }
1846
+ /**
1847
+ * Get native submodule
1848
+ */
1849
+ getNative() {
1850
+ if (!this.native) {
1851
+ throw new Error(
1852
+ 'NATIVE module not initialized. Add "native" to mode array.'
1853
+ );
1854
+ }
1855
+ return this.native;
1856
+ }
1857
+ };
1858
+ // Annotate the CommonJS export names for ESM import in node:
1859
+ 0 && (module.exports = {
1860
+ AggLayerSDK,
1861
+ SDK_MODES
1862
+ });
1863
+ //# sourceMappingURL=index.js.map