@atomiqlabs/lp-lib 15.0.13 → 16.0.0
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 +2 -0
- package/dist/index.js +2 -0
- package/dist/info/InfoHandler.js +0 -3
- package/dist/plugins/IPlugin.d.ts +2 -2
- package/dist/plugins/PluginManager.d.ts +2 -2
- package/dist/storagemanager/IntermediaryStorageManager.d.ts +1 -0
- package/dist/storagemanager/IntermediaryStorageManager.js +9 -2
- package/dist/storagemanager/StorageManager.d.ts +1 -0
- package/dist/storagemanager/StorageManager.js +9 -2
- package/dist/swaps/SwapHandler.d.ts +4 -10
- package/dist/swaps/SwapHandler.js +4 -13
- package/dist/swaps/assertions/FromBtcAmountAssertions.d.ts +2 -2
- package/dist/swaps/assertions/FromBtcAmountAssertions.js +13 -5
- package/dist/swaps/escrow/EscrowHandlerSwap.js +2 -2
- package/dist/swaps/escrow/FromBtcBaseSwapHandler.d.ts +2 -1
- package/dist/swaps/escrow/FromBtcBaseSwapHandler.js +8 -5
- package/dist/swaps/escrow/frombtc_abstract/FromBtcAbs.js +2 -2
- package/dist/swaps/escrow/frombtcln_abstract/FromBtcLnAbs.js +11 -13
- package/dist/swaps/escrow/frombtcln_abstract/FromBtcLnSwapAbs.d.ts +1 -0
- package/dist/swaps/escrow/frombtcln_abstract/FromBtcLnSwapAbs.js +3 -0
- package/dist/swaps/escrow/frombtcln_autoinit/FromBtcLnAuto.d.ts +111 -0
- package/dist/swaps/escrow/frombtcln_autoinit/FromBtcLnAuto.js +682 -0
- package/dist/swaps/escrow/frombtcln_autoinit/FromBtcLnAutoSwap.d.ts +55 -0
- package/dist/swaps/escrow/frombtcln_autoinit/FromBtcLnAutoSwap.js +120 -0
- package/dist/swaps/escrow/tobtc_abstract/ToBtcAbs.d.ts +0 -2
- package/dist/swaps/escrow/tobtc_abstract/ToBtcAbs.js +44 -27
- package/dist/swaps/escrow/tobtcln_abstract/ToBtcLnAbs.js +12 -10
- package/dist/swaps/spv_vault_swap/SpvVault.d.ts +2 -3
- package/dist/swaps/spv_vault_swap/SpvVault.js +2 -2
- package/dist/swaps/spv_vault_swap/SpvVaultSwapHandler.js +10 -8
- package/dist/swaps/spv_vault_swap/SpvVaults.d.ts +4 -9
- package/dist/swaps/spv_vault_swap/SpvVaults.js +114 -80
- package/dist/swaps/trusted/frombtc_trusted/FromBtcTrusted.js +3 -3
- package/dist/swaps/trusted/frombtcln_trusted/FromBtcLnTrusted.js +14 -17
- package/dist/utils/Utils.d.ts +7 -7
- package/dist/utils/Utils.js +12 -11
- package/dist/utils/paramcoders/server/ServerParamDecoder.js +8 -6
- package/dist/wallets/IBitcoinWallet.d.ts +7 -0
- package/package.json +3 -3
- package/src/index.ts +2 -0
- package/src/info/InfoHandler.ts +0 -6
- package/src/plugins/IPlugin.ts +2 -2
- package/src/plugins/PluginManager.ts +2 -2
- package/src/storagemanager/IntermediaryStorageManager.ts +11 -2
- package/src/storagemanager/StorageManager.ts +12 -2
- package/src/swaps/SwapHandler.ts +6 -17
- package/src/swaps/assertions/FromBtcAmountAssertions.ts +16 -8
- package/src/swaps/escrow/EscrowHandlerSwap.ts +2 -2
- package/src/swaps/escrow/FromBtcBaseSwapHandler.ts +8 -5
- package/src/swaps/escrow/frombtc_abstract/FromBtcAbs.ts +2 -2
- package/src/swaps/escrow/frombtcln_abstract/FromBtcLnAbs.ts +11 -12
- package/src/swaps/escrow/frombtcln_abstract/FromBtcLnSwapAbs.ts +4 -0
- package/src/swaps/escrow/frombtcln_autoinit/FromBtcLnAuto.ts +847 -0
- package/src/swaps/escrow/frombtcln_autoinit/FromBtcLnAutoSwap.ts +196 -0
- package/src/swaps/escrow/tobtc_abstract/ToBtcAbs.ts +55 -36
- package/src/swaps/escrow/tobtcln_abstract/ToBtcLnAbs.ts +19 -15
- package/src/swaps/spv_vault_swap/SpvVault.ts +3 -3
- package/src/swaps/spv_vault_swap/SpvVaultSwapHandler.ts +10 -8
- package/src/swaps/spv_vault_swap/SpvVaults.ts +130 -91
- package/src/swaps/trusted/frombtc_trusted/FromBtcTrusted.ts +3 -3
- package/src/swaps/trusted/frombtcln_trusted/FromBtcLnTrusted.ts +13 -16
- package/src/utils/Utils.ts +19 -17
- package/src/utils/paramcoders/server/ServerParamDecoder.ts +9 -6
- package/src/wallets/IBitcoinWallet.ts +8 -0
- package/dist/wallets/ISpvVaultWallet.d.ts +0 -42
- package/dist/wallets/ISpvVaultWallet.js +0 -2
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { SwapData } from "@atomiqlabs/base";
|
|
2
|
+
import { FromBtcBaseSwap } from "../FromBtcBaseSwap";
|
|
3
|
+
export declare enum FromBtcLnAutoSwapState {
|
|
4
|
+
REFUNDED = -2,
|
|
5
|
+
CANCELED = -1,
|
|
6
|
+
CREATED = 0,
|
|
7
|
+
RECEIVED = 1,
|
|
8
|
+
TXS_SENT = 2,
|
|
9
|
+
COMMITED = 3,
|
|
10
|
+
CLAIMED = 4,
|
|
11
|
+
SETTLED = 5
|
|
12
|
+
}
|
|
13
|
+
export declare class FromBtcLnAutoSwap<T extends SwapData = SwapData> extends FromBtcBaseSwap<T, FromBtcLnAutoSwapState> {
|
|
14
|
+
readonly pr: string;
|
|
15
|
+
readonly lnPaymentHash: string;
|
|
16
|
+
readonly claimHash: string;
|
|
17
|
+
readonly claimer: string;
|
|
18
|
+
readonly token: string;
|
|
19
|
+
readonly gasToken: string;
|
|
20
|
+
readonly amountToken: bigint;
|
|
21
|
+
readonly amountGasToken: bigint;
|
|
22
|
+
readonly tokenSwapFee: bigint;
|
|
23
|
+
readonly tokenSwapFeeInToken: bigint;
|
|
24
|
+
readonly gasSwapFee: bigint;
|
|
25
|
+
readonly gasSwapFeeInToken: bigint;
|
|
26
|
+
readonly claimerBounty: bigint;
|
|
27
|
+
secret: string;
|
|
28
|
+
constructor(chainIdentifier: string, pr: string, lnPaymentHash: string, claimHash: string, amountMtokens: bigint, claimer: string, token: string, gasToken: string, amountToken: bigint, amountGasToken: bigint, tokenSwapFee: bigint, tokenSwapFeeInToken: bigint, gasSwapFee: bigint, gasSwapFeeInToken: bigint, claimerBounty: bigint);
|
|
29
|
+
constructor(obj: any);
|
|
30
|
+
serialize(): any;
|
|
31
|
+
getClaimHash(): string;
|
|
32
|
+
getIdentifierHash(): string;
|
|
33
|
+
getOutputGasAmount(): bigint;
|
|
34
|
+
getOutputAmount(): bigint;
|
|
35
|
+
getTotalOutputAmount(): bigint;
|
|
36
|
+
getTotalOutputGasAmount(): bigint;
|
|
37
|
+
getSequence(): bigint;
|
|
38
|
+
getSwapFee(): {
|
|
39
|
+
inInputToken: bigint;
|
|
40
|
+
inOutputToken: bigint;
|
|
41
|
+
};
|
|
42
|
+
getTokenSwapFee(): {
|
|
43
|
+
inInputToken: bigint;
|
|
44
|
+
inOutputToken: bigint;
|
|
45
|
+
};
|
|
46
|
+
getGasSwapFee(): {
|
|
47
|
+
inInputToken: bigint;
|
|
48
|
+
inOutputToken: bigint;
|
|
49
|
+
};
|
|
50
|
+
getToken(): string;
|
|
51
|
+
getGasToken(): string;
|
|
52
|
+
isInitiated(): boolean;
|
|
53
|
+
isFailed(): boolean;
|
|
54
|
+
isSuccess(): boolean;
|
|
55
|
+
}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.FromBtcLnAutoSwap = exports.FromBtcLnAutoSwapState = void 0;
|
|
4
|
+
const index_1 = require("../../../index");
|
|
5
|
+
const FromBtcBaseSwap_1 = require("../FromBtcBaseSwap");
|
|
6
|
+
const Utils_1 = require("../../../utils/Utils");
|
|
7
|
+
var FromBtcLnAutoSwapState;
|
|
8
|
+
(function (FromBtcLnAutoSwapState) {
|
|
9
|
+
FromBtcLnAutoSwapState[FromBtcLnAutoSwapState["REFUNDED"] = -2] = "REFUNDED";
|
|
10
|
+
FromBtcLnAutoSwapState[FromBtcLnAutoSwapState["CANCELED"] = -1] = "CANCELED";
|
|
11
|
+
FromBtcLnAutoSwapState[FromBtcLnAutoSwapState["CREATED"] = 0] = "CREATED";
|
|
12
|
+
FromBtcLnAutoSwapState[FromBtcLnAutoSwapState["RECEIVED"] = 1] = "RECEIVED";
|
|
13
|
+
FromBtcLnAutoSwapState[FromBtcLnAutoSwapState["TXS_SENT"] = 2] = "TXS_SENT";
|
|
14
|
+
FromBtcLnAutoSwapState[FromBtcLnAutoSwapState["COMMITED"] = 3] = "COMMITED";
|
|
15
|
+
FromBtcLnAutoSwapState[FromBtcLnAutoSwapState["CLAIMED"] = 4] = "CLAIMED";
|
|
16
|
+
FromBtcLnAutoSwapState[FromBtcLnAutoSwapState["SETTLED"] = 5] = "SETTLED";
|
|
17
|
+
})(FromBtcLnAutoSwapState = exports.FromBtcLnAutoSwapState || (exports.FromBtcLnAutoSwapState = {}));
|
|
18
|
+
class FromBtcLnAutoSwap extends FromBtcBaseSwap_1.FromBtcBaseSwap {
|
|
19
|
+
constructor(chainIdOrObj, pr, lnPaymentHash, claimHash, amountMtokens, claimer, token, gasToken, amountToken, amountGasToken, tokenSwapFee, tokenSwapFeeInToken, gasSwapFee, gasSwapFeeInToken, claimerBounty) {
|
|
20
|
+
if (typeof (chainIdOrObj) === "string") {
|
|
21
|
+
super(chainIdOrObj, (amountMtokens + 999n) / 1000n, tokenSwapFee + gasSwapFee, tokenSwapFeeInToken);
|
|
22
|
+
this.state = FromBtcLnAutoSwapState.CREATED;
|
|
23
|
+
this.pr = pr;
|
|
24
|
+
this.lnPaymentHash = lnPaymentHash;
|
|
25
|
+
this.claimHash = claimHash;
|
|
26
|
+
this.claimer = claimer;
|
|
27
|
+
this.token = token;
|
|
28
|
+
this.gasToken = gasToken;
|
|
29
|
+
this.amountToken = amountToken;
|
|
30
|
+
this.amountGasToken = amountGasToken;
|
|
31
|
+
this.tokenSwapFee = tokenSwapFee;
|
|
32
|
+
this.tokenSwapFeeInToken = tokenSwapFeeInToken;
|
|
33
|
+
this.gasSwapFee = gasSwapFee;
|
|
34
|
+
this.gasSwapFeeInToken = gasSwapFeeInToken;
|
|
35
|
+
this.claimerBounty = claimerBounty;
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
super(chainIdOrObj);
|
|
39
|
+
this.pr = chainIdOrObj.pr;
|
|
40
|
+
this.lnPaymentHash = chainIdOrObj.lnPaymentHash;
|
|
41
|
+
this.claimHash = chainIdOrObj.claimHash;
|
|
42
|
+
this.claimer = chainIdOrObj.claimer;
|
|
43
|
+
this.token = chainIdOrObj.token;
|
|
44
|
+
this.gasToken = chainIdOrObj.gasToken;
|
|
45
|
+
this.amountToken = (0, Utils_1.deserializeBN)(chainIdOrObj.amountToken);
|
|
46
|
+
this.amountGasToken = (0, Utils_1.deserializeBN)(chainIdOrObj.amountGasToken);
|
|
47
|
+
this.tokenSwapFee = (0, Utils_1.deserializeBN)(chainIdOrObj.tokenSwapFee);
|
|
48
|
+
this.tokenSwapFeeInToken = (0, Utils_1.deserializeBN)(chainIdOrObj.tokenSwapFeeInToken);
|
|
49
|
+
this.gasSwapFee = (0, Utils_1.deserializeBN)(chainIdOrObj.gasSwapFee);
|
|
50
|
+
this.gasSwapFeeInToken = (0, Utils_1.deserializeBN)(chainIdOrObj.gasSwapFeeInToken);
|
|
51
|
+
this.claimerBounty = (0, Utils_1.deserializeBN)(chainIdOrObj.claimerBounty);
|
|
52
|
+
this.secret = chainIdOrObj.secret;
|
|
53
|
+
}
|
|
54
|
+
this.type = index_1.SwapHandlerType.FROM_BTCLN_AUTO;
|
|
55
|
+
}
|
|
56
|
+
serialize() {
|
|
57
|
+
const partialSerialized = super.serialize();
|
|
58
|
+
partialSerialized.pr = this.pr;
|
|
59
|
+
partialSerialized.secret = this.secret;
|
|
60
|
+
partialSerialized.lnPaymentHash = this.lnPaymentHash;
|
|
61
|
+
partialSerialized.claimHash = this.claimHash;
|
|
62
|
+
partialSerialized.claimer = this.claimer;
|
|
63
|
+
partialSerialized.token = this.token;
|
|
64
|
+
partialSerialized.gasToken = this.gasToken;
|
|
65
|
+
partialSerialized.amountToken = (0, Utils_1.serializeBN)(this.amountToken);
|
|
66
|
+
partialSerialized.amountGasToken = (0, Utils_1.serializeBN)(this.amountGasToken);
|
|
67
|
+
partialSerialized.tokenSwapFee = (0, Utils_1.serializeBN)(this.tokenSwapFee);
|
|
68
|
+
partialSerialized.tokenSwapFeeInToken = (0, Utils_1.serializeBN)(this.tokenSwapFeeInToken);
|
|
69
|
+
partialSerialized.gasSwapFee = (0, Utils_1.serializeBN)(this.gasSwapFee);
|
|
70
|
+
partialSerialized.gasSwapFeeInToken = (0, Utils_1.serializeBN)(this.gasSwapFeeInToken);
|
|
71
|
+
partialSerialized.claimerBounty = (0, Utils_1.serializeBN)(this.claimerBounty);
|
|
72
|
+
return partialSerialized;
|
|
73
|
+
}
|
|
74
|
+
getClaimHash() {
|
|
75
|
+
return this.claimHash;
|
|
76
|
+
}
|
|
77
|
+
getIdentifierHash() {
|
|
78
|
+
return this.lnPaymentHash;
|
|
79
|
+
}
|
|
80
|
+
getOutputGasAmount() {
|
|
81
|
+
return this.amountGasToken;
|
|
82
|
+
}
|
|
83
|
+
getOutputAmount() {
|
|
84
|
+
return this.amountToken;
|
|
85
|
+
}
|
|
86
|
+
getTotalOutputAmount() {
|
|
87
|
+
return this.amountToken;
|
|
88
|
+
}
|
|
89
|
+
getTotalOutputGasAmount() {
|
|
90
|
+
return this.amountGasToken + this.claimerBounty;
|
|
91
|
+
}
|
|
92
|
+
getSequence() {
|
|
93
|
+
return 0n;
|
|
94
|
+
}
|
|
95
|
+
getSwapFee() {
|
|
96
|
+
return { inInputToken: this.swapFee, inOutputToken: this.swapFeeInToken };
|
|
97
|
+
}
|
|
98
|
+
getTokenSwapFee() {
|
|
99
|
+
return { inInputToken: this.tokenSwapFee, inOutputToken: this.tokenSwapFeeInToken };
|
|
100
|
+
}
|
|
101
|
+
getGasSwapFee() {
|
|
102
|
+
return { inInputToken: this.gasSwapFee, inOutputToken: this.gasSwapFeeInToken };
|
|
103
|
+
}
|
|
104
|
+
getToken() {
|
|
105
|
+
return this.token;
|
|
106
|
+
}
|
|
107
|
+
getGasToken() {
|
|
108
|
+
return this.gasToken;
|
|
109
|
+
}
|
|
110
|
+
isInitiated() {
|
|
111
|
+
return this.state !== FromBtcLnAutoSwapState.CREATED;
|
|
112
|
+
}
|
|
113
|
+
isFailed() {
|
|
114
|
+
return this.state === FromBtcLnAutoSwapState.CANCELED || this.state === FromBtcLnAutoSwapState.REFUNDED;
|
|
115
|
+
}
|
|
116
|
+
isSuccess() {
|
|
117
|
+
return this.state === FromBtcLnAutoSwapState.SETTLED;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
exports.FromBtcLnAutoSwap = FromBtcLnAutoSwap;
|
|
@@ -5,7 +5,6 @@ import { ISwapPrice } from "../../../prices/ISwapPrice";
|
|
|
5
5
|
import { BtcTx, ChainSwapType, ClaimEvent, InitializeEvent, RefundEvent, SwapData, BitcoinRpc, BtcBlock } from "@atomiqlabs/base";
|
|
6
6
|
import { IIntermediaryStorage } from "../../../storage/IIntermediaryStorage";
|
|
7
7
|
import { ToBtcBaseConfig, ToBtcBaseSwapHandler } from "../ToBtcBaseSwapHandler";
|
|
8
|
-
import { PromiseQueue } from "promise-queue-ts";
|
|
9
8
|
import { IBitcoinWallet } from "../../../wallets/IBitcoinWallet";
|
|
10
9
|
export type ToBtcConfig = ToBtcBaseConfig & {
|
|
11
10
|
sendSafetyFactor: bigint;
|
|
@@ -38,7 +37,6 @@ export declare class ToBtcAbs extends ToBtcBaseSwapHandler<ToBtcSwapAbs, ToBtcSw
|
|
|
38
37
|
};
|
|
39
38
|
bitcoinRpc: BitcoinRpc<BtcBlock>;
|
|
40
39
|
bitcoin: IBitcoinWallet;
|
|
41
|
-
sendBtcQueue: PromiseQueue;
|
|
42
40
|
readonly config: ToBtcConfig;
|
|
43
41
|
constructor(storageDirectory: IIntermediaryStorage<ToBtcSwapAbs>, path: string, chainData: MultichainData, bitcoin: IBitcoinWallet, swapPricing: ISwapPrice, bitcoinRpc: BitcoinRpc<BtcBlock>, config: ToBtcConfig);
|
|
44
42
|
/**
|
|
@@ -10,9 +10,9 @@ const crypto_1 = require("crypto");
|
|
|
10
10
|
const SchemaVerifier_1 = require("../../../utils/paramcoders/SchemaVerifier");
|
|
11
11
|
const ServerParamDecoder_1 = require("../../../utils/paramcoders/server/ServerParamDecoder");
|
|
12
12
|
const ToBtcBaseSwapHandler_1 = require("../ToBtcBaseSwapHandler");
|
|
13
|
-
const promise_queue_ts_1 = require("promise-queue-ts");
|
|
14
13
|
const BitcoinUtils_1 = require("../../../utils/BitcoinUtils");
|
|
15
14
|
const OUTPUT_SCRIPT_MAX_LENGTH = 200;
|
|
15
|
+
const MAX_PARALLEL_TX_PROCESSED = 10;
|
|
16
16
|
/**
|
|
17
17
|
* Handler for to BTC swaps, utilizing PTLCs (proof-time locked contracts) using btc relay (on-chain bitcoin SPV)
|
|
18
18
|
*/
|
|
@@ -22,7 +22,6 @@ class ToBtcAbs extends ToBtcBaseSwapHandler_1.ToBtcBaseSwapHandler {
|
|
|
22
22
|
this.type = SwapHandler_1.SwapHandlerType.TO_BTC;
|
|
23
23
|
this.swapType = base_1.ChainSwapType.CHAIN_NONCED;
|
|
24
24
|
this.activeSubscriptions = {};
|
|
25
|
-
this.sendBtcQueue = new promise_queue_ts_1.PromiseQueue();
|
|
26
25
|
this.bitcoinRpc = bitcoinRpc;
|
|
27
26
|
this.bitcoin = bitcoin;
|
|
28
27
|
this.config = config;
|
|
@@ -49,17 +48,25 @@ class ToBtcAbs extends ToBtcBaseSwapHandler_1.ToBtcBaseSwapHandler {
|
|
|
49
48
|
* @param vout
|
|
50
49
|
*/
|
|
51
50
|
async tryClaimSwap(tx, swap, vout) {
|
|
52
|
-
const { swapContract, signer } = this.getChain(swap.chainIdentifier);
|
|
51
|
+
const { chainInterface, swapContract, signer } = this.getChain(swap.chainIdentifier);
|
|
53
52
|
const blockHeader = await this.bitcoinRpc.getBlockHeader(tx.blockhash);
|
|
54
53
|
//Set flag that we are sending the transaction already, so we don't end up with race condition
|
|
54
|
+
if (swap.isLocked())
|
|
55
|
+
return false;
|
|
56
|
+
let txns;
|
|
57
|
+
try {
|
|
58
|
+
txns = await swapContract.txsClaimWithTxData(signer, swap.data, { ...tx, height: blockHeader.getHeight() }, swap.requiredConfirmations, vout, null, null, false);
|
|
59
|
+
}
|
|
60
|
+
catch (e) {
|
|
61
|
+
this.swapLogger.error(swap, "tryClaimSwap(): error occurred creating swap claim transactions, height: " + blockHeader.getHeight() + " utxo: " + tx.txid + ":" + vout + " address: " + swap.address, e);
|
|
62
|
+
return false;
|
|
63
|
+
}
|
|
55
64
|
const unlock = swap.lock(swapContract.claimWithTxDataTimeout);
|
|
56
65
|
if (unlock == null)
|
|
57
66
|
return false;
|
|
58
67
|
try {
|
|
59
68
|
this.swapLogger.debug(swap, "tryClaimSwap(): initiate claim of swap, height: " + blockHeader.getHeight() + " utxo: " + tx.txid + ":" + vout);
|
|
60
|
-
|
|
61
|
-
waitForConfirmation: true
|
|
62
|
-
});
|
|
69
|
+
await chainInterface.sendAndConfirm(signer, txns, true);
|
|
63
70
|
this.swapLogger.info(swap, "tryClaimSwap(): swap claimed successfully, height: " + blockHeader.getHeight() + " utxo: " + tx.txid + ":" + vout + " address: " + swap.address);
|
|
64
71
|
if (swap.metadata != null)
|
|
65
72
|
swap.metadata.times.txClaimed = Date.now();
|
|
@@ -171,22 +178,30 @@ class ToBtcAbs extends ToBtcBaseSwapHandler_1.ToBtcBaseSwapHandler {
|
|
|
171
178
|
*/
|
|
172
179
|
async processBtcTxs() {
|
|
173
180
|
const unsubscribeSwaps = [];
|
|
181
|
+
let promises = [];
|
|
174
182
|
for (let txId in this.activeSubscriptions) {
|
|
175
183
|
const swap = this.activeSubscriptions[txId];
|
|
176
184
|
//TODO: RBF the transaction if it's already taking too long to confirm
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
this.
|
|
183
|
-
|
|
185
|
+
promises.push((async () => {
|
|
186
|
+
try {
|
|
187
|
+
let tx = await this.bitcoin.getWalletTransaction(txId);
|
|
188
|
+
if (tx == null)
|
|
189
|
+
return;
|
|
190
|
+
if (await this.processBtcTx(swap, tx)) {
|
|
191
|
+
this.swapLogger.info(swap, "processBtcTxs(): swap claimed successfully, txId: " + tx.txid + " address: " + swap.address);
|
|
192
|
+
unsubscribeSwaps.push(swap);
|
|
193
|
+
}
|
|
184
194
|
}
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
195
|
+
catch (e) {
|
|
196
|
+
this.swapLogger.error(swap, "processBtcTxs(): error processing btc transaction", e);
|
|
197
|
+
}
|
|
198
|
+
})());
|
|
199
|
+
if (promises.length >= MAX_PARALLEL_TX_PROCESSED) {
|
|
200
|
+
await Promise.all(promises);
|
|
201
|
+
promises = [];
|
|
188
202
|
}
|
|
189
203
|
}
|
|
204
|
+
await Promise.all(promises);
|
|
190
205
|
unsubscribeSwaps.forEach(swap => {
|
|
191
206
|
this.unsubscribePayment(swap);
|
|
192
207
|
});
|
|
@@ -260,7 +275,7 @@ class ToBtcAbs extends ToBtcBaseSwapHandler_1.ToBtcBaseSwapHandler {
|
|
|
260
275
|
sendBitcoinPayment(swap) {
|
|
261
276
|
//Make sure that bitcoin payouts are processed sequentially to avoid race conditions between multiple payouts,
|
|
262
277
|
// e.g. that 2 payouts share the same input and would effectively double-spend each other
|
|
263
|
-
return this.
|
|
278
|
+
return this.bitcoin.execute(async () => {
|
|
264
279
|
//Run checks
|
|
265
280
|
this.checkExpiresTooSoon(swap);
|
|
266
281
|
if (swap.metadata != null)
|
|
@@ -502,7 +517,7 @@ class ToBtcAbs extends ToBtcBaseSwapHandler_1.ToBtcBaseSwapHandler {
|
|
|
502
517
|
restServer.use(this.path + "/payInvoice", (0, ServerParamDecoder_1.serverParamDecoder)(10 * 1000));
|
|
503
518
|
restServer.post(this.path + "/payInvoice", (0, Utils_1.expressHandlerWrapper)(async (req, res) => {
|
|
504
519
|
const metadata = { request: {}, times: {} };
|
|
505
|
-
const chainIdentifier = req.query.chain
|
|
520
|
+
const chainIdentifier = req.query.chain;
|
|
506
521
|
const { swapContract, signer, chainInterface } = this.getChain(chainIdentifier);
|
|
507
522
|
metadata.times.requestReceived = Date.now();
|
|
508
523
|
/**
|
|
@@ -530,7 +545,7 @@ class ToBtcAbs extends ToBtcBaseSwapHandler_1.ToBtcBaseSwapHandler {
|
|
|
530
545
|
this.isTokenSupported(chainIdentifier, val) ? val : null,
|
|
531
546
|
offerer: (val) => val != null &&
|
|
532
547
|
typeof (val) === "string" &&
|
|
533
|
-
chainInterface.isValidAddress(val) ? val : null,
|
|
548
|
+
chainInterface.isValidAddress(val, true) ? val : null,
|
|
534
549
|
exactIn: SchemaVerifier_1.FieldTypeEnum.BooleanOptional
|
|
535
550
|
});
|
|
536
551
|
if (parsedBody == null)
|
|
@@ -631,21 +646,23 @@ class ToBtcAbs extends ToBtcBaseSwapHandler_1.ToBtcBaseSwapHandler {
|
|
|
631
646
|
msg: "Payment not found"
|
|
632
647
|
};
|
|
633
648
|
await this.checkExpired(payment);
|
|
634
|
-
if (payment.state === ToBtcSwapAbs_1.ToBtcSwapState.COMMITED)
|
|
635
|
-
|
|
636
|
-
_httpStatus: 200,
|
|
649
|
+
if (payment.state === ToBtcSwapAbs_1.ToBtcSwapState.COMMITED) {
|
|
650
|
+
res.status(200).json({
|
|
637
651
|
code: 20008,
|
|
638
652
|
msg: "Payment processing"
|
|
639
|
-
};
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
653
|
+
});
|
|
654
|
+
return;
|
|
655
|
+
}
|
|
656
|
+
if (payment.state === ToBtcSwapAbs_1.ToBtcSwapState.BTC_SENT || payment.state === ToBtcSwapAbs_1.ToBtcSwapState.BTC_SENDING) {
|
|
657
|
+
res.status(200).json({
|
|
643
658
|
code: 20006,
|
|
644
659
|
msg: "Already paid",
|
|
645
660
|
data: {
|
|
646
661
|
txId: payment.txId
|
|
647
662
|
}
|
|
648
|
-
};
|
|
663
|
+
});
|
|
664
|
+
return;
|
|
665
|
+
}
|
|
649
666
|
const { swapContract, signer } = this.getChain(payment.chainIdentifier);
|
|
650
667
|
if (payment.state === ToBtcSwapAbs_1.ToBtcSwapState.NON_PAYABLE) {
|
|
651
668
|
const isCommited = await swapContract.isCommited(payment.data);
|
|
@@ -604,7 +604,7 @@ class ToBtcLnAbs extends ToBtcBaseSwapHandler_1.ToBtcBaseSwapHandler {
|
|
|
604
604
|
restServer.use(this.path + "/payInvoice", (0, ServerParamDecoder_1.serverParamDecoder)(10 * 1000));
|
|
605
605
|
restServer.post(this.path + "/payInvoice", (0, Utils_1.expressHandlerWrapper)(async (req, res) => {
|
|
606
606
|
const metadata = { request: {}, times: {} };
|
|
607
|
-
const chainIdentifier = req.query.chain
|
|
607
|
+
const chainIdentifier = req.query.chain;
|
|
608
608
|
const { swapContract, signer, chainInterface } = this.getChain(chainIdentifier);
|
|
609
609
|
metadata.times.requestReceived = Date.now();
|
|
610
610
|
/**
|
|
@@ -629,7 +629,7 @@ class ToBtcLnAbs extends ToBtcBaseSwapHandler_1.ToBtcBaseSwapHandler {
|
|
|
629
629
|
this.isTokenSupported(chainIdentifier, val) ? val : null,
|
|
630
630
|
offerer: (val) => val != null &&
|
|
631
631
|
typeof (val) === "string" &&
|
|
632
|
-
chainInterface.isValidAddress(val) ? val : null,
|
|
632
|
+
chainInterface.isValidAddress(val, true) ? val : null,
|
|
633
633
|
exactIn: SchemaVerifier_1.FieldTypeEnum.BooleanOptional,
|
|
634
634
|
amount: SchemaVerifier_1.FieldTypeEnum.BigIntOptional
|
|
635
635
|
});
|
|
@@ -811,21 +811,23 @@ class ToBtcLnAbs extends ToBtcBaseSwapHandler_1.ToBtcBaseSwapHandler {
|
|
|
811
811
|
code: 20007,
|
|
812
812
|
msg: "Payment not found"
|
|
813
813
|
};
|
|
814
|
-
if (payment.status === "pending")
|
|
815
|
-
|
|
816
|
-
_httpStatus: 200,
|
|
814
|
+
if (payment.status === "pending") {
|
|
815
|
+
res.status(200).json({
|
|
817
816
|
code: 20008,
|
|
818
817
|
msg: "Payment in-flight"
|
|
819
|
-
};
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
818
|
+
});
|
|
819
|
+
return;
|
|
820
|
+
}
|
|
821
|
+
if (payment.status === "confirmed") {
|
|
822
|
+
res.status(200).json({
|
|
823
823
|
code: 20006,
|
|
824
824
|
msg: "Already paid",
|
|
825
825
|
data: {
|
|
826
826
|
secret: payment.secret
|
|
827
827
|
}
|
|
828
|
-
};
|
|
828
|
+
});
|
|
829
|
+
return;
|
|
830
|
+
}
|
|
829
831
|
if (payment.status === "failed")
|
|
830
832
|
throw {
|
|
831
833
|
_httpStatus: 200,
|
|
@@ -16,9 +16,8 @@ export declare class SpvVault<D extends SpvWithdrawalTransactionData = SpvWithdr
|
|
|
16
16
|
data: T;
|
|
17
17
|
state: SpvVaultState;
|
|
18
18
|
balances: SpvVaultTokenBalance[];
|
|
19
|
-
|
|
20
|
-
txId: string;
|
|
21
|
-
rawTx: string;
|
|
19
|
+
scOpenTxs: {
|
|
20
|
+
[txId: string]: string;
|
|
22
21
|
};
|
|
23
22
|
constructor(chainId: string, vault: T, btcAddress: string);
|
|
24
23
|
constructor(obj: any);
|
|
@@ -28,7 +28,7 @@ class SpvVault extends base_1.Lockable {
|
|
|
28
28
|
this.initialUtxo = chainIdOrObj.initialUtxo;
|
|
29
29
|
this.btcAddress = chainIdOrObj.btcAddress;
|
|
30
30
|
this.pendingWithdrawals = chainIdOrObj.pendingWithdrawals.map((base_1.SpvWithdrawalTransactionData.deserialize));
|
|
31
|
-
this.
|
|
31
|
+
this.scOpenTxs = chainIdOrObj.scOpenTxs;
|
|
32
32
|
this.replacedWithdrawals = new Map();
|
|
33
33
|
if (chainIdOrObj.replacedWithdrawals != null) {
|
|
34
34
|
chainIdOrObj.replacedWithdrawals.forEach((val) => {
|
|
@@ -117,7 +117,7 @@ class SpvVault extends base_1.Lockable {
|
|
|
117
117
|
btcAddress: this.btcAddress,
|
|
118
118
|
pendingWithdrawals: this.pendingWithdrawals.map(val => val.serialize()),
|
|
119
119
|
replacedWithdrawals,
|
|
120
|
-
|
|
120
|
+
scOpenTxs: this.scOpenTxs
|
|
121
121
|
};
|
|
122
122
|
}
|
|
123
123
|
getIdentifier() {
|
|
@@ -25,7 +25,7 @@ class SpvVaultSwapHandler extends SwapHandler_1.SwapHandler {
|
|
|
25
25
|
this.vaultSigner = spvVaultSigner;
|
|
26
26
|
this.config = config;
|
|
27
27
|
this.AmountAssertions = new FromBtcAmountAssertions_1.FromBtcAmountAssertions(config, swapPricing);
|
|
28
|
-
this.Vaults = new SpvVaults_1.SpvVaults(vaultStorage, bitcoin, spvVaultSigner, bitcoinRpc, this.
|
|
28
|
+
this.Vaults = new SpvVaults_1.SpvVaults(vaultStorage, bitcoin, spvVaultSigner, bitcoinRpc, this.chains, config);
|
|
29
29
|
}
|
|
30
30
|
async processClaimEvent(swap, event) {
|
|
31
31
|
if (swap == null)
|
|
@@ -121,7 +121,7 @@ class SpvVaultSwapHandler extends SwapHandler_1.SwapHandler {
|
|
|
121
121
|
await this.saveSwapData(swap);
|
|
122
122
|
}
|
|
123
123
|
}
|
|
124
|
-
if (swap.state === SpvVaultSwap_1.SpvVaultSwapState.SENT) {
|
|
124
|
+
if (swap.state === SpvVaultSwap_1.SpvVaultSwapState.SENT || swap.state === SpvVaultSwap_1.SpvVaultSwapState.BTC_CONFIRMED) {
|
|
125
125
|
//Check if confirmed or double-spent
|
|
126
126
|
if (swap.sending)
|
|
127
127
|
return;
|
|
@@ -135,8 +135,10 @@ class SpvVaultSwapHandler extends SwapHandler_1.SwapHandler {
|
|
|
135
135
|
return;
|
|
136
136
|
}
|
|
137
137
|
else if (tx.confirmations > 0) {
|
|
138
|
-
|
|
139
|
-
|
|
138
|
+
if (swap.state !== SpvVaultSwap_1.SpvVaultSwapState.BTC_CONFIRMED) {
|
|
139
|
+
await swap.setState(SpvVaultSwap_1.SpvVaultSwapState.BTC_CONFIRMED);
|
|
140
|
+
await this.saveSwapData(swap);
|
|
141
|
+
}
|
|
140
142
|
}
|
|
141
143
|
}
|
|
142
144
|
}
|
|
@@ -174,7 +176,7 @@ class SpvVaultSwapHandler extends SwapHandler_1.SwapHandler {
|
|
|
174
176
|
restServer.use(this.path + "/getQuote", (0, ServerParamDecoder_1.serverParamDecoder)(10 * 1000));
|
|
175
177
|
restServer.post(this.path + "/getQuote", (0, Utils_1.expressHandlerWrapper)(async (req, res) => {
|
|
176
178
|
const metadata = { request: {}, times: {} };
|
|
177
|
-
const chainIdentifier = req.query.chain
|
|
179
|
+
const chainIdentifier = req.query.chain;
|
|
178
180
|
const { signer, chainInterface, spvVaultContract } = this.getChain(chainIdentifier);
|
|
179
181
|
metadata.times.requestReceived = Date.now();
|
|
180
182
|
/**
|
|
@@ -190,7 +192,7 @@ class SpvVaultSwapHandler extends SwapHandler_1.SwapHandler {
|
|
|
190
192
|
const parsedBody = await req.paramReader.getParams({
|
|
191
193
|
address: (val) => val != null &&
|
|
192
194
|
typeof (val) === "string" &&
|
|
193
|
-
chainInterface.isValidAddress(val) ? val : null,
|
|
195
|
+
chainInterface.isValidAddress(val, true) ? val : null,
|
|
194
196
|
amount: SchemaVerifier_1.FieldTypeEnum.BigInt,
|
|
195
197
|
token: (val) => val != null &&
|
|
196
198
|
typeof (val) === "string" &&
|
|
@@ -388,7 +390,7 @@ class SpvVaultSwapHandler extends SwapHandler_1.SwapHandler {
|
|
|
388
390
|
msg: "PSBT transaction cannot be parsed!"
|
|
389
391
|
};
|
|
390
392
|
}
|
|
391
|
-
if (data.
|
|
393
|
+
if (!data.isRecipient(swap.recipient) ||
|
|
392
394
|
data.callerFeeRate !== swap.callerFeeShare ||
|
|
393
395
|
data.frontingFeeRate !== swap.frontingFeeShare ||
|
|
394
396
|
data.executionFeeRate !== swap.executionFeeShare ||
|
|
@@ -423,7 +425,7 @@ class SpvVaultSwapHandler extends SwapHandler_1.SwapHandler {
|
|
|
423
425
|
msg: "One or more PSBT inputs not finalized!"
|
|
424
426
|
};
|
|
425
427
|
const effectiveFeeRate = await this.bitcoinRpc.getEffectiveFeeRate(await this.bitcoin.parsePsbt(signedTx));
|
|
426
|
-
if (effectiveFeeRate.feeRate < swap.btcFeeRate)
|
|
428
|
+
if (effectiveFeeRate.feeRate < 1 || Math.round(effectiveFeeRate.feeRate) < swap.btcFeeRate)
|
|
427
429
|
throw {
|
|
428
430
|
code: 20511,
|
|
429
431
|
msg: "Bitcoin transaction fee too low, expected minimum: " + swap.btcFeeRate + " adjusted effective fee rate: " + effectiveFeeRate.feeRate
|
|
@@ -3,7 +3,7 @@ import { BitcoinRpc, IStorageManager, SpvVaultClaimEvent, SpvVaultCloseEvent, Sp
|
|
|
3
3
|
import { SpvVaultSwap } from "./SpvVaultSwap";
|
|
4
4
|
import { IBitcoinWallet } from "../../wallets/IBitcoinWallet";
|
|
5
5
|
import { ISpvVaultSigner } from "../../wallets/ISpvVaultSigner";
|
|
6
|
-
import {
|
|
6
|
+
import { MultichainData } from "../SwapHandler";
|
|
7
7
|
export declare const VAULT_DUST_AMOUNT = 600;
|
|
8
8
|
export declare class SpvVaults {
|
|
9
9
|
readonly vaultStorage: IStorageManager<SpvVault>;
|
|
@@ -14,14 +14,9 @@ export declare class SpvVaults {
|
|
|
14
14
|
vaultsCheckInterval: number;
|
|
15
15
|
maxUnclaimedWithdrawals?: number;
|
|
16
16
|
};
|
|
17
|
-
readonly
|
|
18
|
-
readonly logger:
|
|
19
|
-
|
|
20
|
-
info: (msg: string, ...args: any) => void;
|
|
21
|
-
warn: (msg: string, ...args: any) => void;
|
|
22
|
-
error: (msg: string, ...args: any) => void;
|
|
23
|
-
};
|
|
24
|
-
constructor(vaultStorage: IStorageManager<SpvVault>, bitcoin: IBitcoinWallet, vaultSigner: ISpvVaultSigner, bitcoinRpc: BitcoinRpc<any>, getChain: (chainId: string) => ChainData, config: {
|
|
17
|
+
readonly chains: MultichainData;
|
|
18
|
+
readonly logger: import("../../utils/Utils").LoggerType;
|
|
19
|
+
constructor(vaultStorage: IStorageManager<SpvVault>, bitcoin: IBitcoinWallet, vaultSigner: ISpvVaultSigner, bitcoinRpc: BitcoinRpc<any>, chains: MultichainData, config: {
|
|
25
20
|
vaultsCheckInterval: number;
|
|
26
21
|
maxUnclaimedWithdrawals?: number;
|
|
27
22
|
});
|