@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
|
@@ -21,7 +21,7 @@ import {UnifiedSwapEventListener} from "../../events/UnifiedSwapEventListener";
|
|
|
21
21
|
import {ISwapPrice} from "../../prices/abstract/ISwapPrice";
|
|
22
22
|
import {EventEmitter} from "events";
|
|
23
23
|
import {Intermediary} from "../../intermediaries/Intermediary";
|
|
24
|
-
import {extendAbortController, randomBytes, throwIfUndefined} from "../../utils/Utils";
|
|
24
|
+
import {extendAbortController, mapArrayToObject, randomBytes, throwIfUndefined} from "../../utils/Utils";
|
|
25
25
|
import {fromOutputScript, toCoinselectAddressType, toOutputScript} from "../../utils/BitcoinUtils";
|
|
26
26
|
import {IntermediaryAPI, SpvFromBTCPrepareResponseType} from "../../intermediaries/apis/IntermediaryAPI";
|
|
27
27
|
import {RequestError} from "../../errors/RequestError";
|
|
@@ -111,7 +111,12 @@ export class SpvFromBTCWrapper<
|
|
|
111
111
|
/**
|
|
112
112
|
* @internal
|
|
113
113
|
*/
|
|
114
|
-
protected readonly btcRelay: T["
|
|
114
|
+
protected readonly btcRelay: (version?: string) => BtcRelay<any, T["TX"], any> = (version?: string) => {
|
|
115
|
+
const _version = version ?? "v1";
|
|
116
|
+
const data = this.versionedContracts[_version];
|
|
117
|
+
if(data==null) throw new Error(`Invalid contract version ${_version} requested`);
|
|
118
|
+
return data.btcRelay;
|
|
119
|
+
};
|
|
115
120
|
/**
|
|
116
121
|
* @internal
|
|
117
122
|
*/
|
|
@@ -127,11 +132,21 @@ export class SpvFromBTCWrapper<
|
|
|
127
132
|
/**
|
|
128
133
|
* @internal
|
|
129
134
|
*/
|
|
130
|
-
readonly _synchronizer: RelaySynchronizer<any, T["TX"], any
|
|
135
|
+
readonly _synchronizer: (version?: string) => RelaySynchronizer<any, T["TX"], any> = (version?: string) => {
|
|
136
|
+
const _version = version ?? "v1";
|
|
137
|
+
const data = this.versionedSynchronizer[_version];
|
|
138
|
+
if(data==null) throw new Error(`Invalid contract version ${_version} requested`);
|
|
139
|
+
return data.synchronizer;
|
|
140
|
+
};
|
|
131
141
|
/**
|
|
132
142
|
* @internal
|
|
133
143
|
*/
|
|
134
|
-
readonly _contract: T["SpvVaultContract"]
|
|
144
|
+
readonly _contract: (version?: string) => T["SpvVaultContract"] = (version?: string) => {
|
|
145
|
+
const _version = version ?? "v1";
|
|
146
|
+
const data = this.versionedContracts[_version];
|
|
147
|
+
if(data==null) throw new Error(`Invalid contract version ${_version} requested`);
|
|
148
|
+
return data.spvVaultContract;
|
|
149
|
+
};
|
|
135
150
|
/**
|
|
136
151
|
* @internal
|
|
137
152
|
*/
|
|
@@ -139,7 +154,13 @@ export class SpvFromBTCWrapper<
|
|
|
139
154
|
/**
|
|
140
155
|
* @internal
|
|
141
156
|
*/
|
|
142
|
-
readonly _spvWithdrawalDataDeserializer: new (data: any) => T["SpvVaultWithdrawalData"]
|
|
157
|
+
readonly _spvWithdrawalDataDeserializer: (version?: string) => (new (data: any) => T["SpvVaultWithdrawalData"]) = (version?: string) => {
|
|
158
|
+
const _version = version ?? "v1";
|
|
159
|
+
const data = this.versionedContracts[_version];
|
|
160
|
+
if(data==null) throw new Error(`Invalid contract version ${_version} requested`);
|
|
161
|
+
return data.spvVaultWithdrawalDataConstructor;
|
|
162
|
+
};
|
|
163
|
+
|
|
143
164
|
/**
|
|
144
165
|
* @internal
|
|
145
166
|
*/
|
|
@@ -153,17 +174,29 @@ export class SpvFromBTCWrapper<
|
|
|
153
174
|
SpvFromBTCSwapState.BTC_TX_CONFIRMED
|
|
154
175
|
];
|
|
155
176
|
|
|
177
|
+
private readonly versionedContracts: {
|
|
178
|
+
[version: string]: {
|
|
179
|
+
btcRelay: BtcRelay<any, T["TX"], any>,
|
|
180
|
+
spvVaultContract: T["SpvVaultContract"],
|
|
181
|
+
spvVaultWithdrawalDataConstructor: new (data: any) => T["SpvVaultWithdrawalData"]
|
|
182
|
+
}
|
|
183
|
+
} = {};
|
|
184
|
+
|
|
185
|
+
private readonly versionedSynchronizer: {
|
|
186
|
+
[version: string]: {
|
|
187
|
+
synchronizer: RelaySynchronizer<any, T["TX"], any>
|
|
188
|
+
}
|
|
189
|
+
} = {};
|
|
190
|
+
|
|
156
191
|
/**
|
|
157
192
|
* @param chainIdentifier
|
|
158
193
|
* @param unifiedStorage Storage interface for the current environment
|
|
159
194
|
* @param unifiedChainEvents On-chain event listener
|
|
160
195
|
* @param chain
|
|
161
|
-
* @param contract Underlying contract handling the swaps
|
|
162
196
|
* @param prices Pricing to use
|
|
163
197
|
* @param tokens
|
|
164
|
-
* @param
|
|
165
|
-
* @param
|
|
166
|
-
* @param synchronizer Btc relay synchronizer
|
|
198
|
+
* @param versionedContracts
|
|
199
|
+
* @param versionedSynchronizer
|
|
167
200
|
* @param btcRpc Bitcoin RPC which also supports getting transactions by txoHash
|
|
168
201
|
* @param options
|
|
169
202
|
* @param events Instance to use for emitting events
|
|
@@ -173,12 +206,20 @@ export class SpvFromBTCWrapper<
|
|
|
173
206
|
unifiedStorage: UnifiedSwapStorage<T>,
|
|
174
207
|
unifiedChainEvents: UnifiedSwapEventListener<T>,
|
|
175
208
|
chain: T["ChainInterface"],
|
|
176
|
-
contract: T["SpvVaultContract"],
|
|
177
209
|
prices: ISwapPrice,
|
|
178
210
|
tokens: WrapperCtorTokens,
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
211
|
+
versionedContracts: {
|
|
212
|
+
[version: string]: {
|
|
213
|
+
btcRelay: BtcRelay<any, T["TX"], any>,
|
|
214
|
+
spvVaultContract: T["SpvVaultContract"],
|
|
215
|
+
spvVaultWithdrawalDataConstructor: new (data: any) => T["SpvVaultWithdrawalData"]
|
|
216
|
+
}
|
|
217
|
+
},
|
|
218
|
+
versionedSynchronizer: {
|
|
219
|
+
[version: string]: {
|
|
220
|
+
synchronizer: RelaySynchronizer<any, T["TX"], any>
|
|
221
|
+
}
|
|
222
|
+
},
|
|
182
223
|
btcRpc: BitcoinRpcWithAddressIndex<any>,
|
|
183
224
|
options?: AllOptional<SpvFromBTCWrapperOptions>,
|
|
184
225
|
events?: EventEmitter<{swapState: [ISwap]}>
|
|
@@ -197,10 +238,8 @@ export class SpvFromBTCWrapper<
|
|
|
197
238
|
},
|
|
198
239
|
events
|
|
199
240
|
);
|
|
200
|
-
this.
|
|
201
|
-
this.
|
|
202
|
-
this.btcRelay = btcRelay;
|
|
203
|
-
this._synchronizer = synchronizer;
|
|
241
|
+
this.versionedContracts = versionedContracts;
|
|
242
|
+
this.versionedSynchronizer = versionedSynchronizer;
|
|
204
243
|
this._btcRpc = btcRpc;
|
|
205
244
|
}
|
|
206
245
|
|
|
@@ -304,6 +343,7 @@ export class SpvFromBTCWrapper<
|
|
|
304
343
|
* @param pricePrefetch
|
|
305
344
|
* @param nativeTokenPricePrefetch
|
|
306
345
|
* @param abortController
|
|
346
|
+
* @param contractVersion
|
|
307
347
|
* @private
|
|
308
348
|
*/
|
|
309
349
|
private async preFetchCallerFeeShare(
|
|
@@ -314,7 +354,8 @@ export class SpvFromBTCWrapper<
|
|
|
314
354
|
},
|
|
315
355
|
pricePrefetch: Promise<bigint | undefined>,
|
|
316
356
|
nativeTokenPricePrefetch: Promise<bigint | undefined> | undefined,
|
|
317
|
-
abortController: AbortController
|
|
357
|
+
abortController: AbortController,
|
|
358
|
+
contractVersion: string
|
|
318
359
|
): Promise<bigint | undefined> {
|
|
319
360
|
if(options.unsafeZeroWatchtowerFee) return 0n;
|
|
320
361
|
if(amountData.amount===0n) return 0n;
|
|
@@ -327,10 +368,10 @@ export class SpvFromBTCWrapper<
|
|
|
327
368
|
claimFeeRate,
|
|
328
369
|
nativeTokenPrice
|
|
329
370
|
] = await Promise.all([
|
|
330
|
-
this.btcRelay.getFeePerBlock(),
|
|
331
|
-
this.btcRelay.getTipData(),
|
|
371
|
+
this.btcRelay(contractVersion).getFeePerBlock(),
|
|
372
|
+
this.btcRelay(contractVersion).getTipData(),
|
|
332
373
|
this._btcRpc.getTipHeight(),
|
|
333
|
-
this._contract.getClaimFee(this._chain.randomAddress()),
|
|
374
|
+
this._contract(contractVersion).getClaimFee(this._chain.randomAddress()),
|
|
334
375
|
nativeTokenPricePrefetch ?? (amountData.token===this._chain.getNativeCurrencyAddress() ?
|
|
335
376
|
pricePrefetch :
|
|
336
377
|
this._prices.preFetchPrice(this.chainIdentifier, this._chain.getNativeCurrencyAddress(), abortController.signal))
|
|
@@ -405,6 +446,8 @@ export class SpvFromBTCWrapper<
|
|
|
405
446
|
abortSignal.throwIfAborted();
|
|
406
447
|
if(btcFeeRate!=null && resp.btcFeeRate > btcFeeRate) throw new IntermediaryError(`Required bitcoin fee rate returned from the LP is too high! Maximum accepted: ${btcFeeRate} sats/vB, required by LP: ${resp.btcFeeRate} sats/vB`);
|
|
407
448
|
|
|
449
|
+
const lpVersion = lp.getContractVersion(this.chainIdentifier);
|
|
450
|
+
|
|
408
451
|
//Vault related
|
|
409
452
|
let vaultScript: Uint8Array;
|
|
410
453
|
let vaultAddressType: CoinselectAddressTypes;
|
|
@@ -452,7 +495,7 @@ export class SpvFromBTCWrapper<
|
|
|
452
495
|
//Fetch vault data
|
|
453
496
|
let vault: T["SpvVaultData"] | null;
|
|
454
497
|
try {
|
|
455
|
-
vault = await this._contract.getVaultData(resp.address, resp.vaultId);
|
|
498
|
+
vault = await this._contract(lpVersion).getVaultData(resp.address, resp.vaultId);
|
|
456
499
|
} catch (e) {
|
|
457
500
|
this.logger.error("Error getting spv vault (owner: "+resp.address+" vaultId: "+resp.vaultId.toString(10)+"): ", e);
|
|
458
501
|
throw new IntermediaryError("Spv swap vault not found", e);
|
|
@@ -522,7 +565,7 @@ export class SpvFromBTCWrapper<
|
|
|
522
565
|
if(_btcTx==null) throw new IntermediaryError("Invalid ancestor transaction (not found)");
|
|
523
566
|
btcTx = _btcTx;
|
|
524
567
|
}
|
|
525
|
-
const withdrawalData = await this._contract.getWithdrawalData(btcTx);
|
|
568
|
+
const withdrawalData = await this._contract(lpVersion).getWithdrawalData(btcTx);
|
|
526
569
|
abortSignal.throwIfAborted();
|
|
527
570
|
pendingWithdrawals.unshift(withdrawalData);
|
|
528
571
|
utxo = pendingWithdrawals[0].getSpentVaultUtxo();
|
|
@@ -549,7 +592,7 @@ export class SpvFromBTCWrapper<
|
|
|
549
592
|
//Also verify that all the withdrawal txns are valid, this is an extra sanity check
|
|
550
593
|
try {
|
|
551
594
|
for(let withdrawal of pendingWithdrawals) {
|
|
552
|
-
await this._contract.checkWithdrawalTx(withdrawal);
|
|
595
|
+
await this._contract(lpVersion).checkWithdrawalTx(withdrawal);
|
|
553
596
|
}
|
|
554
597
|
} catch (e) {
|
|
555
598
|
this.logger.error("Error calculating spv vault balance (owner: "+resp.address+" vaultId: "+resp.vaultId.toString(10)+"): ", e);
|
|
@@ -596,6 +639,8 @@ export class SpvFromBTCWrapper<
|
|
|
596
639
|
if(amountData.token===this._chain.getNativeCurrencyAddress() && _options.gasAmount!==0n)
|
|
597
640
|
throw new UserError("Cannot specify `gasAmount` for swaps to a native token!");
|
|
598
641
|
|
|
642
|
+
const lpVersions = Intermediary.getContractVersionsForLps(this.chainIdentifier, lps);
|
|
643
|
+
|
|
599
644
|
const _abortController = extendAbortController(abortSignal);
|
|
600
645
|
const pricePrefetchPromise: Promise<bigint | undefined> = this.preFetchPrice(amountData, _abortController.signal);
|
|
601
646
|
const usdPricePrefetchPromise: Promise<number | undefined> = this.preFetchUsdPrice(_abortController.signal);
|
|
@@ -604,7 +649,9 @@ export class SpvFromBTCWrapper<
|
|
|
604
649
|
const gasTokenPricePrefetchPromise: Promise<bigint | undefined> | undefined = _options.gasAmount===0n ?
|
|
605
650
|
undefined :
|
|
606
651
|
this.preFetchPrice({token: nativeTokenAddress}, _abortController.signal);
|
|
607
|
-
const callerFeePrefetchPromise =
|
|
652
|
+
const callerFeePrefetchPromise = mapArrayToObject(lpVersions, (contractVersion: string) => {
|
|
653
|
+
return this.preFetchCallerFeeShare(amountData, _options, pricePrefetchPromise, gasTokenPricePrefetchPromise, _abortController, contractVersion);
|
|
654
|
+
});
|
|
608
655
|
const bitcoinFeeRatePromise: Promise<number | undefined> = _options.maxAllowedBitcoinFeeRate!=Infinity ?
|
|
609
656
|
Promise.resolve(_options.maxAllowedBitcoinFeeRate) :
|
|
610
657
|
this._btcRpc.getFeeRate().then(x => this._options.maxBtcFeeOffset + (x*this._options.maxBtcFeeMultiplier)).catch(e => {
|
|
@@ -617,6 +664,7 @@ export class SpvFromBTCWrapper<
|
|
|
617
664
|
intermediary: lp,
|
|
618
665
|
quote: tryWithRetries(async () => {
|
|
619
666
|
if(lp.services[SwapType.SPV_VAULT_FROM_BTC]==null) throw new Error("LP service for processing spv vault swaps not found!");
|
|
667
|
+
const version = lp.getContractVersion(this.chainIdentifier);
|
|
620
668
|
|
|
621
669
|
const abortController = extendAbortController(_abortController.signal);
|
|
622
670
|
|
|
@@ -631,7 +679,7 @@ export class SpvFromBTCWrapper<
|
|
|
631
679
|
exactOut: !amountData.exactIn,
|
|
632
680
|
gasToken: nativeTokenAddress,
|
|
633
681
|
gasAmount: _options.gasAmount,
|
|
634
|
-
callerFeeRate: throwIfUndefined(callerFeePrefetchPromise, "Caller fee prefetch failed!"),
|
|
682
|
+
callerFeeRate: throwIfUndefined(callerFeePrefetchPromise[version], "Caller fee prefetch failed!"),
|
|
635
683
|
frontingFeeRate: 0n,
|
|
636
684
|
additionalParams
|
|
637
685
|
},
|
|
@@ -641,7 +689,7 @@ export class SpvFromBTCWrapper<
|
|
|
641
689
|
|
|
642
690
|
this.logger.debug("create("+lp.url+"): LP response: ", resp)
|
|
643
691
|
|
|
644
|
-
const callerFeeShare = (await callerFeePrefetchPromise)!;
|
|
692
|
+
const callerFeeShare = (await callerFeePrefetchPromise[version])!;
|
|
645
693
|
|
|
646
694
|
const [
|
|
647
695
|
pricingInfo,
|
|
@@ -704,7 +752,8 @@ export class SpvFromBTCWrapper<
|
|
|
704
752
|
genesisSmartChainBlockHeight: await throwIfUndefined(
|
|
705
753
|
finalizedBlockHeightPrefetchPromise,
|
|
706
754
|
"Finalize block height promise failed!"
|
|
707
|
-
)
|
|
755
|
+
),
|
|
756
|
+
contractVersion: version
|
|
708
757
|
};
|
|
709
758
|
const quote = new SpvFromBTCSwap<T>(this, swapInit);
|
|
710
759
|
return quote;
|
|
@@ -724,14 +773,14 @@ export class SpvFromBTCWrapper<
|
|
|
724
773
|
* @param vault SPV vault processing the swap
|
|
725
774
|
* @param lp Intermediary (LP) used as a counterparty for the swap
|
|
726
775
|
*/
|
|
727
|
-
public async recoverFromState(state: SpvWithdrawalClaimedState | SpvWithdrawalFrontedState, vault?: SpvVaultData | null, lp?: Intermediary): Promise<SpvFromBTCSwap<T> | null> {
|
|
776
|
+
public async recoverFromState(state: SpvWithdrawalClaimedState | SpvWithdrawalFrontedState, contractVersion: string, vault?: SpvVaultData | null, lp?: Intermediary): Promise<SpvFromBTCSwap<T> | null> {
|
|
728
777
|
//Get the vault
|
|
729
|
-
vault ??= await this._contract.getVaultData(state.owner, state.vaultId);
|
|
778
|
+
vault ??= await this._contract(contractVersion).getVaultData(state.owner, state.vaultId);
|
|
730
779
|
if(vault==null) return null;
|
|
731
780
|
if(state.btcTxId==null) return null;
|
|
732
781
|
const btcTx = await this._btcRpc.getTransaction(state.btcTxId);
|
|
733
782
|
if(btcTx==null) return null;
|
|
734
|
-
const withdrawalData = await this._contract.getWithdrawalData(btcTx)
|
|
783
|
+
const withdrawalData = await this._contract(contractVersion).getWithdrawalData(btcTx)
|
|
735
784
|
.catch(e => {
|
|
736
785
|
this.logger.warn(`Error parsing withdrawal data for tx ${btcTx.txid}: `, e);
|
|
737
786
|
return null;
|
|
@@ -798,7 +847,9 @@ export class SpvFromBTCWrapper<
|
|
|
798
847
|
frontingFeeShare: withdrawalData.frontingFeeRate,
|
|
799
848
|
executionFeeShare: withdrawalData.executionFeeRate,
|
|
800
849
|
|
|
801
|
-
genesisSmartChainBlockHeight: txBlock?.blockHeight ?? 0
|
|
850
|
+
genesisSmartChainBlockHeight: txBlock?.blockHeight ?? 0,
|
|
851
|
+
|
|
852
|
+
contractVersion
|
|
802
853
|
};
|
|
803
854
|
const quote = new SpvFromBTCSwap<T>(this, swapInit);
|
|
804
855
|
quote._data = withdrawalData;
|
|
@@ -853,15 +904,21 @@ export class SpvFromBTCWrapper<
|
|
|
853
904
|
amount: 600n
|
|
854
905
|
});
|
|
855
906
|
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
907
|
+
let longestOpReturnData: Buffer | undefined = undefined;
|
|
908
|
+
for(let contractVersion in this.versionedContracts) {
|
|
909
|
+
if(this.versionedContracts[contractVersion].spvVaultContract==null) continue;
|
|
910
|
+
const opReturnData = this._contract(contractVersion).toOpReturnData(
|
|
911
|
+
this._chain.randomAddress(),
|
|
912
|
+
includeGasToken ? [0xFFFFFFFFFFFFFFFFn, 0xFFFFFFFFFFFFFFFFn] : [0xFFFFFFFFFFFFFFFFn]
|
|
913
|
+
);
|
|
914
|
+
if(longestOpReturnData==null || longestOpReturnData.length < opReturnData.length) longestOpReturnData = opReturnData;
|
|
915
|
+
}
|
|
916
|
+
if(longestOpReturnData==null) throw new Error(`No contract version supporting the Spv Vault BTC -> ${this.chainIdentifier} swaps found!`);
|
|
860
917
|
|
|
861
918
|
psbt.addOutput({
|
|
862
919
|
script: Buffer.concat([
|
|
863
|
-
|
|
864
|
-
|
|
920
|
+
longestOpReturnData.length <= 75 ? Buffer.from([0x6a, longestOpReturnData.length]) : Buffer.from([0x6a, 0x4c, longestOpReturnData.length]),
|
|
921
|
+
longestOpReturnData
|
|
865
922
|
]),
|
|
866
923
|
amount: 0n
|
|
867
924
|
});
|
|
@@ -880,7 +937,7 @@ export class SpvFromBTCWrapper<
|
|
|
880
937
|
const changedSwaps: Set<SpvFromBTCSwap<T>> = new Set();
|
|
881
938
|
const removeSwaps: SpvFromBTCSwap<T>[] = [];
|
|
882
939
|
|
|
883
|
-
const broadcastedOrConfirmedSwaps: (SpvFromBTCSwap<T> & {_data: T["SpvVaultWithdrawalData"]})[] =
|
|
940
|
+
const broadcastedOrConfirmedSwaps: {[version: string]: (SpvFromBTCSwap<T> & {_data: T["SpvVaultWithdrawalData"]})[]} = {};
|
|
884
941
|
|
|
885
942
|
for(let pastSwap of pastSwaps) {
|
|
886
943
|
let changed: boolean = false;
|
|
@@ -919,56 +976,65 @@ export class SpvFromBTCWrapper<
|
|
|
919
976
|
if(changed) changedSwaps.add(pastSwap);
|
|
920
977
|
|
|
921
978
|
if(pastSwap._state===SpvFromBTCSwapState.BROADCASTED || pastSwap._state===SpvFromBTCSwapState.BTC_TX_CONFIRMED) {
|
|
922
|
-
if(pastSwap._data!=null) broadcastedOrConfirmedSwaps.push(pastSwap as (SpvFromBTCSwap<T> & {_data: T["SpvVaultWithdrawalData"]}));
|
|
979
|
+
if(pastSwap._data!=null) (broadcastedOrConfirmedSwaps[pastSwap._contractVersion ?? "v1"] ??= []).push(pastSwap as (SpvFromBTCSwap<T> & {_data: T["SpvVaultWithdrawalData"]}));
|
|
923
980
|
}
|
|
924
981
|
}
|
|
925
982
|
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
withdrawal: val._data!
|
|
930
|
-
})));
|
|
931
|
-
const _vaultUtxos = await this._contract.getVaultLatestUtxos(broadcastedOrConfirmedSwaps.map(val => val.getSpvVaultData()));
|
|
932
|
-
for(const pastSwap of broadcastedOrConfirmedSwaps) {
|
|
933
|
-
const fronterAddress = _fronts[pastSwap._data.getTxId()];
|
|
934
|
-
const vault = pastSwap.getSpvVaultData();
|
|
935
|
-
const latestVaultUtxo = _vaultUtxos[vault.owner]?.[vault.vaultId.toString(10)];
|
|
936
|
-
if(fronterAddress===undefined) this.logger.warn(`_checkPastSwaps(): No fronter address returned for ${pastSwap._data.getTxId()}`);
|
|
937
|
-
if(latestVaultUtxo===undefined) this.logger.warn(`_checkPastSwaps(): No last vault utxo returned for ${pastSwap._data.getTxId()}`);
|
|
938
|
-
if(await pastSwap._shouldCheckWithdrawalState(fronterAddress, latestVaultUtxo)) checkWithdrawalStateSwaps.push(pastSwap);
|
|
939
|
-
}
|
|
940
|
-
|
|
941
|
-
const withdrawalStates = await this._contract.getWithdrawalStates(
|
|
942
|
-
checkWithdrawalStateSwaps.map(val => ({
|
|
943
|
-
withdrawal: val._data,
|
|
944
|
-
scStartBlockheight: val._genesisSmartChainBlockHeight
|
|
945
|
-
}))
|
|
946
|
-
);
|
|
947
|
-
for(const pastSwap of checkWithdrawalStateSwaps) {
|
|
948
|
-
const status = withdrawalStates[pastSwap._data.getTxId()];
|
|
949
|
-
if(status==null) {
|
|
950
|
-
this.logger.warn(`_checkPastSwaps(): No withdrawal state returned for ${pastSwap._data.getTxId()}`);
|
|
983
|
+
for(let contractVersion in broadcastedOrConfirmedSwaps) {
|
|
984
|
+
if(this.versionedContracts[contractVersion]==null) {
|
|
985
|
+
this.logger.warn(`_checkPastSwaps(): No contract was found for ${this.chainIdentifier} version ${contractVersion}! Skipping these swaps!`);
|
|
951
986
|
continue;
|
|
952
987
|
}
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
988
|
+
|
|
989
|
+
const _broadcastedOrConfirmedSwaps = broadcastedOrConfirmedSwaps[contractVersion];
|
|
990
|
+
|
|
991
|
+
const checkWithdrawalStateSwaps: (SpvFromBTCSwap<T> & {_data: T["SpvVaultWithdrawalData"]})[] = [];
|
|
992
|
+
const _fronts = await this._contract(contractVersion).getFronterAddresses(_broadcastedOrConfirmedSwaps.map(val => ({
|
|
993
|
+
...val.getSpvVaultData(),
|
|
994
|
+
withdrawal: val._data!
|
|
995
|
+
})));
|
|
996
|
+
const _vaultUtxos = await this._contract(contractVersion).getVaultLatestUtxos(_broadcastedOrConfirmedSwaps.map(val => val.getSpvVaultData()));
|
|
997
|
+
for(const pastSwap of _broadcastedOrConfirmedSwaps) {
|
|
998
|
+
const fronterAddress = _fronts[pastSwap._data.getTxId()];
|
|
999
|
+
const vault = pastSwap.getSpvVaultData();
|
|
1000
|
+
const latestVaultUtxo = _vaultUtxos[vault.owner]?.[vault.vaultId.toString(10)];
|
|
1001
|
+
if(fronterAddress===undefined) this.logger.warn(`_checkPastSwaps(): No fronter address returned for ${pastSwap._data.getTxId()}`);
|
|
1002
|
+
if(latestVaultUtxo===undefined) this.logger.warn(`_checkPastSwaps(): No last vault utxo returned for ${pastSwap._data.getTxId()}`);
|
|
1003
|
+
if(await pastSwap._shouldCheckWithdrawalState(fronterAddress, latestVaultUtxo)) checkWithdrawalStateSwaps.push(pastSwap);
|
|
1004
|
+
}
|
|
1005
|
+
|
|
1006
|
+
const withdrawalStates = await this._contract(contractVersion).getWithdrawalStates(
|
|
1007
|
+
checkWithdrawalStateSwaps.map(val => ({
|
|
1008
|
+
withdrawal: val._data,
|
|
1009
|
+
scStartBlockheight: val._genesisSmartChainBlockHeight
|
|
1010
|
+
}))
|
|
1011
|
+
);
|
|
1012
|
+
for(const pastSwap of checkWithdrawalStateSwaps) {
|
|
1013
|
+
const status = withdrawalStates[pastSwap._data.getTxId()];
|
|
1014
|
+
if(status==null) {
|
|
1015
|
+
this.logger.warn(`_checkPastSwaps(): No withdrawal state returned for ${pastSwap._data.getTxId()}`);
|
|
1016
|
+
continue;
|
|
1017
|
+
}
|
|
1018
|
+
this.logger.debug("syncStateFromChain(): status of "+pastSwap._data.btcTx.txid, status?.type);
|
|
1019
|
+
let changed = false;
|
|
1020
|
+
switch(status.type) {
|
|
1021
|
+
case SpvWithdrawalStateType.FRONTED:
|
|
1022
|
+
pastSwap._frontTxId = status.txId;
|
|
1023
|
+
pastSwap._state = SpvFromBTCSwapState.FRONTED;
|
|
1024
|
+
changed ||= true;
|
|
1025
|
+
break;
|
|
1026
|
+
case SpvWithdrawalStateType.CLAIMED:
|
|
1027
|
+
pastSwap._claimTxId = status.txId;
|
|
1028
|
+
pastSwap._state = SpvFromBTCSwapState.CLAIMED;
|
|
1029
|
+
changed ||= true;
|
|
1030
|
+
break;
|
|
1031
|
+
case SpvWithdrawalStateType.CLOSED:
|
|
1032
|
+
pastSwap._state = SpvFromBTCSwapState.CLOSED;
|
|
1033
|
+
changed ||= true;
|
|
1034
|
+
break;
|
|
1035
|
+
}
|
|
1036
|
+
if(changed) changedSwaps.add(pastSwap);
|
|
970
1037
|
}
|
|
971
|
-
if(changed) changedSwaps.add(pastSwap);
|
|
972
1038
|
}
|
|
973
1039
|
|
|
974
1040
|
return {
|
|
@@ -81,7 +81,8 @@ export class LnForGasWrapper<T extends ChainType> extends ISwapWrapper<T, LnForG
|
|
|
81
81
|
swapFee: resp.swapFee,
|
|
82
82
|
swapFeeBtc: resp.swapFeeSats,
|
|
83
83
|
token,
|
|
84
|
-
exactIn: false
|
|
84
|
+
exactIn: false,
|
|
85
|
+
contractVersion: "v1"
|
|
85
86
|
};
|
|
86
87
|
const quote = new LnForGasSwap(this, quoteInit);
|
|
87
88
|
return quote;
|
|
@@ -122,7 +122,8 @@ export class OnchainForGasWrapper<T extends ChainType> extends ISwapWrapper<T, O
|
|
|
122
122
|
swapFee: resp.swapFee,
|
|
123
123
|
swapFeeBtc: resp.swapFeeSats,
|
|
124
124
|
exactIn: false,
|
|
125
|
-
token
|
|
125
|
+
token,
|
|
126
|
+
contractVersion: "v1"
|
|
126
127
|
} as OnchainForGasSwapInit);
|
|
127
128
|
return quote;
|
|
128
129
|
}
|
package/src/utils/RetryUtils.ts
CHANGED
|
@@ -40,12 +40,19 @@ function checkError(e: any, errorAllowed: ((e: any) => boolean) | Constructor<Er
|
|
|
40
40
|
* @param retryPolicy.exponential Whether to use exponentially increasing delays
|
|
41
41
|
* @param errorAllowed A callback for determining whether a given error is allowed, and we should therefore not retry
|
|
42
42
|
* @param abortSignal
|
|
43
|
+
* @param failureLogLevel
|
|
43
44
|
* @returns Result of the action executing callback
|
|
44
45
|
* @category Utilities
|
|
45
46
|
*/
|
|
46
|
-
export async function tryWithRetries<T>(
|
|
47
|
-
|
|
48
|
-
|
|
47
|
+
export async function tryWithRetries<T>(
|
|
48
|
+
func: (retryCount: number) => Promise<T>,
|
|
49
|
+
retryPolicy?: {
|
|
50
|
+
maxRetries?: number, delay?: number, exponential?: boolean
|
|
51
|
+
},
|
|
52
|
+
errorAllowed?: ((e: any) => boolean) | Constructor<Error> | Constructor<Error>[],
|
|
53
|
+
abortSignal?: AbortSignal,
|
|
54
|
+
failureLogLevel: "debug" | "info" | "warn" | "error" = "warn"
|
|
55
|
+
): Promise<T> {
|
|
49
56
|
retryPolicy = retryPolicy || {};
|
|
50
57
|
retryPolicy.maxRetries = retryPolicy.maxRetries || 5;
|
|
51
58
|
retryPolicy.delay = retryPolicy.delay || 500;
|
|
@@ -59,7 +66,7 @@ export async function tryWithRetries<T>(func: (retryCount: number) => Promise<T>
|
|
|
59
66
|
} catch (e) {
|
|
60
67
|
if (errorAllowed != null && checkError(e, errorAllowed)) throw e;
|
|
61
68
|
err = e;
|
|
62
|
-
logger
|
|
69
|
+
logger[failureLogLevel]("tryWithRetries(): Error on try number: " + i, e);
|
|
63
70
|
}
|
|
64
71
|
if (abortSignal != null && abortSignal.aborted) throw (abortSignal.reason || new Error("Aborted"));
|
|
65
72
|
if (i !== retryPolicy.maxRetries - 1) {
|
package/src/utils/Utils.ts
CHANGED
|
@@ -46,6 +46,20 @@ export function promiseAny<T>(promises: Promise<T>[]): Promise<T> {
|
|
|
46
46
|
});
|
|
47
47
|
}
|
|
48
48
|
|
|
49
|
+
/**
|
|
50
|
+
* Maps an array to object properties using the translation function
|
|
51
|
+
*
|
|
52
|
+
* @param array
|
|
53
|
+
* @param translator
|
|
54
|
+
*/
|
|
55
|
+
export function mapArrayToObject<T extends string[], O>(array: T, translator: (key: T[number]) => O): {[key in T[number]]: O} {
|
|
56
|
+
const obj: any = {};
|
|
57
|
+
array.forEach((item) => {
|
|
58
|
+
obj[item] = translator(item);
|
|
59
|
+
});
|
|
60
|
+
return obj;
|
|
61
|
+
}
|
|
62
|
+
|
|
49
63
|
/**
|
|
50
64
|
* Maps a JS object to another JS object based on the translation function, the translation function is called for every
|
|
51
65
|
* property (value/key) of the old object and returns the new value of for this property
|