@atomiqlabs/lp-lib 12.1.0 → 13.0.0-beta.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/index.d.ts +18 -13
- package/dist/index.js +18 -13
- package/dist/plugins/IPlugin.d.ts +35 -12
- package/dist/plugins/PluginManager.d.ts +38 -15
- package/dist/plugins/PluginManager.js +33 -9
- package/dist/prices/BinanceSwapPrice.d.ts +1 -1
- package/dist/prices/BinanceSwapPrice.js +1 -1
- package/dist/prices/CoinGeckoSwapPrice.d.ts +1 -1
- package/dist/prices/CoinGeckoSwapPrice.js +1 -1
- package/dist/{swaps → prices}/ISwapPrice.js +4 -0
- package/dist/prices/OKXSwapPrice.d.ts +1 -1
- package/dist/prices/OKXSwapPrice.js +1 -1
- package/dist/swaps/SwapHandler.d.ts +20 -58
- package/dist/swaps/SwapHandler.js +17 -186
- package/dist/swaps/SwapHandlerSwap.d.ts +8 -23
- package/dist/swaps/SwapHandlerSwap.js +7 -39
- package/dist/swaps/assertions/AmountAssertions.d.ts +28 -0
- package/dist/swaps/assertions/AmountAssertions.js +72 -0
- package/dist/swaps/assertions/FromBtcAmountAssertions.d.ts +76 -0
- package/dist/swaps/assertions/FromBtcAmountAssertions.js +162 -0
- package/dist/swaps/assertions/LightningAssertions.d.ts +44 -0
- package/dist/swaps/assertions/LightningAssertions.js +86 -0
- package/dist/swaps/assertions/ToBtcAmountAssertions.d.ts +53 -0
- package/dist/swaps/{ToBtcBaseSwapHandler.js → assertions/ToBtcAmountAssertions.js} +20 -94
- package/dist/swaps/escrow/EscrowHandler.d.ts +51 -0
- package/dist/swaps/escrow/EscrowHandler.js +158 -0
- package/dist/swaps/escrow/EscrowHandlerSwap.d.ts +35 -0
- package/dist/swaps/escrow/EscrowHandlerSwap.js +69 -0
- package/dist/swaps/{FromBtcBaseSwap.d.ts → escrow/FromBtcBaseSwap.d.ts} +2 -3
- package/dist/swaps/{FromBtcBaseSwap.js → escrow/FromBtcBaseSwap.js} +4 -7
- package/dist/swaps/{FromBtcBaseSwapHandler.d.ts → escrow/FromBtcBaseSwapHandler.d.ts} +10 -49
- package/dist/swaps/{FromBtcBaseSwapHandler.js → escrow/FromBtcBaseSwapHandler.js} +16 -137
- package/dist/swaps/{ToBtcBaseSwap.d.ts → escrow/ToBtcBaseSwap.d.ts} +2 -2
- package/dist/swaps/{ToBtcBaseSwap.js → escrow/ToBtcBaseSwap.js} +4 -4
- package/dist/swaps/escrow/ToBtcBaseSwapHandler.d.ts +53 -0
- package/dist/swaps/escrow/ToBtcBaseSwapHandler.js +81 -0
- package/dist/swaps/{frombtc_abstract → escrow/frombtc_abstract}/FromBtcAbs.d.ts +4 -4
- package/dist/swaps/{frombtc_abstract → escrow/frombtc_abstract}/FromBtcAbs.js +15 -15
- package/dist/swaps/{frombtc_abstract → escrow/frombtc_abstract}/FromBtcSwapAbs.js +1 -1
- package/dist/swaps/{frombtcln_abstract → escrow/frombtcln_abstract}/FromBtcLnAbs.d.ts +9 -7
- package/dist/swaps/{frombtcln_abstract → escrow/frombtcln_abstract}/FromBtcLnAbs.js +22 -19
- package/dist/swaps/{frombtcln_abstract → escrow/frombtcln_abstract}/FromBtcLnSwapAbs.js +3 -3
- package/dist/swaps/{tobtc_abstract → escrow/tobtc_abstract}/ToBtcAbs.d.ts +4 -4
- package/dist/swaps/{tobtc_abstract → escrow/tobtc_abstract}/ToBtcAbs.js +14 -13
- package/dist/swaps/{tobtc_abstract → escrow/tobtc_abstract}/ToBtcSwapAbs.js +3 -3
- package/dist/swaps/{tobtcln_abstract → escrow/tobtcln_abstract}/ToBtcLnAbs.d.ts +6 -26
- package/dist/swaps/{tobtcln_abstract → escrow/tobtcln_abstract}/ToBtcLnAbs.js +20 -57
- package/dist/swaps/{tobtcln_abstract → escrow/tobtcln_abstract}/ToBtcLnSwapAbs.js +3 -3
- package/dist/swaps/spv_vault_swap/SpvVault.d.ts +41 -0
- package/dist/swaps/spv_vault_swap/SpvVault.js +111 -0
- package/dist/swaps/spv_vault_swap/SpvVaultSwap.d.ts +63 -0
- package/dist/swaps/spv_vault_swap/SpvVaultSwap.js +145 -0
- package/dist/swaps/spv_vault_swap/SpvVaultSwapHandler.d.ts +68 -0
- package/dist/swaps/spv_vault_swap/SpvVaultSwapHandler.js +469 -0
- package/dist/swaps/spv_vault_swap/SpvVaults.d.ts +57 -0
- package/dist/swaps/spv_vault_swap/SpvVaults.js +369 -0
- package/dist/swaps/{frombtc_trusted → trusted/frombtc_trusted}/FromBtcTrusted.d.ts +10 -13
- package/dist/swaps/{frombtc_trusted → trusted/frombtc_trusted}/FromBtcTrusted.js +25 -30
- package/dist/swaps/{frombtc_trusted → trusted/frombtc_trusted}/FromBtcTrustedSwap.d.ts +9 -4
- package/dist/swaps/{frombtc_trusted → trusted/frombtc_trusted}/FromBtcTrustedSwap.js +15 -7
- package/dist/swaps/{frombtcln_trusted → trusted/frombtcln_trusted}/FromBtcLnTrusted.d.ts +12 -14
- package/dist/swaps/{frombtcln_trusted → trusted/frombtcln_trusted}/FromBtcLnTrusted.js +33 -35
- package/dist/swaps/{frombtcln_trusted → trusted/frombtcln_trusted}/FromBtcLnTrustedSwap.d.ts +9 -4
- package/dist/swaps/{frombtcln_trusted → trusted/frombtcln_trusted}/FromBtcLnTrustedSwap.js +17 -7
- package/dist/utils/Utils.d.ts +13 -5
- package/dist/utils/Utils.js +23 -1
- package/dist/wallets/IBitcoinWallet.d.ts +6 -0
- package/dist/wallets/ISpvVaultSigner.d.ts +7 -0
- package/dist/wallets/ISpvVaultSigner.js +2 -0
- package/dist/wallets/ISpvVaultWallet.d.ts +42 -0
- package/dist/wallets/ISpvVaultWallet.js +2 -0
- package/package.json +2 -2
- package/src/index.ts +21 -15
- package/src/plugins/IPlugin.ts +27 -19
- package/src/plugins/PluginManager.ts +51 -26
- package/src/prices/BinanceSwapPrice.ts +1 -1
- package/src/prices/CoinGeckoSwapPrice.ts +1 -1
- package/src/{swaps → prices}/ISwapPrice.ts +4 -0
- package/src/prices/OKXSwapPrice.ts +1 -1
- package/src/swaps/SwapHandler.ts +22 -205
- package/src/swaps/SwapHandlerSwap.ts +10 -46
- package/src/swaps/assertions/AmountAssertions.ts +77 -0
- package/src/swaps/assertions/FromBtcAmountAssertions.ts +228 -0
- package/src/swaps/assertions/LightningAssertions.ts +103 -0
- package/src/swaps/{ToBtcBaseSwapHandler.ts → assertions/ToBtcAmountAssertions.ts} +27 -142
- package/src/swaps/escrow/EscrowHandler.ts +179 -0
- package/src/swaps/escrow/EscrowHandlerSwap.ts +87 -0
- package/src/swaps/{FromBtcBaseSwap.ts → escrow/FromBtcBaseSwap.ts} +4 -8
- package/src/swaps/{FromBtcBaseSwapHandler.ts → escrow/FromBtcBaseSwapHandler.ts} +30 -190
- package/src/swaps/{ToBtcBaseSwap.ts → escrow/ToBtcBaseSwap.ts} +4 -5
- package/src/swaps/escrow/ToBtcBaseSwapHandler.ts +130 -0
- package/src/swaps/{frombtc_abstract → escrow/frombtc_abstract}/FromBtcAbs.ts +20 -20
- package/src/swaps/{frombtc_abstract → escrow/frombtc_abstract}/FromBtcSwapAbs.ts +1 -1
- package/src/swaps/{frombtcln_abstract → escrow/frombtcln_abstract}/FromBtcLnAbs.ts +29 -25
- package/src/swaps/{frombtcln_abstract → escrow/frombtcln_abstract}/FromBtcLnSwapAbs.ts +2 -2
- package/src/swaps/{tobtc_abstract → escrow/tobtc_abstract}/ToBtcAbs.ts +19 -18
- package/src/swaps/{tobtc_abstract → escrow/tobtc_abstract}/ToBtcSwapAbs.ts +2 -2
- package/src/swaps/{tobtcln_abstract → escrow/tobtcln_abstract}/ToBtcLnAbs.ts +26 -66
- package/src/swaps/{tobtcln_abstract → escrow/tobtcln_abstract}/ToBtcLnSwapAbs.ts +2 -2
- package/src/swaps/spv_vault_swap/SpvVault.ts +143 -0
- package/src/swaps/spv_vault_swap/SpvVaultSwap.ts +207 -0
- package/src/swaps/spv_vault_swap/SpvVaultSwapHandler.ts +606 -0
- package/src/swaps/spv_vault_swap/SpvVaults.ts +441 -0
- package/src/swaps/{frombtc_trusted → trusted/frombtc_trusted}/FromBtcTrusted.ts +36 -51
- package/src/swaps/{frombtc_trusted → trusted/frombtc_trusted}/FromBtcTrustedSwap.ts +18 -8
- package/src/swaps/{frombtcln_trusted → trusted/frombtcln_trusted}/FromBtcLnTrusted.ts +43 -52
- package/src/swaps/{frombtcln_trusted → trusted/frombtcln_trusted}/FromBtcLnTrustedSwap.ts +20 -8
- package/src/utils/Utils.ts +27 -1
- package/src/wallets/IBitcoinWallet.ts +4 -0
- package/src/wallets/ISpvVaultSigner.ts +11 -0
- package/dist/swaps/FromBtcLnBaseSwapHandler.d.ts +0 -26
- package/dist/swaps/FromBtcLnBaseSwapHandler.js +0 -46
- package/dist/swaps/ToBtcBaseSwapHandler.d.ts +0 -95
- package/src/swaps/FromBtcLnBaseSwapHandler.ts +0 -63
- /package/dist/{swaps → prices}/ISwapPrice.d.ts +0 -0
- /package/dist/swaps/{frombtc_abstract → escrow/frombtc_abstract}/FromBtcSwapAbs.d.ts +0 -0
- /package/dist/swaps/{frombtcln_abstract → escrow/frombtcln_abstract}/FromBtcLnSwapAbs.d.ts +0 -0
- /package/dist/swaps/{tobtc_abstract → escrow/tobtc_abstract}/ToBtcSwapAbs.d.ts +0 -0
- /package/dist/swaps/{tobtcln_abstract → escrow/tobtcln_abstract}/ToBtcLnSwapAbs.d.ts +0 -0
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import {Express, Request, Response} from "express";
|
|
2
2
|
import {createHash, randomBytes} from "crypto";
|
|
3
3
|
import {FromBtcLnSwapAbs, FromBtcLnSwapState} from "./FromBtcLnSwapAbs";
|
|
4
|
-
import {MultichainData, SwapHandlerType} from "
|
|
5
|
-
import {ISwapPrice} from "
|
|
4
|
+
import {MultichainData, SwapHandlerType} from "../../SwapHandler";
|
|
5
|
+
import {ISwapPrice} from "../../../prices/ISwapPrice";
|
|
6
6
|
import {
|
|
7
7
|
BigIntBufferUtils,
|
|
8
8
|
ChainSwapType,
|
|
@@ -11,21 +11,21 @@ import {
|
|
|
11
11
|
RefundEvent,
|
|
12
12
|
SwapData
|
|
13
13
|
} from "@atomiqlabs/base";
|
|
14
|
-
import {expressHandlerWrapper, HEX_REGEX, isDefinedRuntimeError} from "
|
|
15
|
-
import {PluginManager} from "
|
|
16
|
-
import {IIntermediaryStorage} from "
|
|
17
|
-
import {FieldTypeEnum, verifySchema} from "
|
|
18
|
-
import {serverParamDecoder} from "
|
|
19
|
-
import {ServerParamEncoder} from "
|
|
20
|
-
import {IParamReader} from "
|
|
21
|
-
import {FromBtcBaseConfig} from "../FromBtcBaseSwapHandler";
|
|
22
|
-
import {FromBtcLnBaseSwapHandler} from "../FromBtcLnBaseSwapHandler";
|
|
14
|
+
import {expressHandlerWrapper, getAbortController, HEX_REGEX, isDefinedRuntimeError} from "../../../utils/Utils";
|
|
15
|
+
import {PluginManager} from "../../../plugins/PluginManager";
|
|
16
|
+
import {IIntermediaryStorage} from "../../../storage/IIntermediaryStorage";
|
|
17
|
+
import {FieldTypeEnum, verifySchema} from "../../../utils/paramcoders/SchemaVerifier";
|
|
18
|
+
import {serverParamDecoder} from "../../../utils/paramcoders/server/ServerParamDecoder";
|
|
19
|
+
import {ServerParamEncoder} from "../../../utils/paramcoders/server/ServerParamEncoder";
|
|
20
|
+
import {IParamReader} from "../../../utils/paramcoders/IParamReader";
|
|
21
|
+
import {FromBtcBaseConfig, FromBtcBaseSwapHandler} from "../FromBtcBaseSwapHandler";
|
|
23
22
|
import {
|
|
24
23
|
HodlInvoiceInit,
|
|
25
24
|
ILightningWallet,
|
|
26
25
|
LightningNetworkChannel,
|
|
27
26
|
LightningNetworkInvoice
|
|
28
|
-
} from "
|
|
27
|
+
} from "../../../wallets/ILightningWallet";
|
|
28
|
+
import { LightningAssertions } from "../../assertions/LightningAssertions";
|
|
29
29
|
|
|
30
30
|
export type FromBtcLnConfig = FromBtcBaseConfig & {
|
|
31
31
|
invoiceTimeoutSeconds?: number,
|
|
@@ -45,11 +45,13 @@ export type FromBtcLnRequestType = {
|
|
|
45
45
|
/**
|
|
46
46
|
* Swap handler handling from BTCLN swaps using submarine swaps
|
|
47
47
|
*/
|
|
48
|
-
export class FromBtcLnAbs extends
|
|
48
|
+
export class FromBtcLnAbs extends FromBtcBaseSwapHandler<FromBtcLnSwapAbs, FromBtcLnSwapState> {
|
|
49
49
|
readonly type = SwapHandlerType.FROM_BTCLN;
|
|
50
50
|
readonly swapType = ChainSwapType.HTLC;
|
|
51
51
|
|
|
52
52
|
readonly config: FromBtcLnConfig;
|
|
53
|
+
readonly lightning: ILightningWallet;
|
|
54
|
+
readonly LightningAssertions: LightningAssertions;
|
|
53
55
|
|
|
54
56
|
constructor(
|
|
55
57
|
storageDirectory: IIntermediaryStorage<FromBtcLnSwapAbs>,
|
|
@@ -59,9 +61,11 @@ export class FromBtcLnAbs extends FromBtcLnBaseSwapHandler<FromBtcLnSwapAbs, Fro
|
|
|
59
61
|
swapPricing: ISwapPrice,
|
|
60
62
|
config: FromBtcLnConfig
|
|
61
63
|
) {
|
|
62
|
-
super(storageDirectory, path, chains,
|
|
64
|
+
super(storageDirectory, path, chains, swapPricing, config);
|
|
63
65
|
this.config = config;
|
|
64
66
|
this.config.invoiceTimeoutSeconds = this.config.invoiceTimeoutSeconds || 90;
|
|
67
|
+
this.lightning = lightning;
|
|
68
|
+
this.LightningAssertions = new LightningAssertions(this.logger, lightning);
|
|
65
69
|
}
|
|
66
70
|
|
|
67
71
|
protected async processPastSwap(swap: FromBtcLnSwapAbs): Promise<"REFUND" | "SETTLE" | "CANCEL" | null> {
|
|
@@ -499,8 +503,8 @@ export class FromBtcLnAbs extends FromBtcLnBaseSwapHandler<FromBtcLnSwapAbs, Fro
|
|
|
499
503
|
chainIdentifier = this.chains.default;
|
|
500
504
|
address = invoice.description;
|
|
501
505
|
}
|
|
502
|
-
const {
|
|
503
|
-
if(!
|
|
506
|
+
const {chainInterface} = this.getChain(chainIdentifier);
|
|
507
|
+
if(!chainInterface.isValidAddress(address)) throw {
|
|
504
508
|
_httpStatus: 200,
|
|
505
509
|
code: 10001,
|
|
506
510
|
msg: "Invoice expired/canceled"
|
|
@@ -542,8 +546,8 @@ export class FromBtcLnAbs extends FromBtcLnBaseSwapHandler<FromBtcLnSwapAbs, Fro
|
|
|
542
546
|
} = {request: {}, times: {}};
|
|
543
547
|
|
|
544
548
|
const chainIdentifier = req.query.chain as string ?? this.chains.default;
|
|
545
|
-
const {swapContract, signer} = this.getChain(chainIdentifier);
|
|
546
|
-
const depositToken = req.query.depositToken as string ??
|
|
549
|
+
const {swapContract, signer, chainInterface} = this.getChain(chainIdentifier);
|
|
550
|
+
const depositToken = req.query.depositToken as string ?? chainInterface.getNativeCurrencyAddress();
|
|
547
551
|
this.checkAllowedDepositToken(chainIdentifier, depositToken);
|
|
548
552
|
|
|
549
553
|
metadata.times.requestReceived = Date.now();
|
|
@@ -563,7 +567,7 @@ export class FromBtcLnAbs extends FromBtcLnBaseSwapHandler<FromBtcLnSwapAbs, Fro
|
|
|
563
567
|
const parsedBody: FromBtcLnRequestType = await req.paramReader.getParams({
|
|
564
568
|
address: (val: string) => val!=null &&
|
|
565
569
|
typeof(val)==="string" &&
|
|
566
|
-
|
|
570
|
+
chainInterface.isValidAddress(val) ? val : null,
|
|
567
571
|
paymentHash: (val: string) => val!=null &&
|
|
568
572
|
typeof(val)==="string" &&
|
|
569
573
|
val.length===64 &&
|
|
@@ -581,7 +585,7 @@ export class FromBtcLnAbs extends FromBtcLnBaseSwapHandler<FromBtcLnSwapAbs, Fro
|
|
|
581
585
|
};
|
|
582
586
|
metadata.request = parsedBody;
|
|
583
587
|
|
|
584
|
-
const requestedAmount = {input: !parsedBody.exactOut, amount: parsedBody.amount};
|
|
588
|
+
const requestedAmount = {input: !parsedBody.exactOut, amount: parsedBody.amount, token: parsedBody.token};
|
|
585
589
|
const request = {
|
|
586
590
|
chainIdentifier,
|
|
587
591
|
raw: req,
|
|
@@ -592,12 +596,12 @@ export class FromBtcLnAbs extends FromBtcLnBaseSwapHandler<FromBtcLnSwapAbs, Fro
|
|
|
592
596
|
|
|
593
597
|
//Check request params
|
|
594
598
|
this.checkDescriptionHash(parsedBody.descriptionHash);
|
|
595
|
-
const fees = await this.
|
|
599
|
+
const fees = await this.AmountAssertions.preCheckFromBtcAmounts(this.type, request, requestedAmount);
|
|
596
600
|
metadata.times.requestChecked = Date.now();
|
|
597
601
|
|
|
598
602
|
//Create abortController for parallel prefetches
|
|
599
603
|
const responseStream = res.responseStream;
|
|
600
|
-
const abortController =
|
|
604
|
+
const abortController = getAbortController(responseStream);
|
|
601
605
|
|
|
602
606
|
//Pre-fetch data
|
|
603
607
|
const {
|
|
@@ -606,7 +610,7 @@ export class FromBtcLnAbs extends FromBtcLnBaseSwapHandler<FromBtcLnSwapAbs, Fro
|
|
|
606
610
|
depositTokenPricePrefetchPromise
|
|
607
611
|
} = this.getFromBtcPricePrefetches(chainIdentifier, useToken, depositToken, abortController);
|
|
608
612
|
const balancePrefetch: Promise<bigint> = this.getBalancePrefetch(chainIdentifier, useToken, abortController);
|
|
609
|
-
const channelsPrefetch: Promise<LightningNetworkChannel[]> = this.getChannelsPrefetch(abortController);
|
|
613
|
+
const channelsPrefetch: Promise<LightningNetworkChannel[]> = this.LightningAssertions.getChannelsPrefetch(abortController);
|
|
610
614
|
|
|
611
615
|
const dummySwapData = await this.getDummySwapData(chainIdentifier, useToken, parsedBody.address, parsedBody.paymentHash);
|
|
612
616
|
abortController.signal.throwIfAborted();
|
|
@@ -627,7 +631,7 @@ export class FromBtcLnAbs extends FromBtcLnBaseSwapHandler<FromBtcLnSwapAbs, Fro
|
|
|
627
631
|
totalInToken,
|
|
628
632
|
securityDepositApyPPM,
|
|
629
633
|
securityDepositBaseMultiplierPPM
|
|
630
|
-
} = await this.checkFromBtcAmount(request, requestedAmount,
|
|
634
|
+
} = await this.AmountAssertions.checkFromBtcAmount(this.type, request, {...requestedAmount, pricePrefetch: pricePrefetchPromise}, fees, abortController.signal);
|
|
631
635
|
metadata.times.priceCalculated = Date.now();
|
|
632
636
|
|
|
633
637
|
if(securityDepositApyPPM!=null) fees.securityDepositApyPPM = securityDepositApyPPM;
|
|
@@ -635,7 +639,7 @@ export class FromBtcLnAbs extends FromBtcLnBaseSwapHandler<FromBtcLnSwapAbs, Fro
|
|
|
635
639
|
|
|
636
640
|
//Check if we have enough funds to honor the request
|
|
637
641
|
await this.checkBalance(totalInToken, balancePrefetch, abortController.signal)
|
|
638
|
-
await this.checkInboundLiquidity(amountBD, channelsPrefetch, abortController.signal);
|
|
642
|
+
await this.LightningAssertions.checkInboundLiquidity(amountBD, channelsPrefetch, abortController.signal);
|
|
639
643
|
metadata.times.balanceChecked = Date.now();
|
|
640
644
|
|
|
641
645
|
//Create swap
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {SwapData} from "@atomiqlabs/base";
|
|
2
|
-
import {SwapHandlerType} from "
|
|
2
|
+
import {SwapHandlerType} from "../../../index";
|
|
3
3
|
import {FromBtcBaseSwap} from "../FromBtcBaseSwap";
|
|
4
|
-
import {deserializeBN, serializeBN} from "
|
|
4
|
+
import {deserializeBN, serializeBN} from "../../../utils/Utils";
|
|
5
5
|
|
|
6
6
|
export enum FromBtcLnSwapState {
|
|
7
7
|
REFUNDED = -2,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {Express, Request, Response} from "express";
|
|
2
2
|
import {ToBtcSwapAbs, ToBtcSwapState} from "./ToBtcSwapAbs";
|
|
3
|
-
import {MultichainData, SwapHandlerType} from "
|
|
4
|
-
import {ISwapPrice} from "
|
|
3
|
+
import {MultichainData, SwapHandlerType} from "../../SwapHandler";
|
|
4
|
+
import {ISwapPrice} from "../../../prices/ISwapPrice";
|
|
5
5
|
import {
|
|
6
6
|
BtcTx,
|
|
7
7
|
ChainSwapType,
|
|
@@ -13,17 +13,17 @@ import {
|
|
|
13
13
|
BitcoinRpc,
|
|
14
14
|
BtcBlock, BigIntBufferUtils
|
|
15
15
|
} from "@atomiqlabs/base";
|
|
16
|
-
import {expressHandlerWrapper, HEX_REGEX, isDefinedRuntimeError} from "
|
|
17
|
-
import {PluginManager} from "
|
|
18
|
-
import {IIntermediaryStorage} from "
|
|
16
|
+
import {expressHandlerWrapper, getAbortController, HEX_REGEX, isDefinedRuntimeError} from "../../../utils/Utils";
|
|
17
|
+
import {PluginManager} from "../../../plugins/PluginManager";
|
|
18
|
+
import {IIntermediaryStorage} from "../../../storage/IIntermediaryStorage";
|
|
19
19
|
import {randomBytes} from "crypto";
|
|
20
|
-
import {FieldTypeEnum, verifySchema} from "
|
|
21
|
-
import {serverParamDecoder} from "
|
|
22
|
-
import {IParamReader} from "
|
|
23
|
-
import {ServerParamEncoder} from "
|
|
20
|
+
import {FieldTypeEnum, verifySchema} from "../../../utils/paramcoders/SchemaVerifier";
|
|
21
|
+
import {serverParamDecoder} from "../../../utils/paramcoders/server/ServerParamDecoder";
|
|
22
|
+
import {IParamReader} from "../../../utils/paramcoders/IParamReader";
|
|
23
|
+
import {ServerParamEncoder} from "../../../utils/paramcoders/server/ServerParamEncoder";
|
|
24
24
|
import {ToBtcBaseConfig, ToBtcBaseSwapHandler} from "../ToBtcBaseSwapHandler";
|
|
25
25
|
import {PromiseQueue} from "promise-queue-ts";
|
|
26
|
-
import {IBitcoinWallet} from "
|
|
26
|
+
import {IBitcoinWallet} from "../../../wallets/IBitcoinWallet";
|
|
27
27
|
|
|
28
28
|
const OUTPUT_SCRIPT_MAX_LENGTH = 200;
|
|
29
29
|
|
|
@@ -75,7 +75,7 @@ export class ToBtcAbs extends ToBtcBaseSwapHandler<ToBtcSwapAbs, ToBtcSwapState>
|
|
|
75
75
|
bitcoinRpc: BitcoinRpc<BtcBlock>,
|
|
76
76
|
config: ToBtcConfig
|
|
77
77
|
) {
|
|
78
|
-
super(storageDirectory, path, chainData, swapPricing);
|
|
78
|
+
super(storageDirectory, path, chainData, swapPricing, config);
|
|
79
79
|
this.bitcoinRpc = bitcoinRpc;
|
|
80
80
|
this.bitcoin = bitcoin;
|
|
81
81
|
this.config = config;
|
|
@@ -595,7 +595,7 @@ export class ToBtcAbs extends ToBtcBaseSwapHandler<ToBtcSwapAbs, ToBtcSwapState>
|
|
|
595
595
|
} = {request: {}, times: {}};
|
|
596
596
|
|
|
597
597
|
const chainIdentifier = req.query.chain as string ?? this.chains.default;
|
|
598
|
-
const {swapContract, signer} = this.getChain(chainIdentifier);
|
|
598
|
+
const {swapContract, signer, chainInterface} = this.getChain(chainIdentifier);
|
|
599
599
|
|
|
600
600
|
metadata.times.requestReceived = Date.now();
|
|
601
601
|
/**
|
|
@@ -623,7 +623,7 @@ export class ToBtcAbs extends ToBtcBaseSwapHandler<ToBtcSwapAbs, ToBtcSwapState>
|
|
|
623
623
|
this.isTokenSupported(chainIdentifier, val) ? val : null,
|
|
624
624
|
offerer: (val: string) => val!=null &&
|
|
625
625
|
typeof(val)==="string" &&
|
|
626
|
-
|
|
626
|
+
chainInterface.isValidAddress(val) ? val : null,
|
|
627
627
|
exactIn: FieldTypeEnum.BooleanOptional
|
|
628
628
|
});
|
|
629
629
|
if (parsedBody==null) throw {
|
|
@@ -632,7 +632,7 @@ export class ToBtcAbs extends ToBtcBaseSwapHandler<ToBtcSwapAbs, ToBtcSwapState>
|
|
|
632
632
|
};
|
|
633
633
|
metadata.request = parsedBody;
|
|
634
634
|
|
|
635
|
-
const requestedAmount = {input: !!parsedBody.exactIn, amount: parsedBody.amount};
|
|
635
|
+
const requestedAmount = {input: !!parsedBody.exactIn, amount: parsedBody.amount, token: parsedBody.token};
|
|
636
636
|
const request = {
|
|
637
637
|
chainIdentifier,
|
|
638
638
|
raw: req,
|
|
@@ -648,12 +648,12 @@ export class ToBtcAbs extends ToBtcBaseSwapHandler<ToBtcSwapAbs, ToBtcSwapState>
|
|
|
648
648
|
this.checkRequiredConfirmations(parsedBody.confirmations);
|
|
649
649
|
this.checkAddress(parsedBody.address);
|
|
650
650
|
await this.checkVaultInitialized(chainIdentifier, parsedBody.token);
|
|
651
|
-
const fees = await this.
|
|
651
|
+
const fees = await this.AmountAssertions.preCheckToBtcAmounts(this.type, request, requestedAmount);
|
|
652
652
|
|
|
653
653
|
metadata.times.requestChecked = Date.now();
|
|
654
654
|
|
|
655
655
|
//Initialize abort controller for the parallel async operations
|
|
656
|
-
const abortController =
|
|
656
|
+
const abortController = getAbortController(responseStream);
|
|
657
657
|
|
|
658
658
|
const {pricePrefetchPromise, signDataPrefetchPromise} = this.getToBtcPrefetches(chainIdentifier, useToken, responseStream, abortController);
|
|
659
659
|
|
|
@@ -664,12 +664,13 @@ export class ToBtcAbs extends ToBtcBaseSwapHandler<ToBtcSwapAbs, ToBtcSwapState>
|
|
|
664
664
|
swapFee,
|
|
665
665
|
swapFeeInToken,
|
|
666
666
|
networkFeeInToken
|
|
667
|
-
} = await this.checkToBtcAmount(request, requestedAmount,
|
|
667
|
+
} = await this.AmountAssertions.checkToBtcAmount(this.type, request, {...requestedAmount, pricePrefetch: pricePrefetchPromise}, fees, async (amount: bigint) => {
|
|
668
668
|
metadata.times.amountsChecked = Date.now();
|
|
669
669
|
const resp = await this.checkAndGetNetworkFee(parsedBody.address, amount);
|
|
670
|
+
this.logger.debug("checkToBtcAmount(): network fee calculated, amount: "+amount.toString(10)+" fee: "+resp.networkFee.toString(10));
|
|
670
671
|
metadata.times.chainFeeCalculated = Date.now();
|
|
671
672
|
return resp;
|
|
672
|
-
}, abortController.signal
|
|
673
|
+
}, abortController.signal);
|
|
673
674
|
metadata.times.priceCalculated = Date.now();
|
|
674
675
|
|
|
675
676
|
const paymentHash = this.getHash(chainIdentifier, parsedBody.address, parsedBody.confirmations, parsedBody.nonce, amountBD).toString("hex");
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {SwapData} from "@atomiqlabs/base";
|
|
2
|
-
import {SwapHandlerType} from "
|
|
2
|
+
import {SwapHandlerType} from "../../../index";
|
|
3
3
|
import {ToBtcBaseSwap} from "../ToBtcBaseSwap";
|
|
4
|
-
import {deserializeBN} from "
|
|
4
|
+
import {deserializeBN} from "../../../utils/Utils";
|
|
5
5
|
|
|
6
6
|
export enum ToBtcSwapState {
|
|
7
7
|
REFUNDED = -3,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {Express, Request, Response} from "express";
|
|
2
2
|
import {ToBtcLnSwapAbs, ToBtcLnSwapState} from "./ToBtcLnSwapAbs";
|
|
3
|
-
import {MultichainData, SwapHandlerType} from "
|
|
4
|
-
import {ISwapPrice} from "
|
|
3
|
+
import {MultichainData, SwapHandlerType} from "../../SwapHandler";
|
|
4
|
+
import {ISwapPrice} from "../../../prices/ISwapPrice";
|
|
5
5
|
import {
|
|
6
6
|
BigIntBufferUtils,
|
|
7
7
|
ChainSwapType,
|
|
@@ -11,14 +11,14 @@ import {
|
|
|
11
11
|
SwapCommitStatus,
|
|
12
12
|
SwapData
|
|
13
13
|
} from "@atomiqlabs/base";
|
|
14
|
-
import {expressHandlerWrapper, HEX_REGEX, isDefinedRuntimeError} from "
|
|
15
|
-
import {PluginManager} from "
|
|
16
|
-
import {IIntermediaryStorage} from "
|
|
14
|
+
import {expressHandlerWrapper, getAbortController, HEX_REGEX, isDefinedRuntimeError} from "../../../utils/Utils";
|
|
15
|
+
import {PluginManager} from "../../../plugins/PluginManager";
|
|
16
|
+
import {IIntermediaryStorage} from "../../../storage/IIntermediaryStorage";
|
|
17
17
|
import {randomBytes} from "crypto";
|
|
18
|
-
import {serverParamDecoder} from "
|
|
19
|
-
import {IParamReader} from "
|
|
20
|
-
import {FieldTypeEnum, verifySchema} from "
|
|
21
|
-
import {ServerParamEncoder} from "
|
|
18
|
+
import {serverParamDecoder} from "../../../utils/paramcoders/server/ServerParamDecoder";
|
|
19
|
+
import {IParamReader} from "../../../utils/paramcoders/IParamReader";
|
|
20
|
+
import {FieldTypeEnum, verifySchema} from "../../../utils/paramcoders/SchemaVerifier";
|
|
21
|
+
import {ServerParamEncoder} from "../../../utils/paramcoders/server/ServerParamEncoder";
|
|
22
22
|
import {ToBtcBaseConfig, ToBtcBaseSwapHandler} from "../ToBtcBaseSwapHandler";
|
|
23
23
|
import {
|
|
24
24
|
ILightningWallet,
|
|
@@ -27,7 +27,8 @@ import {
|
|
|
27
27
|
ProbeAndRouteInit,
|
|
28
28
|
ProbeAndRouteResponse,
|
|
29
29
|
routesMatch
|
|
30
|
-
} from "
|
|
30
|
+
} from "../../../wallets/ILightningWallet";
|
|
31
|
+
import { LightningAssertions } from "../../assertions/LightningAssertions";
|
|
31
32
|
|
|
32
33
|
export type ToBtcLnConfig = ToBtcBaseConfig & {
|
|
33
34
|
routingFeeMultiplier: bigint,
|
|
@@ -86,13 +87,8 @@ export type ToBtcLnRequestType = {
|
|
|
86
87
|
* Swap handler handling to BTCLN swaps using submarine swaps
|
|
87
88
|
*/
|
|
88
89
|
export class ToBtcLnAbs extends ToBtcBaseSwapHandler<ToBtcLnSwapAbs, ToBtcLnSwapState> {
|
|
89
|
-
protected readonly LIGHTNING_LIQUIDITY_CACHE_TIMEOUT = 5*1000;
|
|
90
90
|
|
|
91
91
|
activeSubscriptions: Set<string> = new Set<string>();
|
|
92
|
-
lightningLiquidityCache: {
|
|
93
|
-
liquidity: bigint,
|
|
94
|
-
timestamp: number
|
|
95
|
-
};
|
|
96
92
|
|
|
97
93
|
readonly type = SwapHandlerType.TO_BTCLN;
|
|
98
94
|
readonly swapType = ChainSwapType.HTLC;
|
|
@@ -104,6 +100,7 @@ export class ToBtcLnAbs extends ToBtcBaseSwapHandler<ToBtcLnSwapAbs, ToBtcLnSwap
|
|
|
104
100
|
} = {};
|
|
105
101
|
|
|
106
102
|
readonly lightning: ILightningWallet;
|
|
103
|
+
readonly LightningAssertions: LightningAssertions;
|
|
107
104
|
|
|
108
105
|
constructor(
|
|
109
106
|
storageDirectory: IIntermediaryStorage<ToBtcLnSwapAbs>,
|
|
@@ -113,8 +110,9 @@ export class ToBtcLnAbs extends ToBtcBaseSwapHandler<ToBtcLnSwapAbs, ToBtcLnSwap
|
|
|
113
110
|
swapPricing: ISwapPrice,
|
|
114
111
|
config: ToBtcLnConfig
|
|
115
112
|
) {
|
|
116
|
-
super(storageDirectory, path, chainData, swapPricing);
|
|
113
|
+
super(storageDirectory, path, chainData, swapPricing, config);
|
|
117
114
|
this.lightning = lightning;
|
|
115
|
+
this.LightningAssertions = new LightningAssertions(this.logger, lightning);
|
|
118
116
|
const anyConfig = config as any;
|
|
119
117
|
anyConfig.minTsSendCltv = config.gracePeriod + (config.bitcoinBlocktime * config.minSendCltv * config.safetyFactor);
|
|
120
118
|
this.config = anyConfig;
|
|
@@ -522,47 +520,6 @@ export class ToBtcLnAbs extends ToBtcBaseSwapHandler<ToBtcLnSwapAbs, ToBtcLnSwap
|
|
|
522
520
|
}
|
|
523
521
|
}
|
|
524
522
|
|
|
525
|
-
/**
|
|
526
|
-
* Checks if the prior payment with the same paymentHash exists
|
|
527
|
-
*
|
|
528
|
-
* @param paymentHash
|
|
529
|
-
* @param abortSignal
|
|
530
|
-
* @throws {DefinedRuntimeError} will throw an error if payment already exists
|
|
531
|
-
*/
|
|
532
|
-
private async checkPriorPayment(paymentHash: string, abortSignal: AbortSignal): Promise<void> {
|
|
533
|
-
const payment = await this.lightning.getPayment(paymentHash);
|
|
534
|
-
if(payment!=null) throw {
|
|
535
|
-
code: 20010,
|
|
536
|
-
msg: "Already processed"
|
|
537
|
-
};
|
|
538
|
-
abortSignal.throwIfAborted();
|
|
539
|
-
}
|
|
540
|
-
|
|
541
|
-
/**
|
|
542
|
-
* Checks if the underlying LND backend has enough liquidity in channels to honor the swap
|
|
543
|
-
*
|
|
544
|
-
* @param amount
|
|
545
|
-
* @param abortSignal
|
|
546
|
-
* @param useCached Whether to use cached liquidity values
|
|
547
|
-
* @throws {DefinedRuntimeError} will throw an error if there isn't enough liquidity
|
|
548
|
-
*/
|
|
549
|
-
private async checkLiquidity(amount: bigint, abortSignal: AbortSignal, useCached: boolean = false): Promise<void> {
|
|
550
|
-
if(!useCached || this.lightningLiquidityCache==null || this.lightningLiquidityCache.timestamp<Date.now()-this.LIGHTNING_LIQUIDITY_CACHE_TIMEOUT) {
|
|
551
|
-
const channelBalances = await this.lightning.getLightningBalance();
|
|
552
|
-
this.lightningLiquidityCache = {
|
|
553
|
-
liquidity: channelBalances.localBalance,
|
|
554
|
-
timestamp: Date.now()
|
|
555
|
-
}
|
|
556
|
-
}
|
|
557
|
-
if(amount > this.lightningLiquidityCache.liquidity) {
|
|
558
|
-
throw {
|
|
559
|
-
code: 20002,
|
|
560
|
-
msg: "Not enough liquidity"
|
|
561
|
-
};
|
|
562
|
-
}
|
|
563
|
-
abortSignal.throwIfAborted();
|
|
564
|
-
}
|
|
565
|
-
|
|
566
523
|
/**
|
|
567
524
|
* Estimates the routing fee & confidence by either probing or routing (if probing fails), the fee is also adjusted
|
|
568
525
|
* according to routing fee multiplier, and subject to minimums set in config
|
|
@@ -645,6 +602,8 @@ export class ToBtcLnAbs extends ToBtcBaseSwapHandler<ToBtcLnSwapAbs, ToBtcLnSwap
|
|
|
645
602
|
actualRoutingFee = maxFee;
|
|
646
603
|
}
|
|
647
604
|
|
|
605
|
+
this.logger.debug("checkAndGetNetworkFee(): network fee calculated, amount: "+amountBD.toString(10)+" fee: "+actualRoutingFee.toString(10));
|
|
606
|
+
|
|
648
607
|
return {
|
|
649
608
|
networkFee: actualRoutingFee,
|
|
650
609
|
confidence: probeOrRouteResp.confidence
|
|
@@ -822,7 +781,7 @@ export class ToBtcLnAbs extends ToBtcBaseSwapHandler<ToBtcLnSwapAbs, ToBtcLnSwap
|
|
|
822
781
|
} = {request: {}, times: {}};
|
|
823
782
|
|
|
824
783
|
const chainIdentifier = req.query.chain as string ?? this.chains.default;
|
|
825
|
-
const {swapContract, signer} = this.getChain(chainIdentifier);
|
|
784
|
+
const {swapContract, signer, chainInterface} = this.getChain(chainIdentifier);
|
|
826
785
|
|
|
827
786
|
metadata.times.requestReceived = Date.now();
|
|
828
787
|
/**
|
|
@@ -847,7 +806,7 @@ export class ToBtcLnAbs extends ToBtcBaseSwapHandler<ToBtcLnSwapAbs, ToBtcLnSwap
|
|
|
847
806
|
this.isTokenSupported(chainIdentifier, val) ? val : null,
|
|
848
807
|
offerer: (val: string) => val!=null &&
|
|
849
808
|
typeof(val)==="string" &&
|
|
850
|
-
|
|
809
|
+
chainInterface.isValidAddress(val) ? val : null,
|
|
851
810
|
exactIn: FieldTypeEnum.BooleanOptional,
|
|
852
811
|
amount: FieldTypeEnum.BigIntOptional
|
|
853
812
|
});
|
|
@@ -879,19 +838,20 @@ export class ToBtcLnAbs extends ToBtcBaseSwapHandler<ToBtcLnSwapAbs, ToBtcLnSwap
|
|
|
879
838
|
const {parsedPR, halfConfidence} = await this.checkPaymentRequest(chainIdentifier, parsedBody.pr);
|
|
880
839
|
const requestedAmount = {
|
|
881
840
|
input: !!parsedBody.exactIn,
|
|
882
|
-
amount: !!parsedBody.exactIn ? parsedBody.amount : (parsedPR.mtokens + 999n) / 1000n
|
|
841
|
+
amount: !!parsedBody.exactIn ? parsedBody.amount : (parsedPR.mtokens + 999n) / 1000n,
|
|
842
|
+
token: useToken
|
|
883
843
|
};
|
|
884
|
-
const fees = await this.
|
|
844
|
+
const fees = await this.AmountAssertions.preCheckToBtcAmounts(this.type, request, requestedAmount);
|
|
885
845
|
metadata.times.requestChecked = Date.now();
|
|
886
846
|
|
|
887
847
|
//Create abort controller for parallel pre-fetches
|
|
888
|
-
const abortController =
|
|
848
|
+
const abortController = getAbortController(responseStream);
|
|
889
849
|
|
|
890
850
|
//Pre-fetch
|
|
891
851
|
const {pricePrefetchPromise, signDataPrefetchPromise} = this.getToBtcPrefetches(chainIdentifier, useToken, responseStream, abortController);
|
|
892
852
|
|
|
893
853
|
//Check if prior payment has been made
|
|
894
|
-
await this.checkPriorPayment(parsedPR.id, abortController.signal);
|
|
854
|
+
await this.LightningAssertions.checkPriorPayment(parsedPR.id, abortController.signal);
|
|
895
855
|
metadata.times.priorPaymentChecked = Date.now();
|
|
896
856
|
|
|
897
857
|
//Check amounts
|
|
@@ -902,9 +862,9 @@ export class ToBtcLnAbs extends ToBtcBaseSwapHandler<ToBtcLnSwapAbs, ToBtcLnSwap
|
|
|
902
862
|
swapFee,
|
|
903
863
|
swapFeeInToken,
|
|
904
864
|
networkFeeInToken
|
|
905
|
-
} = await this.checkToBtcAmount(request, requestedAmount,
|
|
865
|
+
} = await this.AmountAssertions.checkToBtcAmount(this.type, request, {...requestedAmount, pricePrefetch: pricePrefetchPromise}, fees, async (amountBD: bigint) => {
|
|
906
866
|
//Check if we have enough liquidity to process the swap
|
|
907
|
-
await this.checkLiquidity(amountBD, abortController.signal, true);
|
|
867
|
+
await this.LightningAssertions.checkLiquidity(amountBD, abortController.signal, true);
|
|
908
868
|
metadata.times.liquidityChecked = Date.now();
|
|
909
869
|
|
|
910
870
|
const maxFee = parsedBody.exactIn ?
|
|
@@ -912,7 +872,7 @@ export class ToBtcLnAbs extends ToBtcBaseSwapHandler<ToBtcLnSwapAbs, ToBtcLnSwap
|
|
|
912
872
|
parsedBody.maxFee;
|
|
913
873
|
|
|
914
874
|
return await this.checkAndGetNetworkFee(amountBD, maxFee, parsedBody.expiryTimestamp, currentTimestamp, parsedBody.pr, metadata, abortController.signal);
|
|
915
|
-
}, abortController.signal
|
|
875
|
+
}, abortController.signal);
|
|
916
876
|
metadata.times.priceCalculated = Date.now();
|
|
917
877
|
|
|
918
878
|
//For exactIn swap, just save and wait for the actual invoice to be submitted
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {SwapData} from "@atomiqlabs/base";
|
|
2
|
-
import {SwapHandlerType} from "
|
|
3
|
-
import {deserializeBN} from "
|
|
2
|
+
import {SwapHandlerType} from "../../../index";
|
|
3
|
+
import {deserializeBN} from "../../../utils/Utils";
|
|
4
4
|
import {ToBtcBaseSwap} from "../ToBtcBaseSwap";
|
|
5
5
|
|
|
6
6
|
export enum ToBtcLnSwapState {
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Lockable,
|
|
3
|
+
SpvVaultClaimEvent,
|
|
4
|
+
SpvVaultCloseEvent,
|
|
5
|
+
SpvVaultData,
|
|
6
|
+
SpvVaultDepositEvent,
|
|
7
|
+
SpvVaultOpenEvent,
|
|
8
|
+
SpvVaultTokenBalance,
|
|
9
|
+
SpvWithdrawalTransactionData,
|
|
10
|
+
StorageObject
|
|
11
|
+
} from "@atomiqlabs/base";
|
|
12
|
+
|
|
13
|
+
export enum SpvVaultState {
|
|
14
|
+
CLOSED = -1,
|
|
15
|
+
BTC_INITIATED = 0,
|
|
16
|
+
BTC_CONFIRMED = 1,
|
|
17
|
+
OPENED = 2
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export class SpvVault<
|
|
21
|
+
D extends SpvWithdrawalTransactionData = SpvWithdrawalTransactionData,
|
|
22
|
+
T extends SpvVaultData = SpvVaultData
|
|
23
|
+
> extends Lockable implements StorageObject {
|
|
24
|
+
|
|
25
|
+
readonly chainId: string;
|
|
26
|
+
|
|
27
|
+
readonly initialUtxo: string;
|
|
28
|
+
readonly btcAddress: string;
|
|
29
|
+
|
|
30
|
+
readonly pendingWithdrawals: D[];
|
|
31
|
+
data: T;
|
|
32
|
+
|
|
33
|
+
state: SpvVaultState;
|
|
34
|
+
|
|
35
|
+
balances: SpvVaultTokenBalance[];
|
|
36
|
+
|
|
37
|
+
scOpenTx: {txId: string, rawTx: string};
|
|
38
|
+
|
|
39
|
+
constructor(chainId: string, vault: T, btcAddress: string);
|
|
40
|
+
constructor(obj: any);
|
|
41
|
+
constructor(chainIdOrObj: string | any, vault?: T, btcAddress?: string) {
|
|
42
|
+
super();
|
|
43
|
+
if(typeof(chainIdOrObj)==="string") {
|
|
44
|
+
this.state = SpvVaultState.BTC_INITIATED;
|
|
45
|
+
this.chainId = chainIdOrObj;
|
|
46
|
+
this.data = vault;
|
|
47
|
+
this.initialUtxo = vault.getUtxo();
|
|
48
|
+
this.btcAddress = btcAddress;
|
|
49
|
+
this.pendingWithdrawals = [];
|
|
50
|
+
} else {
|
|
51
|
+
this.state = chainIdOrObj.state;
|
|
52
|
+
this.chainId = chainIdOrObj.chainId;
|
|
53
|
+
this.data = SpvVaultData.deserialize<T>(chainIdOrObj.data);
|
|
54
|
+
this.initialUtxo = chainIdOrObj.initialUtxo;
|
|
55
|
+
this.btcAddress = chainIdOrObj.btcAddress;
|
|
56
|
+
this.pendingWithdrawals = chainIdOrObj.pendingWithdrawals.map(SpvWithdrawalTransactionData.deserialize<D>);
|
|
57
|
+
this.scOpenTx = chainIdOrObj.scOpenTx;
|
|
58
|
+
}
|
|
59
|
+
this.balances = this.data.calculateStateAfter(this.pendingWithdrawals).balances;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
update(event: SpvVaultOpenEvent | SpvVaultDepositEvent | SpvVaultCloseEvent | SpvVaultClaimEvent): void {
|
|
63
|
+
if(event instanceof SpvVaultClaimEvent || event instanceof SpvVaultCloseEvent) {
|
|
64
|
+
const processedWithdrawalIndex = this.pendingWithdrawals.findIndex(val => val.btcTx.txid === event.btcTxId);
|
|
65
|
+
if(processedWithdrawalIndex!==-1) this.pendingWithdrawals.splice(0, processedWithdrawalIndex + 1);
|
|
66
|
+
}
|
|
67
|
+
this.data.updateState(event);
|
|
68
|
+
this.balances = this.data.calculateStateAfter(this.pendingWithdrawals).balances;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
addWithdrawal(withdrawalData: D): void {
|
|
72
|
+
//Make sure this is a valid state transition before adding the tx to pending withdrawals
|
|
73
|
+
this.balances = this.data.calculateStateAfter([...this.pendingWithdrawals, withdrawalData]).balances;
|
|
74
|
+
this.pendingWithdrawals.push(withdrawalData);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
removeWithdrawal(withdrawalData: D): boolean {
|
|
78
|
+
const index = this.pendingWithdrawals.indexOf(withdrawalData);
|
|
79
|
+
if(index===-1) return false;
|
|
80
|
+
this.pendingWithdrawals.splice(index, 1);
|
|
81
|
+
this.balances = this.data.calculateStateAfter(this.pendingWithdrawals).balances;
|
|
82
|
+
return true;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
toRawAmounts(amounts: bigint[]): bigint[] {
|
|
86
|
+
return amounts.map((amt, index) => {
|
|
87
|
+
const tokenData = this.data.getTokenData()[index];
|
|
88
|
+
if(tokenData==null) throw new Error("Amount index out of bounds!");
|
|
89
|
+
return amt / tokenData.multiplier;
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
fromRawAmounts(rawAmounts: bigint[]): bigint[] {
|
|
94
|
+
return rawAmounts.map((amt, index) => {
|
|
95
|
+
const tokenData = this.data.getTokenData()[index];
|
|
96
|
+
if(tokenData==null) throw new Error("Amount index out of bounds!");
|
|
97
|
+
return amt * tokenData.multiplier;
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Returns the vault balance after processing all currently confirmed (at least 1 btc confirmation) withdrawals
|
|
103
|
+
*/
|
|
104
|
+
getConfirmedBalance(): SpvVaultTokenBalance[] {
|
|
105
|
+
return this.data.calculateStateAfter(this.pendingWithdrawals.filter(val => val.btcTx.confirmations>=1)).balances;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
serialize(): any {
|
|
109
|
+
return {
|
|
110
|
+
state: this.state,
|
|
111
|
+
chainId: this.chainId,
|
|
112
|
+
data: this.data.serialize(),
|
|
113
|
+
initialUtxo: this.initialUtxo,
|
|
114
|
+
btcAddress: this.btcAddress,
|
|
115
|
+
pendingWithdrawals: this.pendingWithdrawals.map(val => val.serialize()),
|
|
116
|
+
scOpenTx: this.scOpenTx
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
getIdentifier(): string {
|
|
121
|
+
return this.chainId+"_"+this.data.getOwner()+"_"+this.data.getVaultId().toString(10);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Returns the latest vault utxo
|
|
126
|
+
*/
|
|
127
|
+
getLatestUtxo(): string {
|
|
128
|
+
if(this.pendingWithdrawals.length===0) {
|
|
129
|
+
return this.data.getUtxo();
|
|
130
|
+
}
|
|
131
|
+
const latestWithdrawal = this.pendingWithdrawals[this.pendingWithdrawals.length - 1];
|
|
132
|
+
if(latestWithdrawal.btcTx.confirmations>=1) return latestWithdrawal.btcTx.txid+":0";
|
|
133
|
+
return null;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Returns whether the vault is ready for the next swap
|
|
138
|
+
*/
|
|
139
|
+
isReady(): boolean {
|
|
140
|
+
return this.data.isOpened() && this.getLatestUtxo()!=null;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
}
|