@atomiqlabs/lp-lib 11.0.5 → 12.0.0-beta.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/info/InfoHandler.js +3 -12
- package/dist/plugins/IPlugin.d.ts +34 -35
- package/dist/plugins/IPlugin.js +7 -8
- package/dist/plugins/PluginManager.d.ts +29 -30
- package/dist/plugins/PluginManager.js +160 -188
- package/dist/prices/BinanceSwapPrice.d.ts +1 -2
- package/dist/prices/BinanceSwapPrice.js +56 -70
- package/dist/prices/CoinGeckoSwapPrice.d.ts +2 -3
- package/dist/prices/CoinGeckoSwapPrice.js +30 -42
- package/dist/prices/OKXSwapPrice.d.ts +1 -2
- package/dist/prices/OKXSwapPrice.js +56 -70
- package/dist/storage/IIntermediaryStorage.d.ts +8 -5
- package/dist/storagemanager/IntermediaryStorageManager.d.ts +8 -5
- package/dist/storagemanager/IntermediaryStorageManager.js +52 -61
- package/dist/storagemanager/StorageManager.js +42 -59
- package/dist/swaps/FromBtcBaseSwap.d.ts +7 -8
- package/dist/swaps/FromBtcBaseSwap.js +2 -3
- package/dist/swaps/FromBtcBaseSwapHandler.d.ts +44 -31
- package/dist/swaps/FromBtcBaseSwapHandler.js +217 -196
- package/dist/swaps/FromBtcLnBaseSwapHandler.d.ts +1 -2
- package/dist/swaps/FromBtcLnBaseSwapHandler.js +13 -24
- package/dist/swaps/ISwapPrice.d.ts +4 -5
- package/dist/swaps/ISwapPrice.js +8 -30
- package/dist/swaps/SwapHandler.d.ts +26 -15
- package/dist/swaps/SwapHandler.js +107 -66
- package/dist/swaps/SwapHandlerSwap.d.ts +22 -11
- package/dist/swaps/SwapHandlerSwap.js +32 -8
- package/dist/swaps/ToBtcBaseSwap.d.ts +16 -17
- package/dist/swaps/ToBtcBaseSwap.js +4 -4
- package/dist/swaps/ToBtcBaseSwapHandler.d.ts +17 -17
- package/dist/swaps/ToBtcBaseSwapHandler.js +140 -155
- package/dist/swaps/frombtc_abstract/FromBtcAbs.d.ts +8 -15
- package/dist/swaps/frombtc_abstract/FromBtcAbs.js +131 -196
- package/dist/swaps/frombtc_abstract/FromBtcSwapAbs.d.ts +3 -5
- package/dist/swaps/frombtc_abstract/FromBtcSwapAbs.js +4 -4
- package/dist/swaps/frombtc_trusted/FromBtcTrusted.d.ts +10 -8
- package/dist/swaps/frombtc_trusted/FromBtcTrusted.js +330 -362
- package/dist/swaps/frombtc_trusted/FromBtcTrustedSwap.d.ts +10 -10
- package/dist/swaps/frombtc_trusted/FromBtcTrustedSwap.js +7 -4
- package/dist/swaps/frombtcln_abstract/FromBtcLnAbs.d.ts +8 -8
- package/dist/swaps/frombtcln_abstract/FromBtcLnAbs.js +330 -400
- package/dist/swaps/frombtcln_abstract/FromBtcLnSwapAbs.d.ts +10 -4
- package/dist/swaps/frombtcln_abstract/FromBtcLnSwapAbs.js +36 -6
- package/dist/swaps/frombtcln_trusted/FromBtcLnTrusted.d.ts +8 -7
- package/dist/swaps/frombtcln_trusted/FromBtcLnTrusted.js +251 -273
- package/dist/swaps/frombtcln_trusted/FromBtcLnTrustedSwap.d.ts +5 -5
- package/dist/swaps/frombtcln_trusted/FromBtcLnTrustedSwap.js +7 -5
- package/dist/swaps/tobtc_abstract/ToBtcAbs.d.ts +13 -12
- package/dist/swaps/tobtc_abstract/ToBtcAbs.js +261 -323
- package/dist/swaps/tobtc_abstract/ToBtcSwapAbs.d.ts +4 -4
- package/dist/swaps/tobtc_abstract/ToBtcSwapAbs.js +7 -6
- package/dist/swaps/tobtcln_abstract/ToBtcLnAbs.d.ts +22 -21
- package/dist/swaps/tobtcln_abstract/ToBtcLnAbs.js +398 -453
- package/dist/swaps/tobtcln_abstract/ToBtcLnSwapAbs.d.ts +3 -2
- package/dist/swaps/tobtcln_abstract/ToBtcLnSwapAbs.js +10 -6
- package/dist/utils/Utils.d.ts +2 -3
- package/dist/utils/Utils.js +4 -14
- package/dist/utils/paramcoders/LegacyParamEncoder.js +3 -14
- package/dist/utils/paramcoders/ParamDecoder.js +53 -65
- package/dist/utils/paramcoders/SchemaVerifier.d.ts +4 -5
- package/dist/utils/paramcoders/SchemaVerifier.js +8 -9
- package/dist/utils/paramcoders/server/ServerParamDecoder.js +1 -1
- package/dist/utils/paramcoders/server/ServerParamEncoder.js +3 -14
- package/dist/wallets/IBitcoinWallet.d.ts +4 -5
- package/dist/wallets/ILightningWallet.d.ts +20 -21
- package/dist/wallets/ILightningWallet.js +1 -1
- package/package.json +4 -6
- package/src/plugins/IPlugin.ts +28 -29
- package/src/plugins/PluginManager.ts +21 -22
- package/src/prices/BinanceSwapPrice.ts +3 -4
- package/src/prices/CoinGeckoSwapPrice.ts +4 -5
- package/src/prices/OKXSwapPrice.ts +3 -4
- package/src/storage/IIntermediaryStorage.ts +4 -5
- package/src/storagemanager/IntermediaryStorageManager.ts +17 -9
- package/src/swaps/FromBtcBaseSwap.ts +9 -10
- package/src/swaps/FromBtcBaseSwapHandler.ts +133 -91
- package/src/swaps/FromBtcLnBaseSwapHandler.ts +2 -3
- package/src/swaps/ISwapPrice.ts +10 -20
- package/src/swaps/SwapHandler.ts +101 -35
- package/src/swaps/SwapHandlerSwap.ts +42 -17
- package/src/swaps/ToBtcBaseSwap.ts +20 -18
- package/src/swaps/ToBtcBaseSwapHandler.ts +33 -33
- package/src/swaps/frombtc_abstract/FromBtcAbs.ts +64 -97
- package/src/swaps/frombtc_abstract/FromBtcSwapAbs.ts +7 -8
- package/src/swaps/frombtc_trusted/FromBtcTrusted.ts +56 -55
- package/src/swaps/frombtc_trusted/FromBtcTrustedSwap.ts +28 -21
- package/src/swaps/frombtcln_abstract/FromBtcLnAbs.ts +81 -116
- package/src/swaps/frombtcln_abstract/FromBtcLnSwapAbs.ts +73 -9
- package/src/swaps/frombtcln_trusted/FromBtcLnTrusted.ts +39 -36
- package/src/swaps/frombtcln_trusted/FromBtcLnTrustedSwap.ts +26 -12
- package/src/swaps/tobtc_abstract/ToBtcAbs.ts +82 -98
- package/src/swaps/tobtc_abstract/ToBtcSwapAbs.ts +25 -20
- package/src/swaps/tobtcln_abstract/ToBtcLnAbs.ts +106 -118
- package/src/swaps/tobtcln_abstract/ToBtcLnSwapAbs.ts +17 -9
- package/src/utils/Utils.ts +3 -4
- package/src/utils/paramcoders/ParamDecoder.ts +5 -5
- package/src/utils/paramcoders/SchemaVerifier.ts +10 -11
- package/src/utils/paramcoders/server/ServerParamDecoder.ts +1 -1
- package/src/wallets/IBitcoinWallet.ts +4 -5
- package/src/wallets/ILightningWallet.ts +21 -22
|
@@ -1,16 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
-
});
|
|
10
|
-
};
|
|
11
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
3
|
exports.ToBtcAbs = void 0;
|
|
13
|
-
const BN = require("bn.js");
|
|
14
4
|
const ToBtcSwapAbs_1 = require("./ToBtcSwapAbs");
|
|
15
5
|
const SwapHandler_1 = require("../SwapHandler");
|
|
16
6
|
const base_1 = require("@atomiqlabs/base");
|
|
@@ -29,6 +19,7 @@ class ToBtcAbs extends ToBtcBaseSwapHandler_1.ToBtcBaseSwapHandler {
|
|
|
29
19
|
constructor(storageDirectory, path, chainData, bitcoin, swapPricing, bitcoinRpc, config) {
|
|
30
20
|
super(storageDirectory, path, chainData, swapPricing);
|
|
31
21
|
this.type = SwapHandler_1.SwapHandlerType.TO_BTC;
|
|
22
|
+
this.swapType = base_1.ChainSwapType.CHAIN_NONCED;
|
|
32
23
|
this.activeSubscriptions = {};
|
|
33
24
|
this.sendBtcQueue = new promise_queue_ts_1.PromiseQueue();
|
|
34
25
|
this.bitcoinRpc = bitcoinRpc;
|
|
@@ -40,13 +31,14 @@ class ToBtcAbs extends ToBtcBaseSwapHandler_1.ToBtcBaseSwapHandler {
|
|
|
40
31
|
*
|
|
41
32
|
* @param chainIdentifier
|
|
42
33
|
* @param address
|
|
34
|
+
* @param confirmations
|
|
43
35
|
* @param nonce
|
|
44
36
|
* @param amount
|
|
45
37
|
*/
|
|
46
|
-
getHash(chainIdentifier, address, nonce, amount) {
|
|
38
|
+
getHash(chainIdentifier, address, confirmations, nonce, amount) {
|
|
47
39
|
const parsedOutputScript = this.bitcoin.toOutputScript(address);
|
|
48
40
|
const { swapContract } = this.getChain(chainIdentifier);
|
|
49
|
-
return swapContract.getHashForOnchain(parsedOutputScript, amount, nonce);
|
|
41
|
+
return swapContract.getHashForOnchain(parsedOutputScript, amount, confirmations, nonce);
|
|
50
42
|
}
|
|
51
43
|
/**
|
|
52
44
|
* Tries to claim the swap after our transaction was confirmed
|
|
@@ -55,153 +47,143 @@ class ToBtcAbs extends ToBtcBaseSwapHandler_1.ToBtcBaseSwapHandler {
|
|
|
55
47
|
* @param swap
|
|
56
48
|
* @param vout
|
|
57
49
|
*/
|
|
58
|
-
tryClaimSwap(tx, swap, vout) {
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
}
|
|
81
|
-
});
|
|
50
|
+
async tryClaimSwap(tx, swap, vout) {
|
|
51
|
+
const { swapContract, signer } = this.getChain(swap.chainIdentifier);
|
|
52
|
+
const blockHeader = await this.bitcoinRpc.getBlockHeader(tx.blockhash);
|
|
53
|
+
//Set flag that we are sending the transaction already, so we don't end up with race condition
|
|
54
|
+
const unlock = swap.lock(swapContract.claimWithTxDataTimeout);
|
|
55
|
+
if (unlock == null)
|
|
56
|
+
return false;
|
|
57
|
+
try {
|
|
58
|
+
this.swapLogger.debug(swap, "tryClaimSwap(): initiate claim of swap, height: " + blockHeader.getHeight() + " utxo: " + tx.txid + ":" + vout);
|
|
59
|
+
const result = await swapContract.claimWithTxData(signer, swap.data, { ...tx, height: blockHeader.getHeight() }, swap.requiredConfirmations, vout, null, null, false, {
|
|
60
|
+
waitForConfirmation: true
|
|
61
|
+
});
|
|
62
|
+
this.swapLogger.info(swap, "tryClaimSwap(): swap claimed successfully, height: " + blockHeader.getHeight() + " utxo: " + tx.txid + ":" + vout + " address: " + swap.address);
|
|
63
|
+
if (swap.metadata != null)
|
|
64
|
+
swap.metadata.times.txClaimed = Date.now();
|
|
65
|
+
unlock();
|
|
66
|
+
return true;
|
|
67
|
+
}
|
|
68
|
+
catch (e) {
|
|
69
|
+
this.swapLogger.error(swap, "tryClaimSwap(): error occurred claiming swap, height: " + blockHeader.getHeight() + " utxo: " + tx.txid + ":" + vout + " address: " + swap.address, e);
|
|
70
|
+
return false;
|
|
71
|
+
}
|
|
82
72
|
}
|
|
83
|
-
processPastSwap(swap) {
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
yield this.removeSwapData(swap, ToBtcSwapAbs_1.ToBtcSwapState.CANCELED);
|
|
93
|
-
}
|
|
94
|
-
else {
|
|
95
|
-
this.swapLogger.info(swap, "processPastSwap(state=SAVED): swap committed (detected from processPastSwap), address: " + swap.address);
|
|
96
|
-
yield swap.setState(ToBtcSwapAbs_1.ToBtcSwapState.COMMITED);
|
|
97
|
-
yield this.storageManager.saveData(swap.getHash(), swap.data.getSequence(), swap);
|
|
98
|
-
}
|
|
99
|
-
return;
|
|
73
|
+
async processPastSwap(swap) {
|
|
74
|
+
const { swapContract, signer } = this.getChain(swap.chainIdentifier);
|
|
75
|
+
if (swap.state === ToBtcSwapAbs_1.ToBtcSwapState.SAVED) {
|
|
76
|
+
const isSignatureExpired = await swapContract.isInitAuthorizationExpired(swap.data, swap);
|
|
77
|
+
if (isSignatureExpired) {
|
|
78
|
+
const isCommitted = await swapContract.isCommited(swap.data);
|
|
79
|
+
if (!isCommitted) {
|
|
80
|
+
this.swapLogger.info(swap, "processPastSwap(state=SAVED): authorization expired & swap not committed, cancelling swap, address: " + swap.address);
|
|
81
|
+
await this.removeSwapData(swap, ToBtcSwapAbs_1.ToBtcSwapState.CANCELED);
|
|
100
82
|
}
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
this.
|
|
105
|
-
yield this.removeSwapData(swap, ToBtcSwapAbs_1.ToBtcSwapState.CANCELED);
|
|
106
|
-
return;
|
|
83
|
+
else {
|
|
84
|
+
this.swapLogger.info(swap, "processPastSwap(state=SAVED): swap committed (detected from processPastSwap), address: " + swap.address);
|
|
85
|
+
await swap.setState(ToBtcSwapAbs_1.ToBtcSwapState.COMMITED);
|
|
86
|
+
await this.saveSwapData(swap);
|
|
107
87
|
}
|
|
88
|
+
return;
|
|
108
89
|
}
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
this.swapLogger.info(swap, "processPastSwap(state=BTC_SENT): swap claimed (detected from processPastSwap), address: " + swap.address);
|
|
116
|
-
this.unsubscribePayment(swap);
|
|
117
|
-
yield this.removeSwapData(swap, ToBtcSwapAbs_1.ToBtcSwapState.CLAIMED);
|
|
118
|
-
}
|
|
119
|
-
else if (status === base_1.SwapCommitStatus.EXPIRED) {
|
|
120
|
-
this.swapLogger.warn(swap, "processPastSwap(state=BTC_SENT): swap expired, but bitcoin was probably already sent, txId: " + swap.txId + " address: " + swap.address);
|
|
121
|
-
this.unsubscribePayment(swap);
|
|
122
|
-
yield this.removeSwapData(swap, ToBtcSwapAbs_1.ToBtcSwapState.REFUNDED);
|
|
123
|
-
}
|
|
124
|
-
return;
|
|
125
|
-
}
|
|
90
|
+
}
|
|
91
|
+
if (swap.state === ToBtcSwapAbs_1.ToBtcSwapState.NON_PAYABLE || swap.state === ToBtcSwapAbs_1.ToBtcSwapState.SAVED) {
|
|
92
|
+
if (await swapContract.isExpired(signer.getAddress(), swap.data)) {
|
|
93
|
+
this.swapLogger.info(swap, "processPastSwap(state=NON_PAYABLE|SAVED): swap expired, cancelling, address: " + swap.address);
|
|
94
|
+
await this.removeSwapData(swap, ToBtcSwapAbs_1.ToBtcSwapState.CANCELED);
|
|
95
|
+
return;
|
|
126
96
|
}
|
|
127
|
-
|
|
128
|
-
|
|
97
|
+
}
|
|
98
|
+
//Sanity check for sent swaps
|
|
99
|
+
if (swap.state === ToBtcSwapAbs_1.ToBtcSwapState.BTC_SENT) {
|
|
100
|
+
const isCommited = await swapContract.isCommited(swap.data);
|
|
101
|
+
if (!isCommited) {
|
|
102
|
+
const status = await swapContract.getCommitStatus(signer.getAddress(), swap.data);
|
|
103
|
+
if (status === base_1.SwapCommitStatus.PAID) {
|
|
104
|
+
this.swapLogger.info(swap, "processPastSwap(state=BTC_SENT): swap claimed (detected from processPastSwap), address: " + swap.address);
|
|
105
|
+
this.unsubscribePayment(swap);
|
|
106
|
+
await this.removeSwapData(swap, ToBtcSwapAbs_1.ToBtcSwapState.CLAIMED);
|
|
107
|
+
}
|
|
108
|
+
else if (status === base_1.SwapCommitStatus.EXPIRED) {
|
|
109
|
+
this.swapLogger.warn(swap, "processPastSwap(state=BTC_SENT): swap expired, but bitcoin was probably already sent, txId: " + swap.txId + " address: " + swap.address);
|
|
110
|
+
this.unsubscribePayment(swap);
|
|
111
|
+
await this.removeSwapData(swap, ToBtcSwapAbs_1.ToBtcSwapState.REFUNDED);
|
|
112
|
+
}
|
|
129
113
|
return;
|
|
130
114
|
}
|
|
131
|
-
}
|
|
115
|
+
}
|
|
116
|
+
if (swap.state === ToBtcSwapAbs_1.ToBtcSwapState.COMMITED || swap.state === ToBtcSwapAbs_1.ToBtcSwapState.BTC_SENDING || swap.state === ToBtcSwapAbs_1.ToBtcSwapState.BTC_SENT) {
|
|
117
|
+
await this.processInitialized(swap);
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
132
120
|
}
|
|
133
121
|
/**
|
|
134
122
|
* Checks past swaps, deletes ones that are already expired.
|
|
135
123
|
*/
|
|
136
|
-
processPastSwaps() {
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
]
|
|
148
|
-
}
|
|
149
|
-
]);
|
|
150
|
-
for (let swap of queriedData) {
|
|
151
|
-
yield this.processPastSwap(swap);
|
|
124
|
+
async processPastSwaps() {
|
|
125
|
+
const queriedData = await this.storageManager.query([
|
|
126
|
+
{
|
|
127
|
+
key: "state",
|
|
128
|
+
values: [
|
|
129
|
+
ToBtcSwapAbs_1.ToBtcSwapState.SAVED,
|
|
130
|
+
ToBtcSwapAbs_1.ToBtcSwapState.NON_PAYABLE,
|
|
131
|
+
ToBtcSwapAbs_1.ToBtcSwapState.COMMITED,
|
|
132
|
+
ToBtcSwapAbs_1.ToBtcSwapState.BTC_SENDING,
|
|
133
|
+
ToBtcSwapAbs_1.ToBtcSwapState.BTC_SENT,
|
|
134
|
+
]
|
|
152
135
|
}
|
|
153
|
-
|
|
136
|
+
]);
|
|
137
|
+
for (let { obj: swap } of queriedData) {
|
|
138
|
+
await this.processPastSwap(swap);
|
|
139
|
+
}
|
|
154
140
|
}
|
|
155
|
-
processBtcTx(swap, tx) {
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
return success;
|
|
178
|
-
});
|
|
141
|
+
async processBtcTx(swap, tx) {
|
|
142
|
+
tx.confirmations = tx.confirmations || 0;
|
|
143
|
+
//Check transaction has enough confirmations
|
|
144
|
+
const hasEnoughConfirmations = tx.confirmations >= swap.requiredConfirmations;
|
|
145
|
+
if (!hasEnoughConfirmations) {
|
|
146
|
+
return false;
|
|
147
|
+
}
|
|
148
|
+
this.swapLogger.debug(swap, "processBtcTx(): address: " + swap.address + " amount: " + swap.amount.toString(10) + " btcTx: " + tx);
|
|
149
|
+
//Search for required transaction output (vout)
|
|
150
|
+
const outputScript = this.bitcoin.toOutputScript(swap.address);
|
|
151
|
+
const vout = tx.outs.find(e => BigInt(e.value) === swap.amount && Buffer.from(e.scriptPubKey.hex, "hex").equals(outputScript));
|
|
152
|
+
if (vout == null) {
|
|
153
|
+
this.swapLogger.warn(swap, "processBtcTx(): cannot find correct vout," +
|
|
154
|
+
" required output script: " + outputScript.toString("hex") +
|
|
155
|
+
" required amount: " + swap.amount.toString(10) +
|
|
156
|
+
" vouts: ", tx.outs);
|
|
157
|
+
return false;
|
|
158
|
+
}
|
|
159
|
+
if (swap.metadata != null)
|
|
160
|
+
swap.metadata.times.payTxConfirmed = Date.now();
|
|
161
|
+
const success = await this.tryClaimSwap(tx, swap, vout.n);
|
|
162
|
+
return success;
|
|
179
163
|
}
|
|
180
164
|
/**
|
|
181
165
|
* Checks active sent out bitcoin transactions
|
|
182
166
|
*/
|
|
183
|
-
processBtcTxs() {
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
unsubscribeSwaps.push(swap);
|
|
196
|
-
}
|
|
197
|
-
}
|
|
198
|
-
catch (e) {
|
|
199
|
-
this.swapLogger.error(swap, "processBtcTxs(): error processing btc transaction", e);
|
|
167
|
+
async processBtcTxs() {
|
|
168
|
+
const unsubscribeSwaps = [];
|
|
169
|
+
for (let txId in this.activeSubscriptions) {
|
|
170
|
+
const swap = this.activeSubscriptions[txId];
|
|
171
|
+
//TODO: RBF the transaction if it's already taking too long to confirm
|
|
172
|
+
try {
|
|
173
|
+
let tx = await this.bitcoin.getWalletTransaction(txId);
|
|
174
|
+
if (tx == null)
|
|
175
|
+
continue;
|
|
176
|
+
if (await this.processBtcTx(swap, tx)) {
|
|
177
|
+
this.swapLogger.info(swap, "processBtcTxs(): swap claimed successfully, txId: " + tx.txid + " address: " + swap.address);
|
|
178
|
+
unsubscribeSwaps.push(swap);
|
|
200
179
|
}
|
|
201
180
|
}
|
|
202
|
-
|
|
203
|
-
this.
|
|
204
|
-
}
|
|
181
|
+
catch (e) {
|
|
182
|
+
this.swapLogger.error(swap, "processBtcTxs(): error processing btc transaction", e);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
unsubscribeSwaps.forEach(swap => {
|
|
186
|
+
this.unsubscribePayment(swap);
|
|
205
187
|
});
|
|
206
188
|
}
|
|
207
189
|
/**
|
|
@@ -229,10 +211,10 @@ class ToBtcAbs extends ToBtcBaseSwapHandler_1.ToBtcBaseSwapHandler {
|
|
|
229
211
|
* @throws DefinedRuntimeError will throw an error in case there isn't enough time for us to send a BTC payout tx
|
|
230
212
|
*/
|
|
231
213
|
checkExpiresTooSoon(swap) {
|
|
232
|
-
const currentTimestamp =
|
|
233
|
-
const tsDelta = swap.data.getExpiry()
|
|
234
|
-
const minRequiredCLTV = this.getExpiryFromCLTV(swap.preferedConfirmationTarget, swap.
|
|
235
|
-
const hasRequiredCLTVDelta = tsDelta
|
|
214
|
+
const currentTimestamp = BigInt(Math.floor(Date.now() / 1000));
|
|
215
|
+
const tsDelta = swap.data.getExpiry() - currentTimestamp;
|
|
216
|
+
const minRequiredCLTV = this.getExpiryFromCLTV(swap.preferedConfirmationTarget, swap.requiredConfirmations);
|
|
217
|
+
const hasRequiredCLTVDelta = tsDelta >= minRequiredCLTV;
|
|
236
218
|
if (!hasRequiredCLTVDelta)
|
|
237
219
|
throw {
|
|
238
220
|
code: 90001,
|
|
@@ -252,7 +234,7 @@ class ToBtcAbs extends ToBtcBaseSwapHandler_1.ToBtcBaseSwapHandler {
|
|
|
252
234
|
* @throws DefinedRuntimeError will throw an error in case the actual fee is higher than quoted fee
|
|
253
235
|
*/
|
|
254
236
|
checkCalculatedTxFee(quotedSatsPerVbyte, actualSatsPerVbyte) {
|
|
255
|
-
const swapPaysEnoughNetworkFee = quotedSatsPerVbyte
|
|
237
|
+
const swapPaysEnoughNetworkFee = quotedSatsPerVbyte >= actualSatsPerVbyte;
|
|
256
238
|
if (!swapPaysEnoughNetworkFee)
|
|
257
239
|
throw {
|
|
258
240
|
code: 90003,
|
|
@@ -273,16 +255,16 @@ class ToBtcAbs extends ToBtcBaseSwapHandler_1.ToBtcBaseSwapHandler {
|
|
|
273
255
|
sendBitcoinPayment(swap) {
|
|
274
256
|
//Make sure that bitcoin payouts are processed sequentially to avoid race conditions between multiple payouts,
|
|
275
257
|
// e.g. that 2 payouts share the same input and would effectively double-spend each other
|
|
276
|
-
return this.sendBtcQueue.enqueue(() =>
|
|
258
|
+
return this.sendBtcQueue.enqueue(async () => {
|
|
277
259
|
//Run checks
|
|
278
260
|
this.checkExpiresTooSoon(swap);
|
|
279
261
|
if (swap.metadata != null)
|
|
280
262
|
swap.metadata.times.payCLTVChecked = Date.now();
|
|
281
|
-
const satsPerVbyte =
|
|
282
|
-
this.checkCalculatedTxFee(swap.satsPerVbyte,
|
|
263
|
+
const satsPerVbyte = await this.bitcoin.getFeeRate();
|
|
264
|
+
this.checkCalculatedTxFee(swap.satsPerVbyte, BigInt(satsPerVbyte));
|
|
283
265
|
if (swap.metadata != null)
|
|
284
266
|
swap.metadata.times.payChainFee = Date.now();
|
|
285
|
-
const signResult =
|
|
267
|
+
const signResult = await this.bitcoin.getSignedTransaction(swap.address, Number(swap.amount), satsPerVbyte, swap.nonce, Number(swap.satsPerVbyte));
|
|
286
268
|
if (signResult == null)
|
|
287
269
|
throw {
|
|
288
270
|
code: 90002,
|
|
@@ -291,117 +273,87 @@ class ToBtcAbs extends ToBtcBaseSwapHandler_1.ToBtcBaseSwapHandler {
|
|
|
291
273
|
if (swap.metadata != null)
|
|
292
274
|
swap.metadata.times.paySignPSBT = Date.now();
|
|
293
275
|
this.swapLogger.debug(swap, "sendBitcoinPayment(): signed raw transaction: " + signResult.raw);
|
|
294
|
-
swap.txId = signResult.tx.
|
|
295
|
-
swap.setRealNetworkFee(
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
276
|
+
swap.txId = signResult.tx.id;
|
|
277
|
+
swap.setRealNetworkFee(BigInt(signResult.networkFee));
|
|
278
|
+
await swap.setState(ToBtcSwapAbs_1.ToBtcSwapState.BTC_SENDING);
|
|
279
|
+
await this.saveSwapData(swap);
|
|
280
|
+
await this.bitcoin.sendRawTransaction(signResult.raw);
|
|
299
281
|
if (swap.metadata != null)
|
|
300
282
|
swap.metadata.times.payTxSent = Date.now();
|
|
301
|
-
this.swapLogger.info(swap, "sendBitcoinPayment(): btc transaction generated, signed & broadcasted, txId: " +
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
})
|
|
283
|
+
this.swapLogger.info(swap, "sendBitcoinPayment(): btc transaction generated, signed & broadcasted, txId: " + swap.txId + " address: " + swap.address);
|
|
284
|
+
await swap.setState(ToBtcSwapAbs_1.ToBtcSwapState.BTC_SENT);
|
|
285
|
+
await this.saveSwapData(swap);
|
|
286
|
+
});
|
|
305
287
|
}
|
|
306
288
|
/**
|
|
307
289
|
* Called after swap was successfully committed, will check if bitcoin tx is already sent, if not tries to send it and subscribes to it
|
|
308
290
|
*
|
|
309
291
|
* @param swap
|
|
310
292
|
*/
|
|
311
|
-
processInitialized(swap) {
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
yield swap.setState(ToBtcSwapAbs_1.ToBtcSwapState.COMMITED);
|
|
321
|
-
}
|
|
322
|
-
else {
|
|
323
|
-
this.swapLogger.info(swap, "processInitialized(state=BTC_SENDING): btc transaction found, advancing to BTC_SENT state, txId: " + swap.txId + " address: " + swap.address);
|
|
324
|
-
yield swap.setState(ToBtcSwapAbs_1.ToBtcSwapState.BTC_SENT);
|
|
325
|
-
yield this.storageManager.saveData(swap.getHash(), swap.data.getSequence(), swap);
|
|
326
|
-
}
|
|
293
|
+
async processInitialized(swap) {
|
|
294
|
+
if (swap.state === ToBtcSwapAbs_1.ToBtcSwapState.BTC_SENDING) {
|
|
295
|
+
//Bitcoin transaction was signed (maybe also sent)
|
|
296
|
+
const tx = await this.bitcoin.getWalletTransaction(swap.txId);
|
|
297
|
+
const isTxSent = tx != null;
|
|
298
|
+
if (!isTxSent) {
|
|
299
|
+
//Reset the state to COMMITED
|
|
300
|
+
this.swapLogger.info(swap, "processInitialized(state=BTC_SENDING): btc transaction not found, resetting to COMMITED state, txId: " + swap.txId + " address: " + swap.address);
|
|
301
|
+
await swap.setState(ToBtcSwapAbs_1.ToBtcSwapState.COMMITED);
|
|
327
302
|
}
|
|
328
|
-
|
|
329
|
-
this.swapLogger.info(swap, "processInitialized(state=
|
|
330
|
-
|
|
331
|
-
|
|
303
|
+
else {
|
|
304
|
+
this.swapLogger.info(swap, "processInitialized(state=BTC_SENDING): btc transaction found, advancing to BTC_SENT state, txId: " + swap.txId + " address: " + swap.address);
|
|
305
|
+
await swap.setState(ToBtcSwapAbs_1.ToBtcSwapState.BTC_SENT);
|
|
306
|
+
await this.saveSwapData(swap);
|
|
332
307
|
}
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
308
|
+
}
|
|
309
|
+
if (swap.state === ToBtcSwapAbs_1.ToBtcSwapState.SAVED) {
|
|
310
|
+
this.swapLogger.info(swap, "processInitialized(state=SAVED): advancing to COMMITED state, address: " + swap.address);
|
|
311
|
+
await swap.setState(ToBtcSwapAbs_1.ToBtcSwapState.COMMITED);
|
|
312
|
+
await this.saveSwapData(swap);
|
|
313
|
+
}
|
|
314
|
+
if (swap.state === ToBtcSwapAbs_1.ToBtcSwapState.COMMITED) {
|
|
315
|
+
const unlock = swap.lock(60);
|
|
316
|
+
if (unlock == null)
|
|
317
|
+
return;
|
|
318
|
+
this.swapLogger.debug(swap, "processInitialized(state=COMMITED): sending bitcoin transaction, address: " + swap.address);
|
|
319
|
+
try {
|
|
320
|
+
await this.sendBitcoinPayment(swap);
|
|
321
|
+
this.swapLogger.info(swap, "processInitialized(state=COMMITED): btc transaction sent, address: " + swap.address);
|
|
322
|
+
}
|
|
323
|
+
catch (e) {
|
|
324
|
+
if ((0, Utils_1.isDefinedRuntimeError)(e)) {
|
|
325
|
+
this.swapLogger.error(swap, "processInitialized(state=COMMITED): setting state to NON_PAYABLE due to send bitcoin payment error", e);
|
|
326
|
+
if (swap.metadata != null)
|
|
327
|
+
swap.metadata.payError = e;
|
|
328
|
+
await swap.setState(ToBtcSwapAbs_1.ToBtcSwapState.NON_PAYABLE);
|
|
329
|
+
await this.saveSwapData(swap);
|
|
341
330
|
}
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
if (swap.metadata != null)
|
|
346
|
-
swap.metadata.payError = e;
|
|
347
|
-
yield swap.setState(ToBtcSwapAbs_1.ToBtcSwapState.NON_PAYABLE);
|
|
348
|
-
yield this.storageManager.saveData(swap.getHash(), swap.data.getSequence(), swap);
|
|
349
|
-
}
|
|
350
|
-
else {
|
|
351
|
-
this.swapLogger.error(swap, "processInitialized(state=COMMITED): send bitcoin payment error", e);
|
|
352
|
-
throw e;
|
|
353
|
-
}
|
|
331
|
+
else {
|
|
332
|
+
this.swapLogger.error(swap, "processInitialized(state=COMMITED): send bitcoin payment error", e);
|
|
333
|
+
throw e;
|
|
354
334
|
}
|
|
355
|
-
unlock();
|
|
356
335
|
}
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
336
|
+
unlock();
|
|
337
|
+
}
|
|
338
|
+
if (swap.state === ToBtcSwapAbs_1.ToBtcSwapState.NON_PAYABLE)
|
|
339
|
+
return;
|
|
340
|
+
this.subscribeToPayment(swap);
|
|
361
341
|
}
|
|
362
|
-
processInitializeEvent(chainIdentifier, event) {
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
if (event.swapType !== base_1.ChainSwapType.CHAIN_NONCED)
|
|
366
|
-
return;
|
|
367
|
-
const paymentHash = event.paymentHash;
|
|
368
|
-
const swap = yield this.storageManager.getData(paymentHash, event.sequence);
|
|
369
|
-
if (swap == null || swap.chainIdentifier !== chainIdentifier)
|
|
370
|
-
return;
|
|
371
|
-
swap.txIds.init = (_a = event.meta) === null || _a === void 0 ? void 0 : _a.txId;
|
|
372
|
-
if (swap.metadata != null)
|
|
373
|
-
swap.metadata.times.txReceived = Date.now();
|
|
374
|
-
this.swapLogger.info(swap, "SC: InitializeEvent: swap initialized by the client, address: " + swap.address);
|
|
375
|
-
yield this.processInitialized(swap);
|
|
376
|
-
});
|
|
342
|
+
async processInitializeEvent(chainIdentifier, swap, event) {
|
|
343
|
+
this.swapLogger.info(swap, "SC: InitializeEvent: swap initialized by the client, address: " + swap.address);
|
|
344
|
+
await this.processInitialized(swap);
|
|
377
345
|
}
|
|
378
|
-
processClaimEvent(chainIdentifier, event) {
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
if (swap == null || swap.chainIdentifier !== chainIdentifier)
|
|
384
|
-
return;
|
|
385
|
-
swap.txIds.claim = (_a = event.meta) === null || _a === void 0 ? void 0 : _a.txId;
|
|
386
|
-
this.swapLogger.info(swap, "SC: ClaimEvent: swap successfully claimed to us, address: " + swap.address);
|
|
387
|
-
//Also remove transaction from active subscriptions
|
|
388
|
-
this.unsubscribePayment(swap);
|
|
389
|
-
yield this.removeSwapData(swap, ToBtcSwapAbs_1.ToBtcSwapState.CLAIMED);
|
|
390
|
-
});
|
|
346
|
+
async processClaimEvent(chainIdentifier, swap, event) {
|
|
347
|
+
this.swapLogger.info(swap, "SC: ClaimEvent: swap successfully claimed to us, address: " + swap.address);
|
|
348
|
+
//Also remove transaction from active subscriptions
|
|
349
|
+
this.unsubscribePayment(swap);
|
|
350
|
+
await this.removeSwapData(swap, ToBtcSwapAbs_1.ToBtcSwapState.CLAIMED);
|
|
391
351
|
}
|
|
392
|
-
processRefundEvent(chainIdentifier, event) {
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
if (swap == null || swap.chainIdentifier !== chainIdentifier)
|
|
398
|
-
return;
|
|
399
|
-
swap.txIds.refund = (_a = event.meta) === null || _a === void 0 ? void 0 : _a.txId;
|
|
400
|
-
this.swapLogger.info(swap, "SC: RefundEvent: swap successfully refunded by the user, address: " + swap.address);
|
|
401
|
-
//Also remove transaction from active subscriptions
|
|
402
|
-
this.unsubscribePayment(swap);
|
|
403
|
-
yield this.removeSwapData(swap, ToBtcSwapAbs_1.ToBtcSwapState.REFUNDED);
|
|
404
|
-
});
|
|
352
|
+
async processRefundEvent(chainIdentifier, swap, event) {
|
|
353
|
+
this.swapLogger.info(swap, "SC: RefundEvent: swap successfully refunded by the user, address: " + swap.address);
|
|
354
|
+
//Also remove transaction from active subscriptions
|
|
355
|
+
this.unsubscribePayment(swap);
|
|
356
|
+
await this.removeSwapData(swap, ToBtcSwapAbs_1.ToBtcSwapState.REFUNDED);
|
|
405
357
|
}
|
|
406
358
|
/**
|
|
407
359
|
* Returns required expiry delta for swap params
|
|
@@ -412,8 +364,8 @@ class ToBtcAbs extends ToBtcBaseSwapHandler_1.ToBtcBaseSwapHandler {
|
|
|
412
364
|
getExpiryFromCLTV(confirmationTarget, confirmations) {
|
|
413
365
|
//Blocks = 10 + (confirmations + confirmationTarget)*2
|
|
414
366
|
//Time = 3600 + (600*blocks*2)
|
|
415
|
-
const cltv = this.config.minChainCltv
|
|
416
|
-
return this.config.gracePeriod
|
|
367
|
+
const cltv = this.config.minChainCltv + (BigInt(confirmations + confirmationTarget) * this.config.sendSafetyFactor);
|
|
368
|
+
return this.config.gracePeriod + (this.config.bitcoinBlocktime * cltv * this.config.safetyFactor);
|
|
417
369
|
}
|
|
418
370
|
/**
|
|
419
371
|
* Checks if the requested nonce is valid
|
|
@@ -422,15 +374,14 @@ class ToBtcAbs extends ToBtcBaseSwapHandler_1.ToBtcBaseSwapHandler {
|
|
|
422
374
|
* @throws {DefinedRuntimeError} will throw an error if the nonce is invalid
|
|
423
375
|
*/
|
|
424
376
|
checkNonceValid(nonce) {
|
|
425
|
-
if (nonce
|
|
377
|
+
if (nonce < 0 || nonce >= (2n ** 64n))
|
|
426
378
|
throw {
|
|
427
379
|
code: 20021,
|
|
428
380
|
msg: "Invalid request body (nonce - cannot be parsed)"
|
|
429
381
|
};
|
|
430
|
-
const
|
|
431
|
-
const
|
|
432
|
-
|
|
433
|
-
if (firstPart.gt(maxAllowedValue))
|
|
382
|
+
const firstPart = nonce >> 24n;
|
|
383
|
+
const maxAllowedValue = BigInt(Math.floor(Date.now() / 1000) - 600000000);
|
|
384
|
+
if (firstPart > maxAllowedValue)
|
|
434
385
|
throw {
|
|
435
386
|
code: 20022,
|
|
436
387
|
msg: "Invalid request body (nonce - too high)"
|
|
@@ -501,9 +452,9 @@ class ToBtcAbs extends ToBtcBaseSwapHandler_1.ToBtcBaseSwapHandler {
|
|
|
501
452
|
* @param swap
|
|
502
453
|
* @throws {DefinedRuntimeError} will throw an error if the swap is expired
|
|
503
454
|
*/
|
|
504
|
-
checkExpired(swap) {
|
|
455
|
+
async checkExpired(swap) {
|
|
505
456
|
const { swapContract, signer } = this.getChain(swap.chainIdentifier);
|
|
506
|
-
const isExpired = swapContract.isExpired(signer.getAddress(), swap.data);
|
|
457
|
+
const isExpired = await swapContract.isExpired(signer.getAddress(), swap.data);
|
|
507
458
|
if (isExpired)
|
|
508
459
|
throw {
|
|
509
460
|
_httpStatus: 200,
|
|
@@ -518,27 +469,24 @@ class ToBtcAbs extends ToBtcBaseSwapHandler_1.ToBtcBaseSwapHandler {
|
|
|
518
469
|
* @param amount
|
|
519
470
|
* @throws {DefinedRuntimeError} will throw an error if there are not enough BTC funds
|
|
520
471
|
*/
|
|
521
|
-
checkAndGetNetworkFee(address, amount) {
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
msg: "Not enough liquidity"
|
|
529
|
-
};
|
|
530
|
-
return {
|
|
531
|
-
networkFee: new BN(chainFeeResp.networkFee),
|
|
532
|
-
satsPerVbyte: new BN(chainFeeResp.satsPerVbyte)
|
|
472
|
+
async checkAndGetNetworkFee(address, amount) {
|
|
473
|
+
let chainFeeResp = await this.bitcoin.estimateFee(address, Number(amount), null, this.config.networkFeeMultiplier);
|
|
474
|
+
const hasEnoughFunds = chainFeeResp != null;
|
|
475
|
+
if (!hasEnoughFunds)
|
|
476
|
+
throw {
|
|
477
|
+
code: 20002,
|
|
478
|
+
msg: "Not enough liquidity"
|
|
533
479
|
};
|
|
534
|
-
|
|
480
|
+
return {
|
|
481
|
+
networkFee: BigInt(chainFeeResp.networkFee),
|
|
482
|
+
satsPerVbyte: BigInt(chainFeeResp.satsPerVbyte)
|
|
483
|
+
};
|
|
535
484
|
}
|
|
536
485
|
startRestServer(restServer) {
|
|
537
486
|
restServer.use(this.path + "/payInvoice", (0, ServerParamDecoder_1.serverParamDecoder)(10 * 1000));
|
|
538
|
-
restServer.post(this.path + "/payInvoice", (0, Utils_1.expressHandlerWrapper)((req, res) =>
|
|
539
|
-
var _a;
|
|
487
|
+
restServer.post(this.path + "/payInvoice", (0, Utils_1.expressHandlerWrapper)(async (req, res) => {
|
|
540
488
|
const metadata = { request: {}, times: {} };
|
|
541
|
-
const chainIdentifier =
|
|
489
|
+
const chainIdentifier = req.query.chain ?? this.chains.default;
|
|
542
490
|
const { swapContract, signer } = this.getChain(chainIdentifier);
|
|
543
491
|
metadata.times.requestReceived = Date.now();
|
|
544
492
|
/**
|
|
@@ -555,12 +503,12 @@ class ToBtcAbs extends ToBtcBaseSwapHandler_1.ToBtcBaseSwapHandler {
|
|
|
555
503
|
*Sent later:
|
|
556
504
|
* feeRate: string Fee rate to use for the init signature
|
|
557
505
|
*/
|
|
558
|
-
const parsedBody =
|
|
506
|
+
const parsedBody = await req.paramReader.getParams({
|
|
559
507
|
address: SchemaVerifier_1.FieldTypeEnum.String,
|
|
560
|
-
amount: SchemaVerifier_1.FieldTypeEnum.
|
|
508
|
+
amount: SchemaVerifier_1.FieldTypeEnum.BigInt,
|
|
561
509
|
confirmationTarget: SchemaVerifier_1.FieldTypeEnum.Number,
|
|
562
510
|
confirmations: SchemaVerifier_1.FieldTypeEnum.Number,
|
|
563
|
-
nonce: SchemaVerifier_1.FieldTypeEnum.
|
|
511
|
+
nonce: SchemaVerifier_1.FieldTypeEnum.BigInt,
|
|
564
512
|
token: (val) => val != null &&
|
|
565
513
|
typeof (val) === "string" &&
|
|
566
514
|
this.isTokenSupported(chainIdentifier, val) ? val : null,
|
|
@@ -588,41 +536,41 @@ class ToBtcAbs extends ToBtcBaseSwapHandler_1.ToBtcBaseSwapHandler {
|
|
|
588
536
|
this.checkConfirmationTarget(parsedBody.confirmationTarget);
|
|
589
537
|
this.checkRequiredConfirmations(parsedBody.confirmations);
|
|
590
538
|
this.checkAddress(parsedBody.address);
|
|
591
|
-
|
|
592
|
-
const fees =
|
|
539
|
+
await this.checkVaultInitialized(chainIdentifier, parsedBody.token);
|
|
540
|
+
const fees = await this.preCheckAmounts(request, requestedAmount, useToken);
|
|
593
541
|
metadata.times.requestChecked = Date.now();
|
|
594
542
|
//Initialize abort controller for the parallel async operations
|
|
595
543
|
const abortController = this.getAbortController(responseStream);
|
|
596
544
|
const { pricePrefetchPromise, signDataPrefetchPromise } = this.getToBtcPrefetches(chainIdentifier, useToken, responseStream, abortController);
|
|
597
|
-
const { amountBD, networkFeeData, totalInToken, swapFee, swapFeeInToken, networkFeeInToken } =
|
|
545
|
+
const { amountBD, networkFeeData, totalInToken, swapFee, swapFeeInToken, networkFeeInToken } = await this.checkToBtcAmount(request, requestedAmount, fees, useToken, async (amount) => {
|
|
598
546
|
metadata.times.amountsChecked = Date.now();
|
|
599
|
-
const resp =
|
|
547
|
+
const resp = await this.checkAndGetNetworkFee(parsedBody.address, amount);
|
|
600
548
|
metadata.times.chainFeeCalculated = Date.now();
|
|
601
549
|
return resp;
|
|
602
|
-
}
|
|
550
|
+
}, abortController.signal, pricePrefetchPromise);
|
|
603
551
|
metadata.times.priceCalculated = Date.now();
|
|
604
|
-
const paymentHash = this.getHash(chainIdentifier, parsedBody.address, parsedBody.nonce, amountBD).toString("hex");
|
|
552
|
+
const paymentHash = this.getHash(chainIdentifier, parsedBody.address, parsedBody.confirmations, parsedBody.nonce, amountBD).toString("hex");
|
|
605
553
|
//Add grace period another time, so the user has 1 hour to commit
|
|
606
|
-
const expirySeconds = this.getExpiryFromCLTV(parsedBody.confirmationTarget, parsedBody.confirmations)
|
|
607
|
-
const currentTimestamp =
|
|
608
|
-
const minRequiredExpiry = currentTimestamp
|
|
609
|
-
const sequence =
|
|
610
|
-
const payObject =
|
|
554
|
+
const expirySeconds = this.getExpiryFromCLTV(parsedBody.confirmationTarget, parsedBody.confirmations) + this.config.gracePeriod;
|
|
555
|
+
const currentTimestamp = BigInt(Math.floor(Date.now() / 1000));
|
|
556
|
+
const minRequiredExpiry = currentTimestamp + expirySeconds;
|
|
557
|
+
const sequence = base_1.BigIntBufferUtils.fromBuffer((0, crypto_1.randomBytes)(8));
|
|
558
|
+
const payObject = await swapContract.createSwapData(base_1.ChainSwapType.CHAIN_NONCED, parsedBody.offerer, signer.getAddress(), useToken, totalInToken, paymentHash, sequence, minRequiredExpiry, true, false, 0n, 0n);
|
|
611
559
|
abortController.signal.throwIfAborted();
|
|
612
560
|
metadata.times.swapCreated = Date.now();
|
|
613
|
-
const sigData =
|
|
561
|
+
const sigData = await this.getToBtcSignatureData(chainIdentifier, payObject, req, abortController.signal, signDataPrefetchPromise);
|
|
614
562
|
metadata.times.swapSigned = Date.now();
|
|
615
|
-
const createdSwap = new ToBtcSwapAbs_1.ToBtcSwapAbs(chainIdentifier, parsedBody.address, amountBD, swapFee, swapFeeInToken, networkFeeData.networkFee, networkFeeInToken, networkFeeData.satsPerVbyte, parsedBody.nonce, parsedBody.confirmationTarget);
|
|
563
|
+
const createdSwap = new ToBtcSwapAbs_1.ToBtcSwapAbs(chainIdentifier, parsedBody.address, amountBD, swapFee, swapFeeInToken, networkFeeData.networkFee, networkFeeInToken, networkFeeData.satsPerVbyte, parsedBody.nonce, parsedBody.confirmations, parsedBody.confirmationTarget);
|
|
616
564
|
createdSwap.data = payObject;
|
|
617
565
|
createdSwap.metadata = metadata;
|
|
618
566
|
createdSwap.prefix = sigData.prefix;
|
|
619
567
|
createdSwap.timeout = sigData.timeout;
|
|
620
568
|
createdSwap.signature = sigData.signature;
|
|
621
569
|
createdSwap.feeRate = sigData.feeRate;
|
|
622
|
-
|
|
623
|
-
|
|
570
|
+
await PluginManager_1.PluginManager.swapCreate(createdSwap);
|
|
571
|
+
await this.saveSwapData(createdSwap);
|
|
624
572
|
this.swapLogger.info(createdSwap, "REST: /payInvoice: created swap address: " + createdSwap.address + " amount: " + amountBD.toString(10));
|
|
625
|
-
|
|
573
|
+
await responseStream.writeParamsAndEnd({
|
|
626
574
|
code: 20000,
|
|
627
575
|
msg: "Success",
|
|
628
576
|
data: {
|
|
@@ -631,7 +579,7 @@ class ToBtcAbs extends ToBtcBaseSwapHandler_1.ToBtcBaseSwapHandler {
|
|
|
631
579
|
satsPervByte: networkFeeData.satsPerVbyte.toString(10),
|
|
632
580
|
networkFee: networkFeeInToken.toString(10),
|
|
633
581
|
swapFee: swapFeeInToken.toString(10),
|
|
634
|
-
totalFee: swapFeeInToken
|
|
582
|
+
totalFee: (swapFeeInToken + networkFeeInToken).toString(10),
|
|
635
583
|
total: totalInToken.toString(10),
|
|
636
584
|
minRequiredExpiry: minRequiredExpiry.toString(10),
|
|
637
585
|
data: payObject.serialize(),
|
|
@@ -640,18 +588,17 @@ class ToBtcAbs extends ToBtcBaseSwapHandler_1.ToBtcBaseSwapHandler {
|
|
|
640
588
|
signature: sigData.signature
|
|
641
589
|
}
|
|
642
590
|
});
|
|
643
|
-
}))
|
|
644
|
-
const getRefundAuthorization = (0, Utils_1.expressHandlerWrapper)((req, res) =>
|
|
591
|
+
}));
|
|
592
|
+
const getRefundAuthorization = (0, Utils_1.expressHandlerWrapper)(async (req, res) => {
|
|
645
593
|
/**
|
|
646
594
|
* paymentHash: string Payment hash identifier of the swap
|
|
647
595
|
* sequence: BN Sequence identifier of the swap
|
|
648
596
|
*/
|
|
649
|
-
const parsedBody = (0, SchemaVerifier_1.verifySchema)(
|
|
597
|
+
const parsedBody = (0, SchemaVerifier_1.verifySchema)({ ...req.body, ...req.query }, {
|
|
650
598
|
paymentHash: (val) => val != null &&
|
|
651
599
|
typeof (val) === "string" &&
|
|
652
|
-
val.length === 64 &&
|
|
653
600
|
Utils_1.HEX_REGEX.test(val) ? val : null,
|
|
654
|
-
sequence: SchemaVerifier_1.FieldTypeEnum.
|
|
601
|
+
sequence: SchemaVerifier_1.FieldTypeEnum.BigInt
|
|
655
602
|
});
|
|
656
603
|
if (parsedBody == null)
|
|
657
604
|
throw {
|
|
@@ -659,14 +606,14 @@ class ToBtcAbs extends ToBtcBaseSwapHandler_1.ToBtcBaseSwapHandler {
|
|
|
659
606
|
msg: "Invalid request body/query (paymentHash/sequence)"
|
|
660
607
|
};
|
|
661
608
|
this.checkSequence(parsedBody.sequence);
|
|
662
|
-
const payment =
|
|
609
|
+
const payment = await this.storageManager.getData(parsedBody.paymentHash, parsedBody.sequence);
|
|
663
610
|
if (payment == null || payment.state === ToBtcSwapAbs_1.ToBtcSwapState.SAVED)
|
|
664
611
|
throw {
|
|
665
612
|
_httpStatus: 200,
|
|
666
613
|
code: 20007,
|
|
667
614
|
msg: "Payment not found"
|
|
668
615
|
};
|
|
669
|
-
this.checkExpired(payment);
|
|
616
|
+
await this.checkExpired(payment);
|
|
670
617
|
if (payment.state === ToBtcSwapAbs_1.ToBtcSwapState.COMMITED)
|
|
671
618
|
throw {
|
|
672
619
|
_httpStatus: 200,
|
|
@@ -684,13 +631,13 @@ class ToBtcAbs extends ToBtcBaseSwapHandler_1.ToBtcBaseSwapHandler {
|
|
|
684
631
|
};
|
|
685
632
|
const { swapContract, signer } = this.getChain(payment.chainIdentifier);
|
|
686
633
|
if (payment.state === ToBtcSwapAbs_1.ToBtcSwapState.NON_PAYABLE) {
|
|
687
|
-
const isCommited =
|
|
634
|
+
const isCommited = await swapContract.isCommited(payment.data);
|
|
688
635
|
if (!isCommited)
|
|
689
636
|
throw {
|
|
690
637
|
code: 20005,
|
|
691
638
|
msg: "Not committed"
|
|
692
639
|
};
|
|
693
|
-
const refundResponse =
|
|
640
|
+
const refundResponse = await swapContract.getRefundSignature(signer, payment.data, this.config.refundAuthorizationTimeout);
|
|
694
641
|
//Double check the state after promise result
|
|
695
642
|
if (payment.state !== ToBtcSwapAbs_1.ToBtcSwapState.NON_PAYABLE)
|
|
696
643
|
throw {
|
|
@@ -715,7 +662,7 @@ class ToBtcAbs extends ToBtcBaseSwapHandler_1.ToBtcBaseSwapHandler {
|
|
|
715
662
|
code: 20009,
|
|
716
663
|
msg: "Invalid payment status"
|
|
717
664
|
};
|
|
718
|
-
})
|
|
665
|
+
});
|
|
719
666
|
restServer.post(this.path + "/getRefundAuthorization", getRefundAuthorization);
|
|
720
667
|
restServer.get(this.path + "/getRefundAuthorization", getRefundAuthorization);
|
|
721
668
|
this.logger.info("started at path: ", this.path);
|
|
@@ -723,35 +670,26 @@ class ToBtcAbs extends ToBtcBaseSwapHandler_1.ToBtcBaseSwapHandler {
|
|
|
723
670
|
/**
|
|
724
671
|
* Starts watchdog checking sent bitcoin transactions
|
|
725
672
|
*/
|
|
726
|
-
startTxTimer() {
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
yield rerun();
|
|
734
|
-
});
|
|
673
|
+
async startTxTimer() {
|
|
674
|
+
let rerun;
|
|
675
|
+
rerun = async () => {
|
|
676
|
+
await this.processBtcTxs().catch(e => this.logger.error("startTxTimer(): call to processBtcTxs() errored", e));
|
|
677
|
+
setTimeout(rerun, this.config.txCheckInterval);
|
|
678
|
+
};
|
|
679
|
+
await rerun();
|
|
735
680
|
}
|
|
736
|
-
startWatchdog() {
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
});
|
|
740
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
741
|
-
yield _super.startWatchdog.call(this);
|
|
742
|
-
yield this.startTxTimer();
|
|
743
|
-
});
|
|
681
|
+
async startWatchdog() {
|
|
682
|
+
await super.startWatchdog();
|
|
683
|
+
await this.startTxTimer();
|
|
744
684
|
}
|
|
745
|
-
init() {
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
yield PluginManager_1.PluginManager.serviceInitialize(this);
|
|
750
|
-
});
|
|
685
|
+
async init() {
|
|
686
|
+
await this.loadData(ToBtcSwapAbs_1.ToBtcSwapAbs);
|
|
687
|
+
this.subscribeToEvents();
|
|
688
|
+
await PluginManager_1.PluginManager.serviceInitialize(this);
|
|
751
689
|
}
|
|
752
690
|
getInfoData() {
|
|
753
691
|
return {
|
|
754
|
-
minCltv: this.config.minChainCltv
|
|
692
|
+
minCltv: Number(this.config.minChainCltv),
|
|
755
693
|
minConfirmations: this.config.minConfirmations,
|
|
756
694
|
maxConfirmations: this.config.maxConfirmations,
|
|
757
695
|
minConfTarget: this.config.minConfTarget,
|