@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.
- package/dist/storage/UnifiedSwapStorage.js +13 -8
- package/dist/swapper/Swapper.d.ts +10 -15
- package/dist/swapper/Swapper.js +26 -26
- package/dist/swapper/SwapperFactory.d.ts +1 -0
- package/dist/swapper/SwapperFactory.js +9 -4
- package/dist/swaps/ISwap.d.ts +8 -0
- package/dist/swaps/ISwap.js +10 -2
- package/dist/swaps/ISwapWrapper.d.ts +23 -1
- package/dist/swaps/ISwapWrapper.js +88 -28
- package/dist/swaps/escrow_swaps/IEscrowSwapWrapper.js +4 -1
- package/dist/swaps/escrow_swaps/frombtc/IFromBTCSelfInitSwap.d.ts +2 -2
- package/dist/swaps/escrow_swaps/frombtc/IFromBTCSelfInitSwap.js +1 -1
- package/dist/swaps/escrow_swaps/frombtc/ln/FromBTCLNSwap.d.ts +2 -2
- package/dist/swaps/escrow_swaps/frombtc/ln/FromBTCLNSwap.js +16 -6
- package/dist/swaps/escrow_swaps/frombtc/ln/FromBTCLNWrapper.js +8 -2
- package/dist/swaps/escrow_swaps/frombtc/ln_auto/FromBTCLNAutoSwap.d.ts +1 -1
- package/dist/swaps/escrow_swaps/frombtc/ln_auto/FromBTCLNAutoSwap.js +14 -4
- package/dist/swaps/escrow_swaps/frombtc/ln_auto/FromBTCLNAutoWrapper.js +12 -9
- package/dist/swaps/escrow_swaps/frombtc/onchain/FromBTCSwap.d.ts +2 -1
- package/dist/swaps/escrow_swaps/frombtc/onchain/FromBTCSwap.js +7 -5
- package/dist/swaps/escrow_swaps/frombtc/onchain/FromBTCWrapper.js +8 -2
- package/dist/swaps/escrow_swaps/tobtc/IToBTCSwap.js +1 -1
- package/dist/swaps/escrow_swaps/tobtc/IToBTCWrapper.js +0 -6
- package/dist/swaps/escrow_swaps/tobtc/ln/ToBTCLNWrapper.js +8 -3
- package/dist/swaps/escrow_swaps/tobtc/onchain/ToBTCWrapper.js +8 -2
- package/dist/swaps/spv_swaps/SpvFromBTCSwap.d.ts +3 -0
- package/dist/swaps/spv_swaps/SpvFromBTCSwap.js +14 -4
- package/dist/swaps/spv_swaps/SpvFromBTCWrapper.js +1 -3
- package/dist/swaps/trusted/ln/LnForGasWrapper.js +0 -1
- package/dist/swaps/trusted/onchain/OnchainForGasWrapper.js +0 -1
- package/package.json +1 -1
- package/src/storage/UnifiedSwapStorage.ts +13 -8
- package/src/swapper/Swapper.ts +37 -30
- package/src/swapper/SwapperFactory.ts +12 -6
- package/src/swaps/ISwap.ts +11 -3
- package/src/swaps/ISwapWrapper.ts +104 -28
- package/src/swaps/escrow_swaps/IEscrowSwapWrapper.ts +5 -1
- package/src/swaps/escrow_swaps/frombtc/IFromBTCSelfInitSwap.ts +3 -3
- package/src/swaps/escrow_swaps/frombtc/ln/FromBTCLNSwap.ts +17 -8
- package/src/swaps/escrow_swaps/frombtc/ln/FromBTCLNWrapper.ts +8 -3
- package/src/swaps/escrow_swaps/frombtc/ln_auto/FromBTCLNAutoSwap.ts +13 -5
- package/src/swaps/escrow_swaps/frombtc/ln_auto/FromBTCLNAutoWrapper.ts +9 -8
- package/src/swaps/escrow_swaps/frombtc/onchain/FromBTCSwap.ts +9 -5
- package/src/swaps/escrow_swaps/frombtc/onchain/FromBTCWrapper.ts +7 -2
- package/src/swaps/escrow_swaps/tobtc/IToBTCSwap.ts +1 -1
- package/src/swaps/escrow_swaps/tobtc/IToBTCWrapper.ts +0 -3
- package/src/swaps/escrow_swaps/tobtc/ln/ToBTCLNWrapper.ts +7 -3
- package/src/swaps/escrow_swaps/tobtc/onchain/ToBTCWrapper.ts +7 -2
- package/src/swaps/spv_swaps/SpvFromBTCSwap.ts +19 -4
- package/src/swaps/spv_swaps/SpvFromBTCWrapper.ts +1 -3
- package/src/swaps/trusted/ln/LnForGasWrapper.ts +0 -1
- 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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
*
|
|
127
|
-
*
|
|
128
|
-
*
|
|
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:
|
|
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;
|
package/dist/swapper/Swapper.js
CHANGED
|
@@ -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
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
74
|
+
const token = {
|
|
74
75
|
chain: "SC",
|
|
75
76
|
chainId: initializer.chainId,
|
|
76
|
-
|
|
77
|
+
ticker,
|
|
77
78
|
name: SmartChainAssets_1.SmartChainAssets[ticker]?.name ?? ticker,
|
|
78
79
|
decimals: assetData.decimals,
|
|
79
80
|
displayDecimals: assetData.displayDecimals,
|
|
80
|
-
|
|
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,
|
|
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
|
package/dist/swaps/ISwap.d.ts
CHANGED
|
@@ -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
|
*/
|
package/dist/swaps/ISwap.js
CHANGED
|
@@ -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 = (
|
|
113
|
-
if (type === "eq" ?
|
|
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.
|
|
132
|
-
this.tick
|
|
133
|
-
|
|
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
|
-
|
|
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
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
changedSwaps.
|
|
219
|
-
|
|
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
|
-
|
|
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 (!
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
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.
|
|
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?");
|