@atomiqlabs/chain-solana 13.3.0 → 13.5.6

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.
Files changed (54) hide show
  1. package/dist/index.d.ts +2 -2
  2. package/dist/index.js +2 -2
  3. package/dist/solana/SolanaChainType.d.ts +1 -1
  4. package/dist/solana/SolanaChains.d.ts +5 -2
  5. package/dist/solana/SolanaChains.js +25 -13
  6. package/dist/solana/SolanaInitializer.d.ts +30 -4
  7. package/dist/solana/SolanaInitializer.js +105 -15
  8. package/dist/solana/btcrelay/SolanaBtcRelay.d.ts +4 -2
  9. package/dist/solana/btcrelay/SolanaBtcRelay.js +7 -1
  10. package/dist/solana/chain/SolanaAction.d.ts +1 -1
  11. package/dist/solana/chain/SolanaAction.js +2 -2
  12. package/dist/solana/chain/SolanaChainInterface.d.ts +6 -1
  13. package/dist/solana/chain/SolanaChainInterface.js +30 -0
  14. package/dist/solana/events/SolanaChainEvents.d.ts +5 -1
  15. package/dist/solana/events/SolanaChainEvents.js +16 -6
  16. package/dist/solana/events/SolanaChainEventsBrowser.d.ts +39 -16
  17. package/dist/solana/events/SolanaChainEventsBrowser.js +96 -61
  18. package/dist/solana/swaps/SolanaSwapData.d.ts +50 -5
  19. package/dist/solana/swaps/SolanaSwapData.js +52 -8
  20. package/dist/solana/swaps/SolanaSwapModule.d.ts +4 -3
  21. package/dist/solana/swaps/SolanaSwapProgram.d.ts +12 -6
  22. package/dist/solana/swaps/SolanaSwapProgram.js +73 -47
  23. package/dist/solana/swaps/modules/SwapClaim.js +2 -0
  24. package/dist/solana/swaps/modules/SwapInit.d.ts +10 -5
  25. package/dist/solana/swaps/modules/SwapInit.js +222 -85
  26. package/dist/solana/swaps/modules/SwapRefund.d.ts +8 -2
  27. package/dist/solana/swaps/modules/SwapRefund.js +38 -22
  28. package/dist/solana/swaps/v1/programIdl.json +945 -0
  29. package/dist/solana/swaps/v1/programTypes.d.ts +943 -0
  30. package/dist/solana/swaps/v1/programTypes.js +945 -0
  31. package/dist/solana/swaps/v2/programIdl.json +952 -0
  32. package/dist/solana/swaps/v2/programTypes.d.ts +950 -0
  33. package/dist/solana/swaps/v2/programTypes.js +952 -0
  34. package/package.json +2 -2
  35. package/src/index.ts +2 -2
  36. package/src/solana/SolanaChainType.ts +2 -2
  37. package/src/solana/SolanaChains.ts +29 -14
  38. package/src/solana/SolanaInitializer.ts +147 -25
  39. package/src/solana/btcrelay/SolanaBtcRelay.ts +10 -2
  40. package/src/solana/chain/SolanaAction.ts +2 -2
  41. package/src/solana/chain/SolanaChainInterface.ts +35 -1
  42. package/src/solana/events/SolanaChainEvents.ts +22 -11
  43. package/src/solana/events/SolanaChainEventsBrowser.ts +110 -67
  44. package/src/solana/swaps/SolanaSwapData.ts +95 -11
  45. package/src/solana/swaps/SolanaSwapModule.ts +5 -3
  46. package/src/solana/swaps/SolanaSwapProgram.ts +87 -43
  47. package/src/solana/swaps/modules/SolanaLpVault.ts +2 -2
  48. package/src/solana/swaps/modules/SwapClaim.ts +3 -1
  49. package/src/solana/swaps/modules/SwapInit.ts +227 -99
  50. package/src/solana/swaps/modules/SwapRefund.ts +38 -20
  51. package/src/solana/swaps/v2/programIdl.json +952 -0
  52. package/src/solana/swaps/v2/programTypes.ts +1899 -0
  53. /package/src/solana/swaps/{programIdl.json → v1/programIdl.json} +0 -0
  54. /package/src/solana/swaps/{programTypes.ts → v1/programTypes.ts} +0 -0
@@ -9,6 +9,8 @@ const SolanaSwapModule_1 = require("../SolanaSwapModule");
9
9
  const Utils_1 = require("../../../utils/Utils");
10
10
  const buffer_1 = require("buffer");
11
11
  const SolanaTokens_1 = require("../../chain/modules/SolanaTokens");
12
+ const SolanaSwapProgram_1 = require("../SolanaSwapProgram");
13
+ const BN = require("bn.js");
12
14
  class SwapInit extends SolanaSwapModule_1.SolanaSwapModule {
13
15
  constructor() {
14
16
  super(...arguments);
@@ -18,14 +20,16 @@ class SwapInit extends SolanaSwapModule_1.SolanaSwapModule {
18
20
  /**
19
21
  * bare Init action based on the data passed in swapData
20
22
  *
23
+ * @param sender
21
24
  * @param swapData
22
25
  * @param timeout
23
26
  * @private
24
27
  */
25
- async Init(swapData, timeout) {
28
+ async Init(sender, swapData, timeout) {
26
29
  const claimerAta = (0, spl_token_1.getAssociatedTokenAddressSync)(swapData.token, swapData.claimer);
27
30
  const paymentHash = buffer_1.Buffer.from(swapData.paymentHash, "hex");
28
31
  const accounts = {
32
+ initializer: sender,
29
33
  claimer: swapData.claimer,
30
34
  offerer: swapData.offerer,
31
35
  escrowState: this.program._SwapEscrowState(paymentHash),
@@ -36,58 +40,116 @@ class SwapInit extends SolanaSwapModule_1.SolanaSwapModule {
36
40
  };
37
41
  if (swapData.payIn) {
38
42
  const ata = (0, spl_token_1.getAssociatedTokenAddressSync)(swapData.token, swapData.offerer);
39
- return new SolanaAction_1.SolanaAction(swapData.offerer, this.root, await this.swapProgram.methods
40
- .offererInitializePayIn(swapData.toSwapDataStruct(), [...buffer_1.Buffer.alloc(32, 0)], (0, Utils_1.toBN)(timeout))
41
- .accounts({
42
- ...accounts,
43
- offererAta: ata,
44
- vault: this.program._SwapVault(swapData.token),
45
- vaultAuthority: this.program._SwapVaultAuthority,
46
- tokenProgram: spl_token_1.TOKEN_PROGRAM_ID,
47
- })
48
- .instruction(), SwapInit.CUCosts.INIT_PAY_IN);
43
+ let instruction;
44
+ const program = this.swapProgram;
45
+ if ((0, SolanaSwapProgram_1.isSwapProgramV1)(program)) {
46
+ if (!swapData.securityDeposit.eq(new BN(0)))
47
+ throw new Error("Swap data for V1 payIn=true swaps cannot have any security deposit!");
48
+ if (!swapData.claimerBounty.eq(new BN(0)))
49
+ throw new Error("Swap data for V1 payIn=true swaps cannot have any claimer bounty!");
50
+ instruction = await program.methods
51
+ .offererInitializePayIn(swapData.toSwapDataStruct(), [...buffer_1.Buffer.alloc(32, 0)], (0, Utils_1.toBN)(timeout))
52
+ .accounts({
53
+ ...accounts,
54
+ offererAta: ata,
55
+ vault: this.program._SwapVault(swapData.token),
56
+ vaultAuthority: this.program._SwapVaultAuthority,
57
+ tokenProgram: spl_token_1.TOKEN_PROGRAM_ID,
58
+ })
59
+ .instruction();
60
+ }
61
+ else if ((0, SolanaSwapProgram_1.isSwapProgramV2)(program)) {
62
+ instruction = await program.methods
63
+ .offererInitializePayIn(swapData.toSwapDataStruct(), swapData.securityDeposit, swapData.claimerBounty, [...(swapData.txoHash != null ? buffer_1.Buffer.from(swapData.txoHash, "hex") : buffer_1.Buffer.alloc(32, 0))], (0, Utils_1.toBN)(timeout))
64
+ .accounts({
65
+ ...accounts,
66
+ offererAta: ata,
67
+ vault: this.program._SwapVault(swapData.token),
68
+ vaultAuthority: this.program._SwapVaultAuthority,
69
+ tokenProgram: spl_token_1.TOKEN_PROGRAM_ID,
70
+ })
71
+ .instruction();
72
+ // Mark the claimer as signer for non payOut swaps
73
+ if (!swapData.isPayOut()) {
74
+ instruction.keys.forEach(key => {
75
+ if (key.pubkey.equals(swapData.claimer))
76
+ key.isSigner = true;
77
+ });
78
+ }
79
+ }
80
+ else
81
+ throw new Error("Invalid swap program version!");
82
+ return new SolanaAction_1.SolanaAction(sender, this.root, instruction, SwapInit.CUCosts.INIT_PAY_IN);
49
83
  }
50
84
  else {
51
- return new SolanaAction_1.SolanaAction(swapData.claimer, this.root, await this.swapProgram.methods
85
+ const instruction = await this.swapProgram.methods
52
86
  .offererInitialize(swapData.toSwapDataStruct(), swapData.securityDeposit, swapData.claimerBounty, [...(swapData.txoHash != null ? buffer_1.Buffer.from(swapData.txoHash, "hex") : buffer_1.Buffer.alloc(32, 0))], (0, Utils_1.toBN)(timeout))
53
87
  .accounts({
54
88
  ...accounts,
55
89
  offererUserData: this.program._SwapUserVault(swapData.offerer, swapData.token),
56
90
  })
57
- .instruction(), SwapInit.CUCosts.INIT);
91
+ .instruction();
92
+ // Mark the claimer as signer for non payOut swaps
93
+ if ((0, SolanaSwapProgram_1.isSwapProgramV2)(this.swapProgram) && !swapData.isPayOut()) {
94
+ instruction.keys.forEach(key => {
95
+ if (key.pubkey.equals(swapData.claimer))
96
+ key.isSigner = true;
97
+ });
98
+ }
99
+ return new SolanaAction_1.SolanaAction(sender, this.root, instruction, SwapInit.CUCosts.INIT);
58
100
  }
59
101
  }
60
102
  /**
61
103
  * InitPayIn action which includes SOL to WSOL wrapping if indicated by the fee rate
62
104
  *
105
+ * @param signer
63
106
  * @param swapData
64
107
  * @param timeout
65
108
  * @param feeRate
66
109
  * @private
67
110
  */
68
- async InitPayIn(swapData, timeout, feeRate) {
111
+ async InitPayIn(sender, swapData, timeout, feeRate) {
69
112
  if (!swapData.isPayIn())
70
113
  throw new Error("Must be payIn==true");
71
- const action = new SolanaAction_1.SolanaAction(swapData.offerer, this.root);
114
+ if ((0, SolanaSwapProgram_1.isSwapProgramV1)(this.swapProgram)) {
115
+ if (!sender.equals(swapData.offerer))
116
+ throw new Error("Transaction signer must be offerer for payIn=true escrows!");
117
+ }
118
+ else {
119
+ if (!sender.equals(swapData.offerer) && !sender.equals(swapData.claimer))
120
+ throw new Error("Transaction signer must be either offerer or claimer claimer!");
121
+ }
122
+ const action = new SolanaAction_1.SolanaAction(sender, this.root);
72
123
  if (this.shouldWrapOnInit(swapData, feeRate))
73
- action.addAction(this.Wrap(swapData, feeRate));
74
- action.addAction(await this.Init(swapData, timeout));
124
+ action.addAction(this.Wrap(swapData, feeRate), undefined, true);
125
+ action.addAction(await this.Init(sender, swapData, timeout));
75
126
  return action;
76
127
  }
77
128
  /**
78
129
  * InitNotPayIn action with additional createAssociatedTokenAccountIdempotentInstruction instruction, such that
79
130
  * a recipient ATA is created if it doesn't exist
80
131
  *
132
+ * @param sender
81
133
  * @param swapData
82
134
  * @param timeout
83
135
  * @private
84
136
  */
85
- async InitNotPayIn(swapData, timeout) {
137
+ async InitNotPayIn(sender, swapData, timeout) {
86
138
  if (swapData.isPayIn())
87
139
  throw new Error("Must be payIn==false");
88
- const action = new SolanaAction_1.SolanaAction(swapData.claimer, this.root);
89
- action.addIx((0, spl_token_1.createAssociatedTokenAccountIdempotentInstruction)(swapData.claimer, swapData.claimerAta ?? await (0, spl_token_1.getAssociatedTokenAddress)(swapData.token, swapData.claimer), swapData.claimer, swapData.token));
90
- action.addAction(await this.Init(swapData, timeout));
140
+ if ((0, SolanaSwapProgram_1.isSwapProgramV1)(this.swapProgram)) {
141
+ if (!sender.equals(swapData.claimer))
142
+ throw new Error("Transaction signer must be claimer for payIn=false escrows!");
143
+ }
144
+ else {
145
+ if (!sender.equals(swapData.offerer) && !sender.equals(swapData.claimer))
146
+ throw new Error("Transaction signer must be either offerer or claimer claimer!");
147
+ }
148
+ const action = new SolanaAction_1.SolanaAction(sender, this.root);
149
+ if ((0, SolanaSwapProgram_1.isSwapProgramV1)(this.swapProgram)) {
150
+ action.addIx((0, spl_token_1.createAssociatedTokenAccountIdempotentInstruction)(sender, swapData.claimerAta ?? await (0, spl_token_1.getAssociatedTokenAddress)(swapData.token, swapData.claimer), swapData.claimer, swapData.token));
151
+ } // V2 doesn't explicitly check the token account on initialization, no need to open it
152
+ action.addAction(await this.Init(sender, swapData, timeout));
91
153
  return action;
92
154
  }
93
155
  Wrap(swapData, feeRate) {
@@ -139,10 +201,19 @@ class SwapInit extends SolanaSwapModule_1.SolanaSwapModule {
139
201
  * @param feeRate
140
202
  * @private
141
203
  */
142
- async getTxToSign(swapData, timeout, feeRate) {
204
+ async getTxToSign(signer, swapData, timeout, feeRate) {
205
+ let txSender;
206
+ if (signer.equals(swapData.offerer)) {
207
+ txSender = swapData.claimer;
208
+ }
209
+ else if (signer.equals(swapData.claimer)) {
210
+ txSender = swapData.offerer;
211
+ }
212
+ else
213
+ throw new Error("Signer needs to be either claimer or offerer of the swap!");
143
214
  const action = swapData.isPayIn() ?
144
- await this.InitPayIn(swapData, BigInt(timeout), feeRate) :
145
- await this.InitNotPayIn(swapData, BigInt(timeout));
215
+ await this.InitPayIn(txSender, swapData, BigInt(timeout), feeRate) :
216
+ await this.InitNotPayIn(txSender, swapData, BigInt(timeout));
146
217
  const tx = (await action.tx(feeRate)).tx;
147
218
  return tx;
148
219
  }
@@ -234,14 +305,20 @@ class SwapInit extends SolanaSwapModule_1.SolanaSwapModule {
234
305
  async signSwapInitialization(signer, swapData, authorizationTimeout, preFetchedBlockData, feeRate) {
235
306
  if (signer.keypair == null)
236
307
  throw new Error("Unsupported");
237
- if (!signer.getPublicKey().equals(swapData.isPayIn() ? swapData.claimer : swapData.offerer))
238
- throw new Error("Invalid signer, wrong public key!");
308
+ if ((0, SolanaSwapProgram_1.isSwapProgramV1)(this.swapProgram)) {
309
+ if (!signer.getPublicKey().equals(swapData.isPayIn() ? swapData.claimer : swapData.offerer))
310
+ throw new Error("Invalid signer, wrong public key!");
311
+ }
312
+ else {
313
+ if (!signer.getPublicKey().equals(swapData.offerer) && !signer.getPublicKey().equals(swapData.claimer))
314
+ throw new Error("Invalid signer, must be either offerer or claimer claimer!");
315
+ }
239
316
  if (preFetchedBlockData != null && Date.now() - preFetchedBlockData.timestamp > this.SIGNATURE_PREFETCH_DATA_VALIDITY)
240
317
  preFetchedBlockData = undefined;
241
318
  const { block: latestBlock, slot: latestSlot } = preFetchedBlockData || await this.root.Blocks.findLatestParsedBlock("finalized");
242
319
  const authTimeout = Math.floor(Date.now() / 1000) + authorizationTimeout;
243
- const txToSign = await this.getTxToSign(swapData, authTimeout.toString(10), feeRate);
244
- txToSign.feePayer = swapData.isPayIn() ? swapData.offerer : swapData.claimer;
320
+ const txToSign = await this.getTxToSign(signer.getPublicKey(), swapData, authTimeout.toString(10), feeRate);
321
+ txToSign.feePayer = signer.getPublicKey().equals(swapData.offerer) ? swapData.claimer : swapData.offerer;
245
322
  txToSign.recentBlockhash = latestBlock.blockhash;
246
323
  txToSign.sign(signer.keypair);
247
324
  // this.logger.debug("signSwapInitialization(): Signed tx: ",txToSign);
@@ -267,15 +344,25 @@ class SwapInit extends SolanaSwapModule_1.SolanaSwapModule {
267
344
  * @public
268
345
  */
269
346
  async isSignatureValid(sender, swapData, timeout, prefix, signature, feeRate, preFetchedData) {
270
- if (swapData.isPayIn()) {
271
- if (!swapData.isOfferer(sender))
272
- throw new base_1.SignatureVerificationError("Sender needs to be offerer in payIn=true swaps");
347
+ if ((0, SolanaSwapProgram_1.isSwapProgramV1)(this.swapProgram)) {
348
+ if (swapData.isPayIn()) {
349
+ if (!swapData.offerer.equals(sender))
350
+ throw new base_1.SignatureVerificationError("Sender needs to be offerer in payIn=true swaps");
351
+ }
352
+ else {
353
+ if (!swapData.claimer.equals(sender))
354
+ throw new base_1.SignatureVerificationError("Sender needs to be claimer in payIn=false swaps");
355
+ }
273
356
  }
274
- else {
275
- if (!swapData.isClaimer(sender))
276
- throw new base_1.SignatureVerificationError("Sender needs to be claimer in payIn=false swaps");
357
+ let signer;
358
+ if (sender.equals(swapData.offerer)) {
359
+ signer = swapData.claimer;
360
+ }
361
+ else if (sender.equals(swapData.claimer)) {
362
+ signer = swapData.offerer;
277
363
  }
278
- const signer = swapData.isPayIn() ? swapData.claimer : swapData.offerer;
364
+ else
365
+ throw new Error("Signer needs to be either claimer or offerer of the swap!");
279
366
  if (!swapData.isPayIn() && await this.program.isExpired(sender.toString(), swapData)) {
280
367
  throw new base_1.SignatureVerificationError("Swap will expire too soon!");
281
368
  }
@@ -285,25 +372,31 @@ class SwapInit extends SolanaSwapModule_1.SolanaSwapModule {
285
372
  const isExpired = (BigInt(timeout) - currentTimestamp) < BigInt(this.program._authGracePeriod);
286
373
  if (isExpired)
287
374
  throw new base_1.SignatureVerificationError("Authorization expired!");
288
- const [transactionSlot, signatureString] = signature.split(";");
289
- const txSlot = parseInt(transactionSlot);
290
- const [latestSlot, blockhash] = await Promise.all([
291
- this.getSlotForSignature(preFetchedData),
292
- this.getBlockhashForSignature(txSlot, preFetchedData)
293
- ]);
294
- const lastValidTransactionSlot = txSlot + this.root._TX_SLOT_VALIDITY;
295
- const slotsLeft = lastValidTransactionSlot - latestSlot - this.SIGNATURE_SLOT_BUFFER;
296
- if (slotsLeft < 0)
297
- throw new base_1.SignatureVerificationError("Authorization expired!");
298
- const txToSign = await this.getTxToSign(swapData, timeout, feeRate);
299
- txToSign.feePayer = new web3_js_1.PublicKey(sender);
300
- txToSign.recentBlockhash = blockhash;
301
- txToSign.addSignature(signer, buffer_1.Buffer.from(signatureString, "hex"));
302
- // this.logger.debug("isSignatureValid(): Signed tx: ",txToSign);
303
- const valid = txToSign.verifySignatures(false);
304
- if (!valid)
305
- throw new base_1.SignatureVerificationError("Invalid signature!");
306
- return buffer_1.Buffer.from(blockhash);
375
+ const requiresCounterpartySignature = (0, SolanaSwapProgram_1.isSwapProgramV1)(this.swapProgram) || !swapData.isPayOut() || sender.equals(swapData.claimer);
376
+ if (requiresCounterpartySignature) {
377
+ if (signature == null)
378
+ throw new base_1.SignatureVerificationError("Counterparty signature is required to initiate the swap!");
379
+ const [transactionSlot, signatureString] = signature.split(";");
380
+ const txSlot = parseInt(transactionSlot);
381
+ const [latestSlot, blockhash] = await Promise.all([
382
+ this.getSlotForSignature(preFetchedData),
383
+ this.getBlockhashForSignature(txSlot, preFetchedData)
384
+ ]);
385
+ const lastValidTransactionSlot = txSlot + this.root._TX_SLOT_VALIDITY;
386
+ const slotsLeft = lastValidTransactionSlot - latestSlot - this.SIGNATURE_SLOT_BUFFER;
387
+ if (slotsLeft < 0)
388
+ throw new base_1.SignatureVerificationError("Authorization expired!");
389
+ const txToSign = await this.getTxToSign(signer, swapData, timeout, feeRate);
390
+ txToSign.feePayer = sender;
391
+ txToSign.recentBlockhash = blockhash;
392
+ txToSign.addSignature(signer, buffer_1.Buffer.from(signatureString, "hex"));
393
+ // this.logger.debug("isSignatureValid(): Signed tx: ",txToSign);
394
+ const valid = txToSign.verifySignatures(false);
395
+ if (!valid)
396
+ throw new base_1.SignatureVerificationError("Invalid signature!");
397
+ return buffer_1.Buffer.from(blockhash);
398
+ }
399
+ return buffer_1.Buffer.alloc(32, 0);
307
400
  }
308
401
  /**
309
402
  * Gets expiry of the provided signature data, this is a minimum of slot expiry & swap signature expiry
@@ -314,16 +407,18 @@ class SwapInit extends SolanaSwapModule_1.SolanaSwapModule {
314
407
  * @public
315
408
  */
316
409
  async getSignatureExpiry(timeout, signature, preFetchedData) {
317
- const [transactionSlotStr, signatureString] = signature.split(";");
318
- const txSlot = parseInt(transactionSlotStr);
319
- const latestSlot = await this.getSlotForSignature(preFetchedData);
320
- const lastValidTransactionSlot = txSlot + this.root._TX_SLOT_VALIDITY;
321
- const slotsLeft = lastValidTransactionSlot - latestSlot - this.SIGNATURE_SLOT_BUFFER;
322
- const now = Date.now();
323
- const slotExpiryTime = now + (slotsLeft * this.root._SLOT_TIME);
324
- const timeoutExpiryTime = (parseInt(timeout) - this.program._authGracePeriod) * 1000;
325
- const expiry = Math.min(slotExpiryTime, timeoutExpiryTime);
326
- if (expiry < now)
410
+ let expiry = (parseInt(timeout) - this.program._authGracePeriod) * 1000;
411
+ if (signature != null) {
412
+ const [transactionSlotStr, signatureString] = signature.split(";");
413
+ const txSlot = parseInt(transactionSlotStr);
414
+ const latestSlot = await this.getSlotForSignature(preFetchedData);
415
+ const lastValidTransactionSlot = txSlot + this.root._TX_SLOT_VALIDITY;
416
+ const slotsLeft = lastValidTransactionSlot - latestSlot - this.SIGNATURE_SLOT_BUFFER;
417
+ const slotExpiryTime = Date.now() + (slotsLeft * this.root._SLOT_TIME);
418
+ if (slotExpiryTime < expiry)
419
+ expiry = slotExpiryTime;
420
+ }
421
+ if (expiry < Date.now())
327
422
  return 0;
328
423
  return expiry;
329
424
  }
@@ -335,13 +430,15 @@ class SwapInit extends SolanaSwapModule_1.SolanaSwapModule {
335
430
  * @public
336
431
  */
337
432
  async isSignatureExpired(signature, timeout) {
338
- const [transactionSlotStr, signatureString] = signature.split(";");
339
- const txSlot = parseInt(transactionSlotStr);
340
- const lastValidTransactionSlot = txSlot + this.root._TX_SLOT_VALIDITY;
341
- const latestSlot = await this.root.Slots.getSlot("finalized");
342
- const slotsLeft = lastValidTransactionSlot - latestSlot + this.SIGNATURE_SLOT_BUFFER;
343
- if (slotsLeft < 0)
344
- return true;
433
+ if (signature != null) {
434
+ const [transactionSlotStr, signatureString] = signature.split(";");
435
+ const txSlot = parseInt(transactionSlotStr);
436
+ const lastValidTransactionSlot = txSlot + this.root._TX_SLOT_VALIDITY;
437
+ const latestSlot = await this.root.Slots.getSlot("finalized");
438
+ const slotsLeft = lastValidTransactionSlot - latestSlot + this.SIGNATURE_SLOT_BUFFER;
439
+ if (slotsLeft < 0)
440
+ return true;
441
+ }
345
442
  if ((parseInt(timeout) + this.program._authGracePeriod) * 1000 < Date.now())
346
443
  return true;
347
444
  return false;
@@ -351,6 +448,7 @@ class SwapInit extends SolanaSwapModule_1.SolanaSwapModule {
351
448
  * the init transaction (if indicated by the fee rate) or adds the wrapping in a separate transaction (if no
352
449
  * indication in the fee rate)
353
450
  *
451
+ * @param sender
354
452
  * @param swapData swap to initialize
355
453
  * @param timeout init signature timeout
356
454
  * @param prefix init signature prefix
@@ -358,20 +456,37 @@ class SwapInit extends SolanaSwapModule_1.SolanaSwapModule {
358
456
  * @param skipChecks whether to skip signature validity checks
359
457
  * @param feeRate fee rate to use for the transaction
360
458
  */
361
- async txsInitPayIn(swapData, timeout, prefix, signature, skipChecks, feeRate) {
459
+ async txsInitPayIn(sender, swapData, timeout, prefix, signature, skipChecks, feeRate) {
460
+ if ((0, SolanaSwapProgram_1.isSwapProgramV1)(this.swapProgram)) {
461
+ if (!sender.equals(swapData.offerer))
462
+ throw new Error("Transaction sender has to be the offerer!");
463
+ }
464
+ let signer;
465
+ if (sender.equals(swapData.offerer)) {
466
+ signer = swapData.claimer;
467
+ }
468
+ else if (sender.equals(swapData.claimer)) {
469
+ signer = swapData.offerer;
470
+ }
471
+ else
472
+ throw new Error("Signer needs to be either claimer or offerer of the swap!");
362
473
  if (swapData.offererAta == undefined)
363
474
  throw new base_1.SwapDataVerificationError("No offererAta specified for payIn swap!");
364
475
  const offererAta = swapData.offererAta;
476
+ const requiresCounterpartySignature = (0, SolanaSwapProgram_1.isSwapProgramV1)(this.swapProgram) || !swapData.isPayOut() || sender.equals(swapData.claimer);
365
477
  if (!skipChecks) {
366
478
  const [_, payStatus] = await Promise.all([
367
- this.isSignatureValid(swapData.getOfferer(), swapData, timeout, prefix, signature, feeRate),
479
+ requiresCounterpartySignature ? this.isSignatureValid(sender, swapData, timeout, prefix, signature, feeRate) : Promise.resolve(),
368
480
  this.program.getClaimHashStatus(swapData.getClaimHash())
369
481
  ]);
370
482
  if (payStatus !== base_1.SwapCommitStateType.NOT_COMMITED)
371
483
  throw new base_1.SwapDataVerificationError("Invoice already being paid for or paid");
372
484
  }
373
- const [slotNumber, signatureStr] = signature.split(";");
374
- const block = await (0, Utils_1.tryWithRetries)(() => this.root.Blocks.getParsedBlock(parseInt(slotNumber)), { maxRetries: 3, delay: 100, exponential: true });
485
+ let block;
486
+ if (requiresCounterpartySignature) {
487
+ const slotNumber = signature.split(";")[0];
488
+ block = await (0, Utils_1.tryWithRetries)(() => this.root.Blocks.getParsedBlock(parseInt(slotNumber)), { maxRetries: 3, delay: 100, exponential: true });
489
+ }
375
490
  const txs = [];
376
491
  let isWrapping = false;
377
492
  const isWrappedInSignedTx = feeRate != null && feeRate.split("#").length > 1;
@@ -379,14 +494,17 @@ class SwapInit extends SolanaSwapModule_1.SolanaSwapModule {
379
494
  const ataAcc = await this.root.Tokens.getATAOrNull(offererAta);
380
495
  const balance = ataAcc?.amount ?? 0n;
381
496
  if (balance < swapData.getAmount()) {
497
+ if (!swapData.offerer.equals(sender))
498
+ throw new Error("Additional SOL needs to be wrapped but the sender is not offerer!");
382
499
  //Need to wrap more SOL to WSOL
383
500
  await this.root.Tokens.Wrap(swapData.offerer, swapData.getAmount() - balance, ataAcc == null)
384
501
  .addToTxs(txs, feeRate, block);
385
502
  isWrapping = true;
386
503
  }
387
504
  }
388
- const initTx = await (await this.InitPayIn(swapData, BigInt(timeout), feeRate)).tx(feeRate, block);
389
- initTx.tx.addSignature(swapData.claimer, buffer_1.Buffer.from(signatureStr, "hex"));
505
+ const initTx = await (await this.InitPayIn(sender, swapData, BigInt(timeout), feeRate)).tx(feeRate, block);
506
+ if (requiresCounterpartySignature)
507
+ initTx.tx.addSignature(signer, buffer_1.Buffer.from(signature.split(";")[1], "hex"));
390
508
  txs.push(initTx);
391
509
  this.logger.debug("txsInitPayIn(): create swap init TX, swap: " + swapData.getClaimHash() +
392
510
  " wrapping client-side: " + isWrapping + " feerate: " + feeRate);
@@ -395,6 +513,7 @@ class SwapInit extends SolanaSwapModule_1.SolanaSwapModule {
395
513
  /**
396
514
  * Creates init transactions (InitNotPayIn) with a valid signature from an intermediary
397
515
  *
516
+ * @param sender
398
517
  * @param swapData swap to initialize
399
518
  * @param timeout init signature timeout
400
519
  * @param prefix init signature prefix
@@ -402,14 +521,32 @@ class SwapInit extends SolanaSwapModule_1.SolanaSwapModule {
402
521
  * @param skipChecks whether to skip signature validity checks
403
522
  * @param feeRate fee rate to use for the transaction
404
523
  */
405
- async txsInit(swapData, timeout, prefix, signature, skipChecks, feeRate) {
406
- if (!skipChecks) {
407
- await this.isSignatureValid(swapData.getClaimer(), swapData, timeout, prefix, signature, feeRate);
524
+ async txsInit(sender, swapData, timeout, prefix, signature, skipChecks, feeRate) {
525
+ if ((0, SolanaSwapProgram_1.isSwapProgramV1)(this.swapProgram)) {
526
+ if (!sender.equals(swapData.claimer))
527
+ throw new Error("Transaction sender has to be the claimer!");
528
+ }
529
+ let signer;
530
+ if (sender.equals(swapData.offerer)) {
531
+ signer = swapData.claimer;
532
+ }
533
+ else if (sender.equals(swapData.claimer)) {
534
+ signer = swapData.offerer;
535
+ }
536
+ else
537
+ throw new Error("Signer needs to be either claimer or offerer of the swap!");
538
+ const requiresCounterpartySignature = (0, SolanaSwapProgram_1.isSwapProgramV1)(this.swapProgram) || !swapData.isPayOut() || sender.equals(swapData.claimer);
539
+ let block;
540
+ if (requiresCounterpartySignature) {
541
+ if (!skipChecks) {
542
+ await this.isSignatureValid(sender, swapData, timeout, prefix, signature, feeRate);
543
+ }
544
+ const slotNumber = signature.split(";")[0];
545
+ block = await (0, Utils_1.tryWithRetries)(() => this.root.Blocks.getParsedBlock(parseInt(slotNumber)), { maxRetries: 3, delay: 100, exponential: true });
408
546
  }
409
- const [slotNumber, signatureStr] = signature.split(";");
410
- const block = await (0, Utils_1.tryWithRetries)(() => this.root.Blocks.getParsedBlock(parseInt(slotNumber)), { maxRetries: 3, delay: 100, exponential: true });
411
- const initTx = await (await this.InitNotPayIn(swapData, BigInt(timeout))).tx(feeRate, block);
412
- initTx.tx.addSignature(swapData.offerer, buffer_1.Buffer.from(signatureStr, "hex"));
547
+ const initTx = await (await this.InitNotPayIn(sender, swapData, BigInt(timeout))).tx(feeRate, block);
548
+ if (requiresCounterpartySignature)
549
+ initTx.tx.addSignature(signer, buffer_1.Buffer.from(signature.split(";")[1], "hex"));
413
550
  this.logger.debug("txsInit(): create swap init TX, swap: " + swapData.getClaimHash() + " feerate: " + feeRate);
414
551
  return [initTx];
415
552
  }
@@ -481,7 +618,7 @@ class SwapInit extends SolanaSwapModule_1.SolanaSwapModule {
481
618
  : await this.getInitFeeRate(swapData.offerer, swapData.claimer, swapData.token, swapData.paymentHash));
482
619
  const [rawFee, initAta] = await Promise.all([
483
620
  this.getRawInitFee(swapData, feeRate),
484
- swapData != null && swapData.payOut ?
621
+ (0, SolanaSwapProgram_1.isSwapProgramV1)(this.swapProgram) && swapData != null && swapData.payOut ?
485
622
  this.root.Tokens.getATAOrNull((0, spl_token_1.getAssociatedTokenAddressSync)(swapData.token, swapData.claimer)).then(acc => acc == null) :
486
623
  Promise.resolve(null)
487
624
  ]);
@@ -3,6 +3,7 @@
3
3
  import { SolanaSwapModule } from "../SolanaSwapModule";
4
4
  import { SolanaSwapData } from "../SolanaSwapData";
5
5
  import { SolanaTx } from "../../chain/modules/SolanaTransactions";
6
+ import { PublicKey } from "@solana/web3.js";
6
7
  import { Buffer } from "buffer";
7
8
  import { SolanaSigner } from "../../wallet/SolanaSigner";
8
9
  export declare class SwapRefund extends SolanaSwapModule {
@@ -10,6 +11,7 @@ export declare class SwapRefund extends SolanaSwapModule {
10
11
  /**
11
12
  * Action for generic Refund instruction
12
13
  *
14
+ * @param signer
13
15
  * @param swapData
14
16
  * @param refundAuthTimeout optional refund authorization timeout (should be 0 for refunding expired swaps)
15
17
  * @private
@@ -18,6 +20,7 @@ export declare class SwapRefund extends SolanaSwapModule {
18
20
  /**
19
21
  * Action for refunding with signature, adds the Ed25519 verify instruction
20
22
  *
23
+ * @param signer
21
24
  * @param swapData
22
25
  * @param timeout
23
26
  * @param prefix
@@ -37,6 +40,7 @@ export declare class SwapRefund extends SolanaSwapModule {
37
40
  /**
38
41
  * Checks whether we should unwrap the WSOL to SOL when refunding the swap
39
42
  *
43
+ * @param signer
40
44
  * @param swapData
41
45
  * @private
42
46
  */
@@ -50,15 +54,17 @@ export declare class SwapRefund extends SolanaSwapModule {
50
54
  /**
51
55
  * Creates transactions required for refunding timed out swap, also unwraps WSOL to SOL
52
56
  *
57
+ * @param signer
53
58
  * @param swapData swap data to refund
54
59
  * @param check whether to check if swap is already expired and refundable
55
60
  * @param initAta should initialize ATA if it doesn't exist
56
61
  * @param feeRate fee rate to be used for the transactions
57
62
  */
58
- txsRefund(swapData: SolanaSwapData, check?: boolean, initAta?: boolean, feeRate?: string): Promise<SolanaTx[]>;
63
+ txsRefund(signer: PublicKey, swapData: SolanaSwapData, check?: boolean, initAta?: boolean, feeRate?: string): Promise<SolanaTx[]>;
59
64
  /**
60
65
  * Creates transactions required for refunding the swap with authorization signature, also unwraps WSOL to SOL
61
66
  *
67
+ * @param signer
62
68
  * @param swapData swap data to refund
63
69
  * @param timeout signature timeout
64
70
  * @param prefix signature prefix of the counterparty
@@ -67,7 +73,7 @@ export declare class SwapRefund extends SolanaSwapModule {
67
73
  * @param initAta should initialize ATA if it doesn't exist
68
74
  * @param feeRate fee rate to be used for the transactions
69
75
  */
70
- txsRefundWithAuthorization(swapData: SolanaSwapData, timeout: string, prefix: string, signature: string, check?: boolean, initAta?: boolean, feeRate?: string): Promise<SolanaTx[]>;
76
+ txsRefundWithAuthorization(signer: PublicKey, swapData: SolanaSwapData, timeout: string, prefix: string, signature: string, check?: boolean, initAta?: boolean, feeRate?: string): Promise<SolanaTx[]>;
71
77
  getRefundFeeRate(swapData: SolanaSwapData): Promise<string>;
72
78
  /**
73
79
  * Get the estimated solana transaction fee of the refund transaction, in the worst case scenario in case where the