@atomiqlabs/chain-solana 11.0.0 → 12.0.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.
@@ -7,4 +7,5 @@ import { SolanaSwapData } from "./swaps/SolanaSwapData";
7
7
  import { SolanaChainEventsBrowser } from "./events/SolanaChainEventsBrowser";
8
8
  import { SolanaBtcRelay } from "./btcrelay/SolanaBtcRelay";
9
9
  import { SolanaChainInterface } from "./chain/SolanaChainInterface";
10
- export type SolanaChainType = ChainType<"SOLANA", SolanaPreFetchData, SolanaPreFetchVerification, SolanaTx, SolanaSigner, SolanaSwapData, SolanaSwapProgram, SolanaChainInterface, SolanaChainEventsBrowser, SolanaBtcRelay<any>, never, never, never>;
10
+ import { Wallet } from "@coral-xyz/anchor/dist/cjs/provider";
11
+ export type SolanaChainType = ChainType<"SOLANA", SolanaPreFetchData, SolanaPreFetchVerification, SolanaTx, SolanaSigner, Wallet, SolanaSwapData, SolanaSwapProgram, SolanaChainInterface, SolanaChainEventsBrowser, SolanaBtcRelay<any>, never, never, never>;
@@ -10,13 +10,14 @@ import { SolanaEvents } from "./modules/SolanaEvents";
10
10
  import { ChainInterface, TransactionConfirmationOptions } from "@atomiqlabs/base";
11
11
  import { SolanaSigner } from "../wallet/SolanaSigner";
12
12
  import { Buffer } from "buffer";
13
+ import { Wallet } from "@coral-xyz/anchor/dist/cjs/provider";
13
14
  export type SolanaRetryPolicy = {
14
15
  maxRetries?: number;
15
16
  delay?: number;
16
17
  exponential?: boolean;
17
18
  transactionResendInterval?: number;
18
19
  };
19
- export declare class SolanaChainInterface implements ChainInterface<SolanaTx, SolanaSigner, "SOLANA"> {
20
+ export declare class SolanaChainInterface implements ChainInterface<SolanaTx, SolanaSigner, "SOLANA", Wallet> {
20
21
  readonly chainId = "SOLANA";
21
22
  readonly SLOT_TIME = 400;
22
23
  readonly TX_SLOT_VALIDITY = 151;
@@ -38,6 +39,7 @@ export declare class SolanaChainInterface implements ChainInterface<SolanaTx, So
38
39
  constructor(connection: Connection, retryPolicy?: SolanaRetryPolicy, solanaFeeEstimator?: SolanaFees);
39
40
  getBalance(signer: string, tokenAddress: string): Promise<bigint>;
40
41
  isValidAddress(address: string): boolean;
42
+ normalizeAddress(address: string): string;
41
43
  getNativeCurrencyAddress(): string;
42
44
  txsTransfer(signer: string, token: string, amount: bigint, dstAddress: string, feeRate?: string): Promise<SolanaTx[]>;
43
45
  transfer(signer: SolanaSigner, token: string, amount: bigint, dstAddress: string, txOptions?: TransactionConfirmationOptions): Promise<string>;
@@ -46,6 +48,10 @@ export declare class SolanaChainInterface implements ChainInterface<SolanaTx, So
46
48
  deserializeTx(txData: string): Promise<SolanaTx>;
47
49
  getTxIdStatus(txId: string): Promise<"not_found" | "pending" | "success" | "reverted">;
48
50
  getTxStatus(tx: string): Promise<"not_found" | "pending" | "success" | "reverted">;
51
+ getFinalizedBlock(): Promise<{
52
+ height: number;
53
+ blockHash: string;
54
+ }>;
49
55
  offBeforeTxReplace(callback: (oldTx: string, oldTxId: string, newTx: string, newTxId: string) => Promise<void>): boolean;
50
56
  onBeforeTxReplace(callback: (oldTx: string, oldTxId: string, newTx: string, newTxId: string) => Promise<void>): void;
51
57
  onBeforeTxSigned(callback: (tx: SolanaTx) => Promise<void>): void;
@@ -55,4 +61,5 @@ export declare class SolanaChainInterface implements ChainInterface<SolanaTx, So
55
61
  isValidToken(tokenIdentifier: string): boolean;
56
62
  randomAddress(): string;
57
63
  randomSigner(): SolanaSigner;
64
+ wrapSigner(signer: Wallet): Promise<SolanaSigner>;
58
65
  }
@@ -45,6 +45,9 @@ class SolanaChainInterface {
45
45
  isValidAddress(address) {
46
46
  return SolanaAddresses_1.SolanaAddresses.isValidAddress(address);
47
47
  }
48
+ normalizeAddress(address) {
49
+ return address;
50
+ }
48
51
  getNativeCurrencyAddress() {
49
52
  return this.Tokens.getNativeCurrencyAddress().toString();
50
53
  }
@@ -73,6 +76,13 @@ class SolanaChainInterface {
73
76
  getTxStatus(tx) {
74
77
  return this.Transactions.getTxStatus(tx);
75
78
  }
79
+ async getFinalizedBlock() {
80
+ const { block } = await this.Blocks.findLatestParsedBlock("finalized");
81
+ return {
82
+ height: block.blockHeight,
83
+ blockHash: block.blockhash
84
+ };
85
+ }
76
86
  ///////////////////////////////////
77
87
  //// Callbacks & handlers
78
88
  offBeforeTxReplace(callback) {
@@ -108,5 +118,8 @@ class SolanaChainInterface {
108
118
  const wallet = new SolanaKeypairWallet_1.SolanaKeypairWallet(keypair);
109
119
  return new SolanaSigner_1.SolanaSigner(wallet, keypair);
110
120
  }
121
+ wrapSigner(signer) {
122
+ return Promise.resolve(new SolanaSigner_1.SolanaSigner(signer));
123
+ }
111
124
  }
112
125
  exports.SolanaChainInterface = SolanaChainInterface;
@@ -6,6 +6,7 @@ const SolanaModule_1 = require("../SolanaModule");
6
6
  const bs58 = require("bs58");
7
7
  const Utils_1 = require("../../../utils/Utils");
8
8
  const buffer_1 = require("buffer");
9
+ const base_1 = require("@atomiqlabs/base");
9
10
  class SolanaTransactions extends SolanaModule_1.SolanaModule {
10
11
  /**
11
12
  * Sends raw solana transaction, first through the cbkSendTransaction callback (for e.g. sending the transaction
@@ -54,7 +55,7 @@ class SolanaTransactions extends SolanaModule_1.SolanaModule {
54
55
  resolve(signature);
55
56
  }
56
57
  if (status === "reverted")
57
- reject(new Error("Transaction reverted!"));
58
+ reject(new base_1.TransactionRevertedError("Transaction reverted!"));
58
59
  clearInterval(watchdogInterval);
59
60
  }, this.retryPolicy?.transactionResendInterval || 3000);
60
61
  if (abortSignal != null)
@@ -95,7 +96,7 @@ class SolanaTransactions extends SolanaModule_1.SolanaModule {
95
96
  if (status === "success")
96
97
  return signature;
97
98
  if (status === "reverted")
98
- throw new Error("Transaction reverted!");
99
+ throw new base_1.TransactionRevertedError("Transaction reverted!");
99
100
  if (err instanceof web3_js_1.TransactionExpiredBlockheightExceededError || err.toString().startsWith("TransactionExpiredBlockheightExceededError")) {
100
101
  throw new Error("Transaction expired before confirmation, please try again!");
101
102
  }
@@ -104,7 +105,7 @@ class SolanaTransactions extends SolanaModule_1.SolanaModule {
104
105
  }
105
106
  }
106
107
  if (result.value.err != null)
107
- throw new Error("Transaction reverted!");
108
+ throw new base_1.TransactionRevertedError("Transaction reverted!");
108
109
  return signature;
109
110
  }
110
111
  /**
@@ -209,9 +210,10 @@ class SolanaTransactions extends SolanaModule_1.SolanaModule {
209
210
  };
210
211
  this.logger.debug("sendAndConfirm(): sending transactions, count: " + _txs.length +
211
212
  " waitForConfirmation: " + waitForConfirmation + " parallel: " + parallel);
213
+ const BATCH_SIZE = 50;
212
214
  const signatures = [];
213
- for (let e = 0; e < _txs.length; e += 50) {
214
- const txs = _txs.slice(e, e + 50);
215
+ for (let e = 0; e < _txs.length; e += BATCH_SIZE) {
216
+ const txs = _txs.slice(e, e + BATCH_SIZE);
215
217
  await this.prepareTransactions(signer, txs);
216
218
  const signedTxs = await signer.wallet.signAllTransactions(txs.map(e => e.tx));
217
219
  signedTxs.forEach((tx, index) => {
@@ -220,27 +222,16 @@ class SolanaTransactions extends SolanaModule_1.SolanaModule {
220
222
  solTx.tx = tx;
221
223
  });
222
224
  this.logger.debug("sendAndConfirm(): sending transaction batch (" + e + ".." + (e + 50) + "), count: " + txs.length);
223
- if (parallel) {
224
- const promises = [];
225
- for (let solTx of txs) {
226
- const signature = await this.sendSignedTransaction(solTx, options, onBeforePublish);
227
- if (waitForConfirmation)
228
- promises.push(this.confirmTransaction(solTx, abortSignal, "confirmed"));
229
- signatures.push(signature);
230
- }
231
- if (promises.length > 0)
232
- await Promise.all(promises);
233
- }
234
- else {
235
- for (let i = 0; i < txs.length; i++) {
236
- const solTx = txs[i];
237
- const signature = await this.sendSignedTransaction(solTx, options, onBeforePublish);
238
- const confirmPromise = this.confirmTransaction(solTx, abortSignal, "confirmed");
239
- //Don't await the last promise when !waitForConfirmation
240
- if (i < txs.length - 1 || e + 50 < _txs.length || waitForConfirmation)
241
- await confirmPromise;
242
- signatures.push(signature);
243
- }
225
+ //For solana we are forced to send txs one-by-one even with parallel, as we cannot determine their order upfront,
226
+ // however e.g. Jito could possibly handle sending a single package of up to 5 txns in order.
227
+ for (let i = 0; i < txs.length; i++) {
228
+ const solTx = txs[i];
229
+ const signature = await this.sendSignedTransaction(solTx, options, onBeforePublish);
230
+ const confirmPromise = this.confirmTransaction(solTx, abortSignal, "confirmed");
231
+ //Don't await the last promise when !waitForConfirmation
232
+ if (i < txs.length - 1 || e + 50 < _txs.length || waitForConfirmation)
233
+ await confirmPromise;
234
+ signatures.push(signature);
244
235
  }
245
236
  }
246
237
  this.logger.info("sendAndConfirm(): sent transactions, count: " + _txs.length +
@@ -118,6 +118,12 @@ export declare class SolanaSwapProgram extends SolanaProgramBase<SwapProgram> im
118
118
  * @param data
119
119
  */
120
120
  getCommitStatus(signer: string, data: SolanaSwapData): Promise<SwapCommitState>;
121
+ getCommitStatuses(request: {
122
+ signer: string;
123
+ swapData: SolanaSwapData;
124
+ }[]): Promise<{
125
+ [p: string]: SwapCommitState;
126
+ }>;
121
127
  /**
122
128
  * Checks the status of the specific payment hash
123
129
  *
@@ -185,18 +191,18 @@ export declare class SolanaSwapProgram extends SolanaProgramBase<SwapProgram> im
185
191
  /**
186
192
  * Get the estimated solana fee of the commit transaction
187
193
  */
188
- getCommitFee(swapData: SolanaSwapData, feeRate?: string): Promise<bigint>;
194
+ getCommitFee(signer: string, swapData: SolanaSwapData, feeRate?: string): Promise<bigint>;
189
195
  /**
190
196
  * Get the estimated solana fee of the commit transaction, without any deposits
191
197
  */
192
- getRawCommitFee(swapData: SolanaSwapData, feeRate?: string): Promise<bigint>;
198
+ getRawCommitFee(signer: string, swapData: SolanaSwapData, feeRate?: string): Promise<bigint>;
193
199
  /**
194
200
  * Get the estimated solana transaction fee of the refund transaction
195
201
  */
196
- getRefundFee(swapData: SolanaSwapData, feeRate?: string): Promise<bigint>;
202
+ getRefundFee(signer: string, swapData: SolanaSwapData, feeRate?: string): Promise<bigint>;
197
203
  /**
198
204
  * Get the estimated solana transaction fee of the refund transaction
199
205
  */
200
- getRawRefundFee(swapData: SolanaSwapData, feeRate?: string): Promise<bigint>;
206
+ getRawRefundFee(signer: string, swapData: SolanaSwapData, feeRate?: string): Promise<bigint>;
201
207
  getExtraData(outputScript: Buffer, amount: bigint, confirmations: number, nonce?: bigint): Buffer;
202
208
  }
@@ -20,6 +20,7 @@ const BN = require("bn.js");
20
20
  function toPublicKeyOrNull(str) {
21
21
  return str == null ? null : new web3_js_1.PublicKey(str);
22
22
  }
23
+ const MAX_PARALLEL_COMMIT_STATUS_CHECKS = 5;
23
24
  class SolanaSwapProgram extends SolanaProgramBase_1.SolanaProgramBase {
24
25
  constructor(chainInterface, btcRelay, storage, programAddress) {
25
26
  super(chainInterface, programIdl, programAddress);
@@ -237,6 +238,21 @@ class SolanaSwapProgram extends SolanaProgramBase_1.SolanaProgramBase {
237
238
  return { type: base_1.SwapCommitStateType.EXPIRED };
238
239
  return { type: base_1.SwapCommitStateType.NOT_COMMITED };
239
240
  }
241
+ async getCommitStatuses(request) {
242
+ const result = {};
243
+ let promises = [];
244
+ for (let { signer, swapData } of request) {
245
+ promises.push(this.getCommitStatus(signer, swapData).then(val => {
246
+ result[swapData.getEscrowHash()] = val;
247
+ }));
248
+ if (promises.length >= MAX_PARALLEL_COMMIT_STATUS_CHECKS) {
249
+ await Promise.all(promises);
250
+ promises = [];
251
+ }
252
+ }
253
+ await Promise.all(promises);
254
+ return result;
255
+ }
240
256
  /**
241
257
  * Checks the status of the specific payment hash
242
258
  *
@@ -439,25 +455,25 @@ class SolanaSwapProgram extends SolanaProgramBase_1.SolanaProgramBase {
439
455
  /**
440
456
  * Get the estimated solana fee of the commit transaction
441
457
  */
442
- getCommitFee(swapData, feeRate) {
458
+ getCommitFee(signer, swapData, feeRate) {
443
459
  return this.Init.getInitFee(swapData, feeRate);
444
460
  }
445
461
  /**
446
462
  * Get the estimated solana fee of the commit transaction, without any deposits
447
463
  */
448
- getRawCommitFee(swapData, feeRate) {
464
+ getRawCommitFee(signer, swapData, feeRate) {
449
465
  return this.Init.getRawInitFee(swapData, feeRate);
450
466
  }
451
467
  /**
452
468
  * Get the estimated solana transaction fee of the refund transaction
453
469
  */
454
- getRefundFee(swapData, feeRate) {
470
+ getRefundFee(signer, swapData, feeRate) {
455
471
  return this.Refund.getRefundFee(swapData, feeRate);
456
472
  }
457
473
  /**
458
474
  * Get the estimated solana transaction fee of the refund transaction
459
475
  */
460
- getRawRefundFee(swapData, feeRate) {
476
+ getRawRefundFee(signer, swapData, feeRate) {
461
477
  return this.Refund.getRawRefundFee(swapData, feeRate);
462
478
  }
463
479
  getExtraData(outputScript, amount, confirmations, nonce) {
@@ -2,6 +2,7 @@ import { Wallet } from "@coral-xyz/anchor/dist/cjs/provider";
2
2
  import { AbstractSigner } from "@atomiqlabs/base";
3
3
  import { PublicKey, Signer } from "@solana/web3.js";
4
4
  export declare class SolanaSigner implements AbstractSigner {
5
+ type: "AtomiqAbstractSigner";
5
6
  wallet: Wallet;
6
7
  keypair?: Signer;
7
8
  constructor(wallet: Wallet, keypair?: Signer);
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.SolanaSigner = void 0;
4
4
  class SolanaSigner {
5
5
  constructor(wallet, keypair) {
6
+ this.type = "AtomiqAbstractSigner";
6
7
  this.wallet = wallet;
7
8
  this.keypair = keypair;
8
9
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atomiqlabs/chain-solana",
3
- "version": "11.0.0",
3
+ "version": "12.0.0",
4
4
  "description": "Solana specific base implementation",
5
5
  "main": "./dist/index.js",
6
6
  "types:": "./dist/index.d.ts",
@@ -22,7 +22,7 @@
22
22
  "author": "adambor",
23
23
  "license": "ISC",
24
24
  "dependencies": {
25
- "@atomiqlabs/base": "^11.0.0",
25
+ "@atomiqlabs/base": "^12.0.0",
26
26
  "@noble/hashes": "^1.7.1",
27
27
  "bn.js": "5.2.1",
28
28
  "bs58": "4.0.1",
@@ -7,6 +7,7 @@ import {SolanaSwapData} from "./swaps/SolanaSwapData";
7
7
  import {SolanaChainEventsBrowser} from "./events/SolanaChainEventsBrowser";
8
8
  import {SolanaBtcRelay} from "./btcrelay/SolanaBtcRelay";
9
9
  import {SolanaChainInterface} from "./chain/SolanaChainInterface";
10
+ import {Wallet} from "@coral-xyz/anchor/dist/cjs/provider";
10
11
 
11
12
  export type SolanaChainType = ChainType<
12
13
  "SOLANA",
@@ -14,6 +15,7 @@ export type SolanaChainType = ChainType<
14
15
  SolanaPreFetchVerification,
15
16
  SolanaTx,
16
17
  SolanaSigner,
18
+ Wallet,
17
19
  SolanaSwapData,
18
20
  SolanaSwapProgram,
19
21
  SolanaChainInterface,
@@ -12,6 +12,7 @@ import {SolanaAddresses} from "./modules/SolanaAddresses";
12
12
  import {SolanaSigner} from "../wallet/SolanaSigner";
13
13
  import {Buffer} from "buffer";
14
14
  import {SolanaKeypairWallet} from "../wallet/SolanaKeypairWallet";
15
+ import {Wallet} from "@coral-xyz/anchor/dist/cjs/provider";
15
16
 
16
17
  export type SolanaRetryPolicy = {
17
18
  maxRetries?: number,
@@ -23,7 +24,8 @@ export type SolanaRetryPolicy = {
23
24
  export class SolanaChainInterface implements ChainInterface<
24
25
  SolanaTx,
25
26
  SolanaSigner,
26
- "SOLANA"
27
+ "SOLANA",
28
+ Wallet
27
29
  > {
28
30
  readonly chainId = "SOLANA";
29
31
 
@@ -78,6 +80,10 @@ export class SolanaChainInterface implements ChainInterface<
78
80
  return SolanaAddresses.isValidAddress(address);
79
81
  }
80
82
 
83
+ normalizeAddress(address: string): string {
84
+ return address;
85
+ }
86
+
81
87
  getNativeCurrencyAddress(): string {
82
88
  return this.Tokens.getNativeCurrencyAddress().toString();
83
89
  }
@@ -128,6 +134,14 @@ export class SolanaChainInterface implements ChainInterface<
128
134
  return this.Transactions.getTxStatus(tx);
129
135
  }
130
136
 
137
+ async getFinalizedBlock(): Promise<{ height: number; blockHash: string }> {
138
+ const {block} = await this.Blocks.findLatestParsedBlock("finalized");
139
+ return {
140
+ height: block.blockHeight,
141
+ blockHash: block.blockhash
142
+ };
143
+ }
144
+
131
145
 
132
146
  ///////////////////////////////////
133
147
  //// Callbacks & handlers
@@ -172,4 +186,8 @@ export class SolanaChainInterface implements ChainInterface<
172
186
  return new SolanaSigner(wallet, keypair);
173
187
  }
174
188
 
189
+ wrapSigner(signer: Wallet): Promise<SolanaSigner> {
190
+ return Promise.resolve(new SolanaSigner(signer));
191
+ }
192
+
175
193
  }
@@ -9,6 +9,7 @@ import * as bs58 from "bs58";
9
9
  import {tryWithRetries} from "../../../utils/Utils";
10
10
  import {Buffer} from "buffer";
11
11
  import {SolanaSigner} from "../../wallet/SolanaSigner";
12
+ import {TransactionRevertedError} from "@atomiqlabs/base";
12
13
 
13
14
  export type SolanaTx = {tx: Transaction, signers: Signer[]};
14
15
 
@@ -74,7 +75,7 @@ export class SolanaTransactions extends SolanaModule {
74
75
  this.logger.info("txConfirmationAndResendWatchdog(): transaction confirmed from HTTP polling, signature: "+signature);
75
76
  resolve(signature);
76
77
  }
77
- if(status==="reverted") reject(new Error("Transaction reverted!"));
78
+ if(status==="reverted") reject(new TransactionRevertedError("Transaction reverted!"));
78
79
  clearInterval(watchdogInterval);
79
80
  }, this.retryPolicy?.transactionResendInterval || 3000);
80
81
 
@@ -119,14 +120,14 @@ export class SolanaTransactions extends SolanaModule {
119
120
  );
120
121
  this.logger.info("txConfirmFromWebsocket(): transaction status: "+status+" signature: "+signature);
121
122
  if(status==="success") return signature;
122
- if(status==="reverted") throw new Error("Transaction reverted!");
123
+ if(status==="reverted") throw new TransactionRevertedError("Transaction reverted!");
123
124
  if(err instanceof TransactionExpiredBlockheightExceededError || err.toString().startsWith("TransactionExpiredBlockheightExceededError")) {
124
125
  throw new Error("Transaction expired before confirmation, please try again!");
125
126
  } else {
126
127
  throw err;
127
128
  }
128
129
  }
129
- if(result.value.err!=null) throw new Error("Transaction reverted!");
130
+ if(result.value.err!=null) throw new TransactionRevertedError("Transaction reverted!");
130
131
  return signature;
131
132
  }
132
133
 
@@ -239,9 +240,11 @@ export class SolanaTransactions extends SolanaModule {
239
240
  this.logger.debug("sendAndConfirm(): sending transactions, count: "+_txs.length+
240
241
  " waitForConfirmation: "+waitForConfirmation+" parallel: "+parallel);
241
242
 
243
+ const BATCH_SIZE = 50;
244
+
242
245
  const signatures: string[] = [];
243
- for(let e=0;e<_txs.length;e+=50) {
244
- const txs = _txs.slice(e, e+50);
246
+ for(let e=0;e<_txs.length;e+=BATCH_SIZE) {
247
+ const txs = _txs.slice(e, e+BATCH_SIZE);
245
248
 
246
249
  await this.prepareTransactions(signer, txs)
247
250
  const signedTxs = await signer.wallet.signAllTransactions(txs.map(e => e.tx));
@@ -252,23 +255,15 @@ export class SolanaTransactions extends SolanaModule {
252
255
  });
253
256
  this.logger.debug("sendAndConfirm(): sending transaction batch ("+e+".."+(e+50)+"), count: "+txs.length);
254
257
 
255
- if(parallel) {
256
- const promises: Promise<void>[] = [];
257
- for(let solTx of txs) {
258
- const signature = await this.sendSignedTransaction(solTx, options, onBeforePublish);
259
- if(waitForConfirmation) promises.push(this.confirmTransaction(solTx, abortSignal, "confirmed"));
260
- signatures.push(signature);
261
- }
262
- if(promises.length>0) await Promise.all(promises);
263
- } else {
264
- for(let i=0;i<txs.length;i++) {
265
- const solTx = txs[i];
266
- const signature = await this.sendSignedTransaction(solTx, options, onBeforePublish);
267
- const confirmPromise = this.confirmTransaction(solTx, abortSignal, "confirmed");
268
- //Don't await the last promise when !waitForConfirmation
269
- if(i<txs.length-1 || e+50<_txs.length || waitForConfirmation) await confirmPromise;
270
- signatures.push(signature);
271
- }
258
+ //For solana we are forced to send txs one-by-one even with parallel, as we cannot determine their order upfront,
259
+ // however e.g. Jito could possibly handle sending a single package of up to 5 txns in order.
260
+ for(let i=0;i<txs.length;i++) {
261
+ const solTx = txs[i];
262
+ const signature = await this.sendSignedTransaction(solTx, options, onBeforePublish);
263
+ const confirmPromise = this.confirmTransaction(solTx, abortSignal, "confirmed");
264
+ //Don't await the last promise when !waitForConfirmation
265
+ if(i<txs.length-1 || e+50<_txs.length || waitForConfirmation) await confirmPromise;
266
+ signatures.push(signature);
272
267
  }
273
268
  }
274
269
 
@@ -41,6 +41,8 @@ function toPublicKeyOrNull(str: string | null): PublicKey | null {
41
41
  return str==null ? null : new PublicKey(str);
42
42
  }
43
43
 
44
+ const MAX_PARALLEL_COMMIT_STATUS_CHECKS = 5;
45
+
44
46
  export class SolanaSwapProgram
45
47
  extends SolanaProgramBase<SwapProgram>
46
48
  implements SwapContract<
@@ -308,6 +310,26 @@ export class SolanaSwapProgram
308
310
  return {type: SwapCommitStateType.NOT_COMMITED};
309
311
  }
310
312
 
313
+ async getCommitStatuses(request: { signer: string; swapData: SolanaSwapData }[]): Promise<{
314
+ [p: string]: SwapCommitState
315
+ }> {
316
+ const result: {
317
+ [p: string]: SwapCommitState
318
+ } = {};
319
+ let promises: Promise<void>[] = [];
320
+ for(let {signer, swapData} of request) {
321
+ promises.push(this.getCommitStatus(signer, swapData).then(val => {
322
+ result[swapData.getEscrowHash()] = val;
323
+ }));
324
+ if(promises.length>=MAX_PARALLEL_COMMIT_STATUS_CHECKS) {
325
+ await Promise.all(promises);
326
+ promises = [];
327
+ }
328
+ }
329
+ await Promise.all(promises);
330
+ return result;
331
+ }
332
+
311
333
  /**
312
334
  * Checks the status of the specific payment hash
313
335
  *
@@ -662,28 +684,28 @@ export class SolanaSwapProgram
662
684
  /**
663
685
  * Get the estimated solana fee of the commit transaction
664
686
  */
665
- getCommitFee(swapData: SolanaSwapData, feeRate?: string): Promise<bigint> {
687
+ getCommitFee(signer: string, swapData: SolanaSwapData, feeRate?: string): Promise<bigint> {
666
688
  return this.Init.getInitFee(swapData, feeRate);
667
689
  }
668
690
 
669
691
  /**
670
692
  * Get the estimated solana fee of the commit transaction, without any deposits
671
693
  */
672
- getRawCommitFee(swapData: SolanaSwapData, feeRate?: string): Promise<bigint> {
694
+ getRawCommitFee(signer: string, swapData: SolanaSwapData, feeRate?: string): Promise<bigint> {
673
695
  return this.Init.getRawInitFee(swapData, feeRate);
674
696
  }
675
697
 
676
698
  /**
677
699
  * Get the estimated solana transaction fee of the refund transaction
678
700
  */
679
- getRefundFee(swapData: SolanaSwapData, feeRate?: string): Promise<bigint> {
701
+ getRefundFee(signer: string, swapData: SolanaSwapData, feeRate?: string): Promise<bigint> {
680
702
  return this.Refund.getRefundFee(swapData, feeRate);
681
703
  }
682
704
 
683
705
  /**
684
706
  * Get the estimated solana transaction fee of the refund transaction
685
707
  */
686
- getRawRefundFee(swapData: SolanaSwapData, feeRate?: string): Promise<bigint> {
708
+ getRawRefundFee(signer: string, swapData: SolanaSwapData, feeRate?: string): Promise<bigint> {
687
709
  return this.Refund.getRawRefundFee(swapData, feeRate);
688
710
  }
689
711
 
@@ -3,6 +3,7 @@ import {AbstractSigner} from "@atomiqlabs/base";
3
3
  import {PublicKey, Signer} from "@solana/web3.js";
4
4
 
5
5
  export class SolanaSigner implements AbstractSigner {
6
+ type = "AtomiqAbstractSigner" as const;
6
7
 
7
8
  wallet: Wallet;
8
9
  keypair?: Signer;