@atomiqlabs/sdk 8.6.2 → 8.7.1
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/events/UnifiedSwapEventListener.js +4 -2
- package/dist/http/paramcoders/ParamDecoder.js +9 -4
- package/dist/http/paramcoders/ParamEncoder.js +6 -1
- package/dist/intermediaries/Intermediary.d.ts +21 -0
- package/dist/intermediaries/Intermediary.js +25 -1
- package/dist/intermediaries/IntermediaryDiscovery.d.ts +15 -3
- package/dist/intermediaries/IntermediaryDiscovery.js +25 -6
- package/dist/intermediaries/apis/IntermediaryAPI.d.ts +1 -0
- package/dist/swapper/Swapper.d.ts +9 -4
- package/dist/swapper/Swapper.js +94 -42
- package/dist/swapper/SwapperUtils.js +2 -1
- package/dist/swaps/ISwap.d.ts +5 -0
- package/dist/swaps/ISwap.js +4 -1
- package/dist/swaps/escrow_swaps/IEscrowSelfInitSwap.js +5 -5
- package/dist/swaps/escrow_swaps/IEscrowSwap.d.ts +4 -0
- package/dist/swaps/escrow_swaps/IEscrowSwap.js +4 -3
- package/dist/swaps/escrow_swaps/IEscrowSwapWrapper.d.ts +19 -6
- package/dist/swaps/escrow_swaps/IEscrowSwapWrapper.js +54 -21
- package/dist/swaps/escrow_swaps/frombtc/IFromBTCLNWrapper.d.ts +7 -3
- package/dist/swaps/escrow_swaps/frombtc/IFromBTCLNWrapper.js +3 -4
- package/dist/swaps/escrow_swaps/frombtc/IFromBTCSelfInitSwap.js +3 -3
- package/dist/swaps/escrow_swaps/frombtc/IFromBTCWrapper.d.ts +8 -2
- package/dist/swaps/escrow_swaps/frombtc/IFromBTCWrapper.js +12 -8
- package/dist/swaps/escrow_swaps/frombtc/ln/FromBTCLNSwap.js +18 -18
- package/dist/swaps/escrow_swaps/frombtc/ln/FromBTCLNWrapper.d.ts +12 -6
- package/dist/swaps/escrow_swaps/frombtc/ln/FromBTCLNWrapper.js +38 -24
- package/dist/swaps/escrow_swaps/frombtc/ln_auto/FromBTCLNAutoSwap.js +9 -9
- package/dist/swaps/escrow_swaps/frombtc/ln_auto/FromBTCLNAutoWrapper.d.ts +14 -7
- package/dist/swaps/escrow_swaps/frombtc/ln_auto/FromBTCLNAutoWrapper.js +54 -38
- package/dist/swaps/escrow_swaps/frombtc/onchain/FromBTCSwap.js +5 -5
- package/dist/swaps/escrow_swaps/frombtc/onchain/FromBTCWrapper.d.ts +18 -7
- package/dist/swaps/escrow_swaps/frombtc/onchain/FromBTCWrapper.js +61 -33
- package/dist/swaps/escrow_swaps/tobtc/IToBTCSwap.js +12 -12
- package/dist/swaps/escrow_swaps/tobtc/IToBTCWrapper.d.ts +8 -2
- package/dist/swaps/escrow_swaps/tobtc/IToBTCWrapper.js +13 -8
- package/dist/swaps/escrow_swaps/tobtc/ln/ToBTCLNSwap.js +1 -1
- package/dist/swaps/escrow_swaps/tobtc/ln/ToBTCLNWrapper.d.ts +13 -4
- package/dist/swaps/escrow_swaps/tobtc/ln/ToBTCLNWrapper.js +44 -28
- package/dist/swaps/escrow_swaps/tobtc/onchain/ToBTCSwap.js +2 -2
- package/dist/swaps/escrow_swaps/tobtc/onchain/ToBTCWrapper.d.ts +8 -4
- package/dist/swaps/escrow_swaps/tobtc/onchain/ToBTCWrapper.js +29 -21
- package/dist/swaps/spv_swaps/SpvFromBTCSwap.d.ts +1 -0
- package/dist/swaps/spv_swaps/SpvFromBTCSwap.js +13 -12
- package/dist/swaps/spv_swaps/SpvFromBTCWrapper.d.ts +21 -10
- package/dist/swaps/spv_swaps/SpvFromBTCWrapper.js +136 -73
- package/dist/swaps/trusted/ln/LnForGasWrapper.js +2 -1
- package/dist/swaps/trusted/onchain/OnchainForGasWrapper.js +2 -1
- package/dist/utils/RetryUtils.d.ts +2 -1
- package/dist/utils/RetryUtils.js +3 -2
- package/dist/utils/Utils.d.ts +9 -0
- package/dist/utils/Utils.js +15 -1
- package/package.json +2 -2
- package/src/events/UnifiedSwapEventListener.ts +4 -2
- package/src/http/paramcoders/ParamDecoder.ts +8 -4
- package/src/http/paramcoders/ParamEncoder.ts +5 -1
- package/src/intermediaries/Intermediary.ts +31 -1
- package/src/intermediaries/IntermediaryDiscovery.ts +33 -12
- package/src/intermediaries/apis/IntermediaryAPI.ts +2 -1
- package/src/swapper/Swapper.ts +141 -62
- package/src/swapper/SwapperUtils.ts +3 -1
- package/src/swaps/ISwap.ts +10 -2
- package/src/swaps/escrow_swaps/IEscrowSelfInitSwap.ts +5 -5
- package/src/swaps/escrow_swaps/IEscrowSwap.ts +10 -3
- package/src/swaps/escrow_swaps/IEscrowSwapWrapper.ts +64 -26
- package/src/swaps/escrow_swaps/frombtc/IFromBTCLNWrapper.ts +8 -5
- package/src/swaps/escrow_swaps/frombtc/IFromBTCSelfInitSwap.ts +3 -3
- package/src/swaps/escrow_swaps/frombtc/IFromBTCWrapper.ts +22 -12
- package/src/swaps/escrow_swaps/frombtc/ln/FromBTCLNSwap.ts +18 -18
- package/src/swaps/escrow_swaps/frombtc/ln/FromBTCLNWrapper.ts +52 -31
- package/src/swaps/escrow_swaps/frombtc/ln_auto/FromBTCLNAutoSwap.ts +9 -9
- package/src/swaps/escrow_swaps/frombtc/ln_auto/FromBTCLNAutoWrapper.ts +76 -52
- package/src/swaps/escrow_swaps/frombtc/onchain/FromBTCSwap.ts +5 -5
- package/src/swaps/escrow_swaps/frombtc/onchain/FromBTCWrapper.ts +82 -38
- package/src/swaps/escrow_swaps/tobtc/IToBTCSwap.ts +12 -12
- package/src/swaps/escrow_swaps/tobtc/IToBTCWrapper.ts +21 -9
- package/src/swaps/escrow_swaps/tobtc/ln/ToBTCLNSwap.ts +1 -1
- package/src/swaps/escrow_swaps/tobtc/ln/ToBTCLNWrapper.ts +56 -33
- package/src/swaps/escrow_swaps/tobtc/onchain/ToBTCSwap.ts +2 -2
- package/src/swaps/escrow_swaps/tobtc/onchain/ToBTCWrapper.ts +40 -22
- package/src/swaps/spv_swaps/SpvFromBTCSwap.ts +17 -13
- package/src/swaps/spv_swaps/SpvFromBTCWrapper.ts +149 -83
- package/src/swaps/trusted/ln/LnForGasWrapper.ts +2 -1
- package/src/swaps/trusted/onchain/OnchainForGasWrapper.ts +2 -1
- package/src/utils/RetryUtils.ts +11 -4
- package/src/utils/Utils.ts +14 -0
|
@@ -34,46 +34,68 @@ export abstract class IEscrowSwapWrapper<
|
|
|
34
34
|
/**
|
|
35
35
|
* @internal
|
|
36
36
|
*/
|
|
37
|
-
readonly _contract: T["Contract"]
|
|
37
|
+
readonly _contract: (version?: string) => T["Contract"] = (version?: string) => {
|
|
38
|
+
const _version = version ?? "v1";
|
|
39
|
+
const data = this._versionedContracts[_version];
|
|
40
|
+
if(data==null) throw new Error(`Invalid contract version ${_version} requested`);
|
|
41
|
+
return data.swapContract;
|
|
42
|
+
};
|
|
38
43
|
/**
|
|
39
44
|
* @internal
|
|
40
45
|
*/
|
|
41
|
-
readonly _swapDataDeserializer: new (data: any) => T["Data"]
|
|
46
|
+
readonly _swapDataDeserializer: (version?: string) => new (data: any) => T["Data"] = (version?: string) => {
|
|
47
|
+
const _version = version ?? "v1";
|
|
48
|
+
const data = this._versionedContracts[_version];
|
|
49
|
+
if(data==null) throw new Error(`Invalid contract version ${_version} requested`);
|
|
50
|
+
return data.swapDataConstructor;
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
//TODO: Properly populate in constructor
|
|
54
|
+
readonly _versionedContracts: {
|
|
55
|
+
[version: string]: {
|
|
56
|
+
swapContract: T["Contract"],
|
|
57
|
+
swapDataConstructor: new (data: any) => T["Data"]
|
|
58
|
+
}
|
|
59
|
+
} = {};
|
|
42
60
|
|
|
43
61
|
constructor(
|
|
44
62
|
chainIdentifier: string,
|
|
45
63
|
unifiedStorage: UnifiedSwapStorage<T>,
|
|
46
64
|
unifiedChainEvents: UnifiedSwapEventListener<T>,
|
|
47
65
|
chain: T["ChainInterface"],
|
|
48
|
-
contract: T["Contract"],
|
|
49
66
|
prices: ISwapPrice,
|
|
50
67
|
tokens: WrapperCtorTokens,
|
|
51
|
-
swapDataDeserializer: new (data: any) => T["Data"],
|
|
52
68
|
options: O,
|
|
69
|
+
versionedContracts: {
|
|
70
|
+
[version: string]: {
|
|
71
|
+
swapContract: T["Contract"],
|
|
72
|
+
swapDataConstructor: new (data: any) => T["Data"]
|
|
73
|
+
}
|
|
74
|
+
},
|
|
53
75
|
events?: EventEmitter<{swapState: [ISwap]}>
|
|
54
76
|
) {
|
|
55
77
|
super(chainIdentifier, unifiedStorage, unifiedChainEvents, chain, prices, tokens, options, events);
|
|
56
|
-
this.
|
|
57
|
-
this._contract = contract;
|
|
78
|
+
this._versionedContracts = versionedContracts;
|
|
58
79
|
}
|
|
59
80
|
|
|
60
81
|
/**
|
|
61
82
|
* Pre-fetches signature verification data from the server's pre-sent promise, doesn't throw, instead returns null
|
|
62
83
|
*
|
|
63
84
|
* @param signDataPrefetch Promise that resolves when we receive "signDataPrefetch" from the LP in streaming mode
|
|
85
|
+
* @param contractVersion
|
|
64
86
|
* @returns Pre-fetched signature verification data or null if failed
|
|
65
87
|
*
|
|
66
88
|
* @internal
|
|
67
89
|
*/
|
|
68
|
-
protected preFetchSignData(signDataPrefetch: Promise<any | null
|
|
69
|
-
if(this._contract.preFetchForInitSignatureVerification==null) {
|
|
90
|
+
protected preFetchSignData(signDataPrefetch: Promise<any | null>, contractVersion: string): Promise<T["PreFetchVerification"] | undefined> {
|
|
91
|
+
if(this._contract(contractVersion).preFetchForInitSignatureVerification==null) {
|
|
70
92
|
// Catch promise rejections, should they happen
|
|
71
93
|
signDataPrefetch.catch(() => {});
|
|
72
94
|
return Promise.resolve(undefined);
|
|
73
95
|
}
|
|
74
96
|
return signDataPrefetch.then(obj => {
|
|
75
97
|
if(obj==null) return undefined;
|
|
76
|
-
return this._contract.preFetchForInitSignatureVerification!(obj);
|
|
98
|
+
return this._contract(contractVersion).preFetchForInitSignatureVerification!(obj);
|
|
77
99
|
}).catch(e => {
|
|
78
100
|
this.logger.error("preFetchSignData(): Error: ", e);
|
|
79
101
|
});
|
|
@@ -87,6 +109,7 @@ export abstract class IEscrowSwapWrapper<
|
|
|
87
109
|
* @param signature Response of the intermediary
|
|
88
110
|
* @param feeRatePromise Pre-fetched fee rate promise
|
|
89
111
|
* @param preFetchSignatureVerificationData Pre-fetched signature verification data
|
|
112
|
+
* @param contractVersion
|
|
90
113
|
* @param abortSignal
|
|
91
114
|
* @returns Swap initialization signature expiry
|
|
92
115
|
* @throws {SignatureVerificationError} when swap init signature is invalid
|
|
@@ -99,11 +122,12 @@ export abstract class IEscrowSwapWrapper<
|
|
|
99
122
|
signature: SignatureData,
|
|
100
123
|
feeRatePromise: Promise<any>,
|
|
101
124
|
preFetchSignatureVerificationData: Promise<any>,
|
|
102
|
-
|
|
125
|
+
contractVersion: string,
|
|
126
|
+
abortSignal?: AbortSignal,
|
|
103
127
|
): Promise<number> {
|
|
104
128
|
const [feeRate, preFetchedSignatureData] = await Promise.all([feeRatePromise, preFetchSignatureVerificationData]);
|
|
105
|
-
await this._contract.isValidInitAuthorization(initiator, data, signature, feeRate, preFetchedSignatureData);
|
|
106
|
-
return await this._contract.getInitAuthorizationExpiry(data, signature, preFetchedSignatureData);
|
|
129
|
+
await this._contract(contractVersion).isValidInitAuthorization(initiator, data, signature, feeRate, preFetchedSignatureData);
|
|
130
|
+
return await this._contract(contractVersion).getInitAuthorizationExpiry(data, signature, preFetchedSignatureData);
|
|
107
131
|
}
|
|
108
132
|
|
|
109
133
|
/**
|
|
@@ -186,7 +210,7 @@ export abstract class IEscrowSwapWrapper<
|
|
|
186
210
|
|
|
187
211
|
const swapExpiredStatus: {[id: string]: boolean} = {};
|
|
188
212
|
|
|
189
|
-
const checkStatusSwaps: (D["Swap"] & {_data: T["Data"]})[] =
|
|
213
|
+
const checkStatusSwaps: {[contractVersion: string]: (D["Swap"] & {_data: T["Data"]})[]} = {};
|
|
190
214
|
|
|
191
215
|
for(let pastSwap of pastSwaps) {
|
|
192
216
|
if(pastSwap._shouldFetchExpiryStatus()) {
|
|
@@ -195,24 +219,37 @@ export abstract class IEscrowSwapWrapper<
|
|
|
195
219
|
}
|
|
196
220
|
if(pastSwap._shouldFetchOnchainState()) {
|
|
197
221
|
//Add to swaps for which status should be checked
|
|
198
|
-
if(pastSwap._data!=null) checkStatusSwaps.push(pastSwap as (D["Swap"] & {_data: T["Data"]}));
|
|
222
|
+
if(pastSwap._data!=null) (checkStatusSwaps[pastSwap._contractVersion ?? "v1"] ??= []).push(pastSwap as (D["Swap"] & {_data: T["Data"]}));
|
|
199
223
|
}
|
|
200
224
|
}
|
|
201
225
|
|
|
202
|
-
|
|
226
|
+
for(let version in checkStatusSwaps) {
|
|
227
|
+
if(this._versionedContracts[version]==null) {
|
|
228
|
+
this.logger.warn(`_checkPastSwaps(): No contract was found for ${this.chainIdentifier} version ${version}! Skipping these swaps!`);
|
|
229
|
+
continue;
|
|
230
|
+
}
|
|
203
231
|
|
|
204
|
-
|
|
205
|
-
const
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
232
|
+
const _checkStatusSwap = checkStatusSwaps[version];
|
|
233
|
+
const swapStatuses = await this._contract(version).getCommitStatuses(
|
|
234
|
+
_checkStatusSwap.map(val => ({
|
|
235
|
+
signer: val._getInitiator(),
|
|
236
|
+
swapData: val._data
|
|
237
|
+
}))
|
|
210
238
|
);
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
239
|
+
|
|
240
|
+
for(let pastSwap of _checkStatusSwap) {
|
|
241
|
+
const escrowHash = pastSwap.getEscrowHash();
|
|
242
|
+
const shouldSave = await pastSwap._sync(
|
|
243
|
+
false,
|
|
244
|
+
swapExpiredStatus[pastSwap.getId()],
|
|
245
|
+
escrowHash==null ? undefined : swapStatuses[escrowHash]
|
|
246
|
+
);
|
|
247
|
+
if(shouldSave) {
|
|
248
|
+
if(pastSwap.isQuoteExpired()) {
|
|
249
|
+
removeSwaps.push(pastSwap);
|
|
250
|
+
} else {
|
|
251
|
+
changedSwaps.push(pastSwap);
|
|
252
|
+
}
|
|
216
253
|
}
|
|
217
254
|
}
|
|
218
255
|
}
|
|
@@ -239,6 +276,7 @@ export abstract class IEscrowSwapWrapper<
|
|
|
239
276
|
getTxBlock: () => Promise<{blockTime: number, blockHeight: number}>
|
|
240
277
|
},
|
|
241
278
|
state: SwapCommitState,
|
|
279
|
+
contractVersion: string,
|
|
242
280
|
lp?: Intermediary
|
|
243
281
|
): Promise<D["Swap"] | null>;
|
|
244
282
|
|
|
@@ -38,10 +38,9 @@ export abstract class IFromBTCLNWrapper<
|
|
|
38
38
|
* @param unifiedStorage Storage interface for the current environment
|
|
39
39
|
* @param unifiedChainEvents On-chain event listener
|
|
40
40
|
* @param chain
|
|
41
|
-
* @param contract Underlying contract handling the swaps
|
|
42
41
|
* @param prices Swap pricing handler
|
|
43
42
|
* @param tokens
|
|
44
|
-
* @param
|
|
43
|
+
* @param versionedContracts
|
|
45
44
|
* @param lnApi
|
|
46
45
|
* @param options
|
|
47
46
|
* @param events Instance to use for emitting events
|
|
@@ -51,15 +50,19 @@ export abstract class IFromBTCLNWrapper<
|
|
|
51
50
|
unifiedStorage: UnifiedSwapStorage<T>,
|
|
52
51
|
unifiedChainEvents: UnifiedSwapEventListener<T>,
|
|
53
52
|
chain: T["ChainInterface"],
|
|
54
|
-
contract: T["Contract"],
|
|
55
53
|
prices: ISwapPrice,
|
|
56
54
|
tokens: WrapperCtorTokens,
|
|
57
|
-
|
|
55
|
+
versionedContracts: {
|
|
56
|
+
[version: string]: {
|
|
57
|
+
swapContract: T["Contract"],
|
|
58
|
+
swapDataConstructor: new (data: any) => T["Data"]
|
|
59
|
+
}
|
|
60
|
+
},
|
|
58
61
|
lnApi: LightningNetworkApi,
|
|
59
62
|
options: O,
|
|
60
63
|
events?: EventEmitter<{swapState: [IEscrowSwap]}>
|
|
61
64
|
) {
|
|
62
|
-
super(chainIdentifier, unifiedStorage, unifiedChainEvents, chain,
|
|
65
|
+
super(chainIdentifier, unifiedStorage, unifiedChainEvents, chain, prices, tokens, options, versionedContracts, events);
|
|
63
66
|
this.lnApi = lnApi;
|
|
64
67
|
}
|
|
65
68
|
|
|
@@ -196,7 +196,7 @@ export abstract class IFromBTCSelfInitSwap<
|
|
|
196
196
|
required: TokenAmount<SCToken<T["ChainId"]>, true>
|
|
197
197
|
}> {
|
|
198
198
|
const [balance, commitFee] = await Promise.all([
|
|
199
|
-
this.
|
|
199
|
+
this._contract.getBalance(this._getInitiator(), this.wrapper._chain.getNativeCurrencyAddress(), false),
|
|
200
200
|
this.getCommitFee()
|
|
201
201
|
]);
|
|
202
202
|
const totalFee = commitFee + this.getSwapData().getTotalDeposit();
|
|
@@ -247,7 +247,7 @@ export abstract class IFromBTCSelfInitSwap<
|
|
|
247
247
|
await this._saveAndEmit();
|
|
248
248
|
}
|
|
249
249
|
|
|
250
|
-
return await this.
|
|
250
|
+
return await this._contract.txsInit(
|
|
251
251
|
this._getInitiator(), this._data, this.signatureData, skipChecks, this.feeRate
|
|
252
252
|
).catch(e => Promise.reject(e instanceof SignatureVerificationError ? new Error("Request timed out") : e));
|
|
253
253
|
}
|
|
@@ -274,7 +274,7 @@ export abstract class IFromBTCSelfInitSwap<
|
|
|
274
274
|
* smart chain
|
|
275
275
|
*/
|
|
276
276
|
async getClaimNetworkFee(): Promise<TokenAmount<SCToken<T["ChainId"]>, true>> {
|
|
277
|
-
const swapContract: T["Contract"] = this.
|
|
277
|
+
const swapContract: T["Contract"] = this._contract;
|
|
278
278
|
return toTokenAmount(
|
|
279
279
|
await swapContract.getClaimFee(this._getInitiator(), this.getSwapData()),
|
|
280
280
|
this.wrapper._getNativeToken(),
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {ISwapWrapperOptions} from "../../ISwapWrapper";
|
|
2
2
|
import {Intermediary} from "../../../intermediaries/Intermediary";
|
|
3
3
|
import {IntermediaryError} from "../../../errors/IntermediaryError";
|
|
4
|
-
import {randomBytes} from "../../../utils/Utils";
|
|
4
|
+
import {mapArrayToObject, randomBytes} from "../../../utils/Utils";
|
|
5
5
|
import {BigIntBufferUtils, ChainType} from "@atomiqlabs/base";
|
|
6
6
|
import {IEscrowSwapDefinition, IEscrowSwapWrapper} from "../IEscrowSwapWrapper";
|
|
7
7
|
import {IEscrowSwap} from "../IEscrowSwap";
|
|
@@ -39,6 +39,7 @@ export abstract class IFromBTCWrapper<
|
|
|
39
39
|
* @param claimHash optional claim hash of the swap or null
|
|
40
40
|
* @param abortController
|
|
41
41
|
*
|
|
42
|
+
* @param contractVersions
|
|
42
43
|
* @returns Fee rate
|
|
43
44
|
*
|
|
44
45
|
* @internal
|
|
@@ -46,15 +47,18 @@ export abstract class IFromBTCWrapper<
|
|
|
46
47
|
protected preFetchFeeRate(
|
|
47
48
|
signer: string,
|
|
48
49
|
amountData: AmountData,
|
|
49
|
-
claimHash: string | undefined,
|
|
50
|
-
abortController: AbortController
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
50
|
+
claimHash: {[contractVersion: string]: string} | undefined,
|
|
51
|
+
abortController: AbortController,
|
|
52
|
+
contractVersions: string[]
|
|
53
|
+
): {[contractVersion: string]: Promise<string | undefined>} {
|
|
54
|
+
return mapArrayToObject(contractVersions, (contractVersion) => {
|
|
55
|
+
return this._contract(contractVersion).getInitFeeRate(this._chain.randomAddress(), signer, amountData.token, claimHash?.[contractVersion])
|
|
56
|
+
.catch(e => {
|
|
57
|
+
this.logger.warn("preFetchFeeRate(): Error: ", e);
|
|
58
|
+
abortController.abort(e);
|
|
59
|
+
return undefined;
|
|
60
|
+
});
|
|
61
|
+
});
|
|
58
62
|
}
|
|
59
63
|
|
|
60
64
|
/**
|
|
@@ -64,12 +68,18 @@ export abstract class IFromBTCWrapper<
|
|
|
64
68
|
* @param lp Intermediary
|
|
65
69
|
* @param abortController
|
|
66
70
|
*
|
|
71
|
+
* @param contractVersion
|
|
67
72
|
* @returns Intermediary's liquidity balance
|
|
68
73
|
*
|
|
69
74
|
* @internal
|
|
70
75
|
*/
|
|
71
|
-
protected preFetchIntermediaryLiquidity(
|
|
72
|
-
|
|
76
|
+
protected preFetchIntermediaryLiquidity(
|
|
77
|
+
amountData: AmountData,
|
|
78
|
+
lp: Intermediary,
|
|
79
|
+
abortController: AbortController,
|
|
80
|
+
contractVersion: string
|
|
81
|
+
): Promise<bigint | undefined> {
|
|
82
|
+
return lp.getLiquidity(this.chainIdentifier, this._contract(contractVersion), amountData.token.toString(), abortController.signal).catch(e => {
|
|
73
83
|
this.logger.warn("preFetchIntermediaryLiquidity(): Error: ", e);
|
|
74
84
|
abortController.abort(e);
|
|
75
85
|
return undefined;
|
|
@@ -474,16 +474,16 @@ export class FromBTCLNSwap<T extends ChainType = ChainType>
|
|
|
474
474
|
required: TokenAmount<SCToken<T["ChainId"]>, true>
|
|
475
475
|
}> {
|
|
476
476
|
const [balance, feeRate] = await Promise.all([
|
|
477
|
-
this.
|
|
478
|
-
this.feeRate!=null ? Promise.resolve<string>(this.feeRate) : this.
|
|
477
|
+
this._contract.getBalance(this._getInitiator(), this.wrapper._chain.getNativeCurrencyAddress(), false),
|
|
478
|
+
this.feeRate!=null ? Promise.resolve<string>(this.feeRate) : this._contract.getInitFeeRate(
|
|
479
479
|
this.getSwapData().getOfferer(),
|
|
480
480
|
this.getSwapData().getClaimer(),
|
|
481
481
|
this.getSwapData().getToken(),
|
|
482
482
|
this.getSwapData().getClaimHash()
|
|
483
483
|
)
|
|
484
484
|
]);
|
|
485
|
-
const commitFee = await this.
|
|
486
|
-
const claimFee = await this.
|
|
485
|
+
const commitFee = await this._contract.getCommitFee(this._getInitiator(), this.getSwapData(), feeRate);
|
|
486
|
+
const claimFee = await this._contract.getClaimFee(this._getInitiator(), this.getSwapData(), feeRate);
|
|
487
487
|
const totalFee = commitFee + claimFee + this.getSwapData().getTotalDeposit();
|
|
488
488
|
return {
|
|
489
489
|
enoughBalance: balance >= totalFee,
|
|
@@ -494,7 +494,7 @@ export class FromBTCLNSwap<T extends ChainType = ChainType>
|
|
|
494
494
|
|
|
495
495
|
private isValidSecretPreimage(secret: string) {
|
|
496
496
|
const paymentHash = Buffer.from(sha256(Buffer.from(secret, "hex")));
|
|
497
|
-
const claimHash = this.
|
|
497
|
+
const claimHash = this._contract.getHashForHtlc(paymentHash).toString("hex");
|
|
498
498
|
return this.getSwapData().getClaimHash()===claimHash;
|
|
499
499
|
}
|
|
500
500
|
|
|
@@ -716,10 +716,10 @@ export class FromBTCLNSwap<T extends ChainType = ChainType>
|
|
|
716
716
|
const resp = await IntermediaryAPI.getPaymentAuthorization(this.url, paymentHash.toString("hex"));
|
|
717
717
|
switch(resp.code) {
|
|
718
718
|
case PaymentAuthorizationResponseCodes.AUTH_DATA:
|
|
719
|
-
const data = new this.wrapper._swapDataDeserializer(resp.data.data);
|
|
719
|
+
const data = new (this.wrapper._swapDataDeserializer(this._contractVersion))(resp.data.data);
|
|
720
720
|
try {
|
|
721
721
|
await this.checkIntermediaryReturnedAuthData(this._getInitiator(), data, resp.data);
|
|
722
|
-
this.expiry = await this.
|
|
722
|
+
this.expiry = await this._contract.getInitAuthorizationExpiry(
|
|
723
723
|
data,
|
|
724
724
|
resp.data
|
|
725
725
|
);
|
|
@@ -773,8 +773,8 @@ export class FromBTCLNSwap<T extends ChainType = ChainType>
|
|
|
773
773
|
if (data.hasSuccessAction()) throw new IntermediaryError("Invalid has success action");
|
|
774
774
|
|
|
775
775
|
await Promise.all([
|
|
776
|
-
this.
|
|
777
|
-
this.
|
|
776
|
+
this._contract.isValidInitAuthorization(this._getInitiator(), data, signature, this.feeRate),
|
|
777
|
+
this._contract.getCommitStatus(data.getClaimer(), data)
|
|
778
778
|
.then(status => {
|
|
779
779
|
if (status?.type !== SwapCommitStateType.NOT_COMMITED)
|
|
780
780
|
throw new Error("Swap already committed on-chain!");
|
|
@@ -846,9 +846,9 @@ export class FromBTCLNSwap<T extends ChainType = ChainType>
|
|
|
846
846
|
|
|
847
847
|
if(resp.code===PaymentAuthorizationResponseCodes.AUTH_DATA) {
|
|
848
848
|
const sigData = resp.data;
|
|
849
|
-
const swapData = new this.wrapper._swapDataDeserializer(resp.data.data);
|
|
849
|
+
const swapData = new (this.wrapper._swapDataDeserializer(this._contractVersion))(resp.data.data);
|
|
850
850
|
await this.checkIntermediaryReturnedAuthData(this._getInitiator(), swapData, sigData);
|
|
851
|
-
this.expiry = await this.
|
|
851
|
+
this.expiry = await this._contract.getInitAuthorizationExpiry(
|
|
852
852
|
swapData,
|
|
853
853
|
sigData
|
|
854
854
|
);
|
|
@@ -972,7 +972,7 @@ export class FromBTCLNSwap<T extends ChainType = ChainType>
|
|
|
972
972
|
if(!this.isValidSecretPreimage(useSecret))
|
|
973
973
|
throw new Error("Invalid swap secret pre-image provided!");
|
|
974
974
|
|
|
975
|
-
return this.
|
|
975
|
+
return this._contract.txsClaimWithSecret(
|
|
976
976
|
address ?? this._getInitiator(),
|
|
977
977
|
this._data, useSecret, true, true
|
|
978
978
|
);
|
|
@@ -1092,7 +1092,7 @@ export class FromBTCLNSwap<T extends ChainType = ChainType>
|
|
|
1092
1092
|
* to settle the swap on the smart chain destination side.
|
|
1093
1093
|
*/
|
|
1094
1094
|
async getCommitAndClaimNetworkFee(): Promise<TokenAmount<SCToken<T["ChainId"]>, true>> {
|
|
1095
|
-
const swapContract: T["Contract"] = this.
|
|
1095
|
+
const swapContract: T["Contract"] = this._contract;
|
|
1096
1096
|
const feeRate = this.feeRate ?? await swapContract.getInitFeeRate(
|
|
1097
1097
|
this.getSwapData().getOfferer(),
|
|
1098
1098
|
this.getSwapData().getClaimer(),
|
|
@@ -1123,7 +1123,7 @@ export class FromBTCLNSwap<T extends ChainType = ChainType>
|
|
|
1123
1123
|
* call {@link commit} first and then {@link claim}.
|
|
1124
1124
|
*/
|
|
1125
1125
|
canCommitAndClaimInOneShot(): boolean {
|
|
1126
|
-
return this.
|
|
1126
|
+
return this._contract.initAndClaimWithSecret!=null;
|
|
1127
1127
|
}
|
|
1128
1128
|
|
|
1129
1129
|
/**
|
|
@@ -1154,7 +1154,7 @@ export class FromBTCLNSwap<T extends ChainType = ChainType>
|
|
|
1154
1154
|
throw new Error("Invalid swap secret pre-image provided!");
|
|
1155
1155
|
|
|
1156
1156
|
const initTxs = await this.txsCommit(skipChecks);
|
|
1157
|
-
const claimTxs = await this.
|
|
1157
|
+
const claimTxs = await this._contract.txsClaimWithSecret(
|
|
1158
1158
|
this._getInitiator(), this._data, useSecret,
|
|
1159
1159
|
true, true, undefined,
|
|
1160
1160
|
true
|
|
@@ -1311,7 +1311,7 @@ export class FromBTCLNSwap<T extends ChainType = ChainType>
|
|
|
1311
1311
|
}
|
|
1312
1312
|
|
|
1313
1313
|
//Check if it's already successfully paid
|
|
1314
|
-
commitStatus ??= await this.
|
|
1314
|
+
commitStatus ??= await this._contract.getCommitStatus(this._getInitiator(), this._data!);
|
|
1315
1315
|
if(commitStatus!=null && await this._forciblySetOnchainState(commitStatus)) return true;
|
|
1316
1316
|
|
|
1317
1317
|
//Set the state on expiry here
|
|
@@ -1382,7 +1382,7 @@ export class FromBTCLNSwap<T extends ChainType = ChainType>
|
|
|
1382
1382
|
if(await this.syncStateFromChain(quoteDefinitelyExpired, commitStatus)) changed = true;
|
|
1383
1383
|
|
|
1384
1384
|
if(this._state===FromBTCLNSwapState.CLAIM_COMMITED) {
|
|
1385
|
-
const expired = await this.
|
|
1385
|
+
const expired = await this._contract.isExpired(this._getInitiator(), this._data!);
|
|
1386
1386
|
if(expired) {
|
|
1387
1387
|
this._state = FromBTCLNSwapState.EXPIRED;
|
|
1388
1388
|
changed = true;
|
|
@@ -1447,7 +1447,7 @@ export class FromBTCLNSwap<T extends ChainType = ChainType>
|
|
|
1447
1447
|
}
|
|
1448
1448
|
break;
|
|
1449
1449
|
case FromBTCLNSwapState.CLAIM_COMMITED:
|
|
1450
|
-
const expired = await this.
|
|
1450
|
+
const expired = await this._contract.isExpired(this._getInitiator(), this._data!);
|
|
1451
1451
|
if(expired) {
|
|
1452
1452
|
this._state = FromBTCLNSwapState.EXPIRED;
|
|
1453
1453
|
if(save) await this._saveAndEmit();
|
|
@@ -13,7 +13,7 @@ import {UserError} from "../../../../errors/UserError";
|
|
|
13
13
|
import {IntermediaryError} from "../../../../errors/IntermediaryError";
|
|
14
14
|
import {SwapType} from "../../../../enums/SwapType";
|
|
15
15
|
import {
|
|
16
|
-
extendAbortController, parseHashValueExact32Bytes,
|
|
16
|
+
extendAbortController, mapArrayToObject, parseHashValueExact32Bytes,
|
|
17
17
|
throwIfUndefined
|
|
18
18
|
} from "../../../../utils/Utils";
|
|
19
19
|
import {FromBTCLNResponseType, IntermediaryAPI} from "../../../../intermediaries/apis/IntermediaryAPI";
|
|
@@ -113,10 +113,9 @@ export class FromBTCLNWrapper<
|
|
|
113
113
|
* @param unifiedStorage Storage interface for the current environment
|
|
114
114
|
* @param unifiedChainEvents On-chain event listener
|
|
115
115
|
* @param chain
|
|
116
|
-
* @param contract Underlying contract handling the swaps
|
|
117
116
|
* @param prices Swap pricing handler
|
|
118
117
|
* @param tokens
|
|
119
|
-
* @param
|
|
118
|
+
* @param versionedContracts
|
|
120
119
|
* @param lnApi
|
|
121
120
|
* @param options
|
|
122
121
|
* @param events Instance to use for emitting events
|
|
@@ -126,16 +125,20 @@ export class FromBTCLNWrapper<
|
|
|
126
125
|
unifiedStorage: UnifiedSwapStorage<T>,
|
|
127
126
|
unifiedChainEvents: UnifiedSwapEventListener<T>,
|
|
128
127
|
chain: T["ChainInterface"],
|
|
129
|
-
contract: T["Contract"],
|
|
130
128
|
prices: ISwapPrice,
|
|
131
129
|
tokens: WrapperCtorTokens,
|
|
132
|
-
|
|
130
|
+
versionedContracts: {
|
|
131
|
+
[version: string]: {
|
|
132
|
+
swapContract: T["Contract"],
|
|
133
|
+
swapDataConstructor: new (data: any) => T["Data"]
|
|
134
|
+
}
|
|
135
|
+
},
|
|
133
136
|
lnApi: LightningNetworkApi,
|
|
134
137
|
options?: AllOptional<FromBTCLNWrapperOptions>,
|
|
135
138
|
events?: EventEmitter<{swapState: [ISwap]}>
|
|
136
139
|
) {
|
|
137
140
|
super(
|
|
138
|
-
chainIdentifier, unifiedStorage, unifiedChainEvents, chain,
|
|
141
|
+
chainIdentifier, unifiedStorage, unifiedChainEvents, chain, prices, tokens, versionedContracts, lnApi,
|
|
139
142
|
{
|
|
140
143
|
...options,
|
|
141
144
|
safetyFactor: options?.safetyFactor ?? 2,
|
|
@@ -254,8 +257,8 @@ export class FromBTCLNWrapper<
|
|
|
254
257
|
abortSignal?: AbortSignal,
|
|
255
258
|
preFetches?: {
|
|
256
259
|
usdPricePrefetchPromise: Promise<number | undefined>,
|
|
257
|
-
pricePrefetchPromise
|
|
258
|
-
feeRatePromise
|
|
260
|
+
pricePrefetchPromise: Promise<bigint | undefined>,
|
|
261
|
+
feeRatePromise: {[contractVersion: string]: Promise<string | undefined>},
|
|
259
262
|
}
|
|
260
263
|
): {
|
|
261
264
|
quote: Promise<FromBTCLNSwap<T>>,
|
|
@@ -273,6 +276,8 @@ export class FromBTCLNWrapper<
|
|
|
273
276
|
if(_options.description!=null && Buffer.byteLength(_options.description, "utf8") > 500)
|
|
274
277
|
throw new UserError("Invalid description length");
|
|
275
278
|
|
|
279
|
+
const lpVersions = Intermediary.getContractVersionsForLps(this.chainIdentifier, lps);
|
|
280
|
+
|
|
276
281
|
let secret: Buffer | undefined;
|
|
277
282
|
let paymentHash: Buffer;
|
|
278
283
|
if(_options.paymentHash!=null) {
|
|
@@ -280,15 +285,17 @@ export class FromBTCLNWrapper<
|
|
|
280
285
|
} else {
|
|
281
286
|
({secret, paymentHash} = this.getSecretAndHash());
|
|
282
287
|
}
|
|
283
|
-
const
|
|
288
|
+
const _hash = mapArrayToObject(lpVersions, (contractVersion: string) => {
|
|
289
|
+
return this._contract(contractVersion).getHashForHtlc(paymentHash).toString("hex");
|
|
290
|
+
});
|
|
284
291
|
|
|
285
292
|
const nativeTokenAddress = this._chain.getNativeCurrencyAddress();
|
|
286
293
|
|
|
287
294
|
const _abortController = extendAbortController(abortSignal);
|
|
288
|
-
const _preFetches = {
|
|
289
|
-
pricePrefetchPromise:
|
|
290
|
-
feeRatePromise:
|
|
291
|
-
usdPricePrefetchPromise:
|
|
295
|
+
const _preFetches = preFetches ?? {
|
|
296
|
+
pricePrefetchPromise: this.preFetchPrice(amountData, _abortController.signal),
|
|
297
|
+
feeRatePromise: this.preFetchFeeRate(recipient, amountData, _hash, _abortController, lpVersions),
|
|
298
|
+
usdPricePrefetchPromise: this.preFetchUsdPrice(_abortController.signal),
|
|
292
299
|
}
|
|
293
300
|
|
|
294
301
|
return lps.map(lp => {
|
|
@@ -296,10 +303,11 @@ export class FromBTCLNWrapper<
|
|
|
296
303
|
intermediary: lp,
|
|
297
304
|
quote: (async () => {
|
|
298
305
|
if(lp.services[SwapType.FROM_BTCLN]==null) throw new Error("LP service for processing from btcln swaps not found!");
|
|
306
|
+
const version = lp.getContractVersion(this.chainIdentifier);
|
|
299
307
|
|
|
300
308
|
const abortController = extendAbortController(_abortController.signal);
|
|
301
309
|
|
|
302
|
-
const liquidityPromise: Promise<bigint | undefined> = this.preFetchIntermediaryLiquidity(amountData, lp, abortController);
|
|
310
|
+
const liquidityPromise: Promise<bigint | undefined> = this.preFetchIntermediaryLiquidity(amountData, lp, abortController, version);
|
|
303
311
|
|
|
304
312
|
const {lnCapacityPromise, resp} = await tryWithRetries(async(retryCount: number) => {
|
|
305
313
|
const {lnPublicKey, response} = IntermediaryAPI.initFromBTCLN(
|
|
@@ -312,7 +320,7 @@ export class FromBTCLNWrapper<
|
|
|
312
320
|
description: _options.description,
|
|
313
321
|
descriptionHash: _options.descriptionHash,
|
|
314
322
|
exactOut: !amountData.exactIn,
|
|
315
|
-
feeRate: throwIfUndefined(_preFetches.feeRatePromise),
|
|
323
|
+
feeRate: throwIfUndefined(_preFetches.feeRatePromise[version]),
|
|
316
324
|
additionalParams
|
|
317
325
|
},
|
|
318
326
|
this._options.postRequestTimeout, abortController.signal, retryCount>0 ? false : undefined
|
|
@@ -351,16 +359,17 @@ export class FromBTCLNWrapper<
|
|
|
351
359
|
expiry: decodedPr.timeExpireDate*1000,
|
|
352
360
|
swapFee: resp.swapFee,
|
|
353
361
|
swapFeeBtc: resp.swapFee * amountIn / (resp.total - resp.swapFee),
|
|
354
|
-
feeRate: (await _preFetches.feeRatePromise)!,
|
|
355
|
-
initialSwapData: await this._contract.createSwapData(
|
|
362
|
+
feeRate: (await _preFetches.feeRatePromise[version])!,
|
|
363
|
+
initialSwapData: await this._contract(version).createSwapData(
|
|
356
364
|
ChainSwapType.HTLC, lp.getAddress(this.chainIdentifier), recipient, amountData.token,
|
|
357
|
-
resp.total,
|
|
365
|
+
resp.total, _hash[version],
|
|
358
366
|
this.getRandomSequence(), BigInt(Math.floor(Date.now()/1000)), false, true,
|
|
359
367
|
resp.securityDeposit, 0n, nativeTokenAddress
|
|
360
368
|
),
|
|
361
369
|
pr: resp.pr,
|
|
362
370
|
secret: secret?.toString("hex"),
|
|
363
|
-
exactIn: amountData.exactIn ?? true
|
|
371
|
+
exactIn: amountData.exactIn ?? true,
|
|
372
|
+
contractVersion: version
|
|
364
373
|
} as FromBTCLNSwapInit<T["Data"]>);
|
|
365
374
|
return quote;
|
|
366
375
|
} catch (e) {
|
|
@@ -408,11 +417,13 @@ export class FromBTCLNWrapper<
|
|
|
408
417
|
unsafeSkipLnNodeCheck: options?.unsafeSkipLnNodeCheck ?? this._options.unsafeSkipLnNodeCheck
|
|
409
418
|
};
|
|
410
419
|
|
|
420
|
+
const lpVersions = Intermediary.getContractVersionsForLps(this.chainIdentifier, lps);
|
|
421
|
+
|
|
411
422
|
const abortController = extendAbortController(abortSignal);
|
|
412
423
|
const preFetches = {
|
|
413
424
|
pricePrefetchPromise: this.preFetchPrice(amountData, abortController.signal),
|
|
414
425
|
usdPricePrefetchPromise: this.preFetchUsdPrice(abortController.signal),
|
|
415
|
-
feeRatePromise: this.preFetchFeeRate(recipient, amountData, undefined, abortController)
|
|
426
|
+
feeRatePromise: this.preFetchFeeRate(recipient, amountData, undefined, abortController, lpVersions)
|
|
416
427
|
};
|
|
417
428
|
|
|
418
429
|
try {
|
|
@@ -474,7 +485,7 @@ export class FromBTCLNWrapper<
|
|
|
474
485
|
const changedSwapSet: Set<FromBTCLNSwap<T>> = new Set();
|
|
475
486
|
|
|
476
487
|
const swapExpiredStatus: {[id: string]: boolean} = {};
|
|
477
|
-
const checkStatusSwaps: (FromBTCLNSwap<T> & {_data: T["Data"]})[] =
|
|
488
|
+
const checkStatusSwaps: {[contractVersion: string]: (FromBTCLNSwap<T> & {_data: T["Data"]})[]} = {};
|
|
478
489
|
|
|
479
490
|
await Promise.all(pastSwaps.map(async (pastSwap) => {
|
|
480
491
|
if(pastSwap._shouldCheckIntermediary()) {
|
|
@@ -493,19 +504,27 @@ export class FromBTCLNWrapper<
|
|
|
493
504
|
}
|
|
494
505
|
if(pastSwap._shouldFetchOnchainState()) {
|
|
495
506
|
//Add to swaps for which status should be checked
|
|
496
|
-
if(pastSwap._data!=null) checkStatusSwaps.push(pastSwap as (FromBTCLNSwap<T> & {_data: T["Data"]}));
|
|
507
|
+
if(pastSwap._data!=null) (checkStatusSwaps[pastSwap._contractVersion ?? "v1"] ??= []).push(pastSwap as (FromBTCLNSwap<T> & {_data: T["Data"]}));
|
|
497
508
|
}
|
|
498
509
|
}));
|
|
499
510
|
|
|
500
|
-
|
|
511
|
+
for(let version in checkStatusSwaps) {
|
|
512
|
+
if(this._versionedContracts[version]==null) {
|
|
513
|
+
this.logger.warn(`_checkPastSwaps(): No contract was found for ${this.chainIdentifier} version ${version}! Skipping these swaps!`);
|
|
514
|
+
continue;
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
const _checkStatusSwap = checkStatusSwaps[version];
|
|
518
|
+
const swapStatuses = await this._contract(version).getCommitStatuses(_checkStatusSwap.map(val => ({signer: val._getInitiator(), swapData: val._data})));
|
|
501
519
|
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
520
|
+
for(let pastSwap of _checkStatusSwap) {
|
|
521
|
+
const shouldSave = await pastSwap._sync(
|
|
522
|
+
false, swapExpiredStatus[pastSwap.getId()],
|
|
523
|
+
swapStatuses[pastSwap.getEscrowHash()!], true
|
|
524
|
+
);
|
|
525
|
+
if(shouldSave) {
|
|
526
|
+
changedSwapSet.add(pastSwap);
|
|
527
|
+
}
|
|
509
528
|
}
|
|
510
529
|
}
|
|
511
530
|
|
|
@@ -532,6 +551,7 @@ export class FromBTCLNWrapper<
|
|
|
532
551
|
async recoverFromSwapDataAndState(
|
|
533
552
|
init: {data: T["Data"], getInitTxId: () => Promise<string>, getTxBlock: () => Promise<{blockTime: number, blockHeight: number}>},
|
|
534
553
|
state: SwapCommitState,
|
|
554
|
+
contractVersion: string,
|
|
535
555
|
lp?: Intermediary
|
|
536
556
|
): Promise<FromBTCLNSwap<T> | null> {
|
|
537
557
|
const data = init.data;
|
|
@@ -562,7 +582,8 @@ export class FromBTCLNWrapper<
|
|
|
562
582
|
data,
|
|
563
583
|
pr: paymentHash ?? undefined,
|
|
564
584
|
secret,
|
|
565
|
-
exactIn: false
|
|
585
|
+
exactIn: false,
|
|
586
|
+
contractVersion
|
|
566
587
|
}
|
|
567
588
|
const swap = new FromBTCLNSwap(this, swapInit);
|
|
568
589
|
swap._commitTxId = await init.getInitTxId();
|