@usewhisk/cctp 0.0.0 → 0.1.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/index.cjs ADDED
@@ -0,0 +1,4018 @@
1
+ 'use strict';
2
+
3
+ var stellarSdk = require('@stellar/stellar-sdk');
4
+ var starknet = require('starknet');
5
+ var viem = require('viem');
6
+ var web3_js = require('@solana/web3.js');
7
+ var sha256 = require('@noble/hashes/sha256');
8
+ var splToken = require('@solana/spl-token');
9
+ var buffer = require('buffer');
10
+
11
+ // src/errors.ts
12
+ var CctpError = class extends Error {
13
+ code;
14
+ cause;
15
+ constructor(code, message, cause) {
16
+ super(message);
17
+ this.name = "CctpError";
18
+ this.code = code;
19
+ if (cause !== void 0) this.cause = cause;
20
+ }
21
+ };
22
+ var InvalidInputError = class extends CctpError {
23
+ constructor(code, message, cause) {
24
+ super(code, message, cause);
25
+ this.name = "InvalidInputError";
26
+ }
27
+ };
28
+ var IrisError = class extends CctpError {
29
+ constructor(code, message, cause) {
30
+ super(code, message, cause);
31
+ this.name = "IrisError";
32
+ }
33
+ };
34
+ var IrisHttpError = class extends IrisError {
35
+ status;
36
+ bodySnippet;
37
+ url;
38
+ constructor(status, url, bodySnippet) {
39
+ super(
40
+ "iris_http",
41
+ `Iris ${status} on ${url}: ${bodySnippet.slice(0, 200)}`
42
+ );
43
+ this.name = "IrisHttpError";
44
+ this.status = status;
45
+ this.url = url;
46
+ this.bodySnippet = bodySnippet;
47
+ }
48
+ };
49
+ var IrisRateLimitedError = class extends IrisError {
50
+ retryAt;
51
+ host;
52
+ constructor(host, retryAt) {
53
+ super(
54
+ "iris_rate_limited",
55
+ `Iris rate limit reached on ${host}; requests resume at ${new Date(retryAt).toISOString()}`
56
+ );
57
+ this.name = "IrisRateLimitedError";
58
+ this.host = host;
59
+ this.retryAt = retryAt;
60
+ }
61
+ };
62
+ var IrisNetworkError = class extends IrisError {
63
+ constructor(message, cause) {
64
+ super("iris_network", message, cause);
65
+ this.name = "IrisNetworkError";
66
+ }
67
+ };
68
+ var IrisParseError = class extends IrisError {
69
+ constructor(message, cause) {
70
+ super("iris_parse", message, cause);
71
+ this.name = "IrisParseError";
72
+ }
73
+ };
74
+ var IrisAbortedError = class extends IrisError {
75
+ constructor(message) {
76
+ super("iris_aborted", message);
77
+ this.name = "IrisAbortedError";
78
+ }
79
+ };
80
+ var ProtocolError = class extends CctpError {
81
+ constructor(code, message, cause) {
82
+ super(code, message, cause);
83
+ this.name = "ProtocolError";
84
+ }
85
+ };
86
+ var UnsupportedError = class extends CctpError {
87
+ constructor(code, message) {
88
+ super(code, message);
89
+ this.name = "UnsupportedError";
90
+ }
91
+ };
92
+ function isCctpError(value) {
93
+ return value instanceof CctpError;
94
+ }
95
+
96
+ // src/chains/constants.ts
97
+ var TOKEN_MESSENGER_V2_EVM_MAINNET = "0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d";
98
+ var MESSAGE_TRANSMITTER_V2_EVM_MAINNET = "0x81D40F21F12A8F0E3252Bccb954D722d4c464B64";
99
+ var TOKEN_MESSENGER_V2_EVM_TESTNET = "0x8FE6B999Dc680CcFDD5Bf7EB0974218be2542DAA";
100
+ var MESSAGE_TRANSMITTER_V2_EVM_TESTNET = "0xE737e5cEBEEBa77EFE34D4aa090756590b1CE275";
101
+ var TOKEN_MESSENGER_WITH_FEES_EVM_MAINNET = "0x71f54F818671cD0D7ea140Da213e5C8b5C92a408";
102
+ var TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET = "0x8745D906D67C346E5eb1aEEED38Eb87F34DF0C0A";
103
+ var TOKEN_MESSENGER_MINTER_V2_SOLANA = "CCTPV2vPZJS2u2BBsUoscuikbYjnpFmbFsvVuJdgUMQe";
104
+ var MESSAGE_TRANSMITTER_V2_SOLANA = "CCTPV2Sm4AdWt5296sk4P66VBZ7bEhcARwFaaS9YPbeC";
105
+ var USDC_SPL_MAINNET = "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v";
106
+ var USDC_SPL_DEVNET = "4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU";
107
+ var SOLANA_CCTP_DOMAIN = 5;
108
+ var TOKEN_MESSENGER_MINTER_STELLAR_MAINNET = "CAE2G5Z77UP7GYPYGFOWFGW7C7J6I4YP2AFGSADRKQY62SYUFLPNFTXL";
109
+ var MESSAGE_TRANSMITTER_STELLAR_MAINNET = "CACMENFFJPJMSDAJQLX4R7K3SFZIW2LJSE3R2UMLGSWHFHS353FVXAZV";
110
+ var CCTP_FORWARDER_STELLAR_MAINNET = "CBZL2IH7F6BIDAA3WBNXYKIXSATJGMSW7K5P5MJ6STX5RXN47TZJDF5T";
111
+ var TOKEN_MESSENGER_MINTER_STELLAR_TESTNET = "CDNG7HXAPBWICI2E3AUBP3YZWZELJLYSB6F5CC7WLDTLTHVM74SLRTHP";
112
+ var MESSAGE_TRANSMITTER_STELLAR_TESTNET = "CBJ6MTCKKZG73PMDZCJMSFRD7DQEMI4FKDH7CGDSV4W6FHCRBCQAVVJY";
113
+ var CCTP_FORWARDER_STELLAR_TESTNET = "CA66Q2WFBND6V4UEB7RD4SAXSVIWMD6RA4X3U32ELVFGXV5PJK4T4VSZ";
114
+ var USDC_ISSUER_STELLAR_MAINNET = "GA5ZSEJYB37JRC5AVCIA5MOP4RHTM335X2KGX3IHOJAPP5RE34K4KZVN";
115
+ var USDC_ISSUER_STELLAR_TESTNET = "GBBD47IF6LWK7P7MDEVSCWR7DPUWV3NY3DTQEVFL4NAT4AQH3ZLLFLA5";
116
+ var STELLAR_NETWORK_PASSPHRASE_MAINNET = "Public Global Stellar Network ; September 2015";
117
+ var STELLAR_NETWORK_PASSPHRASE_TESTNET = "Test SDF Network ; September 2015";
118
+ var STELLAR_CCTP_DOMAIN = 27;
119
+ var STELLAR_USDC_DECIMALS = 7;
120
+ var CCTP_USDC_DECIMALS = 6;
121
+ var TOKEN_MESSENGER_MINTER_V2_STARKNET_MAINNET = "0x07d421B9cA8aA32DF259965cDA8ACb93F7599F69209A41872AE84638B2A20F2a";
122
+ var MESSAGE_TRANSMITTER_V2_STARKNET_MAINNET = "0x02EBB5777B6dD8B26ea11D68Fdf1D2c85cD2099335328Be845a28c77A8AEf183";
123
+ var TOKEN_MESSENGER_MINTER_V2_STARKNET_SEPOLIA = "0x04bDdE1E09a4B09a2F95d893D94a967b7717eB85A3f6dEcA8c080Ee01fBc3370";
124
+ var MESSAGE_TRANSMITTER_V2_STARKNET_SEPOLIA = "0x04db7926C64f1f32a840F3Fa95cB551f3801a3600Bae87aF87807A54DCE12Fe8";
125
+ var USDC_STARKNET_MAINNET = "0x033068F6539f8e6e6b131e6B2B814e6c34A5224bC66947c47DaB9dFeE93b35fb";
126
+ var USDC_STARKNET_SEPOLIA = "0x0512feAc6339Ff7889822cb5aA2a86C848e9D392bB0E3E237C008674feeD8343";
127
+ var STARKNET_CHAIN_ID_MAINNET = "0x534e5f4d41494e";
128
+ var STARKNET_CHAIN_ID_SEPOLIA = "0x534e5f5345504f4c4941";
129
+ var STARKNET_CCTP_DOMAIN = 25;
130
+
131
+ // src/chains/mainnet.ts
132
+ var Ethereum = {
133
+ id: "Ethereum",
134
+ label: "Ethereum",
135
+ ecosystem: "evm",
136
+ network: "mainnet",
137
+ evmChainId: 1,
138
+ cctpDomain: 0,
139
+ usdc: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
140
+ usdcDecimals: 6,
141
+ tokenMessenger: TOKEN_MESSENGER_V2_EVM_MAINNET,
142
+ messageTransmitter: MESSAGE_TRANSMITTER_V2_EVM_MAINNET,
143
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_MAINNET,
144
+ nativeCurrency: { symbol: "ETH", decimals: 18 },
145
+ defaultRpcUrls: [
146
+ "https://ethereum-rpc.publicnode.com",
147
+ "https://ethereum.publicnode.com"
148
+ ],
149
+ explorerUrl: "https://etherscan.io",
150
+ capabilities: {
151
+ fastSource: true,
152
+ forwardingDestination: true,
153
+ upfrontFeeSource: true,
154
+ standardFeeSwitch: false
155
+ }
156
+ };
157
+ var Avalanche = {
158
+ id: "Avalanche",
159
+ label: "Avalanche",
160
+ ecosystem: "evm",
161
+ network: "mainnet",
162
+ evmChainId: 43114,
163
+ cctpDomain: 1,
164
+ usdc: "0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E",
165
+ usdcDecimals: 6,
166
+ tokenMessenger: TOKEN_MESSENGER_V2_EVM_MAINNET,
167
+ messageTransmitter: MESSAGE_TRANSMITTER_V2_EVM_MAINNET,
168
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_MAINNET,
169
+ nativeCurrency: { symbol: "AVAX", decimals: 18 },
170
+ defaultRpcUrls: ["https://api.avax.network/ext/bc/C/rpc"],
171
+ explorerUrl: "https://explorer.avax.network/c-chain",
172
+ capabilities: {
173
+ fastSource: false,
174
+ forwardingDestination: true,
175
+ upfrontFeeSource: true,
176
+ standardFeeSwitch: false
177
+ }
178
+ };
179
+ var Optimism = {
180
+ id: "Optimism",
181
+ label: "OP Mainnet",
182
+ ecosystem: "evm",
183
+ network: "mainnet",
184
+ evmChainId: 10,
185
+ cctpDomain: 2,
186
+ usdc: "0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85",
187
+ usdcDecimals: 6,
188
+ tokenMessenger: TOKEN_MESSENGER_V2_EVM_MAINNET,
189
+ messageTransmitter: MESSAGE_TRANSMITTER_V2_EVM_MAINNET,
190
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_MAINNET,
191
+ nativeCurrency: { symbol: "ETH", decimals: 18 },
192
+ defaultRpcUrls: ["https://mainnet.optimism.io"],
193
+ explorerUrl: "https://explorer.optimism.io",
194
+ capabilities: {
195
+ fastSource: true,
196
+ forwardingDestination: true,
197
+ upfrontFeeSource: true,
198
+ standardFeeSwitch: false
199
+ }
200
+ };
201
+ var Arbitrum = {
202
+ id: "Arbitrum",
203
+ label: "Arbitrum",
204
+ ecosystem: "evm",
205
+ network: "mainnet",
206
+ evmChainId: 42161,
207
+ cctpDomain: 3,
208
+ usdc: "0xaf88d065e77c8cC2239327C5EDb3A432268e5831",
209
+ usdcDecimals: 6,
210
+ tokenMessenger: TOKEN_MESSENGER_V2_EVM_MAINNET,
211
+ messageTransmitter: MESSAGE_TRANSMITTER_V2_EVM_MAINNET,
212
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_MAINNET,
213
+ nativeCurrency: { symbol: "ETH", decimals: 18 },
214
+ defaultRpcUrls: ["https://arb1.arbitrum.io/rpc"],
215
+ explorerUrl: "https://arbiscan.io",
216
+ capabilities: {
217
+ fastSource: true,
218
+ forwardingDestination: true,
219
+ upfrontFeeSource: true,
220
+ standardFeeSwitch: false
221
+ }
222
+ };
223
+ var Base = {
224
+ id: "Base",
225
+ label: "Base",
226
+ ecosystem: "evm",
227
+ network: "mainnet",
228
+ evmChainId: 8453,
229
+ cctpDomain: 6,
230
+ usdc: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
231
+ usdcDecimals: 6,
232
+ tokenMessenger: TOKEN_MESSENGER_V2_EVM_MAINNET,
233
+ messageTransmitter: MESSAGE_TRANSMITTER_V2_EVM_MAINNET,
234
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_MAINNET,
235
+ nativeCurrency: { symbol: "ETH", decimals: 18 },
236
+ defaultRpcUrls: ["https://mainnet.base.org"],
237
+ explorerUrl: "https://basescan.org",
238
+ capabilities: {
239
+ fastSource: true,
240
+ forwardingDestination: true,
241
+ upfrontFeeSource: true,
242
+ standardFeeSwitch: false
243
+ }
244
+ };
245
+ var Polygon = {
246
+ id: "Polygon",
247
+ label: "Polygon PoS",
248
+ ecosystem: "evm",
249
+ network: "mainnet",
250
+ evmChainId: 137,
251
+ cctpDomain: 7,
252
+ usdc: "0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359",
253
+ usdcDecimals: 6,
254
+ tokenMessenger: TOKEN_MESSENGER_V2_EVM_MAINNET,
255
+ messageTransmitter: MESSAGE_TRANSMITTER_V2_EVM_MAINNET,
256
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_MAINNET,
257
+ nativeCurrency: { symbol: "POL", decimals: 18 },
258
+ defaultRpcUrls: [
259
+ "https://polygon.drpc.org",
260
+ "https://polygon.publicnode.com"
261
+ ],
262
+ explorerUrl: "https://polygonscan.com",
263
+ capabilities: {
264
+ fastSource: false,
265
+ forwardingDestination: true,
266
+ upfrontFeeSource: true,
267
+ standardFeeSwitch: false
268
+ }
269
+ };
270
+ var Unichain = {
271
+ id: "Unichain",
272
+ label: "Unichain",
273
+ ecosystem: "evm",
274
+ network: "mainnet",
275
+ evmChainId: 130,
276
+ cctpDomain: 10,
277
+ usdc: "0x078D782b760474a361dDA0AF3839290b0EF57AD6",
278
+ usdcDecimals: 6,
279
+ tokenMessenger: TOKEN_MESSENGER_V2_EVM_MAINNET,
280
+ messageTransmitter: MESSAGE_TRANSMITTER_V2_EVM_MAINNET,
281
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_MAINNET,
282
+ nativeCurrency: { symbol: "ETH", decimals: 18 },
283
+ defaultRpcUrls: ["https://mainnet.unichain.org"],
284
+ explorerUrl: "https://uniscan.xyz",
285
+ capabilities: {
286
+ fastSource: true,
287
+ forwardingDestination: true,
288
+ upfrontFeeSource: true,
289
+ standardFeeSwitch: false
290
+ }
291
+ };
292
+ var Linea = {
293
+ id: "Linea",
294
+ label: "Linea",
295
+ ecosystem: "evm",
296
+ network: "mainnet",
297
+ evmChainId: 59144,
298
+ cctpDomain: 11,
299
+ usdc: "0x176211869cA2b568f2A7D4EE941E073a821EE1ff",
300
+ usdcDecimals: 6,
301
+ tokenMessenger: TOKEN_MESSENGER_V2_EVM_MAINNET,
302
+ messageTransmitter: MESSAGE_TRANSMITTER_V2_EVM_MAINNET,
303
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_MAINNET,
304
+ nativeCurrency: { symbol: "ETH", decimals: 18 },
305
+ defaultRpcUrls: ["https://rpc.linea.build"],
306
+ explorerUrl: "https://lineascan.build",
307
+ capabilities: {
308
+ fastSource: true,
309
+ forwardingDestination: true,
310
+ upfrontFeeSource: true,
311
+ standardFeeSwitch: false
312
+ }
313
+ };
314
+ var Codex = {
315
+ id: "Codex",
316
+ label: "Codex",
317
+ ecosystem: "evm",
318
+ network: "mainnet",
319
+ evmChainId: 81224,
320
+ cctpDomain: 12,
321
+ usdc: "0xd996633a415985DBd7D6D12f4A4343E31f5037cf",
322
+ usdcDecimals: 6,
323
+ tokenMessenger: TOKEN_MESSENGER_V2_EVM_MAINNET,
324
+ messageTransmitter: MESSAGE_TRANSMITTER_V2_EVM_MAINNET,
325
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_MAINNET,
326
+ nativeCurrency: { symbol: "ETH", decimals: 18 },
327
+ defaultRpcUrls: ["https://rpc.codex.xyz"],
328
+ explorerUrl: "https://explorer.codex.xyz",
329
+ capabilities: {
330
+ fastSource: true,
331
+ forwardingDestination: true,
332
+ upfrontFeeSource: true,
333
+ standardFeeSwitch: false
334
+ }
335
+ };
336
+ var Sonic = {
337
+ id: "Sonic",
338
+ label: "Sonic",
339
+ ecosystem: "evm",
340
+ network: "mainnet",
341
+ evmChainId: 146,
342
+ cctpDomain: 13,
343
+ usdc: "0x29219dd400f2Bf60E5a23d13Be72B486D4038894",
344
+ usdcDecimals: 6,
345
+ tokenMessenger: TOKEN_MESSENGER_V2_EVM_MAINNET,
346
+ messageTransmitter: MESSAGE_TRANSMITTER_V2_EVM_MAINNET,
347
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_MAINNET,
348
+ nativeCurrency: { symbol: "S", decimals: 18 },
349
+ defaultRpcUrls: ["https://rpc.soniclabs.com"],
350
+ explorerUrl: "https://sonicscan.org",
351
+ capabilities: {
352
+ fastSource: false,
353
+ forwardingDestination: true,
354
+ upfrontFeeSource: true,
355
+ standardFeeSwitch: false
356
+ }
357
+ };
358
+ var WorldChain = {
359
+ id: "World_Chain",
360
+ label: "World Chain",
361
+ ecosystem: "evm",
362
+ network: "mainnet",
363
+ evmChainId: 480,
364
+ cctpDomain: 14,
365
+ usdc: "0x79A02482A880bCE3F13e09Da970dC34db4CD24d1",
366
+ usdcDecimals: 6,
367
+ tokenMessenger: TOKEN_MESSENGER_V2_EVM_MAINNET,
368
+ messageTransmitter: MESSAGE_TRANSMITTER_V2_EVM_MAINNET,
369
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_MAINNET,
370
+ nativeCurrency: { symbol: "ETH", decimals: 18 },
371
+ defaultRpcUrls: ["https://worldchain-mainnet.g.alchemy.com/public"],
372
+ explorerUrl: "https://worldscan.org",
373
+ capabilities: {
374
+ fastSource: true,
375
+ forwardingDestination: true,
376
+ upfrontFeeSource: true,
377
+ standardFeeSwitch: false
378
+ }
379
+ };
380
+ var Monad = {
381
+ id: "Monad",
382
+ label: "Monad",
383
+ ecosystem: "evm",
384
+ network: "mainnet",
385
+ evmChainId: 143,
386
+ cctpDomain: 15,
387
+ usdc: "0x754704Bc059F8C67012fEd69BC8A327a5aafb603",
388
+ usdcDecimals: 6,
389
+ tokenMessenger: TOKEN_MESSENGER_V2_EVM_MAINNET,
390
+ messageTransmitter: MESSAGE_TRANSMITTER_V2_EVM_MAINNET,
391
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_MAINNET,
392
+ nativeCurrency: { symbol: "MON", decimals: 18 },
393
+ defaultRpcUrls: ["https://rpc.monad.xyz", "https://rpc1.monad.xyz"],
394
+ explorerUrl: "https://monadvision.com",
395
+ capabilities: {
396
+ fastSource: false,
397
+ forwardingDestination: true,
398
+ upfrontFeeSource: true,
399
+ standardFeeSwitch: true
400
+ }
401
+ };
402
+ var Sei = {
403
+ id: "Sei",
404
+ label: "Sei",
405
+ ecosystem: "evm",
406
+ network: "mainnet",
407
+ evmChainId: 1329,
408
+ cctpDomain: 16,
409
+ usdc: "0xe15fC38F6D8c56aF07bbCBe3BAf5708A2Bf42392",
410
+ usdcDecimals: 6,
411
+ tokenMessenger: TOKEN_MESSENGER_V2_EVM_MAINNET,
412
+ messageTransmitter: MESSAGE_TRANSMITTER_V2_EVM_MAINNET,
413
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_MAINNET,
414
+ nativeCurrency: { symbol: "SEI", decimals: 18 },
415
+ defaultRpcUrls: ["https://evm-rpc.sei-apis.com"],
416
+ explorerUrl: "https://seiscan.io",
417
+ capabilities: {
418
+ fastSource: false,
419
+ forwardingDestination: true,
420
+ upfrontFeeSource: true,
421
+ standardFeeSwitch: true
422
+ }
423
+ };
424
+ var XDC = {
425
+ id: "XDC",
426
+ label: "XDC",
427
+ ecosystem: "evm",
428
+ network: "mainnet",
429
+ evmChainId: 50,
430
+ cctpDomain: 18,
431
+ usdc: "0xfA2958CB79b0491CC627c1557F441eF849Ca8eb1",
432
+ usdcDecimals: 6,
433
+ tokenMessenger: TOKEN_MESSENGER_V2_EVM_MAINNET,
434
+ messageTransmitter: MESSAGE_TRANSMITTER_V2_EVM_MAINNET,
435
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_MAINNET,
436
+ nativeCurrency: { symbol: "XDC", decimals: 18 },
437
+ defaultRpcUrls: ["https://erpc.xinfin.network", "https://rpc.xinfin.network"],
438
+ explorerUrl: "https://xdcscan.io",
439
+ capabilities: {
440
+ fastSource: false,
441
+ forwardingDestination: true,
442
+ upfrontFeeSource: true,
443
+ standardFeeSwitch: true
444
+ }
445
+ };
446
+ var HyperEVM = {
447
+ id: "HyperEVM",
448
+ label: "HyperEVM",
449
+ ecosystem: "evm",
450
+ network: "mainnet",
451
+ evmChainId: 999,
452
+ cctpDomain: 19,
453
+ usdc: "0xb88339CB7199b77E23DB6E890353E22632Ba630f",
454
+ usdcDecimals: 6,
455
+ tokenMessenger: TOKEN_MESSENGER_V2_EVM_MAINNET,
456
+ messageTransmitter: MESSAGE_TRANSMITTER_V2_EVM_MAINNET,
457
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_MAINNET,
458
+ nativeCurrency: { symbol: "HYPE", decimals: 18 },
459
+ defaultRpcUrls: ["https://rpc.hyperliquid.xyz/evm"],
460
+ explorerUrl: "https://hyperevmscan.io",
461
+ capabilities: {
462
+ fastSource: false,
463
+ forwardingDestination: true,
464
+ upfrontFeeSource: true,
465
+ standardFeeSwitch: true
466
+ }
467
+ };
468
+ var Ink = {
469
+ id: "Ink",
470
+ label: "Ink",
471
+ ecosystem: "evm",
472
+ network: "mainnet",
473
+ evmChainId: 57073,
474
+ cctpDomain: 21,
475
+ usdc: "0x2D270e6886d130D724215A266106e6832161EAEd",
476
+ usdcDecimals: 6,
477
+ tokenMessenger: TOKEN_MESSENGER_V2_EVM_MAINNET,
478
+ messageTransmitter: MESSAGE_TRANSMITTER_V2_EVM_MAINNET,
479
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_MAINNET,
480
+ nativeCurrency: { symbol: "ETH", decimals: 18 },
481
+ defaultRpcUrls: [
482
+ "https://rpc-gel.inkonchain.com",
483
+ "https://rpc-qnd.inkonchain.com"
484
+ ],
485
+ explorerUrl: "https://explorer.inkonchain.com",
486
+ capabilities: {
487
+ fastSource: true,
488
+ forwardingDestination: true,
489
+ upfrontFeeSource: true,
490
+ standardFeeSwitch: true
491
+ }
492
+ };
493
+ var Plume = {
494
+ id: "Plume",
495
+ label: "Plume",
496
+ ecosystem: "evm",
497
+ network: "mainnet",
498
+ evmChainId: 98866,
499
+ cctpDomain: 22,
500
+ usdc: "0x222365EF19F7947e5484218551B56bb3965Aa7aF",
501
+ usdcDecimals: 6,
502
+ tokenMessenger: TOKEN_MESSENGER_V2_EVM_MAINNET,
503
+ messageTransmitter: MESSAGE_TRANSMITTER_V2_EVM_MAINNET,
504
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_MAINNET,
505
+ nativeCurrency: { symbol: "PLUME", decimals: 18 },
506
+ defaultRpcUrls: ["https://rpc.plume.org"],
507
+ explorerUrl: "https://explorer.plume.org",
508
+ capabilities: {
509
+ fastSource: true,
510
+ forwardingDestination: true,
511
+ upfrontFeeSource: true,
512
+ standardFeeSwitch: true
513
+ }
514
+ };
515
+ var Arc = {
516
+ id: "Arc",
517
+ label: "Arc",
518
+ ecosystem: "evm",
519
+ network: "mainnet",
520
+ evmChainId: 5042,
521
+ cctpDomain: 26,
522
+ usdc: "0x3600000000000000000000000000000000000000",
523
+ usdcDecimals: 6,
524
+ tokenMessenger: TOKEN_MESSENGER_V2_EVM_MAINNET,
525
+ messageTransmitter: MESSAGE_TRANSMITTER_V2_EVM_MAINNET,
526
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_MAINNET,
527
+ nativeCurrency: { symbol: "USDC", decimals: 18 },
528
+ defaultRpcUrls: ["https://rpc.mainnet.arc.io"],
529
+ explorerUrl: "https://explorer.arc.io",
530
+ capabilities: {
531
+ fastSource: false,
532
+ forwardingDestination: true,
533
+ upfrontFeeSource: true,
534
+ standardFeeSwitch: true
535
+ }
536
+ };
537
+ var Edge = {
538
+ id: "Edge",
539
+ label: "EDGE",
540
+ ecosystem: "evm",
541
+ network: "mainnet",
542
+ evmChainId: 3343,
543
+ cctpDomain: 28,
544
+ usdc: "0x98d2919b9A214E6Fa5384AC81E6864bA686Ad74c",
545
+ usdcDecimals: 6,
546
+ tokenMessenger: "0x98706A006bc632Df31CAdFCBD43F38887ce2ca5c",
547
+ messageTransmitter: "0x5b61381Fc9e58E70EfC13a4A97516997019198ee",
548
+ nativeCurrency: { symbol: "ETH", decimals: 18 },
549
+ defaultRpcUrls: ["https://edge-mainnet.g.alchemy.com/public"],
550
+ explorerUrl: "https://pro.edgex.exchange/en-US/explorer",
551
+ capabilities: {
552
+ fastSource: true,
553
+ forwardingDestination: true,
554
+ upfrontFeeSource: false,
555
+ standardFeeSwitch: true
556
+ }
557
+ };
558
+ var Injective = {
559
+ id: "Injective",
560
+ label: "Injective",
561
+ ecosystem: "evm",
562
+ network: "mainnet",
563
+ evmChainId: 1776,
564
+ cctpDomain: 29,
565
+ usdc: "0xa00C59fF5a080D2b954d0c75e46E22a0c371235a",
566
+ usdcDecimals: 6,
567
+ tokenMessenger: TOKEN_MESSENGER_V2_EVM_MAINNET,
568
+ messageTransmitter: MESSAGE_TRANSMITTER_V2_EVM_MAINNET,
569
+ nativeCurrency: { symbol: "INJ", decimals: 18 },
570
+ defaultRpcUrls: [
571
+ "https://sentry.evm-rpc.injective.network",
572
+ "https://evm.archival.chain.virtual.json-rpc.injective.network"
573
+ ],
574
+ explorerUrl: "https://blockscout.injective.network",
575
+ capabilities: {
576
+ fastSource: false,
577
+ forwardingDestination: false,
578
+ upfrontFeeSource: false,
579
+ standardFeeSwitch: true
580
+ }
581
+ };
582
+ var Morph = {
583
+ id: "Morph",
584
+ label: "Morph",
585
+ ecosystem: "evm",
586
+ network: "mainnet",
587
+ evmChainId: 2818,
588
+ cctpDomain: 30,
589
+ usdc: "0xCfb1186F4e93D60E60a8bDd997427D1F33bc372B",
590
+ usdcDecimals: 6,
591
+ tokenMessenger: TOKEN_MESSENGER_V2_EVM_MAINNET,
592
+ messageTransmitter: MESSAGE_TRANSMITTER_V2_EVM_MAINNET,
593
+ nativeCurrency: { symbol: "ETH", decimals: 18 },
594
+ defaultRpcUrls: ["https://rpc-bgw.morph.network"],
595
+ explorerUrl: "https://explorer.morph.network",
596
+ capabilities: {
597
+ fastSource: true,
598
+ forwardingDestination: false,
599
+ upfrontFeeSource: false,
600
+ standardFeeSwitch: true
601
+ }
602
+ };
603
+ var Pharos = {
604
+ id: "Pharos",
605
+ label: "Pharos",
606
+ ecosystem: "evm",
607
+ network: "mainnet",
608
+ evmChainId: 1672,
609
+ cctpDomain: 31,
610
+ usdc: "0xC879C018dB60520F4355C26eD1a6D572cdAC1815",
611
+ usdcDecimals: 6,
612
+ tokenMessenger: TOKEN_MESSENGER_V2_EVM_MAINNET,
613
+ messageTransmitter: MESSAGE_TRANSMITTER_V2_EVM_MAINNET,
614
+ nativeCurrency: { symbol: "PROS", decimals: 18 },
615
+ defaultRpcUrls: ["https://rpc.pharos.xyz"],
616
+ explorerUrl: "https://www.pharosscan.xyz",
617
+ capabilities: {
618
+ fastSource: false,
619
+ forwardingDestination: false,
620
+ upfrontFeeSource: false,
621
+ standardFeeSwitch: true
622
+ }
623
+ };
624
+ var Cronos = {
625
+ id: "Cronos",
626
+ label: "Cronos",
627
+ ecosystem: "evm",
628
+ network: "mainnet",
629
+ evmChainId: 25,
630
+ cctpDomain: 32,
631
+ usdc: "0x3D7F2C478aAfdB65542BCB44bCeeC05849999d2D",
632
+ usdcDecimals: 6,
633
+ tokenMessenger: TOKEN_MESSENGER_V2_EVM_MAINNET,
634
+ messageTransmitter: MESSAGE_TRANSMITTER_V2_EVM_MAINNET,
635
+ nativeCurrency: { symbol: "CRO", decimals: 18 },
636
+ defaultRpcUrls: ["https://evm.cronos.com"],
637
+ explorerUrl: "https://explorer.cronos.com",
638
+ capabilities: {
639
+ fastSource: false,
640
+ forwardingDestination: false,
641
+ upfrontFeeSource: false,
642
+ standardFeeSwitch: true
643
+ }
644
+ };
645
+ var Plasma = {
646
+ id: "Plasma",
647
+ label: "Plasma",
648
+ ecosystem: "evm",
649
+ network: "mainnet",
650
+ evmChainId: 9745,
651
+ cctpDomain: 33,
652
+ usdc: "0x2d661C89D812261039AF9764eceaAee884f5F67F",
653
+ usdcDecimals: 6,
654
+ tokenMessenger: TOKEN_MESSENGER_V2_EVM_MAINNET,
655
+ messageTransmitter: MESSAGE_TRANSMITTER_V2_EVM_MAINNET,
656
+ nativeCurrency: { symbol: "XPL", decimals: 18 },
657
+ defaultRpcUrls: ["https://rpc.plasma.to"],
658
+ explorerUrl: "https://plasmascan.to",
659
+ capabilities: {
660
+ fastSource: false,
661
+ forwardingDestination: false,
662
+ upfrontFeeSource: false,
663
+ standardFeeSwitch: true
664
+ }
665
+ };
666
+ var XLayer = {
667
+ id: "X_Layer",
668
+ label: "X Layer",
669
+ ecosystem: "evm",
670
+ network: "mainnet",
671
+ evmChainId: 196,
672
+ cctpDomain: 37,
673
+ usdc: "0xB6CEceAB302E2E4948951eE7843FC24E92933061",
674
+ usdcDecimals: 6,
675
+ tokenMessenger: TOKEN_MESSENGER_V2_EVM_MAINNET,
676
+ messageTransmitter: MESSAGE_TRANSMITTER_V2_EVM_MAINNET,
677
+ nativeCurrency: { symbol: "OKB", decimals: 18 },
678
+ defaultRpcUrls: ["https://rpc.xlayer.tech", "https://xlayerrpc.okx.com"],
679
+ explorerUrl: "https://www.okx.com/web3/explorer/xlayer",
680
+ capabilities: {
681
+ fastSource: true,
682
+ forwardingDestination: false,
683
+ upfrontFeeSource: false,
684
+ standardFeeSwitch: true
685
+ }
686
+ };
687
+ var EVM_MAINNET_CHAINS = [
688
+ Ethereum,
689
+ Avalanche,
690
+ Optimism,
691
+ Arbitrum,
692
+ Base,
693
+ Polygon,
694
+ Unichain,
695
+ Linea,
696
+ Codex,
697
+ Sonic,
698
+ WorldChain,
699
+ Monad,
700
+ Sei,
701
+ XDC,
702
+ HyperEVM,
703
+ Ink,
704
+ Plume,
705
+ Arc,
706
+ Edge,
707
+ Injective,
708
+ Morph,
709
+ Pharos,
710
+ Cronos,
711
+ Plasma,
712
+ XLayer
713
+ ];
714
+
715
+ // src/chains/testnet.ts
716
+ var EthereumSepolia = {
717
+ id: "Ethereum_Sepolia",
718
+ label: "Ethereum Sepolia",
719
+ ecosystem: "evm",
720
+ network: "testnet",
721
+ evmChainId: 11155111,
722
+ cctpDomain: 0,
723
+ usdc: "0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238",
724
+ usdcDecimals: 6,
725
+ tokenMessenger: TOKEN_MESSENGER_V2_EVM_TESTNET,
726
+ messageTransmitter: MESSAGE_TRANSMITTER_V2_EVM_TESTNET,
727
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET,
728
+ nativeCurrency: { symbol: "ETH", decimals: 18 },
729
+ defaultRpcUrls: ["https://ethereum-sepolia-rpc.publicnode.com"],
730
+ explorerUrl: "https://sepolia.etherscan.io",
731
+ capabilities: {
732
+ fastSource: true,
733
+ forwardingDestination: true,
734
+ upfrontFeeSource: true,
735
+ standardFeeSwitch: false
736
+ }
737
+ };
738
+ var AvalancheFuji = {
739
+ id: "Avalanche_Fuji",
740
+ label: "Avalanche Fuji",
741
+ ecosystem: "evm",
742
+ network: "testnet",
743
+ evmChainId: 43113,
744
+ cctpDomain: 1,
745
+ usdc: "0x5425890298aed601595a70AB815c96711a31Bc65",
746
+ usdcDecimals: 6,
747
+ tokenMessenger: TOKEN_MESSENGER_V2_EVM_TESTNET,
748
+ messageTransmitter: MESSAGE_TRANSMITTER_V2_EVM_TESTNET,
749
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET,
750
+ nativeCurrency: { symbol: "AVAX", decimals: 18 },
751
+ defaultRpcUrls: ["https://api.avax-test.network/ext/bc/C/rpc"],
752
+ explorerUrl: "https://explorer-test.avax.network/c-chain",
753
+ capabilities: {
754
+ fastSource: false,
755
+ forwardingDestination: true,
756
+ upfrontFeeSource: true,
757
+ standardFeeSwitch: false
758
+ }
759
+ };
760
+ var OptimismSepolia = {
761
+ id: "Optimism_Sepolia",
762
+ label: "OP Sepolia",
763
+ ecosystem: "evm",
764
+ network: "testnet",
765
+ evmChainId: 11155420,
766
+ cctpDomain: 2,
767
+ usdc: "0x5fd84259d66Cd46123540766Be93DFE6D43130D7",
768
+ usdcDecimals: 6,
769
+ tokenMessenger: TOKEN_MESSENGER_V2_EVM_TESTNET,
770
+ messageTransmitter: MESSAGE_TRANSMITTER_V2_EVM_TESTNET,
771
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET,
772
+ nativeCurrency: { symbol: "ETH", decimals: 18 },
773
+ defaultRpcUrls: ["https://sepolia.optimism.io"],
774
+ explorerUrl: "https://testnet-explorer.optimism.io",
775
+ capabilities: {
776
+ fastSource: true,
777
+ forwardingDestination: true,
778
+ upfrontFeeSource: true,
779
+ standardFeeSwitch: false
780
+ }
781
+ };
782
+ var ArbitrumSepolia = {
783
+ id: "Arbitrum_Sepolia",
784
+ label: "Arbitrum Sepolia",
785
+ ecosystem: "evm",
786
+ network: "testnet",
787
+ evmChainId: 421614,
788
+ cctpDomain: 3,
789
+ usdc: "0x75faf114eafb1BDbe2F0316DF893fd58CE46AA4d",
790
+ usdcDecimals: 6,
791
+ tokenMessenger: TOKEN_MESSENGER_V2_EVM_TESTNET,
792
+ messageTransmitter: MESSAGE_TRANSMITTER_V2_EVM_TESTNET,
793
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET,
794
+ nativeCurrency: { symbol: "ETH", decimals: 18 },
795
+ defaultRpcUrls: ["https://sepolia-rollup.arbitrum.io/rpc"],
796
+ explorerUrl: "https://sepolia.arbiscan.io",
797
+ capabilities: {
798
+ fastSource: true,
799
+ forwardingDestination: true,
800
+ upfrontFeeSource: true,
801
+ standardFeeSwitch: false
802
+ }
803
+ };
804
+ var BaseSepolia = {
805
+ id: "Base_Sepolia",
806
+ label: "Base Sepolia",
807
+ ecosystem: "evm",
808
+ network: "testnet",
809
+ evmChainId: 84532,
810
+ cctpDomain: 6,
811
+ usdc: "0x036CbD53842c5426634e7929541eC2318f3dCF7e",
812
+ usdcDecimals: 6,
813
+ tokenMessenger: TOKEN_MESSENGER_V2_EVM_TESTNET,
814
+ messageTransmitter: MESSAGE_TRANSMITTER_V2_EVM_TESTNET,
815
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET,
816
+ nativeCurrency: { symbol: "ETH", decimals: 18 },
817
+ defaultRpcUrls: ["https://sepolia.base.org"],
818
+ explorerUrl: "https://sepolia.basescan.org",
819
+ capabilities: {
820
+ fastSource: true,
821
+ forwardingDestination: true,
822
+ upfrontFeeSource: true,
823
+ standardFeeSwitch: false
824
+ }
825
+ };
826
+ var PolygonAmoyTestnet = {
827
+ id: "Polygon_Amoy_Testnet",
828
+ label: "Polygon PoS Amoy",
829
+ ecosystem: "evm",
830
+ network: "testnet",
831
+ evmChainId: 80002,
832
+ cctpDomain: 7,
833
+ usdc: "0x41E94Eb019C0762f9Bfcf9Fb1E58725BfB0e7582",
834
+ usdcDecimals: 6,
835
+ tokenMessenger: TOKEN_MESSENGER_V2_EVM_TESTNET,
836
+ messageTransmitter: MESSAGE_TRANSMITTER_V2_EVM_TESTNET,
837
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET,
838
+ nativeCurrency: { symbol: "POL", decimals: 18 },
839
+ defaultRpcUrls: ["https://polygon-amoy.drpc.org"],
840
+ explorerUrl: "https://amoy.polygonscan.com",
841
+ capabilities: {
842
+ fastSource: false,
843
+ forwardingDestination: true,
844
+ upfrontFeeSource: true,
845
+ standardFeeSwitch: false
846
+ }
847
+ };
848
+ var UnichainSepolia = {
849
+ id: "Unichain_Sepolia",
850
+ label: "Unichain Sepolia",
851
+ ecosystem: "evm",
852
+ network: "testnet",
853
+ evmChainId: 1301,
854
+ cctpDomain: 10,
855
+ usdc: "0x31d0220469e10c4E71834a79b1f276d740d3768F",
856
+ usdcDecimals: 6,
857
+ tokenMessenger: TOKEN_MESSENGER_V2_EVM_TESTNET,
858
+ messageTransmitter: MESSAGE_TRANSMITTER_V2_EVM_TESTNET,
859
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET,
860
+ nativeCurrency: { symbol: "ETH", decimals: 18 },
861
+ defaultRpcUrls: ["https://sepolia.unichain.org"],
862
+ explorerUrl: "https://sepolia.uniscan.xyz",
863
+ capabilities: {
864
+ fastSource: true,
865
+ forwardingDestination: true,
866
+ upfrontFeeSource: true,
867
+ standardFeeSwitch: false
868
+ }
869
+ };
870
+ var LineaSepolia = {
871
+ id: "Linea_Sepolia",
872
+ label: "Linea Sepolia",
873
+ ecosystem: "evm",
874
+ network: "testnet",
875
+ evmChainId: 59141,
876
+ cctpDomain: 11,
877
+ usdc: "0xFEce4462D57bD51A6A552365A011b95f0E16d9B7",
878
+ usdcDecimals: 6,
879
+ tokenMessenger: TOKEN_MESSENGER_V2_EVM_TESTNET,
880
+ messageTransmitter: MESSAGE_TRANSMITTER_V2_EVM_TESTNET,
881
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET,
882
+ nativeCurrency: { symbol: "ETH", decimals: 18 },
883
+ defaultRpcUrls: ["https://rpc.sepolia.linea.build"],
884
+ explorerUrl: "https://sepolia.lineascan.build",
885
+ capabilities: {
886
+ fastSource: true,
887
+ forwardingDestination: true,
888
+ upfrontFeeSource: true,
889
+ standardFeeSwitch: false
890
+ }
891
+ };
892
+ var CodexTestnet = {
893
+ id: "Codex_Testnet",
894
+ label: "Codex Testnet",
895
+ ecosystem: "evm",
896
+ network: "testnet",
897
+ evmChainId: 812242,
898
+ cctpDomain: 12,
899
+ usdc: "0x6d7f141b6819C2c9CC2f818e6ad549E7Ca090F8f",
900
+ usdcDecimals: 6,
901
+ tokenMessenger: TOKEN_MESSENGER_V2_EVM_TESTNET,
902
+ messageTransmitter: MESSAGE_TRANSMITTER_V2_EVM_TESTNET,
903
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET,
904
+ nativeCurrency: { symbol: "ETH", decimals: 18 },
905
+ defaultRpcUrls: ["https://rpc.codex-stg.xyz"],
906
+ explorerUrl: "https://explorer.codex-stg.xyz",
907
+ capabilities: {
908
+ fastSource: true,
909
+ forwardingDestination: true,
910
+ upfrontFeeSource: true,
911
+ standardFeeSwitch: false
912
+ }
913
+ };
914
+ var SonicTestnet = {
915
+ id: "Sonic_Testnet",
916
+ label: "Sonic Testnet",
917
+ ecosystem: "evm",
918
+ network: "testnet",
919
+ evmChainId: 14601,
920
+ cctpDomain: 13,
921
+ usdc: "0x0BA304580ee7c9a980CF72e55f5Ed2E9fd30Bc51",
922
+ usdcDecimals: 6,
923
+ tokenMessenger: TOKEN_MESSENGER_V2_EVM_TESTNET,
924
+ messageTransmitter: MESSAGE_TRANSMITTER_V2_EVM_TESTNET,
925
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET,
926
+ nativeCurrency: { symbol: "S", decimals: 18 },
927
+ defaultRpcUrls: ["https://rpc.testnet.soniclabs.com"],
928
+ explorerUrl: "https://testnet.sonicscan.org",
929
+ capabilities: {
930
+ fastSource: false,
931
+ forwardingDestination: true,
932
+ upfrontFeeSource: true,
933
+ standardFeeSwitch: true
934
+ }
935
+ };
936
+ var WorldChainSepolia = {
937
+ id: "World_Chain_Sepolia",
938
+ label: "World Chain Sepolia",
939
+ ecosystem: "evm",
940
+ network: "testnet",
941
+ evmChainId: 4801,
942
+ cctpDomain: 14,
943
+ usdc: "0x66145f38cBAC35Ca6F1Dfb4914dF98F1614aeA88",
944
+ usdcDecimals: 6,
945
+ tokenMessenger: TOKEN_MESSENGER_V2_EVM_TESTNET,
946
+ messageTransmitter: MESSAGE_TRANSMITTER_V2_EVM_TESTNET,
947
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET,
948
+ nativeCurrency: { symbol: "ETH", decimals: 18 },
949
+ defaultRpcUrls: ["https://worldchain-sepolia.g.alchemy.com/public"],
950
+ explorerUrl: "https://worldchain-sepolia.explorer.alchemy.com",
951
+ capabilities: {
952
+ fastSource: true,
953
+ forwardingDestination: true,
954
+ upfrontFeeSource: true,
955
+ standardFeeSwitch: false
956
+ }
957
+ };
958
+ var MonadTestnet = {
959
+ id: "Monad_Testnet",
960
+ label: "Monad Testnet",
961
+ ecosystem: "evm",
962
+ network: "testnet",
963
+ evmChainId: 10143,
964
+ cctpDomain: 15,
965
+ usdc: "0x534b2f3A21130d7a60830c2Df862319e593943A3",
966
+ usdcDecimals: 6,
967
+ tokenMessenger: TOKEN_MESSENGER_V2_EVM_TESTNET,
968
+ messageTransmitter: MESSAGE_TRANSMITTER_V2_EVM_TESTNET,
969
+ nativeCurrency: { symbol: "MON", decimals: 18 },
970
+ defaultRpcUrls: [
971
+ "https://testnet-rpc.monad.xyz",
972
+ "https://rpc-testnet.monadinfra.com"
973
+ ],
974
+ explorerUrl: "https://testnet.monadvision.com",
975
+ capabilities: {
976
+ fastSource: false,
977
+ forwardingDestination: true,
978
+ upfrontFeeSource: false,
979
+ standardFeeSwitch: true
980
+ }
981
+ };
982
+ var SeiTestnet = {
983
+ id: "Sei_Testnet",
984
+ label: "Sei Testnet",
985
+ ecosystem: "evm",
986
+ network: "testnet",
987
+ evmChainId: 1328,
988
+ cctpDomain: 16,
989
+ usdc: "0x4fCF1784B31630811181f670Aea7A7bEF803eaED",
990
+ usdcDecimals: 6,
991
+ tokenMessenger: TOKEN_MESSENGER_V2_EVM_TESTNET,
992
+ messageTransmitter: MESSAGE_TRANSMITTER_V2_EVM_TESTNET,
993
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET,
994
+ nativeCurrency: { symbol: "SEI", decimals: 18 },
995
+ defaultRpcUrls: ["https://evm-rpc-testnet.sei-apis.com"],
996
+ explorerUrl: "https://testnet.seiscan.io",
997
+ capabilities: {
998
+ fastSource: false,
999
+ forwardingDestination: true,
1000
+ upfrontFeeSource: true,
1001
+ standardFeeSwitch: true
1002
+ }
1003
+ };
1004
+ var XDCApothem = {
1005
+ id: "XDC_Apothem",
1006
+ label: "XDC Apothem",
1007
+ ecosystem: "evm",
1008
+ network: "testnet",
1009
+ evmChainId: 51,
1010
+ cctpDomain: 18,
1011
+ usdc: "0xb5AB69F7bBada22B28e79C8FFAECe55eF1c771D4",
1012
+ usdcDecimals: 6,
1013
+ tokenMessenger: TOKEN_MESSENGER_V2_EVM_TESTNET,
1014
+ messageTransmitter: MESSAGE_TRANSMITTER_V2_EVM_TESTNET,
1015
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET,
1016
+ nativeCurrency: { symbol: "TXDC", decimals: 18 },
1017
+ defaultRpcUrls: [
1018
+ "https://rpc.apothem.network",
1019
+ "https://erpc.apothem.network"
1020
+ ],
1021
+ explorerUrl: "https://testnet.xdcscan.com",
1022
+ capabilities: {
1023
+ fastSource: false,
1024
+ forwardingDestination: true,
1025
+ upfrontFeeSource: true,
1026
+ standardFeeSwitch: true
1027
+ }
1028
+ };
1029
+ var HyperEVMTestnet = {
1030
+ id: "HyperEVM_Testnet",
1031
+ label: "HyperEVM Testnet",
1032
+ ecosystem: "evm",
1033
+ network: "testnet",
1034
+ evmChainId: 998,
1035
+ cctpDomain: 19,
1036
+ usdc: "0x2B3370eE501B4a559b57D449569354196457D8Ab",
1037
+ usdcDecimals: 6,
1038
+ tokenMessenger: TOKEN_MESSENGER_V2_EVM_TESTNET,
1039
+ messageTransmitter: MESSAGE_TRANSMITTER_V2_EVM_TESTNET,
1040
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET,
1041
+ nativeCurrency: { symbol: "HYPE", decimals: 18 },
1042
+ defaultRpcUrls: ["https://rpc.hyperliquid-testnet.xyz/evm"],
1043
+ explorerUrl: "https://app.hyperliquid-testnet.xyz/explorer",
1044
+ capabilities: {
1045
+ fastSource: false,
1046
+ forwardingDestination: true,
1047
+ upfrontFeeSource: true,
1048
+ standardFeeSwitch: true
1049
+ }
1050
+ };
1051
+ var InkTestnet = {
1052
+ id: "Ink_Testnet",
1053
+ label: "Ink Testnet",
1054
+ ecosystem: "evm",
1055
+ network: "testnet",
1056
+ evmChainId: 763373,
1057
+ cctpDomain: 21,
1058
+ usdc: "0xFabab97dCE620294D2B0b0e46C68964e326300Ac",
1059
+ usdcDecimals: 6,
1060
+ tokenMessenger: TOKEN_MESSENGER_V2_EVM_TESTNET,
1061
+ messageTransmitter: MESSAGE_TRANSMITTER_V2_EVM_TESTNET,
1062
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET,
1063
+ nativeCurrency: { symbol: "ETH", decimals: 18 },
1064
+ defaultRpcUrls: [
1065
+ "https://rpc-gel-sepolia.inkonchain.com",
1066
+ "https://rpc-qnd-sepolia.inkonchain.com"
1067
+ ],
1068
+ explorerUrl: "https://explorer-sepolia.inkonchain.com",
1069
+ capabilities: {
1070
+ fastSource: true,
1071
+ forwardingDestination: true,
1072
+ upfrontFeeSource: true,
1073
+ standardFeeSwitch: true
1074
+ }
1075
+ };
1076
+ var PlumeTestnet = {
1077
+ id: "Plume_Testnet",
1078
+ label: "Plume Testnet",
1079
+ ecosystem: "evm",
1080
+ network: "testnet",
1081
+ evmChainId: 98867,
1082
+ cctpDomain: 22,
1083
+ usdc: "0xcB5f30e335672893c7eb944B374c196392C19D18",
1084
+ usdcDecimals: 6,
1085
+ tokenMessenger: TOKEN_MESSENGER_V2_EVM_TESTNET,
1086
+ messageTransmitter: MESSAGE_TRANSMITTER_V2_EVM_TESTNET,
1087
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET,
1088
+ nativeCurrency: { symbol: "PLUME", decimals: 18 },
1089
+ defaultRpcUrls: ["https://testnet-rpc.plume.org"],
1090
+ explorerUrl: "https://testnet-explorer.plume.org",
1091
+ capabilities: {
1092
+ fastSource: true,
1093
+ forwardingDestination: true,
1094
+ upfrontFeeSource: true,
1095
+ standardFeeSwitch: true
1096
+ }
1097
+ };
1098
+ var ArcTestnet = {
1099
+ id: "Arc_Testnet",
1100
+ label: "Arc Testnet",
1101
+ ecosystem: "evm",
1102
+ network: "testnet",
1103
+ evmChainId: 5042002,
1104
+ cctpDomain: 26,
1105
+ usdc: "0x3600000000000000000000000000000000000000",
1106
+ usdcDecimals: 6,
1107
+ tokenMessenger: TOKEN_MESSENGER_V2_EVM_TESTNET,
1108
+ messageTransmitter: MESSAGE_TRANSMITTER_V2_EVM_TESTNET,
1109
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET,
1110
+ nativeCurrency: { symbol: "USDC", decimals: 18 },
1111
+ defaultRpcUrls: ["https://rpc.testnet.arc.io"],
1112
+ explorerUrl: "https://explorer.testnet.arc.io",
1113
+ capabilities: {
1114
+ fastSource: false,
1115
+ forwardingDestination: true,
1116
+ upfrontFeeSource: true,
1117
+ standardFeeSwitch: true
1118
+ }
1119
+ };
1120
+ var EdgeTestnet = {
1121
+ id: "Edge_Testnet",
1122
+ label: "EDGE Testnet",
1123
+ ecosystem: "evm",
1124
+ network: "testnet",
1125
+ evmChainId: 33431,
1126
+ cctpDomain: 28,
1127
+ usdc: "0x2d9F7CAD728051AA35Ecdc472a14cf8cDF5CFD6B",
1128
+ usdcDecimals: 6,
1129
+ tokenMessenger: TOKEN_MESSENGER_V2_EVM_TESTNET,
1130
+ messageTransmitter: MESSAGE_TRANSMITTER_V2_EVM_TESTNET,
1131
+ nativeCurrency: { symbol: "ETH", decimals: 18 },
1132
+ defaultRpcUrls: ["https://edge-testnet.g.alchemy.com/public"],
1133
+ explorerUrl: "https://edge-testnet.explorer.alchemy.com",
1134
+ capabilities: {
1135
+ fastSource: true,
1136
+ forwardingDestination: true,
1137
+ upfrontFeeSource: false,
1138
+ standardFeeSwitch: true
1139
+ }
1140
+ };
1141
+ var InjectiveTestnet = {
1142
+ id: "Injective_Testnet",
1143
+ label: "Injective Testnet",
1144
+ ecosystem: "evm",
1145
+ network: "testnet",
1146
+ evmChainId: 1439,
1147
+ cctpDomain: 29,
1148
+ usdc: "0x0C382e685bbeeFE5d3d9C29e29E341fEE8E84C5d",
1149
+ usdcDecimals: 6,
1150
+ tokenMessenger: TOKEN_MESSENGER_V2_EVM_TESTNET,
1151
+ messageTransmitter: MESSAGE_TRANSMITTER_V2_EVM_TESTNET,
1152
+ nativeCurrency: { symbol: "INJ", decimals: 18 },
1153
+ defaultRpcUrls: [
1154
+ "https://k8s.testnet.json-rpc.injective.network",
1155
+ "https://testnet.evm.archival.chain.virtual.json-rpc.injective.network"
1156
+ ],
1157
+ explorerUrl: "https://testnet.blockscout.injective.network",
1158
+ capabilities: {
1159
+ fastSource: false,
1160
+ forwardingDestination: false,
1161
+ upfrontFeeSource: false,
1162
+ standardFeeSwitch: true
1163
+ }
1164
+ };
1165
+ var MorphTestnet = {
1166
+ id: "Morph_Testnet",
1167
+ label: "Morph Hoodi Testnet",
1168
+ ecosystem: "evm",
1169
+ network: "testnet",
1170
+ evmChainId: 2910,
1171
+ cctpDomain: 30,
1172
+ usdc: "0x7433b41C6c5e1d58D4Da99483609520255ab661B",
1173
+ usdcDecimals: 6,
1174
+ tokenMessenger: TOKEN_MESSENGER_V2_EVM_TESTNET,
1175
+ messageTransmitter: MESSAGE_TRANSMITTER_V2_EVM_TESTNET,
1176
+ nativeCurrency: { symbol: "ETH", decimals: 18 },
1177
+ defaultRpcUrls: ["https://rpc-hoodi-bgw.morph.network"],
1178
+ explorerUrl: "https://explorer-hoodi.morph.network",
1179
+ capabilities: {
1180
+ fastSource: true,
1181
+ forwardingDestination: false,
1182
+ upfrontFeeSource: false,
1183
+ standardFeeSwitch: true
1184
+ }
1185
+ };
1186
+ var PharosTestnet = {
1187
+ id: "Pharos_Testnet",
1188
+ label: "Pharos Testnet",
1189
+ ecosystem: "evm",
1190
+ network: "testnet",
1191
+ evmChainId: 688689,
1192
+ cctpDomain: 31,
1193
+ usdc: "0xcfC8330f4BCAB529c625D12781b1C19466A9Fc8B",
1194
+ usdcDecimals: 6,
1195
+ tokenMessenger: TOKEN_MESSENGER_V2_EVM_TESTNET,
1196
+ messageTransmitter: MESSAGE_TRANSMITTER_V2_EVM_TESTNET,
1197
+ nativeCurrency: { symbol: "PHAROS", decimals: 18 },
1198
+ defaultRpcUrls: ["https://atlantic.dplabs-internal.com"],
1199
+ explorerUrl: "https://atlantic.pharosscan.xyz",
1200
+ capabilities: {
1201
+ fastSource: false,
1202
+ forwardingDestination: false,
1203
+ upfrontFeeSource: false,
1204
+ standardFeeSwitch: true
1205
+ }
1206
+ };
1207
+ var CronosTestnet = {
1208
+ id: "Cronos_Testnet",
1209
+ label: "Cronos Testnet",
1210
+ ecosystem: "evm",
1211
+ network: "testnet",
1212
+ evmChainId: 338,
1213
+ cctpDomain: 32,
1214
+ usdc: "0xEb33dc5fac03833e132593659e1dE7256aB59794",
1215
+ usdcDecimals: 6,
1216
+ tokenMessenger: TOKEN_MESSENGER_V2_EVM_TESTNET,
1217
+ messageTransmitter: MESSAGE_TRANSMITTER_V2_EVM_TESTNET,
1218
+ nativeCurrency: { symbol: "tCRO", decimals: 18 },
1219
+ defaultRpcUrls: ["https://evm-t3.cronos.com"],
1220
+ explorerUrl: "https://explorer.cronos.com/testnet",
1221
+ capabilities: {
1222
+ fastSource: false,
1223
+ forwardingDestination: false,
1224
+ upfrontFeeSource: false,
1225
+ standardFeeSwitch: true
1226
+ }
1227
+ };
1228
+ var PlasmaTestnet = {
1229
+ id: "Plasma_Testnet",
1230
+ label: "Plasma Testnet",
1231
+ ecosystem: "evm",
1232
+ network: "testnet",
1233
+ evmChainId: 9746,
1234
+ cctpDomain: 33,
1235
+ usdc: "0xE67Fb267022cBA8064Dd388CC2FED724F3120D9D",
1236
+ usdcDecimals: 6,
1237
+ tokenMessenger: TOKEN_MESSENGER_V2_EVM_TESTNET,
1238
+ messageTransmitter: MESSAGE_TRANSMITTER_V2_EVM_TESTNET,
1239
+ nativeCurrency: { symbol: "XPL", decimals: 18 },
1240
+ defaultRpcUrls: ["https://testnet-rpc.plasma.to"],
1241
+ explorerUrl: "https://testnet.plasmascan.to",
1242
+ capabilities: {
1243
+ fastSource: false,
1244
+ forwardingDestination: false,
1245
+ upfrontFeeSource: false,
1246
+ standardFeeSwitch: true
1247
+ }
1248
+ };
1249
+ var XLayerTestnet = {
1250
+ id: "X_Layer_Testnet",
1251
+ label: "X Layer Testnet",
1252
+ ecosystem: "evm",
1253
+ network: "testnet",
1254
+ evmChainId: 1952,
1255
+ cctpDomain: 37,
1256
+ usdc: "0xDec90b78111Ba2fc6FC6d84d8B9ec159A2d4b9B3",
1257
+ usdcDecimals: 6,
1258
+ tokenMessenger: TOKEN_MESSENGER_V2_EVM_TESTNET,
1259
+ messageTransmitter: MESSAGE_TRANSMITTER_V2_EVM_TESTNET,
1260
+ nativeCurrency: { symbol: "OKB", decimals: 18 },
1261
+ defaultRpcUrls: [
1262
+ "https://testrpc.xlayer.tech/terigon",
1263
+ "https://xlayertestrpc.okx.com/terigon"
1264
+ ],
1265
+ explorerUrl: "https://www.okx.com/web3/explorer/xlayer-test",
1266
+ capabilities: {
1267
+ fastSource: true,
1268
+ forwardingDestination: false,
1269
+ upfrontFeeSource: false,
1270
+ standardFeeSwitch: true
1271
+ }
1272
+ };
1273
+ var EVM_TESTNET_CHAINS = [
1274
+ EthereumSepolia,
1275
+ AvalancheFuji,
1276
+ OptimismSepolia,
1277
+ ArbitrumSepolia,
1278
+ BaseSepolia,
1279
+ PolygonAmoyTestnet,
1280
+ UnichainSepolia,
1281
+ LineaSepolia,
1282
+ CodexTestnet,
1283
+ SonicTestnet,
1284
+ WorldChainSepolia,
1285
+ MonadTestnet,
1286
+ SeiTestnet,
1287
+ XDCApothem,
1288
+ HyperEVMTestnet,
1289
+ InkTestnet,
1290
+ PlumeTestnet,
1291
+ ArcTestnet,
1292
+ EdgeTestnet,
1293
+ InjectiveTestnet,
1294
+ MorphTestnet,
1295
+ PharosTestnet,
1296
+ CronosTestnet,
1297
+ PlasmaTestnet,
1298
+ XLayerTestnet
1299
+ ];
1300
+
1301
+ // src/chains/solana.ts
1302
+ var Solana = {
1303
+ id: "Solana",
1304
+ label: "Solana",
1305
+ ecosystem: "solana",
1306
+ network: "mainnet",
1307
+ cluster: "mainnet-beta",
1308
+ cctpDomain: SOLANA_CCTP_DOMAIN,
1309
+ usdc: USDC_SPL_MAINNET,
1310
+ usdcDecimals: 6,
1311
+ tokenMessengerMinter: TOKEN_MESSENGER_MINTER_V2_SOLANA,
1312
+ messageTransmitter: MESSAGE_TRANSMITTER_V2_SOLANA,
1313
+ nativeCurrency: { symbol: "SOL", decimals: 9 },
1314
+ defaultRpcUrls: [
1315
+ "https://api.mainnet.solana.com",
1316
+ "https://api.mainnet-beta.solana.com"
1317
+ ],
1318
+ explorerUrl: "https://explorer.solana.com",
1319
+ capabilities: {
1320
+ fastSource: true,
1321
+ forwardingDestination: true,
1322
+ upfrontFeeSource: false,
1323
+ standardFeeSwitch: false
1324
+ }
1325
+ };
1326
+ var SolanaDevnet = {
1327
+ id: "Solana_Devnet",
1328
+ label: "Solana Devnet",
1329
+ ecosystem: "solana",
1330
+ network: "testnet",
1331
+ cluster: "devnet",
1332
+ cctpDomain: SOLANA_CCTP_DOMAIN,
1333
+ usdc: USDC_SPL_DEVNET,
1334
+ usdcDecimals: 6,
1335
+ tokenMessengerMinter: TOKEN_MESSENGER_MINTER_V2_SOLANA,
1336
+ messageTransmitter: MESSAGE_TRANSMITTER_V2_SOLANA,
1337
+ nativeCurrency: { symbol: "SOL", decimals: 9 },
1338
+ defaultRpcUrls: ["https://api.devnet.solana.com"],
1339
+ explorerUrl: "https://explorer.solana.com",
1340
+ explorerQuery: "?cluster=devnet",
1341
+ capabilities: {
1342
+ fastSource: true,
1343
+ forwardingDestination: true,
1344
+ upfrontFeeSource: false,
1345
+ standardFeeSwitch: false
1346
+ }
1347
+ };
1348
+ function deriveUsdcSac(issuer, passphrase) {
1349
+ return new stellarSdk.Asset("USDC", issuer).contractId(passphrase);
1350
+ }
1351
+ var USDC_SAC_STELLAR_MAINNET = deriveUsdcSac(
1352
+ USDC_ISSUER_STELLAR_MAINNET,
1353
+ STELLAR_NETWORK_PASSPHRASE_MAINNET
1354
+ );
1355
+ var USDC_SAC_STELLAR_TESTNET = deriveUsdcSac(
1356
+ USDC_ISSUER_STELLAR_TESTNET,
1357
+ STELLAR_NETWORK_PASSPHRASE_TESTNET
1358
+ );
1359
+ var Stellar = {
1360
+ id: "Stellar",
1361
+ label: "Stellar",
1362
+ ecosystem: "stellar",
1363
+ network: "mainnet",
1364
+ stellarNetwork: "public",
1365
+ networkPassphrase: STELLAR_NETWORK_PASSPHRASE_MAINNET,
1366
+ cctpDomain: STELLAR_CCTP_DOMAIN,
1367
+ usdcIssuer: USDC_ISSUER_STELLAR_MAINNET,
1368
+ usdc: USDC_SAC_STELLAR_MAINNET,
1369
+ usdcDecimals: STELLAR_USDC_DECIMALS,
1370
+ tokenMessengerMinter: TOKEN_MESSENGER_MINTER_STELLAR_MAINNET,
1371
+ messageTransmitter: MESSAGE_TRANSMITTER_STELLAR_MAINNET,
1372
+ cctpForwarder: CCTP_FORWARDER_STELLAR_MAINNET,
1373
+ nativeCurrency: { symbol: "XLM", decimals: 7 },
1374
+ defaultRpcUrls: [
1375
+ "https://soroban-rpc.mainnet.stellar.gateway.fm",
1376
+ "https://mainnet.sorobanrpc.com"
1377
+ ],
1378
+ explorerUrl: "https://stellar.expert/explorer/public",
1379
+ capabilities: {
1380
+ fastSource: false,
1381
+ forwardingDestination: false,
1382
+ upfrontFeeSource: false,
1383
+ standardFeeSwitch: false
1384
+ }
1385
+ };
1386
+ var StellarTestnet = {
1387
+ id: "Stellar_Testnet",
1388
+ label: "Stellar Testnet",
1389
+ ecosystem: "stellar",
1390
+ network: "testnet",
1391
+ stellarNetwork: "testnet",
1392
+ networkPassphrase: STELLAR_NETWORK_PASSPHRASE_TESTNET,
1393
+ cctpDomain: STELLAR_CCTP_DOMAIN,
1394
+ usdcIssuer: USDC_ISSUER_STELLAR_TESTNET,
1395
+ usdc: USDC_SAC_STELLAR_TESTNET,
1396
+ usdcDecimals: STELLAR_USDC_DECIMALS,
1397
+ tokenMessengerMinter: TOKEN_MESSENGER_MINTER_STELLAR_TESTNET,
1398
+ messageTransmitter: MESSAGE_TRANSMITTER_STELLAR_TESTNET,
1399
+ cctpForwarder: CCTP_FORWARDER_STELLAR_TESTNET,
1400
+ nativeCurrency: { symbol: "XLM", decimals: 7 },
1401
+ defaultRpcUrls: ["https://soroban-testnet.stellar.org"],
1402
+ explorerUrl: "https://stellar.expert/explorer/testnet",
1403
+ capabilities: {
1404
+ fastSource: false,
1405
+ forwardingDestination: false,
1406
+ upfrontFeeSource: false,
1407
+ standardFeeSwitch: false
1408
+ }
1409
+ };
1410
+
1411
+ // src/chains/starknet.ts
1412
+ var Starknet = {
1413
+ id: "Starknet",
1414
+ label: "Starknet",
1415
+ ecosystem: "starknet",
1416
+ network: "mainnet",
1417
+ starknetNetwork: "mainnet",
1418
+ chainId: STARKNET_CHAIN_ID_MAINNET,
1419
+ cctpDomain: STARKNET_CCTP_DOMAIN,
1420
+ usdc: USDC_STARKNET_MAINNET,
1421
+ usdcDecimals: 6,
1422
+ tokenMessengerMinter: TOKEN_MESSENGER_MINTER_V2_STARKNET_MAINNET,
1423
+ messageTransmitter: MESSAGE_TRANSMITTER_V2_STARKNET_MAINNET,
1424
+ nativeCurrency: { symbol: "STRK", decimals: 18 },
1425
+ defaultRpcUrls: ["https://starknet-rpc.publicnode.com"],
1426
+ explorerUrl: "https://voyager.online",
1427
+ capabilities: {
1428
+ fastSource: true,
1429
+ forwardingDestination: false,
1430
+ upfrontFeeSource: false,
1431
+ standardFeeSwitch: false
1432
+ }
1433
+ };
1434
+ var StarknetSepolia = {
1435
+ id: "Starknet_Sepolia",
1436
+ label: "Starknet Sepolia",
1437
+ ecosystem: "starknet",
1438
+ network: "testnet",
1439
+ starknetNetwork: "sepolia",
1440
+ chainId: STARKNET_CHAIN_ID_SEPOLIA,
1441
+ cctpDomain: STARKNET_CCTP_DOMAIN,
1442
+ usdc: USDC_STARKNET_SEPOLIA,
1443
+ usdcDecimals: 6,
1444
+ tokenMessengerMinter: TOKEN_MESSENGER_MINTER_V2_STARKNET_SEPOLIA,
1445
+ messageTransmitter: MESSAGE_TRANSMITTER_V2_STARKNET_SEPOLIA,
1446
+ nativeCurrency: { symbol: "STRK", decimals: 18 },
1447
+ defaultRpcUrls: ["https://starknet-sepolia-rpc.publicnode.com"],
1448
+ explorerUrl: "https://sepolia.voyager.online",
1449
+ capabilities: {
1450
+ fastSource: true,
1451
+ forwardingDestination: false,
1452
+ upfrontFeeSource: false,
1453
+ standardFeeSwitch: false
1454
+ }
1455
+ };
1456
+
1457
+ // src/chains/registry.ts
1458
+ var UnknownChainError = class extends InvalidInputError {
1459
+ constructor(detail) {
1460
+ super("invalid_chain", `Unknown chain: ${detail}`);
1461
+ this.name = "UnknownChainError";
1462
+ }
1463
+ };
1464
+ var CHAINS = [
1465
+ ...EVM_MAINNET_CHAINS,
1466
+ ...EVM_TESTNET_CHAINS,
1467
+ Solana,
1468
+ SolanaDevnet,
1469
+ Stellar,
1470
+ StellarTestnet,
1471
+ Starknet,
1472
+ StarknetSepolia
1473
+ ];
1474
+ var ALL = CHAINS;
1475
+ var BY_ID = new Map(ALL.map((c) => [c.id, c]));
1476
+ var BY_EVM_CHAIN_ID = new Map(
1477
+ ALL.filter(isEvmChain).map((c) => [c.evmChainId, c])
1478
+ );
1479
+ var BY_DOMAIN_AND_NETWORK = new Map(
1480
+ ALL.map((c) => [`${c.cctpDomain}:${c.network}`, c])
1481
+ );
1482
+ function isEvmChain(chain) {
1483
+ return chain.ecosystem === "evm";
1484
+ }
1485
+ function isSolanaChain(chain) {
1486
+ return chain.ecosystem === "solana";
1487
+ }
1488
+ function isStellarChain(chain) {
1489
+ return chain.ecosystem === "stellar";
1490
+ }
1491
+ function isStarknetChain(chain) {
1492
+ return chain.ecosystem === "starknet";
1493
+ }
1494
+ function isChainId(value) {
1495
+ return BY_ID.has(value);
1496
+ }
1497
+ function getChain(id) {
1498
+ const chain = BY_ID.get(id);
1499
+ if (!chain) throw new UnknownChainError(`id="${id}"`);
1500
+ return chain;
1501
+ }
1502
+ function chainsByNetwork(network) {
1503
+ return ALL.filter((c) => c.network === network);
1504
+ }
1505
+ function chainByEvmChainId(evmChainId) {
1506
+ const chain = BY_EVM_CHAIN_ID.get(evmChainId);
1507
+ if (!chain) throw new UnknownChainError(`evmChainId=${evmChainId}`);
1508
+ return chain;
1509
+ }
1510
+ function tryChainByEvmChainId(evmChainId) {
1511
+ return BY_EVM_CHAIN_ID.get(evmChainId);
1512
+ }
1513
+ function chainByDomain(domain, network) {
1514
+ const chain = BY_DOMAIN_AND_NETWORK.get(`${domain}:${network}`);
1515
+ if (!chain) {
1516
+ throw new UnknownChainError(`domain=${domain} network=${network}`);
1517
+ }
1518
+ return chain;
1519
+ }
1520
+ function explorerTxUrl(chain, txHash) {
1521
+ return `${chain.explorerUrl}/tx/${txHash}${chain.explorerQuery ?? ""}`;
1522
+ }
1523
+ function explorerAddressUrl(chain, address) {
1524
+ return `${chain.explorerUrl}/${addressPath(chain, address)}/${address}${chain.explorerQuery ?? ""}`;
1525
+ }
1526
+ function addressPath(chain, address) {
1527
+ switch (chain.ecosystem) {
1528
+ case "starknet":
1529
+ return "contract";
1530
+ case "stellar":
1531
+ return address.startsWith("C") ? "contract" : "account";
1532
+ default:
1533
+ return "address";
1534
+ }
1535
+ }
1536
+
1537
+ // src/chains/attestation.ts
1538
+ var s = (min, max = min) => ({ min, max });
1539
+ var L1_FINALITY = s(900, 1140);
1540
+ var BY_DOMAIN = {
1541
+ 0: { fast: s(20), standard: L1_FINALITY },
1542
+ 1: { standard: s(8) },
1543
+ 2: { fast: s(8), standard: L1_FINALITY },
1544
+ 3: { fast: s(8), standard: L1_FINALITY },
1545
+ 5: { fast: s(8), standard: s(25) },
1546
+ 6: { fast: s(8), standard: L1_FINALITY },
1547
+ 7: { standard: s(8) },
1548
+ 10: { fast: s(8), standard: L1_FINALITY },
1549
+ 11: { fast: s(8), standard: s(21600, 115200) },
1550
+ 12: { fast: s(8), standard: L1_FINALITY },
1551
+ 13: { standard: s(8) },
1552
+ 14: { fast: s(8), standard: L1_FINALITY },
1553
+ 15: { standard: s(5) },
1554
+ 16: { standard: s(5) },
1555
+ 18: { standard: s(10) },
1556
+ 19: { standard: s(5) },
1557
+ 21: { fast: s(8), standard: s(1800) },
1558
+ 22: { fast: s(8), standard: L1_FINALITY },
1559
+ 25: { fast: s(20), standard: s(7200, 14400) },
1560
+ 26: { standard: s(0.5) },
1561
+ 27: { standard: s(5) },
1562
+ 28: { fast: s(8), standard: s(960, 1260) },
1563
+ 29: { standard: s(0.65) },
1564
+ 30: { fast: s(8), standard: s(1200, 1800) },
1565
+ 31: { standard: s(7) },
1566
+ 32: { standard: s(0.5) },
1567
+ 33: { standard: s(1) },
1568
+ 37: { fast: s(8), standard: L1_FINALITY }
1569
+ };
1570
+ function attestationSeconds(chain, speed) {
1571
+ const times = BY_DOMAIN[chain.cctpDomain]?.[speed];
1572
+ if (!times) {
1573
+ throw new ProtocolError(
1574
+ "no_route",
1575
+ `No ${speed} attestation time for ${chain.label}.`
1576
+ );
1577
+ }
1578
+ return times;
1579
+ }
1580
+
1581
+ // src/abi/tokenMessengerV2.ts
1582
+ var tokenMessengerV2Abi = [
1583
+ {
1584
+ type: "function",
1585
+ name: "depositForBurn",
1586
+ stateMutability: "nonpayable",
1587
+ inputs: [
1588
+ { name: "amount", type: "uint256" },
1589
+ { name: "destinationDomain", type: "uint32" },
1590
+ { name: "mintRecipient", type: "bytes32" },
1591
+ { name: "burnToken", type: "address" },
1592
+ { name: "destinationCaller", type: "bytes32" },
1593
+ { name: "maxFee", type: "uint256" },
1594
+ { name: "minFinalityThreshold", type: "uint32" }
1595
+ ],
1596
+ outputs: []
1597
+ },
1598
+ {
1599
+ type: "function",
1600
+ name: "depositForBurnWithHook",
1601
+ stateMutability: "nonpayable",
1602
+ inputs: [
1603
+ { name: "amount", type: "uint256" },
1604
+ { name: "destinationDomain", type: "uint32" },
1605
+ { name: "mintRecipient", type: "bytes32" },
1606
+ { name: "burnToken", type: "address" },
1607
+ { name: "destinationCaller", type: "bytes32" },
1608
+ { name: "maxFee", type: "uint256" },
1609
+ { name: "minFinalityThreshold", type: "uint32" },
1610
+ { name: "hookData", type: "bytes" }
1611
+ ],
1612
+ outputs: []
1613
+ },
1614
+ {
1615
+ type: "event",
1616
+ name: "DepositForBurn",
1617
+ anonymous: false,
1618
+ inputs: [
1619
+ { name: "burnToken", type: "address", indexed: true },
1620
+ { name: "amount", type: "uint256", indexed: false },
1621
+ { name: "depositor", type: "address", indexed: true },
1622
+ { name: "mintRecipient", type: "bytes32", indexed: false },
1623
+ { name: "destinationDomain", type: "uint32", indexed: false },
1624
+ { name: "destinationTokenMessenger", type: "bytes32", indexed: false },
1625
+ { name: "destinationCaller", type: "bytes32", indexed: false },
1626
+ { name: "maxFee", type: "uint256", indexed: false },
1627
+ { name: "minFinalityThreshold", type: "uint32", indexed: false },
1628
+ { name: "hookData", type: "bytes", indexed: false }
1629
+ ]
1630
+ }
1631
+ ];
1632
+
1633
+ // src/abi/messageTransmitterV2.ts
1634
+ var messageTransmitterV2Abi = [
1635
+ {
1636
+ type: "function",
1637
+ name: "receiveMessage",
1638
+ stateMutability: "nonpayable",
1639
+ inputs: [
1640
+ { name: "message", type: "bytes" },
1641
+ { name: "attestation", type: "bytes" }
1642
+ ],
1643
+ outputs: [{ name: "success", type: "bool" }]
1644
+ },
1645
+ {
1646
+ type: "function",
1647
+ name: "usedNonces",
1648
+ stateMutability: "view",
1649
+ inputs: [{ name: "nonce", type: "bytes32" }],
1650
+ outputs: [{ name: "isUsed", type: "uint256" }]
1651
+ },
1652
+ {
1653
+ type: "event",
1654
+ name: "MessageReceived",
1655
+ anonymous: false,
1656
+ inputs: [
1657
+ { name: "caller", type: "address", indexed: true },
1658
+ { name: "sourceDomain", type: "uint32", indexed: true },
1659
+ { name: "nonce", type: "bytes32", indexed: true },
1660
+ { name: "sender", type: "bytes32", indexed: false },
1661
+ { name: "finalityThresholdExecuted", type: "uint32", indexed: false },
1662
+ { name: "messageBody", type: "bytes", indexed: false }
1663
+ ]
1664
+ },
1665
+ {
1666
+ type: "event",
1667
+ name: "MessageSent",
1668
+ anonymous: false,
1669
+ inputs: [{ name: "message", type: "bytes", indexed: false }]
1670
+ }
1671
+ ];
1672
+
1673
+ // src/abi/usdc.ts
1674
+ var usdcAbi = [
1675
+ {
1676
+ type: "function",
1677
+ name: "balanceOf",
1678
+ stateMutability: "view",
1679
+ inputs: [{ name: "account", type: "address" }],
1680
+ outputs: [{ name: "balance", type: "uint256" }]
1681
+ },
1682
+ {
1683
+ type: "function",
1684
+ name: "allowance",
1685
+ stateMutability: "view",
1686
+ inputs: [
1687
+ { name: "owner", type: "address" },
1688
+ { name: "spender", type: "address" }
1689
+ ],
1690
+ outputs: [{ name: "remaining", type: "uint256" }]
1691
+ },
1692
+ {
1693
+ type: "function",
1694
+ name: "decimals",
1695
+ stateMutability: "view",
1696
+ inputs: [],
1697
+ outputs: [{ name: "", type: "uint8" }]
1698
+ },
1699
+ {
1700
+ type: "function",
1701
+ name: "approve",
1702
+ stateMutability: "nonpayable",
1703
+ inputs: [
1704
+ { name: "spender", type: "address" },
1705
+ { name: "value", type: "uint256" }
1706
+ ],
1707
+ outputs: [{ name: "", type: "bool" }]
1708
+ },
1709
+ {
1710
+ type: "function",
1711
+ name: "transfer",
1712
+ stateMutability: "nonpayable",
1713
+ inputs: [
1714
+ { name: "to", type: "address" },
1715
+ { name: "value", type: "uint256" }
1716
+ ],
1717
+ outputs: [{ name: "", type: "bool" }]
1718
+ },
1719
+ {
1720
+ type: "function",
1721
+ name: "nonces",
1722
+ stateMutability: "view",
1723
+ inputs: [{ name: "owner", type: "address" }],
1724
+ outputs: [{ name: "", type: "uint256" }]
1725
+ },
1726
+ {
1727
+ type: "function",
1728
+ name: "DOMAIN_SEPARATOR",
1729
+ stateMutability: "view",
1730
+ inputs: [],
1731
+ outputs: [{ name: "", type: "bytes32" }]
1732
+ },
1733
+ {
1734
+ type: "function",
1735
+ name: "permit",
1736
+ stateMutability: "nonpayable",
1737
+ inputs: [
1738
+ { name: "owner", type: "address" },
1739
+ { name: "spender", type: "address" },
1740
+ { name: "value", type: "uint256" },
1741
+ { name: "deadline", type: "uint256" },
1742
+ { name: "v", type: "uint8" },
1743
+ { name: "r", type: "bytes32" },
1744
+ { name: "s", type: "bytes32" }
1745
+ ],
1746
+ outputs: []
1747
+ },
1748
+ {
1749
+ type: "event",
1750
+ name: "Transfer",
1751
+ anonymous: false,
1752
+ inputs: [
1753
+ { name: "from", type: "address", indexed: true },
1754
+ { name: "to", type: "address", indexed: true },
1755
+ { name: "value", type: "uint256", indexed: false }
1756
+ ]
1757
+ },
1758
+ {
1759
+ type: "event",
1760
+ name: "Approval",
1761
+ anonymous: false,
1762
+ inputs: [
1763
+ { name: "owner", type: "address", indexed: true },
1764
+ { name: "spender", type: "address", indexed: true },
1765
+ { name: "value", type: "uint256", indexed: false }
1766
+ ]
1767
+ }
1768
+ ];
1769
+
1770
+ // src/abi/tokenMessengerWithFees.ts
1771
+ var tokenMessengerWithFeesAbi = [
1772
+ {
1773
+ type: "function",
1774
+ name: "depositForBurnWithFees",
1775
+ stateMutability: "payable",
1776
+ inputs: [
1777
+ { name: "amount", type: "uint256" },
1778
+ { name: "destinationDomain", type: "uint32" },
1779
+ { name: "mintRecipient", type: "bytes32" },
1780
+ { name: "burnToken", type: "address" },
1781
+ { name: "destinationCaller", type: "bytes32" },
1782
+ {
1783
+ name: "claim",
1784
+ type: "tuple",
1785
+ components: [
1786
+ { name: "signedQuote", type: "bytes" },
1787
+ { name: "refundAddress", type: "address" }
1788
+ ]
1789
+ }
1790
+ ],
1791
+ outputs: []
1792
+ },
1793
+ {
1794
+ type: "function",
1795
+ name: "getFee",
1796
+ stateMutability: "pure",
1797
+ inputs: [{ name: "signedQuote", type: "bytes" }],
1798
+ outputs: [
1799
+ { name: "totalFee", type: "uint256" },
1800
+ { name: "feeToken", type: "address" }
1801
+ ]
1802
+ },
1803
+ {
1804
+ type: "function",
1805
+ name: "tokenMessenger",
1806
+ stateMutability: "view",
1807
+ inputs: [],
1808
+ outputs: [{ name: "", type: "address" }]
1809
+ }
1810
+ ];
1811
+
1812
+ // src/iris/urls.ts
1813
+ var IRIS_MAINNET_URL = "https://iris-api.circle.com";
1814
+ var IRIS_SANDBOX_URL = "https://iris-api-sandbox.circle.com";
1815
+ function irisBaseUrl(network) {
1816
+ return network === "mainnet" ? IRIS_MAINNET_URL : IRIS_SANDBOX_URL;
1817
+ }
1818
+
1819
+ // src/iris/limiter.ts
1820
+ function createIrisLimiter(options = {}) {
1821
+ const rate = options.ratePerSecond ?? 30;
1822
+ const standDownMs = options.standDownMs ?? 5 * 6e4;
1823
+ const now = options.now ?? (() => Date.now());
1824
+ const sleep3 = options.sleep ?? ((ms) => new Promise((resolve) => setTimeout(resolve, ms)));
1825
+ const buckets = /* @__PURE__ */ new Map();
1826
+ const bucket = (host) => {
1827
+ let b = buckets.get(host);
1828
+ if (!b) {
1829
+ b = { tokens: rate, updatedAt: now(), blockedUntil: 0 };
1830
+ buckets.set(host, b);
1831
+ }
1832
+ return b;
1833
+ };
1834
+ return {
1835
+ async acquire(host) {
1836
+ const b = bucket(host);
1837
+ if (now() < b.blockedUntil) {
1838
+ throw new IrisRateLimitedError(host, b.blockedUntil);
1839
+ }
1840
+ const elapsed = (now() - b.updatedAt) / 1e3;
1841
+ b.tokens = Math.min(rate, b.tokens + elapsed * rate);
1842
+ b.updatedAt = now();
1843
+ if (b.tokens < 1) {
1844
+ const waitMs = Math.ceil((1 - b.tokens) / rate * 1e3);
1845
+ await sleep3(waitMs);
1846
+ b.tokens += waitMs / 1e3 * rate;
1847
+ b.updatedAt = now();
1848
+ }
1849
+ b.tokens -= 1;
1850
+ },
1851
+ standDown(host) {
1852
+ const b = bucket(host);
1853
+ b.blockedUntil = now() + standDownMs;
1854
+ return b.blockedUntil;
1855
+ },
1856
+ now,
1857
+ sleep: sleep3
1858
+ };
1859
+ }
1860
+ var defaultIrisLimiter = createIrisLimiter();
1861
+
1862
+ // src/iris/fetch.ts
1863
+ var DEFAULT_TIMEOUT_MS = 5e3;
1864
+ var DEFAULT_MAX_RETRIES = 3;
1865
+ var DEFAULT_BASE_DELAY_MS = 300;
1866
+ async function fetchIrisJson(url, options = {}, request = {
1867
+ method: "GET"
1868
+ }) {
1869
+ const {
1870
+ timeoutMs = DEFAULT_TIMEOUT_MS,
1871
+ maxRetries = DEFAULT_MAX_RETRIES,
1872
+ baseDelayMs = DEFAULT_BASE_DELAY_MS,
1873
+ signal,
1874
+ fetch: fetchImpl = fetch,
1875
+ limiter = defaultIrisLimiter
1876
+ } = options;
1877
+ const host = new URL(url).host;
1878
+ let lastError;
1879
+ for (let attempt = 0; attempt <= maxRetries; attempt++) {
1880
+ if (signal?.aborted) throw new IrisAbortedError("Aborted by caller");
1881
+ await limiter.acquire(host);
1882
+ const ctrl = new AbortController();
1883
+ const timer = setTimeout(() => ctrl.abort(), timeoutMs);
1884
+ const onCallerAbort = () => ctrl.abort();
1885
+ signal?.addEventListener("abort", onCallerAbort);
1886
+ try {
1887
+ const res = await fetchImpl(url, {
1888
+ method: request.method,
1889
+ headers: {
1890
+ accept: "application/json",
1891
+ ...request.method === "POST" && {
1892
+ "content-type": "application/json"
1893
+ }
1894
+ },
1895
+ ...request.method === "POST" && {
1896
+ body: JSON.stringify(request.body)
1897
+ },
1898
+ signal: ctrl.signal
1899
+ });
1900
+ if (res.ok) {
1901
+ let json;
1902
+ try {
1903
+ json = await res.json();
1904
+ } catch (err) {
1905
+ throw new IrisParseError(`Invalid JSON from ${url}`, err);
1906
+ }
1907
+ return json;
1908
+ }
1909
+ if (res.status === 429) {
1910
+ throw new IrisRateLimitedError(host, limiter.standDown(host));
1911
+ }
1912
+ if (res.status >= 400 && res.status < 500 && res.status !== 429) {
1913
+ throw new IrisHttpError(res.status, url, await safeText(res));
1914
+ }
1915
+ lastError = new IrisHttpError(res.status, url, await safeText(res));
1916
+ } catch (err) {
1917
+ if (err instanceof IrisParseError) throw err;
1918
+ if (err instanceof IrisRateLimitedError) throw err;
1919
+ if (err instanceof IrisHttpError) {
1920
+ if (err.status < 500 && err.status !== 429) throw err;
1921
+ }
1922
+ if (signal?.aborted) throw new IrisAbortedError("Aborted by caller");
1923
+ lastError = err;
1924
+ } finally {
1925
+ clearTimeout(timer);
1926
+ signal?.removeEventListener("abort", onCallerAbort);
1927
+ }
1928
+ if (attempt < maxRetries) {
1929
+ await sleep(baseDelayMs * (attempt + 1), signal);
1930
+ }
1931
+ }
1932
+ if (lastError instanceof IrisHttpError) throw lastError;
1933
+ throw new IrisNetworkError(
1934
+ `Iris request failed after ${maxRetries + 1} attempts`,
1935
+ lastError
1936
+ );
1937
+ }
1938
+ async function safeText(res) {
1939
+ try {
1940
+ return await res.text();
1941
+ } catch {
1942
+ return "";
1943
+ }
1944
+ }
1945
+ function sleep(ms, signal) {
1946
+ return new Promise((resolve, reject) => {
1947
+ if (signal?.aborted) {
1948
+ reject(new IrisAbortedError("Aborted by caller"));
1949
+ return;
1950
+ }
1951
+ const timer = setTimeout(() => {
1952
+ signal?.removeEventListener("abort", onAbort);
1953
+ resolve();
1954
+ }, ms);
1955
+ function onAbort() {
1956
+ clearTimeout(timer);
1957
+ reject(new IrisAbortedError("Aborted by caller"));
1958
+ }
1959
+ signal?.addEventListener("abort", onAbort);
1960
+ });
1961
+ }
1962
+
1963
+ // src/iris/types.ts
1964
+ var FINALITY_FAST = 1e3;
1965
+ var FINALITY_STANDARD = 2e3;
1966
+
1967
+ // src/fees/math.ts
1968
+ var CENTI_BPS_PER_UNIT = 1000000n;
1969
+ var DECIMAL = /^(\d+)(?:\.(\d+))?$/;
1970
+ function ceilDecimal(raw, decimals, what) {
1971
+ const text = typeof raw === "number" ? String(raw) : typeof raw === "string" ? raw : "";
1972
+ const match = DECIMAL.exec(text);
1973
+ if (!match) {
1974
+ throw new IrisParseError(`Iris ${what} is invalid: ${String(raw)}`);
1975
+ }
1976
+ const fraction = match[2] ?? "";
1977
+ const kept = fraction.slice(0, decimals).padEnd(decimals, "0");
1978
+ const dropped = /[1-9]/.test(fraction.slice(decimals)) ? 1n : 0n;
1979
+ return BigInt((match[1] ?? "0") + kept) + dropped;
1980
+ }
1981
+ function parseFeeBps(raw) {
1982
+ return ceilDecimal(raw, 2, "minimumFee");
1983
+ }
1984
+ function parseForwarderFee(raw) {
1985
+ return ceilDecimal(raw, 0, "forwardFee");
1986
+ }
1987
+ function computeBurnFee(amount, feeCentiBps) {
1988
+ if (amount < 0n) {
1989
+ throw new InvalidInputError(
1990
+ "invalid_amount",
1991
+ `amount must be non-negative, got ${amount}`
1992
+ );
1993
+ }
1994
+ if (feeCentiBps < 0n) {
1995
+ throw new InvalidInputError(
1996
+ "invalid_input",
1997
+ `feeCentiBps must be non-negative, got ${feeCentiBps}`
1998
+ );
1999
+ }
2000
+ return ceilDiv(amount * feeCentiBps, CENTI_BPS_PER_UNIT);
2001
+ }
2002
+ function selectForwarderFee(tier, level = "med") {
2003
+ if (!tier.forwardFee) {
2004
+ throw new ProtocolError(
2005
+ "fee_unavailable",
2006
+ "Tier has no forwardFee. Fetch burn fees with includeForwarderFee=true"
2007
+ );
2008
+ }
2009
+ const value = tier.forwardFee[level];
2010
+ if (value < 0n) {
2011
+ throw new ProtocolError(
2012
+ "fee_unavailable",
2013
+ `Invalid forwardFee.${level}: ${value}`
2014
+ );
2015
+ }
2016
+ return value;
2017
+ }
2018
+ function computeMaxFee(input) {
2019
+ const {
2020
+ amount,
2021
+ tier,
2022
+ forwarderLevel = "med",
2023
+ forwarderBufferBps = 0,
2024
+ includeForwarder = true,
2025
+ burnFeeBufferBps = 0,
2026
+ minBurnFee = 0n
2027
+ } = input;
2028
+ const irisFee = computeBurnFee(amount, tier.minimumFee);
2029
+ const burnFee = irisFee > minBurnFee ? irisFee : minBurnFee;
2030
+ const forwarderFee = includeForwarder ? applyBufferBps(
2031
+ selectForwarderFee(tier, forwarderLevel),
2032
+ forwarderBufferBps
2033
+ ) : 0n;
2034
+ return {
2035
+ burnFee,
2036
+ forwarderFee,
2037
+ maxFee: applyBufferBps(burnFee, burnFeeBufferBps) + forwarderFee
2038
+ };
2039
+ }
2040
+ function applyBufferBps(value, bps) {
2041
+ if (!Number.isSafeInteger(bps) || bps < 0) {
2042
+ throw new InvalidInputError(
2043
+ "invalid_input",
2044
+ `bufferBps must be a non-negative whole number, got ${bps}`
2045
+ );
2046
+ }
2047
+ return ceilDiv(value * (10000n + BigInt(bps)), 10000n);
2048
+ }
2049
+ function ceilDiv(numerator, denominator) {
2050
+ return (numerator + denominator - 1n) / denominator;
2051
+ }
2052
+
2053
+ // src/iris/fees.ts
2054
+ async function getBurnFees(network, sourceDomain, destinationDomain, options = {}) {
2055
+ const { includeForwarderFee = true, ...fetchOpts } = options;
2056
+ const base = irisBaseUrl(network);
2057
+ const url = new URL(
2058
+ `${base}/v2/burn/USDC/fees/${sourceDomain}/${destinationDomain}`
2059
+ );
2060
+ if (includeForwarderFee) url.searchParams.set("forward", "true");
2061
+ const raw = await fetchIrisJson(url.toString(), fetchOpts);
2062
+ if (!Array.isArray(raw)) {
2063
+ throw new IrisParseError("Iris burn-fees response is not an array");
2064
+ }
2065
+ return raw.map((row) => normalizeTier(row)).filter((t) => t !== null);
2066
+ }
2067
+ function normalizeTier(row) {
2068
+ if (!row || typeof row !== "object") {
2069
+ throw new IrisParseError("Iris fee tier is not an object");
2070
+ }
2071
+ const r = row;
2072
+ const threshold = r.finalityThreshold;
2073
+ if (threshold !== FINALITY_FAST && threshold !== FINALITY_STANDARD) {
2074
+ return null;
2075
+ }
2076
+ const out = {
2077
+ finalityThreshold: threshold,
2078
+ minimumFee: parseFeeBps(r.minimumFee)
2079
+ };
2080
+ if (r.forwardFee && typeof r.forwardFee === "object") {
2081
+ const ff = r.forwardFee;
2082
+ out.forwardFee = {
2083
+ low: parseForwarderFee(ff.low),
2084
+ med: parseForwarderFee(ff.med),
2085
+ high: parseForwarderFee(ff.high)
2086
+ };
2087
+ }
2088
+ return out;
2089
+ }
2090
+ function pickFeeTier(tiers, speed) {
2091
+ const threshold = speed === "fast" ? FINALITY_FAST : FINALITY_STANDARD;
2092
+ const tier = tiers.find((t) => t.finalityThreshold === threshold);
2093
+ if (!tier) {
2094
+ throw new ProtocolError(
2095
+ "tier_not_found",
2096
+ `Iris returned no ${speed === "fast" ? "Fast" : "Standard"} Transfer fee for this route.`
2097
+ );
2098
+ }
2099
+ return tier;
2100
+ }
2101
+ function pickForwarderFee(tier, level = "med") {
2102
+ return selectForwarderFee(tier, level);
2103
+ }
2104
+
2105
+ // src/iris/messages.ts
2106
+ async function getMessages(query, options) {
2107
+ const { network, baseUrl, ...fetchOpts } = options;
2108
+ const base = (baseUrl ?? irisBaseUrl(network)).replace(/\/+$/, "");
2109
+ const url = new URL(`${base}/v2/messages/${query.sourceDomain}`);
2110
+ if (query.transactionHash) {
2111
+ url.searchParams.set("transactionHash", query.transactionHash);
2112
+ }
2113
+ if (query.nonce) {
2114
+ url.searchParams.set("nonce", query.nonce);
2115
+ }
2116
+ try {
2117
+ const json = await fetchIrisJson(
2118
+ url.toString(),
2119
+ fetchOpts
2120
+ );
2121
+ return json.messages ?? [];
2122
+ } catch (err) {
2123
+ if (err instanceof IrisHttpError && err.status === 404) {
2124
+ return [];
2125
+ }
2126
+ throw err;
2127
+ }
2128
+ }
2129
+ var DEFAULT_INTERVAL_MS = 3e3;
2130
+ var DEFAULT_TIMEOUT_MS2 = 15 * 60 * 1e3;
2131
+ var TIMEOUT_MARGIN_MS = 5 * 60 * 1e3;
2132
+ function pollBudget(eta) {
2133
+ const intervalMs = eta.max <= 60 ? 2e3 : eta.max <= 30 * 60 ? 1e4 : 3e4;
2134
+ return { intervalMs, timeoutMs: eta.max * 2 * 1e3 + TIMEOUT_MARGIN_MS };
2135
+ }
2136
+ function isForwardDone(message) {
2137
+ return (message.forwardState === "CONFIRMED" || message.forwardState === "COMPLETE") && !!message.forwardTxHash;
2138
+ }
2139
+ function defaultIsDone(message) {
2140
+ if (message.forwardState != null) {
2141
+ return isForwardDone(message) || message.forwardState === "FAILED";
2142
+ }
2143
+ return message.status === "complete";
2144
+ }
2145
+ async function pollMessages(query, options) {
2146
+ const {
2147
+ intervalMs = DEFAULT_INTERVAL_MS,
2148
+ timeoutMs = DEFAULT_TIMEOUT_MS2,
2149
+ isDone = defaultIsDone,
2150
+ onRateLimited,
2151
+ signal,
2152
+ ...rest
2153
+ } = options;
2154
+ const limiter = rest.limiter ?? defaultIrisLimiter;
2155
+ let deadline = limiter.now() + timeoutMs;
2156
+ let latest = null;
2157
+ while (limiter.now() < deadline) {
2158
+ if (signal?.aborted) throw new IrisAbortedError("Aborted by caller");
2159
+ let messages;
2160
+ try {
2161
+ messages = await getMessages(query, { ...rest, signal });
2162
+ } catch (err) {
2163
+ if (!(err instanceof IrisRateLimitedError)) throw err;
2164
+ onRateLimited?.(err.retryAt);
2165
+ const waitMs = Math.max(0, err.retryAt - limiter.now());
2166
+ deadline += waitMs;
2167
+ await limiter.sleep(waitMs);
2168
+ continue;
2169
+ }
2170
+ if (messages.length > 0) {
2171
+ const first = messages[0];
2172
+ if (first) {
2173
+ latest = first;
2174
+ if (isDone(first)) return first;
2175
+ }
2176
+ }
2177
+ await sleep2(intervalMs, signal);
2178
+ }
2179
+ return latest;
2180
+ }
2181
+ function sleep2(ms, signal) {
2182
+ return new Promise((resolve, reject) => {
2183
+ if (signal?.aborted) {
2184
+ reject(new IrisAbortedError("Aborted by caller"));
2185
+ return;
2186
+ }
2187
+ const timer = setTimeout(() => {
2188
+ signal?.removeEventListener("abort", onAbort);
2189
+ resolve();
2190
+ }, ms);
2191
+ function onAbort() {
2192
+ clearTimeout(timer);
2193
+ reject(new IrisAbortedError("Aborted by caller"));
2194
+ }
2195
+ signal?.addEventListener("abort", onAbort);
2196
+ });
2197
+ }
2198
+
2199
+ // src/iris/reattest.ts
2200
+ async function reattest(nonce, options) {
2201
+ const { network, ...fetchOpts } = options;
2202
+ const url = `${irisBaseUrl(network)}/v2/reattest/${nonce}`;
2203
+ let json;
2204
+ try {
2205
+ json = await fetchIrisJson(url, fetchOpts, {
2206
+ method: "POST",
2207
+ body: {}
2208
+ });
2209
+ } catch (err) {
2210
+ if (err instanceof IrisHttpError && err.status === 404) return null;
2211
+ throw err;
2212
+ }
2213
+ const acknowledged = typeof json === "object" && json !== null && "nonce" in json ? json.nonce : void 0;
2214
+ if (typeof acknowledged !== "string") {
2215
+ throw new IrisParseError("Iris reattest reply has no nonce");
2216
+ }
2217
+ return { nonce: acknowledged };
2218
+ }
2219
+
2220
+ // src/iris/quote.ts
2221
+ async function getSignedBurnQuote(network, sourceDomain, destinationDomain, request, options = {}) {
2222
+ const url = `${irisBaseUrl(network)}/v2/quote/burn/usdc/${sourceDomain}/${destinationDomain}`;
2223
+ const raw = await fetchIrisJson(url, options, {
2224
+ method: "POST",
2225
+ body: {
2226
+ amount: request.amount.toString(),
2227
+ feeToken: request.feeToken,
2228
+ requests: request.requests.map((type) => ({ type }))
2229
+ }
2230
+ });
2231
+ const quote = parseQuote(raw);
2232
+ if (quote.burnAmount !== void 0 && quote.burnAmount !== request.amount) {
2233
+ throw new IrisParseError(
2234
+ `Iris quoted ${quote.burnAmount} subunits, not the ${request.amount} requested`
2235
+ );
2236
+ }
2237
+ if (quote.feeToken.toLowerCase() !== request.feeToken.toLowerCase()) {
2238
+ throw new IrisParseError(
2239
+ `Iris priced the fee in ${quote.feeToken}, not ${request.feeToken}`
2240
+ );
2241
+ }
2242
+ const types = quote.items.map((i) => i.type).sort();
2243
+ if (types.join() !== [...request.requests].sort().join()) {
2244
+ throw new IrisParseError(
2245
+ `Iris priced ${types.join(", ")}, not ${request.requests.join(", ")}`
2246
+ );
2247
+ }
2248
+ return quote;
2249
+ }
2250
+ function parseQuote(raw) {
2251
+ const fail = (what) => {
2252
+ throw new IrisParseError(`Iris quote: ${what}`);
2253
+ };
2254
+ if (typeof raw !== "object" || raw === null) return fail("not an object");
2255
+ const r = raw;
2256
+ const signedQuote = r.signedQuote;
2257
+ if (typeof signedQuote !== "string" || !/^0x([0-9a-fA-F]{2})+$/.test(signedQuote)) {
2258
+ return fail("signedQuote is not hex bytes");
2259
+ }
2260
+ if (!Number.isSafeInteger(r.issuedAt))
2261
+ return fail("issuedAt is not a timestamp");
2262
+ const feeToken = r.feeToken;
2263
+ if (typeof feeToken !== "string" || !/^0x[0-9a-fA-F]{40}$/.test(feeToken)) {
2264
+ return fail("feeToken is not an address");
2265
+ }
2266
+ const feeTotalAmount = subunits(r.feeTotalAmount) ?? fail("feeTotalAmount");
2267
+ const burnAmount = r.burnAmount === void 0 ? void 0 : subunits(r.burnAmount) ?? fail("burnAmount");
2268
+ if (!Array.isArray(r.items) || r.items.length === 0) return fail("no items");
2269
+ const items = r.items.map(
2270
+ (item) => {
2271
+ const i = item ?? {};
2272
+ if (i.type !== "FORWARD" && i.type !== "PRE_FINALITY") {
2273
+ return fail(`unknown item type ${String(i.type)}`);
2274
+ }
2275
+ return {
2276
+ type: i.type,
2277
+ amount: subunits(i.amount) ?? fail("item amount")
2278
+ };
2279
+ }
2280
+ );
2281
+ if (items.reduce((sum, i) => sum + i.amount, 0n) !== feeTotalAmount) {
2282
+ return fail("items do not add up to feeTotalAmount");
2283
+ }
2284
+ return {
2285
+ signedQuote,
2286
+ issuedAt: r.issuedAt,
2287
+ expiry: parseExpiry(r.expiry) ?? fail("expiry"),
2288
+ feeTotalAmount,
2289
+ feeToken,
2290
+ ...burnAmount !== void 0 && { burnAmount },
2291
+ items
2292
+ };
2293
+ }
2294
+ function parseExpiry(raw) {
2295
+ if (typeof raw !== "object" || raw === null) return void 0;
2296
+ const e = raw;
2297
+ if (e.mode === "TIMESTAMP" && Number.isSafeInteger(e.expiresAt)) {
2298
+ return { mode: "TIMESTAMP", expiresAt: e.expiresAt };
2299
+ }
2300
+ if (e.mode === "BLOCK_NUMBER" && Number.isSafeInteger(e.expiresAtBlock)) {
2301
+ return {
2302
+ mode: "BLOCK_NUMBER",
2303
+ expiresAtBlock: BigInt(e.expiresAtBlock)
2304
+ };
2305
+ }
2306
+ return void 0;
2307
+ }
2308
+ function subunits(raw) {
2309
+ return typeof raw === "string" && /^(0|[1-9]\d*)$/.test(raw) ? BigInt(raw) : void 0;
2310
+ }
2311
+ async function getFastBurnAllowance(network, options = {}) {
2312
+ const raw = await fetchIrisJson(
2313
+ `${irisBaseUrl(network)}/v2/fastBurn/USDC/allowance`,
2314
+ options
2315
+ );
2316
+ const value = typeof raw === "object" && raw !== null && "allowance" in raw ? raw.allowance : void 0;
2317
+ if (typeof value !== "number" || !Number.isFinite(value) || value < 0) {
2318
+ throw new IrisParseError("Iris allowance is not a non-negative number");
2319
+ }
2320
+ const match = /^(\d+)(?:\.(\d+))?$/.exec(String(value));
2321
+ if (!match)
2322
+ throw new IrisParseError(`Iris allowance ${value} is not decimal`);
2323
+ const frac = (match[2] ?? "").padEnd(6, "0").slice(0, 6);
2324
+ return BigInt(match[1]) * 1000000n + BigInt(frac);
2325
+ }
2326
+
2327
+ // src/rpc/jsonRpc.ts
2328
+ async function callRpc(chain, method, params, parse, options = {}, parseError) {
2329
+ const doFetch = options.fetch ?? globalThis.fetch;
2330
+ const body = JSON.stringify({ jsonrpc: "2.0", id: 1, method, params });
2331
+ const urls = [...options.rpcUrls ?? [], ...chain.defaultRpcUrls];
2332
+ const failures = [];
2333
+ for (let i = 0, behind = 0; i < urls.length; i++) {
2334
+ const url = urls[i];
2335
+ try {
2336
+ const res = await doFetch(url, {
2337
+ method: "POST",
2338
+ headers: { "content-type": "application/json" },
2339
+ body
2340
+ });
2341
+ if (!res.ok) {
2342
+ failures.push(`${url}: HTTP ${res.status}`);
2343
+ continue;
2344
+ }
2345
+ const payload = await res.json();
2346
+ const result = typeof payload === "object" && payload !== null && "result" in payload ? parse(payload.result) : void 0;
2347
+ if (result !== void 0) return result;
2348
+ const answer = parseError?.(errorCode(payload));
2349
+ if (answer !== void 0) return answer;
2350
+ failures.push(`${url}: ${JSON.stringify(payload)}`);
2351
+ if (errorCode(payload) === LAGGING_BACKEND && behind < LAG_RETRIES) {
2352
+ behind += 1;
2353
+ await new Promise((resolve) => setTimeout(resolve, 250 * behind));
2354
+ i -= 1;
2355
+ continue;
2356
+ }
2357
+ behind = 0;
2358
+ } catch (err) {
2359
+ failures.push(
2360
+ `${url}: ${err instanceof Error ? err.message : String(err)}`
2361
+ );
2362
+ }
2363
+ }
2364
+ throw new ProtocolError(
2365
+ "rpc_unavailable",
2366
+ `${method} on ${chain.id} failed: ${failures.join("; ")}`
2367
+ );
2368
+ }
2369
+ var LAGGING_BACKEND = -32014;
2370
+ var LAG_RETRIES = 3;
2371
+ function errorCode(payload) {
2372
+ if (typeof payload !== "object" || payload === null) return void 0;
2373
+ const error = payload.error;
2374
+ return error?.code;
2375
+ }
2376
+ async function getGasPrice(chain, options = {}) {
2377
+ return callRpc(
2378
+ chain,
2379
+ "eth_gasPrice",
2380
+ [],
2381
+ (r) => typeof r === "string" && /^0x[0-9a-fA-F]+$/.test(r) ? BigInt(r) : void 0,
2382
+ options
2383
+ );
2384
+ }
2385
+ async function getBlockNumber(chain, options = {}) {
2386
+ return callRpc(
2387
+ chain,
2388
+ "eth_blockNumber",
2389
+ [],
2390
+ (r) => typeof r === "string" && /^0x[0-9a-fA-F]+$/.test(r) ? BigInt(r) : void 0,
2391
+ options
2392
+ );
2393
+ }
2394
+ var USED_NONCES = "0xfeb61724";
2395
+ async function isNonceUsed(chain, nonce, options = {}) {
2396
+ if (!/^0x[0-9a-fA-F]{64}$/.test(nonce)) {
2397
+ throw new ProtocolError("rpc_unavailable", `nonce ${nonce} is not bytes32`);
2398
+ }
2399
+ return callRpc(
2400
+ chain,
2401
+ "eth_call",
2402
+ [
2403
+ { to: chain.messageTransmitter, data: `${USED_NONCES}${nonce.slice(2)}` },
2404
+ "latest"
2405
+ ],
2406
+ (r) => typeof r === "string" && /^0x[0-9a-fA-F]{64}$/.test(r) ? BigInt(r) !== 0n : void 0,
2407
+ options
2408
+ );
2409
+ }
2410
+ async function getTransactionStatus(chain, hash2, options = {}) {
2411
+ return callRpc(
2412
+ chain,
2413
+ "eth_getTransactionReceipt",
2414
+ [hash2],
2415
+ (r) => {
2416
+ if (r === null) return "unknown";
2417
+ if (typeof r !== "object") return void 0;
2418
+ const status = r.status;
2419
+ if (status === "0x1") return "success";
2420
+ if (status === "0x0") return "reverted";
2421
+ return void 0;
2422
+ },
2423
+ options
2424
+ );
2425
+ }
2426
+ var BALANCE_OF = "0x70a08231";
2427
+ async function getUsdcBalance(chain, owner, options = {}) {
2428
+ if (!/^0x[0-9a-fA-F]{40}$/.test(owner)) {
2429
+ throw new ProtocolError("rpc_unavailable", `${owner} is not an address`);
2430
+ }
2431
+ return callRpc(
2432
+ chain,
2433
+ "eth_call",
2434
+ [
2435
+ {
2436
+ to: chain.usdc,
2437
+ data: `${BALANCE_OF}${owner.slice(2).padStart(64, "0")}`
2438
+ },
2439
+ "latest"
2440
+ ],
2441
+ (r) => typeof r === "string" && /^0x[0-9a-fA-F]{64}$/.test(r) ? BigInt(r) : void 0,
2442
+ options
2443
+ );
2444
+ }
2445
+ var IS_NONCE_USED_SELECTOR = starknet.hash.getSelectorFromName("is_nonce_used");
2446
+ function bytes32(nonce) {
2447
+ if (!/^0x[0-9a-fA-F]{64}$/.test(nonce)) {
2448
+ throw new ProtocolError("rpc_unavailable", `nonce ${nonce} is not bytes32`);
2449
+ }
2450
+ return nonce.slice(2).toLowerCase();
2451
+ }
2452
+ async function isStarknetNonceUsed(chain, nonce, options = {}) {
2453
+ const hex = bytes32(nonce);
2454
+ return callRpc(
2455
+ chain,
2456
+ "starknet_call",
2457
+ {
2458
+ request: {
2459
+ contract_address: chain.messageTransmitter,
2460
+ entry_point_selector: IS_NONCE_USED_SELECTOR,
2461
+ // A u256 goes over the wire as its low then high 128 bits.
2462
+ calldata: [`0x${hex.slice(32)}`, `0x${hex.slice(0, 32)}`]
2463
+ },
2464
+ // Public Starknet RPCs reject the "pending" tag starknet.js defaults to.
2465
+ block_id: "latest"
2466
+ },
2467
+ (r) => Array.isArray(r) && (r[0] === "0x0" || r[0] === "0x1") ? r[0] === "0x1" : void 0,
2468
+ options
2469
+ );
2470
+ }
2471
+ async function isStellarNonceUsed(chain, nonce, options = {}) {
2472
+ const tx = new stellarSdk.TransactionBuilder(new stellarSdk.Account(chain.usdcIssuer, "0"), {
2473
+ fee: stellarSdk.BASE_FEE,
2474
+ networkPassphrase: chain.networkPassphrase
2475
+ }).addOperation(
2476
+ new stellarSdk.Contract(chain.messageTransmitter).call(
2477
+ "is_nonce_used",
2478
+ stellarSdk.nativeToScVal(Buffer.from(bytes32(nonce), "hex"), { type: "bytes" })
2479
+ )
2480
+ ).setTimeout(30).build();
2481
+ return callRpc(
2482
+ chain,
2483
+ "simulateTransaction",
2484
+ { transaction: tx.toXDR() },
2485
+ (r) => {
2486
+ const results = r?.results;
2487
+ const value = results?.[0]?.xdr;
2488
+ if (typeof value !== "string") return void 0;
2489
+ const used = stellarSdk.scValToNative(stellarSdk.xdr.ScVal.fromXDR(value, "base64"));
2490
+ return typeof used === "boolean" ? used : void 0;
2491
+ },
2492
+ options
2493
+ );
2494
+ }
2495
+
2496
+ // src/rpc/starknetClass.ts
2497
+ var CONTRACT_NOT_FOUND = 20;
2498
+ var FELT = /^0x[0-9a-fA-F]{1,64}$/;
2499
+ async function getStarknetClassHashAt(chain, address, options = {}) {
2500
+ return callRpc(
2501
+ chain,
2502
+ "starknet_getClassHashAt",
2503
+ { block_id: "latest", contract_address: address },
2504
+ (r) => typeof r === "string" && FELT.test(r) ? r : void 0,
2505
+ options,
2506
+ (code) => code === CONTRACT_NOT_FOUND ? null : void 0
2507
+ );
2508
+ }
2509
+
2510
+ // src/rpc/starknetTx.ts
2511
+ var TXN_HASH_NOT_FOUND = 29;
2512
+ var ACCEPTED = /* @__PURE__ */ new Set(["ACCEPTED_ON_L2", "ACCEPTED_ON_L1"]);
2513
+ var NOT_YET = /* @__PURE__ */ new Set(["RECEIVED", "CANDIDATE", "PRE_CONFIRMED"]);
2514
+ async function getStarknetTransactionStatus(chain, hash2, options = {}) {
2515
+ return callRpc(
2516
+ chain,
2517
+ "starknet_getTransactionReceipt",
2518
+ { transaction_hash: hash2 },
2519
+ (r) => {
2520
+ if (typeof r !== "object" || r === null) return void 0;
2521
+ const { finality_status, execution_status, block_number } = r;
2522
+ if (typeof finality_status !== "string") return void 0;
2523
+ if (NOT_YET.has(finality_status)) return { state: "pending" };
2524
+ if (!ACCEPTED.has(finality_status)) return void 0;
2525
+ if (typeof block_number !== "number") return void 0;
2526
+ if (execution_status === "SUCCEEDED") {
2527
+ return { state: "success", blockNumber: block_number };
2528
+ }
2529
+ if (execution_status === "REVERTED") {
2530
+ return { state: "reverted", blockNumber: block_number };
2531
+ }
2532
+ return void 0;
2533
+ },
2534
+ options,
2535
+ (code) => code === TXN_HASH_NOT_FOUND ? { state: "pending" } : void 0
2536
+ );
2537
+ }
2538
+
2539
+ // src/forwarder/hookData.ts
2540
+ var CCTP_FORWARD_HOOK_DATA = "0x636374702d666f72776172640000000000000000000000000000000000000000";
2541
+ var CCTP_FORWARD_HOOK_DATA_LENGTH = 32;
2542
+ var MAGIC_PREFIX = "cctp-forward";
2543
+ var VERSION = 0;
2544
+ var PAYLOAD_LENGTH = 0;
2545
+ function buildForwarderHookData() {
2546
+ const buf = new Uint8Array(CCTP_FORWARD_HOOK_DATA_LENGTH);
2547
+ const encoder = new TextEncoder();
2548
+ buf.set(encoder.encode(MAGIC_PREFIX), 0);
2549
+ const view = new DataView(buf.buffer);
2550
+ view.setUint32(24, VERSION, false);
2551
+ view.setUint32(28, PAYLOAD_LENGTH, false);
2552
+ return bytesToHex(buf);
2553
+ }
2554
+ function isForwarderHookData(hex) {
2555
+ if (!hex.startsWith("0x")) return false;
2556
+ return hex.toLowerCase().startsWith(
2557
+ "0x636374702d666f72776172640000000000000000000000000000000000000000"
2558
+ );
2559
+ }
2560
+ var ANY_DESTINATION_CALLER = "0x0000000000000000000000000000000000000000000000000000000000000000";
2561
+ function bytesToHex(bytes) {
2562
+ let out = "0x";
2563
+ for (let i = 0; i < bytes.length; i++) {
2564
+ const byte = bytes[i];
2565
+ if (byte === void 0) continue;
2566
+ out += byte.toString(16).padStart(2, "0");
2567
+ }
2568
+ return out;
2569
+ }
2570
+
2571
+ // src/encoding/address.ts
2572
+ var ADDRESS_REGEX = /^0x[0-9a-fA-F]{40}$/;
2573
+ var InvalidAddressError = class extends InvalidInputError {
2574
+ constructor(input) {
2575
+ super("invalid_address", `Invalid EVM address: ${input}`);
2576
+ this.name = "InvalidAddressError";
2577
+ }
2578
+ };
2579
+ var InvalidBytes32Error = class extends InvalidInputError {
2580
+ constructor(input) {
2581
+ super("invalid_bytes32", `Invalid bytes32 value: ${input}`);
2582
+ this.name = "InvalidBytes32Error";
2583
+ }
2584
+ };
2585
+ function toBytes32(address) {
2586
+ if (!ADDRESS_REGEX.test(address)) {
2587
+ throw new InvalidAddressError(address);
2588
+ }
2589
+ const hex = address.slice(2).toLowerCase();
2590
+ return `0x${"00".repeat(12)}${hex}`;
2591
+ }
2592
+ function fromBytes32(value) {
2593
+ const cleaned = value.toLowerCase();
2594
+ if (!/^0x[0-9a-f]{64}$/.test(cleaned)) {
2595
+ throw new InvalidBytes32Error(value);
2596
+ }
2597
+ const upper = cleaned.slice(2, 2 + 24);
2598
+ if (upper !== "00".repeat(12)) {
2599
+ throw new InvalidBytes32Error(
2600
+ `non-zero upper 12 bytes (not an EVM address): ${value}`
2601
+ );
2602
+ }
2603
+ return `0x${cleaned.slice(26)}`;
2604
+ }
2605
+ function tryFromBytes32(value) {
2606
+ try {
2607
+ return fromBytes32(value);
2608
+ } catch {
2609
+ return void 0;
2610
+ }
2611
+ }
2612
+ function isAddress(value) {
2613
+ return ADDRESS_REGEX.test(value);
2614
+ }
2615
+
2616
+ // src/fees/minFee.ts
2617
+ var GET_MIN_FEE_AMOUNT = "0x516990e3";
2618
+ async function getStandardMinFee(chain, amount, options = {}) {
2619
+ if (!chain.capabilities.standardFeeSwitch) {
2620
+ throw new InvalidInputError(
2621
+ "invalid_chain",
2622
+ `${chain.id} has no getMinFeeAmount; its TokenMessengerV2 reverts the call`
2623
+ );
2624
+ }
2625
+ if (amount < 0n) {
2626
+ throw new InvalidInputError(
2627
+ "invalid_amount",
2628
+ `amount must be non-negative, got ${amount}`
2629
+ );
2630
+ }
2631
+ return callRpc(
2632
+ chain,
2633
+ "eth_call",
2634
+ [
2635
+ {
2636
+ to: chain.tokenMessenger,
2637
+ data: `${GET_MIN_FEE_AMOUNT}${amount.toString(16).padStart(64, "0")}`
2638
+ },
2639
+ "latest"
2640
+ ],
2641
+ (r) => typeof r === "string" && /^0x[0-9a-fA-F]{64}$/.test(r) ? BigInt(r) : void 0,
2642
+ options
2643
+ );
2644
+ }
2645
+
2646
+ // src/message/decode.ts
2647
+ var HEADER_BYTES = 148;
2648
+ var BODY_BYTES = 228;
2649
+ function decodeBurnMessage(message) {
2650
+ if (!/^0x([0-9a-fA-F]{2})*$/.test(message)) {
2651
+ throw new InvalidInputError("invalid_input", "message is not hex bytes");
2652
+ }
2653
+ const hex = message.slice(2).toLowerCase();
2654
+ if (hex.length < (HEADER_BYTES + BODY_BYTES) * 2) {
2655
+ throw new InvalidInputError(
2656
+ "invalid_input",
2657
+ `a burn message is at least ${HEADER_BYTES + BODY_BYTES} bytes, got ${hex.length / 2}`
2658
+ );
2659
+ }
2660
+ let at = 0;
2661
+ const take = (bytes) => {
2662
+ const part = hex.slice(at, at + bytes * 2);
2663
+ at += bytes * 2;
2664
+ return part;
2665
+ };
2666
+ const uint = (bytes) => BigInt(`0x${take(bytes)}`);
2667
+ const word = () => `0x${take(32)}`;
2668
+ const small = (bytes) => Number.parseInt(take(bytes), 16);
2669
+ return {
2670
+ version: small(4),
2671
+ sourceDomain: small(4),
2672
+ destinationDomain: small(4),
2673
+ nonce: word(),
2674
+ sender: word(),
2675
+ recipient: word(),
2676
+ destinationCaller: word(),
2677
+ minFinalityThreshold: small(4),
2678
+ finalityThresholdExecuted: small(4),
2679
+ body: {
2680
+ version: small(4),
2681
+ burnToken: word(),
2682
+ mintRecipient: word(),
2683
+ amount: uint(32),
2684
+ messageSender: word(),
2685
+ maxFee: uint(32),
2686
+ feeExecuted: uint(32),
2687
+ expirationBlock: uint(32),
2688
+ hookData: `0x${hex.slice(at)}`
2689
+ }
2690
+ };
2691
+ }
2692
+ function encodeMintRecipient(destination, mintRecipient) {
2693
+ if (destination.ecosystem === "solana") {
2694
+ try {
2695
+ new web3_js.PublicKey(mintRecipient);
2696
+ } catch {
2697
+ throw new InvalidInputError(
2698
+ "invalid_address",
2699
+ `mintRecipient is not a valid Solana pubkey: ${mintRecipient}`
2700
+ );
2701
+ }
2702
+ } else if (destination.ecosystem === "stellar") {
2703
+ if (!/^0x[a-fA-F0-9]{64}$/.test(mintRecipient)) {
2704
+ throw new InvalidInputError(
2705
+ "invalid_address",
2706
+ `mintRecipient for Stellar must be 0x-prefixed 32-byte hex (the CctpForwarder strkey decoded); got: ${mintRecipient}`
2707
+ );
2708
+ }
2709
+ } else if (destination.ecosystem === "starknet") {
2710
+ if (!/^0x[a-fA-F0-9]{64}$/.test(mintRecipient)) {
2711
+ throw new InvalidInputError(
2712
+ "invalid_address",
2713
+ `mintRecipient for Starknet must be 0x-prefixed 32-byte hex; got: ${mintRecipient}`
2714
+ );
2715
+ }
2716
+ } else if (!isAddress(mintRecipient)) {
2717
+ throw new InvalidInputError(
2718
+ "invalid_address",
2719
+ `mintRecipient is not a valid EVM address: ${mintRecipient}`
2720
+ );
2721
+ }
2722
+ if (destination.ecosystem === "solana") {
2723
+ const bytes = new web3_js.PublicKey(mintRecipient).toBytes();
2724
+ let hex = "0x";
2725
+ for (const b of bytes) hex += b.toString(16).padStart(2, "0");
2726
+ return hex;
2727
+ }
2728
+ if (destination.ecosystem === "stellar" || destination.ecosystem === "starknet") {
2729
+ return mintRecipient;
2730
+ }
2731
+ return toBytes32(mintRecipient);
2732
+ }
2733
+
2734
+ // src/burn/build.ts
2735
+ var MAX_USDC_AMOUNT = 10000000n * 1000000n;
2736
+ function buildBurnIntent(input) {
2737
+ if (input.source.ecosystem !== "evm") {
2738
+ throw new UnsupportedError(
2739
+ "unsupported_ecosystem",
2740
+ `Source chain "${input.source.id}" is not EVM. Use the Solana burn builder for Solana sources.`
2741
+ );
2742
+ }
2743
+ if (input.source.cctpDomain === input.destination.cctpDomain) {
2744
+ throw new InvalidInputError(
2745
+ "no_route",
2746
+ `Source and destination domains are identical (${input.source.cctpDomain}). Use a same-chain transfer instead of bridge.`
2747
+ );
2748
+ }
2749
+ if (input.amount <= 0n) {
2750
+ throw new InvalidInputError(
2751
+ "invalid_amount",
2752
+ `amount must be positive, got ${input.amount}`
2753
+ );
2754
+ }
2755
+ if (input.amount > MAX_USDC_AMOUNT) {
2756
+ throw new ProtocolError(
2757
+ "amount_too_large",
2758
+ `amount exceeds CCTP per-burn cap of 10,000,000 USDC (got ${input.amount} subunits)`
2759
+ );
2760
+ }
2761
+ const mintRecipientBytes32 = encodeMintRecipient(
2762
+ input.destination,
2763
+ input.mintRecipient
2764
+ );
2765
+ const finalityThreshold = input.fee.tier.finalityThreshold;
2766
+ if (finalityThreshold === FINALITY_FAST && !input.source.capabilities.fastSource) {
2767
+ throw new ProtocolError(
2768
+ "no_route",
2769
+ `Source chain "${input.source.id}" has no Fast Transfer. Use its Standard fee tier.`
2770
+ );
2771
+ }
2772
+ const withForwarder = input.withForwarder ?? true;
2773
+ const destinationCaller = input.destinationCaller ?? ANY_DESTINATION_CALLER;
2774
+ const computed = computeMaxFee({
2775
+ amount: input.amount,
2776
+ tier: input.fee.tier,
2777
+ ...input.fee.forwarderLevel !== void 0 && {
2778
+ forwarderLevel: input.fee.forwarderLevel
2779
+ },
2780
+ ...input.fee.forwarderBufferBps !== void 0 && {
2781
+ forwarderBufferBps: input.fee.forwarderBufferBps
2782
+ },
2783
+ includeForwarder: withForwarder
2784
+ });
2785
+ const { burnFee, forwarderFee } = computed;
2786
+ const maxFee = input.fee.maxFee ?? computed.maxFee;
2787
+ if (maxFee < 0n || maxFee >= input.amount) {
2788
+ throw new InvalidInputError(
2789
+ "invalid_amount",
2790
+ `maxFee must be at least 0 and below amount (TokenMessengerV2 reverts otherwise), got ${maxFee}`
2791
+ );
2792
+ }
2793
+ const calls = [];
2794
+ if (!input.skipApprove) {
2795
+ const approveAmount = input.approveAmount ?? input.amount;
2796
+ if (approveAmount < input.amount) {
2797
+ throw new InvalidInputError(
2798
+ "invalid_amount",
2799
+ `approveAmount (${approveAmount}) must be \u2265 amount (${input.amount})`
2800
+ );
2801
+ }
2802
+ calls.push({
2803
+ to: input.source.usdc,
2804
+ data: viem.encodeFunctionData({
2805
+ abi: usdcAbi,
2806
+ functionName: "approve",
2807
+ args: [input.source.tokenMessenger, approveAmount]
2808
+ }),
2809
+ value: 0n
2810
+ });
2811
+ }
2812
+ const burnArgs = [
2813
+ input.amount,
2814
+ input.destination.cctpDomain,
2815
+ mintRecipientBytes32,
2816
+ input.source.usdc,
2817
+ destinationCaller,
2818
+ maxFee,
2819
+ finalityThreshold
2820
+ ];
2821
+ const effectiveHookData = input.customHookData ?? CCTP_FORWARD_HOOK_DATA;
2822
+ const callWithHook = withForwarder || input.customHookData !== void 0;
2823
+ calls.push({
2824
+ to: input.source.tokenMessenger,
2825
+ data: callWithHook ? viem.encodeFunctionData({
2826
+ abi: tokenMessengerV2Abi,
2827
+ functionName: "depositForBurnWithHook",
2828
+ args: [...burnArgs, effectiveHookData]
2829
+ }) : viem.encodeFunctionData({
2830
+ abi: tokenMessengerV2Abi,
2831
+ functionName: "depositForBurn",
2832
+ args: burnArgs
2833
+ }),
2834
+ value: 0n
2835
+ });
2836
+ return {
2837
+ source: input.source,
2838
+ destination: input.destination,
2839
+ calls,
2840
+ amount: input.amount,
2841
+ maxFee,
2842
+ burnFee,
2843
+ forwarderFee,
2844
+ mintRecipientBytes32,
2845
+ withForwarder,
2846
+ finalityThreshold
2847
+ };
2848
+ }
2849
+ function buildBurnWithFeesIntent(input) {
2850
+ const { source, destination } = input;
2851
+ if (source.ecosystem !== "evm" || !source.tokenMessengerWithFees) {
2852
+ throw new UnsupportedError(
2853
+ "unsupported_chain",
2854
+ `${source.id} has no TokenMessengerWithFees, so it cannot pay fees upfront`
2855
+ );
2856
+ }
2857
+ if (destination.ecosystem === "stellar") {
2858
+ throw new UnsupportedError(
2859
+ "unsupported_chain",
2860
+ "burns to Stellar carry custom hook data and cannot pay fees upfront"
2861
+ );
2862
+ }
2863
+ if (source.cctpDomain === destination.cctpDomain) {
2864
+ throw new InvalidInputError(
2865
+ "no_route",
2866
+ `Source and destination domains are identical (${source.cctpDomain})`
2867
+ );
2868
+ }
2869
+ if (input.amount <= 0n || input.fee < 0n) {
2870
+ throw new InvalidInputError(
2871
+ "invalid_amount",
2872
+ `amount must be positive and fee non-negative, got ${input.amount} and ${input.fee}`
2873
+ );
2874
+ }
2875
+ if (!isAddress(input.refundAddress)) {
2876
+ throw new InvalidInputError(
2877
+ "invalid_address",
2878
+ `refundAddress is not a valid EVM address: ${input.refundAddress}`
2879
+ );
2880
+ }
2881
+ const mintRecipientBytes32 = encodeMintRecipient(
2882
+ destination,
2883
+ input.mintRecipient
2884
+ );
2885
+ const approveAmount = input.approveAmount ?? input.amount + input.fee;
2886
+ if (approveAmount < input.amount + input.fee) {
2887
+ throw new InvalidInputError(
2888
+ "invalid_amount",
2889
+ `approveAmount (${approveAmount}) must cover amount plus fee (${input.amount + input.fee})`
2890
+ );
2891
+ }
2892
+ const calls = [
2893
+ {
2894
+ to: source.usdc,
2895
+ data: viem.encodeFunctionData({
2896
+ abi: usdcAbi,
2897
+ functionName: "approve",
2898
+ args: [source.tokenMessengerWithFees, approveAmount]
2899
+ }),
2900
+ value: 0n
2901
+ },
2902
+ {
2903
+ to: source.tokenMessengerWithFees,
2904
+ data: viem.encodeFunctionData({
2905
+ abi: tokenMessengerWithFeesAbi,
2906
+ functionName: "depositForBurnWithFees",
2907
+ args: [
2908
+ input.amount,
2909
+ destination.cctpDomain,
2910
+ mintRecipientBytes32,
2911
+ source.usdc,
2912
+ ANY_DESTINATION_CALLER,
2913
+ {
2914
+ signedQuote: input.signedQuote,
2915
+ refundAddress: input.refundAddress
2916
+ }
2917
+ ]
2918
+ }),
2919
+ value: 0n
2920
+ }
2921
+ ];
2922
+ return { calls, amount: input.amount, fee: input.fee, mintRecipientBytes32 };
2923
+ }
2924
+ var HEX_PREFIX_REGEX = /^0x[0-9a-fA-F]+$/;
2925
+ var NON_EVM_BUILDERS = {
2926
+ solana: "buildSolanaReceiveIntent",
2927
+ stellar: "buildStellarMintIntent",
2928
+ starknet: "buildStarknetReceiveIntent"
2929
+ };
2930
+ function buildMintIntent(input) {
2931
+ if (input.destination.ecosystem !== "evm") {
2932
+ throw new UnsupportedError(
2933
+ "unsupported_ecosystem",
2934
+ `buildMintIntent builds EVM mints. Use ${NON_EVM_BUILDERS[input.destination.ecosystem]} for "${input.destination.id}".`
2935
+ );
2936
+ }
2937
+ if (!HEX_PREFIX_REGEX.test(input.message)) {
2938
+ throw new InvalidInputError(
2939
+ "invalid_input",
2940
+ "message must be a 0x-prefixed hex string"
2941
+ );
2942
+ }
2943
+ if (!HEX_PREFIX_REGEX.test(input.attestation)) {
2944
+ throw new InvalidInputError(
2945
+ "invalid_input",
2946
+ "attestation must be a 0x-prefixed hex string"
2947
+ );
2948
+ }
2949
+ const data = viem.encodeFunctionData({
2950
+ abi: messageTransmitterV2Abi,
2951
+ functionName: "receiveMessage",
2952
+ args: [input.message, input.attestation]
2953
+ });
2954
+ return {
2955
+ destination: input.destination,
2956
+ call: {
2957
+ to: input.destination.messageTransmitter,
2958
+ data,
2959
+ value: 0n
2960
+ }
2961
+ };
2962
+ }
2963
+
2964
+ // src/starknet/address.ts
2965
+ var STARKNET_FELT_RE = /^0x[a-fA-F0-9]{1,64}$/;
2966
+ function isValidStarknetFelt(s2) {
2967
+ return STARKNET_FELT_RE.test(s2);
2968
+ }
2969
+ function assertStarknetFelt(s2) {
2970
+ if (!isValidStarknetFelt(s2)) {
2971
+ throw new InvalidInputError(
2972
+ "invalid_address",
2973
+ `Not a valid Starknet felt: ${s2}`
2974
+ );
2975
+ }
2976
+ return s2;
2977
+ }
2978
+ function feltToBytes32Hex(felt) {
2979
+ if (!isValidStarknetFelt(felt)) {
2980
+ throw new InvalidInputError(
2981
+ "invalid_address",
2982
+ `Not a valid Starknet felt: ${felt}`
2983
+ );
2984
+ }
2985
+ const stripped = felt.slice(2);
2986
+ if (stripped.length > 64) {
2987
+ throw new InvalidInputError(
2988
+ "invalid_address",
2989
+ `Starknet felt exceeds 32 bytes: ${felt}`
2990
+ );
2991
+ }
2992
+ return `0x${stripped.padStart(64, "0")}`;
2993
+ }
2994
+ function bytes32HexToFelt(hex) {
2995
+ const stripped = hex.startsWith("0x") ? hex.slice(2) : hex;
2996
+ if (stripped.length > 64) {
2997
+ throw new InvalidInputError(
2998
+ "invalid_address",
2999
+ `bytes32 input exceeds 32 bytes (${stripped.length / 2})`
3000
+ );
3001
+ }
3002
+ const stripped64 = stripped.padStart(64, "0").replace(/^0+/, "");
3003
+ const canonical = stripped64.length === 0 ? "0" : stripped64;
3004
+ return `0x${canonical}`;
3005
+ }
3006
+ function feltToBigInt(felt) {
3007
+ if (!isValidStarknetFelt(felt)) {
3008
+ throw new InvalidInputError(
3009
+ "invalid_address",
3010
+ `Not a valid Starknet felt: ${felt}`
3011
+ );
3012
+ }
3013
+ return BigInt(felt);
3014
+ }
3015
+ function u256ToFelts(value) {
3016
+ if (value < 0n) {
3017
+ throw new RangeError(
3018
+ `u256ToFelts: value must be non-negative, got ${value}`
3019
+ );
3020
+ }
3021
+ const u = starknet.cairo.uint256(value);
3022
+ return [u.low.toString(), u.high.toString()];
3023
+ }
3024
+ function feltToString(value) {
3025
+ return starknet.num.toBigInt(value).toString();
3026
+ }
3027
+ function bytesToByteArrayFelts(bytes) {
3028
+ const CHUNK = 31;
3029
+ const dataFelts = [];
3030
+ let i = 0;
3031
+ while (i + CHUNK <= bytes.length) {
3032
+ dataFelts.push(bytesToBigIntBE(bytes.subarray(i, i + CHUNK)).toString());
3033
+ i += CHUNK;
3034
+ }
3035
+ const rest = bytes.subarray(i);
3036
+ const pendingWord = bytesToBigIntBE(rest).toString();
3037
+ const pendingWordLen = rest.length.toString();
3038
+ return [
3039
+ dataFelts.length.toString(),
3040
+ ...dataFelts,
3041
+ pendingWord,
3042
+ pendingWordLen
3043
+ ];
3044
+ }
3045
+ function bytesToBigIntBE(bytes) {
3046
+ let n = 0n;
3047
+ for (const b of bytes) n = n << 8n | BigInt(b);
3048
+ return n;
3049
+ }
3050
+ function hexToByteArrayFelts(hex) {
3051
+ const stripped = hex.startsWith("0x") ? hex.slice(2) : hex;
3052
+ const bytes = new Uint8Array(stripped.length / 2);
3053
+ for (let i = 0; i < bytes.length; i++) {
3054
+ bytes[i] = parseInt(stripped.slice(i * 2, i * 2 + 2), 16);
3055
+ }
3056
+ return bytesToByteArrayFelts(bytes);
3057
+ }
3058
+
3059
+ // src/starknet/burn.ts
3060
+ function buildStarknetBurnIntent(input) {
3061
+ if (input.source.ecosystem !== "starknet") {
3062
+ throw new InvalidInputError(
3063
+ "invalid_chain",
3064
+ `source must be Starknet, got ${input.source.ecosystem}`
3065
+ );
3066
+ }
3067
+ if (input.amount <= 0n) {
3068
+ throw new InvalidInputError(
3069
+ "invalid_amount",
3070
+ `amount must be positive, got ${input.amount}`
3071
+ );
3072
+ }
3073
+ if (input.maxFee < 0n) {
3074
+ throw new InvalidInputError(
3075
+ "invalid_amount",
3076
+ `maxFee must be non-negative, got ${input.maxFee}`
3077
+ );
3078
+ }
3079
+ if (input.mintRecipient < 0n) {
3080
+ throw new InvalidInputError(
3081
+ "invalid_input",
3082
+ `mintRecipient must be non-negative, got ${input.mintRecipient}`
3083
+ );
3084
+ }
3085
+ const withHook = !!input.hookData && input.hookData.length > 0;
3086
+ const entrypoint = withHook ? "deposit_for_burn_with_hook" : "deposit_for_burn";
3087
+ const [amountLo, amountHi] = u256ToFelts(input.amount);
3088
+ const [recipLo, recipHi] = u256ToFelts(input.mintRecipient);
3089
+ const [callerLo, callerHi] = u256ToFelts(input.destinationCaller);
3090
+ const [maxFeeLo, maxFeeHi] = u256ToFelts(input.maxFee);
3091
+ const calldata = [
3092
+ amountLo,
3093
+ amountHi,
3094
+ feltToString(input.destinationDomain),
3095
+ recipLo,
3096
+ recipHi,
3097
+ assertStarknetFelt(input.source.usdc),
3098
+ callerLo,
3099
+ callerHi,
3100
+ maxFeeLo,
3101
+ maxFeeHi,
3102
+ feltToString(input.minFinalityThreshold)
3103
+ ];
3104
+ if (withHook) {
3105
+ calldata.push(...bytesToByteArrayFelts(input.hookData));
3106
+ }
3107
+ return {
3108
+ source: input.source,
3109
+ destinationDomain: input.destinationDomain,
3110
+ amount: input.amount,
3111
+ maxFee: input.maxFee,
3112
+ call: {
3113
+ contractAddress: input.source.tokenMessengerMinter,
3114
+ entrypoint,
3115
+ calldata
3116
+ },
3117
+ withHook
3118
+ };
3119
+ }
3120
+ function buildStarknetApproveCall(args) {
3121
+ if (args.source.ecosystem !== "starknet") {
3122
+ throw new InvalidInputError(
3123
+ "invalid_chain",
3124
+ `source must be Starknet, got ${args.source.ecosystem}`
3125
+ );
3126
+ }
3127
+ if (args.amount <= 0n) {
3128
+ throw new InvalidInputError(
3129
+ "invalid_amount",
3130
+ `amount must be positive, got ${args.amount}`
3131
+ );
3132
+ }
3133
+ const [lo, hi] = u256ToFelts(args.amount);
3134
+ return {
3135
+ contractAddress: args.source.usdc,
3136
+ entrypoint: "approve",
3137
+ calldata: [assertStarknetFelt(args.spender), lo, hi]
3138
+ };
3139
+ }
3140
+
3141
+ // src/starknet/receive.ts
3142
+ function buildStarknetReceiveIntent(input) {
3143
+ if (input.destination.ecosystem !== "starknet") {
3144
+ throw new InvalidInputError(
3145
+ "invalid_chain",
3146
+ `destination must be Starknet, got ${input.destination.ecosystem}`
3147
+ );
3148
+ }
3149
+ if (!input.message.startsWith("0x") || input.message.length < 90) {
3150
+ throw new InvalidInputError(
3151
+ "invalid_input",
3152
+ "message must be a 0x-prefixed hex blob of at least 44 bytes"
3153
+ );
3154
+ }
3155
+ if (!input.attestation.startsWith("0x") || input.attestation.length < 4) {
3156
+ throw new InvalidInputError(
3157
+ "invalid_input",
3158
+ "attestation must be a 0x-prefixed hex blob"
3159
+ );
3160
+ }
3161
+ const calldata = [
3162
+ ...hexToByteArrayFelts(input.message),
3163
+ ...hexToByteArrayFelts(input.attestation)
3164
+ ];
3165
+ return {
3166
+ destination: input.destination,
3167
+ call: {
3168
+ contractAddress: input.destination.messageTransmitter,
3169
+ entrypoint: "receive_message",
3170
+ calldata
3171
+ }
3172
+ };
3173
+ }
3174
+ function isValidStellarStrkey(s2) {
3175
+ return stellarSdk.StrKey.isValidEd25519PublicKey(s2) || stellarSdk.StrKey.isValidMed25519PublicKey(s2) || stellarSdk.StrKey.isValidContract(s2);
3176
+ }
3177
+ function strkeyType(s2) {
3178
+ if (stellarSdk.StrKey.isValidEd25519PublicKey(s2)) return "G";
3179
+ if (stellarSdk.StrKey.isValidMed25519PublicKey(s2)) return "M";
3180
+ if (stellarSdk.StrKey.isValidContract(s2)) return "C";
3181
+ throw new InvalidInputError(
3182
+ "invalid_address",
3183
+ `Invalid Stellar strkey: ${s2}`
3184
+ );
3185
+ }
3186
+ function decodeStrkeyToBytes32(s2) {
3187
+ if (stellarSdk.StrKey.isValidEd25519PublicKey(s2))
3188
+ return stellarSdk.StrKey.decodeEd25519PublicKey(s2);
3189
+ if (stellarSdk.StrKey.isValidContract(s2)) return stellarSdk.StrKey.decodeContract(s2);
3190
+ if (stellarSdk.StrKey.isValidMed25519PublicKey(s2)) {
3191
+ return stellarSdk.StrKey.decodeMed25519PublicKey(s2).slice(0, 32);
3192
+ }
3193
+ throw new InvalidInputError(
3194
+ "invalid_address",
3195
+ `Invalid Stellar strkey: ${s2}`
3196
+ );
3197
+ }
3198
+ function encodeContractStrkey(bytes) {
3199
+ if (bytes.length !== 32) {
3200
+ throw new InvalidInputError(
3201
+ "invalid_input",
3202
+ `encodeContractStrkey: bytes must be 32, got ${bytes.length}`
3203
+ );
3204
+ }
3205
+ return stellarSdk.StrKey.encodeContract(Buffer.from(bytes));
3206
+ }
3207
+ function contractStrkeyToBytes32Hex(s2) {
3208
+ if (!stellarSdk.StrKey.isValidContract(s2)) {
3209
+ throw new InvalidInputError(
3210
+ "invalid_address",
3211
+ `Not a Stellar contract strkey (C\u2026): ${s2}`
3212
+ );
3213
+ }
3214
+ const bytes = stellarSdk.StrKey.decodeContract(s2);
3215
+ let hex = "0x";
3216
+ for (const b of bytes) hex += b.toString(16).padStart(2, "0");
3217
+ return hex;
3218
+ }
3219
+
3220
+ // src/stellar/precision.ts
3221
+ var DECIMAL_FACTOR = 10n ** BigInt(STELLAR_USDC_DECIMALS - CCTP_USDC_DECIMALS);
3222
+ function stellarSubunitsToCanonical(stellarSubunits) {
3223
+ if (stellarSubunits < 0n) {
3224
+ throw new RangeError(
3225
+ `stellarSubunitsToCanonical: amount must be non-negative, got ${stellarSubunits}`
3226
+ );
3227
+ }
3228
+ return stellarSubunits / DECIMAL_FACTOR;
3229
+ }
3230
+ function canonicalToStellarSubunits(canonicalSubunits) {
3231
+ if (canonicalSubunits < 0n) {
3232
+ throw new RangeError(
3233
+ `canonicalToStellarSubunits: amount must be non-negative, got ${canonicalSubunits}`
3234
+ );
3235
+ }
3236
+ return canonicalSubunits * DECIMAL_FACTOR;
3237
+ }
3238
+ function stellarBurnDust(stellarSubunits) {
3239
+ return stellarSubunits % DECIMAL_FACTOR;
3240
+ }
3241
+ var VERSION_OFFSET = 24;
3242
+ var LENGTH_OFFSET = 28;
3243
+ var PAYLOAD_OFFSET = 32;
3244
+ var HOOK_DATA_VERSION = 0;
3245
+ function buildStellarForwarderHookData(forwardRecipientStrkey, integratorPayload) {
3246
+ if (!isValidStellarStrkey(forwardRecipientStrkey)) {
3247
+ throw new InvalidInputError(
3248
+ "invalid_address",
3249
+ `Stellar forwardRecipient must be a G/M/C strkey, got: ${forwardRecipientStrkey}`
3250
+ );
3251
+ }
3252
+ const recipientBytes = new TextEncoder().encode(forwardRecipientStrkey);
3253
+ const payloadLength = integratorPayload?.length ?? 0;
3254
+ const total = PAYLOAD_OFFSET + recipientBytes.length + payloadLength;
3255
+ const buf = new Uint8Array(total);
3256
+ writeU32BE(buf, VERSION_OFFSET, HOOK_DATA_VERSION);
3257
+ writeU32BE(buf, LENGTH_OFFSET, recipientBytes.length);
3258
+ buf.set(recipientBytes, PAYLOAD_OFFSET);
3259
+ if (integratorPayload && integratorPayload.length > 0) {
3260
+ buf.set(integratorPayload, PAYLOAD_OFFSET + recipientBytes.length);
3261
+ }
3262
+ let hex = "0x";
3263
+ for (const b of buf) hex += b.toString(16).padStart(2, "0");
3264
+ return hex;
3265
+ }
3266
+ function writeU32BE(buf, offset, value) {
3267
+ buf[offset] = value >>> 24 & 255;
3268
+ buf[offset + 1] = value >>> 16 & 255;
3269
+ buf[offset + 2] = value >>> 8 & 255;
3270
+ buf[offset + 3] = value & 255;
3271
+ }
3272
+ function buildStellarApproveInvocation(input) {
3273
+ if (input.source.ecosystem !== "stellar") {
3274
+ throw new InvalidInputError(
3275
+ "invalid_chain",
3276
+ `source must be Stellar, got ${input.source.ecosystem}`
3277
+ );
3278
+ }
3279
+ if (input.amount <= 0n) {
3280
+ throw new InvalidInputError(
3281
+ "invalid_amount",
3282
+ `amount must be positive, got ${input.amount}`
3283
+ );
3284
+ }
3285
+ if (input.expirationLedger < 0) {
3286
+ throw new InvalidInputError(
3287
+ "invalid_input",
3288
+ `expirationLedger must be \u2265 0, got ${input.expirationLedger}`
3289
+ );
3290
+ }
3291
+ const args = [
3292
+ new stellarSdk.Address(input.owner).toScVal(),
3293
+ new stellarSdk.Address(input.spender).toScVal(),
3294
+ stellarSdk.nativeToScVal(input.amount, { type: "i128" }),
3295
+ stellarSdk.nativeToScVal(input.expirationLedger, { type: "u32" })
3296
+ ];
3297
+ const operation = new stellarSdk.Contract(input.source.usdc).call("approve", ...args);
3298
+ return {
3299
+ ecosystem: "stellar",
3300
+ contractId: input.source.usdc,
3301
+ functionName: "approve",
3302
+ args,
3303
+ operation
3304
+ };
3305
+ }
3306
+ function buildStellarBurnIntent(input) {
3307
+ if (input.source.ecosystem !== "stellar") {
3308
+ throw new InvalidInputError(
3309
+ "invalid_chain",
3310
+ `source must be a Stellar chain, got ${input.source.ecosystem}`
3311
+ );
3312
+ }
3313
+ if (!isValidStellarStrkey(input.caller)) {
3314
+ throw new InvalidInputError(
3315
+ "invalid_address",
3316
+ `caller is not a valid Stellar strkey: ${input.caller}`
3317
+ );
3318
+ }
3319
+ if (input.mintRecipientBytes32.length !== 32) {
3320
+ throw new InvalidInputError(
3321
+ "invalid_input",
3322
+ `mintRecipientBytes32 must be 32 bytes, got ${input.mintRecipientBytes32.length}`
3323
+ );
3324
+ }
3325
+ if (input.destinationCallerBytes32.length !== 32) {
3326
+ throw new InvalidInputError(
3327
+ "invalid_input",
3328
+ `destinationCallerBytes32 must be 32 bytes, got ${input.destinationCallerBytes32.length}`
3329
+ );
3330
+ }
3331
+ if (input.amount <= 0n) {
3332
+ throw new InvalidInputError(
3333
+ "invalid_amount",
3334
+ `amount must be positive, got ${input.amount}`
3335
+ );
3336
+ }
3337
+ if (input.maxFee < 0n) {
3338
+ throw new InvalidInputError(
3339
+ "invalid_amount",
3340
+ `maxFee must be non-negative, got ${input.maxFee}`
3341
+ );
3342
+ }
3343
+ const withHook = !!input.hookData && input.hookData.length > 0;
3344
+ const fn = withHook ? "deposit_for_burn_with_hook" : "deposit_for_burn";
3345
+ const tmm = input.source.tokenMessengerMinter;
3346
+ const usdcSac = input.source.usdc;
3347
+ const args = [
3348
+ new stellarSdk.Address(input.caller).toScVal(),
3349
+ stellarSdk.nativeToScVal(input.amount, { type: "i128" }),
3350
+ stellarSdk.nativeToScVal(input.destinationDomain, { type: "u32" }),
3351
+ stellarSdk.nativeToScVal(Buffer.from(input.mintRecipientBytes32), {
3352
+ type: "bytes"
3353
+ }),
3354
+ new stellarSdk.Address(usdcSac).toScVal(),
3355
+ stellarSdk.nativeToScVal(Buffer.from(input.destinationCallerBytes32), {
3356
+ type: "bytes"
3357
+ }),
3358
+ stellarSdk.nativeToScVal(input.maxFee, { type: "i128" }),
3359
+ stellarSdk.nativeToScVal(input.minFinalityThreshold, { type: "u32" })
3360
+ ];
3361
+ if (withHook) {
3362
+ args.push(stellarSdk.nativeToScVal(Buffer.from(input.hookData), { type: "bytes" }));
3363
+ }
3364
+ const operation = new stellarSdk.Contract(tmm).call(fn, ...args);
3365
+ return {
3366
+ source: input.source,
3367
+ destinationDomain: input.destinationDomain,
3368
+ amount: input.amount,
3369
+ maxFee: input.maxFee,
3370
+ invocation: {
3371
+ ecosystem: "stellar",
3372
+ contractId: tmm,
3373
+ functionName: fn,
3374
+ args,
3375
+ operation
3376
+ },
3377
+ withHook
3378
+ };
3379
+ }
3380
+ function strkeyTo32Bytes(strkey) {
3381
+ return decodeStrkeyToBytes32(strkey);
3382
+ }
3383
+ function buildStellarMintIntent(input) {
3384
+ if (input.destination.ecosystem !== "stellar") {
3385
+ throw new InvalidInputError(
3386
+ "invalid_chain",
3387
+ `destination must be a Stellar chain, got ${input.destination.ecosystem}`
3388
+ );
3389
+ }
3390
+ if (input.message.length < 44) {
3391
+ throw new InvalidInputError(
3392
+ "invalid_input",
3393
+ `message must be at least 44 bytes, got ${input.message.length}`
3394
+ );
3395
+ }
3396
+ if (input.attestation.length === 0) {
3397
+ throw new InvalidInputError(
3398
+ "invalid_input",
3399
+ "attestation must not be empty"
3400
+ );
3401
+ }
3402
+ const args = [
3403
+ stellarSdk.nativeToScVal(Buffer.from(input.message), { type: "bytes" }),
3404
+ stellarSdk.nativeToScVal(Buffer.from(input.attestation), { type: "bytes" })
3405
+ ];
3406
+ const operation = new stellarSdk.Contract(input.destination.cctpForwarder).call(
3407
+ "mint_and_forward",
3408
+ ...args
3409
+ );
3410
+ return {
3411
+ destination: input.destination,
3412
+ invocation: {
3413
+ ecosystem: "stellar",
3414
+ contractId: input.destination.cctpForwarder,
3415
+ functionName: "mint_and_forward",
3416
+ args,
3417
+ operation
3418
+ }
3419
+ };
3420
+ }
3421
+ var enc = new TextEncoder();
3422
+ var SEEDS = {
3423
+ tokenMessenger: enc.encode("token_messenger"),
3424
+ tokenMinter: enc.encode("token_minter"),
3425
+ senderAuthority: enc.encode("sender_authority"),
3426
+ remoteTokenMessenger: enc.encode("remote_token_messenger"),
3427
+ localToken: enc.encode("local_token"),
3428
+ tokenPair: enc.encode("token_pair"),
3429
+ custody: enc.encode("custody"),
3430
+ denylistAccount: enc.encode("denylist_account"),
3431
+ messageTransmitter: enc.encode("message_transmitter"),
3432
+ messageTransmitterAuthority: enc.encode("message_transmitter_authority"),
3433
+ usedNonce: enc.encode("used_nonce"),
3434
+ eventAuthority: enc.encode("__event_authority")
3435
+ };
3436
+ function deriveTokenMessenger(tokenMessengerMinterProgram) {
3437
+ return web3_js.PublicKey.findProgramAddressSync(
3438
+ [SEEDS.tokenMessenger],
3439
+ tokenMessengerMinterProgram
3440
+ )[0];
3441
+ }
3442
+ function deriveTokenMinter(tokenMessengerMinterProgram) {
3443
+ return web3_js.PublicKey.findProgramAddressSync(
3444
+ [SEEDS.tokenMinter],
3445
+ tokenMessengerMinterProgram
3446
+ )[0];
3447
+ }
3448
+ function deriveSenderAuthority(tokenMessengerMinterProgram) {
3449
+ return web3_js.PublicKey.findProgramAddressSync(
3450
+ [SEEDS.senderAuthority],
3451
+ tokenMessengerMinterProgram
3452
+ )[0];
3453
+ }
3454
+ function deriveRemoteTokenMessenger(tokenMessengerMinterProgram, domain) {
3455
+ return web3_js.PublicKey.findProgramAddressSync(
3456
+ [SEEDS.remoteTokenMessenger, enc.encode(domain.toString())],
3457
+ tokenMessengerMinterProgram
3458
+ )[0];
3459
+ }
3460
+ function deriveLocalToken(tokenMessengerMinterProgram, mint) {
3461
+ return web3_js.PublicKey.findProgramAddressSync(
3462
+ [SEEDS.localToken, mint.toBytes()],
3463
+ tokenMessengerMinterProgram
3464
+ )[0];
3465
+ }
3466
+ function deriveTokenPair(tokenMessengerMinterProgram, sourceDomain, sourceTokenBytes32) {
3467
+ if (sourceTokenBytes32.length !== 32) {
3468
+ throw new Error(
3469
+ `deriveTokenPair: sourceTokenBytes32 must be 32 bytes, got ${sourceTokenBytes32.length}`
3470
+ );
3471
+ }
3472
+ return web3_js.PublicKey.findProgramAddressSync(
3473
+ [SEEDS.tokenPair, enc.encode(sourceDomain.toString()), sourceTokenBytes32],
3474
+ tokenMessengerMinterProgram
3475
+ )[0];
3476
+ }
3477
+ function deriveCustodyTokenAccount(tokenMessengerMinterProgram, mint) {
3478
+ return web3_js.PublicKey.findProgramAddressSync(
3479
+ [SEEDS.custody, mint.toBytes()],
3480
+ tokenMessengerMinterProgram
3481
+ )[0];
3482
+ }
3483
+ function deriveDenylistAccount(tokenMessengerMinterProgram, owner) {
3484
+ return web3_js.PublicKey.findProgramAddressSync(
3485
+ [SEEDS.denylistAccount, owner.toBytes()],
3486
+ tokenMessengerMinterProgram
3487
+ )[0];
3488
+ }
3489
+ function deriveMessageTransmitter(messageTransmitterProgram) {
3490
+ return web3_js.PublicKey.findProgramAddressSync(
3491
+ [SEEDS.messageTransmitter],
3492
+ messageTransmitterProgram
3493
+ )[0];
3494
+ }
3495
+ function deriveMessageTransmitterAuthority(messageTransmitterProgram, receiverProgram) {
3496
+ return web3_js.PublicKey.findProgramAddressSync(
3497
+ [SEEDS.messageTransmitterAuthority, receiverProgram.toBytes()],
3498
+ messageTransmitterProgram
3499
+ )[0];
3500
+ }
3501
+ function deriveUsedNonce(messageTransmitterProgram, messageBytes) {
3502
+ if (messageBytes.length < 44) {
3503
+ throw new Error(
3504
+ `deriveUsedNonce: message must be at least 44 bytes, got ${messageBytes.length}`
3505
+ );
3506
+ }
3507
+ const nonce = messageBytes.slice(12, 44);
3508
+ return web3_js.PublicKey.findProgramAddressSync(
3509
+ [SEEDS.usedNonce, nonce],
3510
+ messageTransmitterProgram
3511
+ )[0];
3512
+ }
3513
+ function deriveEventAuthority(programId) {
3514
+ return web3_js.PublicKey.findProgramAddressSync([SEEDS.eventAuthority], programId)[0];
3515
+ }
3516
+ function anchorDiscriminator(snakeCaseName) {
3517
+ const bytes = new TextEncoder().encode(`global:${snakeCaseName}`);
3518
+ return sha256.sha256(bytes).slice(0, 8);
3519
+ }
3520
+ var DISCRIMINATOR_DEPOSIT_FOR_BURN = anchorDiscriminator("deposit_for_burn");
3521
+ var DISCRIMINATOR_DEPOSIT_FOR_BURN_WITH_HOOK = anchorDiscriminator("deposit_for_burn_with_hook");
3522
+ var DISCRIMINATOR_RECEIVE_MESSAGE = anchorDiscriminator("receive_message");
3523
+ function createWriter(initialSize = 64) {
3524
+ return { buf: buffer.Buffer.alloc(initialSize), offset: 0 };
3525
+ }
3526
+ function ensure(w, extra) {
3527
+ if (w.offset + extra <= w.buf.length) return;
3528
+ const next = buffer.Buffer.alloc(Math.max(w.buf.length * 2, w.offset + extra));
3529
+ w.buf.copy(next, 0, 0, w.offset);
3530
+ w.buf = next;
3531
+ }
3532
+ function writeU32LE(w, value) {
3533
+ ensure(w, 4);
3534
+ w.buf.writeUInt32LE(value >>> 0, w.offset);
3535
+ w.offset += 4;
3536
+ }
3537
+ function writeU64LE(w, value) {
3538
+ if (value < 0n) {
3539
+ throw new RangeError(
3540
+ `writeU64LE: value must be non-negative, got ${value}`
3541
+ );
3542
+ }
3543
+ ensure(w, 8);
3544
+ w.buf.writeBigUInt64LE(value, w.offset);
3545
+ w.offset += 8;
3546
+ }
3547
+ function writePubkey(w, bytes) {
3548
+ if (bytes.length !== 32) {
3549
+ throw new RangeError(`writePubkey: expected 32 bytes, got ${bytes.length}`);
3550
+ }
3551
+ ensure(w, 32);
3552
+ w.buf.set(bytes, w.offset);
3553
+ w.offset += 32;
3554
+ }
3555
+ function writeBytes(w, bytes) {
3556
+ writeU32LE(w, bytes.length);
3557
+ ensure(w, bytes.length);
3558
+ w.buf.set(bytes, w.offset);
3559
+ w.offset += bytes.length;
3560
+ }
3561
+ function withDiscriminator(discriminator, w) {
3562
+ const out = buffer.Buffer.alloc(discriminator.length + w.offset);
3563
+ out.set(discriminator, 0);
3564
+ w.buf.copy(out, discriminator.length, 0, w.offset);
3565
+ return out;
3566
+ }
3567
+
3568
+ // src/solana/burn.ts
3569
+ var ANY_DESTINATION_CALLER2 = new web3_js.PublicKey(new Uint8Array(32));
3570
+ var MAX_USDC_AMOUNT2 = 10000000n * 1000000n;
3571
+ function buildSolanaBurnIntent(input) {
3572
+ if (input.source.ecosystem !== "solana") {
3573
+ throw new InvalidInputError(
3574
+ "invalid_chain",
3575
+ `source must be a Solana chain, got ${input.source.ecosystem}`
3576
+ );
3577
+ }
3578
+ if (input.amount <= 0n) {
3579
+ throw new InvalidInputError(
3580
+ "invalid_amount",
3581
+ `amount must be positive, got ${input.amount}`
3582
+ );
3583
+ }
3584
+ if (input.amount > MAX_USDC_AMOUNT2) {
3585
+ throw new InvalidInputError(
3586
+ "amount_too_large",
3587
+ `amount exceeds CCTP per-burn cap of 10M USDC`
3588
+ );
3589
+ }
3590
+ if (input.amount <= input.maxFee) {
3591
+ throw new InvalidInputError(
3592
+ "invalid_amount",
3593
+ "amount must exceed maxFee (program would revert MaxFeeMustBeLessThanAmount)"
3594
+ );
3595
+ }
3596
+ if (input.mintRecipientBytes32.length !== 32) {
3597
+ throw new InvalidInputError(
3598
+ "invalid_input",
3599
+ `mintRecipientBytes32 must be 32 bytes, got ${input.mintRecipientBytes32.length}`
3600
+ );
3601
+ }
3602
+ const destCaller = input.destinationCallerBytes32 ?? new Uint8Array(32);
3603
+ if (destCaller.length !== 32) {
3604
+ throw new InvalidInputError(
3605
+ "invalid_input",
3606
+ `destinationCallerBytes32 must be 32 bytes, got ${destCaller.length}`
3607
+ );
3608
+ }
3609
+ if (input.hookData !== void 0 && input.hookData.length === 0) {
3610
+ throw new InvalidInputError(
3611
+ "invalid_input",
3612
+ "hookData must be non-empty (use the no-hook builder for plain burns)"
3613
+ );
3614
+ }
3615
+ const tmmProgram = new web3_js.PublicKey(input.source.tokenMessengerMinter);
3616
+ const mtProgram = new web3_js.PublicKey(input.source.messageTransmitter);
3617
+ const burnTokenMint = new web3_js.PublicKey(input.source.usdc);
3618
+ const senderAuthorityPda = deriveSenderAuthority(tmmProgram);
3619
+ const denylistAccount = deriveDenylistAccount(tmmProgram, input.owner);
3620
+ const messageTransmitter = deriveMessageTransmitter(mtProgram);
3621
+ const tokenMessenger = deriveTokenMessenger(tmmProgram);
3622
+ const remoteTokenMessenger = deriveRemoteTokenMessenger(
3623
+ tmmProgram,
3624
+ input.destinationDomain
3625
+ );
3626
+ const tokenMinter = deriveTokenMinter(tmmProgram);
3627
+ const localToken = deriveLocalToken(tmmProgram, burnTokenMint);
3628
+ const eventAuthority = deriveEventAuthority(tmmProgram);
3629
+ const keys = [
3630
+ { pubkey: input.owner, isSigner: true, isWritable: false },
3631
+ { pubkey: input.owner, isSigner: true, isWritable: true },
3632
+ // event_rent_payer = owner
3633
+ { pubkey: senderAuthorityPda, isSigner: false, isWritable: false },
3634
+ { pubkey: input.ownerUsdcAta, isSigner: false, isWritable: true },
3635
+ { pubkey: denylistAccount, isSigner: false, isWritable: false },
3636
+ { pubkey: messageTransmitter, isSigner: false, isWritable: true },
3637
+ { pubkey: tokenMessenger, isSigner: false, isWritable: false },
3638
+ { pubkey: remoteTokenMessenger, isSigner: false, isWritable: false },
3639
+ { pubkey: tokenMinter, isSigner: false, isWritable: false },
3640
+ { pubkey: localToken, isSigner: false, isWritable: true },
3641
+ { pubkey: burnTokenMint, isSigner: false, isWritable: true },
3642
+ {
3643
+ pubkey: input.messageSentEventDataKey,
3644
+ isSigner: true,
3645
+ isWritable: true
3646
+ },
3647
+ { pubkey: mtProgram, isSigner: false, isWritable: false },
3648
+ { pubkey: tmmProgram, isSigner: false, isWritable: false },
3649
+ { pubkey: splToken.TOKEN_PROGRAM_ID, isSigner: false, isWritable: false },
3650
+ { pubkey: web3_js.SystemProgram.programId, isSigner: false, isWritable: false },
3651
+ { pubkey: eventAuthority, isSigner: false, isWritable: false },
3652
+ { pubkey: tmmProgram, isSigner: false, isWritable: false }
3653
+ ];
3654
+ const writer = createWriter(96);
3655
+ writeU64LE(writer, input.amount);
3656
+ writeU32LE(writer, input.destinationDomain);
3657
+ writePubkey(writer, input.mintRecipientBytes32);
3658
+ writePubkey(writer, destCaller);
3659
+ writeU64LE(writer, input.maxFee);
3660
+ writeU32LE(writer, input.minFinalityThreshold);
3661
+ if (input.hookData !== void 0) {
3662
+ writeBytes(writer, input.hookData);
3663
+ }
3664
+ const discriminator = input.hookData !== void 0 ? DISCRIMINATOR_DEPOSIT_FOR_BURN_WITH_HOOK : DISCRIMINATOR_DEPOSIT_FOR_BURN;
3665
+ const data = withDiscriminator(discriminator, writer);
3666
+ return {
3667
+ source: input.source,
3668
+ destinationDomain: input.destinationDomain,
3669
+ amount: input.amount,
3670
+ maxFee: input.maxFee,
3671
+ messageSentEventDataKey: input.messageSentEventDataKey,
3672
+ withHook: input.hookData !== void 0,
3673
+ instruction: {
3674
+ programId: tmmProgram,
3675
+ keys,
3676
+ data,
3677
+ ecosystem: "solana"
3678
+ }
3679
+ };
3680
+ }
3681
+ function burnIntentToTransactionInstruction(intent) {
3682
+ return new web3_js.TransactionInstruction({
3683
+ programId: intent.instruction.programId,
3684
+ keys: intent.instruction.keys,
3685
+ data: intent.instruction.data
3686
+ });
3687
+ }
3688
+ function buildSolanaReceiveIntent(input) {
3689
+ if (input.destination.ecosystem !== "solana") {
3690
+ throw new InvalidInputError(
3691
+ "invalid_chain",
3692
+ `destination must be a Solana chain, got ${input.destination.ecosystem}`
3693
+ );
3694
+ }
3695
+ if (input.message.length < 44) {
3696
+ throw new InvalidInputError(
3697
+ "invalid_input",
3698
+ `message must be at least 44 bytes (Iris messages are much larger), got ${input.message.length}`
3699
+ );
3700
+ }
3701
+ if (input.attestation.length === 0) {
3702
+ throw new InvalidInputError(
3703
+ "invalid_input",
3704
+ "attestation must not be empty"
3705
+ );
3706
+ }
3707
+ if (input.sourceTokenBytes32.length !== 32) {
3708
+ throw new InvalidInputError(
3709
+ "invalid_input",
3710
+ `sourceTokenBytes32 must be 32 bytes, got ${input.sourceTokenBytes32.length}`
3711
+ );
3712
+ }
3713
+ const tmmProgram = new web3_js.PublicKey(input.destination.tokenMessengerMinter);
3714
+ const mtProgram = new web3_js.PublicKey(input.destination.messageTransmitter);
3715
+ const localMint = new web3_js.PublicKey(input.destination.usdc);
3716
+ const authorityPda = deriveMessageTransmitterAuthority(mtProgram, tmmProgram);
3717
+ const messageTransmitter = deriveMessageTransmitter(mtProgram);
3718
+ const usedNonce = deriveUsedNonce(mtProgram, input.message);
3719
+ const mtEventAuthority = deriveEventAuthority(mtProgram);
3720
+ const tokenMessenger = deriveTokenMessenger(tmmProgram);
3721
+ const remoteTokenMessenger = deriveRemoteTokenMessenger(
3722
+ tmmProgram,
3723
+ input.sourceDomain
3724
+ );
3725
+ const tokenMinter = deriveTokenMinter(tmmProgram);
3726
+ const localToken = deriveLocalToken(tmmProgram, localMint);
3727
+ const tokenPair = deriveTokenPair(
3728
+ tmmProgram,
3729
+ input.sourceDomain,
3730
+ input.sourceTokenBytes32
3731
+ );
3732
+ const custodyTokenAccount = deriveCustodyTokenAccount(tmmProgram, localMint);
3733
+ const tmmEventAuthority = deriveEventAuthority(tmmProgram);
3734
+ const keys = [
3735
+ { pubkey: input.payer, isSigner: true, isWritable: true },
3736
+ { pubkey: input.payer, isSigner: true, isWritable: false },
3737
+ // caller = payer
3738
+ { pubkey: authorityPda, isSigner: false, isWritable: false },
3739
+ { pubkey: messageTransmitter, isSigner: false, isWritable: false },
3740
+ { pubkey: usedNonce, isSigner: false, isWritable: true },
3741
+ { pubkey: tmmProgram, isSigner: false, isWritable: false },
3742
+ // receiver
3743
+ { pubkey: web3_js.SystemProgram.programId, isSigner: false, isWritable: false },
3744
+ { pubkey: mtEventAuthority, isSigner: false, isWritable: false },
3745
+ { pubkey: mtProgram, isSigner: false, isWritable: false },
3746
+ // Remaining accounts for TMM handle_receive
3747
+ { pubkey: tokenMessenger, isSigner: false, isWritable: false },
3748
+ { pubkey: remoteTokenMessenger, isSigner: false, isWritable: false },
3749
+ { pubkey: tokenMinter, isSigner: false, isWritable: true },
3750
+ { pubkey: localToken, isSigner: false, isWritable: true },
3751
+ { pubkey: tokenPair, isSigner: false, isWritable: false },
3752
+ { pubkey: input.feeRecipientUsdcAta, isSigner: false, isWritable: true },
3753
+ { pubkey: input.recipientUsdcAta, isSigner: false, isWritable: true },
3754
+ { pubkey: custodyTokenAccount, isSigner: false, isWritable: true },
3755
+ { pubkey: splToken.TOKEN_PROGRAM_ID, isSigner: false, isWritable: false },
3756
+ { pubkey: tmmEventAuthority, isSigner: false, isWritable: false },
3757
+ { pubkey: tmmProgram, isSigner: false, isWritable: false }
3758
+ ];
3759
+ const writer = createWriter(
3760
+ input.message.length + input.attestation.length + 16
3761
+ );
3762
+ writeBytes(writer, input.message);
3763
+ writeBytes(writer, input.attestation);
3764
+ const data = withDiscriminator(DISCRIMINATOR_RECEIVE_MESSAGE, writer);
3765
+ return {
3766
+ destination: input.destination,
3767
+ instruction: {
3768
+ programId: mtProgram,
3769
+ keys,
3770
+ data,
3771
+ ecosystem: "solana"
3772
+ }
3773
+ };
3774
+ }
3775
+ function receiveIntentToTransactionInstruction(intent) {
3776
+ return new web3_js.TransactionInstruction({
3777
+ programId: intent.instruction.programId,
3778
+ keys: intent.instruction.keys,
3779
+ data: intent.instruction.data
3780
+ });
3781
+ }
3782
+ var FEE_RECIPIENT_OFFSET = 109;
3783
+ var FEE_RECIPIENT_END = 141;
3784
+ function parseTokenMessengerFeeRecipient(accountData) {
3785
+ if (accountData.length < FEE_RECIPIENT_END) {
3786
+ throw new InvalidInputError(
3787
+ "invalid_input",
3788
+ `TokenMessenger account too small (${accountData.length} bytes) \u2014 cannot read fee_recipient.`
3789
+ );
3790
+ }
3791
+ return new web3_js.PublicKey(
3792
+ accountData.slice(FEE_RECIPIENT_OFFSET, FEE_RECIPIENT_END)
3793
+ );
3794
+ }
3795
+
3796
+ // src/index.ts
3797
+ var VERSION2 = "0.1.0";
3798
+
3799
+ exports.ANY_DESTINATION_CALLER = ANY_DESTINATION_CALLER;
3800
+ exports.Arbitrum = Arbitrum;
3801
+ exports.ArbitrumSepolia = ArbitrumSepolia;
3802
+ exports.Arc = Arc;
3803
+ exports.ArcTestnet = ArcTestnet;
3804
+ exports.Avalanche = Avalanche;
3805
+ exports.AvalancheFuji = AvalancheFuji;
3806
+ exports.Base = Base;
3807
+ exports.BaseSepolia = BaseSepolia;
3808
+ exports.CCTP_FORWARDER_STELLAR_MAINNET = CCTP_FORWARDER_STELLAR_MAINNET;
3809
+ exports.CCTP_FORWARDER_STELLAR_TESTNET = CCTP_FORWARDER_STELLAR_TESTNET;
3810
+ exports.CCTP_FORWARD_HOOK_DATA = CCTP_FORWARD_HOOK_DATA;
3811
+ exports.CCTP_FORWARD_HOOK_DATA_LENGTH = CCTP_FORWARD_HOOK_DATA_LENGTH;
3812
+ exports.CCTP_USDC_DECIMALS = CCTP_USDC_DECIMALS;
3813
+ exports.CHAINS = CHAINS;
3814
+ exports.CctpError = CctpError;
3815
+ exports.Codex = Codex;
3816
+ exports.CodexTestnet = CodexTestnet;
3817
+ exports.Cronos = Cronos;
3818
+ exports.CronosTestnet = CronosTestnet;
3819
+ exports.DISCRIMINATOR_DEPOSIT_FOR_BURN = DISCRIMINATOR_DEPOSIT_FOR_BURN;
3820
+ exports.DISCRIMINATOR_DEPOSIT_FOR_BURN_WITH_HOOK = DISCRIMINATOR_DEPOSIT_FOR_BURN_WITH_HOOK;
3821
+ exports.DISCRIMINATOR_RECEIVE_MESSAGE = DISCRIMINATOR_RECEIVE_MESSAGE;
3822
+ exports.EVM_MAINNET_CHAINS = EVM_MAINNET_CHAINS;
3823
+ exports.EVM_TESTNET_CHAINS = EVM_TESTNET_CHAINS;
3824
+ exports.Edge = Edge;
3825
+ exports.EdgeTestnet = EdgeTestnet;
3826
+ exports.Ethereum = Ethereum;
3827
+ exports.EthereumSepolia = EthereumSepolia;
3828
+ exports.FINALITY_FAST = FINALITY_FAST;
3829
+ exports.FINALITY_STANDARD = FINALITY_STANDARD;
3830
+ exports.HyperEVM = HyperEVM;
3831
+ exports.HyperEVMTestnet = HyperEVMTestnet;
3832
+ exports.IRIS_MAINNET_URL = IRIS_MAINNET_URL;
3833
+ exports.IRIS_SANDBOX_URL = IRIS_SANDBOX_URL;
3834
+ exports.Injective = Injective;
3835
+ exports.InjectiveTestnet = InjectiveTestnet;
3836
+ exports.Ink = Ink;
3837
+ exports.InkTestnet = InkTestnet;
3838
+ exports.InvalidAddressError = InvalidAddressError;
3839
+ exports.InvalidBytes32Error = InvalidBytes32Error;
3840
+ exports.InvalidInputError = InvalidInputError;
3841
+ exports.IrisAbortedError = IrisAbortedError;
3842
+ exports.IrisError = IrisError;
3843
+ exports.IrisHttpError = IrisHttpError;
3844
+ exports.IrisNetworkError = IrisNetworkError;
3845
+ exports.IrisParseError = IrisParseError;
3846
+ exports.IrisRateLimitedError = IrisRateLimitedError;
3847
+ exports.Linea = Linea;
3848
+ exports.LineaSepolia = LineaSepolia;
3849
+ exports.MESSAGE_TRANSMITTER_STELLAR_MAINNET = MESSAGE_TRANSMITTER_STELLAR_MAINNET;
3850
+ exports.MESSAGE_TRANSMITTER_STELLAR_TESTNET = MESSAGE_TRANSMITTER_STELLAR_TESTNET;
3851
+ exports.MESSAGE_TRANSMITTER_V2_EVM_MAINNET = MESSAGE_TRANSMITTER_V2_EVM_MAINNET;
3852
+ exports.MESSAGE_TRANSMITTER_V2_EVM_TESTNET = MESSAGE_TRANSMITTER_V2_EVM_TESTNET;
3853
+ exports.MESSAGE_TRANSMITTER_V2_SOLANA = MESSAGE_TRANSMITTER_V2_SOLANA;
3854
+ exports.MESSAGE_TRANSMITTER_V2_STARKNET_MAINNET = MESSAGE_TRANSMITTER_V2_STARKNET_MAINNET;
3855
+ exports.MESSAGE_TRANSMITTER_V2_STARKNET_SEPOLIA = MESSAGE_TRANSMITTER_V2_STARKNET_SEPOLIA;
3856
+ exports.Monad = Monad;
3857
+ exports.MonadTestnet = MonadTestnet;
3858
+ exports.Morph = Morph;
3859
+ exports.MorphTestnet = MorphTestnet;
3860
+ exports.Optimism = Optimism;
3861
+ exports.OptimismSepolia = OptimismSepolia;
3862
+ exports.Pharos = Pharos;
3863
+ exports.PharosTestnet = PharosTestnet;
3864
+ exports.Plasma = Plasma;
3865
+ exports.PlasmaTestnet = PlasmaTestnet;
3866
+ exports.Plume = Plume;
3867
+ exports.PlumeTestnet = PlumeTestnet;
3868
+ exports.Polygon = Polygon;
3869
+ exports.PolygonAmoyTestnet = PolygonAmoyTestnet;
3870
+ exports.ProtocolError = ProtocolError;
3871
+ exports.SOLANA_ANY_DESTINATION_CALLER = ANY_DESTINATION_CALLER2;
3872
+ exports.SOLANA_CCTP_DOMAIN = SOLANA_CCTP_DOMAIN;
3873
+ exports.SOLANA_CCTP_PDA_SEEDS = SEEDS;
3874
+ exports.STARKNET_CCTP_DOMAIN = STARKNET_CCTP_DOMAIN;
3875
+ exports.STARKNET_CHAIN_ID_MAINNET = STARKNET_CHAIN_ID_MAINNET;
3876
+ exports.STARKNET_CHAIN_ID_SEPOLIA = STARKNET_CHAIN_ID_SEPOLIA;
3877
+ exports.STELLAR_CCTP_DOMAIN = STELLAR_CCTP_DOMAIN;
3878
+ exports.STELLAR_NETWORK_PASSPHRASE_MAINNET = STELLAR_NETWORK_PASSPHRASE_MAINNET;
3879
+ exports.STELLAR_NETWORK_PASSPHRASE_TESTNET = STELLAR_NETWORK_PASSPHRASE_TESTNET;
3880
+ exports.STELLAR_USDC_DECIMALS = STELLAR_USDC_DECIMALS;
3881
+ exports.Sei = Sei;
3882
+ exports.SeiTestnet = SeiTestnet;
3883
+ exports.Solana = Solana;
3884
+ exports.SolanaDevnet = SolanaDevnet;
3885
+ exports.Sonic = Sonic;
3886
+ exports.SonicTestnet = SonicTestnet;
3887
+ exports.Starknet = Starknet;
3888
+ exports.StarknetSepolia = StarknetSepolia;
3889
+ exports.Stellar = Stellar;
3890
+ exports.StellarTestnet = StellarTestnet;
3891
+ exports.TOKEN_MESSENGER_MINTER_STELLAR_MAINNET = TOKEN_MESSENGER_MINTER_STELLAR_MAINNET;
3892
+ exports.TOKEN_MESSENGER_MINTER_STELLAR_TESTNET = TOKEN_MESSENGER_MINTER_STELLAR_TESTNET;
3893
+ exports.TOKEN_MESSENGER_MINTER_V2_SOLANA = TOKEN_MESSENGER_MINTER_V2_SOLANA;
3894
+ exports.TOKEN_MESSENGER_MINTER_V2_STARKNET_MAINNET = TOKEN_MESSENGER_MINTER_V2_STARKNET_MAINNET;
3895
+ exports.TOKEN_MESSENGER_MINTER_V2_STARKNET_SEPOLIA = TOKEN_MESSENGER_MINTER_V2_STARKNET_SEPOLIA;
3896
+ exports.TOKEN_MESSENGER_V2_EVM_MAINNET = TOKEN_MESSENGER_V2_EVM_MAINNET;
3897
+ exports.TOKEN_MESSENGER_V2_EVM_TESTNET = TOKEN_MESSENGER_V2_EVM_TESTNET;
3898
+ exports.TOKEN_MESSENGER_WITH_FEES_EVM_MAINNET = TOKEN_MESSENGER_WITH_FEES_EVM_MAINNET;
3899
+ exports.TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET = TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET;
3900
+ exports.USDC_ISSUER_STELLAR_MAINNET = USDC_ISSUER_STELLAR_MAINNET;
3901
+ exports.USDC_ISSUER_STELLAR_TESTNET = USDC_ISSUER_STELLAR_TESTNET;
3902
+ exports.USDC_SPL_DEVNET = USDC_SPL_DEVNET;
3903
+ exports.USDC_SPL_MAINNET = USDC_SPL_MAINNET;
3904
+ exports.USDC_STARKNET_MAINNET = USDC_STARKNET_MAINNET;
3905
+ exports.USDC_STARKNET_SEPOLIA = USDC_STARKNET_SEPOLIA;
3906
+ exports.Unichain = Unichain;
3907
+ exports.UnichainSepolia = UnichainSepolia;
3908
+ exports.UnknownChainError = UnknownChainError;
3909
+ exports.UnsupportedError = UnsupportedError;
3910
+ exports.VERSION = VERSION2;
3911
+ exports.WorldChain = WorldChain;
3912
+ exports.WorldChainSepolia = WorldChainSepolia;
3913
+ exports.XDC = XDC;
3914
+ exports.XDCApothem = XDCApothem;
3915
+ exports.XLayer = XLayer;
3916
+ exports.XLayerTestnet = XLayerTestnet;
3917
+ exports.anchorDiscriminator = anchorDiscriminator;
3918
+ exports.assertStarknetFelt = assertStarknetFelt;
3919
+ exports.attestationSeconds = attestationSeconds;
3920
+ exports.buildBurnIntent = buildBurnIntent;
3921
+ exports.buildBurnWithFeesIntent = buildBurnWithFeesIntent;
3922
+ exports.buildForwarderHookData = buildForwarderHookData;
3923
+ exports.buildMintIntent = buildMintIntent;
3924
+ exports.buildSolanaBurnIntent = buildSolanaBurnIntent;
3925
+ exports.buildSolanaReceiveIntent = buildSolanaReceiveIntent;
3926
+ exports.buildStarknetApproveCall = buildStarknetApproveCall;
3927
+ exports.buildStarknetBurnIntent = buildStarknetBurnIntent;
3928
+ exports.buildStarknetReceiveIntent = buildStarknetReceiveIntent;
3929
+ exports.buildStellarApproveInvocation = buildStellarApproveInvocation;
3930
+ exports.buildStellarBurnIntent = buildStellarBurnIntent;
3931
+ exports.buildStellarForwarderHookData = buildStellarForwarderHookData;
3932
+ exports.buildStellarMintIntent = buildStellarMintIntent;
3933
+ exports.burnIntentToTransactionInstruction = burnIntentToTransactionInstruction;
3934
+ exports.bytes32HexToFelt = bytes32HexToFelt;
3935
+ exports.bytesToByteArrayFelts = bytesToByteArrayFelts;
3936
+ exports.canonicalToStellarSubunits = canonicalToStellarSubunits;
3937
+ exports.chainByDomain = chainByDomain;
3938
+ exports.chainByEvmChainId = chainByEvmChainId;
3939
+ exports.chainsByNetwork = chainsByNetwork;
3940
+ exports.computeBurnFee = computeBurnFee;
3941
+ exports.computeMaxFee = computeMaxFee;
3942
+ exports.contractStrkeyToBytes32Hex = contractStrkeyToBytes32Hex;
3943
+ exports.createIrisLimiter = createIrisLimiter;
3944
+ exports.decodeBurnMessage = decodeBurnMessage;
3945
+ exports.decodeStrkeyToBytes32 = decodeStrkeyToBytes32;
3946
+ exports.defaultIrisLimiter = defaultIrisLimiter;
3947
+ exports.deriveCustodyTokenAccount = deriveCustodyTokenAccount;
3948
+ exports.deriveDenylistAccount = deriveDenylistAccount;
3949
+ exports.deriveEventAuthority = deriveEventAuthority;
3950
+ exports.deriveLocalToken = deriveLocalToken;
3951
+ exports.deriveMessageTransmitter = deriveMessageTransmitter;
3952
+ exports.deriveMessageTransmitterAuthority = deriveMessageTransmitterAuthority;
3953
+ exports.deriveRemoteTokenMessenger = deriveRemoteTokenMessenger;
3954
+ exports.deriveSenderAuthority = deriveSenderAuthority;
3955
+ exports.deriveTokenMessenger = deriveTokenMessenger;
3956
+ exports.deriveTokenMinter = deriveTokenMinter;
3957
+ exports.deriveTokenPair = deriveTokenPair;
3958
+ exports.deriveUsedNonce = deriveUsedNonce;
3959
+ exports.encodeContractStrkey = encodeContractStrkey;
3960
+ exports.explorerAddressUrl = explorerAddressUrl;
3961
+ exports.explorerTxUrl = explorerTxUrl;
3962
+ exports.feltToBigInt = feltToBigInt;
3963
+ exports.feltToBytes32Hex = feltToBytes32Hex;
3964
+ exports.fetchIrisJson = fetchIrisJson;
3965
+ exports.fromBytes32 = fromBytes32;
3966
+ exports.getBlockNumber = getBlockNumber;
3967
+ exports.getBurnFees = getBurnFees;
3968
+ exports.getChain = getChain;
3969
+ exports.getFastBurnAllowance = getFastBurnAllowance;
3970
+ exports.getGasPrice = getGasPrice;
3971
+ exports.getMessages = getMessages;
3972
+ exports.getSignedBurnQuote = getSignedBurnQuote;
3973
+ exports.getStandardMinFee = getStandardMinFee;
3974
+ exports.getStarknetClassHashAt = getStarknetClassHashAt;
3975
+ exports.getStarknetTransactionStatus = getStarknetTransactionStatus;
3976
+ exports.getTransactionStatus = getTransactionStatus;
3977
+ exports.getUsdcBalance = getUsdcBalance;
3978
+ exports.hexToByteArrayFelts = hexToByteArrayFelts;
3979
+ exports.irisBaseUrl = irisBaseUrl;
3980
+ exports.isAddress = isAddress;
3981
+ exports.isCctpError = isCctpError;
3982
+ exports.isChainId = isChainId;
3983
+ exports.isEvmChain = isEvmChain;
3984
+ exports.isForwardDone = isForwardDone;
3985
+ exports.isForwarderHookData = isForwarderHookData;
3986
+ exports.isNonceUsed = isNonceUsed;
3987
+ exports.isSolanaChain = isSolanaChain;
3988
+ exports.isStarknetChain = isStarknetChain;
3989
+ exports.isStarknetNonceUsed = isStarknetNonceUsed;
3990
+ exports.isStellarChain = isStellarChain;
3991
+ exports.isStellarNonceUsed = isStellarNonceUsed;
3992
+ exports.isValidStarknetFelt = isValidStarknetFelt;
3993
+ exports.isValidStellarStrkey = isValidStellarStrkey;
3994
+ exports.messageTransmitterV2Abi = messageTransmitterV2Abi;
3995
+ exports.parseFeeBps = parseFeeBps;
3996
+ exports.parseForwarderFee = parseForwarderFee;
3997
+ exports.parseTokenMessengerFeeRecipient = parseTokenMessengerFeeRecipient;
3998
+ exports.pickFeeTier = pickFeeTier;
3999
+ exports.pickForwarderFee = pickForwarderFee;
4000
+ exports.pollBudget = pollBudget;
4001
+ exports.pollMessages = pollMessages;
4002
+ exports.reattest = reattest;
4003
+ exports.receiveIntentToTransactionInstruction = receiveIntentToTransactionInstruction;
4004
+ exports.selectForwarderFee = selectForwarderFee;
4005
+ exports.starknetFeltToString = feltToString;
4006
+ exports.stellarBurnDust = stellarBurnDust;
4007
+ exports.stellarSubunitsToCanonical = stellarSubunitsToCanonical;
4008
+ exports.strkeyTo32Bytes = strkeyTo32Bytes;
4009
+ exports.strkeyType = strkeyType;
4010
+ exports.toBytes32 = toBytes32;
4011
+ exports.tokenMessengerV2Abi = tokenMessengerV2Abi;
4012
+ exports.tokenMessengerWithFeesAbi = tokenMessengerWithFeesAbi;
4013
+ exports.tryChainByEvmChainId = tryChainByEvmChainId;
4014
+ exports.tryFromBytes32 = tryFromBytes32;
4015
+ exports.u256ToFelts = u256ToFelts;
4016
+ exports.usdcAbi = usdcAbi;
4017
+ //# sourceMappingURL=index.cjs.map
4018
+ //# sourceMappingURL=index.cjs.map