@m0-foundation/ntt-sdk-route 0.0.7 → 0.0.10

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.mjs CHANGED
@@ -1,23 +1,497 @@
1
- import { routes, Wormhole, isSameToken, amount, finality, chainToPlatform, canonicalAddress, signSendWait, TransferState, universalAddress, toChainId, toUniversal, isSourceInitiated, isSourceFinalized, isAttested, isRedeemed } from '@wormhole-foundation/sdk-connect';
1
+ import { routes, Wormhole, isSameToken, amount, finality, chainToPlatform, canonicalAddress, signSendWait, TransferState, universalAddress, toChainId, toUniversal, isSourceInitiated, isSourceFinalized, isAttested, isRedeemed, chainToChainId } from '@wormhole-foundation/sdk-connect';
2
2
  import { Ntt } from '@wormhole-foundation/sdk-definitions-ntt';
3
- import '@wormhole-foundation/sdk-solana-ntt';
3
+ import { WEI_PER_GWEI } from '@wormhole-foundation/sdk-solana-ntt';
4
4
  import { EvmAddress, EvmPlatform, addFrom, EvmUnsignedTransaction, addChainId } from '@wormhole-foundation/sdk-evm';
5
- import '@wormhole-foundation/sdk-solana';
5
+ import { SolanaAddress } from '@wormhole-foundation/sdk-solana';
6
6
  import { NttRoute } from '@wormhole-foundation/sdk-route-ntt';
7
7
  import { Contract } from 'ethers';
8
+ import { Keypair, PublicKey, Transaction, LAMPORTS_PER_SOL, TransactionMessage, VersionedTransaction, TransactionInstruction, SystemProgram, AddressLookupTableAccount } from '@solana/web3.js';
9
+ import { TOKEN_2022_PROGRAM_ID, getAssociatedTokenAddressSync } from '@solana/spl-token';
10
+ import BN from 'bn.js';
11
+ import { sha256 } from '@noble/hashes/sha2';
8
12
 
9
13
  // src/m0AutomaticRoute.ts
10
- var _M0AutomaticRoute = class _M0AutomaticRoute extends routes.AutomaticRoute {
11
- static solanaContracts(network) {
14
+ var SolanaRoutes = class {
15
+ constructor(network) {
16
+ if (network === "Devnet") {
17
+ throw new Error("Solana does not support Devnet for NTT contracts");
18
+ }
19
+ this.network = network;
20
+ this.programs = {
21
+ Mainnet: {
22
+ swap: pk("MSwapi3WhNKMUGm9YrxGhypgUEt7wYQH3ZgG32XoWzH"),
23
+ earn: pk("mz2vDzjbQDUDXBH6FPF5s4odCJ4y8YLE5QWaZ8XdZ9Z"),
24
+ lut: pk("9JLRqBqkznKiSoNfotA4ywSRdnWb2fE76SiFrAfkaRCD"),
25
+ mMint: pk("mzerokyEX9TNDoK4o2YZQBDmMzjokAeN6M2g2S3pLJo"),
26
+ portal: pk("mzp1q2j5Hr1QuLC3KFBCAUz5aUckT6qyuZKZ3WJnMmY"),
27
+ quoter: pk("Nqd6XqA8LbsCuG8MLWWuP865NV6jR1MbXeKxD4HLKDJ")
28
+ },
29
+ Testnet: {
30
+ swap: pk("MSwapi3WhNKMUGm9YrxGhypgUEt7wYQH3ZgG32XoWzH"),
31
+ earn: pk("mz2vDzjbQDUDXBH6FPF5s4odCJ4y8YLE5QWaZ8XdZ9Z"),
32
+ lut: pk("6GhuWPuAmiJeeSVsr58KjqHcAejJRndCx9BVtHkaYHUR"),
33
+ mMint: pk("mzeroZRGCah3j5xEWp2Nih3GDejSBbH1rbHoxDg8By6"),
34
+ portal: pk("mzp1q2j5Hr1QuLC3KFBCAUz5aUckT6qyuZKZ3WJnMmY"),
35
+ quoter: pk("Nqd6XqA8LbsCuG8MLWWuP865NV6jR1MbXeKxD4HLKDJ")
36
+ }
37
+ }[network];
38
+ this.extPrograms = {
39
+ Mainnet: {
40
+ mzeroXDoBpRVhnEXBra27qzAMdxgpWVY3DzQW7xMVJp: {
41
+ program: pk("wMXX1K1nca5W4pZr1piETe78gcAVVrEFi9f4g46uXko"),
42
+ tokenProgram: TOKEN_2022_PROGRAM_ID
43
+ },
44
+ usdkbee86pkLyRmxfFCdkyySpxRb5ndCxVsK2BkRXwX: {
45
+ program: pk("extaykYu5AQcDm3qZAbiDN3yp6skqn6Nssj7veUUGZw"),
46
+ tokenProgram: TOKEN_2022_PROGRAM_ID
47
+ },
48
+ usdkyPPxgV7sfNyKb8eDz66ogPrkRXG3wS2FVb6LLUf: {
49
+ program: pk("extMahs9bUFMYcviKCvnSRaXgs5PcqmMzcnHRtTqE85"),
50
+ tokenProgram: TOKEN_2022_PROGRAM_ID
51
+ }
52
+ },
53
+ Testnet: {
54
+ mzeroXDoBpRVhnEXBra27qzAMdxgpWVY3DzQW7xMVJp: {
55
+ program: pk("wMXX1K1nca5W4pZr1piETe78gcAVVrEFi9f4g46uXko"),
56
+ tokenProgram: TOKEN_2022_PROGRAM_ID
57
+ },
58
+ usdkbee86pkLyRmxfFCdkyySpxRb5ndCxVsK2BkRXwX: {
59
+ program: pk("Fb2AsCKmPd4gKhabT6KsremSHMrJ8G2Mopnc6rDQZX9e"),
60
+ tokenProgram: TOKEN_2022_PROGRAM_ID
61
+ },
62
+ usdkyPPxgV7sfNyKb8eDz66ogPrkRXG3wS2FVb6LLUf: {
63
+ program: pk("3PskKTHgboCbUSQPMcCAZdZNFHbNvSoZ8zEFYANCdob7"),
64
+ tokenProgram: TOKEN_2022_PROGRAM_ID
65
+ }
66
+ }
67
+ }[network];
68
+ }
69
+ getSolanaContracts() {
12
70
  return {
13
- token: network == "Mainnet" ? this.SOLANA_MAINNET_M_TOKEN : this.SOLANA_TESTNET_M_TOKEN,
14
- // Only M token can be bridged from Solana
15
- mLikeTokens: [],
16
- manager: "mzp1q2j5Hr1QuLC3KFBCAUz5aUckT6qyuZKZ3WJnMmY",
17
- transceiver: { wormhole: "mzp1q2j5Hr1QuLC3KFBCAUz5aUckT6qyuZKZ3WJnMmY" },
18
- quoter: "Nqd6XqA8LbsCuG8MLWWuP865NV6jR1MbXeKxD4HLKDJ"
71
+ token: this.programs.mMint.toBase58(),
72
+ mLikeTokens: Object.keys(this.extPrograms),
73
+ manager: this.programs.portal.toBase58(),
74
+ transceiver: { wormhole: this.programs.portal.toBase58() },
75
+ quoter: this.programs.quoter.toBase58()
19
76
  };
20
77
  }
78
+ getTransferExtensionBurnIx(ntt, amount2, recipient, payer, outboxItem, extMint, destinationToken, shouldQueue = true) {
79
+ const recipientAddress = Buffer.alloc(32);
80
+ const dest = Buffer.from(recipient.address.toUint8Array());
81
+ dest.copy(recipientAddress);
82
+ if (destinationToken.length !== 32) {
83
+ throw new Error(
84
+ `destinationToken must be 32 bytes, got ${destinationToken.length} bytes`
85
+ );
86
+ }
87
+ const extension = this.extPrograms[extMint.toBase58()];
88
+ if (!extension) {
89
+ throw new Error(
90
+ `No extension program found for mint ${extMint.toBase58()}`
91
+ );
92
+ }
93
+ const { program: extProgram, tokenProgram: extTokenProgram } = extension;
94
+ return new TransactionInstruction({
95
+ programId: ntt.program.programId,
96
+ keys: [
97
+ {
98
+ pubkey: payer,
99
+ isSigner: true,
100
+ isWritable: true
101
+ },
102
+ {
103
+ // config
104
+ pubkey: ntt.pdas.configAccount(),
105
+ isSigner: false,
106
+ isWritable: false
107
+ },
108
+ {
109
+ // m mint
110
+ pubkey: this.programs.mMint,
111
+ isSigner: false,
112
+ isWritable: true
113
+ },
114
+ {
115
+ // from (token auth m token account)
116
+ pubkey: getAssociatedTokenAddressSync(
117
+ this.programs.mMint,
118
+ PublicKey.findProgramAddressSync(
119
+ [Buffer.from("token_authority")],
120
+ ntt.program.programId
121
+ )[0],
122
+ true,
123
+ TOKEN_2022_PROGRAM_ID
124
+ ),
125
+ isSigner: false,
126
+ isWritable: true
127
+ },
128
+ {
129
+ // m token program
130
+ pubkey: TOKEN_2022_PROGRAM_ID,
131
+ isSigner: false,
132
+ isWritable: false
133
+ },
134
+ {
135
+ // outbox item
136
+ pubkey: outboxItem,
137
+ isSigner: true,
138
+ isWritable: true
139
+ },
140
+ {
141
+ // outbox rate limit
142
+ pubkey: ntt.pdas.outboxRateLimitAccount(),
143
+ isSigner: false,
144
+ isWritable: true
145
+ },
146
+ {
147
+ // custody
148
+ pubkey: ntt.config.custody,
149
+ isSigner: false,
150
+ isWritable: true
151
+ },
152
+ {
153
+ // system program
154
+ pubkey: SystemProgram.programId,
155
+ isSigner: false,
156
+ isWritable: false
157
+ },
158
+ {
159
+ // inbox rate limit
160
+ pubkey: ntt.pdas.inboxRateLimitAccount(recipient.chain),
161
+ isSigner: false,
162
+ isWritable: true
163
+ },
164
+ {
165
+ // peer
166
+ pubkey: ntt.pdas.peerAccount(recipient.chain),
167
+ isSigner: false,
168
+ isWritable: false
169
+ },
170
+ {
171
+ // session auth
172
+ pubkey: ntt.pdas.sessionAuthority(payer, {
173
+ amount: new BN(amount2),
174
+ recipientChain: {
175
+ id: 2
176
+ // Ethereum
177
+ },
178
+ recipientAddress: [...Array(32)],
179
+ shouldQueue: false
180
+ }),
181
+ isSigner: false,
182
+ isWritable: false
183
+ },
184
+ {
185
+ // token auth
186
+ pubkey: PublicKey.findProgramAddressSync(
187
+ [Buffer.from("token_authority")],
188
+ ntt.program.programId
189
+ )[0],
190
+ isSigner: false,
191
+ isWritable: false
192
+ },
193
+ {
194
+ // ext mint
195
+ pubkey: extMint,
196
+ isSigner: false,
197
+ isWritable: true
198
+ },
199
+ {
200
+ // swap global
201
+ pubkey: PublicKey.findProgramAddressSync(
202
+ [Buffer.from("global")],
203
+ this.programs.swap
204
+ )[0],
205
+ isSigner: false,
206
+ isWritable: false
207
+ },
208
+ {
209
+ // m global
210
+ pubkey: PublicKey.findProgramAddressSync(
211
+ [Buffer.from("global")],
212
+ this.programs.earn
213
+ )[0],
214
+ isSigner: false,
215
+ isWritable: false
216
+ },
217
+ {
218
+ // ext global
219
+ pubkey: PublicKey.findProgramAddressSync(
220
+ [Buffer.from("global")],
221
+ extProgram
222
+ )[0],
223
+ isSigner: false,
224
+ isWritable: true
225
+ },
226
+ {
227
+ // ext token account
228
+ pubkey: getAssociatedTokenAddressSync(
229
+ extMint,
230
+ payer,
231
+ true,
232
+ extTokenProgram
233
+ ),
234
+ isSigner: false,
235
+ isWritable: true
236
+ },
237
+ {
238
+ // ext m vault
239
+ pubkey: getAssociatedTokenAddressSync(
240
+ this.programs.mMint,
241
+ PublicKey.findProgramAddressSync(
242
+ [Buffer.from("m_vault")],
243
+ extProgram
244
+ )[0],
245
+ true,
246
+ TOKEN_2022_PROGRAM_ID
247
+ ),
248
+ isSigner: false,
249
+ isWritable: true
250
+ },
251
+ {
252
+ // ext m vault auth
253
+ pubkey: PublicKey.findProgramAddressSync(
254
+ [Buffer.from("m_vault")],
255
+ extProgram
256
+ )[0],
257
+ isSigner: false,
258
+ isWritable: false
259
+ },
260
+ {
261
+ // ext mint auth
262
+ pubkey: PublicKey.findProgramAddressSync(
263
+ [Buffer.from("mint_authority")],
264
+ extProgram
265
+ )[0],
266
+ isSigner: false,
267
+ isWritable: false
268
+ },
269
+ {
270
+ // ext program
271
+ pubkey: extProgram,
272
+ isSigner: false,
273
+ isWritable: false
274
+ },
275
+ {
276
+ // swap program
277
+ pubkey: this.programs.swap,
278
+ isSigner: false,
279
+ isWritable: false
280
+ },
281
+ {
282
+ // ext token program
283
+ pubkey: extTokenProgram,
284
+ isSigner: false,
285
+ isWritable: false
286
+ }
287
+ ],
288
+ data: Buffer.concat([
289
+ Buffer.from(sha256("global:transfer_extension_burn").subarray(0, 8)),
290
+ new BN(amount2).toArrayLike(Buffer, "le", 8),
291
+ // amount
292
+ new BN(chainToChainId(recipient.chain)).toArrayLike(Buffer, "le", 2),
293
+ // chain_id
294
+ recipientAddress,
295
+ // recipient_address
296
+ destinationToken,
297
+ // destination_token
298
+ Buffer.from([Number(shouldQueue)])
299
+ // should_queue
300
+ ])
301
+ });
302
+ }
303
+ getReleaseInboundMintExtensionIx(ntt, payer, inboxItem, mMint, extMint, extAta) {
304
+ const extension = this.extPrograms[extMint.toBase58()];
305
+ if (!extension) {
306
+ throw new Error(
307
+ `No extension program found for mint ${extMint.toBase58()}`
308
+ );
309
+ }
310
+ const { program: extProgram, tokenProgram: extTokenProgram } = extension;
311
+ return new TransactionInstruction({
312
+ programId: ntt.program.programId,
313
+ keys: [
314
+ {
315
+ pubkey: pk(payer),
316
+ isSigner: true,
317
+ isWritable: true
318
+ },
319
+ {
320
+ // config
321
+ pubkey: ntt.pdas.configAccount(),
322
+ isSigner: false,
323
+ isWritable: false
324
+ },
325
+ {
326
+ // inbox item
327
+ pubkey: inboxItem,
328
+ isSigner: false,
329
+ isWritable: true
330
+ },
331
+ {
332
+ // recipient (mint to token auth which wraps to user)
333
+ pubkey: getAssociatedTokenAddressSync(
334
+ mMint,
335
+ PublicKey.findProgramAddressSync(
336
+ [Buffer.from("token_authority")],
337
+ ntt.program.programId
338
+ )[0],
339
+ true,
340
+ TOKEN_2022_PROGRAM_ID
341
+ ),
342
+ isSigner: false,
343
+ isWritable: true
344
+ },
345
+ {
346
+ // token auth
347
+ pubkey: PublicKey.findProgramAddressSync(
348
+ [Buffer.from("token_authority")],
349
+ ntt.program.programId
350
+ )[0],
351
+ isSigner: false,
352
+ isWritable: false
353
+ },
354
+ {
355
+ // m mint
356
+ pubkey: mMint,
357
+ isSigner: false,
358
+ isWritable: true
359
+ },
360
+ {
361
+ // m token program
362
+ pubkey: TOKEN_2022_PROGRAM_ID,
363
+ isSigner: false,
364
+ isWritable: false
365
+ },
366
+ {
367
+ // custody
368
+ pubkey: ntt.config.custody,
369
+ isSigner: false,
370
+ isWritable: true
371
+ },
372
+ {
373
+ // earn program
374
+ pubkey: this.programs.earn,
375
+ isSigner: false,
376
+ isWritable: false
377
+ },
378
+ {
379
+ // m global
380
+ pubkey: PublicKey.findProgramAddressSync(
381
+ [Buffer.from("global")],
382
+ this.programs.earn
383
+ )[0],
384
+ isSigner: false,
385
+ isWritable: false
386
+ },
387
+ {
388
+ // ext mint
389
+ pubkey: extMint,
390
+ isSigner: false,
391
+ isWritable: true
392
+ },
393
+ {
394
+ // swap global
395
+ pubkey: PublicKey.findProgramAddressSync(
396
+ [Buffer.from("global")],
397
+ this.programs.swap
398
+ )[0],
399
+ isSigner: false,
400
+ isWritable: false
401
+ },
402
+ {
403
+ // ext global
404
+ pubkey: PublicKey.findProgramAddressSync(
405
+ [Buffer.from("global")],
406
+ extProgram
407
+ )[0],
408
+ isSigner: false,
409
+ isWritable: true
410
+ },
411
+ {
412
+ // ext m vault auth
413
+ pubkey: PublicKey.findProgramAddressSync(
414
+ [Buffer.from("m_vault")],
415
+ extProgram
416
+ )[0],
417
+ isSigner: false,
418
+ isWritable: false
419
+ },
420
+ {
421
+ // ext mint auth
422
+ pubkey: PublicKey.findProgramAddressSync(
423
+ [Buffer.from("mint_authority")],
424
+ extProgram
425
+ )[0],
426
+ isSigner: false,
427
+ isWritable: false
428
+ },
429
+ {
430
+ // ext m vault
431
+ pubkey: getAssociatedTokenAddressSync(
432
+ mMint,
433
+ PublicKey.findProgramAddressSync(
434
+ [Buffer.from("m_vault")],
435
+ extProgram
436
+ )[0],
437
+ true,
438
+ TOKEN_2022_PROGRAM_ID
439
+ ),
440
+ isSigner: false,
441
+ isWritable: true
442
+ },
443
+ {
444
+ // ext token account
445
+ pubkey: extAta,
446
+ isSigner: false,
447
+ isWritable: true
448
+ },
449
+ {
450
+ // ext token account
451
+ pubkey: this.programs.swap,
452
+ isSigner: false,
453
+ isWritable: false
454
+ },
455
+ {
456
+ // ext program
457
+ pubkey: extProgram,
458
+ isSigner: false,
459
+ isWritable: false
460
+ },
461
+ {
462
+ // ext token program
463
+ pubkey: extTokenProgram,
464
+ isSigner: false,
465
+ isWritable: false
466
+ },
467
+ {
468
+ // system program
469
+ pubkey: SystemProgram.programId,
470
+ isSigner: false,
471
+ isWritable: false
472
+ }
473
+ ],
474
+ data: Buffer.concat([
475
+ Buffer.from(
476
+ sha256("global:release_inbound_mint_extension").subarray(0, 8)
477
+ )
478
+ ])
479
+ });
480
+ }
481
+ async getAddressLookupTableAccounts(connection) {
482
+ const info = await connection.getAccountInfo(this.programs.lut);
483
+ return new AddressLookupTableAccount({
484
+ key: this.programs.lut,
485
+ state: AddressLookupTableAccount.deserialize(info.data)
486
+ });
487
+ }
488
+ };
489
+ function pk(address) {
490
+ return new PublicKey(address);
491
+ }
492
+
493
+ // src/m0AutomaticRoute.ts
494
+ var _M0AutomaticRoute = class _M0AutomaticRoute extends routes.AutomaticRoute {
21
495
  static supportedNetworks() {
22
496
  return ["Mainnet", "Testnet"];
23
497
  }
@@ -27,9 +501,15 @@ var _M0AutomaticRoute = class _M0AutomaticRoute extends routes.AutomaticRoute {
27
501
  static supportedChains(network) {
28
502
  switch (network) {
29
503
  case "Mainnet":
30
- return ["Ethereum", "Arbitrum", "Optimism", "Solana"];
504
+ return ["Ethereum", "Arbitrum", "Optimism", "Solana", "Fogo"];
31
505
  case "Testnet":
32
- return ["Sepolia", "ArbitrumSepolia", "OptimismSepolia", "Solana"];
506
+ return [
507
+ "Sepolia",
508
+ "ArbitrumSepolia",
509
+ "OptimismSepolia",
510
+ "Solana",
511
+ "Fogo"
512
+ ];
33
513
  default:
34
514
  throw new Error(`Unsupported network: ${network}`);
35
515
  }
@@ -49,7 +529,9 @@ var _M0AutomaticRoute = class _M0AutomaticRoute extends routes.AutomaticRoute {
49
529
  case "ArbitrumSepolia":
50
530
  return this.EVM_CONTRACTS;
51
531
  case "Solana":
52
- return this.solanaContracts(chainContext.network);
532
+ return new SolanaRoutes(chainContext.network).getSolanaContracts();
533
+ case "Fogo":
534
+ return new SolanaRoutes(chainContext.network).getSolanaContracts();
53
535
  default:
54
536
  throw new Error(`Unsupported chain: ${chainContext.chain}`);
55
537
  }
@@ -67,10 +549,9 @@ var _M0AutomaticRoute = class _M0AutomaticRoute extends routes.AutomaticRoute {
67
549
  return [];
68
550
  }
69
551
  const { token: mToken, mLikeTokens } = this.getContracts(toChain);
70
- return [
71
- Wormhole.tokenId(toChain.chain, mToken),
72
- ...mLikeTokens.map((x) => Wormhole.tokenId(toChain.chain, x))
73
- ];
552
+ return [mToken, ...mLikeTokens].map(
553
+ (x) => Wormhole.tokenId(toChain.chain, x)
554
+ );
74
555
  }
75
556
  static isProtocolSupported(chain) {
76
557
  return chain.supportsProtocol("Ntt");
@@ -165,14 +646,39 @@ var _M0AutomaticRoute = class _M0AutomaticRoute extends routes.AutomaticRoute {
165
646
  const platform = chainToPlatform(fromChain.chain);
166
647
  const transferAmount = amount.units(params.normalizedParams.amount);
167
648
  const options = params.normalizedParams.options;
168
- if (platform !== "Evm" && platform !== "Solana")
649
+ if (!_M0AutomaticRoute.isPlatformSupported(platform))
169
650
  throw new Error(`Unsupported platform ${platform}`);
170
651
  const ntt = await fromChain.getProtocol("Ntt", {
171
652
  ntt: _M0AutomaticRoute.getContracts(fromChain)
172
653
  });
173
654
  const sourceToken = canonicalAddress(request.source.id);
174
655
  const destinationToken = canonicalAddress(request.destination.id);
175
- const initXfer = platform === "Evm" ? this.transferMLike(ntt, sender, transferAmount, to, sourceToken, destinationToken, options) : ntt.transfer(sender, transferAmount, to, options);
656
+ const initXfer = platform === "Evm" ? (
657
+ // for EVM call transferMLike function
658
+ this.transferMLike(
659
+ ntt,
660
+ // @ts-ignore
661
+ sender,
662
+ transferAmount,
663
+ to,
664
+ sourceToken,
665
+ destinationToken,
666
+ options
667
+ )
668
+ ) : (
669
+ // for Solana use custom transfer instruction
670
+ this.transferSolanaExtension(
671
+ ntt,
672
+ request.fromChain.network,
673
+ // @ts-ignore
674
+ sender,
675
+ transferAmount,
676
+ to,
677
+ sourceToken,
678
+ destinationToken,
679
+ options
680
+ )
681
+ );
176
682
  const txids = await signSendWait(fromChain, initXfer, signer);
177
683
  return {
178
684
  from: fromChain.chain,
@@ -232,6 +738,76 @@ var _M0AutomaticRoute = class _M0AutomaticRoute extends routes.AutomaticRoute {
232
738
  parallelizable
233
739
  );
234
740
  }
741
+ async *transferSolanaExtension(ntt, network, sender, amount2, recipient, sourceToken, destinationToken, options) {
742
+ const router = new SolanaRoutes(network);
743
+ if (router.getSolanaContracts().token === sourceToken) {
744
+ return ntt.transfer(sender, amount2, recipient, options);
745
+ }
746
+ const config = await ntt.getConfig();
747
+ if (config.paused) throw new Error("Contract is paused");
748
+ const outboxItem = Keypair.generate();
749
+ const payerAddress = new SolanaAddress(sender).unwrap();
750
+ const ixs = [
751
+ router.getTransferExtensionBurnIx(
752
+ ntt,
753
+ amount2,
754
+ recipient,
755
+ new PublicKey(sender.toUint8Array()),
756
+ outboxItem.publicKey,
757
+ new PublicKey(sourceToken),
758
+ toUniversal(recipient.chain, destinationToken).toUint8Array(),
759
+ options.queue
760
+ )
761
+ ];
762
+ for (let ix = 0; ix < ntt.transceivers.length; ++ix) {
763
+ if (ix === 0) {
764
+ const whTransceiver = await ntt.getWormholeTransceiver();
765
+ if (!whTransceiver) {
766
+ throw new Error("wormhole transceiver not found");
767
+ }
768
+ const releaseIx = await whTransceiver.createReleaseWormholeOutboundIx(
769
+ payerAddress,
770
+ outboxItem.publicKey,
771
+ !options.queue
772
+ );
773
+ ixs.push(releaseIx);
774
+ }
775
+ }
776
+ const tx = new Transaction();
777
+ tx.feePayer = payerAddress;
778
+ tx.add(...ixs);
779
+ if (options.automatic) {
780
+ if (!ntt.quoter)
781
+ throw new Error(
782
+ "No quoter available, cannot initiate an automatic transfer."
783
+ );
784
+ const fee = await ntt.quoteDeliveryPrice(recipient.chain, options);
785
+ const relayIx = await ntt.quoter.createRequestRelayInstruction(
786
+ payerAddress,
787
+ outboxItem.publicKey,
788
+ recipient.chain,
789
+ Number(fee) / LAMPORTS_PER_SOL,
790
+ Number(options.gasDropoff ?? 0n) / WEI_PER_GWEI
791
+ );
792
+ tx.add(relayIx);
793
+ }
794
+ const luts = [];
795
+ try {
796
+ luts.push(await ntt.getAddressLookupTable());
797
+ luts.push(await router.getAddressLookupTableAccounts(ntt.connection));
798
+ } catch {
799
+ }
800
+ const messageV0 = new TransactionMessage({
801
+ payerKey: payerAddress,
802
+ instructions: tx.instructions,
803
+ recentBlockhash: (await ntt.connection.getLatestBlockhash()).blockhash
804
+ }).compileToV0Message(luts);
805
+ const vtx = new VersionedTransaction(messageV0);
806
+ yield ntt.createUnsignedTx(
807
+ { transaction: vtx, signers: [outboxItem] },
808
+ "Ntt.Transfer"
809
+ );
810
+ }
235
811
  async *track(receipt, timeout) {
236
812
  const isEvmPlatform = (chain) => chainToPlatform(chain) === "Evm";
237
813
  if (isSourceInitiated(receipt) || isSourceFinalized(receipt)) {
@@ -274,7 +850,9 @@ var _M0AutomaticRoute = class _M0AutomaticRoute extends routes.AutomaticRoute {
274
850
  }
275
851
  }
276
852
  if (isRedeemed(receipt)) {
277
- const { attestation: { attestation: vaa } } = receipt;
853
+ const {
854
+ attestation: { attestation: vaa }
855
+ } = receipt;
278
856
  const payload = vaa.payloadName === "WormholeTransfer" ? vaa.payload : vaa.payload["payload"];
279
857
  const isExecuted = isEvmPlatform(receipt.to) ? await ntt.manager.isMessageExecuted(
280
858
  Ntt.messageDigest(vaa.emitterChain, payload["nttManagerPayload"])
@@ -294,8 +872,6 @@ var _M0AutomaticRoute = class _M0AutomaticRoute extends routes.AutomaticRoute {
294
872
  _M0AutomaticRoute.NATIVE_GAS_DROPOFF_SUPPORTED = false;
295
873
  // Wrapped M token address is the same on EVM chains
296
874
  _M0AutomaticRoute.EVM_WRAPPED_M_TOKEN = "0x437cc33344a0B27A429f795ff6B469C72698B291";
297
- _M0AutomaticRoute.SOLANA_MAINNET_M_TOKEN = "mzerokyEX9TNDoK4o2YZQBDmMzjokAeN6M2g2S3pLJo";
298
- _M0AutomaticRoute.SOLANA_TESTNET_M_TOKEN = "mzeroZRGCah3j5xEWp2Nih3GDejSBbH1rbHoxDg8By6";
299
875
  // Contract addresses are the same on all EVM chains
300
876
  _M0AutomaticRoute.EVM_CONTRACTS = {
301
877
  // M token address is the same on EVM chains
@@ -310,4 +886,4 @@ _M0AutomaticRoute.EVM_CONTRACTS = {
310
886
  _M0AutomaticRoute.meta = { name: "M0AutomaticRoute", provider: "M0" };
311
887
  var M0AutomaticRoute = _M0AutomaticRoute;
312
888
 
313
- export { M0AutomaticRoute };
889
+ export { M0AutomaticRoute, SolanaRoutes };