@atomiqlabs/chain-solana 13.2.3 → 13.3.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.
@@ -134,7 +134,7 @@ class SolanaChainEventsBrowser {
134
134
  const initIx = eventObject.instructions.find(ix => ix != null && (ix.name === "offererInitializePayIn" || ix.name === "offererInitialize"));
135
135
  if (initIx == null)
136
136
  return null;
137
- return SolanaSwapData_1.SolanaSwapData.fromInstruction(initIx, txoHash);
137
+ return SolanaSwapData_1.SolanaSwapData.fromInstruction(this.solanaSwapProgram.program.programId, initIx, txoHash);
138
138
  };
139
139
  }
140
140
  /**
@@ -45,6 +45,23 @@ export declare class SolanaProgramBase<T extends Idl> {
45
45
  * @internal
46
46
  */
47
47
  protected pda<T extends Array<any>>(seed: string, func: (...args: T) => Buffer[]): (...args: T) => PublicKey;
48
+ /**
49
+ * Derives static PDA address from the seed
50
+ *
51
+ * @param seed
52
+ *
53
+ * @internal
54
+ */
55
+ static _pda(seed: string): (programId: PublicKey) => PublicKey;
56
+ /**
57
+ * Returns a function for deriving a dynamic PDA address from seed + dynamic arguments
58
+ *
59
+ * @param seed
60
+ * @param func function translating the function argument to Buffer[]
61
+ *
62
+ * @internal
63
+ */
64
+ static _pda<T extends Array<any>>(seed: string, func: (...args: T) => Buffer[]): (programId: PublicKey, ...args: T) => PublicKey;
48
65
  /**
49
66
  * Returns a function for deriving a dynamic deterministic keypair from dynamic arguments
50
67
  *
@@ -23,11 +23,17 @@ class SolanaProgramBase {
23
23
  }
24
24
  pda(seed, func) {
25
25
  if (func == null) {
26
- return web3_js_1.PublicKey.findProgramAddressSync([buffer_1.Buffer.from(seed)], this.program.programId)[0];
26
+ return SolanaProgramBase._pda(seed)(this.program.programId);
27
27
  }
28
- return (...args) => {
28
+ return SolanaProgramBase._pda(seed, func).bind(this, this.program.programId);
29
+ }
30
+ static _pda(seed, func) {
31
+ if (func == null) {
32
+ return (programId) => web3_js_1.PublicKey.findProgramAddressSync([buffer_1.Buffer.from(seed)], programId)[0];
33
+ }
34
+ return (programId, ...args) => {
29
35
  const res = func(...args);
30
- return web3_js_1.PublicKey.findProgramAddressSync([buffer_1.Buffer.from(seed)].concat(res), this.program.programId)[0];
36
+ return web3_js_1.PublicKey.findProgramAddressSync([buffer_1.Buffer.from(seed)].concat(res), programId)[0];
31
37
  };
32
38
  }
33
39
  /**
@@ -7,6 +7,7 @@ import { Serialized } from "../../utils/Utils";
7
7
  import { SingleInstructionWithAccounts } from "../program/modules/SolanaProgramEvents";
8
8
  export type InitInstruction = SingleInstructionWithAccounts<SwapProgram["instructions"][2 | 3], SwapProgram>;
9
9
  export type SolanaSwapDataCtorArgs = {
10
+ programId: PublicKey;
10
11
  offerer: PublicKey;
11
12
  claimer: PublicKey;
12
13
  token: PublicKey;
@@ -34,6 +35,10 @@ export declare function isSerializedData(obj: any): obj is ({
34
35
  * @category Swaps
35
36
  */
36
37
  export declare class SolanaSwapData extends SwapData {
38
+ /**
39
+ * Program ID for which this swap data was created
40
+ */
41
+ programId: PublicKey;
37
42
  /**
38
43
  * Offerer address funding the swap.
39
44
  */
@@ -235,17 +240,19 @@ export declare class SolanaSwapData extends SwapData {
235
240
  /**
236
241
  * Converts initialize instruction data into {@link SolanaSwapData}.
237
242
  *
243
+ * @param programId
238
244
  * @param initIx Decoded initialize instruction
239
245
  * @param txoHash Parsed txo hash hint from initialize event
240
246
  * @returns Converted and parsed swap data
241
247
  */
242
- static fromInstruction(initIx: InitInstruction, txoHash: string): SolanaSwapData;
248
+ static fromInstruction(programId: PublicKey, initIx: InitInstruction, txoHash: string): SolanaSwapData;
243
249
  /**
244
250
  * Deserializes swap data from an on-chain escrow account state.
245
251
  *
252
+ * @param programId
246
253
  * @param account Escrow account state as returned by Anchor
247
254
  */
248
- static fromEscrowState(account: IdlAccounts<SwapProgram>["escrowState"]): SolanaSwapData;
255
+ static fromEscrowState(programId: PublicKey, account: IdlAccounts<SwapProgram>["escrowState"]): SolanaSwapData;
249
256
  /**
250
257
  * Converts abstract swap type to Solana program kind discriminator.
251
258
  *
@@ -274,4 +281,8 @@ export declare class SolanaSwapData extends SwapData {
274
281
  * @inheritDoc
275
282
  */
276
283
  isDepositToken(token: string): boolean;
284
+ /**
285
+ * @inheritDoc
286
+ */
287
+ getEscrowStruct(): any;
277
288
  }
@@ -9,6 +9,7 @@ const buffer_1 = require("buffer");
9
9
  const spl_token_1 = require("@solana/spl-token");
10
10
  const Utils_1 = require("../../utils/Utils");
11
11
  const SolanaTokens_1 = require("../chain/modules/SolanaTokens");
12
+ const SolanaSwapProgram_1 = require("./SolanaSwapProgram");
12
13
  const EXPIRY_BLOCKHEIGHT_THRESHOLD = new BN("1000000000");
13
14
  function isSerializedData(obj) {
14
15
  return obj.type === "sol";
@@ -23,6 +24,7 @@ class SolanaSwapData extends base_1.SwapData {
23
24
  constructor(data) {
24
25
  super();
25
26
  if (!isSerializedData(data)) {
27
+ this.programId = data.programId;
26
28
  this.offerer = data.offerer;
27
29
  this.claimer = data.claimer;
28
30
  this.token = data.token;
@@ -42,6 +44,7 @@ class SolanaSwapData extends base_1.SwapData {
42
44
  this.txoHash = data.txoHash;
43
45
  }
44
46
  else {
47
+ this.programId = new web3_js_1.PublicKey(data.programId ?? "4hfUykhqmD7ZRvNh1HuzVKEY7ToENixtdUKZspNDCrEM");
45
48
  this.offerer = new web3_js_1.PublicKey(data.offerer);
46
49
  this.claimer = new web3_js_1.PublicKey(data.claimer);
47
50
  this.token = new web3_js_1.PublicKey(data.token);
@@ -96,6 +99,7 @@ class SolanaSwapData extends base_1.SwapData {
96
99
  serialize() {
97
100
  return {
98
101
  type: "sol",
102
+ programId: this.programId?.toBase58(),
99
103
  offerer: this.offerer?.toBase58(),
100
104
  claimer: this.claimer?.toBase58(),
101
105
  token: this.token?.toBase58(),
@@ -318,11 +322,12 @@ class SolanaSwapData extends base_1.SwapData {
318
322
  /**
319
323
  * Converts initialize instruction data into {@link SolanaSwapData}.
320
324
  *
325
+ * @param programId
321
326
  * @param initIx Decoded initialize instruction
322
327
  * @param txoHash Parsed txo hash hint from initialize event
323
328
  * @returns Converted and parsed swap data
324
329
  */
325
- static fromInstruction(initIx, txoHash) {
330
+ static fromInstruction(programId, initIx, txoHash) {
326
331
  const paymentHash = buffer_1.Buffer.from(initIx.data.swapData.hash);
327
332
  let securityDeposit = new BN(0);
328
333
  let claimerBounty = new BN(0);
@@ -333,6 +338,7 @@ class SolanaSwapData extends base_1.SwapData {
333
338
  claimerBounty = initIx.data.claimerBounty;
334
339
  }
335
340
  return new SolanaSwapData({
341
+ programId,
336
342
  offerer: initIx.accounts.offerer,
337
343
  claimer: initIx.accounts.claimer,
338
344
  token: initIx.accounts.mint,
@@ -355,11 +361,13 @@ class SolanaSwapData extends base_1.SwapData {
355
361
  /**
356
362
  * Deserializes swap data from an on-chain escrow account state.
357
363
  *
364
+ * @param programId
358
365
  * @param account Escrow account state as returned by Anchor
359
366
  */
360
- static fromEscrowState(account) {
367
+ static fromEscrowState(programId, account) {
361
368
  const data = account.data;
362
369
  return new SolanaSwapData({
370
+ programId,
363
371
  offerer: account.offerer,
364
372
  claimer: account.claimer,
365
373
  token: account.mint,
@@ -444,6 +452,40 @@ class SolanaSwapData extends base_1.SwapData {
444
452
  isDepositToken(token) {
445
453
  return SolanaTokens_1.SolanaTokens.WSOL_ADDRESS.equals(new web3_js_1.PublicKey(token));
446
454
  }
455
+ /**
456
+ * @inheritDoc
457
+ */
458
+ getEscrowStruct() {
459
+ return {
460
+ accounts: {
461
+ offerer: this.offerer.toString(),
462
+ claimer: this.claimer.toString(),
463
+ claimerAta: this.claimerAta == null || this.claimerAta.equals(web3_js_1.PublicKey.default) ? null : this.claimerAta.toString(),
464
+ offererAta: this.offererAta == null || this.offererAta.equals(web3_js_1.PublicKey.default) ? null : this.offererAta.toString(),
465
+ claimerUserData: SolanaSwapProgram_1.SolanaSwapProgram._SwapUserVault(this.programId, this.claimer, this.token).toString(),
466
+ offererUserData: SolanaSwapProgram_1.SolanaSwapProgram._SwapUserVault(this.programId, this.offerer, this.token).toString(),
467
+ initializer: this.isPayIn() ? this.offerer.toString() : this.claimer.toString(),
468
+ escrowState: SolanaSwapProgram_1.SolanaSwapProgram._SwapEscrowState(this.programId, buffer_1.Buffer.from(this.paymentHash, "hex")).toString(),
469
+ mint: this.token.toString(),
470
+ vault: SolanaSwapProgram_1.SolanaSwapProgram._SwapVault(this.programId, this.token).toString(),
471
+ vaultAuthority: SolanaSwapProgram_1.SolanaSwapProgram._SwapVaultAuthority(this.programId).toString(),
472
+ systemProgram: web3_js_1.SystemProgram.programId.toString(),
473
+ tokenProgram: spl_token_1.TOKEN_PROGRAM_ID.toString(),
474
+ ixSysvar: web3_js_1.SYSVAR_INSTRUCTIONS_PUBKEY.toString(),
475
+ },
476
+ data: {
477
+ kind: SwapTypeEnum_1.SwapTypeEnum.fromNumber(this.kind),
478
+ confirmations: this.confirmations,
479
+ nonce: this.nonce.toString(10),
480
+ hash: [...buffer_1.Buffer.from(this.paymentHash, "hex")],
481
+ payIn: this.payIn,
482
+ payOut: this.payOut,
483
+ amount: this.amount.toString(10),
484
+ expiry: this.expiry.toString(10),
485
+ sequence: this.sequence.toString(10)
486
+ }
487
+ };
488
+ }
447
489
  }
448
490
  exports.SolanaSwapData = SolanaSwapData;
449
491
  base_1.SwapData.deserializers["sol"] = SolanaSwapData;
@@ -27,21 +27,25 @@ export declare class SolanaSwapProgram extends SolanaProgramBase<SwapProgram> im
27
27
  * PDA of the swap vault authority.
28
28
  * @internal
29
29
  */
30
+ static readonly _SwapVaultAuthority: (programId: PublicKey) => PublicKey;
30
31
  readonly _SwapVaultAuthority: PublicKey;
31
32
  /**
32
33
  * PDA helper for global token vault accounts.
33
34
  * @internal
34
35
  */
36
+ static readonly _SwapVault: (programId: PublicKey, tokenAddress: PublicKey) => PublicKey;
35
37
  readonly _SwapVault: (tokenAddress: PublicKey) => PublicKey;
36
38
  /**
37
39
  * PDA helper for per-user token vault accounts.
38
40
  * @internal
39
41
  */
42
+ static readonly _SwapUserVault: (programId: PublicKey, publicKey: PublicKey, tokenAddress: PublicKey) => PublicKey;
40
43
  readonly _SwapUserVault: (publicKey: PublicKey, tokenAddress: PublicKey) => PublicKey;
41
44
  /**
42
45
  * PDA helper for escrow state accounts.
43
46
  * @internal
44
47
  */
48
+ static readonly _SwapEscrowState: (programId: PublicKey, hash: Buffer) => PublicKey;
45
49
  readonly _SwapEscrowState: (hash: Buffer) => PublicKey;
46
50
  /**
47
51
  * @inheritDoc
@@ -35,28 +35,10 @@ class SolanaSwapProgram extends SolanaProgramBase_1.SolanaProgramBase {
35
35
  * Rent-exempt amount (lamports) for escrow state accounts.
36
36
  */
37
37
  this.ESCROW_STATE_RENT_EXEMPT = 2658720;
38
- ////////////////////////
39
- //// PDA accessors
40
- /**
41
- * PDA of the swap vault authority.
42
- * @internal
43
- */
44
- this._SwapVaultAuthority = this.pda("authority");
45
- /**
46
- * PDA helper for global token vault accounts.
47
- * @internal
48
- */
49
- this._SwapVault = this.pda("vault", (tokenAddress) => [tokenAddress.toBuffer()]);
50
- /**
51
- * PDA helper for per-user token vault accounts.
52
- * @internal
53
- */
54
- this._SwapUserVault = this.pda("uservault", (publicKey, tokenAddress) => [publicKey.toBuffer(), tokenAddress.toBuffer()]);
55
- /**
56
- * PDA helper for escrow state accounts.
57
- * @internal
58
- */
59
- this._SwapEscrowState = this.pda("state", (hash) => [hash]);
38
+ this._SwapVaultAuthority = SolanaSwapProgram._SwapVaultAuthority(this.program.programId);
39
+ this._SwapVault = SolanaSwapProgram._SwapVault.bind(this, this.program.programId);
40
+ this._SwapUserVault = SolanaSwapProgram._SwapUserVault.bind(this, this.program.programId);
41
+ this._SwapEscrowState = SolanaSwapProgram._SwapEscrowState.bind(this, this.program.programId);
60
42
  ////////////////////////
61
43
  //// Timeouts
62
44
  /**
@@ -360,7 +342,7 @@ class SolanaSwapProgram extends SolanaProgramBase_1.SolanaProgramBase {
360
342
  const account = await this.program.account.escrowState.fetchNullable(this._SwapEscrowState(paymentHashBuffer));
361
343
  if (account == null)
362
344
  return null;
363
- return SolanaSwapData_1.SolanaSwapData.fromEscrowState(account);
345
+ return SolanaSwapData_1.SolanaSwapData.fromEscrowState(this.program.programId, account);
364
346
  }
365
347
  /**
366
348
  * @inheritDoc
@@ -395,7 +377,7 @@ class SolanaSwapProgram extends SolanaProgramBase_1.SolanaProgramBase {
395
377
  continue;
396
378
  }
397
379
  swapsOpened[escrowHash] = {
398
- data: SolanaSwapData_1.SolanaSwapData.fromInstruction(initIx, txoHash),
380
+ data: SolanaSwapData_1.SolanaSwapData.fromInstruction(this.program.programId, initIx, txoHash),
399
381
  getInitTxId: () => Promise.resolve(txSignature),
400
382
  getTxBlock: () => Promise.resolve({
401
383
  blockHeight: tx.slot,
@@ -468,6 +450,7 @@ class SolanaSwapProgram extends SolanaProgramBase_1.SolanaProgramBase {
468
450
  const claimerKey = new web3_js_1.PublicKey(claimer);
469
451
  const { paymentHash, nonce, confirmations } = (0, Utils_1.fromClaimHash)(claimHash);
470
452
  const swapData = new SolanaSwapData_1.SolanaSwapData({
453
+ programId: this.program.programId,
471
454
  offerer: offererKey,
472
455
  claimer: claimerKey,
473
456
  token: tokenAddr,
@@ -736,3 +719,25 @@ class SolanaSwapProgram extends SolanaProgramBase_1.SolanaProgramBase {
736
719
  }
737
720
  }
738
721
  exports.SolanaSwapProgram = SolanaSwapProgram;
722
+ ////////////////////////
723
+ //// PDA accessors
724
+ /**
725
+ * PDA of the swap vault authority.
726
+ * @internal
727
+ */
728
+ SolanaSwapProgram._SwapVaultAuthority = SolanaProgramBase_1.SolanaProgramBase._pda("authority");
729
+ /**
730
+ * PDA helper for global token vault accounts.
731
+ * @internal
732
+ */
733
+ SolanaSwapProgram._SwapVault = SolanaProgramBase_1.SolanaProgramBase._pda("vault", (tokenAddress) => [tokenAddress.toBuffer()]);
734
+ /**
735
+ * PDA helper for per-user token vault accounts.
736
+ * @internal
737
+ */
738
+ SolanaSwapProgram._SwapUserVault = SolanaProgramBase_1.SolanaProgramBase._pda("uservault", (publicKey, tokenAddress) => [publicKey.toBuffer(), tokenAddress.toBuffer()]);
739
+ /**
740
+ * PDA helper for escrow state accounts.
741
+ * @internal
742
+ */
743
+ SolanaSwapProgram._SwapEscrowState = SolanaProgramBase_1.SolanaProgramBase._pda("state", (hash) => [hash]);
@@ -244,7 +244,7 @@ class SwapInit extends SolanaSwapModule_1.SolanaSwapModule {
244
244
  txToSign.feePayer = swapData.isPayIn() ? swapData.offerer : swapData.claimer;
245
245
  txToSign.recentBlockhash = latestBlock.blockhash;
246
246
  txToSign.sign(signer.keypair);
247
- this.logger.debug("signSwapInitialization(): Signed tx: ", txToSign);
247
+ // this.logger.debug("signSwapInitialization(): Signed tx: ",txToSign);
248
248
  const sig = txToSign.signatures.find(e => e.publicKey.equals(signer.getPublicKey()));
249
249
  if (sig == null || sig.signature == null)
250
250
  throw new Error(`Unable to extract transaction signature! Signer: ${signer.getAddress()}`);
@@ -299,7 +299,7 @@ class SwapInit extends SolanaSwapModule_1.SolanaSwapModule {
299
299
  txToSign.feePayer = new web3_js_1.PublicKey(sender);
300
300
  txToSign.recentBlockhash = blockhash;
301
301
  txToSign.addSignature(signer, buffer_1.Buffer.from(signatureString, "hex"));
302
- this.logger.debug("isSignatureValid(): Signed tx: ", txToSign);
302
+ // this.logger.debug("isSignatureValid(): Signed tx: ",txToSign);
303
303
  const valid = txToSign.verifySignatures(false);
304
304
  if (!valid)
305
305
  throw new base_1.SignatureVerificationError("Invalid signature!");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atomiqlabs/chain-solana",
3
- "version": "13.2.3",
3
+ "version": "13.3.0",
4
4
  "description": "Solana specific base implementation",
5
5
  "main": "./dist/index.js",
6
6
  "types:": "./dist/index.d.ts",
@@ -26,7 +26,7 @@
26
26
  "author": "adambor",
27
27
  "license": "ISC",
28
28
  "dependencies": {
29
- "@atomiqlabs/base": "^13.2.0",
29
+ "@atomiqlabs/base": "^13.3.0",
30
30
  "@coral-xyz/anchor": "0.29.0",
31
31
  "@noble/hashes": "^1.7.1",
32
32
  "@solana/spl-token": "0.4.14",
@@ -193,7 +193,7 @@ export class SolanaChainEventsBrowser implements ChainEvents<SolanaSwapData, Sol
193
193
  ) as InitInstruction;
194
194
  if(initIx == null) return null;
195
195
 
196
- return SolanaSwapData.fromInstruction(initIx, txoHash);
196
+ return SolanaSwapData.fromInstruction(this.solanaSwapProgram.program.programId, initIx, txoHash);
197
197
  }
198
198
  }
199
199
 
@@ -64,19 +64,44 @@ export class SolanaProgramBase<T extends Idl> {
64
64
  protected pda<T extends Array<any>>(seed: string, func: (...args: T) => Buffer[]): (...args: T) => PublicKey;
65
65
  protected pda<T extends Array<any>>(seed: string, func?: (...args: T) => Buffer[]): PublicKey | ((...args: T) => PublicKey) {
66
66
  if(func==null) {
67
- return PublicKey.findProgramAddressSync(
67
+ return SolanaProgramBase._pda(seed)(this.program.programId);
68
+ }
69
+ return SolanaProgramBase._pda(seed, func).bind(this, this.program.programId);
70
+ }
71
+
72
+ /**
73
+ * Derives static PDA address from the seed
74
+ *
75
+ * @param seed
76
+ *
77
+ * @internal
78
+ */
79
+ static _pda(seed: string): (programId: PublicKey) => PublicKey;
80
+ /**
81
+ * Returns a function for deriving a dynamic PDA address from seed + dynamic arguments
82
+ *
83
+ * @param seed
84
+ * @param func function translating the function argument to Buffer[]
85
+ *
86
+ * @internal
87
+ */
88
+ static _pda<T extends Array<any>>(seed: string, func: (...args: T) => Buffer[]): (programId: PublicKey, ...args: T) => PublicKey;
89
+ static _pda<T extends Array<any>>(seed: string, func?: (...args: T) => Buffer[]): ((programId: PublicKey) => PublicKey) | ((programId: PublicKey, ...args: T) => PublicKey) {
90
+ if(func==null) {
91
+ return (programId: PublicKey) => PublicKey.findProgramAddressSync(
68
92
  [Buffer.from(seed)],
69
- this.program.programId
93
+ programId
70
94
  )[0];
71
95
  }
72
- return (...args: T) => {
96
+ return (programId: PublicKey, ...args: T) => {
73
97
  const res = func(...args);
74
98
  return PublicKey.findProgramAddressSync(
75
99
  [Buffer.from(seed)].concat(res as Buffer<ArrayBuffer>[]),
76
- this.program.programId
100
+ programId
77
101
  )[0]
78
102
  }
79
103
  }
104
+
80
105
  /**
81
106
  * Returns a function for deriving a dynamic deterministic keypair from dynamic arguments
82
107
  *
@@ -1,20 +1,23 @@
1
- import {PublicKey} from "@solana/web3.js";
1
+ import {PublicKey, SystemProgram, SYSVAR_INSTRUCTIONS_PUBKEY} from "@solana/web3.js";
2
2
  import * as BN from "bn.js";
3
3
  import {ChainSwapType, SwapData} from "@atomiqlabs/base";
4
4
  import {SwapProgram} from "./programTypes";
5
5
  import {IdlAccounts, IdlTypes} from "@coral-xyz/anchor";
6
6
  import {SwapTypeEnum} from "./SwapTypeEnum";
7
7
  import {Buffer} from "buffer";
8
- import {getAssociatedTokenAddressSync} from "@solana/spl-token";
8
+ import {getAssociatedTokenAddressSync, TOKEN_PROGRAM_ID} from "@solana/spl-token";
9
9
  import {Serialized, toBigInt, toClaimHash, toEscrowHash} from "../../utils/Utils";
10
10
  import {SolanaTokens} from "../chain/modules/SolanaTokens";
11
11
  import {SingleInstructionWithAccounts} from "../program/modules/SolanaProgramEvents";
12
+ import {SolanaSwapProgram} from "./SolanaSwapProgram";
12
13
 
13
14
  export type InitInstruction = SingleInstructionWithAccounts<SwapProgram["instructions"][2 | 3], SwapProgram>;
14
15
 
15
16
  const EXPIRY_BLOCKHEIGHT_THRESHOLD = new BN("1000000000");
16
17
 
17
18
  export type SolanaSwapDataCtorArgs = {
19
+ programId: PublicKey,
20
+
18
21
  offerer: PublicKey,
19
22
  claimer: PublicKey,
20
23
  token: PublicKey,
@@ -48,6 +51,10 @@ export function isSerializedData(obj: any): obj is ({type: "sol"} & Serialized<S
48
51
  */
49
52
  export class SolanaSwapData extends SwapData {
50
53
 
54
+ /**
55
+ * Program ID for which this swap data was created
56
+ */
57
+ programId: PublicKey;
51
58
  /**
52
59
  * Offerer address funding the swap.
53
60
  */
@@ -135,6 +142,7 @@ export class SolanaSwapData extends SwapData {
135
142
  constructor(data: ({type: "sol"} & Serialized<SolanaSwapData>) | SolanaSwapDataCtorArgs) {
136
143
  super();
137
144
  if(!isSerializedData(data)) {
145
+ this.programId = data.programId;
138
146
  this.offerer = data.offerer;
139
147
  this.claimer = data.claimer;
140
148
  this.token = data.token;
@@ -153,6 +161,7 @@ export class SolanaSwapData extends SwapData {
153
161
  this.claimerBounty = data.claimerBounty;
154
162
  this.txoHash = data.txoHash;
155
163
  } else {
164
+ this.programId = new PublicKey(data.programId ?? "4hfUykhqmD7ZRvNh1HuzVKEY7ToENixtdUKZspNDCrEM");
156
165
  this.offerer = new PublicKey(data.offerer);
157
166
  this.claimer = new PublicKey(data.claimer);
158
167
  this.token = new PublicKey(data.token);
@@ -212,6 +221,7 @@ export class SolanaSwapData extends SwapData {
212
221
  serialize(): {type: "sol"} & Serialized<SolanaSwapData> {
213
222
  return {
214
223
  type: "sol",
224
+ programId: this.programId?.toBase58(),
215
225
  offerer: this.offerer?.toBase58(),
216
226
  claimer: this.claimer?.toBase58(),
217
227
  token: this.token?.toBase58(),
@@ -452,11 +462,13 @@ export class SolanaSwapData extends SwapData {
452
462
  /**
453
463
  * Converts initialize instruction data into {@link SolanaSwapData}.
454
464
  *
465
+ * @param programId
455
466
  * @param initIx Decoded initialize instruction
456
467
  * @param txoHash Parsed txo hash hint from initialize event
457
468
  * @returns Converted and parsed swap data
458
469
  */
459
470
  static fromInstruction(
471
+ programId: PublicKey,
460
472
  initIx: InitInstruction,
461
473
  txoHash: string
462
474
  ): SolanaSwapData {
@@ -471,6 +483,7 @@ export class SolanaSwapData extends SwapData {
471
483
  }
472
484
 
473
485
  return new SolanaSwapData({
486
+ programId,
474
487
  offerer: initIx.accounts.offerer,
475
488
  claimer: initIx.accounts.claimer,
476
489
  token: initIx.accounts.mint,
@@ -494,12 +507,17 @@ export class SolanaSwapData extends SwapData {
494
507
  /**
495
508
  * Deserializes swap data from an on-chain escrow account state.
496
509
  *
510
+ * @param programId
497
511
  * @param account Escrow account state as returned by Anchor
498
512
  */
499
- static fromEscrowState(account: IdlAccounts<SwapProgram>["escrowState"]) {
513
+ static fromEscrowState(
514
+ programId: PublicKey,
515
+ account: IdlAccounts<SwapProgram>["escrowState"]
516
+ ) {
500
517
  const data: IdlTypes<SwapProgram>["SwapData"] = account.data;
501
518
 
502
519
  return new SolanaSwapData({
520
+ programId,
503
521
  offerer: account.offerer,
504
522
  claimer: account.claimer,
505
523
  token: account.mint,
@@ -590,6 +608,44 @@ export class SolanaSwapData extends SwapData {
590
608
  return SolanaTokens.WSOL_ADDRESS.equals(new PublicKey(token));
591
609
  }
592
610
 
611
+ /**
612
+ * @inheritDoc
613
+ */
614
+ getEscrowStruct(): any {
615
+ return {
616
+ accounts: {
617
+ offerer: this.offerer.toString(),
618
+ claimer: this.claimer.toString(),
619
+ claimerAta: this.claimerAta==null || this.claimerAta.equals(PublicKey.default) ? null : this.claimerAta.toString(),
620
+ offererAta: this.offererAta==null || this.offererAta.equals(PublicKey.default) ? null : this.offererAta.toString(),
621
+ claimerUserData: SolanaSwapProgram._SwapUserVault(this.programId, this.claimer, this.token).toString(),
622
+ offererUserData: SolanaSwapProgram._SwapUserVault(this.programId, this.offerer, this.token).toString(),
623
+
624
+ initializer: this.isPayIn() ? this.offerer.toString() : this.claimer.toString(),
625
+
626
+ escrowState: SolanaSwapProgram._SwapEscrowState(this.programId, Buffer.from(this.paymentHash, "hex")).toString(),
627
+ mint: this.token.toString(),
628
+ vault: SolanaSwapProgram._SwapVault(this.programId, this.token).toString(),
629
+ vaultAuthority: SolanaSwapProgram._SwapVaultAuthority(this.programId).toString(),
630
+
631
+ systemProgram: SystemProgram.programId.toString(),
632
+ tokenProgram: TOKEN_PROGRAM_ID.toString(),
633
+ ixSysvar: SYSVAR_INSTRUCTIONS_PUBKEY.toString(),
634
+ },
635
+ data: {
636
+ kind: SwapTypeEnum.fromNumber(this.kind as 0 | 1 | 2 | 3),
637
+ confirmations: this.confirmations,
638
+ nonce: this.nonce.toString(10),
639
+ hash: [...Buffer.from(this.paymentHash, "hex")],
640
+ payIn: this.payIn,
641
+ payOut: this.payOut,
642
+ amount: this.amount.toString(10),
643
+ expiry: this.expiry.toString(10),
644
+ sequence: this.sequence.toString(10)
645
+ }
646
+ }
647
+ }
648
+
593
649
  }
594
650
 
595
651
  SwapData.deserializers["sol"] = SolanaSwapData;
@@ -74,24 +74,28 @@ export class SolanaSwapProgram
74
74
  * PDA of the swap vault authority.
75
75
  * @internal
76
76
  */
77
- readonly _SwapVaultAuthority = this.pda("authority");
77
+ static readonly _SwapVaultAuthority = SolanaProgramBase._pda("authority");
78
+ readonly _SwapVaultAuthority = SolanaSwapProgram._SwapVaultAuthority(this.program.programId);
78
79
  /**
79
80
  * PDA helper for global token vault accounts.
80
81
  * @internal
81
82
  */
82
- readonly _SwapVault = this.pda("vault", (tokenAddress: PublicKey) => [tokenAddress.toBuffer()]);
83
+ static readonly _SwapVault = SolanaProgramBase._pda("vault", (tokenAddress: PublicKey) => [tokenAddress.toBuffer()]);
84
+ readonly _SwapVault = SolanaSwapProgram._SwapVault.bind(this, this.program.programId);
83
85
  /**
84
86
  * PDA helper for per-user token vault accounts.
85
87
  * @internal
86
88
  */
87
- readonly _SwapUserVault = this.pda("uservault",
89
+ static readonly _SwapUserVault = SolanaProgramBase._pda("uservault",
88
90
  (publicKey: PublicKey, tokenAddress: PublicKey) => [publicKey.toBuffer(), tokenAddress.toBuffer()]
89
91
  );
92
+ readonly _SwapUserVault = SolanaSwapProgram._SwapUserVault.bind(this, this.program.programId);
90
93
  /**
91
94
  * PDA helper for escrow state accounts.
92
95
  * @internal
93
96
  */
94
- readonly _SwapEscrowState = this.pda("state", (hash: Buffer) => [hash]);
97
+ static readonly _SwapEscrowState = SolanaProgramBase._pda("state", (hash: Buffer) => [hash]);
98
+ readonly _SwapEscrowState = SolanaSwapProgram._SwapEscrowState.bind(this, this.program.programId);
95
99
 
96
100
  ////////////////////////
97
101
  //// Timeouts
@@ -461,7 +465,7 @@ export class SolanaSwapProgram
461
465
  );
462
466
  if(account==null) return null;
463
467
 
464
- return SolanaSwapData.fromEscrowState(account);
468
+ return SolanaSwapData.fromEscrowState(this.program.programId, account);
465
469
  }
466
470
 
467
471
  /**
@@ -540,7 +544,7 @@ export class SolanaSwapProgram
540
544
  }
541
545
 
542
546
  swapsOpened[escrowHash] = {
543
- data: SolanaSwapData.fromInstruction(initIx, txoHash),
547
+ data: SolanaSwapData.fromInstruction(this.program.programId, initIx, txoHash),
544
548
  getInitTxId: () => Promise.resolve(txSignature),
545
549
  getTxBlock: () => Promise.resolve({
546
550
  blockHeight: tx.slot,
@@ -632,6 +636,7 @@ export class SolanaSwapProgram
632
636
  const claimerKey = new PublicKey(claimer);
633
637
  const {paymentHash, nonce, confirmations} = fromClaimHash(claimHash);
634
638
  const swapData = new SolanaSwapData({
639
+ programId: this.program.programId,
635
640
  offerer: offererKey,
636
641
  claimer: claimerKey,
637
642
  token: tokenAddr,
@@ -326,7 +326,7 @@ export class SwapInit extends SolanaSwapModule {
326
326
  txToSign.feePayer = swapData.isPayIn() ? swapData.offerer : swapData.claimer;
327
327
  txToSign.recentBlockhash = latestBlock.blockhash;
328
328
  txToSign.sign(signer.keypair);
329
- this.logger.debug("signSwapInitialization(): Signed tx: ",txToSign);
329
+ // this.logger.debug("signSwapInitialization(): Signed tx: ",txToSign);
330
330
 
331
331
  const sig = txToSign.signatures.find(e => e.publicKey.equals(signer.getPublicKey()));
332
332
  if(sig==null || sig.signature==null) throw new Error(`Unable to extract transaction signature! Signer: ${signer.getAddress()}`);
@@ -393,7 +393,7 @@ export class SwapInit extends SolanaSwapModule {
393
393
  txToSign.feePayer = new PublicKey(sender);
394
394
  txToSign.recentBlockhash = blockhash;
395
395
  txToSign.addSignature(signer, Buffer.from(signatureString, "hex"));
396
- this.logger.debug("isSignatureValid(): Signed tx: ",txToSign);
396
+ // this.logger.debug("isSignatureValid(): Signed tx: ",txToSign);
397
397
 
398
398
  const valid = txToSign.verifySignatures(false);
399
399