@atomiqlabs/sdk 8.5.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 +10 -15
  3. package/dist/swapper/Swapper.js +26 -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 +10 -2
  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 +12 -9
  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 +3 -0
  27. package/dist/swaps/spv_swaps/SpvFromBTCSwap.js +14 -4
  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 +37 -30
  34. package/src/swapper/SwapperFactory.ts +12 -6
  35. package/src/swaps/ISwap.ts +11 -3
  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 +9 -8
  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 +19 -4
  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;
@@ -123,9 +123,15 @@ export type SwapperOptions = {
123
123
  */
124
124
  dontFetchLPs?: boolean;
125
125
  /**
126
- * By setting this flag the SDK persists all created swaps. By default, the SDK only saves and persists swaps that
127
- * are considered initiated, i.e. when `commit()`, `execute()` or `waitTillPayment` is called (or their respective
128
- * txs... prefixed variations).
126
+ * Defaults to `true`, this means every swap regardless of it being initiated (i.e. when `commit()`, `execute()` or
127
+ * `waitTillPayment` is called) is saved to the persistent storage. This is a reasonable default for when you
128
+ * want to only create a swap, and then later on retrieve it with the `swapper.getSwapById()` function.
129
+ *
130
+ * Setting this to `false` means the SDK only saves and persists swaps that are considered initiated, i.e. when
131
+ * `commit()`, `execute()` or `waitTillPayment` is called (or their respective txs... prefixed variations). This
132
+ * might save calls to the persistent storage for swaps that are never initiated. This is useful in e.g.
133
+ * frontend implementations where the frontend holds the swap object reference until it is initiated anyway, not
134
+ * necessitating the saving of the swap data to the persistent storage until it is actually initiated.
129
135
  */
130
136
  saveUninitializedSwaps?: boolean;
131
137
  /**
@@ -168,17 +174,6 @@ type MultiChainData<T extends MultiChain> = {
168
174
  type CtorMultiChainData<T extends MultiChain> = {
169
175
  [chainIdentifier in keyof T]: ChainData<T[chainIdentifier]>;
170
176
  };
171
- type SwapperCtorTokens<T extends MultiChain = MultiChain> = {
172
- ticker: string;
173
- name: string;
174
- chains: {
175
- [chainId in ChainIds<T>]?: {
176
- address: string;
177
- decimals: number;
178
- displayDecimals?: number;
179
- };
180
- };
181
- }[];
182
177
  /**
183
178
  * Type extracting chain identifiers from a MultiChain type
184
179
  * @category Core
@@ -257,7 +252,7 @@ export declare class Swapper<T extends MultiChain> extends EventEmitter<{
257
252
  /**
258
253
  * @internal
259
254
  */
260
- 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);
261
256
  private _init;
262
257
  private initPromise?;
263
258
  private initialized;
@@ -63,6 +63,7 @@ class Swapper extends events_1.EventEmitter {
63
63
  this.SwapTypeInfo = SwapUtils_1.SwapProtocolInfo;
64
64
  const storagePrefix = options?.storagePrefix ?? "atomiq-";
65
65
  options ??= {};
66
+ options.saveUninitializedSwaps ??= true;
66
67
  options.bitcoinNetwork = options.bitcoinNetwork == null ? base_1.BitcoinNetwork.TESTNET : options.bitcoinNetwork;
67
68
  const swapStorage = options.swapStorage ??= (name) => new IndexedDBUnifiedStorage_1.IndexedDBUnifiedStorage(name);
68
69
  this.options = options;
@@ -81,22 +82,10 @@ class Swapper extends events_1.EventEmitter {
81
82
  this._tokens = {};
82
83
  this._tokensByTicker = {};
83
84
  for (let tokenData of tokens) {
84
- for (let chainId in tokenData.chains) {
85
- const chainData = tokenData.chains[chainId];
86
- this._tokens[chainId] ??= {};
87
- this._tokensByTicker[chainId] ??= {};
88
- this._tokens[chainId][chainData.address] = this._tokensByTicker[chainId][tokenData.ticker] = {
89
- chain: "SC",
90
- chainId,
91
- ticker: tokenData.ticker,
92
- name: tokenData.name,
93
- decimals: chainData.decimals,
94
- displayDecimals: chainData.displayDecimals,
95
- address: chainData.address,
96
- equals: (other) => other.chainId === chainId && other.ticker === tokenData.ticker && other.address === chainData.address,
97
- toString: () => `${chainId}-${tokenData.ticker}`
98
- };
99
- }
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;
100
89
  }
101
90
  this.swapStateListener = (swap) => {
102
91
  this.emit("swapState", swap);
@@ -111,35 +100,42 @@ class Swapper extends events_1.EventEmitter {
111
100
  wrappers[SwapType_1.SwapType.TO_BTCLN] = new ToBTCLNWrapper_1.ToBTCLNWrapper(key, unifiedSwapStorage, unifiedChainEvents, chainInterface, swapContract, pricing, this._tokens[chainId], chainData.swapDataConstructor, {
112
101
  getRequestTimeout: this.options.getRequestTimeout,
113
102
  postRequestTimeout: this.options.postRequestTimeout,
103
+ saveUninitializedSwaps: this.options.saveUninitializedSwaps,
114
104
  });
115
105
  wrappers[SwapType_1.SwapType.TO_BTC] = new ToBTCWrapper_1.ToBTCWrapper(key, unifiedSwapStorage, unifiedChainEvents, chainInterface, swapContract, pricing, this._tokens[chainId], chainData.swapDataConstructor, this._bitcoinRpc, {
116
106
  getRequestTimeout: this.options.getRequestTimeout,
117
107
  postRequestTimeout: this.options.postRequestTimeout,
108
+ saveUninitializedSwaps: this.options.saveUninitializedSwaps,
118
109
  bitcoinNetwork: this._btcNetwork
119
110
  });
120
111
  wrappers[SwapType_1.SwapType.FROM_BTCLN] = new FromBTCLNWrapper_1.FromBTCLNWrapper(key, unifiedSwapStorage, unifiedChainEvents, chainInterface, swapContract, pricing, this._tokens[chainId], chainData.swapDataConstructor, lightningApi, {
121
112
  getRequestTimeout: this.options.getRequestTimeout,
122
113
  postRequestTimeout: this.options.postRequestTimeout,
114
+ saveUninitializedSwaps: this.options.saveUninitializedSwaps,
123
115
  unsafeSkipLnNodeCheck: this.bitcoinNetwork === base_1.BitcoinNetwork.TESTNET4 || this.bitcoinNetwork === base_1.BitcoinNetwork.REGTEST
124
116
  });
125
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, {
126
118
  getRequestTimeout: this.options.getRequestTimeout,
127
119
  postRequestTimeout: this.options.postRequestTimeout,
120
+ saveUninitializedSwaps: this.options.saveUninitializedSwaps,
128
121
  bitcoinNetwork: this._btcNetwork
129
122
  });
130
123
  wrappers[SwapType_1.SwapType.TRUSTED_FROM_BTCLN] = new LnForGasWrapper_1.LnForGasWrapper(key, unifiedSwapStorage, unifiedChainEvents, chainInterface, pricing, this._tokens[chainId], {
131
124
  getRequestTimeout: this.options.getRequestTimeout,
132
- postRequestTimeout: this.options.postRequestTimeout
125
+ postRequestTimeout: this.options.postRequestTimeout,
126
+ saveUninitializedSwaps: this.options.saveUninitializedSwaps,
133
127
  });
134
128
  wrappers[SwapType_1.SwapType.TRUSTED_FROM_BTC] = new OnchainForGasWrapper_1.OnchainForGasWrapper(key, unifiedSwapStorage, unifiedChainEvents, chainInterface, pricing, this._tokens[chainId], bitcoinRpc, {
135
129
  getRequestTimeout: this.options.getRequestTimeout,
136
130
  postRequestTimeout: this.options.postRequestTimeout,
131
+ saveUninitializedSwaps: this.options.saveUninitializedSwaps,
137
132
  bitcoinNetwork: this._btcNetwork
138
133
  });
139
134
  if (spvVaultContract != null) {
140
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, {
141
136
  getRequestTimeout: this.options.getRequestTimeout,
142
137
  postRequestTimeout: this.options.postRequestTimeout,
138
+ saveUninitializedSwaps: this.options.saveUninitializedSwaps,
143
139
  bitcoinNetwork: this._btcNetwork
144
140
  });
145
141
  }
@@ -147,6 +143,7 @@ class Swapper extends events_1.EventEmitter {
147
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, {
148
144
  getRequestTimeout: this.options.getRequestTimeout,
149
145
  postRequestTimeout: this.options.postRequestTimeout,
146
+ saveUninitializedSwaps: this.options.saveUninitializedSwaps,
150
147
  unsafeSkipLnNodeCheck: this.bitcoinNetwork === base_1.BitcoinNetwork.TESTNET4 || this.bitcoinNetwork === base_1.BitcoinNetwork.REGTEST
151
148
  });
152
149
  }
@@ -267,8 +264,10 @@ class Swapper extends events_1.EventEmitter {
267
264
  async init() {
268
265
  if (this.initialized)
269
266
  return;
270
- if (this.initPromise != null)
267
+ if (this.initPromise != null) {
271
268
  await this.initPromise;
269
+ return;
270
+ }
272
271
  try {
273
272
  const promise = this._init();
274
273
  this.initPromise = promise;
@@ -445,10 +444,7 @@ class Swapper extends events_1.EventEmitter {
445
444
  if (swapLimitsChanged)
446
445
  this.emit("swapLimitsChanged");
447
446
  const quote = quotes[0].quote;
448
- if (this.options.saveUninitializedSwaps) {
449
- quote._setInitiated();
450
- await quote._save();
451
- }
447
+ await quote._save();
452
448
  return quote;
453
449
  }
454
450
  catch (e) {
@@ -731,7 +727,7 @@ class Swapper extends events_1.EventEmitter {
731
727
  * @param trustedIntermediaryOrUrl URL or Intermediary object of the trusted intermediary to use, otherwise uses default
732
728
  * @throws {Error} If no trusted intermediary specified
733
729
  */
734
- createTrustedLNForGasSwap(chainIdentifier, recipient, amount, trustedIntermediaryOrUrl) {
730
+ async createTrustedLNForGasSwap(chainIdentifier, recipient, amount, trustedIntermediaryOrUrl) {
735
731
  if (this._chains[chainIdentifier] == null)
736
732
  throw new Error("Invalid chain identifier! Unknown chain: " + chainIdentifier);
737
733
  if (!this._chains[chainIdentifier].chainInterface.isValidAddress(recipient, true))
@@ -740,7 +736,9 @@ class Swapper extends events_1.EventEmitter {
740
736
  const useUrl = trustedIntermediaryOrUrl ?? this.defaultTrustedIntermediary ?? this.options.defaultTrustedIntermediaryUrl;
741
737
  if (useUrl == null)
742
738
  throw new Error("No trusted intermediary specified!");
743
- 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;
744
742
  }
745
743
  /**
746
744
  * Creates a trusted Bitcoin -> Smart chain ({@link SwapType.TRUSTED_FROM_BTC}) gas swap
@@ -752,7 +750,7 @@ class Swapper extends events_1.EventEmitter {
752
750
  * @param trustedIntermediaryOrUrl URL or Intermediary object of the trusted intermediary to use, otherwise uses default
753
751
  * @throws {Error} If no trusted intermediary specified
754
752
  */
755
- createTrustedOnchainForGasSwap(chainIdentifier, recipient, amount, refundAddress, trustedIntermediaryOrUrl) {
753
+ async createTrustedOnchainForGasSwap(chainIdentifier, recipient, amount, refundAddress, trustedIntermediaryOrUrl) {
756
754
  if (this._chains[chainIdentifier] == null)
757
755
  throw new Error("Invalid chain identifier! Unknown chain: " + chainIdentifier);
758
756
  if (!this._chains[chainIdentifier].chainInterface.isValidAddress(recipient, true))
@@ -761,7 +759,9 @@ class Swapper extends events_1.EventEmitter {
761
759
  const useUrl = trustedIntermediaryOrUrl ?? this.defaultTrustedIntermediary ?? this.options.defaultTrustedIntermediaryUrl;
762
760
  if (useUrl == null)
763
761
  throw new Error("No trusted intermediary specified!");
764
- 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;
765
765
  }
766
766
  /**
767
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
  */
@@ -109,8 +117,8 @@ class ISwap {
109
117
  // swap exists, it will just never resolve!
110
118
  return new Promise((resolve, reject) => {
111
119
  let listener;
112
- listener = (swap) => {
113
- if (type === "eq" ? swap._state === targetState : type === "gte" ? swap._state >= targetState : swap._state != targetState) {
120
+ listener = () => {
121
+ if (type === "eq" ? this._state === targetState : type === "gte" ? this._state >= targetState : this._state != targetState) {
114
122
  resolve();
115
123
  this.events.removeListener("swapState", listener);
116
124
  }
@@ -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?");