@atomiqlabs/sdk 8.6.0 → 8.6.2

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 (52) hide show
  1. package/dist/storage/UnifiedSwapStorage.js +13 -8
  2. package/dist/swapper/Swapper.d.ts +1 -12
  3. package/dist/swapper/Swapper.js +25 -26
  4. package/dist/swapper/SwapperFactory.d.ts +1 -0
  5. package/dist/swapper/SwapperFactory.js +9 -4
  6. package/dist/swaps/ISwap.d.ts +8 -0
  7. package/dist/swaps/ISwap.js +8 -0
  8. package/dist/swaps/ISwapWrapper.d.ts +23 -1
  9. package/dist/swaps/ISwapWrapper.js +88 -28
  10. package/dist/swaps/escrow_swaps/IEscrowSwapWrapper.js +4 -1
  11. package/dist/swaps/escrow_swaps/frombtc/IFromBTCSelfInitSwap.d.ts +2 -2
  12. package/dist/swaps/escrow_swaps/frombtc/IFromBTCSelfInitSwap.js +1 -1
  13. package/dist/swaps/escrow_swaps/frombtc/ln/FromBTCLNSwap.d.ts +2 -2
  14. package/dist/swaps/escrow_swaps/frombtc/ln/FromBTCLNSwap.js +16 -6
  15. package/dist/swaps/escrow_swaps/frombtc/ln/FromBTCLNWrapper.js +8 -2
  16. package/dist/swaps/escrow_swaps/frombtc/ln_auto/FromBTCLNAutoSwap.d.ts +1 -1
  17. package/dist/swaps/escrow_swaps/frombtc/ln_auto/FromBTCLNAutoSwap.js +14 -4
  18. package/dist/swaps/escrow_swaps/frombtc/ln_auto/FromBTCLNAutoWrapper.js +8 -6
  19. package/dist/swaps/escrow_swaps/frombtc/onchain/FromBTCSwap.d.ts +2 -1
  20. package/dist/swaps/escrow_swaps/frombtc/onchain/FromBTCSwap.js +7 -5
  21. package/dist/swaps/escrow_swaps/frombtc/onchain/FromBTCWrapper.js +8 -2
  22. package/dist/swaps/escrow_swaps/tobtc/IToBTCSwap.js +1 -1
  23. package/dist/swaps/escrow_swaps/tobtc/IToBTCWrapper.js +0 -6
  24. package/dist/swaps/escrow_swaps/tobtc/ln/ToBTCLNWrapper.js +8 -3
  25. package/dist/swaps/escrow_swaps/tobtc/onchain/ToBTCWrapper.js +8 -2
  26. package/dist/swaps/spv_swaps/SpvFromBTCSwap.d.ts +1 -0
  27. package/dist/swaps/spv_swaps/SpvFromBTCSwap.js +3 -2
  28. package/dist/swaps/spv_swaps/SpvFromBTCWrapper.js +1 -3
  29. package/dist/swaps/trusted/ln/LnForGasWrapper.js +0 -1
  30. package/dist/swaps/trusted/onchain/OnchainForGasWrapper.js +0 -1
  31. package/package.json +1 -1
  32. package/src/storage/UnifiedSwapStorage.ts +13 -8
  33. package/src/swapper/Swapper.ts +27 -27
  34. package/src/swapper/SwapperFactory.ts +12 -6
  35. package/src/swaps/ISwap.ts +8 -0
  36. package/src/swaps/ISwapWrapper.ts +104 -28
  37. package/src/swaps/escrow_swaps/IEscrowSwapWrapper.ts +5 -1
  38. package/src/swaps/escrow_swaps/frombtc/IFromBTCSelfInitSwap.ts +3 -3
  39. package/src/swaps/escrow_swaps/frombtc/ln/FromBTCLNSwap.ts +17 -8
  40. package/src/swaps/escrow_swaps/frombtc/ln/FromBTCLNWrapper.ts +8 -3
  41. package/src/swaps/escrow_swaps/frombtc/ln_auto/FromBTCLNAutoSwap.ts +13 -5
  42. package/src/swaps/escrow_swaps/frombtc/ln_auto/FromBTCLNAutoWrapper.ts +8 -7
  43. package/src/swaps/escrow_swaps/frombtc/onchain/FromBTCSwap.ts +9 -5
  44. package/src/swaps/escrow_swaps/frombtc/onchain/FromBTCWrapper.ts +7 -2
  45. package/src/swaps/escrow_swaps/tobtc/IToBTCSwap.ts +1 -1
  46. package/src/swaps/escrow_swaps/tobtc/IToBTCWrapper.ts +0 -3
  47. package/src/swaps/escrow_swaps/tobtc/ln/ToBTCLNWrapper.ts +7 -3
  48. package/src/swaps/escrow_swaps/tobtc/onchain/ToBTCWrapper.ts +7 -2
  49. package/src/swaps/spv_swaps/SpvFromBTCSwap.ts +5 -2
  50. package/src/swaps/spv_swaps/SpvFromBTCWrapper.ts +1 -3
  51. package/src/swaps/trusted/ln/LnForGasWrapper.ts +0 -1
  52. package/src/swaps/trusted/onchain/OnchainForGasWrapper.ts +0 -1
@@ -64,6 +64,7 @@ class UnifiedSwapStorage {
64
64
  const value = reviver(rawObj);
65
65
  if (value == null)
66
66
  return;
67
+ value._persisted = true;
67
68
  if (!this.noWeakRefMap)
68
69
  this.weakRefCache.set(rawObj.id, new WeakRef(value));
69
70
  result.push(value);
@@ -75,37 +76,41 @@ class UnifiedSwapStorage {
75
76
  *
76
77
  * @param value Swap to save
77
78
  */
78
- save(value) {
79
+ async save(value) {
79
80
  if (!this.noWeakRefMap)
80
81
  this.weakRefCache.set(value.getId(), new WeakRef(value));
81
- return this.storage.save(value.serialize());
82
+ await this.storage.save(value.serialize());
83
+ value._persisted = true;
82
84
  }
83
85
  /**
84
86
  * Saves multiple swaps to storage in a batch operation
85
87
  * @param values Array of swaps to save
86
88
  */
87
- saveAll(values) {
89
+ async saveAll(values) {
88
90
  if (!this.noWeakRefMap)
89
91
  values.forEach(value => this.weakRefCache.set(value.getId(), new WeakRef(value)));
90
- return this.storage.saveAll(values.map(obj => obj.serialize()));
92
+ await this.storage.saveAll(values.map(obj => obj.serialize()));
93
+ values.forEach(value => value._persisted = true);
91
94
  }
92
95
  /**
93
96
  * Removes a swap from storage
94
97
  * @param value Swap to remove
95
98
  */
96
- remove(value) {
99
+ async remove(value) {
97
100
  if (!this.noWeakRefMap)
98
101
  this.weakRefCache.delete(value.getId());
99
- return this.storage.remove(value.serialize());
102
+ await this.storage.remove(value.serialize());
103
+ value._persisted = false;
100
104
  }
101
105
  /**
102
106
  * Removes multiple swaps from storage in a batch operation
103
107
  * @param values Array of swaps to remove
104
108
  */
105
- removeAll(values) {
109
+ async removeAll(values) {
106
110
  if (!this.noWeakRefMap)
107
111
  values.forEach(value => this.weakRefCache.delete(value.getId()));
108
- return this.storage.removeAll(values.map(obj => obj.serialize()));
112
+ await this.storage.removeAll(values.map(obj => obj.serialize()));
113
+ values.forEach(value => value._persisted = false);
109
114
  }
110
115
  }
111
116
  exports.UnifiedSwapStorage = UnifiedSwapStorage;
@@ -174,17 +174,6 @@ type MultiChainData<T extends MultiChain> = {
174
174
  type CtorMultiChainData<T extends MultiChain> = {
175
175
  [chainIdentifier in keyof T]: ChainData<T[chainIdentifier]>;
176
176
  };
177
- type SwapperCtorTokens<T extends MultiChain = MultiChain> = {
178
- ticker: string;
179
- name: string;
180
- chains: {
181
- [chainId in ChainIds<T>]?: {
182
- address: string;
183
- decimals: number;
184
- displayDecimals?: number;
185
- };
186
- };
187
- }[];
188
177
  /**
189
178
  * Type extracting chain identifiers from a MultiChain type
190
179
  * @category Core
@@ -263,7 +252,7 @@ export declare class Swapper<T extends MultiChain> extends EventEmitter<{
263
252
  /**
264
253
  * @internal
265
254
  */
266
- constructor(bitcoinRpc: BitcoinRpcWithAddressIndex<any>, lightningApi: LightningNetworkApi, bitcoinSynchronizer: (btcRelay: BtcRelay<any, any, any>) => RelaySynchronizer<any, any, any>, chainsData: CtorMultiChainData<T>, pricing: ISwapPrice<T>, tokens: SwapperCtorTokens<T>, messenger: Messenger, options?: SwapperOptions);
255
+ constructor(bitcoinRpc: BitcoinRpcWithAddressIndex<any>, lightningApi: LightningNetworkApi, bitcoinSynchronizer: (btcRelay: BtcRelay<any, any, any>) => RelaySynchronizer<any, any, any>, chainsData: CtorMultiChainData<T>, pricing: ISwapPrice<T>, tokens: SCToken[], messenger: Messenger, options?: SwapperOptions);
267
256
  private _init;
268
257
  private initPromise?;
269
258
  private initialized;
@@ -82,22 +82,10 @@ class Swapper extends events_1.EventEmitter {
82
82
  this._tokens = {};
83
83
  this._tokensByTicker = {};
84
84
  for (let tokenData of tokens) {
85
- for (let chainId in tokenData.chains) {
86
- const chainData = tokenData.chains[chainId];
87
- this._tokens[chainId] ??= {};
88
- this._tokensByTicker[chainId] ??= {};
89
- this._tokens[chainId][chainData.address] = this._tokensByTicker[chainId][tokenData.ticker] = {
90
- chain: "SC",
91
- chainId,
92
- ticker: tokenData.ticker,
93
- name: tokenData.name,
94
- decimals: chainData.decimals,
95
- displayDecimals: chainData.displayDecimals,
96
- address: chainData.address,
97
- equals: (other) => other.chainId === chainId && other.ticker === tokenData.ticker && other.address === chainData.address,
98
- toString: () => `${chainId}-${tokenData.ticker}`
99
- };
100
- }
85
+ const chainId = tokenData.chainId;
86
+ this._tokens[chainId] ??= {};
87
+ this._tokensByTicker[chainId] ??= {};
88
+ this._tokens[chainId][tokenData.address] = this._tokensByTicker[chainId][tokenData.ticker] = tokenData;
101
89
  }
102
90
  this.swapStateListener = (swap) => {
103
91
  this.emit("swapState", swap);
@@ -112,35 +100,42 @@ class Swapper extends events_1.EventEmitter {
112
100
  wrappers[SwapType_1.SwapType.TO_BTCLN] = new ToBTCLNWrapper_1.ToBTCLNWrapper(key, unifiedSwapStorage, unifiedChainEvents, chainInterface, swapContract, pricing, this._tokens[chainId], chainData.swapDataConstructor, {
113
101
  getRequestTimeout: this.options.getRequestTimeout,
114
102
  postRequestTimeout: this.options.postRequestTimeout,
103
+ saveUninitializedSwaps: this.options.saveUninitializedSwaps,
115
104
  });
116
105
  wrappers[SwapType_1.SwapType.TO_BTC] = new ToBTCWrapper_1.ToBTCWrapper(key, unifiedSwapStorage, unifiedChainEvents, chainInterface, swapContract, pricing, this._tokens[chainId], chainData.swapDataConstructor, this._bitcoinRpc, {
117
106
  getRequestTimeout: this.options.getRequestTimeout,
118
107
  postRequestTimeout: this.options.postRequestTimeout,
108
+ saveUninitializedSwaps: this.options.saveUninitializedSwaps,
119
109
  bitcoinNetwork: this._btcNetwork
120
110
  });
121
111
  wrappers[SwapType_1.SwapType.FROM_BTCLN] = new FromBTCLNWrapper_1.FromBTCLNWrapper(key, unifiedSwapStorage, unifiedChainEvents, chainInterface, swapContract, pricing, this._tokens[chainId], chainData.swapDataConstructor, lightningApi, {
122
112
  getRequestTimeout: this.options.getRequestTimeout,
123
113
  postRequestTimeout: this.options.postRequestTimeout,
114
+ saveUninitializedSwaps: this.options.saveUninitializedSwaps,
124
115
  unsafeSkipLnNodeCheck: this.bitcoinNetwork === base_1.BitcoinNetwork.TESTNET4 || this.bitcoinNetwork === base_1.BitcoinNetwork.REGTEST
125
116
  });
126
117
  wrappers[SwapType_1.SwapType.FROM_BTC] = new FromBTCWrapper_1.FromBTCWrapper(key, unifiedSwapStorage, unifiedChainEvents, chainInterface, swapContract, pricing, this._tokens[chainId], chainData.swapDataConstructor, btcRelay, synchronizer, this._bitcoinRpc, {
127
118
  getRequestTimeout: this.options.getRequestTimeout,
128
119
  postRequestTimeout: this.options.postRequestTimeout,
120
+ saveUninitializedSwaps: this.options.saveUninitializedSwaps,
129
121
  bitcoinNetwork: this._btcNetwork
130
122
  });
131
123
  wrappers[SwapType_1.SwapType.TRUSTED_FROM_BTCLN] = new LnForGasWrapper_1.LnForGasWrapper(key, unifiedSwapStorage, unifiedChainEvents, chainInterface, pricing, this._tokens[chainId], {
132
124
  getRequestTimeout: this.options.getRequestTimeout,
133
- postRequestTimeout: this.options.postRequestTimeout
125
+ postRequestTimeout: this.options.postRequestTimeout,
126
+ saveUninitializedSwaps: this.options.saveUninitializedSwaps,
134
127
  });
135
128
  wrappers[SwapType_1.SwapType.TRUSTED_FROM_BTC] = new OnchainForGasWrapper_1.OnchainForGasWrapper(key, unifiedSwapStorage, unifiedChainEvents, chainInterface, pricing, this._tokens[chainId], bitcoinRpc, {
136
129
  getRequestTimeout: this.options.getRequestTimeout,
137
130
  postRequestTimeout: this.options.postRequestTimeout,
131
+ saveUninitializedSwaps: this.options.saveUninitializedSwaps,
138
132
  bitcoinNetwork: this._btcNetwork
139
133
  });
140
134
  if (spvVaultContract != null) {
141
135
  wrappers[SwapType_1.SwapType.SPV_VAULT_FROM_BTC] = new SpvFromBTCWrapper_1.SpvFromBTCWrapper(key, unifiedSwapStorage, unifiedChainEvents, chainInterface, spvVaultContract, pricing, this._tokens[chainId], spvVaultWithdrawalDataConstructor, btcRelay, synchronizer, bitcoinRpc, {
142
136
  getRequestTimeout: this.options.getRequestTimeout,
143
137
  postRequestTimeout: this.options.postRequestTimeout,
138
+ saveUninitializedSwaps: this.options.saveUninitializedSwaps,
144
139
  bitcoinNetwork: this._btcNetwork
145
140
  });
146
141
  }
@@ -148,6 +143,7 @@ class Swapper extends events_1.EventEmitter {
148
143
  wrappers[SwapType_1.SwapType.FROM_BTCLN_AUTO] = new FromBTCLNAutoWrapper_1.FromBTCLNAutoWrapper(key, unifiedSwapStorage, unifiedChainEvents, chainInterface, swapContract, pricing, this._tokens[chainId], chainData.swapDataConstructor, lightningApi, this.messenger, {
149
144
  getRequestTimeout: this.options.getRequestTimeout,
150
145
  postRequestTimeout: this.options.postRequestTimeout,
146
+ saveUninitializedSwaps: this.options.saveUninitializedSwaps,
151
147
  unsafeSkipLnNodeCheck: this.bitcoinNetwork === base_1.BitcoinNetwork.TESTNET4 || this.bitcoinNetwork === base_1.BitcoinNetwork.REGTEST
152
148
  });
153
149
  }
@@ -268,8 +264,10 @@ class Swapper extends events_1.EventEmitter {
268
264
  async init() {
269
265
  if (this.initialized)
270
266
  return;
271
- if (this.initPromise != null)
267
+ if (this.initPromise != null) {
272
268
  await this.initPromise;
269
+ return;
270
+ }
273
271
  try {
274
272
  const promise = this._init();
275
273
  this.initPromise = promise;
@@ -446,10 +444,7 @@ class Swapper extends events_1.EventEmitter {
446
444
  if (swapLimitsChanged)
447
445
  this.emit("swapLimitsChanged");
448
446
  const quote = quotes[0].quote;
449
- if (this.options.saveUninitializedSwaps) {
450
- quote._setInitiated();
451
- await quote._save();
452
- }
447
+ await quote._save();
453
448
  return quote;
454
449
  }
455
450
  catch (e) {
@@ -732,7 +727,7 @@ class Swapper extends events_1.EventEmitter {
732
727
  * @param trustedIntermediaryOrUrl URL or Intermediary object of the trusted intermediary to use, otherwise uses default
733
728
  * @throws {Error} If no trusted intermediary specified
734
729
  */
735
- createTrustedLNForGasSwap(chainIdentifier, recipient, amount, trustedIntermediaryOrUrl) {
730
+ async createTrustedLNForGasSwap(chainIdentifier, recipient, amount, trustedIntermediaryOrUrl) {
736
731
  if (this._chains[chainIdentifier] == null)
737
732
  throw new Error("Invalid chain identifier! Unknown chain: " + chainIdentifier);
738
733
  if (!this._chains[chainIdentifier].chainInterface.isValidAddress(recipient, true))
@@ -741,7 +736,9 @@ class Swapper extends events_1.EventEmitter {
741
736
  const useUrl = trustedIntermediaryOrUrl ?? this.defaultTrustedIntermediary ?? this.options.defaultTrustedIntermediaryUrl;
742
737
  if (useUrl == null)
743
738
  throw new Error("No trusted intermediary specified!");
744
- return this._chains[chainIdentifier].wrappers[SwapType_1.SwapType.TRUSTED_FROM_BTCLN].create(recipient, amount, useUrl);
739
+ const swap = await this._chains[chainIdentifier].wrappers[SwapType_1.SwapType.TRUSTED_FROM_BTCLN].create(recipient, amount, useUrl);
740
+ await swap._save();
741
+ return swap;
745
742
  }
746
743
  /**
747
744
  * Creates a trusted Bitcoin -> Smart chain ({@link SwapType.TRUSTED_FROM_BTC}) gas swap
@@ -753,7 +750,7 @@ class Swapper extends events_1.EventEmitter {
753
750
  * @param trustedIntermediaryOrUrl URL or Intermediary object of the trusted intermediary to use, otherwise uses default
754
751
  * @throws {Error} If no trusted intermediary specified
755
752
  */
756
- createTrustedOnchainForGasSwap(chainIdentifier, recipient, amount, refundAddress, trustedIntermediaryOrUrl) {
753
+ async createTrustedOnchainForGasSwap(chainIdentifier, recipient, amount, refundAddress, trustedIntermediaryOrUrl) {
757
754
  if (this._chains[chainIdentifier] == null)
758
755
  throw new Error("Invalid chain identifier! Unknown chain: " + chainIdentifier);
759
756
  if (!this._chains[chainIdentifier].chainInterface.isValidAddress(recipient, true))
@@ -762,7 +759,9 @@ class Swapper extends events_1.EventEmitter {
762
759
  const useUrl = trustedIntermediaryOrUrl ?? this.defaultTrustedIntermediary ?? this.options.defaultTrustedIntermediaryUrl;
763
760
  if (useUrl == null)
764
761
  throw new Error("No trusted intermediary specified!");
765
- return this._chains[chainIdentifier].wrappers[SwapType_1.SwapType.TRUSTED_FROM_BTC].create(recipient, amount, useUrl, refundAddress);
762
+ const swap = await this._chains[chainIdentifier].wrappers[SwapType_1.SwapType.TRUSTED_FROM_BTC].create(recipient, amount, useUrl, refundAddress);
763
+ await swap._save();
764
+ return swap;
766
765
  }
767
766
  /**
768
767
  * Creates a swap from srcToken to dstToken, of a specific token amount, either specifying input amount (exactIn=true)
@@ -113,6 +113,7 @@ export declare class SwapperFactory<T extends readonly ChainInitializer<any, Cha
113
113
  * Token resolvers for various smart chains supported by the SDK, allow fetching tokens based on their addresses
114
114
  */
115
115
  TokenResolver: TypedTokenResolvers<T>;
116
+ private smartChainTokens;
116
117
  constructor(initializers: T);
117
118
  /**
118
119
  * Returns a new swapper instance with the passed options.
@@ -64,21 +64,26 @@ class SwapperFactory {
64
64
  * Token resolvers for various smart chains supported by the SDK, allow fetching tokens based on their addresses
65
65
  */
66
66
  this.TokenResolver = {};
67
+ this.smartChainTokens = [];
67
68
  this.initializers = initializers;
68
69
  initializers.forEach(initializer => {
69
70
  const addressMap = {};
70
71
  const tokens = (this.Tokens[initializer.chainId] = {});
71
72
  for (let ticker in initializer.tokens) {
72
73
  const assetData = initializer.tokens[ticker];
73
- tokens[ticker] = addressMap[assetData.address] = {
74
+ const token = {
74
75
  chain: "SC",
75
76
  chainId: initializer.chainId,
76
- address: assetData.address,
77
+ ticker,
77
78
  name: SmartChainAssets_1.SmartChainAssets[ticker]?.name ?? ticker,
78
79
  decimals: assetData.decimals,
79
80
  displayDecimals: assetData.displayDecimals,
80
- ticker
81
+ address: assetData.address,
82
+ equals: (other) => other.chainId === initializer.chainId && other.ticker === ticker && other.address === assetData.address,
83
+ toString: () => `${initializer.chainId}-${ticker}`
81
84
  };
85
+ this.smartChainTokens.push(token);
86
+ tokens[ticker] = addressMap[assetData.address] = token;
82
87
  }
83
88
  this.TokenResolver[initializer.chainId] = {
84
89
  getToken: (address) => addressMap[address]
@@ -140,7 +145,7 @@ class SwapperFactory {
140
145
  };
141
146
  }), options.getPriceFn)) :
142
147
  RedundantSwapPrice_1.RedundantSwapPrice.createFromTokenMap(options.pricingFeeDifferencePPM ?? 10000n, pricingAssets);
143
- return new Swapper_1.Swapper(bitcoinRpc, bitcoinRpc, (btcRelay) => new btc_mempool_1.MempoolBtcRelaySynchronizer(btcRelay, bitcoinRpc), chains, swapPricing, pricingAssets, options.messenger, options);
148
+ return new Swapper_1.Swapper(bitcoinRpc, bitcoinRpc, (btcRelay) => new btc_mempool_1.MempoolBtcRelaySynchronizer(btcRelay, bitcoinRpc), chains, swapPricing, this.smartChainTokens, options.messenger, options);
144
149
  }
145
150
  /**
146
151
  * Returns a new and already initialized swapper instance with the passed options. There is no need
@@ -111,6 +111,14 @@ export declare abstract class ISwap<T extends ChainType = ChainType, D extends S
111
111
  * @internal
112
112
  */
113
113
  _randomNonce: string;
114
+ /**
115
+ * Whether the swap is saved in the persistent storage or not.
116
+ *
117
+ * @remarks This field itself is not persisted but is instead derived during runtime
118
+ *
119
+ * @internal
120
+ */
121
+ _persisted: boolean;
114
122
  /**
115
123
  * Event emitter emitting `"swapState"` event when swap's state changes
116
124
  */
@@ -49,6 +49,14 @@ class ISwap {
49
49
  * @internal
50
50
  */
51
51
  this._state = 0;
52
+ /**
53
+ * Whether the swap is saved in the persistent storage or not.
54
+ *
55
+ * @remarks This field itself is not persisted but is instead derived during runtime
56
+ *
57
+ * @internal
58
+ */
59
+ this._persisted = false;
52
60
  /**
53
61
  * Event emitter emitting `"swapState"` event when swap's state changes
54
62
  */
@@ -9,6 +9,8 @@ import { SwapType } from "../enums/SwapType";
9
9
  import { UnifiedSwapStorage } from "../storage/UnifiedSwapStorage";
10
10
  import { SCToken } from "../types/Token";
11
11
  import { PriceInfoType } from "../types/PriceInfoType";
12
+ export declare const DEFAULT_MAX_PARALLEL_SWAP_TICKS = 50;
13
+ export declare const DEFAULT_MAX_PARALLEL_SWAP_SYNCS = 50;
12
14
  /**
13
15
  * Options for swap wrapper configuration
14
16
  *
@@ -17,6 +19,18 @@ import { PriceInfoType } from "../types/PriceInfoType";
17
19
  export type ISwapWrapperOptions = {
18
20
  getRequestTimeout?: number;
19
21
  postRequestTimeout?: number;
22
+ /**
23
+ * How many swaps to call `_tick()` for in parallel
24
+ */
25
+ maxParallelSwapTicks?: number;
26
+ /**
27
+ * How many swaps to call `_sync()` for in parallel
28
+ */
29
+ maxParallelSwapSyncs?: number;
30
+ /**
31
+ * Whether to save swaps that are not initialized into the persistent storage
32
+ */
33
+ saveUninitializedSwaps?: boolean;
20
34
  };
21
35
  /**
22
36
  * Token configuration for wrapper constructors
@@ -86,6 +100,11 @@ export declare abstract class ISwapWrapper<T extends ChainType, D extends SwapTy
86
100
  * @internal
87
101
  */
88
102
  protected tickInterval?: NodeJS.Timeout;
103
+ /**
104
+ * An internal abort controller for the running tick handler
105
+ * @internal
106
+ */
107
+ protected tickAbortController?: AbortController;
89
108
  /**
90
109
  * States of the swaps in pending (non-final state), these are checked automatically on initial swap synchronization
91
110
  * @internal
@@ -215,6 +234,8 @@ export declare abstract class ISwapWrapper<T extends ChainType, D extends SwapTy
215
234
  /**
216
235
  * Runs checks on all the known pending swaps, syncing their state from on-chain data
217
236
  *
237
+ * @remarks Doesn't work properly if you pass non-persisted swaps
238
+ *
218
239
  * @param pastSwaps Optional array of past swaps to check, otherwise all relevant swaps will be fetched
219
240
  * from the persistent storage
220
241
  * @param noSave Whether to skip saving the swap changes in the persistent storage
@@ -228,8 +249,9 @@ export declare abstract class ISwapWrapper<T extends ChainType, D extends SwapTy
228
249
  *
229
250
  * @param swaps Optional array of swaps to invoke `_tick()` on, otherwise all relevant swaps will be fetched
230
251
  * from the persistent storage
252
+ * @param abortSignal Abort signal
231
253
  */
232
- tick(swaps?: D["Swap"][]): Promise<void>;
254
+ tick(swaps?: D["Swap"][], abortSignal?: AbortSignal): Promise<void>;
233
255
  /**
234
256
  * Returns the smart chain's native token used to pay for fees
235
257
  * @internal
@@ -1,11 +1,13 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.ISwapWrapper = void 0;
3
+ exports.ISwapWrapper = exports.DEFAULT_MAX_PARALLEL_SWAP_SYNCS = exports.DEFAULT_MAX_PARALLEL_SWAP_TICKS = void 0;
4
4
  const events_1 = require("events");
5
5
  const IntermediaryError_1 = require("../errors/IntermediaryError");
6
6
  const Logger_1 = require("../utils/Logger");
7
7
  const TokenUtils_1 = require("../utils/TokenUtils");
8
8
  const UserError_1 = require("../errors/UserError");
9
+ exports.DEFAULT_MAX_PARALLEL_SWAP_TICKS = 50;
10
+ exports.DEFAULT_MAX_PARALLEL_SWAP_SYNCS = 50;
9
11
  /**
10
12
  * Base abstract class for swap handler implementations
11
13
  *
@@ -29,6 +31,10 @@ class ISwapWrapper {
29
31
  * @internal
30
32
  */
31
33
  this.isInitialized = false;
34
+ if (options?.maxParallelSwapTicks != null && options.maxParallelSwapTicks < 1)
35
+ throw new Error("maxParallelSwapTicks must be at least 1!");
36
+ if (options?.maxParallelSwapSyncs != null && options.maxParallelSwapSyncs < 1)
37
+ throw new Error("maxParallelSwapSyncs must be at least 1!");
32
38
  this.unifiedStorage = unifiedStorage;
33
39
  this.unifiedChainEvents = unifiedChainEvents;
34
40
  this.chainIdentifier = chainIdentifier;
@@ -128,9 +134,25 @@ class ISwapWrapper {
128
134
  startTickInterval() {
129
135
  if (this.tickSwapState == null || this.tickSwapState.length === 0)
130
136
  return;
131
- this.tickInterval = setInterval(() => {
132
- this.tick();
133
- }, 1000);
137
+ if (this.tickAbortController != null)
138
+ this.tickAbortController.abort("New tick interval has been started!");
139
+ const abortController = this.tickAbortController = new AbortController();
140
+ let run;
141
+ run = async () => {
142
+ if (!this.isInitialized)
143
+ return;
144
+ await this.tick(undefined, abortController.signal).catch(e => {
145
+ if (abortController.signal.aborted)
146
+ return;
147
+ this.logger.warn("startTickInterval(): Tick on swaps failed, error: ", e);
148
+ });
149
+ if (abortController.signal.aborted)
150
+ return;
151
+ if (!this.isInitialized)
152
+ return;
153
+ this.tickInterval = setTimeout(run, 1000);
154
+ };
155
+ run();
134
156
  }
135
157
  /**
136
158
  * Runs checks on passed swaps, syncing their state from on-chain data
@@ -186,10 +208,10 @@ class ISwapWrapper {
186
208
  }
187
209
  if (this.processEvent != null)
188
210
  this.unifiedChainEvents.registerListener(this.TYPE, this.processEvent.bind(this), this._swapDeserializer.bind(null, this));
211
+ this.isInitialized = true;
189
212
  if (!noTimers)
190
213
  this.startTickInterval();
191
214
  // this.logger.info("init(): Swap wrapper initialized");
192
- this.isInitialized = true;
193
215
  }
194
216
  /**
195
217
  * Un-subscribes from event listeners on the smart chain, terminates the tick interval and stops this wrapper
@@ -198,12 +220,20 @@ class ISwapWrapper {
198
220
  this.isInitialized = false;
199
221
  this.unifiedChainEvents.unregisterListener(this.TYPE);
200
222
  this.logger.info("stop(): Swap wrapper stopped");
201
- if (this.tickInterval != null)
202
- clearInterval(this.tickInterval);
223
+ if (this.tickInterval != null) {
224
+ clearTimeout(this.tickInterval);
225
+ delete this.tickInterval;
226
+ }
227
+ if (this.tickAbortController != null) {
228
+ this.tickAbortController.abort("Wrapper instance stopped!");
229
+ delete this.tickAbortController;
230
+ }
203
231
  }
204
232
  /**
205
233
  * Runs checks on all the known pending swaps, syncing their state from on-chain data
206
234
  *
235
+ * @remarks Doesn't work properly if you pass non-persisted swaps
236
+ *
207
237
  * @param pastSwaps Optional array of past swaps to check, otherwise all relevant swaps will be fetched
208
238
  * from the persistent storage
209
239
  * @param noSave Whether to skip saving the swap changes in the persistent storage
@@ -211,16 +241,23 @@ class ISwapWrapper {
211
241
  async checkPastSwaps(pastSwaps, noSave) {
212
242
  if (pastSwaps == null)
213
243
  pastSwaps = await this.unifiedStorage.query([[{ key: "type", value: this.TYPE }, { key: "state", value: this._pendingSwapStates }]], (val) => new this._swapDeserializer(this, val));
214
- const { removeSwaps, changedSwaps } = await this._checkPastSwaps(pastSwaps);
215
- if (!noSave) {
216
- await this.unifiedStorage.removeAll(removeSwaps);
217
- await this.unifiedStorage.saveAll(changedSwaps);
218
- changedSwaps.forEach(swap => swap._emitEvent());
219
- removeSwaps.forEach(swap => swap._emitEvent());
244
+ const maxParallelSyncs = this._options.maxParallelSwapSyncs ?? exports.DEFAULT_MAX_PARALLEL_SWAP_SYNCS;
245
+ const totalRemoveSwaps = [];
246
+ const totalChangedSwaps = [];
247
+ for (let i = 0; i < pastSwaps.length; i += maxParallelSyncs) {
248
+ const { removeSwaps, changedSwaps } = await this._checkPastSwaps(pastSwaps.slice(i, i + maxParallelSyncs));
249
+ if (!noSave) {
250
+ await this.unifiedStorage.removeAll(removeSwaps);
251
+ await this.unifiedStorage.saveAll(changedSwaps);
252
+ changedSwaps.forEach(swap => swap._emitEvent());
253
+ removeSwaps.forEach(swap => swap._emitEvent());
254
+ }
255
+ totalRemoveSwaps.push(...removeSwaps);
256
+ totalChangedSwaps.push(...changedSwaps);
220
257
  }
221
258
  return {
222
- removeSwaps,
223
- changedSwaps
259
+ removeSwaps: totalRemoveSwaps,
260
+ changedSwaps: totalChangedSwaps
224
261
  };
225
262
  }
226
263
  /**
@@ -228,18 +265,39 @@ class ISwapWrapper {
228
265
  *
229
266
  * @param swaps Optional array of swaps to invoke `_tick()` on, otherwise all relevant swaps will be fetched
230
267
  * from the persistent storage
268
+ * @param abortSignal Abort signal
231
269
  */
232
- async tick(swaps) {
270
+ async tick(swaps, abortSignal) {
233
271
  if (swaps == null)
234
272
  swaps = await this.unifiedStorage.query([[{ key: "type", value: this.TYPE }, { key: "state", value: this.tickSwapState }]], (val) => new this._swapDeserializer(this, val));
273
+ abortSignal?.throwIfAborted();
274
+ const parallelTicks = this._options.maxParallelSwapTicks ?? exports.DEFAULT_MAX_PARALLEL_SWAP_TICKS;
275
+ let promises = [];
235
276
  for (let pendingSwap of this.pendingSwaps.values()) {
236
277
  const value = pendingSwap.deref();
237
278
  if (value != null)
238
- value._tick(true);
279
+ promises.push(value._tick(true).catch(e => {
280
+ this.logger.warn(`tick(): Error ticking swap ${value.getId()}: `, e);
281
+ }));
282
+ if (promises.length >= parallelTicks) {
283
+ await Promise.all(promises);
284
+ abortSignal?.throwIfAborted();
285
+ promises = [];
286
+ }
239
287
  }
240
- swaps.forEach(value => {
241
- value._tick(true);
242
- });
288
+ for (let value of swaps) {
289
+ promises.push(value._tick(true).catch(e => {
290
+ this.logger.warn(`tick(): Error ticking swap ${value.getId()}: `, e);
291
+ }));
292
+ if (promises.length >= parallelTicks) {
293
+ await Promise.all(promises);
294
+ abortSignal?.throwIfAborted();
295
+ promises = [];
296
+ }
297
+ }
298
+ if (promises.length > 0)
299
+ await Promise.all(promises);
300
+ abortSignal?.throwIfAborted();
243
301
  }
244
302
  /**
245
303
  * Returns the smart chain's native token used to pay for fees
@@ -256,13 +314,15 @@ class ISwapWrapper {
256
314
  * @internal
257
315
  */
258
316
  _saveSwapData(swap) {
259
- if (!swap.isInitiated()) {
260
- this.logger.debug("saveSwapData(): Swap " + swap.getId() + " not initiated, saving to pending swaps");
261
- this.pendingSwaps.set(swap.getId(), new WeakRef(swap));
262
- return Promise.resolve();
263
- }
264
- else {
265
- this.pendingSwaps.delete(swap.getId());
317
+ if (!this._options.saveUninitializedSwaps) {
318
+ if (!swap.isInitiated()) {
319
+ this.logger.debug("saveSwapData(): Swap " + swap.getId() + " not initiated, saving to pending swaps");
320
+ this.pendingSwaps.set(swap.getId(), new WeakRef(swap));
321
+ return Promise.resolve();
322
+ }
323
+ else {
324
+ this.pendingSwaps.delete(swap.getId());
325
+ }
266
326
  }
267
327
  return this.unifiedStorage.save(swap);
268
328
  }
@@ -275,7 +335,7 @@ class ISwapWrapper {
275
335
  */
276
336
  _removeSwapData(swap) {
277
337
  this.pendingSwaps.delete(swap.getId());
278
- if (!swap.isInitiated())
338
+ if (!swap._persisted)
279
339
  return Promise.resolve();
280
340
  return this.unifiedStorage.remove(swap);
281
341
  }
@@ -23,8 +23,11 @@ class IEscrowSwapWrapper extends ISwapWrapper_1.ISwapWrapper {
23
23
  * @internal
24
24
  */
25
25
  preFetchSignData(signDataPrefetch) {
26
- if (this._contract.preFetchForInitSignatureVerification == null)
26
+ if (this._contract.preFetchForInitSignatureVerification == null) {
27
+ // Catch promise rejections, should they happen
28
+ signDataPrefetch.catch(() => { });
27
29
  return Promise.resolve(undefined);
30
+ }
28
31
  return signDataPrefetch.then(obj => {
29
32
  if (obj == null)
30
33
  return undefined;
@@ -42,7 +42,7 @@ export declare abstract class IFromBTCSelfInitSwap<T extends ChainType = ChainTy
42
42
  * Returns if the swap can be committed
43
43
  * @internal
44
44
  */
45
- protected abstract canCommit(): boolean;
45
+ protected abstract canCommit(skipQuoteExpiryChecks?: boolean): boolean;
46
46
  /**
47
47
  * @inheritDoc
48
48
  * @internal
@@ -150,7 +150,7 @@ export declare abstract class IFromBTCSelfInitSwap<T extends ChainType = ChainTy
150
150
  /**
151
151
  * @inheritDoc
152
152
  */
153
- abstract txsClaim(signer?: T["Signer"]): Promise<T["TX"][]>;
153
+ abstract txsClaim(signer?: string | T["Signer"] | T["NativeSigner"]): Promise<T["TX"][]>;
154
154
  /**
155
155
  * @inheritDoc
156
156
  */
@@ -166,7 +166,7 @@ class IFromBTCSelfInitSwap extends IEscrowSelfInitSwap_1.IEscrowSelfInitSwap {
166
166
  * @throws {Error} When in invalid state to commit the swap
167
167
  */
168
168
  async txsCommit(skipChecks) {
169
- if (!this.canCommit())
169
+ if (!this.canCommit(skipChecks))
170
170
  throw new Error("Must be in CREATED state!");
171
171
  if (this._data == null || this.signatureData == null)
172
172
  throw new Error("data or signature data is null, invalid state?");
@@ -152,7 +152,7 @@ export declare class FromBTCLNSwap<T extends ChainType = ChainType> extends IFro
152
152
  * @inheritDoc
153
153
  * @internal
154
154
  */
155
- protected canCommit(): boolean;
155
+ protected canCommit(skipQuoteExpiryChecks?: boolean): boolean;
156
156
  /**
157
157
  * @inheritDoc
158
158
  */
@@ -400,7 +400,7 @@ export declare class FromBTCLNSwap<T extends ChainType = ChainType> extends IFro
400
400
  *
401
401
  * @throws {Error} If in invalid state (must be {@link FromBTCLNSwapState.CLAIM_COMMITED})
402
402
  */
403
- txsClaim(_signer?: T["Signer"] | T["NativeSigner"], secret?: string): Promise<T["TX"][]>;
403
+ txsClaim(_signer?: string | T["Signer"] | T["NativeSigner"], secret?: string): Promise<T["TX"][]>;
404
404
  /**
405
405
  * @inheritDoc
406
406
  *