@usewhisk/cctp 0.0.0 → 0.1.0

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