@atomiqlabs/lp-lib 17.1.2 → 17.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/info/InfoHandler.js +2 -1
- package/dist/plugins/IPlugin.d.ts +17 -3
- package/dist/plugins/IPlugin.js +9 -8
- package/dist/plugins/PluginManager.d.ts +5 -3
- package/dist/plugins/PluginManager.js +30 -0
- package/dist/swaps/SwapHandler.d.ts +1 -0
- package/dist/swaps/SwapHandlerSwap.d.ts +1 -0
- package/dist/swaps/assertions/FromBtcAmountAssertions.js +2 -2
- package/dist/swaps/assertions/ToBtcAmountAssertions.js +2 -2
- package/dist/swaps/escrow/frombtc_abstract/FromBtcAbs.js +7 -0
- package/dist/swaps/escrow/frombtc_abstract/FromBtcSwapAbs.d.ts +1 -0
- package/dist/swaps/escrow/frombtc_abstract/FromBtcSwapAbs.js +3 -0
- package/dist/swaps/escrow/frombtcln_abstract/FromBtcLnAbs.js +31 -11
- 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.js +14 -2
- package/dist/swaps/escrow/frombtcln_autoinit/FromBtcLnAutoSwap.d.ts +1 -0
- package/dist/swaps/escrow/frombtcln_autoinit/FromBtcLnAutoSwap.js +3 -0
- package/dist/swaps/escrow/tobtc_abstract/ToBtcAbs.js +25 -2
- package/dist/swaps/escrow/tobtc_abstract/ToBtcSwapAbs.d.ts +1 -0
- package/dist/swaps/escrow/tobtc_abstract/ToBtcSwapAbs.js +3 -0
- package/dist/swaps/escrow/tobtcln_abstract/ToBtcLnAbs.js +13 -1
- package/dist/swaps/escrow/tobtcln_abstract/ToBtcLnSwapAbs.d.ts +1 -0
- package/dist/swaps/escrow/tobtcln_abstract/ToBtcLnSwapAbs.js +3 -0
- package/dist/swaps/spv_vault_swap/SpvVaultSwap.d.ts +1 -0
- package/dist/swaps/spv_vault_swap/SpvVaultSwap.js +3 -0
- package/dist/swaps/spv_vault_swap/SpvVaultSwapHandler.js +14 -2
- package/dist/swaps/trusted/frombtc_trusted/FromBtcTrusted.js +47 -32
- package/dist/swaps/trusted/frombtc_trusted/FromBtcTrustedSwap.d.ts +1 -0
- package/dist/swaps/trusted/frombtc_trusted/FromBtcTrustedSwap.js +3 -0
- package/dist/swaps/trusted/frombtcln_trusted/FromBtcLnTrusted.js +14 -0
- package/dist/swaps/trusted/frombtcln_trusted/FromBtcLnTrustedSwap.d.ts +1 -0
- package/dist/swaps/trusted/frombtcln_trusted/FromBtcLnTrustedSwap.js +3 -0
- package/package.json +2 -2
- package/src/info/InfoHandler.ts +6 -3
- package/src/plugins/IPlugin.ts +36 -14
- package/src/plugins/PluginManager.ts +41 -6
- package/src/swaps/SwapHandler.ts +2 -1
- package/src/swaps/SwapHandlerSwap.ts +2 -0
- package/src/swaps/assertions/FromBtcAmountAssertions.ts +2 -2
- package/src/swaps/assertions/ToBtcAmountAssertions.ts +2 -2
- package/src/swaps/escrow/frombtc_abstract/FromBtcAbs.ts +11 -0
- package/src/swaps/escrow/frombtc_abstract/FromBtcSwapAbs.ts +4 -0
- package/src/swaps/escrow/frombtcln_abstract/FromBtcLnAbs.ts +23 -1
- package/src/swaps/escrow/frombtcln_abstract/FromBtcLnSwapAbs.ts +4 -0
- package/src/swaps/escrow/frombtcln_autoinit/FromBtcLnAuto.ts +15 -1
- package/src/swaps/escrow/frombtcln_autoinit/FromBtcLnAutoSwap.ts +4 -0
- package/src/swaps/escrow/tobtc_abstract/ToBtcAbs.ts +29 -3
- package/src/swaps/escrow/tobtc_abstract/ToBtcSwapAbs.ts +4 -0
- package/src/swaps/escrow/tobtcln_abstract/ToBtcLnAbs.ts +19 -2
- package/src/swaps/escrow/tobtcln_abstract/ToBtcLnSwapAbs.ts +4 -0
- package/src/swaps/spv_vault_swap/SpvVaultSwap.ts +4 -0
- package/src/swaps/spv_vault_swap/SpvVaultSwapHandler.ts +17 -2
- package/src/swaps/trusted/frombtc_trusted/FromBtcTrusted.ts +53 -33
- package/src/swaps/trusted/frombtc_trusted/FromBtcTrustedSwap.ts +4 -0
- package/src/swaps/trusted/frombtcln_trusted/FromBtcLnTrusted.ts +20 -1
- package/src/swaps/trusted/frombtcln_trusted/FromBtcLnTrustedSwap.ts +4 -0
|
@@ -7,6 +7,7 @@ const PluginManager_1 = require("../../../plugins/PluginManager");
|
|
|
7
7
|
const Utils_1 = require("../../../utils/Utils");
|
|
8
8
|
const SchemaVerifier_1 = require("../../../utils/paramcoders/SchemaVerifier");
|
|
9
9
|
const FromBtcAmountAssertions_1 = require("../../assertions/FromBtcAmountAssertions");
|
|
10
|
+
const IPlugin_1 = require("../../../plugins/IPlugin");
|
|
10
11
|
class FromBtcTrusted extends SwapHandler_1.SwapHandler {
|
|
11
12
|
constructor(storageDirectory, path, chains, bitcoin, swapPricing, bitcoinRpc, config) {
|
|
12
13
|
var _a;
|
|
@@ -30,42 +31,45 @@ class FromBtcTrusted extends SwapHandler_1.SwapHandler {
|
|
|
30
31
|
})));
|
|
31
32
|
}
|
|
32
33
|
async refundSwap(swap) {
|
|
33
|
-
if (swap.
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
await this.storageManager.saveData(swap.getIdentifierHash(), swap.getSequence(), swap);
|
|
37
|
-
}
|
|
38
|
-
return;
|
|
34
|
+
if (swap.state !== FromBtcTrustedSwap_1.FromBtcTrustedSwapState.REFUNDABLE) {
|
|
35
|
+
await swap.setState(FromBtcTrustedSwap_1.FromBtcTrustedSwapState.REFUNDABLE);
|
|
36
|
+
await this.storageManager.saveData(swap.getIdentifierHash(), swap.getSequence(), swap);
|
|
39
37
|
}
|
|
40
|
-
|
|
38
|
+
if (swap.refundAddress == null)
|
|
39
|
+
return;
|
|
40
|
+
let unlock = swap.lock(Infinity);
|
|
41
41
|
if (unlock == null)
|
|
42
42
|
return;
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
43
|
+
try {
|
|
44
|
+
const feeRate = await this.bitcoin.getFeeRate();
|
|
45
|
+
const ourOutput = swap.btcTx.outs[swap.vout];
|
|
46
|
+
const resp = await this.bitcoin.drainAll(swap.refundAddress, [{
|
|
47
|
+
type: this.bitcoin.getAddressType(),
|
|
48
|
+
confirmations: swap.btcTx.confirmations,
|
|
49
|
+
outputScript: Buffer.from(ourOutput.scriptPubKey.hex, "hex"),
|
|
50
|
+
value: ourOutput.value,
|
|
51
|
+
txId: swap.btcTx.txid,
|
|
52
|
+
vout: swap.vout
|
|
53
|
+
}], feeRate);
|
|
54
|
+
if (resp == null) {
|
|
55
|
+
this.swapLogger.error(swap, "refundSwap(): cannot refund swap because of dust limit, txId: " + swap.txId);
|
|
56
|
+
unlock();
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
if (swap.metadata != null)
|
|
60
|
+
swap.metadata.times.refundSignPSBT = Date.now();
|
|
61
|
+
this.swapLogger.debug(swap, "refundSwap(): signed raw transaction: " + resp.raw);
|
|
62
|
+
const refundTxId = resp.txId;
|
|
63
|
+
swap.refundTxId = refundTxId;
|
|
64
|
+
//Send the refund TX
|
|
65
|
+
await this.bitcoin.sendRawTransaction(resp.raw);
|
|
66
|
+
this.swapLogger.debug(swap, "refundSwap(): sent refund transaction: " + refundTxId);
|
|
67
|
+
this.refundedSwaps.set(swap.getIdentifierHash(), refundTxId);
|
|
68
|
+
await this.removeSwapData(swap, FromBtcTrustedSwap_1.FromBtcTrustedSwapState.REFUNDED);
|
|
69
|
+
}
|
|
70
|
+
finally {
|
|
55
71
|
unlock();
|
|
56
|
-
return;
|
|
57
72
|
}
|
|
58
|
-
if (swap.metadata != null)
|
|
59
|
-
swap.metadata.times.refundSignPSBT = Date.now();
|
|
60
|
-
this.swapLogger.debug(swap, "refundSwap(): signed raw transaction: " + resp.raw);
|
|
61
|
-
const refundTxId = resp.txId;
|
|
62
|
-
swap.refundTxId = refundTxId;
|
|
63
|
-
//Send the refund TX
|
|
64
|
-
await this.bitcoin.sendRawTransaction(resp.raw);
|
|
65
|
-
this.swapLogger.debug(swap, "refundSwap(): sent refund transaction: " + refundTxId);
|
|
66
|
-
this.refundedSwaps.set(swap.getIdentifierHash(), refundTxId);
|
|
67
|
-
await this.removeSwapData(swap, FromBtcTrustedSwap_1.FromBtcTrustedSwapState.REFUNDED);
|
|
68
|
-
unlock();
|
|
69
73
|
}
|
|
70
74
|
async burn(swap) {
|
|
71
75
|
const ourOutput = swap.btcTx.outs[swap.vout];
|
|
@@ -241,10 +245,21 @@ class FromBtcTrusted extends SwapHandler_1.SwapHandler {
|
|
|
241
245
|
}
|
|
242
246
|
if (swap.state !== FromBtcTrustedSwap_1.FromBtcTrustedSwapState.BTC_CONFIRMED)
|
|
243
247
|
return;
|
|
248
|
+
const txns = await chainInterface.txsTransfer(signer.getAddress(), swap.token, swap.adjustedOutput, swap.dstAddress);
|
|
244
249
|
let unlock = swap.lock(30 * 1000);
|
|
245
250
|
if (unlock == null)
|
|
246
251
|
return;
|
|
247
|
-
const
|
|
252
|
+
const pluginCheckResult = await PluginManager_1.PluginManager.onHandlePreFromBtcExecute(SwapHandler_1.SwapHandlerType.FROM_BTC_TRUSTED, swap);
|
|
253
|
+
if ((0, IPlugin_1.isQuoteThrow)(pluginCheckResult)) {
|
|
254
|
+
this.swapLogger.error(swap, "processPastSwap(): Error, got negative response from plugin: ", pluginCheckResult);
|
|
255
|
+
await this.refundSwap(swap);
|
|
256
|
+
unlock();
|
|
257
|
+
return;
|
|
258
|
+
}
|
|
259
|
+
if (swap.state !== FromBtcTrustedSwap_1.FromBtcTrustedSwapState.BTC_CONFIRMED) {
|
|
260
|
+
unlock();
|
|
261
|
+
return;
|
|
262
|
+
}
|
|
248
263
|
await chainInterface.sendAndConfirm(signer, txns, true, null, false, async (txId, rawTx) => {
|
|
249
264
|
swap.txIds = { init: txId };
|
|
250
265
|
swap.scRawTx = rawTx;
|
|
@@ -114,5 +114,8 @@ class FromBtcTrustedSwap extends SwapHandlerSwap_1.SwapHandlerSwap {
|
|
|
114
114
|
getIdentifierHash() {
|
|
115
115
|
return (0, crypto_1.createHash)("sha256").update(this.btcAddress).digest().toString("hex");
|
|
116
116
|
}
|
|
117
|
+
getDestinationAddress() {
|
|
118
|
+
return this.dstAddress;
|
|
119
|
+
}
|
|
117
120
|
}
|
|
118
121
|
exports.FromBtcTrustedSwap = FromBtcTrustedSwap;
|
|
@@ -9,6 +9,7 @@ const SchemaVerifier_1 = require("../../../utils/paramcoders/SchemaVerifier");
|
|
|
9
9
|
const PluginManager_1 = require("../../../plugins/PluginManager");
|
|
10
10
|
const FromBtcAmountAssertions_1 = require("../../assertions/FromBtcAmountAssertions");
|
|
11
11
|
const LightningAssertions_1 = require("../../assertions/LightningAssertions");
|
|
12
|
+
const IPlugin_1 = require("../../../plugins/IPlugin");
|
|
12
13
|
/**
|
|
13
14
|
* Swap handler handling from BTCLN swaps using submarine swaps
|
|
14
15
|
*/
|
|
@@ -183,6 +184,19 @@ class FromBtcLnTrusted extends SwapHandler_1.SwapHandler {
|
|
|
183
184
|
let unlock = invoiceData.lock(Infinity);
|
|
184
185
|
if (unlock == null)
|
|
185
186
|
return;
|
|
187
|
+
const pluginCheckResult = await PluginManager_1.PluginManager.onHandlePreFromBtcExecute(SwapHandler_1.SwapHandlerType.FROM_BTCLN_TRUSTED, invoiceData);
|
|
188
|
+
if ((0, IPlugin_1.isQuoteThrow)(pluginCheckResult)) {
|
|
189
|
+
await this.cancelSwapAndInvoice(invoiceData);
|
|
190
|
+
unlock();
|
|
191
|
+
throw {
|
|
192
|
+
code: 29999,
|
|
193
|
+
msg: pluginCheckResult.message
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
if (invoiceData.state !== FromBtcLnTrustedSwap_1.FromBtcLnTrustedSwapState.RECEIVED) {
|
|
197
|
+
unlock();
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
186
200
|
const result = await chainInterface.sendAndConfirm(signer, txns, true, null, false, async (txId, rawTx) => {
|
|
187
201
|
invoiceData.txIds = { init: txId };
|
|
188
202
|
invoiceData.scRawTx = rawTx;
|
|
@@ -77,5 +77,8 @@ class FromBtcLnTrustedSwap extends SwapHandlerSwap_1.SwapHandlerSwap {
|
|
|
77
77
|
getIdentifierHash() {
|
|
78
78
|
return (0, crypto_1.createHash)("sha256").update(Buffer.from(this.secret, "hex")).digest().toString("hex");
|
|
79
79
|
}
|
|
80
|
+
getDestinationAddress() {
|
|
81
|
+
return this.dstAddress;
|
|
82
|
+
}
|
|
80
83
|
}
|
|
81
84
|
exports.FromBtcLnTrustedSwap = FromBtcLnTrustedSwap;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atomiqlabs/lp-lib",
|
|
3
|
-
"version": "17.1
|
|
3
|
+
"version": "17.3.1",
|
|
4
4
|
"description": "Main functionality implementation for atomiq LP node",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"types:": "./dist/index.d.ts",
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
"author": "adambor",
|
|
24
24
|
"license": "ISC",
|
|
25
25
|
"dependencies": {
|
|
26
|
-
"@atomiqlabs/base": "^13.0
|
|
26
|
+
"@atomiqlabs/base": "^13.5.0",
|
|
27
27
|
"@atomiqlabs/server-base": "^3.0.0",
|
|
28
28
|
"@scure/btc-signer": "1.6.0",
|
|
29
29
|
"express": "4.21.1",
|
package/src/info/InfoHandler.ts
CHANGED
|
@@ -16,7 +16,8 @@ type InfoHandlerResponse = {
|
|
|
16
16
|
chains: {
|
|
17
17
|
[chainIdentifier: string]: {
|
|
18
18
|
address: string,
|
|
19
|
-
signature: string
|
|
19
|
+
signature: string,
|
|
20
|
+
contractVersion: string
|
|
20
21
|
}
|
|
21
22
|
}
|
|
22
23
|
}
|
|
@@ -74,14 +75,16 @@ export class InfoHandler {
|
|
|
74
75
|
const chains: {
|
|
75
76
|
[chainIdentifier: string]: {
|
|
76
77
|
address: string,
|
|
77
|
-
signature: string
|
|
78
|
+
signature: string,
|
|
79
|
+
contractVersion: string
|
|
78
80
|
}
|
|
79
81
|
} = {};
|
|
80
82
|
for(let chainIdentifier in this.chainData.chains) {
|
|
81
83
|
const singleChain = this.chainData.chains[chainIdentifier];
|
|
82
84
|
chains[chainIdentifier] = {
|
|
83
85
|
address: singleChain.signer.getAddress(),
|
|
84
|
-
signature: await singleChain.swapContract.getDataSignature(singleChain.signer, envelopeBuffer)
|
|
86
|
+
signature: await singleChain.swapContract.getDataSignature(singleChain.signer, envelopeBuffer),
|
|
87
|
+
contractVersion: singleChain.contractVersion ?? "v1"
|
|
85
88
|
};
|
|
86
89
|
}
|
|
87
90
|
|
package/src/plugins/IPlugin.ts
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import {BitcoinRpc} from "@atomiqlabs/base";
|
|
2
2
|
import {
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
FromBtcLnAbs, FromBtcLnAutoSwap,
|
|
4
|
+
FromBtcLnRequestType, FromBtcLnSwapAbs, FromBtcLnTrustedSwap,
|
|
5
|
+
FromBtcRequestType, FromBtcSwapAbs, FromBtcTrustedRequestType, FromBtcTrustedSwap,
|
|
5
6
|
ISwapPrice, MultichainData, RequestData, SpvVaultPostQuote, SpvVaultSwap, SpvVaultSwapRequestType,
|
|
6
7
|
SwapHandler, SwapHandlerType,
|
|
7
|
-
ToBtcLnRequestType,
|
|
8
|
-
ToBtcRequestType
|
|
8
|
+
ToBtcLnRequestType, ToBtcLnSwapAbs,
|
|
9
|
+
ToBtcRequestType, ToBtcSwapAbs
|
|
9
10
|
} from "..";
|
|
10
11
|
import {SwapHandlerSwap} from "../swaps/SwapHandlerSwap";
|
|
11
12
|
import {Command} from "@atomiqlabs/server-base";
|
|
@@ -20,7 +21,7 @@ export type QuoteThrow = {
|
|
|
20
21
|
}
|
|
21
22
|
|
|
22
23
|
export function isQuoteThrow(obj: any): obj is QuoteThrow {
|
|
23
|
-
return obj.type==="throw" && typeof(obj.message)==="string";
|
|
24
|
+
return obj!=null && obj.type==="throw" && typeof(obj.message)==="string";
|
|
24
25
|
}
|
|
25
26
|
|
|
26
27
|
export type QuoteSetFees = {
|
|
@@ -32,7 +33,8 @@ export type QuoteSetFees = {
|
|
|
32
33
|
};
|
|
33
34
|
|
|
34
35
|
export function isQuoteSetFees(obj: any): obj is QuoteSetFees {
|
|
35
|
-
return obj
|
|
36
|
+
return obj!=null &&
|
|
37
|
+
obj.type==="fees" &&
|
|
36
38
|
(obj.baseFee==null || typeof(obj.baseFee) === "bigint") &&
|
|
37
39
|
(obj.feePPM==null || typeof(obj.feePPM) === "bigint") &&
|
|
38
40
|
(obj.securityDepositApyPPM==null || typeof(obj.securityDepositApyPPM) === "bigint") &&
|
|
@@ -45,7 +47,7 @@ export type QuoteAmountTooLow = {
|
|
|
45
47
|
}
|
|
46
48
|
|
|
47
49
|
export function isQuoteAmountTooLow(obj: any): obj is QuoteAmountTooLow {
|
|
48
|
-
return obj.type==="low" && typeof(obj.data)==="object" && typeof(obj.data.min)==="bigint" && typeof(obj.data.max)==="bigint";
|
|
50
|
+
return obj!=null && obj.type==="low" && obj.data!=null && typeof(obj.data)==="object" && typeof(obj.data.min)==="bigint" && typeof(obj.data.max)==="bigint";
|
|
49
51
|
}
|
|
50
52
|
|
|
51
53
|
export type QuoteAmountTooHigh = {
|
|
@@ -54,7 +56,7 @@ export type QuoteAmountTooHigh = {
|
|
|
54
56
|
}
|
|
55
57
|
|
|
56
58
|
export function isQuoteAmountTooHigh(obj: any): obj is QuoteAmountTooHigh {
|
|
57
|
-
return obj.type==="high" && typeof(obj.data)==="object" && typeof(obj.data.min)==="bigint" && typeof(obj.data.max)==="bigint";
|
|
59
|
+
return obj!=null && obj.type==="high" && obj.data!=null && typeof(obj.data)==="object" && typeof(obj.data.min)==="bigint" && typeof(obj.data.max)==="bigint";
|
|
58
60
|
}
|
|
59
61
|
|
|
60
62
|
export type PluginQuote = {
|
|
@@ -64,9 +66,9 @@ export type PluginQuote = {
|
|
|
64
66
|
};
|
|
65
67
|
|
|
66
68
|
export function isPluginQuote(obj: any): obj is PluginQuote {
|
|
67
|
-
return obj.type==="success" &&
|
|
68
|
-
typeof(obj.amount)==="object" && typeof(obj.amount.input)==="boolean" && typeof(obj.amount.amount)==="bigint" &&
|
|
69
|
-
typeof(obj.swapFee)==="object" && typeof(obj.swapFee.inInputTokens)==="bigint" && typeof(obj.swapFee.inOutputTokens)==="bigint";
|
|
69
|
+
return obj!=null && obj.type==="success" &&
|
|
70
|
+
obj.amount!=null && typeof(obj.amount)==="object" && typeof(obj.amount.input)==="boolean" && typeof(obj.amount.amount)==="bigint" &&
|
|
71
|
+
obj.swapFee!=null && typeof(obj.swapFee)==="object" && typeof(obj.swapFee.inInputTokens)==="bigint" && typeof(obj.swapFee.inOutputTokens)==="bigint";
|
|
70
72
|
}
|
|
71
73
|
|
|
72
74
|
export type ToBtcPluginQuote = PluginQuote & {
|
|
@@ -74,7 +76,7 @@ export type ToBtcPluginQuote = PluginQuote & {
|
|
|
74
76
|
}
|
|
75
77
|
|
|
76
78
|
export function isToBtcPluginQuote(obj: any): obj is ToBtcPluginQuote {
|
|
77
|
-
return typeof(obj.networkFee)==="object" && typeof(obj.networkFee.inInputTokens)==="bigint" && typeof(obj.networkFee.inOutputTokens)==="bigint" &&
|
|
79
|
+
return obj!=null && obj.networkFee!=null && typeof(obj.networkFee)==="object" && typeof(obj.networkFee.inInputTokens)==="bigint" && typeof(obj.networkFee.inOutputTokens)==="bigint" &&
|
|
78
80
|
isPluginQuote(obj);
|
|
79
81
|
}
|
|
80
82
|
|
|
@@ -94,8 +96,8 @@ export interface IPlugin {
|
|
|
94
96
|
|
|
95
97
|
swapPricing: ISwapPrice,
|
|
96
98
|
tokens: {
|
|
97
|
-
[
|
|
98
|
-
[
|
|
99
|
+
[chainId: string]: {
|
|
100
|
+
[ticker: string]: {
|
|
99
101
|
address: string,
|
|
100
102
|
decimals: number
|
|
101
103
|
}
|
|
@@ -133,6 +135,22 @@ export interface IPlugin {
|
|
|
133
135
|
fees: {baseFeeInBtc: bigint, feePPM: bigint},
|
|
134
136
|
gasTokenAmount?: {input: false, amount: bigint, token: string, pricePrefetch?: Promise<bigint>}
|
|
135
137
|
): Promise<QuoteThrow | QuoteSetFees | QuoteAmountTooLow | QuoteAmountTooHigh | PluginQuote>;
|
|
138
|
+
/**
|
|
139
|
+
* Triggered when the quote is about to get executed, this means:
|
|
140
|
+
* - FROM_BTCLN - lightning network payment received and the LP is about to sign an authorization allowing the user to settle
|
|
141
|
+
* - FROM_BTC - triggered on quote request, before the final authorization is given to the user
|
|
142
|
+
* - FROM_BTCLN_TRUSTED - triggered when the LP receives the funds on the source chain and before destination funds are sent
|
|
143
|
+
* - FROM_BTC_TRUSTED - triggered when the LP receives the funds on the source chain and before destination funds are sent
|
|
144
|
+
* - FROM_BTC_SPV - triggered before LP broadcasts the co-signed swap PSBT
|
|
145
|
+
* - FROM_BTCLN_AUTO - lightning network payment received and the LP is about to offer an HTLC to the user
|
|
146
|
+
*
|
|
147
|
+
* @param swapType
|
|
148
|
+
* @param swap
|
|
149
|
+
*/
|
|
150
|
+
onHandlePreFromBtcExecute?(
|
|
151
|
+
swapType: SwapHandlerType.FROM_BTCLN | SwapHandlerType.FROM_BTC | SwapHandlerType.FROM_BTCLN_TRUSTED | SwapHandlerType.FROM_BTC_TRUSTED | SwapHandlerType.FROM_BTC_SPV | SwapHandlerType.FROM_BTCLN_AUTO,
|
|
152
|
+
swap: FromBtcLnSwapAbs | FromBtcSwapAbs | FromBtcLnTrustedSwap | FromBtcTrustedSwap | SpvVaultSwap | FromBtcLnAutoSwap
|
|
153
|
+
): Promise<QuoteThrow | null>;
|
|
136
154
|
|
|
137
155
|
onHandlePreToBtcQuote?(
|
|
138
156
|
swapType: SwapHandlerType.TO_BTCLN | SwapHandlerType.TO_BTC,
|
|
@@ -150,6 +168,10 @@ export interface IPlugin {
|
|
|
150
168
|
constraints: {minInBtc: bigint, maxInBtc: bigint},
|
|
151
169
|
fees: {baseFeeInBtc: bigint, feePPM: bigint, networkFeeGetter: (amount: bigint) => Promise<bigint>}
|
|
152
170
|
): Promise<QuoteThrow | QuoteSetFees | QuoteAmountTooLow | QuoteAmountTooHigh | ToBtcPluginQuote>;
|
|
171
|
+
onHandlePreToBtcExecute?(
|
|
172
|
+
swapType: SwapHandlerType.TO_BTCLN | SwapHandlerType.TO_BTC,
|
|
173
|
+
swap: ToBtcLnSwapAbs | ToBtcSwapAbs
|
|
174
|
+
): Promise<QuoteThrow | null>;
|
|
153
175
|
|
|
154
176
|
onHandlePostedFromBtcQuote?(
|
|
155
177
|
swapType: SwapHandlerType.FROM_BTC_SPV,
|
|
@@ -8,12 +8,13 @@ import {
|
|
|
8
8
|
QuoteThrow, ToBtcPluginQuote
|
|
9
9
|
} from "./IPlugin";
|
|
10
10
|
import {
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
FromBtcLnAutoSwap,
|
|
12
|
+
FromBtcLnRequestType, FromBtcLnSwapAbs, FromBtcLnTrustedSwap,
|
|
13
|
+
FromBtcRequestType, FromBtcSwapAbs, FromBtcTrustedRequestType, FromBtcTrustedSwap,
|
|
13
14
|
ISwapPrice, MultichainData, RequestData, SpvVaultPostQuote, SpvVaultSwap, SpvVaultSwapRequestType,
|
|
14
15
|
SwapHandler, SwapHandlerType,
|
|
15
|
-
ToBtcLnRequestType,
|
|
16
|
-
ToBtcRequestType
|
|
16
|
+
ToBtcLnRequestType, ToBtcLnSwapAbs,
|
|
17
|
+
ToBtcRequestType, ToBtcSwapAbs
|
|
17
18
|
} from "..";
|
|
18
19
|
import {SwapHandlerSwap} from "../swaps/SwapHandlerSwap";
|
|
19
20
|
import * as fs from "fs";
|
|
@@ -73,8 +74,8 @@ export class PluginManager {
|
|
|
73
74
|
|
|
74
75
|
swapPricing: ISwapPrice,
|
|
75
76
|
tokens: {
|
|
76
|
-
[
|
|
77
|
-
[
|
|
77
|
+
[chainId: string]: {
|
|
78
|
+
[ticker: string]: {
|
|
78
79
|
address: string,
|
|
79
80
|
decimals: number
|
|
80
81
|
}
|
|
@@ -224,6 +225,23 @@ export class PluginManager {
|
|
|
224
225
|
return null;
|
|
225
226
|
}
|
|
226
227
|
|
|
228
|
+
static async onHandlePreFromBtcExecute(
|
|
229
|
+
swapType: SwapHandlerType.FROM_BTCLN | SwapHandlerType.FROM_BTC | SwapHandlerType.FROM_BTCLN_TRUSTED | SwapHandlerType.FROM_BTC_TRUSTED | SwapHandlerType.FROM_BTC_SPV | SwapHandlerType.FROM_BTCLN_AUTO,
|
|
230
|
+
swap: FromBtcLnSwapAbs | FromBtcSwapAbs | FromBtcLnTrustedSwap | FromBtcTrustedSwap | SpvVaultSwap | FromBtcLnAutoSwap
|
|
231
|
+
): Promise<QuoteThrow | null> {
|
|
232
|
+
for(let plugin of PluginManager.plugins.values()) {
|
|
233
|
+
try {
|
|
234
|
+
if(plugin.onHandlePreFromBtcExecute!=null) {
|
|
235
|
+
const result = await plugin.onHandlePreFromBtcExecute(swapType, swap);
|
|
236
|
+
if(result!=null && isQuoteThrow(result)) return result;
|
|
237
|
+
}
|
|
238
|
+
} catch (e) {
|
|
239
|
+
pluginLogger.error(plugin, "onHandlePreFromBtcExecute(): plugin error", e);
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
return null;
|
|
243
|
+
}
|
|
244
|
+
|
|
227
245
|
static async onHandlePostToBtcQuote<T extends {networkFee: bigint}>(
|
|
228
246
|
swapType: SwapHandlerType.TO_BTCLN | SwapHandlerType.TO_BTC,
|
|
229
247
|
request: RequestData<ToBtcLnRequestType | ToBtcRequestType>,
|
|
@@ -291,6 +309,23 @@ export class PluginManager {
|
|
|
291
309
|
return null;
|
|
292
310
|
}
|
|
293
311
|
|
|
312
|
+
static async onHandlePreToBtcExecute(
|
|
313
|
+
swapType: SwapHandlerType.TO_BTCLN | SwapHandlerType.TO_BTC,
|
|
314
|
+
swap: ToBtcLnSwapAbs | ToBtcSwapAbs
|
|
315
|
+
): Promise<QuoteThrow | null> {
|
|
316
|
+
for(let plugin of PluginManager.plugins.values()) {
|
|
317
|
+
try {
|
|
318
|
+
if(plugin.onHandlePreToBtcExecute!=null) {
|
|
319
|
+
const result = await plugin.onHandlePreToBtcExecute(swapType, swap);
|
|
320
|
+
if(result!=null && isQuoteThrow(result)) return result;
|
|
321
|
+
}
|
|
322
|
+
} catch (e) {
|
|
323
|
+
pluginLogger.error(plugin, "onHandlePreToBtcExecute(): plugin error", e);
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
return null;
|
|
327
|
+
}
|
|
328
|
+
|
|
294
329
|
static async onHandlePostedFromBtcQuote(
|
|
295
330
|
swapType: SwapHandlerType.FROM_BTC_SPV,
|
|
296
331
|
request: RequestData<SpvVaultPostQuote>,
|
package/src/swaps/SwapHandler.ts
CHANGED
|
@@ -62,7 +62,8 @@ export type ChainData<T extends ChainType = ChainType> = {
|
|
|
62
62
|
allowedTokens: string[],
|
|
63
63
|
tokenMultipliers?: {[tokenAddress: string]: bigint},
|
|
64
64
|
allowedDepositTokens?: string[],
|
|
65
|
-
btcRelay?: T["BtcRelay"]
|
|
65
|
+
btcRelay?: T["BtcRelay"],
|
|
66
|
+
contractVersion?: string
|
|
66
67
|
}
|
|
67
68
|
|
|
68
69
|
export type RequestData<T> = {
|
|
@@ -55,8 +55,8 @@ export class FromBtcAmountAssertions extends AmountAssertions {
|
|
|
55
55
|
AmountAssertions.handlePluginErrorResponses(res);
|
|
56
56
|
if(isQuoteSetFees(res)) {
|
|
57
57
|
return {
|
|
58
|
-
baseFee: res.baseFee
|
|
59
|
-
feePPM: res.feePPM
|
|
58
|
+
baseFee: res.baseFee ?? this.config.baseFee,
|
|
59
|
+
feePPM: res.feePPM ?? this.config.feePPM,
|
|
60
60
|
securityDepositApyPPM: res.securityDepositApyPPM,
|
|
61
61
|
securityDepositBaseMultiplierPPM: res.securityDepositBaseMultiplierPPM
|
|
62
62
|
}
|
|
@@ -33,8 +33,8 @@ export class ToBtcAmountAssertions extends AmountAssertions {
|
|
|
33
33
|
AmountAssertions.handlePluginErrorResponses(res);
|
|
34
34
|
if(isQuoteSetFees(res)) {
|
|
35
35
|
return {
|
|
36
|
-
baseFee: res.baseFee
|
|
37
|
-
feePPM: res.feePPM
|
|
36
|
+
baseFee: res.baseFee ?? this.config.baseFee,
|
|
37
|
+
feePPM: res.feePPM ?? this.config.feePPM
|
|
38
38
|
}
|
|
39
39
|
}
|
|
40
40
|
}
|
|
@@ -20,6 +20,8 @@ import {IParamReader} from "../../../utils/paramcoders/IParamReader";
|
|
|
20
20
|
import {ServerParamEncoder} from "../../../utils/paramcoders/server/ServerParamEncoder";
|
|
21
21
|
import {FromBtcBaseConfig, FromBtcBaseSwapHandler} from "../FromBtcBaseSwapHandler";
|
|
22
22
|
import {IBitcoinWallet} from "../../../wallets/IBitcoinWallet";
|
|
23
|
+
import {isQuoteThrow} from "../../../plugins/IPlugin";
|
|
24
|
+
import {FromBtcLnSwapState} from "../frombtcln_abstract/FromBtcLnSwapAbs";
|
|
23
25
|
|
|
24
26
|
export type FromBtcConfig = FromBtcBaseConfig & {
|
|
25
27
|
confirmations: number,
|
|
@@ -409,6 +411,15 @@ export class FromBtcAbs extends FromBtcBaseSwapHandler<FromBtcSwapAbs, FromBtcSw
|
|
|
409
411
|
createdSwap.signature = sigData.signature;
|
|
410
412
|
createdSwap.feeRate = sigData.feeRate;
|
|
411
413
|
|
|
414
|
+
const pluginCheckResult = await PluginManager.onHandlePreFromBtcExecute(
|
|
415
|
+
SwapHandlerType.FROM_BTC,
|
|
416
|
+
createdSwap
|
|
417
|
+
);
|
|
418
|
+
if(isQuoteThrow(pluginCheckResult)) throw {
|
|
419
|
+
code: 29999,
|
|
420
|
+
msg: pluginCheckResult.message
|
|
421
|
+
};
|
|
422
|
+
|
|
412
423
|
await PluginManager.swapCreate(createdSwap);
|
|
413
424
|
await this.saveSwapData(createdSwap);
|
|
414
425
|
|
|
@@ -27,6 +27,8 @@ import {
|
|
|
27
27
|
LightningNetworkInvoice
|
|
28
28
|
} from "../../../wallets/ILightningWallet";
|
|
29
29
|
import {LightningAssertions} from "../../assertions/LightningAssertions";
|
|
30
|
+
import {isQuoteThrow} from "../../../plugins/IPlugin";
|
|
31
|
+
import {FromBtcLnAutoSwapState} from "../frombtcln_autoinit/FromBtcLnAutoSwap";
|
|
30
32
|
|
|
31
33
|
export type FromBtcLnConfig = FromBtcBaseConfig & {
|
|
32
34
|
invoiceTimeoutSeconds?: number,
|
|
@@ -374,6 +376,20 @@ export class FromBtcLnAbs extends FromBtcBaseSwapHandler<FromBtcLnSwapAbs, FromB
|
|
|
374
376
|
//No need to check abortController anymore since all pending promises are resolved by now
|
|
375
377
|
if(invoiceData.metadata!=null) invoiceData.metadata.times.htlcSwapSigned = Date.now();
|
|
376
378
|
|
|
379
|
+
const pluginCheckResult = await PluginManager.onHandlePreFromBtcExecute(
|
|
380
|
+
SwapHandlerType.FROM_BTCLN,
|
|
381
|
+
invoiceData
|
|
382
|
+
);
|
|
383
|
+
if(isQuoteThrow(pluginCheckResult)) {
|
|
384
|
+
const error = {
|
|
385
|
+
code: 29999,
|
|
386
|
+
msg: pluginCheckResult.message
|
|
387
|
+
};
|
|
388
|
+
if(invoiceData.metadata!=null) invoiceData.metadata.htlcReceiveError = error;
|
|
389
|
+
if(invoiceData.state===FromBtcLnSwapState.CREATED) await this.cancelSwapAndInvoice(invoiceData);
|
|
390
|
+
throw error;
|
|
391
|
+
}
|
|
392
|
+
|
|
377
393
|
//Important to prevent race condition and issuing 2 signed init messages at the same time
|
|
378
394
|
if(invoiceData.state===FromBtcLnSwapState.CREATED) {
|
|
379
395
|
//Re-check right before signing
|
|
@@ -836,7 +852,13 @@ export class FromBtcLnAbs extends FromBtcBaseSwapHandler<FromBtcLnSwapAbs, FromB
|
|
|
836
852
|
msg: "Invoice already committed"
|
|
837
853
|
};
|
|
838
854
|
|
|
839
|
-
|
|
855
|
+
if (swap.state === FromBtcLnSwapState.CLAIMED) throw {
|
|
856
|
+
_httpStatus: 200,
|
|
857
|
+
code: 10005,
|
|
858
|
+
msg: "Invoice already committed & claimed"
|
|
859
|
+
};
|
|
860
|
+
|
|
861
|
+
if (swap.state === FromBtcLnSwapState.RECEIVED) res.status(200).json({
|
|
840
862
|
code: 10000,
|
|
841
863
|
msg: "Success",
|
|
842
864
|
data: {
|
|
@@ -19,6 +19,7 @@ import {
|
|
|
19
19
|
LightningNetworkInvoice
|
|
20
20
|
} from "../../../wallets/ILightningWallet";
|
|
21
21
|
import {LightningAssertions} from "../../assertions/LightningAssertions";
|
|
22
|
+
import {isQuoteThrow} from "../../../plugins/IPlugin";
|
|
22
23
|
|
|
23
24
|
export type FromBtcLnAutoConfig = FromBtcBaseConfig & {
|
|
24
25
|
invoiceTimeoutSeconds?: number,
|
|
@@ -420,6 +421,20 @@ export class FromBtcLnAuto extends FromBtcBaseSwapHandler<FromBtcLnAutoSwap, Fro
|
|
|
420
421
|
signature: invoiceData.signature
|
|
421
422
|
}, true);
|
|
422
423
|
|
|
424
|
+
const pluginCheckResult = await PluginManager.onHandlePreFromBtcExecute(
|
|
425
|
+
SwapHandlerType.FROM_BTCLN_AUTO,
|
|
426
|
+
invoiceData
|
|
427
|
+
);
|
|
428
|
+
if(isQuoteThrow(pluginCheckResult)) {
|
|
429
|
+
const error = {
|
|
430
|
+
code: 29999,
|
|
431
|
+
msg: pluginCheckResult.message
|
|
432
|
+
};
|
|
433
|
+
if(invoiceData.metadata!=null) invoiceData.metadata.htlcOfferError = error;
|
|
434
|
+
if(invoiceData.state===FromBtcLnAutoSwapState.RECEIVED) await this.cancelSwapAndInvoice(invoiceData);
|
|
435
|
+
throw error;
|
|
436
|
+
}
|
|
437
|
+
|
|
423
438
|
if(invoiceData.state===FromBtcLnAutoSwapState.RECEIVED) {
|
|
424
439
|
//Re-check the current HTLC count
|
|
425
440
|
try {
|
|
@@ -821,7 +836,6 @@ export class FromBtcLnAuto extends FromBtcBaseSwapHandler<FromBtcLnAutoSwap, Fro
|
|
|
821
836
|
};
|
|
822
837
|
|
|
823
838
|
if (
|
|
824
|
-
swap.state === FromBtcLnAutoSwapState.RECEIVED ||
|
|
825
839
|
swap.state === FromBtcLnAutoSwapState.TXS_SENT ||
|
|
826
840
|
swap.state === FromBtcLnAutoSwapState.COMMITED
|
|
827
841
|
) {
|
|
@@ -23,6 +23,8 @@ import {ServerParamEncoder} from "../../../utils/paramcoders/server/ServerParamE
|
|
|
23
23
|
import {ToBtcBaseConfig, ToBtcBaseSwapHandler} from "../ToBtcBaseSwapHandler";
|
|
24
24
|
import {IBitcoinWallet} from "../../../wallets/IBitcoinWallet";
|
|
25
25
|
import {checkTransactionReplaced} from "../../../utils/BitcoinUtils";
|
|
26
|
+
import {isQuoteThrow} from "../../../plugins/IPlugin";
|
|
27
|
+
import {FromBtcLnAutoSwapState} from "../frombtcln_autoinit/FromBtcLnAutoSwap";
|
|
26
28
|
|
|
27
29
|
const OUTPUT_SCRIPT_MAX_LENGTH = 200;
|
|
28
30
|
|
|
@@ -435,9 +437,33 @@ export class ToBtcAbs extends ToBtcBaseSwapHandler<ToBtcSwapAbs, ToBtcSwapState>
|
|
|
435
437
|
}
|
|
436
438
|
|
|
437
439
|
if(swap.state===ToBtcSwapState.COMMITED) {
|
|
438
|
-
const unlock: () => boolean = swap.lock(
|
|
440
|
+
const unlock: () => boolean = swap.lock(Infinity);
|
|
439
441
|
if(unlock==null) return;
|
|
440
442
|
|
|
443
|
+
const pluginCheckResult = await PluginManager.onHandlePreToBtcExecute(
|
|
444
|
+
SwapHandlerType.TO_BTC,
|
|
445
|
+
swap
|
|
446
|
+
);
|
|
447
|
+
if(isQuoteThrow(pluginCheckResult)) {
|
|
448
|
+
const error = {
|
|
449
|
+
code: 29999,
|
|
450
|
+
msg: pluginCheckResult.message
|
|
451
|
+
};
|
|
452
|
+
this.swapLogger.error(swap, "processInitialized(state=COMMITED): setting state to NON_PAYABLE due to send bitcoin payment error", error);
|
|
453
|
+
if(swap.metadata!=null) swap.metadata.payError = error;
|
|
454
|
+
unlock();
|
|
455
|
+
if(swap.state===ToBtcSwapState.COMMITED) {
|
|
456
|
+
await swap.setState(ToBtcSwapState.NON_PAYABLE);
|
|
457
|
+
await this.saveSwapData(swap);
|
|
458
|
+
}
|
|
459
|
+
return;
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
if(swap.state!==ToBtcSwapState.COMMITED) {
|
|
463
|
+
unlock();
|
|
464
|
+
return;
|
|
465
|
+
}
|
|
466
|
+
|
|
441
467
|
this.swapLogger.debug(swap, "processInitialized(state=COMMITED): sending bitcoin transaction, address: "+swap.address);
|
|
442
468
|
|
|
443
469
|
try {
|
|
@@ -453,9 +479,9 @@ export class ToBtcAbs extends ToBtcBaseSwapHandler<ToBtcSwapAbs, ToBtcSwapState>
|
|
|
453
479
|
this.swapLogger.error(swap, "processInitialized(state=COMMITED): send bitcoin payment error", e);
|
|
454
480
|
throw e;
|
|
455
481
|
}
|
|
482
|
+
} finally {
|
|
483
|
+
unlock();
|
|
456
484
|
}
|
|
457
|
-
|
|
458
|
-
unlock();
|
|
459
485
|
}
|
|
460
486
|
|
|
461
487
|
if(swap.state===ToBtcSwapState.NON_PAYABLE) return;
|