@atomiqlabs/lp-lib 10.3.11 → 11.0.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.
Files changed (97) hide show
  1. package/dist/index.d.ts +3 -1
  2. package/dist/index.js +3 -4
  3. package/dist/plugins/IPlugin.d.ts +3 -2
  4. package/dist/plugins/PluginManager.d.ts +3 -2
  5. package/dist/plugins/PluginManager.js +2 -2
  6. package/dist/prices/OKXSwapPrice.d.ts +27 -0
  7. package/dist/prices/OKXSwapPrice.js +106 -0
  8. package/dist/swaps/FromBtcBaseSwap.d.ts +5 -1
  9. package/dist/swaps/FromBtcBaseSwap.js +20 -0
  10. package/dist/swaps/FromBtcBaseSwapHandler.d.ts +1 -0
  11. package/dist/swaps/FromBtcBaseSwapHandler.js +1 -1
  12. package/dist/swaps/FromBtcLnBaseSwapHandler.d.ts +8 -6
  13. package/dist/swaps/FromBtcLnBaseSwapHandler.js +7 -5
  14. package/dist/swaps/SwapHandler.d.ts +1 -4
  15. package/dist/swaps/SwapHandler.js +1 -2
  16. package/dist/swaps/SwapHandlerSwap.d.ts +4 -0
  17. package/dist/swaps/SwapHandlerSwap.js +9 -1
  18. package/dist/swaps/ToBtcBaseSwap.d.ts +3 -1
  19. package/dist/swaps/ToBtcBaseSwap.js +8 -2
  20. package/dist/swaps/ToBtcBaseSwapHandler.d.ts +1 -0
  21. package/dist/swaps/ToBtcBaseSwapHandler.js +1 -1
  22. package/dist/swaps/frombtc_abstract/FromBtcAbs.d.ts +3 -5
  23. package/dist/swaps/frombtc_abstract/FromBtcAbs.js +18 -25
  24. package/dist/swaps/frombtc_abstract/FromBtcSwapAbs.d.ts +1 -4
  25. package/dist/swaps/frombtc_abstract/FromBtcSwapAbs.js +3 -16
  26. package/dist/swaps/frombtc_trusted/FromBtcTrusted.d.ts +6 -9
  27. package/dist/swaps/frombtc_trusted/FromBtcTrusted.js +238 -137
  28. package/dist/swaps/frombtc_trusted/FromBtcTrustedSwap.d.ts +9 -6
  29. package/dist/swaps/frombtc_trusted/FromBtcTrustedSwap.js +15 -10
  30. package/dist/swaps/frombtcln_abstract/FromBtcLnAbs.d.ts +2 -2
  31. package/dist/swaps/frombtcln_abstract/FromBtcLnAbs.js +42 -62
  32. package/dist/swaps/frombtcln_abstract/FromBtcLnSwapAbs.d.ts +1 -6
  33. package/dist/swaps/frombtcln_abstract/FromBtcLnSwapAbs.js +2 -14
  34. package/dist/swaps/frombtcln_trusted/FromBtcLnTrusted.d.ts +3 -5
  35. package/dist/swaps/frombtcln_trusted/FromBtcLnTrusted.js +90 -87
  36. package/dist/swaps/frombtcln_trusted/FromBtcLnTrustedSwap.d.ts +1 -2
  37. package/dist/swaps/frombtcln_trusted/FromBtcLnTrustedSwap.js +5 -8
  38. package/dist/swaps/tobtc_abstract/ToBtcAbs.d.ts +5 -125
  39. package/dist/swaps/tobtc_abstract/ToBtcAbs.js +41 -334
  40. package/dist/swaps/tobtc_abstract/ToBtcSwapAbs.d.ts +1 -4
  41. package/dist/swaps/tobtc_abstract/ToBtcSwapAbs.js +2 -11
  42. package/dist/swaps/tobtcln_abstract/ToBtcLnAbs.d.ts +5 -55
  43. package/dist/swaps/tobtcln_abstract/ToBtcLnAbs.js +152 -398
  44. package/dist/swaps/tobtcln_abstract/ToBtcLnSwapAbs.d.ts +1 -6
  45. package/dist/swaps/tobtcln_abstract/ToBtcLnSwapAbs.js +2 -15
  46. package/dist/utils/Utils.d.ts +0 -10
  47. package/dist/utils/Utils.js +1 -34
  48. package/dist/wallets/IBitcoinWallet.d.ts +62 -0
  49. package/dist/wallets/IBitcoinWallet.js +2 -0
  50. package/dist/wallets/ILightningWallet.d.ts +118 -0
  51. package/dist/wallets/ILightningWallet.js +37 -0
  52. package/package.json +4 -9
  53. package/src/index.ts +4 -5
  54. package/src/plugins/IPlugin.ts +4 -2
  55. package/src/plugins/PluginManager.ts +6 -3
  56. package/src/prices/OKXSwapPrice.ts +114 -0
  57. package/src/swaps/FromBtcBaseSwap.ts +24 -1
  58. package/src/swaps/FromBtcBaseSwapHandler.ts +6 -2
  59. package/src/swaps/FromBtcLnBaseSwapHandler.ts +22 -6
  60. package/src/swaps/SwapHandler.ts +1 -8
  61. package/src/swaps/SwapHandlerSwap.ts +14 -1
  62. package/src/swaps/ToBtcBaseSwap.ts +12 -3
  63. package/src/swaps/ToBtcBaseSwapHandler.ts +6 -2
  64. package/src/swaps/frombtc_abstract/FromBtcAbs.ts +24 -28
  65. package/src/swaps/frombtc_abstract/FromBtcSwapAbs.ts +3 -18
  66. package/src/swaps/frombtc_trusted/FromBtcTrusted.ts +260 -159
  67. package/src/swaps/frombtc_trusted/FromBtcTrustedSwap.ts +22 -15
  68. package/src/swaps/frombtcln_abstract/FromBtcLnAbs.ts +69 -79
  69. package/src/swaps/frombtcln_abstract/FromBtcLnSwapAbs.ts +3 -20
  70. package/src/swaps/frombtcln_trusted/FromBtcLnTrusted.ts +108 -103
  71. package/src/swaps/frombtcln_trusted/FromBtcLnTrustedSwap.ts +6 -9
  72. package/src/swaps/tobtc_abstract/ToBtcAbs.ts +52 -410
  73. package/src/swaps/tobtc_abstract/ToBtcSwapAbs.ts +3 -18
  74. package/src/swaps/tobtcln_abstract/ToBtcLnAbs.ts +157 -434
  75. package/src/swaps/tobtcln_abstract/ToBtcLnSwapAbs.ts +3 -20
  76. package/src/utils/Utils.ts +0 -31
  77. package/src/wallets/IBitcoinWallet.ts +66 -0
  78. package/src/wallets/ILightningWallet.ts +179 -0
  79. package/dist/fees/OneDollarFeeEstimator.d.ts +0 -16
  80. package/dist/fees/OneDollarFeeEstimator.js +0 -71
  81. package/dist/utils/coinselect2/accumulative.d.ts +0 -6
  82. package/dist/utils/coinselect2/accumulative.js +0 -44
  83. package/dist/utils/coinselect2/blackjack.d.ts +0 -6
  84. package/dist/utils/coinselect2/blackjack.js +0 -41
  85. package/dist/utils/coinselect2/index.d.ts +0 -16
  86. package/dist/utils/coinselect2/index.js +0 -40
  87. package/dist/utils/coinselect2/utils.d.ts +0 -64
  88. package/dist/utils/coinselect2/utils.js +0 -121
  89. package/src/fees/OneDollarFeeEstimator.ts +0 -95
  90. package/src/utils/coinselect2/accumulative.js +0 -32
  91. package/src/utils/coinselect2/accumulative.ts +0 -58
  92. package/src/utils/coinselect2/blackjack.js +0 -29
  93. package/src/utils/coinselect2/blackjack.ts +0 -54
  94. package/src/utils/coinselect2/index.js +0 -16
  95. package/src/utils/coinselect2/index.ts +0 -50
  96. package/src/utils/coinselect2/utils.js +0 -110
  97. package/src/utils/coinselect2/utils.ts +0 -183
@@ -14,19 +14,15 @@ const FromBtcBaseSwapHandler_1 = require("../FromBtcBaseSwapHandler");
14
14
  const FromBtcTrustedSwap_1 = require("./FromBtcTrustedSwap");
15
15
  const SwapHandler_1 = require("../SwapHandler");
16
16
  const BN = require("bn.js");
17
- const lightning_1 = require("lightning");
18
17
  const PluginManager_1 = require("../../plugins/PluginManager");
19
- const bitcoinjs_lib_1 = require("bitcoinjs-lib");
20
- const utils_1 = require("../../utils/coinselect2/utils");
21
18
  const Utils_1 = require("../../utils/Utils");
22
19
  const SchemaVerifier_1 = require("../../utils/paramcoders/SchemaVerifier");
23
- const bitcoin = require("bitcoinjs-lib");
24
20
  const ServerParamDecoder_1 = require("../../utils/paramcoders/server/ServerParamDecoder");
25
21
  class FromBtcTrusted extends FromBtcBaseSwapHandler_1.FromBtcBaseSwapHandler {
26
- constructor(storageDirectory, path, chains, lnd, swapPricing, bitcoinRpc, config) {
22
+ constructor(storageDirectory, path, chains, bitcoin, swapPricing, bitcoinRpc, config) {
27
23
  var _a;
28
24
  var _b;
29
- super(storageDirectory, path, chains, lnd, swapPricing);
25
+ super(storageDirectory, path, chains, swapPricing);
30
26
  this.type = SwapHandler_1.SwapHandlerType.FROM_BTC_TRUSTED;
31
27
  this.subscriptions = new Map();
32
28
  this.doubleSpendWatchdogSwaps = new Set();
@@ -35,60 +31,51 @@ class FromBtcTrusted extends FromBtcBaseSwapHandler_1.FromBtcBaseSwapHandler {
35
31
  this.processedTxIds = new Map();
36
32
  this.config = config;
37
33
  (_a = (_b = this.config).recommendFeeMultiplier) !== null && _a !== void 0 ? _a : (_b.recommendFeeMultiplier = 1.25);
34
+ this.bitcoin = bitcoin;
38
35
  this.bitcoinRpc = bitcoinRpc;
39
36
  for (let chainId in chains.chains) {
40
37
  this.allowedTokens[chainId] = new Set([chains.chains[chainId].swapContract.getNativeCurrencyAddress()]);
41
38
  }
42
39
  }
43
40
  getAllAncestors(tx) {
44
- return Promise.all(tx.inputs.map(input => this.bitcoinRpc.getTransaction(input.transaction_id).then(tx => {
45
- return { tx, vout: input.transaction_vout };
41
+ return Promise.all(tx.ins.map(input => this.bitcoinRpc.getTransaction(input.txid).then(tx => {
42
+ return { tx, vout: input.vout };
46
43
  })));
47
44
  }
48
45
  refundSwap(swap) {
49
46
  return __awaiter(this, void 0, void 0, function* () {
47
+ if (swap.refundAddress == null) {
48
+ if (swap.state !== FromBtcTrustedSwap_1.FromBtcTrustedSwapState.REFUNDABLE) {
49
+ yield swap.setState(FromBtcTrustedSwap_1.FromBtcTrustedSwapState.REFUNDABLE);
50
+ yield this.storageManager.saveData(swap.getHash(), swap.getSequence(), swap);
51
+ }
52
+ return;
53
+ }
50
54
  let unlock = swap.lock(30 * 1000);
51
55
  if (unlock == null)
52
56
  return;
53
- const feeRate = yield this.config.feeEstimator.estimateFee();
54
- const initialTx = bitcoinjs_lib_1.Transaction.fromHex(swap.rawTx);
55
- const ourOutput = initialTx.outs[swap.vout];
56
- //Construct PSBT
57
- const refundOutputScript = bitcoinjs_lib_1.address.toOutputScript(swap.refundAddress, this.config.bitcoinNetwork);
58
- const txBytes = utils_1.utils.transactionBytes([{ type: "p2wpkh" }], [{ script: refundOutputScript }], "p2wpkh");
59
- const txFee = txBytes * feeRate;
60
- const adjustedOutput = ourOutput.value - txFee;
61
- if (adjustedOutput < 546) {
57
+ const feeRate = yield this.bitcoin.getFeeRate();
58
+ const ourOutput = swap.btcTx.outs[swap.vout];
59
+ const resp = yield this.bitcoin.drainAll(swap.refundAddress, [{
60
+ type: this.bitcoin.getAddressType(),
61
+ confirmations: swap.btcTx.confirmations,
62
+ outputScript: Buffer.from(ourOutput.scriptPubKey.hex, "hex"),
63
+ value: ourOutput.value,
64
+ txId: swap.btcTx.txid,
65
+ vout: swap.vout
66
+ }], feeRate);
67
+ if (resp == null) {
62
68
  this.swapLogger.error(swap, "refundSwap(): cannot refund swap because of dust limit, txId: " + swap.txId);
63
69
  unlock();
64
70
  return;
65
71
  }
66
- //Construct PSBT
67
- const _psbt = new bitcoinjs_lib_1.Psbt({ network: this.config.bitcoinNetwork });
68
- _psbt.addInput({
69
- hash: initialTx.getHash(),
70
- index: swap.vout,
71
- witnessUtxo: ourOutput,
72
- sighashType: 0x01,
73
- sequence: 0xfffffffd
74
- });
75
- _psbt.addOutput({
76
- script: refundOutputScript,
77
- value: adjustedOutput
78
- });
79
- //Sign
80
- const { psbt, transaction } = yield (0, lightning_1.signPsbt)({
81
- lnd: this.LND,
82
- psbt: _psbt.toHex()
83
- });
84
72
  if (swap.metadata != null)
85
73
  swap.metadata.times.refundSignPSBT = Date.now();
86
- this.swapLogger.debug(swap, "refundSwap(): signed raw transaction: " + transaction);
87
- const signedTx = bitcoinjs_lib_1.Transaction.fromHex(transaction);
88
- const refundTxId = signedTx.getId();
74
+ this.swapLogger.debug(swap, "refundSwap(): signed raw transaction: " + resp.raw);
75
+ const refundTxId = resp.txId;
89
76
  swap.refundTxId = refundTxId;
90
77
  //Send the refund TX
91
- yield (0, lightning_1.broadcastChainTransaction)({ transaction, lnd: this.LND });
78
+ yield this.bitcoin.sendRawTransaction(resp.raw);
92
79
  this.swapLogger.debug(swap, "refundSwap(): sent refund transaction: " + refundTxId);
93
80
  this.refundedSwaps.set(swap.getHash(), refundTxId);
94
81
  yield this.removeSwapData(swap, FromBtcTrustedSwap_1.FromBtcTrustedSwapState.REFUNDED);
@@ -97,67 +84,66 @@ class FromBtcTrusted extends FromBtcBaseSwapHandler_1.FromBtcBaseSwapHandler {
97
84
  }
98
85
  burn(swap) {
99
86
  return __awaiter(this, void 0, void 0, function* () {
100
- const initialTx = bitcoinjs_lib_1.Transaction.fromHex(swap.rawTx);
101
- const ourOutput = initialTx.outs[swap.vout];
87
+ const ourOutput = swap.btcTx.outs[swap.vout];
88
+ //Check if we can even increase the feeRate by burning
89
+ const txSize = 110;
90
+ const burnTxFeeRate = Math.floor(ourOutput.value / txSize);
91
+ const initialTxFeeRate = Math.ceil(swap.txFee / swap.txSize);
92
+ if (burnTxFeeRate < initialTxFeeRate) {
93
+ this.swapLogger.warn(swap, "burn(): cannot send burn transaction, pays too little fee, " +
94
+ "initialTxId: " + swap.txId + " initialTxFeeRate: " + initialTxFeeRate + " burnTxFeeRate: " + burnTxFeeRate);
95
+ this.doubleSpentSwaps.set(swap.getHash(), null);
96
+ yield this.removeSwapData(swap, FromBtcTrustedSwap_1.FromBtcTrustedSwapState.DOUBLE_SPENT);
97
+ return;
98
+ }
102
99
  //Construct PSBT
103
- const _psbt = new bitcoinjs_lib_1.Psbt({ network: this.config.bitcoinNetwork });
104
- _psbt.addInput({
105
- hash: initialTx.getHash(),
106
- index: swap.vout,
107
- witnessUtxo: ourOutput,
108
- sighashType: 0x01,
109
- sequence: 0xfffffffd
110
- });
111
- _psbt.addOutput({
112
- script: Buffer.concat([Buffer.from([0x6a, 20]), Buffer.from("BURN, BABY, BURN! AQ", "ascii")]),
113
- value: 0
114
- });
115
- //Sign
116
- const { psbt, transaction } = yield (0, lightning_1.signPsbt)({
117
- lnd: this.LND,
118
- psbt: _psbt.toHex()
119
- });
100
+ const resp = yield this.bitcoin.burnAll([{
101
+ type: this.bitcoin.getAddressType(),
102
+ confirmations: swap.btcTx.confirmations,
103
+ outputScript: Buffer.from(ourOutput.scriptPubKey.hex, "hex"),
104
+ value: ourOutput.value,
105
+ txId: swap.btcTx.txid,
106
+ vout: swap.vout
107
+ }]);
120
108
  if (swap.metadata != null)
121
109
  swap.metadata.times.burnSignPSBT = Date.now();
122
- this.swapLogger.debug(swap, "burn(): signed raw transaction: " + transaction);
123
- const signedTx = bitcoinjs_lib_1.Transaction.fromHex(transaction);
124
- const burnTxId = signedTx.getId();
110
+ this.swapLogger.debug(swap, "burn(): signed raw transaction: " + resp.raw);
111
+ const burnTxId = resp.txId;
125
112
  swap.burnTxId = burnTxId;
126
113
  //Send the original TX + our burn TX as a package
127
- const sendTxns = [swap.rawTx, transaction];
128
- yield this.bitcoinRpc.sendRawPackage(sendTxns);
129
- this.swapLogger.debug(swap, "burn(): sent burn transaction: " + burnTxId);
114
+ const sendTxns = [swap.btcTx.raw, resp.raw];
115
+ //TODO: We should handle this in a better way
116
+ try {
117
+ yield this.bitcoinRpc.sendRawPackage(sendTxns);
118
+ this.swapLogger.debug(swap, "burn(): sent burn transaction: " + burnTxId);
119
+ }
120
+ catch (e) {
121
+ this.swapLogger.error(swap, "burn(): error sending burn package: ", e);
122
+ }
130
123
  this.doubleSpentSwaps.set(swap.getHash(), burnTxId);
131
124
  yield this.removeSwapData(swap, FromBtcTrustedSwap_1.FromBtcTrustedSwapState.DOUBLE_SPENT);
132
125
  });
133
126
  }
134
- processPastSwap(swap, tx) {
127
+ processPastSwap(swap, tx, vout) {
135
128
  return __awaiter(this, void 0, void 0, function* () {
136
- let parsedTx = null;
137
- let foundVout = null;
138
- let vout = -1;
139
- if (tx != null) {
140
- parsedTx = bitcoinjs_lib_1.Transaction.fromHex(tx.transaction);
141
- const requiredOutputScript = bitcoinjs_lib_1.address.toOutputScript(swap.btcAddress, this.config.bitcoinNetwork);
142
- vout = parsedTx.outs.findIndex(vout => vout.script.equals(requiredOutputScript));
143
- if (vout !== -1)
144
- foundVout = parsedTx.outs[vout];
145
- }
129
+ const foundVout = tx.outs[vout];
146
130
  const { swapContract, signer } = this.getChain(swap.chainIdentifier);
131
+ const outputScript = this.bitcoin.toOutputScript(swap.btcAddress).toString("hex");
147
132
  if (swap.state === FromBtcTrustedSwap_1.FromBtcTrustedSwapState.CREATED) {
148
- this.subscriptions.set(swap.btcAddress, swap);
133
+ this.subscriptions.set(outputScript, swap);
149
134
  if (foundVout == null) {
150
135
  //Check expiry
151
136
  if (swap.expiresAt < Date.now()) {
152
- this.subscriptions.delete(swap.btcAddress);
137
+ this.subscriptions.delete(outputScript);
138
+ yield this.bitcoin.addUnusedAddress(swap.btcAddress);
153
139
  yield this.removeSwapData(swap, FromBtcTrustedSwap_1.FromBtcTrustedSwapState.EXPIRED);
154
140
  return;
155
141
  }
156
142
  return;
157
143
  }
158
144
  const sentSats = new BN(foundVout.value);
159
- if (sentSats.eq(swap.inputSats)) {
160
- swap.adjustedInput = swap.inputSats;
145
+ if (sentSats.eq(swap.amount)) {
146
+ swap.adjustedInput = swap.amount;
161
147
  swap.adjustedOutput = swap.outputTokens;
162
148
  }
163
149
  else {
@@ -165,57 +151,70 @@ class FromBtcTrusted extends FromBtcBaseSwapHandler_1.FromBtcBaseSwapHandler {
165
151
  if (sentSats.lt(this.config.min))
166
152
  return;
167
153
  if (sentSats.gt(this.config.max)) {
168
- swap.rawTx = tx.transaction;
169
- swap.txId = tx.id;
154
+ swap.adjustedInput = sentSats;
155
+ swap.btcTx = tx;
156
+ swap.txId = tx.txid;
170
157
  swap.vout = vout;
171
- this.subscriptions.delete(swap.btcAddress);
158
+ this.subscriptions.delete(outputScript);
172
159
  yield this.refundSwap(swap);
173
160
  return;
174
161
  }
175
162
  //Adjust the amount
176
163
  swap.adjustedInput = sentSats;
177
- swap.adjustedOutput = swap.outputTokens.mul(sentSats).div(swap.inputSats);
164
+ swap.adjustedOutput = swap.outputTokens.mul(sentSats).div(swap.amount);
178
165
  }
179
- swap.rawTx = tx.transaction;
180
- swap.txId = tx.id;
166
+ swap.btcTx = tx;
167
+ swap.txId = tx.txid;
181
168
  swap.vout = vout;
182
- this.subscriptions.delete(swap.btcAddress);
169
+ this.subscriptions.delete(outputScript);
183
170
  yield swap.setState(FromBtcTrustedSwap_1.FromBtcTrustedSwapState.RECEIVED);
184
- yield this.storageManager.saveData(swap.getHash(), null, swap);
171
+ yield this.storageManager.saveData(swap.getHash(), swap.getSequence(), swap);
185
172
  }
186
173
  if (swap.state === FromBtcTrustedSwap_1.FromBtcTrustedSwapState.RECEIVED) {
187
174
  //Check if transaction still exists
188
- if (tx == null || foundVout == null || tx.id !== swap.txId) {
175
+ if (tx == null || foundVout == null || tx.txid !== swap.txId) {
189
176
  yield swap.setState(FromBtcTrustedSwap_1.FromBtcTrustedSwapState.CREATED);
190
- yield this.storageManager.saveData(swap.getHash(), null, swap);
177
+ yield this.storageManager.saveData(swap.getHash(), swap.getSequence(), swap);
191
178
  return;
192
179
  }
193
180
  //Check if it is confirmed
194
- if (tx.confirmation_count > 0) {
181
+ if (tx.confirmations > 0) {
195
182
  yield swap.setState(FromBtcTrustedSwap_1.FromBtcTrustedSwapState.BTC_CONFIRMED);
196
- yield this.storageManager.saveData(swap.getHash(), null, swap);
183
+ yield this.storageManager.saveData(swap.getHash(), swap.getSequence(), swap);
197
184
  }
198
185
  else {
199
186
  //Check if it pays high enough fee AND has confirmed ancestors
200
187
  const ancestors = yield this.getAllAncestors(tx);
201
188
  const allAncestorsConfirmed = ancestors.reduce((prev, curr) => prev && curr.tx.confirmations > 0, true);
202
189
  const totalInput = ancestors.reduce((prev, curr) => prev + curr.tx.outs[curr.vout].value, 0);
203
- const totalOutput = parsedTx.outs.reduce((prev, curr) => prev + curr.value, 0);
190
+ const totalOutput = tx.outs.reduce((prev, curr) => prev + curr.value, 0);
204
191
  const fee = totalInput - totalOutput;
205
- const feePerVbyte = Math.ceil(fee / parsedTx.virtualSize());
192
+ const feePerVbyte = Math.ceil(fee / tx.vsize);
206
193
  if (allAncestorsConfirmed &&
207
- (feePerVbyte >= swap.recommendedFee || feePerVbyte >= (yield this.config.feeEstimator.estimateFee()))) {
194
+ (feePerVbyte >= swap.recommendedFee || feePerVbyte >= (yield this.bitcoin.getFeeRate()))) {
208
195
  if (swap.state !== FromBtcTrustedSwap_1.FromBtcTrustedSwapState.RECEIVED)
209
196
  return;
197
+ swap.txSize = tx.vsize;
198
+ swap.txFee = fee;
210
199
  yield swap.setState(FromBtcTrustedSwap_1.FromBtcTrustedSwapState.BTC_CONFIRMED);
211
- yield this.storageManager.saveData(swap.getHash(), null, swap);
200
+ yield this.storageManager.saveData(swap.getHash(), swap.getSequence(), swap);
212
201
  }
213
202
  else {
214
203
  return;
215
204
  }
216
205
  }
217
206
  }
218
- if (swap.doubleSpent || tx == null || foundVout == null || tx.id !== swap.txId) {
207
+ if (swap.state === FromBtcTrustedSwap_1.FromBtcTrustedSwapState.REFUNDABLE) {
208
+ if (swap.refundAddress != null) {
209
+ yield this.refundSwap(swap);
210
+ return;
211
+ }
212
+ }
213
+ if (swap.doubleSpent || tx == null || foundVout == null || tx.txid !== swap.txId) {
214
+ if (swap.state === FromBtcTrustedSwap_1.FromBtcTrustedSwapState.REFUNDABLE) {
215
+ yield swap.setState(FromBtcTrustedSwap_1.FromBtcTrustedSwapState.CREATED);
216
+ return;
217
+ }
219
218
  if (!swap.doubleSpent) {
220
219
  swap.doubleSpent = true;
221
220
  try {
@@ -230,14 +229,13 @@ class FromBtcTrusted extends FromBtcBaseSwapHandler_1.FromBtcBaseSwapHandler {
230
229
  return;
231
230
  }
232
231
  else {
233
- if (!this.doubleSpendWatchdogSwaps.has(swap)) {
232
+ if (tx.confirmations <= 0 && !this.doubleSpendWatchdogSwaps.has(swap)) {
234
233
  this.swapLogger.debug(swap, "processPastSwap(): Adding swap transaction to double spend watchdog list: ", swap.txId);
235
234
  this.doubleSpendWatchdogSwaps.add(swap);
236
235
  }
237
236
  }
238
- if (tx.confirmation_count > 0) {
237
+ if (tx.confirmations > 0 && this.doubleSpendWatchdogSwaps.delete(swap)) {
239
238
  this.swapLogger.debug(swap, "processPastSwap(): Removing confirmed swap transaction from double spend watchdog list: ", swap.txId);
240
- this.doubleSpendWatchdogSwaps.delete(swap);
241
239
  }
242
240
  if (swap.state === FromBtcTrustedSwap_1.FromBtcTrustedSwapState.BTC_CONFIRMED) {
243
241
  //Send gas token
@@ -263,7 +261,7 @@ class FromBtcTrusted extends FromBtcBaseSwapHandler_1.FromBtcBaseSwapHandler {
263
261
  swap.scRawTx = rawTx;
264
262
  if (swap.state === FromBtcTrustedSwap_1.FromBtcTrustedSwapState.BTC_CONFIRMED) {
265
263
  yield swap.setState(FromBtcTrustedSwap_1.FromBtcTrustedSwapState.SENT);
266
- yield this.storageManager.saveData(swap.getHash(), null, swap);
264
+ yield this.storageManager.saveData(swap.getHash(), swap.getSequence(), swap);
267
265
  }
268
266
  if (unlock != null)
269
267
  unlock();
@@ -278,7 +276,7 @@ class FromBtcTrusted extends FromBtcBaseSwapHandler_1.FromBtcBaseSwapHandler {
278
276
  swap.txIds = { init: null };
279
277
  swap.scRawTx = null;
280
278
  yield swap.setState(FromBtcTrustedSwap_1.FromBtcTrustedSwapState.RECEIVED);
281
- yield this.storageManager.saveData(swap.getHash(), null, swap);
279
+ yield this.storageManager.saveData(swap.getHash(), swap.getSequence(), swap);
282
280
  break;
283
281
  case "reverted":
284
282
  //Cancel invoice
@@ -287,27 +285,30 @@ class FromBtcTrusted extends FromBtcBaseSwapHandler_1.FromBtcBaseSwapHandler {
287
285
  break;
288
286
  case "success":
289
287
  yield swap.setState(FromBtcTrustedSwap_1.FromBtcTrustedSwapState.CONFIRMED);
290
- yield this.storageManager.saveData(swap.getHash(), null, swap);
288
+ yield this.storageManager.saveData(swap.getHash(), swap.getSequence(), swap);
291
289
  break;
292
290
  }
293
291
  }
294
292
  if (swap.state === FromBtcTrustedSwap_1.FromBtcTrustedSwapState.CONFIRMED) {
295
293
  this.processedTxIds.set(swap.getHash(), {
296
- txId: swap.txIds.init,
294
+ txId: swap.txId,
295
+ scTxId: swap.txIds.init,
297
296
  adjustedAmount: swap.adjustedInput,
298
297
  adjustedTotal: swap.adjustedOutput
299
298
  });
300
- if (tx.confirmation_count > 0)
299
+ if (tx.confirmations > 0)
301
300
  yield this.removeSwapData(swap, FromBtcTrustedSwap_1.FromBtcTrustedSwapState.FINISHED);
302
301
  }
303
302
  });
304
303
  }
305
304
  processPastSwaps() {
305
+ var _a, _b, _c;
306
306
  return __awaiter(this, void 0, void 0, function* () {
307
307
  const queriedData = yield this.storageManager.query([
308
308
  {
309
309
  key: "state",
310
310
  value: [
311
+ FromBtcTrustedSwap_1.FromBtcTrustedSwapState.REFUNDABLE,
311
312
  FromBtcTrustedSwap_1.FromBtcTrustedSwapState.CREATED,
312
313
  FromBtcTrustedSwap_1.FromBtcTrustedSwapState.RECEIVED,
313
314
  FromBtcTrustedSwap_1.FromBtcTrustedSwapState.BTC_CONFIRMED,
@@ -319,16 +320,34 @@ class FromBtcTrusted extends FromBtcBaseSwapHandler_1.FromBtcBaseSwapHandler {
319
320
  const startingBlockheight = queriedData.reduce((prev, swap) => Math.min(prev, swap.createdHeight), Infinity);
320
321
  if (startingBlockheight === Infinity)
321
322
  return;
322
- const { transactions } = yield (0, lightning_1.getChainTransactions)({ lnd: this.LND, after: startingBlockheight });
323
+ const transactions = yield this.bitcoin.getWalletTransactions(startingBlockheight);
324
+ const map = new Map();
325
+ transactions.forEach(tx => {
326
+ tx.outs.forEach((out, vout) => {
327
+ const existing = map.get(out.scriptPubKey.hex);
328
+ if (existing == null) {
329
+ map.set(out.scriptPubKey.hex, [{ tx, vout }]);
330
+ }
331
+ else {
332
+ existing.push({ tx, vout });
333
+ }
334
+ });
335
+ });
323
336
  for (let swap of queriedData) {
324
- const tx = transactions.find(tx => tx.output_addresses.includes(swap.btcAddress));
325
- yield this.processPastSwap(swap, tx);
337
+ const outputScript = this.bitcoin.toOutputScript(swap.btcAddress).toString("hex");
338
+ const txs = (_a = map.get(outputScript)) !== null && _a !== void 0 ? _a : [];
339
+ try {
340
+ yield this.processPastSwap(swap, (_b = txs[0]) === null || _b === void 0 ? void 0 : _b.tx, (_c = txs[0]) === null || _c === void 0 ? void 0 : _c.vout);
341
+ }
342
+ catch (e) {
343
+ this.swapLogger.error(swap, "processPastSwaps(): Error ocurred while processing swap: ", e);
344
+ }
326
345
  }
327
346
  });
328
347
  }
329
348
  isValidBitcoinAddress(address) {
330
349
  try {
331
- bitcoin.address.toOutputScript(address, this.config.bitcoinNetwork);
350
+ this.bitcoin.toOutputScript(address);
332
351
  return true;
333
352
  }
334
353
  catch (e) { }
@@ -343,7 +362,7 @@ class FromBtcTrusted extends FromBtcBaseSwapHandler_1.FromBtcBaseSwapHandler {
343
362
  metadata.times.requestReceived = Date.now();
344
363
  /**
345
364
  * address: string solana address of the recipient
346
- * refundAddress: string bitcoin address to use in case of refund
365
+ * refundAddress?: string bitcoin address to use in case of refund
347
366
  * amount: string amount (in lamports/smart chain base units) of the invoice
348
367
  * exactOut: boolean whether to create and exact output swap
349
368
  */
@@ -351,9 +370,6 @@ class FromBtcTrusted extends FromBtcBaseSwapHandler_1.FromBtcBaseSwapHandler {
351
370
  address: (val) => val != null &&
352
371
  typeof (val) === "string" &&
353
372
  swapContract.isValidAddress(val) ? val : null,
354
- refundAddress: (val) => val != null &&
355
- typeof (val) === "string" &&
356
- this.isValidBitcoinAddress(val) ? val : null,
357
373
  amount: SchemaVerifier_1.FieldTypeEnum.BN,
358
374
  exactOut: SchemaVerifier_1.FieldTypeEnum.BooleanOptional
359
375
  });
@@ -363,6 +379,12 @@ class FromBtcTrusted extends FromBtcBaseSwapHandler_1.FromBtcBaseSwapHandler {
363
379
  msg: "Invalid request body"
364
380
  };
365
381
  metadata.request = parsedBody;
382
+ const refundAddressData = req.paramReader.getExistingParamsOrNull({
383
+ refundAddress: (val) => val != null &&
384
+ typeof (val) === "string" &&
385
+ this.isValidBitcoinAddress(val) ? val : null
386
+ });
387
+ const refundAddress = refundAddressData === null || refundAddressData === void 0 ? void 0 : refundAddressData.refundAddress;
366
388
  const requestedAmount = { input: !parsedBody.exactOut, amount: parsedBody.amount };
367
389
  const request = {
368
390
  chainIdentifier,
@@ -387,30 +409,36 @@ class FromBtcTrusted extends FromBtcBaseSwapHandler_1.FromBtcBaseSwapHandler {
387
409
  //Check valid amount specified (min/max)
388
410
  const { amountBD, swapFee, swapFeeInToken, totalInToken } = yield this.checkFromBtcAmount(request, requestedAmount, fees, useToken, abortController.signal, pricePrefetchPromise);
389
411
  metadata.times.priceCalculated = Date.now();
390
- //Check if we have enough funds to honor the request
391
- yield this.checkBalance(totalInToken, balancePrefetch, abortController.signal);
412
+ //Make sure we have MORE THAN ENOUGH to honor the swap request
413
+ yield this.checkBalance(totalInToken.mul(new BN(4)), balancePrefetch, abortController.signal);
392
414
  metadata.times.balanceChecked = Date.now();
393
- const { address: receiveAddress } = yield (0, lightning_1.createChainAddress)({
394
- lnd: this.LND,
395
- format: "p2wpkh"
396
- });
415
+ const blockHeight = yield this.bitcoin.getBlockheight();
416
+ const feeRate = yield this.bitcoin.getFeeRate();
417
+ const recommendedFee = Math.ceil(feeRate * this.config.recommendFeeMultiplier);
418
+ if (recommendedFee === 0)
419
+ throw {
420
+ _httpStatus: 500,
421
+ code: 21100,
422
+ msg: "Cannot estimate bitcoin fee!"
423
+ };
424
+ metadata.times.feeEstimated = Date.now();
425
+ const receiveAddress = yield this.bitcoin.getAddress();
426
+ const outputScript = this.bitcoin.toOutputScript(receiveAddress).toString("hex");
397
427
  abortController.signal.throwIfAborted();
398
428
  metadata.times.addressCreated = Date.now();
399
- const { current_block_height } = yield (0, lightning_1.getHeight)({ lnd: this.LND });
400
- const feeRate = yield this.config.feeEstimator.estimateFee();
401
- const recommendedFee = Math.ceil(feeRate * this.config.recommendFeeMultiplier);
402
- const createdSwap = new FromBtcTrustedSwap_1.FromBtcTrustedSwap(chainIdentifier, swapFee, swapFeeInToken, receiveAddress, amountBD, parsedBody.address, totalInToken, current_block_height, Date.now() + (this.config.swapAddressExpiry * 1000), recommendedFee, parsedBody.refundAddress);
429
+ const createdSwap = new FromBtcTrustedSwap_1.FromBtcTrustedSwap(chainIdentifier, swapFee, swapFeeInToken, receiveAddress, amountBD, parsedBody.address, totalInToken, blockHeight, Date.now() + (this.config.swapAddressExpiry * 1000), recommendedFee, refundAddress);
403
430
  metadata.times.swapCreated = Date.now();
404
431
  createdSwap.metadata = metadata;
405
432
  yield PluginManager_1.PluginManager.swapCreate(createdSwap);
406
- yield this.storageManager.saveData(createdSwap.getHash(), null, createdSwap);
407
- this.subscriptions.set(createdSwap.btcAddress, createdSwap);
433
+ yield this.storageManager.saveData(createdSwap.getHash(), createdSwap.getSequence(), createdSwap);
434
+ this.subscriptions.set(outputScript, createdSwap);
408
435
  this.swapLogger.info(createdSwap, "REST: /getAddress: Created swap address: " + createdSwap.btcAddress + " amount: " + amountBD.toString(10));
409
436
  yield responseStream.writeParamsAndEnd({
410
437
  msg: "Success",
411
438
  code: 10000,
412
439
  data: {
413
440
  paymentHash: createdSwap.getHash(),
441
+ sequence: createdSwap.getSequence().toString(10),
414
442
  btcAddress: receiveAddress,
415
443
  amountSats: amountBD.toString(10),
416
444
  swapFeeSats: swapFee.toString(10),
@@ -427,20 +455,32 @@ class FromBtcTrusted extends FromBtcBaseSwapHandler_1.FromBtcBaseSwapHandler {
427
455
  const getInvoiceStatus = (0, Utils_1.expressHandlerWrapper)((req, res) => __awaiter(this, void 0, void 0, function* () {
428
456
  /**
429
457
  * paymentHash: string payment hash of the invoice
458
+ * sequence: BN secret sequence for the swap,
430
459
  */
431
460
  const parsedBody = (0, SchemaVerifier_1.verifySchema)(req.query, {
432
461
  paymentHash: (val) => val != null &&
433
462
  typeof (val) === "string" &&
434
463
  val.length === 64 &&
435
464
  Utils_1.HEX_REGEX.test(val) ? val : null,
465
+ sequence: SchemaVerifier_1.FieldTypeEnum.BN,
436
466
  });
467
+ if (parsedBody == null)
468
+ throw {
469
+ code: 20100,
470
+ msg: "Invalid request"
471
+ };
437
472
  const processedTxData = this.processedTxIds.get(parsedBody.paymentHash);
438
473
  if (processedTxData != null)
439
474
  throw {
440
475
  _httpStatus: 200,
441
476
  code: 10000,
442
477
  msg: "Success, tx confirmed",
443
- data: processedTxData
478
+ data: {
479
+ adjustedAmount: processedTxData.adjustedAmount.toString(10),
480
+ adjustedTotal: processedTxData.adjustedTotal.toString(10),
481
+ txId: processedTxData.txId,
482
+ scTxId: processedTxData.scTxId
483
+ }
444
484
  };
445
485
  const refundTxId = this.refundedSwaps.get(parsedBody.paymentHash);
446
486
  if (refundTxId != null)
@@ -462,7 +502,7 @@ class FromBtcTrusted extends FromBtcBaseSwapHandler_1.FromBtcBaseSwapHandler {
462
502
  txId: doubleSpendTxId
463
503
  }
464
504
  };
465
- const invoiceData = yield this.storageManager.getData(parsedBody.paymentHash, null);
505
+ const invoiceData = yield this.storageManager.getData(parsedBody.paymentHash, parsedBody.sequence);
466
506
  if (invoiceData == null)
467
507
  throw {
468
508
  _httpStatus: 200,
@@ -482,7 +522,8 @@ class FromBtcTrusted extends FromBtcBaseSwapHandler_1.FromBtcBaseSwapHandler {
482
522
  msg: "Bitcoin received, payment processing",
483
523
  data: {
484
524
  adjustedAmount: invoiceData.adjustedInput.toString(10),
485
- adjustedTotal: invoiceData.adjustedOutput.toString(10)
525
+ adjustedTotal: invoiceData.adjustedOutput.toString(10),
526
+ txId: invoiceData.txId
486
527
  }
487
528
  };
488
529
  if (invoiceData.state === FromBtcTrustedSwap_1.FromBtcTrustedSwapState.BTC_CONFIRMED)
@@ -492,7 +533,8 @@ class FromBtcTrusted extends FromBtcBaseSwapHandler_1.FromBtcBaseSwapHandler {
492
533
  msg: "Bitcoin accepted, payment processing",
493
534
  data: {
494
535
  adjustedAmount: invoiceData.adjustedInput.toString(10),
495
- adjustedTotal: invoiceData.adjustedOutput.toString(10)
536
+ adjustedTotal: invoiceData.adjustedOutput.toString(10),
537
+ txId: invoiceData.txId
496
538
  }
497
539
  };
498
540
  if (invoiceData.state === FromBtcTrustedSwap_1.FromBtcTrustedSwapState.SENT)
@@ -503,7 +545,8 @@ class FromBtcTrusted extends FromBtcBaseSwapHandler_1.FromBtcBaseSwapHandler {
503
545
  data: {
504
546
  adjustedAmount: invoiceData.adjustedInput.toString(10),
505
547
  adjustedTotal: invoiceData.adjustedOutput.toString(10),
506
- txId: invoiceData.txIds.init
548
+ txId: invoiceData.txId,
549
+ scTxId: invoiceData.txIds.init
507
550
  }
508
551
  };
509
552
  if (invoiceData.state === FromBtcTrustedSwap_1.FromBtcTrustedSwapState.CONFIRMED || invoiceData.state === FromBtcTrustedSwap_1.FromBtcTrustedSwapState.FINISHED)
@@ -514,20 +557,79 @@ class FromBtcTrusted extends FromBtcBaseSwapHandler_1.FromBtcBaseSwapHandler {
514
557
  data: {
515
558
  adjustedAmount: invoiceData.adjustedInput.toString(10),
516
559
  adjustedTotal: invoiceData.adjustedOutput.toString(10),
517
- txId: invoiceData.txIds.init
560
+ txId: invoiceData.txId,
561
+ scTxId: invoiceData.txIds.init
562
+ }
563
+ };
564
+ if (invoiceData.state === FromBtcTrustedSwap_1.FromBtcTrustedSwapState.REFUNDABLE)
565
+ throw {
566
+ _httpStatus: 200,
567
+ code: 10016,
568
+ msg: "Refundable",
569
+ data: {
570
+ adjustedAmount: invoiceData.adjustedInput.toString(10)
518
571
  }
519
572
  };
520
573
  }));
521
574
  restServer.get(this.path + "/getAddressStatus", getInvoiceStatus);
575
+ const setRefundAddress = (0, Utils_1.expressHandlerWrapper)((req, res) => __awaiter(this, void 0, void 0, function* () {
576
+ /**
577
+ * paymentHash: string payment hash of the invoice
578
+ * sequence: BN secret sequence for the swap,
579
+ * refundAddress: string valid bitcoin address to be used for refunds
580
+ */
581
+ const parsedBody = (0, SchemaVerifier_1.verifySchema)(Object.assign(Object.assign({}, req.body), req.query), {
582
+ paymentHash: (val) => val != null &&
583
+ typeof (val) === "string" &&
584
+ val.length === 64 &&
585
+ Utils_1.HEX_REGEX.test(val) ? val : null,
586
+ sequence: SchemaVerifier_1.FieldTypeEnum.BN,
587
+ refundAddress: (val) => val != null &&
588
+ typeof (val) === "string" &&
589
+ this.isValidBitcoinAddress(val) ? val : null
590
+ });
591
+ if (parsedBody == null)
592
+ throw {
593
+ code: 20100,
594
+ msg: "Invalid request"
595
+ };
596
+ const invoiceData = yield this.storageManager.getData(parsedBody.paymentHash, null);
597
+ if (invoiceData == null || !invoiceData.getSequence().eq(parsedBody.sequence))
598
+ throw {
599
+ code: 10001,
600
+ msg: "Swap not found"
601
+ };
602
+ if (invoiceData.refundAddress != null)
603
+ throw {
604
+ code: 10080,
605
+ msg: "Refund address already set!",
606
+ data: {
607
+ refundAddress: invoiceData.refundAddress
608
+ }
609
+ };
610
+ invoiceData.refundAddress = parsedBody.refundAddress;
611
+ if (invoiceData.state === FromBtcTrustedSwap_1.FromBtcTrustedSwapState.REFUNDABLE) {
612
+ this.refundSwap(invoiceData).catch(e => {
613
+ this.swapLogger.error(invoiceData, "/setRefundAddress: Failed to refund!");
614
+ });
615
+ }
616
+ throw {
617
+ _httpStatus: 200,
618
+ code: 10000,
619
+ msg: "Refund address set"
620
+ };
621
+ }));
622
+ restServer.get(this.path + "/setRefundAddress", setRefundAddress);
623
+ restServer.post(this.path + "/setRefundAddress", setRefundAddress);
522
624
  this.logger.info("started at path: ", this.path);
523
625
  }
524
626
  checkDoubleSpends() {
525
627
  return __awaiter(this, void 0, void 0, function* () {
526
628
  for (let swap of this.doubleSpendWatchdogSwaps.keys()) {
527
- const tx = yield this.bitcoinRpc.getTransaction(swap.txId);
629
+ const tx = yield this.bitcoin.getWalletTransaction(swap.txId);
528
630
  if (tx == null) {
529
631
  this.swapLogger.debug(swap, "checkDoubleSpends(): Swap was double spent, burning... - original txId: " + swap.txId);
530
- this.processPastSwap(swap, null);
632
+ this.processPastSwap(swap, null, null);
531
633
  }
532
634
  }
533
635
  });
@@ -543,13 +645,12 @@ class FromBtcTrusted extends FromBtcBaseSwapHandler_1.FromBtcBaseSwapHandler {
543
645
  });
544
646
  }
545
647
  listenToTxns() {
546
- const res = (0, lightning_1.subscribeToTransactions)({ lnd: this.LND });
547
- res.on("chain_transaction", (tx) => {
548
- for (let address of tx.output_addresses) {
549
- const savedSwap = this.subscriptions.get(address);
648
+ this.bitcoin.subscribeToWalletTransactions((btcTx) => {
649
+ for (let out of btcTx.outs) {
650
+ const savedSwap = this.subscriptions.get(out.scriptPubKey.hex);
550
651
  if (savedSwap == null)
551
652
  continue;
552
- this.processPastSwap(savedSwap, tx);
653
+ this.processPastSwap(savedSwap, btcTx, out.n);
553
654
  return;
554
655
  }
555
656
  });