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

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.d.mts CHANGED
@@ -44,26 +44,36 @@ declare class M0AutomaticRoute<N extends Network> extends routes.AutomaticRoute<
44
44
  */
45
45
  transferMLike<N extends Network, C extends EvmChains>(ntt: EvmNtt<N, C>, sender: AccountAddress<C>, amount: bigint, destination: ChainAddress, sourceToken: string, destinationToken: string, options: Ntt.TransferOptions): AsyncGenerator<EvmUnsignedTransaction<N, C>>;
46
46
  createUnsignedTx<N extends Network, C extends EvmChains>(ntt: EvmNtt<N, C>, txReq: TransactionRequest, description: string, parallelizable?: boolean): EvmUnsignedTransaction<N, C>;
47
- transferSolanaExtension<N extends Network, C extends SolanaChains>(ntt: SolanaNtt<N, C>, network: Network, sender: AccountAddress<C>, amount: bigint, recipient: ChainAddress, sourceToken: string, destinationToken: string, options: Ntt.TransferOptions): AsyncGenerator<SolanaUnsignedTransaction<N, C>>;
47
+ transferSolanaExtension<N extends Network, C extends SolanaChains>(ntt: SolanaNtt<N, C>, sender: AccountAddress<C>, amount: bigint, recipient: ChainAddress, sourceToken: string, destinationToken: string, options: Ntt.TransferOptions): AsyncGenerator<SolanaUnsignedTransaction<N, C>>;
48
48
  track(receipt: R, timeout?: number): AsyncGenerator<R, void, unknown>;
49
49
  }
50
50
 
51
- type SolanaNetwork = Exclude<Network, "Devnet">;
51
+ type SvmNetwork = Exclude<Network, "Devnet">;
52
52
  type ExtensionDetails = {
53
53
  program: PublicKey;
54
54
  tokenProgram: PublicKey;
55
55
  };
56
- declare class SolanaRoutes {
57
- network: SolanaNetwork;
56
+ declare class SolanaRoutes<N extends Network, C extends SolanaChains> {
57
+ ntt: SolanaNtt<N, C>;
58
+ network: SvmNetwork;
58
59
  programs: Record<string, PublicKey>;
59
60
  extPrograms: Record<string, ExtensionDetails>;
60
- constructor(network: Network);
61
- getSolanaContracts(): Ntt.Contracts & {
61
+ constructor(ntt: SolanaNtt<N, C>);
62
+ private static getPrograms;
63
+ private static getExtPrograms;
64
+ static getSolanaContracts(chainContext: ChainContext<Network>): Ntt.Contracts & {
62
65
  mLikeTokens: string[];
63
66
  };
64
- getTransferExtensionBurnIx<N extends Network, C extends SolanaChains>(ntt: SolanaNtt<N, C>, amount: bigint, recipient: ChainAddress, payer: PublicKey, outboxItem: PublicKey, extMint: PublicKey, destinationToken: Uint8Array, shouldQueue?: boolean): TransactionInstruction;
65
- getReleaseInboundMintExtensionIx<N extends Network, C extends SolanaChains>(ntt: SolanaNtt<N, C>, payer: string, inboxItem: PublicKey, mMint: PublicKey, extMint: PublicKey, extAta: PublicKey): TransactionInstruction;
67
+ getTransferExtensionBurnIx(amount: bigint, recipient: ChainAddress, payer: PublicKey, outboxItem: PublicKey, extMint: PublicKey, destinationToken: Uint8Array, shouldQueue?: boolean): TransactionInstruction;
68
+ getReleaseInboundMintExtensionIx(nttMessage: Ntt.Message, emitterChain: Chain, payer: PublicKey, extMint: PublicKey, extAta: PublicKey): TransactionInstruction;
66
69
  getAddressLookupTableAccounts(connection: Connection): Promise<AddressLookupTableAccount>;
70
+ static createReleaseInboundMintInstruction<N extends Network, C extends SolanaChains>(ntt: SolanaNtt<N, C>, args: {
71
+ payer: PublicKey;
72
+ chain: Chain;
73
+ nttMessage: Ntt.Message;
74
+ recipient: PublicKey;
75
+ revertWhenNotReady: boolean;
76
+ }): Promise<TransactionInstruction[]>;
67
77
  }
68
78
 
69
79
  export { M0AutomaticRoute, SolanaRoutes };
package/dist/index.d.ts CHANGED
@@ -44,26 +44,36 @@ declare class M0AutomaticRoute<N extends Network> extends routes.AutomaticRoute<
44
44
  */
45
45
  transferMLike<N extends Network, C extends EvmChains>(ntt: EvmNtt<N, C>, sender: AccountAddress<C>, amount: bigint, destination: ChainAddress, sourceToken: string, destinationToken: string, options: Ntt.TransferOptions): AsyncGenerator<EvmUnsignedTransaction<N, C>>;
46
46
  createUnsignedTx<N extends Network, C extends EvmChains>(ntt: EvmNtt<N, C>, txReq: TransactionRequest, description: string, parallelizable?: boolean): EvmUnsignedTransaction<N, C>;
47
- transferSolanaExtension<N extends Network, C extends SolanaChains>(ntt: SolanaNtt<N, C>, network: Network, sender: AccountAddress<C>, amount: bigint, recipient: ChainAddress, sourceToken: string, destinationToken: string, options: Ntt.TransferOptions): AsyncGenerator<SolanaUnsignedTransaction<N, C>>;
47
+ transferSolanaExtension<N extends Network, C extends SolanaChains>(ntt: SolanaNtt<N, C>, sender: AccountAddress<C>, amount: bigint, recipient: ChainAddress, sourceToken: string, destinationToken: string, options: Ntt.TransferOptions): AsyncGenerator<SolanaUnsignedTransaction<N, C>>;
48
48
  track(receipt: R, timeout?: number): AsyncGenerator<R, void, unknown>;
49
49
  }
50
50
 
51
- type SolanaNetwork = Exclude<Network, "Devnet">;
51
+ type SvmNetwork = Exclude<Network, "Devnet">;
52
52
  type ExtensionDetails = {
53
53
  program: PublicKey;
54
54
  tokenProgram: PublicKey;
55
55
  };
56
- declare class SolanaRoutes {
57
- network: SolanaNetwork;
56
+ declare class SolanaRoutes<N extends Network, C extends SolanaChains> {
57
+ ntt: SolanaNtt<N, C>;
58
+ network: SvmNetwork;
58
59
  programs: Record<string, PublicKey>;
59
60
  extPrograms: Record<string, ExtensionDetails>;
60
- constructor(network: Network);
61
- getSolanaContracts(): Ntt.Contracts & {
61
+ constructor(ntt: SolanaNtt<N, C>);
62
+ private static getPrograms;
63
+ private static getExtPrograms;
64
+ static getSolanaContracts(chainContext: ChainContext<Network>): Ntt.Contracts & {
62
65
  mLikeTokens: string[];
63
66
  };
64
- getTransferExtensionBurnIx<N extends Network, C extends SolanaChains>(ntt: SolanaNtt<N, C>, amount: bigint, recipient: ChainAddress, payer: PublicKey, outboxItem: PublicKey, extMint: PublicKey, destinationToken: Uint8Array, shouldQueue?: boolean): TransactionInstruction;
65
- getReleaseInboundMintExtensionIx<N extends Network, C extends SolanaChains>(ntt: SolanaNtt<N, C>, payer: string, inboxItem: PublicKey, mMint: PublicKey, extMint: PublicKey, extAta: PublicKey): TransactionInstruction;
67
+ getTransferExtensionBurnIx(amount: bigint, recipient: ChainAddress, payer: PublicKey, outboxItem: PublicKey, extMint: PublicKey, destinationToken: Uint8Array, shouldQueue?: boolean): TransactionInstruction;
68
+ getReleaseInboundMintExtensionIx(nttMessage: Ntt.Message, emitterChain: Chain, payer: PublicKey, extMint: PublicKey, extAta: PublicKey): TransactionInstruction;
66
69
  getAddressLookupTableAccounts(connection: Connection): Promise<AddressLookupTableAccount>;
70
+ static createReleaseInboundMintInstruction<N extends Network, C extends SolanaChains>(ntt: SolanaNtt<N, C>, args: {
71
+ payer: PublicKey;
72
+ chain: Chain;
73
+ nttMessage: Ntt.Message;
74
+ recipient: PublicKey;
75
+ revertWhenNotReady: boolean;
76
+ }): Promise<TransactionInstruction[]>;
67
77
  }
68
78
 
69
79
  export { M0AutomaticRoute, SolanaRoutes };
package/dist/index.js CHANGED
@@ -17,13 +17,15 @@ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
17
17
  var BN__default = /*#__PURE__*/_interopDefault(BN);
18
18
 
19
19
  // src/m0AutomaticRoute.ts
20
- var SolanaRoutes = class {
21
- constructor(network) {
22
- if (network === "Devnet") {
23
- throw new Error("Solana does not support Devnet for NTT contracts");
24
- }
25
- this.network = network;
26
- this.programs = {
20
+ var SolanaRoutes = class _SolanaRoutes {
21
+ constructor(ntt) {
22
+ this.ntt = ntt;
23
+ this.network = ntt.network;
24
+ this.programs = _SolanaRoutes.getPrograms(this.network);
25
+ this.extPrograms = _SolanaRoutes.getExtPrograms(this.network);
26
+ }
27
+ static getPrograms(network) {
28
+ return {
27
29
  Mainnet: {
28
30
  swap: pk("MSwapi3WhNKMUGm9YrxGhypgUEt7wYQH3ZgG32XoWzH"),
29
31
  earn: pk("mz2vDzjbQDUDXBH6FPF5s4odCJ4y8YLE5QWaZ8XdZ9Z"),
@@ -41,7 +43,9 @@ var SolanaRoutes = class {
41
43
  quoter: pk("Nqd6XqA8LbsCuG8MLWWuP865NV6jR1MbXeKxD4HLKDJ")
42
44
  }
43
45
  }[network];
44
- this.extPrograms = {
46
+ }
47
+ static getExtPrograms(network) {
48
+ return {
45
49
  Mainnet: {
46
50
  mzeroXDoBpRVhnEXBra27qzAMdxgpWVY3DzQW7xMVJp: {
47
51
  program: pk("wMXX1K1nca5W4pZr1piETe78gcAVVrEFi9f4g46uXko"),
@@ -72,16 +76,22 @@ var SolanaRoutes = class {
72
76
  }
73
77
  }[network];
74
78
  }
75
- getSolanaContracts() {
79
+ static getSolanaContracts(chainContext) {
80
+ const programs = _SolanaRoutes.getPrograms(
81
+ chainContext.network
82
+ );
83
+ const extPrograms = _SolanaRoutes.getExtPrograms(
84
+ chainContext.network
85
+ );
76
86
  return {
77
- token: this.programs.mMint.toBase58(),
78
- mLikeTokens: Object.keys(this.extPrograms),
79
- manager: this.programs.portal.toBase58(),
80
- transceiver: { wormhole: this.programs.portal.toBase58() },
81
- quoter: this.programs.quoter.toBase58()
87
+ token: programs.mMint.toBase58(),
88
+ mLikeTokens: Object.keys(extPrograms),
89
+ manager: programs.portal.toBase58(),
90
+ transceiver: { wormhole: programs.portal.toBase58() },
91
+ quoter: programs.quoter.toBase58()
82
92
  };
83
93
  }
84
- getTransferExtensionBurnIx(ntt, amount2, recipient, payer, outboxItem, extMint, destinationToken, shouldQueue = true) {
94
+ getTransferExtensionBurnIx(amount2, recipient, payer, outboxItem, extMint, destinationToken, shouldQueue = true) {
85
95
  const recipientAddress = Buffer.alloc(32);
86
96
  const dest = Buffer.from(recipient.address.toUint8Array());
87
97
  dest.copy(recipientAddress);
@@ -98,7 +108,7 @@ var SolanaRoutes = class {
98
108
  }
99
109
  const { program: extProgram, tokenProgram: extTokenProgram } = extension;
100
110
  return new web3_js.TransactionInstruction({
101
- programId: ntt.program.programId,
111
+ programId: this.ntt.program.programId,
102
112
  keys: [
103
113
  {
104
114
  pubkey: payer,
@@ -107,7 +117,7 @@ var SolanaRoutes = class {
107
117
  },
108
118
  {
109
119
  // config
110
- pubkey: ntt.pdas.configAccount(),
120
+ pubkey: this.ntt.pdas.configAccount(),
111
121
  isSigner: false,
112
122
  isWritable: false
113
123
  },
@@ -123,7 +133,7 @@ var SolanaRoutes = class {
123
133
  this.programs.mMint,
124
134
  web3_js.PublicKey.findProgramAddressSync(
125
135
  [Buffer.from("token_authority")],
126
- ntt.program.programId
136
+ this.ntt.program.programId
127
137
  )[0],
128
138
  true,
129
139
  splToken.TOKEN_2022_PROGRAM_ID
@@ -145,13 +155,13 @@ var SolanaRoutes = class {
145
155
  },
146
156
  {
147
157
  // outbox rate limit
148
- pubkey: ntt.pdas.outboxRateLimitAccount(),
158
+ pubkey: this.ntt.pdas.outboxRateLimitAccount(),
149
159
  isSigner: false,
150
160
  isWritable: true
151
161
  },
152
162
  {
153
163
  // custody
154
- pubkey: ntt.config.custody,
164
+ pubkey: this.ntt.config.custody,
155
165
  isSigner: false,
156
166
  isWritable: true
157
167
  },
@@ -163,19 +173,19 @@ var SolanaRoutes = class {
163
173
  },
164
174
  {
165
175
  // inbox rate limit
166
- pubkey: ntt.pdas.inboxRateLimitAccount(recipient.chain),
176
+ pubkey: this.ntt.pdas.inboxRateLimitAccount(recipient.chain),
167
177
  isSigner: false,
168
178
  isWritable: true
169
179
  },
170
180
  {
171
181
  // peer
172
- pubkey: ntt.pdas.peerAccount(recipient.chain),
182
+ pubkey: this.ntt.pdas.peerAccount(recipient.chain),
173
183
  isSigner: false,
174
184
  isWritable: false
175
185
  },
176
186
  {
177
187
  // session auth
178
- pubkey: ntt.pdas.sessionAuthority(payer, {
188
+ pubkey: this.ntt.pdas.sessionAuthority(payer, {
179
189
  amount: new BN__default.default(amount2),
180
190
  recipientChain: {
181
191
  id: 2
@@ -191,7 +201,7 @@ var SolanaRoutes = class {
191
201
  // token auth
192
202
  pubkey: web3_js.PublicKey.findProgramAddressSync(
193
203
  [Buffer.from("token_authority")],
194
- ntt.program.programId
204
+ this.ntt.program.programId
195
205
  )[0],
196
206
  isSigner: false,
197
207
  isWritable: false
@@ -306,7 +316,7 @@ var SolanaRoutes = class {
306
316
  ])
307
317
  });
308
318
  }
309
- getReleaseInboundMintExtensionIx(ntt, payer, inboxItem, mMint, extMint, extAta) {
319
+ getReleaseInboundMintExtensionIx(nttMessage, emitterChain, payer, extMint, extAta) {
310
320
  const extension = this.extPrograms[extMint.toBase58()];
311
321
  if (!extension) {
312
322
  throw new Error(
@@ -315,32 +325,32 @@ var SolanaRoutes = class {
315
325
  }
316
326
  const { program: extProgram, tokenProgram: extTokenProgram } = extension;
317
327
  return new web3_js.TransactionInstruction({
318
- programId: ntt.program.programId,
328
+ programId: this.ntt.program.programId,
319
329
  keys: [
320
330
  {
321
- pubkey: pk(payer),
331
+ pubkey: payer,
322
332
  isSigner: true,
323
333
  isWritable: true
324
334
  },
325
335
  {
326
336
  // config
327
- pubkey: ntt.pdas.configAccount(),
337
+ pubkey: this.ntt.pdas.configAccount(),
328
338
  isSigner: false,
329
339
  isWritable: false
330
340
  },
331
341
  {
332
342
  // inbox item
333
- pubkey: inboxItem,
343
+ pubkey: this.ntt.pdas.inboxItemAccount(emitterChain, nttMessage),
334
344
  isSigner: false,
335
345
  isWritable: true
336
346
  },
337
347
  {
338
348
  // recipient (mint to token auth which wraps to user)
339
349
  pubkey: splToken.getAssociatedTokenAddressSync(
340
- mMint,
350
+ this.ntt.config.mint,
341
351
  web3_js.PublicKey.findProgramAddressSync(
342
352
  [Buffer.from("token_authority")],
343
- ntt.program.programId
353
+ this.ntt.program.programId
344
354
  )[0],
345
355
  true,
346
356
  splToken.TOKEN_2022_PROGRAM_ID
@@ -352,14 +362,14 @@ var SolanaRoutes = class {
352
362
  // token auth
353
363
  pubkey: web3_js.PublicKey.findProgramAddressSync(
354
364
  [Buffer.from("token_authority")],
355
- ntt.program.programId
365
+ this.ntt.program.programId
356
366
  )[0],
357
367
  isSigner: false,
358
368
  isWritable: false
359
369
  },
360
370
  {
361
371
  // m mint
362
- pubkey: mMint,
372
+ pubkey: this.ntt.config.mint,
363
373
  isSigner: false,
364
374
  isWritable: true
365
375
  },
@@ -371,7 +381,7 @@ var SolanaRoutes = class {
371
381
  },
372
382
  {
373
383
  // custody
374
- pubkey: ntt.config.custody,
384
+ pubkey: this.ntt.config.custody,
375
385
  isSigner: false,
376
386
  isWritable: true
377
387
  },
@@ -435,7 +445,7 @@ var SolanaRoutes = class {
435
445
  {
436
446
  // ext m vault
437
447
  pubkey: splToken.getAssociatedTokenAddressSync(
438
- mMint,
448
+ this.ntt.config.mint,
439
449
  web3_js.PublicKey.findProgramAddressSync(
440
450
  [Buffer.from("m_vault")],
441
451
  extProgram
@@ -491,6 +501,63 @@ var SolanaRoutes = class {
491
501
  state: web3_js.AddressLookupTableAccount.deserialize(info.data)
492
502
  });
493
503
  }
504
+ static async createReleaseInboundMintInstruction(ntt, args) {
505
+ const router = new _SolanaRoutes(ntt);
506
+ const { additionalPayload } = args.nttMessage.payload;
507
+ if (additionalPayload.length < 40) {
508
+ throw new Error(
509
+ `Invalid additionalPayload length: ${additionalPayload.length}, expected at least 40 bytes`
510
+ );
511
+ }
512
+ const destinationMint = new web3_js.PublicKey(
513
+ // first 8 bytes is the index, next 32 bytes is the mint address
514
+ additionalPayload.slice(8, 40)
515
+ );
516
+ if (destinationMint.equals(ntt.config.mint)) {
517
+ return [
518
+ await sdkSolanaNtt.NTT.createReleaseInboundMintInstruction(
519
+ ntt.program,
520
+ ntt.config,
521
+ args
522
+ )
523
+ ];
524
+ }
525
+ const extPrograms = router.extPrograms[destinationMint.toBase58()];
526
+ if (!extPrograms) {
527
+ throw new Error(
528
+ `No extension program found for mint ${destinationMint.toBase58()}`
529
+ );
530
+ }
531
+ const extAta = splToken.getAssociatedTokenAddressSync(
532
+ destinationMint,
533
+ args.recipient,
534
+ true,
535
+ extPrograms.tokenProgram
536
+ );
537
+ const ixs = [];
538
+ const acctInfo = await ntt.connection.getAccountInfo(extAta);
539
+ if (acctInfo === null) {
540
+ ixs.push(
541
+ splToken.createAssociatedTokenAccountInstruction(
542
+ args.payer,
543
+ extAta,
544
+ args.recipient,
545
+ destinationMint,
546
+ extPrograms.tokenProgram
547
+ )
548
+ );
549
+ }
550
+ ixs.push(
551
+ router.getReleaseInboundMintExtensionIx(
552
+ args.nttMessage,
553
+ args.chain,
554
+ args.payer,
555
+ destinationMint,
556
+ extAta
557
+ )
558
+ );
559
+ return ixs;
560
+ }
494
561
  };
495
562
  function pk(address) {
496
563
  return new web3_js.PublicKey(address);
@@ -535,9 +602,9 @@ var _M0AutomaticRoute = class _M0AutomaticRoute extends sdkConnect.routes.Automa
535
602
  case "ArbitrumSepolia":
536
603
  return this.EVM_CONTRACTS;
537
604
  case "Solana":
538
- return new SolanaRoutes(chainContext.network).getSolanaContracts();
605
+ return SolanaRoutes.getSolanaContracts(chainContext);
539
606
  case "Fogo":
540
- return new SolanaRoutes(chainContext.network).getSolanaContracts();
607
+ return SolanaRoutes.getSolanaContracts(chainContext);
541
608
  default:
542
609
  throw new Error(`Unsupported chain: ${chainContext.chain}`);
543
610
  }
@@ -675,7 +742,6 @@ var _M0AutomaticRoute = class _M0AutomaticRoute extends sdkConnect.routes.Automa
675
742
  // for Solana use custom transfer instruction
676
743
  this.transferSolanaExtension(
677
744
  ntt,
678
- request.fromChain.network,
679
745
  // @ts-ignore
680
746
  sender,
681
747
  transferAmount,
@@ -744,9 +810,9 @@ var _M0AutomaticRoute = class _M0AutomaticRoute extends sdkConnect.routes.Automa
744
810
  parallelizable
745
811
  );
746
812
  }
747
- async *transferSolanaExtension(ntt, network, sender, amount2, recipient, sourceToken, destinationToken, options) {
748
- const router = new SolanaRoutes(network);
749
- if (router.getSolanaContracts().token === sourceToken) {
813
+ async *transferSolanaExtension(ntt, sender, amount2, recipient, sourceToken, destinationToken, options) {
814
+ const router = new SolanaRoutes(ntt);
815
+ if ((await ntt.getConfig()).mint.toBase58() === sourceToken) {
750
816
  return ntt.transfer(sender, amount2, recipient, options);
751
817
  }
752
818
  const config = await ntt.getConfig();
@@ -755,7 +821,6 @@ var _M0AutomaticRoute = class _M0AutomaticRoute extends sdkConnect.routes.Automa
755
821
  const payerAddress = new sdkSolana.SolanaAddress(sender).unwrap();
756
822
  const ixs = [
757
823
  router.getTransferExtensionBurnIx(
758
- ntt,
759
824
  amount2,
760
825
  recipient,
761
826
  new web3_js.PublicKey(sender.toUint8Array()),
package/dist/index.mjs CHANGED
@@ -1,23 +1,25 @@
1
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 { WEI_PER_GWEI } from '@wormhole-foundation/sdk-solana-ntt';
3
+ import { WEI_PER_GWEI, NTT } from '@wormhole-foundation/sdk-solana-ntt';
4
4
  import { EvmAddress, EvmPlatform, addFrom, EvmUnsignedTransaction, addChainId } from '@wormhole-foundation/sdk-evm';
5
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
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';
9
+ import { TOKEN_2022_PROGRAM_ID, getAssociatedTokenAddressSync, createAssociatedTokenAccountInstruction } from '@solana/spl-token';
10
10
  import BN from 'bn.js';
11
11
  import { sha256 } from '@noble/hashes/sha2';
12
12
 
13
13
  // src/m0AutomaticRoute.ts
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 = {
14
+ var SolanaRoutes = class _SolanaRoutes {
15
+ constructor(ntt) {
16
+ this.ntt = ntt;
17
+ this.network = ntt.network;
18
+ this.programs = _SolanaRoutes.getPrograms(this.network);
19
+ this.extPrograms = _SolanaRoutes.getExtPrograms(this.network);
20
+ }
21
+ static getPrograms(network) {
22
+ return {
21
23
  Mainnet: {
22
24
  swap: pk("MSwapi3WhNKMUGm9YrxGhypgUEt7wYQH3ZgG32XoWzH"),
23
25
  earn: pk("mz2vDzjbQDUDXBH6FPF5s4odCJ4y8YLE5QWaZ8XdZ9Z"),
@@ -35,7 +37,9 @@ var SolanaRoutes = class {
35
37
  quoter: pk("Nqd6XqA8LbsCuG8MLWWuP865NV6jR1MbXeKxD4HLKDJ")
36
38
  }
37
39
  }[network];
38
- this.extPrograms = {
40
+ }
41
+ static getExtPrograms(network) {
42
+ return {
39
43
  Mainnet: {
40
44
  mzeroXDoBpRVhnEXBra27qzAMdxgpWVY3DzQW7xMVJp: {
41
45
  program: pk("wMXX1K1nca5W4pZr1piETe78gcAVVrEFi9f4g46uXko"),
@@ -66,16 +70,22 @@ var SolanaRoutes = class {
66
70
  }
67
71
  }[network];
68
72
  }
69
- getSolanaContracts() {
73
+ static getSolanaContracts(chainContext) {
74
+ const programs = _SolanaRoutes.getPrograms(
75
+ chainContext.network
76
+ );
77
+ const extPrograms = _SolanaRoutes.getExtPrograms(
78
+ chainContext.network
79
+ );
70
80
  return {
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()
81
+ token: programs.mMint.toBase58(),
82
+ mLikeTokens: Object.keys(extPrograms),
83
+ manager: programs.portal.toBase58(),
84
+ transceiver: { wormhole: programs.portal.toBase58() },
85
+ quoter: programs.quoter.toBase58()
76
86
  };
77
87
  }
78
- getTransferExtensionBurnIx(ntt, amount2, recipient, payer, outboxItem, extMint, destinationToken, shouldQueue = true) {
88
+ getTransferExtensionBurnIx(amount2, recipient, payer, outboxItem, extMint, destinationToken, shouldQueue = true) {
79
89
  const recipientAddress = Buffer.alloc(32);
80
90
  const dest = Buffer.from(recipient.address.toUint8Array());
81
91
  dest.copy(recipientAddress);
@@ -92,7 +102,7 @@ var SolanaRoutes = class {
92
102
  }
93
103
  const { program: extProgram, tokenProgram: extTokenProgram } = extension;
94
104
  return new TransactionInstruction({
95
- programId: ntt.program.programId,
105
+ programId: this.ntt.program.programId,
96
106
  keys: [
97
107
  {
98
108
  pubkey: payer,
@@ -101,7 +111,7 @@ var SolanaRoutes = class {
101
111
  },
102
112
  {
103
113
  // config
104
- pubkey: ntt.pdas.configAccount(),
114
+ pubkey: this.ntt.pdas.configAccount(),
105
115
  isSigner: false,
106
116
  isWritable: false
107
117
  },
@@ -117,7 +127,7 @@ var SolanaRoutes = class {
117
127
  this.programs.mMint,
118
128
  PublicKey.findProgramAddressSync(
119
129
  [Buffer.from("token_authority")],
120
- ntt.program.programId
130
+ this.ntt.program.programId
121
131
  )[0],
122
132
  true,
123
133
  TOKEN_2022_PROGRAM_ID
@@ -139,13 +149,13 @@ var SolanaRoutes = class {
139
149
  },
140
150
  {
141
151
  // outbox rate limit
142
- pubkey: ntt.pdas.outboxRateLimitAccount(),
152
+ pubkey: this.ntt.pdas.outboxRateLimitAccount(),
143
153
  isSigner: false,
144
154
  isWritable: true
145
155
  },
146
156
  {
147
157
  // custody
148
- pubkey: ntt.config.custody,
158
+ pubkey: this.ntt.config.custody,
149
159
  isSigner: false,
150
160
  isWritable: true
151
161
  },
@@ -157,19 +167,19 @@ var SolanaRoutes = class {
157
167
  },
158
168
  {
159
169
  // inbox rate limit
160
- pubkey: ntt.pdas.inboxRateLimitAccount(recipient.chain),
170
+ pubkey: this.ntt.pdas.inboxRateLimitAccount(recipient.chain),
161
171
  isSigner: false,
162
172
  isWritable: true
163
173
  },
164
174
  {
165
175
  // peer
166
- pubkey: ntt.pdas.peerAccount(recipient.chain),
176
+ pubkey: this.ntt.pdas.peerAccount(recipient.chain),
167
177
  isSigner: false,
168
178
  isWritable: false
169
179
  },
170
180
  {
171
181
  // session auth
172
- pubkey: ntt.pdas.sessionAuthority(payer, {
182
+ pubkey: this.ntt.pdas.sessionAuthority(payer, {
173
183
  amount: new BN(amount2),
174
184
  recipientChain: {
175
185
  id: 2
@@ -185,7 +195,7 @@ var SolanaRoutes = class {
185
195
  // token auth
186
196
  pubkey: PublicKey.findProgramAddressSync(
187
197
  [Buffer.from("token_authority")],
188
- ntt.program.programId
198
+ this.ntt.program.programId
189
199
  )[0],
190
200
  isSigner: false,
191
201
  isWritable: false
@@ -300,7 +310,7 @@ var SolanaRoutes = class {
300
310
  ])
301
311
  });
302
312
  }
303
- getReleaseInboundMintExtensionIx(ntt, payer, inboxItem, mMint, extMint, extAta) {
313
+ getReleaseInboundMintExtensionIx(nttMessage, emitterChain, payer, extMint, extAta) {
304
314
  const extension = this.extPrograms[extMint.toBase58()];
305
315
  if (!extension) {
306
316
  throw new Error(
@@ -309,32 +319,32 @@ var SolanaRoutes = class {
309
319
  }
310
320
  const { program: extProgram, tokenProgram: extTokenProgram } = extension;
311
321
  return new TransactionInstruction({
312
- programId: ntt.program.programId,
322
+ programId: this.ntt.program.programId,
313
323
  keys: [
314
324
  {
315
- pubkey: pk(payer),
325
+ pubkey: payer,
316
326
  isSigner: true,
317
327
  isWritable: true
318
328
  },
319
329
  {
320
330
  // config
321
- pubkey: ntt.pdas.configAccount(),
331
+ pubkey: this.ntt.pdas.configAccount(),
322
332
  isSigner: false,
323
333
  isWritable: false
324
334
  },
325
335
  {
326
336
  // inbox item
327
- pubkey: inboxItem,
337
+ pubkey: this.ntt.pdas.inboxItemAccount(emitterChain, nttMessage),
328
338
  isSigner: false,
329
339
  isWritable: true
330
340
  },
331
341
  {
332
342
  // recipient (mint to token auth which wraps to user)
333
343
  pubkey: getAssociatedTokenAddressSync(
334
- mMint,
344
+ this.ntt.config.mint,
335
345
  PublicKey.findProgramAddressSync(
336
346
  [Buffer.from("token_authority")],
337
- ntt.program.programId
347
+ this.ntt.program.programId
338
348
  )[0],
339
349
  true,
340
350
  TOKEN_2022_PROGRAM_ID
@@ -346,14 +356,14 @@ var SolanaRoutes = class {
346
356
  // token auth
347
357
  pubkey: PublicKey.findProgramAddressSync(
348
358
  [Buffer.from("token_authority")],
349
- ntt.program.programId
359
+ this.ntt.program.programId
350
360
  )[0],
351
361
  isSigner: false,
352
362
  isWritable: false
353
363
  },
354
364
  {
355
365
  // m mint
356
- pubkey: mMint,
366
+ pubkey: this.ntt.config.mint,
357
367
  isSigner: false,
358
368
  isWritable: true
359
369
  },
@@ -365,7 +375,7 @@ var SolanaRoutes = class {
365
375
  },
366
376
  {
367
377
  // custody
368
- pubkey: ntt.config.custody,
378
+ pubkey: this.ntt.config.custody,
369
379
  isSigner: false,
370
380
  isWritable: true
371
381
  },
@@ -429,7 +439,7 @@ var SolanaRoutes = class {
429
439
  {
430
440
  // ext m vault
431
441
  pubkey: getAssociatedTokenAddressSync(
432
- mMint,
442
+ this.ntt.config.mint,
433
443
  PublicKey.findProgramAddressSync(
434
444
  [Buffer.from("m_vault")],
435
445
  extProgram
@@ -485,6 +495,63 @@ var SolanaRoutes = class {
485
495
  state: AddressLookupTableAccount.deserialize(info.data)
486
496
  });
487
497
  }
498
+ static async createReleaseInboundMintInstruction(ntt, args) {
499
+ const router = new _SolanaRoutes(ntt);
500
+ const { additionalPayload } = args.nttMessage.payload;
501
+ if (additionalPayload.length < 40) {
502
+ throw new Error(
503
+ `Invalid additionalPayload length: ${additionalPayload.length}, expected at least 40 bytes`
504
+ );
505
+ }
506
+ const destinationMint = new PublicKey(
507
+ // first 8 bytes is the index, next 32 bytes is the mint address
508
+ additionalPayload.slice(8, 40)
509
+ );
510
+ if (destinationMint.equals(ntt.config.mint)) {
511
+ return [
512
+ await NTT.createReleaseInboundMintInstruction(
513
+ ntt.program,
514
+ ntt.config,
515
+ args
516
+ )
517
+ ];
518
+ }
519
+ const extPrograms = router.extPrograms[destinationMint.toBase58()];
520
+ if (!extPrograms) {
521
+ throw new Error(
522
+ `No extension program found for mint ${destinationMint.toBase58()}`
523
+ );
524
+ }
525
+ const extAta = getAssociatedTokenAddressSync(
526
+ destinationMint,
527
+ args.recipient,
528
+ true,
529
+ extPrograms.tokenProgram
530
+ );
531
+ const ixs = [];
532
+ const acctInfo = await ntt.connection.getAccountInfo(extAta);
533
+ if (acctInfo === null) {
534
+ ixs.push(
535
+ createAssociatedTokenAccountInstruction(
536
+ args.payer,
537
+ extAta,
538
+ args.recipient,
539
+ destinationMint,
540
+ extPrograms.tokenProgram
541
+ )
542
+ );
543
+ }
544
+ ixs.push(
545
+ router.getReleaseInboundMintExtensionIx(
546
+ args.nttMessage,
547
+ args.chain,
548
+ args.payer,
549
+ destinationMint,
550
+ extAta
551
+ )
552
+ );
553
+ return ixs;
554
+ }
488
555
  };
489
556
  function pk(address) {
490
557
  return new PublicKey(address);
@@ -529,9 +596,9 @@ var _M0AutomaticRoute = class _M0AutomaticRoute extends routes.AutomaticRoute {
529
596
  case "ArbitrumSepolia":
530
597
  return this.EVM_CONTRACTS;
531
598
  case "Solana":
532
- return new SolanaRoutes(chainContext.network).getSolanaContracts();
599
+ return SolanaRoutes.getSolanaContracts(chainContext);
533
600
  case "Fogo":
534
- return new SolanaRoutes(chainContext.network).getSolanaContracts();
601
+ return SolanaRoutes.getSolanaContracts(chainContext);
535
602
  default:
536
603
  throw new Error(`Unsupported chain: ${chainContext.chain}`);
537
604
  }
@@ -669,7 +736,6 @@ var _M0AutomaticRoute = class _M0AutomaticRoute extends routes.AutomaticRoute {
669
736
  // for Solana use custom transfer instruction
670
737
  this.transferSolanaExtension(
671
738
  ntt,
672
- request.fromChain.network,
673
739
  // @ts-ignore
674
740
  sender,
675
741
  transferAmount,
@@ -738,9 +804,9 @@ var _M0AutomaticRoute = class _M0AutomaticRoute extends routes.AutomaticRoute {
738
804
  parallelizable
739
805
  );
740
806
  }
741
- async *transferSolanaExtension(ntt, network, sender, amount2, recipient, sourceToken, destinationToken, options) {
742
- const router = new SolanaRoutes(network);
743
- if (router.getSolanaContracts().token === sourceToken) {
807
+ async *transferSolanaExtension(ntt, sender, amount2, recipient, sourceToken, destinationToken, options) {
808
+ const router = new SolanaRoutes(ntt);
809
+ if ((await ntt.getConfig()).mint.toBase58() === sourceToken) {
744
810
  return ntt.transfer(sender, amount2, recipient, options);
745
811
  }
746
812
  const config = await ntt.getConfig();
@@ -749,7 +815,6 @@ var _M0AutomaticRoute = class _M0AutomaticRoute extends routes.AutomaticRoute {
749
815
  const payerAddress = new SolanaAddress(sender).unwrap();
750
816
  const ixs = [
751
817
  router.getTransferExtensionBurnIx(
752
- ntt,
753
818
  amount2,
754
819
  recipient,
755
820
  new PublicKey(sender.toUint8Array()),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@m0-foundation/ntt-sdk-route",
3
- "version": "0.0.10",
3
+ "version": "0.0.11",
4
4
  "exports": {
5
5
  ".": {
6
6
  "types": "./dist/index.d.ts",
@@ -20,6 +20,10 @@
20
20
  "files": [
21
21
  "dist"
22
22
  ],
23
+ "scripts": {
24
+ "build": "$npm_execpath tsup --clean",
25
+ "clean": "rm -rf dist"
26
+ },
23
27
  "devDependencies": {
24
28
  "@changesets/cli": "^2.28.1",
25
29
  "@types/bn.js": "^5.2.0",
@@ -30,6 +34,7 @@
30
34
  "publishConfig": {
31
35
  "access": "public"
32
36
  },
37
+ "packageManager": "pnpm@10.2.0",
33
38
  "dependencies": {
34
39
  "@noble/hashes": "^1.8.0",
35
40
  "@solana/spl-token": "^0.4.13",
@@ -44,9 +49,5 @@
44
49
  "@wormhole-foundation/sdk-solana-ntt": "^0.7.1",
45
50
  "bn.js": "^5.2.2",
46
51
  "ethers": "^6.5.1"
47
- },
48
- "scripts": {
49
- "build": "$npm_execpath tsup --clean",
50
- "clean": "rm -rf dist"
51
52
  }
52
- }
53
+ }