paid-services 4.1.0 → 4.2.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/CHANGELOG.md +4 -0
- package/package.json +13 -13
- package/swaps/complete_off_to_on_swap.js +3 -2
- package/swaps/complete_on_to_off_swap.js +9 -2
- package/swaps/manage_swap.js +5 -1
- package/swaps/output_script_for_address.js +55 -0
- package/swaps/request_swap_out.js +7 -1
- package/test/integration/test_request_swap_out.js +1 -1
- package/test/integration/test_swap_with_claim_path.js +1 -1
- package/test/integration/test_swap_with_refund_path.js +1 -1
package/CHANGELOG.md
CHANGED
package/package.json
CHANGED
|
@@ -7,25 +7,25 @@
|
|
|
7
7
|
"url": "https://github.com/alexbosworth/paid-services/issues"
|
|
8
8
|
},
|
|
9
9
|
"dependencies": {
|
|
10
|
-
"@alexbosworth/fiat": "1.0.
|
|
10
|
+
"@alexbosworth/fiat": "1.0.4",
|
|
11
11
|
"async": "3.2.4",
|
|
12
|
-
"asyncjs-util": "1.2.
|
|
12
|
+
"asyncjs-util": "1.2.11",
|
|
13
13
|
"bech32": "2.0.0",
|
|
14
|
-
"bolt01": "1.2.
|
|
15
|
-
"bolt07": "1.8.
|
|
14
|
+
"bolt01": "1.2.6",
|
|
15
|
+
"bolt07": "1.8.3",
|
|
16
16
|
"ecpair": "2.1.0",
|
|
17
|
-
"goldengate": "
|
|
18
|
-
"invoices": "2.2.
|
|
19
|
-
"ln-service": "54.
|
|
20
|
-
"ln-sync": "4.
|
|
21
|
-
"psbt": "2.7.
|
|
22
|
-
"p2tr": "1.3.
|
|
17
|
+
"goldengate": "12.0.1",
|
|
18
|
+
"invoices": "2.2.3",
|
|
19
|
+
"ln-service": "54.9.0",
|
|
20
|
+
"ln-sync": "4.1.1",
|
|
21
|
+
"psbt": "2.7.2",
|
|
22
|
+
"p2tr": "1.3.3",
|
|
23
23
|
"tiny-secp256k1": "2.2.1"
|
|
24
24
|
},
|
|
25
25
|
"description": "Lightning Paid Services library",
|
|
26
26
|
"devDependencies": {
|
|
27
|
-
"@alexbosworth/tap": "15.0.
|
|
28
|
-
"ln-docker-daemons": "
|
|
27
|
+
"@alexbosworth/tap": "15.0.12",
|
|
28
|
+
"ln-docker-daemons": "4.0.4",
|
|
29
29
|
"mock-lnd": "1.4.4",
|
|
30
30
|
"secp256k1": "4.0.3"
|
|
31
31
|
},
|
|
@@ -47,5 +47,5 @@
|
|
|
47
47
|
"integration-tests": "tap -j 2 --branches=1 --functions=1 --lines=1 --statements=1 -t 180 test/integration/*.js",
|
|
48
48
|
"test": "tap --branches=1 --functions=1 --lines=1 --statements=1 -t 60 test/actions/*.js test/balanced/*.js test/capacity/*.js test/client/*.js test/config/*.js test/p2p/*.js test/records/*.js test/respond/*.js test/server/*.js test/swaps/*.js test/services/*.js test/trades/*.js"
|
|
49
49
|
},
|
|
50
|
-
"version": "4.1
|
|
50
|
+
"version": "4.2.1"
|
|
51
51
|
}
|
|
@@ -65,6 +65,7 @@ const encodeAddress = (prefix, data) => bech32m.encode(prefix, data);
|
|
|
65
65
|
const externalKeyAsOutputScript = key => `5120${key}`;
|
|
66
66
|
const family = 805;
|
|
67
67
|
const {floor} = Math;
|
|
68
|
+
const format = 'p2tr';
|
|
68
69
|
const {from} = Buffer;
|
|
69
70
|
const {fromHex} = Transaction;
|
|
70
71
|
const fuzzBlocks = 100;
|
|
@@ -79,7 +80,7 @@ const {min} = Math;
|
|
|
79
80
|
const minTokens = 10000;
|
|
80
81
|
const minBlockMs = 1000 * 60;
|
|
81
82
|
const pollInterval = {btcregtest: 100};
|
|
82
|
-
const ppmRate = (fee, total) => fee * 1e6 / total
|
|
83
|
+
const ppmRate = (fee, total) => fee * 1e6 / total;
|
|
83
84
|
const preimageByteLength = 32;
|
|
84
85
|
const pubKeyAsInternalKey = key => Buffer.from(key).slice(1).toString('hex');
|
|
85
86
|
const pushSecret = asyncTimeout(releaseSwapOutSecret, 1000 * 30);
|
|
@@ -155,7 +156,7 @@ module.exports = (args, cbk) => {
|
|
|
155
156
|
return cbk(null, {address: args.sweep_address});
|
|
156
157
|
}
|
|
157
158
|
|
|
158
|
-
return createChainAddress({lnd: args.lnd}, cbk);
|
|
159
|
+
return createChainAddress({format, lnd: args.lnd}, cbk);
|
|
159
160
|
}],
|
|
160
161
|
|
|
161
162
|
// Get the current chain fee rate for the sweep fee rate calculation
|
|
@@ -42,9 +42,11 @@ const {typePayMetadata} = require('./swap_field_types');
|
|
|
42
42
|
const bufferAsHex = buffer => buffer.toString('hex');
|
|
43
43
|
const defaultMaxFundingConfirmationDelay = 12;
|
|
44
44
|
const defaultMinDelta = 60;
|
|
45
|
+
const estimatedSize = 150;
|
|
45
46
|
const family = 805;
|
|
46
47
|
const flatten = arr => [].concat(...arr);
|
|
47
48
|
const {floor} = Math;
|
|
49
|
+
const format = 'p2tr';
|
|
48
50
|
const {from} = Buffer;
|
|
49
51
|
const {fromHex} = Transaction;
|
|
50
52
|
const fuzzBlocks = 100;
|
|
@@ -126,7 +128,7 @@ module.exports = (args, cbk) => {
|
|
|
126
128
|
|
|
127
129
|
// Get an address to sweep out to
|
|
128
130
|
getSweepAddress: ['validate', ({}, cbk) => {
|
|
129
|
-
return createChainAddress({lnd: args.lnd}, cbk);
|
|
131
|
+
return createChainAddress({format, lnd: args.lnd}, cbk);
|
|
130
132
|
}],
|
|
131
133
|
|
|
132
134
|
// Get the encryption key to decode the recovery secrets
|
|
@@ -370,6 +372,11 @@ module.exports = (args, cbk) => {
|
|
|
370
372
|
});
|
|
371
373
|
|
|
372
374
|
const refunds = uniqBy(feeRates, 'rate').map(({rate, height}) => {
|
|
375
|
+
// Exit early when there is nothing to recover
|
|
376
|
+
if (rate * estimatedSize > recoveryDetails.tokens) {
|
|
377
|
+
return;
|
|
378
|
+
}
|
|
379
|
+
|
|
373
380
|
return taprootRefundTransaction({
|
|
374
381
|
ecp,
|
|
375
382
|
block_height: height,
|
|
@@ -388,7 +395,7 @@ module.exports = (args, cbk) => {
|
|
|
388
395
|
});
|
|
389
396
|
});
|
|
390
397
|
|
|
391
|
-
return cbk(null, refunds.map(n => n.transaction));
|
|
398
|
+
return cbk(null, refunds.filter(n => !!n).map(n => n.transaction));
|
|
392
399
|
}],
|
|
393
400
|
|
|
394
401
|
// Sign the refund transactions
|
package/swaps/manage_swap.js
CHANGED
|
@@ -13,6 +13,7 @@ const {returnResult} = require('asyncjs-util');
|
|
|
13
13
|
const decodeOffToOnRequest = require('./decode_off_to_on_request');
|
|
14
14
|
const decodeOffToOnRestart = require('./decode_off_to_on_restart');
|
|
15
15
|
const {decodeTrade} = require('./../trades');
|
|
16
|
+
const outputScriptForAddress = require('./output_script_for_address');
|
|
16
17
|
const recoverResponseToSwapOut = require('./recover_response_to_swap_out');
|
|
17
18
|
const requestSwapOut = require('./request_swap_out');
|
|
18
19
|
const respondToSwapOutRequest = require('./respond_to_swap_out_request');
|
|
@@ -310,7 +311,10 @@ module.exports = (args, cbk) => {
|
|
|
310
311
|
}
|
|
311
312
|
|
|
312
313
|
try {
|
|
313
|
-
return !!
|
|
314
|
+
return !!outputScriptForAddress({
|
|
315
|
+
address: input,
|
|
316
|
+
network: getNetwork.bitcoinjs,
|
|
317
|
+
});
|
|
314
318
|
} catch (err) {
|
|
315
319
|
return 'Unsupported on-chain address format';
|
|
316
320
|
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
const {address} = require('bitcoinjs-lib');
|
|
2
|
+
const {networks} = require('bitcoinjs-lib');
|
|
3
|
+
|
|
4
|
+
const bufferAsHex = buffer => buffer.toString('hex');
|
|
5
|
+
const byteLengthForP2tr = 32;
|
|
6
|
+
const {fromBech32} = address;
|
|
7
|
+
const prefixForP2tr = '5120';
|
|
8
|
+
const toOutputScript = (a, n) => address.toOutputScript(a, n).toString('hex');
|
|
9
|
+
const versionTaproot = 1;
|
|
10
|
+
|
|
11
|
+
/** Get the output script for an address
|
|
12
|
+
|
|
13
|
+
{
|
|
14
|
+
address: <Address String>
|
|
15
|
+
network: <BitcoinJs Network Name String>
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
@throws
|
|
19
|
+
<Error>
|
|
20
|
+
|
|
21
|
+
@returns
|
|
22
|
+
{
|
|
23
|
+
script: <Output Script Hex String>
|
|
24
|
+
}
|
|
25
|
+
*/
|
|
26
|
+
module.exports = ({address, network}) => {
|
|
27
|
+
try {
|
|
28
|
+
return {
|
|
29
|
+
script: bufferAsHex(toOutputScript(address, networks[network])),
|
|
30
|
+
};
|
|
31
|
+
} catch (err) {
|
|
32
|
+
// Exit early when this is not a bech32 address
|
|
33
|
+
try {
|
|
34
|
+
fromBech32(address);
|
|
35
|
+
} catch (_) {
|
|
36
|
+
throw err;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const {data, prefix, version} = fromBech32(address);
|
|
40
|
+
|
|
41
|
+
if (prefix !== networks[network].bech32) {
|
|
42
|
+
throw new Error('InvalidNetworkToConvertAddressToOutputScript');
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if (version !== versionTaproot) {
|
|
46
|
+
throw new Error('UnexpectedVersionOfAddressToConverToOutputScript');
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
if (data.length !== byteLengthForP2tr) {
|
|
50
|
+
throw new Error('UnexpectedByteLengthForPayToTaprootAddress');
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
return {script: `${prefixForP2tr}${bufferAsHex(data)}`};
|
|
54
|
+
}
|
|
55
|
+
};
|
|
@@ -31,6 +31,7 @@ const defaultFeeRate = 5000;
|
|
|
31
31
|
const defaultMaxAmount = 21e14;
|
|
32
32
|
const defaultMaxFeeForDeposit = 1337;
|
|
33
33
|
const defaultSwapAmount = 2500000;
|
|
34
|
+
const feeAsPpm = (fee, total) => Math.ceil(fee * 1e6 / total);
|
|
34
35
|
const findRecord = (r, type) => (r.find(n => n.type === type) || {}).value;
|
|
35
36
|
const {floor} = Math;
|
|
36
37
|
const hexAsBuffer = hex => Buffer.from(hex, 'hex');
|
|
@@ -421,14 +422,19 @@ module.exports = (args, cbk) => {
|
|
|
421
422
|
|
|
422
423
|
const deposit = mtokensAsTokens(response.deposit_mtokens);
|
|
423
424
|
|
|
425
|
+
const combinedFee = tokens - askForTokens + deposit;
|
|
424
426
|
const serviceFee = tokensAsBigUnit(deposit);
|
|
425
427
|
const totalFee = tokensAsBigUnit(tokens - askForTokens + deposit);
|
|
426
428
|
|
|
429
|
+
const ppmTotal = feeAsPpm(combinedFee, askForTokens);
|
|
430
|
+
|
|
431
|
+
const feeInfo = `total fee is ${totalFee}, est PPM ${ppmTotal}`
|
|
432
|
+
|
|
427
433
|
return cbk(null, {
|
|
428
434
|
deposit,
|
|
429
435
|
fee: tokens - askForTokens,
|
|
430
436
|
incoming_peer: response.incoming_peer,
|
|
431
|
-
pricing: `Execution cost ${serviceFee},
|
|
437
|
+
pricing: `Execution cost ${serviceFee}, ${feeInfo}`,
|
|
432
438
|
rate: rateForFee(askForTokens, deposit + (tokens - askForTokens)),
|
|
433
439
|
timeout: response.timeout,
|
|
434
440
|
});
|
|
@@ -53,7 +53,7 @@ test(`Start offchain swap`, async ({end, equal, strictSame}) => {
|
|
|
53
53
|
});
|
|
54
54
|
|
|
55
55
|
await asyncRetry({interval, times}, async () => {
|
|
56
|
-
const {channels} = await getChannels({lnd,
|
|
56
|
+
const {channels} = await getChannels({lnd, is_active: true});
|
|
57
57
|
|
|
58
58
|
if (!!channels.length) {
|
|
59
59
|
return channels;
|
|
@@ -53,7 +53,7 @@ test(`Swap with claim path`, async ({end, equal, strictSame}) => {
|
|
|
53
53
|
});
|
|
54
54
|
|
|
55
55
|
await asyncRetry({interval, times}, async () => {
|
|
56
|
-
const {channels} = await getChannels({lnd,
|
|
56
|
+
const {channels} = await getChannels({lnd, is_active: true});
|
|
57
57
|
|
|
58
58
|
if (!!channels.length) {
|
|
59
59
|
return channels;
|
|
@@ -58,7 +58,7 @@ test(`Timeout a swap`, async ({end, equal, strictSame}) => {
|
|
|
58
58
|
});
|
|
59
59
|
|
|
60
60
|
await asyncRetry({interval, times}, async () => {
|
|
61
|
-
const {channels} = await getChannels({lnd,
|
|
61
|
+
const {channels} = await getChannels({lnd, is_active: true});
|
|
62
62
|
|
|
63
63
|
if (!!channels.length) {
|
|
64
64
|
return channels;
|