@atomiqlabs/chain-solana 7.3.8 → 8.0.0-beta.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.
Files changed (57) hide show
  1. package/dist/index.d.ts +1 -0
  2. package/dist/index.js +1 -0
  3. package/dist/solana/SolanaChains.d.ts +14 -0
  4. package/dist/solana/SolanaChains.js +18 -0
  5. package/dist/solana/SolanaInitializer.d.ts +18 -0
  6. package/dist/solana/SolanaInitializer.js +59 -0
  7. package/dist/solana/base/SolanaAction.js +25 -38
  8. package/dist/solana/base/modules/SolanaBlocks.js +18 -29
  9. package/dist/solana/base/modules/SolanaEvents.js +15 -26
  10. package/dist/solana/base/modules/SolanaFees.d.ts +4 -5
  11. package/dist/solana/base/modules/SolanaFees.js +168 -182
  12. package/dist/solana/base/modules/SolanaSlots.js +16 -29
  13. package/dist/solana/base/modules/SolanaTokens.d.ts +6 -7
  14. package/dist/solana/base/modules/SolanaTokens.js +63 -84
  15. package/dist/solana/base/modules/SolanaTransactions.d.ts +2 -2
  16. package/dist/solana/base/modules/SolanaTransactions.js +143 -165
  17. package/dist/solana/btcrelay/SolanaBtcRelay.d.ts +2 -3
  18. package/dist/solana/btcrelay/SolanaBtcRelay.js +185 -221
  19. package/dist/solana/events/SolanaChainEvents.js +113 -138
  20. package/dist/solana/events/SolanaChainEventsBrowser.js +56 -65
  21. package/dist/solana/program/modules/SolanaProgramEvents.js +13 -24
  22. package/dist/solana/swaps/SolanaSwapData.d.ts +15 -11
  23. package/dist/solana/swaps/SolanaSwapData.js +29 -13
  24. package/dist/solana/swaps/SolanaSwapProgram.d.ts +40 -41
  25. package/dist/solana/swaps/SolanaSwapProgram.js +212 -221
  26. package/dist/solana/swaps/modules/SolanaDataAccount.d.ts +2 -3
  27. package/dist/solana/swaps/modules/SolanaDataAccount.js +117 -141
  28. package/dist/solana/swaps/modules/SolanaLpVault.d.ts +4 -5
  29. package/dist/solana/swaps/modules/SolanaLpVault.js +87 -110
  30. package/dist/solana/swaps/modules/SwapClaim.d.ts +4 -4
  31. package/dist/solana/swaps/modules/SwapClaim.js +122 -134
  32. package/dist/solana/swaps/modules/SwapInit.d.ts +2 -3
  33. package/dist/solana/swaps/modules/SwapInit.js +254 -285
  34. package/dist/solana/swaps/modules/SwapRefund.d.ts +2 -3
  35. package/dist/solana/swaps/modules/SwapRefund.js +103 -113
  36. package/dist/utils/Utils.d.ts +10 -0
  37. package/dist/utils/Utils.js +62 -35
  38. package/package.json +9 -6
  39. package/src/index.ts +1 -0
  40. package/src/solana/SolanaChains.ts +16 -0
  41. package/src/solana/SolanaInitializer.ts +98 -0
  42. package/src/solana/base/SolanaBase.ts +1 -2
  43. package/src/solana/base/modules/SolanaEvents.ts +0 -1
  44. package/src/solana/base/modules/SolanaFees.ts +35 -31
  45. package/src/solana/base/modules/SolanaTokens.ts +26 -27
  46. package/src/solana/base/modules/SolanaTransactions.ts +33 -28
  47. package/src/solana/btcrelay/SolanaBtcRelay.ts +6 -10
  48. package/src/solana/events/SolanaChainEventsBrowser.ts +14 -10
  49. package/src/solana/program/modules/SolanaProgramEvents.ts +1 -1
  50. package/src/solana/swaps/SolanaSwapData.ts +38 -19
  51. package/src/solana/swaps/SolanaSwapProgram.ts +133 -105
  52. package/src/solana/swaps/modules/SolanaDataAccount.ts +4 -6
  53. package/src/solana/swaps/modules/SolanaLpVault.ts +18 -18
  54. package/src/solana/swaps/modules/SwapClaim.ts +14 -17
  55. package/src/solana/swaps/modules/SwapInit.ts +35 -38
  56. package/src/solana/swaps/modules/SwapRefund.ts +20 -23
  57. package/src/utils/Utils.ts +35 -0
@@ -6,6 +6,8 @@ import {IdlAccounts, IdlTypes} from "@coral-xyz/anchor";
6
6
  import {SwapTypeEnum} from "./SwapTypeEnum";
7
7
  import {Buffer} from "buffer";
8
8
  import {getAssociatedTokenAddressSync} from "@solana/spl-token";
9
+ import {toBigInt, toClaimHash, toEscrowHash} from "../../utils/Utils";
10
+ import {SolanaTokens} from "../base/modules/SolanaTokens";
9
11
 
10
12
  const EXPIRY_BLOCKHEIGHT_THRESHOLD = new BN("1000000000");
11
13
 
@@ -161,8 +163,8 @@ export class SolanaSwapData extends SwapData {
161
163
  }
162
164
  }
163
165
 
164
- getAmount(): BN {
165
- return this.amount;
166
+ getAmount(): bigint {
167
+ return toBigInt(this.amount);
166
168
  }
167
169
 
168
170
  getToken(): string {
@@ -177,17 +179,17 @@ export class SolanaSwapData extends SwapData {
177
179
  return SolanaSwapData.kindToType(this.kind);
178
180
  }
179
181
 
180
- getExpiry(): BN {
182
+ getExpiry(): bigint {
181
183
  if(this.expiry.lt(EXPIRY_BLOCKHEIGHT_THRESHOLD)) return null;
182
- return this.expiry;
184
+ return toBigInt(this.expiry);
183
185
  }
184
186
 
185
- getConfirmations(): number {
187
+ getConfirmationsHint(): number {
186
188
  return this.confirmations;
187
189
  }
188
190
 
189
- getEscrowNonce(): BN {
190
- return this.nonce;
191
+ getNonceHint(): bigint {
192
+ return toBigInt(this.nonce);
191
193
  }
192
194
 
193
195
  isPayIn(): boolean {
@@ -198,32 +200,41 @@ export class SolanaSwapData extends SwapData {
198
200
  return this.payOut;
199
201
  }
200
202
 
201
- getHash(): string {
202
- return this.paymentHash;
203
+ getClaimHash(): string {
204
+ return toClaimHash(this.paymentHash, toBigInt(this.nonce), this.confirmations);
203
205
  }
204
206
 
205
- getSequence(): BN {
206
- return this.sequence;
207
+ getEscrowHash(): string {
208
+ return toEscrowHash(this.paymentHash, this.sequence);
207
209
  }
208
210
 
209
- getTxoHash(): string {
211
+ getSequence(): bigint {
212
+ return toBigInt(this.sequence);
213
+ }
214
+
215
+ getTxoHashHint(): string {
216
+ if(this.txoHash==="0000000000000000000000000000000000000000000000000000000000000000") return null; //Txo hash opt-out flag
217
+ return this.txoHash;
218
+ }
219
+
220
+ getExtraData(): string {
210
221
  return this.txoHash;
211
222
  }
212
223
 
213
- setTxoHash(txoHash: string): void {
224
+ setExtraData(txoHash: string): void {
214
225
  this.txoHash = txoHash;
215
226
  }
216
227
 
217
- getSecurityDeposit() {
218
- return this.securityDeposit;
228
+ getSecurityDeposit(): bigint {
229
+ return toBigInt(this.securityDeposit);
219
230
  }
220
231
 
221
- getClaimerBounty() {
222
- return this.claimerBounty;
232
+ getClaimerBounty(): bigint {
233
+ return toBigInt(this.claimerBounty);
223
234
  }
224
235
 
225
- getTotalDeposit() {
226
- return this.claimerBounty.lt(this.securityDeposit) ? this.securityDeposit : this.claimerBounty;
236
+ getTotalDeposit(): bigint {
237
+ return toBigInt(this.claimerBounty.lt(this.securityDeposit) ? this.securityDeposit : this.claimerBounty);
227
238
  }
228
239
 
229
240
  toSwapDataStruct(): IdlTypes<SwapProgram>["SwapData"] {
@@ -355,6 +366,14 @@ export class SolanaSwapData extends SwapData {
355
366
  return this.offerer.equals(new PublicKey(address));
356
367
  }
357
368
 
369
+ getDepositToken(): string {
370
+ return SolanaTokens.WSOL_ADDRESS.toString();
371
+ }
372
+
373
+ isDepositToken(token: string): boolean {
374
+ return SolanaTokens.WSOL_ADDRESS.equals(new PublicKey(token));
375
+ }
376
+
358
377
  }
359
378
 
360
379
  SwapData.deserializers["sol"] = SolanaSwapData;
@@ -1,6 +1,5 @@
1
1
  import {SolanaSwapData} from "./SolanaSwapData";
2
2
  import {IdlAccounts} from "@coral-xyz/anchor";
3
- import * as BN from "bn.js";
4
3
  import {
5
4
  Connection, Keypair,
6
5
  PublicKey,
@@ -11,7 +10,7 @@ import {SolanaBtcRelay} from "../btcrelay/SolanaBtcRelay";
11
10
  import * as programIdl from "./programIdl.json";
12
11
  import {
13
12
  IStorageManager, SwapContract, ChainSwapType, IntermediaryReputationType,
14
- SwapCommitStatus, TransactionConfirmationOptions, SignatureData, RelaySynchronizer
13
+ SwapCommitStatus, TransactionConfirmationOptions, SignatureData, RelaySynchronizer, BigIntBufferUtils
15
14
  } from "@atomiqlabs/base";
16
15
  import {SolanaBtcStoredHeader} from "../btcrelay/headers/SolanaBtcStoredHeader";
17
16
  import {
@@ -30,6 +29,9 @@ import {SolanaLpVault} from "./modules/SolanaLpVault";
30
29
  import {Buffer} from "buffer";
31
30
  import {SolanaSigner} from "../wallet/SolanaSigner";
32
31
  import {SolanaKeypairWallet} from "../wallet/SolanaKeypairWallet";
32
+ import {fromClaimHash, toBN, toClaimHash} from "../../utils/Utils";
33
+ import {SolanaTokens} from "../base/modules/SolanaTokens";
34
+ import * as BN from "bn.js";
33
35
 
34
36
  function toPublicKeyOrNull(str: string | null): PublicKey | null {
35
37
  return str==null ? null : new PublicKey(str);
@@ -98,11 +100,11 @@ export class SolanaSwapProgram
98
100
  await this.DataAccount.init();
99
101
  }
100
102
 
101
- getClaimableDeposits(signer: string): Promise<{count: number, totalValue: BN}> {
103
+ getClaimableDeposits(signer: string): Promise<{count: number, totalValue: bigint}> {
102
104
  return this.DataAccount.getDataAccountsInfo(new PublicKey(signer));
103
105
  }
104
106
 
105
- claimDeposits(signer: SolanaSigner): Promise<{txIds: string[], count: number, totalValue: BN}> {
107
+ claimDeposits(signer: SolanaSigner): Promise<{txIds: string[], count: number, totalValue: bigint}> {
106
108
  return this.DataAccount.sweepDataAccounts(signer);
107
109
  }
108
110
 
@@ -156,10 +158,10 @@ export class SolanaSwapProgram
156
158
  * @param signer
157
159
  * @param data
158
160
  */
159
- isClaimable(signer: string, data: SolanaSwapData): Promise<boolean> {
160
- if(!data.isClaimer(signer)) return Promise.resolve(false);
161
- if(this.isExpired(signer, data)) return Promise.resolve(false);
162
- return this.isCommited(data);
161
+ async isClaimable(signer: string, data: SolanaSwapData): Promise<boolean> {
162
+ if(!data.isClaimer(signer)) return false;
163
+ if(await this.isExpired(signer, data)) return false;
164
+ return await this.isCommited(data);
163
165
  }
164
166
 
165
167
  /**
@@ -183,11 +185,11 @@ export class SolanaSwapProgram
183
185
  * @param signer
184
186
  * @param data
185
187
  */
186
- isExpired(signer: string, data: SolanaSwapData): boolean {
188
+ isExpired(signer: string, data: SolanaSwapData): Promise<boolean> {
187
189
  let currentTimestamp: BN = new BN(Math.floor(Date.now()/1000));
188
190
  if(data.isClaimer(signer)) currentTimestamp = currentTimestamp.sub(new BN(this.refundGracePeriod));
189
191
  if(data.isOfferer(signer)) currentTimestamp = currentTimestamp.add(new BN(this.claimGracePeriod));
190
- return data.expiry.lt(currentTimestamp);
192
+ return Promise.resolve(data.expiry.lt(currentTimestamp));
191
193
  }
192
194
 
193
195
  /**
@@ -197,11 +199,11 @@ export class SolanaSwapProgram
197
199
  * @param signer
198
200
  * @param data
199
201
  */
200
- isRequestRefundable(signer: string, data: SolanaSwapData): Promise<boolean> {
202
+ async isRequestRefundable(signer: string, data: SolanaSwapData): Promise<boolean> {
201
203
  //Swap can only be refunded by the offerer
202
- if(!data.isOfferer(signer)) return Promise.resolve(false);
203
- if(!this.isExpired(signer, data)) return Promise.resolve(false);
204
- return this.isCommited(data);
204
+ if(!data.isOfferer(signer)) return false;
205
+ if(!(await this.isExpired(signer, data))) return false;
206
+ return await this.isCommited(data);
205
207
  }
206
208
 
207
209
  /**
@@ -209,14 +211,33 @@ export class SolanaSwapProgram
209
211
  *
210
212
  * @param outputScript output script required to claim the swap
211
213
  * @param amount sats sent required to claim the swap
214
+ * @param confirmations
212
215
  * @param nonce swap nonce uniquely identifying the transaction to prevent replay attacks
213
216
  */
214
- getHashForOnchain(outputScript: Buffer, amount: BN, nonce: BN): Buffer {
215
- return createHash("sha256").update(Buffer.concat([
216
- Buffer.from(nonce.toArray("le", 8)),
217
- Buffer.from(amount.toArray("le", 8)),
217
+ getHashForOnchain(outputScript: Buffer, amount: bigint, confirmations: number, nonce?: bigint): Buffer {
218
+ nonce ??= 0n;
219
+ const paymentHash = createHash("sha256").update(Buffer.concat([
220
+ BigIntBufferUtils.toBuffer(nonce, "le", 8),
221
+ BigIntBufferUtils.toBuffer(amount, "le", 8),
218
222
  outputScript
219
- ])).digest();
223
+ ])).digest().toString("hex");
224
+ return Buffer.from(toClaimHash(paymentHash, nonce, confirmations), "hex");
225
+ }
226
+
227
+ getHashForHtlc(swapHash: Buffer): Buffer {
228
+ return Buffer.from(toClaimHash(
229
+ swapHash.toString("hex"),
230
+ 0n,
231
+ 0
232
+ ), "hex");
233
+ }
234
+
235
+ getHashForTxId(txId: string, confirmations: number): Buffer {
236
+ return Buffer.from(toClaimHash(
237
+ Buffer.from(txId, "hex").reverse().toString("hex"),
238
+ 0n,
239
+ confirmations
240
+ ), "hex");
220
241
  }
221
242
 
222
243
  ////////////////////////////////////////////
@@ -230,14 +251,18 @@ export class SolanaSwapProgram
230
251
  */
231
252
  async getCommitStatus(signer: string, data: SolanaSwapData): Promise<SwapCommitStatus> {
232
253
  const escrowStateKey = this.SwapEscrowState(Buffer.from(data.paymentHash, "hex"));
233
- const escrowState: IdlAccounts<SwapProgram>["escrowState"] = await this.program.account.escrowState.fetchNullable(escrowStateKey);
254
+ const [escrowState, isExpired] = await Promise.all([
255
+ this.program.account.escrowState.fetchNullable(escrowStateKey) as Promise<IdlAccounts<SwapProgram>["escrowState"]>,
256
+ this.isExpired(signer,data)
257
+ ]);
258
+
234
259
  if(escrowState!=null) {
235
260
  if(data.correctPDA(escrowState)) {
236
- if(data.isOfferer(signer) && this.isExpired(signer,data)) return SwapCommitStatus.REFUNDABLE;
261
+ if(data.isOfferer(signer) && isExpired) return SwapCommitStatus.REFUNDABLE;
237
262
  return SwapCommitStatus.COMMITED;
238
263
  }
239
264
 
240
- if(data.isOfferer(signer) && this.isExpired(signer, data)) return SwapCommitStatus.EXPIRED;
265
+ if(data.isOfferer(signer) && isExpired) return SwapCommitStatus.EXPIRED;
241
266
  return SwapCommitStatus.NOT_COMMITED;
242
267
  }
243
268
 
@@ -249,13 +274,13 @@ export class SolanaSwapProgram
249
274
  }
250
275
  if(event.name==="RefundEvent") {
251
276
  if(!event.data.sequence.eq(data.sequence)) return null;
252
- if(this.isExpired(signer, data)) return SwapCommitStatus.EXPIRED;
277
+ if(isExpired) return SwapCommitStatus.EXPIRED;
253
278
  return SwapCommitStatus.NOT_COMMITED;
254
279
  }
255
280
  });
256
281
  if(status!=null) return status;
257
282
 
258
- if(this.isExpired(signer, data)) {
283
+ if(isExpired) {
259
284
  return SwapCommitStatus.EXPIRED;
260
285
  }
261
286
  return SwapCommitStatus.NOT_COMMITED;
@@ -264,9 +289,10 @@ export class SolanaSwapProgram
264
289
  /**
265
290
  * Checks the status of the specific payment hash
266
291
  *
267
- * @param paymentHash
292
+ * @param claimHash
268
293
  */
269
- async getPaymentHashStatus(paymentHash: string): Promise<SwapCommitStatus> {
294
+ async getClaimHashStatus(claimHash: string): Promise<SwapCommitStatus> {
295
+ const {paymentHash} = fromClaimHash(claimHash);
270
296
  const escrowStateKey = this.SwapEscrowState(Buffer.from(paymentHash, "hex"));
271
297
  const abortController = new AbortController();
272
298
 
@@ -298,12 +324,13 @@ export class SolanaSwapProgram
298
324
  * Returns the data committed for a specific payment hash, or null if no data is currently commited for
299
325
  * the specific swap
300
326
  *
301
- * @param paymentHashHex
327
+ * @param claimHashHex
302
328
  */
303
- async getCommitedData(paymentHashHex: string): Promise<SolanaSwapData> {
304
- const paymentHash = Buffer.from(paymentHashHex, "hex");
329
+ async getCommitedData(claimHashHex: string): Promise<SolanaSwapData> {
330
+ const {paymentHash} = fromClaimHash(claimHashHex);
331
+ const paymentHashBuffer = Buffer.from(paymentHash, "hex");
305
332
 
306
- const account: IdlAccounts<SwapProgram>["escrowState"] = await this.program.account.escrowState.fetchNullable(this.SwapEscrowState(paymentHash));
333
+ const account: IdlAccounts<SwapProgram>["escrowState"] = await this.program.account.escrowState.fetchNullable(this.SwapEscrowState(paymentHashBuffer));
307
334
  if(account==null) return null;
308
335
 
309
336
  return SolanaSwapData.fromEscrowState(account);
@@ -316,60 +343,64 @@ export class SolanaSwapProgram
316
343
  offerer: string,
317
344
  claimer: string,
318
345
  token: string,
319
- amount: BN,
320
- paymentHash: string,
321
- sequence: BN,
322
- expiry: BN,
323
- escrowNonce: BN,
324
- confirmations: number,
346
+ amount: bigint,
347
+ claimHash: string,
348
+ sequence: bigint,
349
+ expiry: bigint,
325
350
  payIn: boolean,
326
351
  payOut: boolean,
327
- securityDeposit: BN,
328
- claimerBounty: BN
352
+ securityDeposit: bigint,
353
+ claimerBounty: bigint,
354
+ depositToken?: string
329
355
  ): Promise<SolanaSwapData> {
356
+ if(depositToken!=null) {
357
+ if(!new PublicKey(depositToken).equals(SolanaTokens.WSOL_ADDRESS)) throw new Error("Only SOL supported as deposit token!");
358
+ }
330
359
  const tokenAddr: PublicKey = new PublicKey(token);
331
360
  const offererKey = offerer==null ? null : new PublicKey(offerer);
332
361
  const claimerKey = claimer==null ? null : new PublicKey(claimer);
362
+ const {paymentHash, nonce, confirmations} = fromClaimHash(claimHash);
333
363
  return Promise.resolve(new SolanaSwapData(
334
364
  offererKey,
335
365
  claimerKey,
336
366
  tokenAddr,
337
- amount,
367
+ toBN(amount),
338
368
  paymentHash,
339
- sequence,
340
- expiry,
341
- escrowNonce,
369
+ toBN(sequence),
370
+ toBN(expiry),
371
+ nonce,
342
372
  confirmations,
343
373
  payOut,
344
374
  type==null ? null : SolanaSwapData.typeToKind(type),
345
375
  payIn,
346
376
  offererKey==null ? null : payIn ? getAssociatedTokenAddressSync(tokenAddr, offererKey) : PublicKey.default,
347
377
  claimerKey==null ? null : payOut ? getAssociatedTokenAddressSync(tokenAddr, claimerKey) : PublicKey.default,
348
- securityDeposit,
349
- claimerBounty,
378
+ toBN(securityDeposit),
379
+ toBN(claimerBounty),
350
380
  null
351
381
  ));
352
382
  }
353
383
 
354
384
  ////////////////////////////////////////////
355
385
  //// Utils
356
- async getBalance(signer: string, tokenAddress: string, inContract: boolean): Promise<BN> {
386
+ async getBalance(signer: string, tokenAddress: string, inContract: boolean): Promise<bigint> {
357
387
  const token = new PublicKey(tokenAddress);
358
388
  const publicKey = new PublicKey(signer);
359
389
 
360
390
  if(inContract) return await this.getIntermediaryBalance(publicKey, token);
361
391
 
362
- let { balance, ataExists } = await this.Tokens.getTokenBalance(publicKey, token);
363
- if(token.equals(this.Tokens.WSOL_ADDRESS)) {
364
- const accountRentExemptCost = new BN(1000000);
365
- balance = BN.max(balance.sub(accountRentExemptCost), new BN(0));
392
+ let { balance } = await this.Tokens.getTokenBalance(publicKey, token);
393
+ if(token.equals(SolanaTokens.WSOL_ADDRESS)) {
394
+ const accountRentExemptCost = 1000000n;
395
+ balance = balance - accountRentExemptCost;
396
+ if(balance < 0n) balance = 0n;
366
397
  }
367
398
  this.logger.debug("getBalance(): token balance, token: "+token.toBase58()+" balance: "+balance.toString(10));
368
399
  return balance;
369
400
  }
370
401
 
371
402
  getIntermediaryData(address: string, token: string): Promise<{
372
- balance: BN,
403
+ balance: bigint,
373
404
  reputation: IntermediaryReputationType
374
405
  }> {
375
406
  return this.LpVault.getIntermediaryData(new PublicKey(address), new PublicKey(token));
@@ -379,7 +410,7 @@ export class SolanaSwapProgram
379
410
  return this.LpVault.getIntermediaryReputation(new PublicKey(address), new PublicKey(token));
380
411
  }
381
412
 
382
- getIntermediaryBalance(address: PublicKey, token: PublicKey): Promise<BN> {
413
+ getIntermediaryBalance(address: PublicKey, token: PublicKey): Promise<bigint> {
383
414
  return this.LpVault.getIntermediaryBalance(address, token);
384
415
  }
385
416
 
@@ -408,8 +439,8 @@ export class SolanaSwapProgram
408
439
  async txsClaimWithTxData(
409
440
  signer: string | SolanaSigner,
410
441
  swapData: SolanaSwapData,
411
- blockheight: number,
412
- tx: { blockhash: string, confirmations: number, txid: string, hex: string },
442
+ tx: { blockhash: string, confirmations: number, txid: string, hex: string, height: number },
443
+ requiredConfirmations: number,
413
444
  vout: number,
414
445
  commitedHeader?: SolanaBtcStoredHeader,
415
446
  synchronizer?: RelaySynchronizer<any, SolanaTx, any>,
@@ -417,34 +448,37 @@ export class SolanaSwapProgram
417
448
  feeRate?: string,
418
449
  storageAccHolder?: {storageAcc: PublicKey}
419
450
  ): Promise<SolanaTx[] | null> {
420
- return this.Claim.txsClaimWithTxData(typeof(signer)==="string" ? new PublicKey(signer) : signer, swapData, blockheight, tx, vout, commitedHeader, synchronizer, initAta, storageAccHolder, feeRate);
451
+ if(swapData.confirmations!==requiredConfirmations) throw new Error("Invalid requiredConfirmations provided!");
452
+ return this.Claim.txsClaimWithTxData(typeof(signer)==="string" ? new PublicKey(signer) : signer, swapData, tx, vout, commitedHeader, synchronizer, initAta, storageAccHolder, feeRate);
421
453
  }
422
454
 
423
- txsRefund(swapData: SolanaSwapData, check?: boolean, initAta?: boolean, feeRate?: string): Promise<SolanaTx[]> {
455
+ txsRefund(signer: string, swapData: SolanaSwapData, check?: boolean, initAta?: boolean, feeRate?: string): Promise<SolanaTx[]> {
456
+ if(!swapData.isOfferer(signer)) throw new Error("Only offerer can refund on Solana");
424
457
  return this.Refund.txsRefund(swapData, check, initAta, feeRate);
425
458
  }
426
459
 
427
- txsRefundWithAuthorization(swapData: SolanaSwapData, {timeout, prefix, signature}, check?: boolean, initAta?: boolean, feeRate?: string): Promise<SolanaTx[]> {
460
+ txsRefundWithAuthorization(signer: string, swapData: SolanaSwapData, {timeout, prefix, signature}, check?: boolean, initAta?: boolean, feeRate?: string): Promise<SolanaTx[]> {
461
+ if(!swapData.isOfferer(signer)) throw new Error("Only offerer can refund on Solana");
428
462
  return this.Refund.txsRefundWithAuthorization(swapData,timeout,prefix,signature,check,initAta,feeRate);
429
463
  }
430
464
 
431
- txsInitPayIn(swapData: SolanaSwapData, {timeout, prefix, signature}, skipChecks?: boolean, feeRate?: string): Promise<SolanaTx[]> {
432
- return this.Init.txsInitPayIn(swapData, timeout, prefix, signature, skipChecks, feeRate);
433
- }
434
-
435
- txsInit(swapData: SolanaSwapData, {timeout, prefix, signature}, txoHash?: Buffer, skipChecks?: boolean, feeRate?: string): Promise<SolanaTx[]> {
436
- return this.Init.txsInit(swapData, timeout, prefix, signature, skipChecks, feeRate);
465
+ txsInit(swapData: SolanaSwapData, {timeout, prefix, signature}, skipChecks?: boolean, feeRate?: string): Promise<SolanaTx[]> {
466
+ if(swapData.isPayIn()) {
467
+ return this.Init.txsInitPayIn(swapData, timeout, prefix, signature, skipChecks, feeRate);
468
+ } else {
469
+ return this.Init.txsInit(swapData, timeout, prefix, signature, skipChecks, feeRate);
470
+ }
437
471
  }
438
472
 
439
- txsWithdraw(signer: string, token: string, amount: BN, feeRate?: string): Promise<SolanaTx[]> {
473
+ txsWithdraw(signer: string, token: string, amount: bigint, feeRate?: string): Promise<SolanaTx[]> {
440
474
  return this.LpVault.txsWithdraw(new PublicKey(signer), new PublicKey(token), amount, feeRate);
441
475
  }
442
476
 
443
- txsDeposit(signer: string, token: string, amount: BN, feeRate?: string): Promise<SolanaTx[]> {
477
+ txsDeposit(signer: string, token: string, amount: bigint, feeRate?: string): Promise<SolanaTx[]> {
444
478
  return this.LpVault.txsDeposit(new PublicKey(signer), new PublicKey(token), amount, feeRate);
445
479
  }
446
480
 
447
- txsTransfer(signer: string, token: string, amount: BN, dstAddress: string, feeRate?: string): Promise<SolanaTx[]> {
481
+ txsTransfer(signer: string, token: string, amount: bigint, dstAddress: string, feeRate?: string): Promise<SolanaTx[]> {
448
482
  return this.Tokens.txsTransfer(new PublicKey(signer), new PublicKey(token), amount, new PublicKey(dstAddress), feeRate);
449
483
  }
450
484
 
@@ -466,20 +500,22 @@ export class SolanaSwapProgram
466
500
  async claimWithTxData(
467
501
  signer: SolanaSigner,
468
502
  swapData: SolanaSwapData,
469
- blockheight: number,
470
- tx: { blockhash: string, confirmations: number, txid: string, hex: string },
503
+ tx: { blockhash: string, confirmations: number, txid: string, hex: string, height: number },
504
+ requiredConfirmations: number,
471
505
  vout: number,
472
506
  commitedHeader?: SolanaBtcStoredHeader,
473
507
  synchronizer?: RelaySynchronizer<any, SolanaTx, any>,
474
508
  initAta?: boolean,
475
509
  txOptions?: TransactionConfirmationOptions
476
510
  ): Promise<string> {
511
+ if(requiredConfirmations!==swapData.confirmations) throw new Error("Invalid requiredConfirmations provided!");
512
+
477
513
  const data: {storageAcc: PublicKey} = {
478
514
  storageAcc: null
479
515
  };
480
516
 
481
517
  const txs = await this.Claim.txsClaimWithTxData(
482
- signer, swapData, blockheight, tx, vout,
518
+ signer, swapData, tx, vout,
483
519
  commitedHeader, synchronizer, initAta, data, txOptions?.feeRate
484
520
  );
485
521
  if(txs===null) throw new Error("Btc relay not synchronized to required blockheight!");
@@ -498,9 +534,7 @@ export class SolanaSwapProgram
498
534
  initAta?: boolean,
499
535
  txOptions?: TransactionConfirmationOptions
500
536
  ): Promise<string> {
501
- if(!signer.getPublicKey().equals(swapData.offerer)) throw new Error("Invalid signer provided!");
502
-
503
- let result = await this.txsRefund(swapData, check, initAta, txOptions?.feeRate);
537
+ let result = await this.txsRefund(signer.getAddress(), swapData, check, initAta, txOptions?.feeRate);
504
538
 
505
539
  const [signature] = await this.Transactions.sendAndConfirm(signer, result, txOptions?.waitForConfirmation, txOptions?.abortSignal);
506
540
 
@@ -515,42 +549,27 @@ export class SolanaSwapProgram
515
549
  initAta?: boolean,
516
550
  txOptions?: TransactionConfirmationOptions
517
551
  ): Promise<string> {
518
- if(!signer.getPublicKey().equals(swapData.offerer)) throw new Error("Invalid signer provided!");
519
-
520
- let result = await this.txsRefundWithAuthorization(swapData, signature, check, initAta, txOptions?.feeRate);
552
+ let result = await this.txsRefundWithAuthorization(signer.getAddress(), swapData, signature, check, initAta, txOptions?.feeRate);
521
553
 
522
554
  const [txSignature] = await this.Transactions.sendAndConfirm(signer, result, txOptions?.waitForConfirmation, txOptions?.abortSignal);
523
555
 
524
556
  return txSignature;
525
557
  }
526
558
 
527
- async initPayIn(
528
- signer: SolanaSigner,
529
- swapData: SolanaSwapData,
530
- signature: SignatureData,
531
- skipChecks?: boolean,
532
- txOptions?: TransactionConfirmationOptions
533
- ): Promise<string> {
534
- if(!signer.getPublicKey().equals(swapData.offerer)) throw new Error("Invalid signer provided!");
535
-
536
- let result = await this.txsInitPayIn(swapData, signature, skipChecks, txOptions?.feeRate);
537
-
538
- const signatures = await this.Transactions.sendAndConfirm(signer, result, txOptions?.waitForConfirmation, txOptions?.abortSignal);
539
-
540
- return signatures[signatures.length-1];
541
- }
542
-
543
559
  async init(
544
560
  signer: SolanaSigner,
545
561
  swapData: SolanaSwapData,
546
562
  signature: SignatureData,
547
- txoHash?: Buffer,
548
563
  skipChecks?: boolean,
549
564
  txOptions?: TransactionConfirmationOptions
550
565
  ): Promise<string> {
551
- if(!signer.getPublicKey().equals(swapData.claimer)) throw new Error("Invalid signer provided!");
566
+ if(swapData.isPayIn()) {
567
+ if(!signer.getPublicKey().equals(swapData.offerer)) throw new Error("Invalid signer provided!");
568
+ } else {
569
+ if(!signer.getPublicKey().equals(swapData.claimer)) throw new Error("Invalid signer provided!");
570
+ }
552
571
 
553
- let result = await this.txsInit(swapData, signature, txoHash, skipChecks, txOptions?.feeRate);
572
+ const result = await this.txsInit(swapData, signature, skipChecks, txOptions?.feeRate);
554
573
 
555
574
  const [txSignature] = await this.Transactions.sendAndConfirm(signer, result, txOptions?.waitForConfirmation, txOptions?.abortSignal);
556
575
 
@@ -567,7 +586,7 @@ export class SolanaSwapProgram
567
586
  ): Promise<string[]> {
568
587
  if(!signer.getPublicKey().equals(swapData.claimer)) throw new Error("Invalid signer provided!");
569
588
 
570
- const txsCommit = await this.txsInit(swapData, signature, null, skipChecks, txOptions?.feeRate);
589
+ const txsCommit = await this.txsInit(swapData, signature, skipChecks, txOptions?.feeRate);
571
590
  const txsClaim = await this.Claim.txsClaimWithSecret(signer.getPublicKey(), swapData, secret, true, false, txOptions?.feeRate, true);
572
591
 
573
592
  return await this.Transactions.sendAndConfirm(signer, txsCommit.concat(txsClaim), txOptions?.waitForConfirmation, txOptions?.abortSignal);
@@ -576,7 +595,7 @@ export class SolanaSwapProgram
576
595
  async withdraw(
577
596
  signer: SolanaSigner,
578
597
  token: string,
579
- amount: BN,
598
+ amount: bigint,
580
599
  txOptions?: TransactionConfirmationOptions
581
600
  ): Promise<string> {
582
601
  const txs = await this.LpVault.txsWithdraw(signer.getPublicKey(), new PublicKey(token), amount, txOptions?.feeRate);
@@ -587,7 +606,7 @@ export class SolanaSwapProgram
587
606
  async deposit(
588
607
  signer: SolanaSigner,
589
608
  token: string,
590
- amount: BN,
609
+ amount: bigint,
591
610
  txOptions?: TransactionConfirmationOptions
592
611
  ): Promise<string> {
593
612
  const txs = await this.LpVault.txsDeposit(signer.getPublicKey(), new PublicKey(token), amount, txOptions?.feeRate);
@@ -598,7 +617,7 @@ export class SolanaSwapProgram
598
617
  async transfer(
599
618
  signer: SolanaSigner,
600
619
  token: string,
601
- amount: BN,
620
+ amount: bigint,
602
621
  dstAddress: string,
603
622
  txOptions?: TransactionConfirmationOptions
604
623
  ): Promise<string> {
@@ -638,7 +657,8 @@ export class SolanaSwapProgram
638
657
 
639
658
  ////////////////////////////////////////////
640
659
  //// Fees
641
- getInitPayInFeeRate(offerer?: string, claimer?: string, token?: string, paymentHash?: string): Promise<string> {
660
+ getInitPayInFeeRate(offerer?: string, claimer?: string, token?: string, claimHash?: string): Promise<string> {
661
+ const paymentHash = claimHash==null ? null : fromClaimHash(claimHash).paymentHash;
642
662
  return this.Init.getInitPayInFeeRate(
643
663
  toPublicKeyOrNull(offerer),
644
664
  toPublicKeyOrNull(claimer),
@@ -647,7 +667,8 @@ export class SolanaSwapProgram
647
667
  );
648
668
  }
649
669
 
650
- getInitFeeRate(offerer?: string, claimer?: string, token?: string, paymentHash?: string): Promise<string> {
670
+ getInitFeeRate(offerer?: string, claimer?: string, token?: string, claimHash?: string): Promise<string> {
671
+ const paymentHash = claimHash==null ? null : fromClaimHash(claimHash).paymentHash;
651
672
  return this.Init.getInitFeeRate(
652
673
  toPublicKeyOrNull(offerer),
653
674
  toPublicKeyOrNull(claimer),
@@ -664,39 +685,39 @@ export class SolanaSwapProgram
664
685
  return this.Claim.getClaimFeeRate(new PublicKey(signer), swapData);
665
686
  }
666
687
 
667
- getClaimFee(signer: string, swapData: SolanaSwapData, feeRate?: string): Promise<BN> {
688
+ getClaimFee(signer: string, swapData: SolanaSwapData, feeRate?: string): Promise<bigint> {
668
689
  return this.Claim.getClaimFee(new PublicKey(signer), swapData, feeRate);
669
690
  }
670
691
 
671
- getRawClaimFee(signer: string, swapData: SolanaSwapData, feeRate?: string): Promise<BN> {
692
+ getRawClaimFee(signer: string, swapData: SolanaSwapData, feeRate?: string): Promise<bigint> {
672
693
  return this.Claim.getRawClaimFee(new PublicKey(signer), swapData, feeRate);
673
694
  }
674
695
 
675
696
  /**
676
697
  * Get the estimated solana fee of the commit transaction
677
698
  */
678
- getCommitFee(swapData: SolanaSwapData, feeRate?: string): Promise<BN> {
699
+ getCommitFee(swapData: SolanaSwapData, feeRate?: string): Promise<bigint> {
679
700
  return this.Init.getInitFee(swapData, feeRate);
680
701
  }
681
702
 
682
703
  /**
683
704
  * Get the estimated solana fee of the commit transaction, without any deposits
684
705
  */
685
- getRawCommitFee(swapData: SolanaSwapData, feeRate?: string): Promise<BN> {
706
+ getRawCommitFee(swapData: SolanaSwapData, feeRate?: string): Promise<bigint> {
686
707
  return this.Init.getRawInitFee(swapData, feeRate);
687
708
  }
688
709
 
689
710
  /**
690
711
  * Get the estimated solana transaction fee of the refund transaction
691
712
  */
692
- getRefundFee(swapData: SolanaSwapData, feeRate?: string): Promise<BN> {
713
+ getRefundFee(swapData: SolanaSwapData, feeRate?: string): Promise<bigint> {
693
714
  return this.Refund.getRefundFee(swapData, feeRate);
694
715
  }
695
716
 
696
717
  /**
697
718
  * Get the estimated solana transaction fee of the refund transaction
698
719
  */
699
- getRawRefundFee(swapData: SolanaSwapData, feeRate?: string): Promise<BN> {
720
+ getRawRefundFee(swapData: SolanaSwapData, feeRate?: string): Promise<bigint> {
700
721
  return this.Refund.getRawRefundFee(swapData, feeRate);
701
722
  }
702
723
 
@@ -743,4 +764,11 @@ export class SolanaSwapProgram
743
764
  return new SolanaSigner(wallet, keypair);
744
765
  }
745
766
 
767
+ getExtraData(outputScript: Buffer, amount: bigint, confirmations: number, nonce?: bigint): Buffer {
768
+ return createHash("sha256").update(Buffer.concat([
769
+ BigIntBufferUtils.toBuffer(amount, "le", 8),
770
+ outputScript
771
+ ])).digest();
772
+ }
773
+
746
774
  }