ln-service 52.14.4 → 53.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +21 -0
- package/README.md +163 -11
- package/package.json +7 -14
- package/test/autopilotrpc-integration/test_autopilot.js +9 -15
- package/test/chainrpc-integration/test_get_height.js +7 -10
- package/test/chainrpc-integration/test_subscribe_to_blocks.js +52 -31
- package/test/chainrpc-integration/test_subscribe_to_chain_address.js +72 -66
- package/test/chainrpc-integration/test_subscribe_to_chain_spend.js +47 -16
- package/test/{integration → extra-integration}/test_recover_funds_from_channel.js +0 -0
- package/test/{integration → extra-integration}/test_recover_funds_from_channels.js +0 -0
- package/test/{integration → extra-integration}/test_restrict_macaroon.js +0 -0
- package/test/{integration → extra-integration}/test_revoke_access.js +0 -0
- package/test/{integration → extra-integration}/test_subscribe_to_rpc_requests.js +1 -1
- package/test/integration/test_add_peer.js +16 -12
- package/test/integration/test_cancel_pending_channel.js +20 -6
- package/test/integration/test_close_channel.js +15 -10
- package/test/integration/test_create_chain_address.js +3 -6
- package/test/integration/test_create_invoice.js +27 -23
- package/test/integration/test_decode_payment_request.js +30 -29
- package/test/integration/test_delete_payment.js +11 -8
- package/test/integration/test_delete_payments.js +13 -16
- package/test/integration/test_get_access_ids.js +4 -7
- package/test/integration/test_get_backup.js +12 -8
- package/test/integration/test_get_backups.js +8 -10
- package/test/integration/test_get_chain_balance.js +9 -53
- package/test/integration/test_get_chain_fee_estimate.js +21 -10
- package/test/integration/test_get_chain_transactions.js +30 -52
- package/test/integration/test_get_channel.js +7 -7
- package/test/integration/test_get_channel_balance.js +5 -6
- package/test/integration/test_get_channels.js +11 -10
- package/test/integration/test_get_closed_channels.js +169 -139
- package/test/integration/test_get_failed_payments.js +37 -39
- package/test/integration/test_get_fee_rates.js +6 -9
- package/test/integration/test_get_forwards.js +34 -35
- package/test/integration/test_get_invoice.js +7 -11
- package/test/integration/test_get_invoices.js +33 -30
- package/test/integration/test_get_methods.js +4 -7
- package/test/integration/test_get_network_centrality.js +14 -17
- package/test/integration/test_get_network_graph.js +12 -15
- package/test/integration/test_get_network_info.js +5 -6
- package/test/integration/test_get_node.js +15 -31
- package/test/integration/test_get_payments.js +10 -10
- package/test/integration/test_get_peers.js +10 -13
- package/test/integration/test_get_pending_coop.js +13 -18
- package/test/integration/test_get_pending_force.js +29 -21
- package/test/integration/test_get_route_to_destination.js +47 -40
- package/test/integration/test_get_utxos.js +17 -42
- package/test/integration/test_get_wallet_info.js +5 -12
- package/test/integration/test_open_channel.js +16 -9
- package/test/integration/test_open_channels.js +66 -66
- package/test/integration/test_pay.js +39 -36
- package/test/integration/test_pay_private_invoice.js +78 -72
- package/test/integration/test_payment_errors.js +13 -11
- package/test/integration/test_propose_channel.js +74 -53
- package/test/integration/test_push_funds.js +11 -15
- package/test/integration/test_rebalance.js +11 -22
- package/test/integration/test_remove_peer.js +13 -48
- package/test/integration/test_send_message_to_peer.js +25 -17
- package/test/integration/test_send_to_chain_address.js +60 -51
- package/test/integration/test_send_to_chain_addresses.js +30 -18
- package/test/integration/test_sign_message.js +3 -6
- package/test/integration/test_stop_daemon.js +3 -9
- package/test/integration/test_subscribe_to_backups.js +19 -11
- package/test/integration/test_subscribe_to_channels.js +28 -20
- package/test/integration/test_subscribe_to_graph.js +43 -22
- package/test/integration/test_subscribe_to_invoices.js +89 -103
- package/test/integration/test_subscribe_to_open_requests.js +47 -31
- package/test/integration/test_subscribe_to_peer_messages.js +51 -21
- package/test/integration/test_subscribe_to_peers.js +11 -16
- package/test/integration/test_subscribe_to_transactions.js +49 -45
- package/test/integration/test_update_routing_fees.js +12 -16
- package/test/integration/test_verify_access.js +5 -10
- package/test/integration/test_verify_backup.js +10 -8
- package/test/integration/test_verify_backups.js +11 -16
- package/test/integration/test_verify_message.js +6 -9
- package/test/invoicesrpc-integration/test_cancel_invoice.js +15 -22
- package/test/invoicesrpc-integration/test_get_sweep_transactions.js +15 -11
- package/test/invoicesrpc-integration/test_push_payment.js +53 -55
- package/test/invoicesrpc-integration/test_settle_invoice.js +25 -19
- package/test/invoicesrpc-integration/test_subscribe_cancel_invoice.js +13 -11
- package/test/invoicesrpc-integration/test_subscribe_settle_invoice.js +20 -15
- package/test/macros/btcsuite_type_daemon.js +1 -1
- package/test/macros/chain_send_transaction.js +1 -1
- package/test/macros/change_password.js +15 -13
- package/test/macros/generate_blocks.js +24 -29
- package/test/macros/rpc.js +1 -0
- package/test/macros/setup_channel.js +23 -9
- package/test/macros/spawn_lnd.js +3 -1
- package/test/macros/wait_for_channel.js +8 -3
- package/test/macros/wait_for_route.js +2 -2
- package/test/routerrpc-integration/test_delete_forwarding_reputations.js +15 -22
- package/test/routerrpc-integration/test_disable_channel.js +8 -12
- package/test/routerrpc-integration/test_get_forwarding_confidence.js +17 -37
- package/test/routerrpc-integration/test_get_forwarding_reputations.js +26 -25
- package/test/routerrpc-integration/test_get_pathfinding_settings.js +6 -12
- package/test/routerrpc-integration/test_get_payment.js +19 -26
- package/test/routerrpc-integration/test_get_route_confidence.js +15 -21
- package/test/routerrpc-integration/test_get_route_through_hops.js +29 -32
- package/test/routerrpc-integration/test_multipath_payment.js +18 -20
- package/test/routerrpc-integration/test_pay_via_payment_details.js +19 -34
- package/test/routerrpc-integration/test_pay_via_payment_request.js +17 -27
- package/test/routerrpc-integration/test_pay_via_routes.js +37 -37
- package/test/routerrpc-integration/test_probe_for_route.js +27 -33
- package/test/routerrpc-integration/test_subscribe_to_forward_requests.js +138 -32
- package/test/routerrpc-integration/test_subscribe_to_forwards.js +83 -77
- package/test/routerrpc-integration/test_subscribe_to_past_payments.js +34 -28
- package/test/routerrpc-integration/test_update_pathfinding_settings.js +7 -10
- package/test/signerrpc-integration/test_diffie_hellman_compute_secret.js +15 -14
- package/test/signerrpc-integration/test_sign_bytes.js +11 -15
- package/test/signerrpc-integration/test_sign_transaction.js +6 -7
- package/test/signerrpc-integration/test_verify_bytes_signature.js +11 -12
- package/test/versionrpc-integration/test_get_wallet_version.js +6 -7
- package/test/walletrpc-integration/test_fund_psbt.js +13 -12
- package/test/walletrpc-integration/test_get_chain_fee_rate.js +4 -8
- package/test/walletrpc-integration/test_get_locked_utxos.js +11 -27
- package/test/walletrpc-integration/test_get_public_key.js +5 -13
- package/test/walletrpc-integration/test_lock_utxo.js +16 -23
- package/test/walletrpc-integration/test_send_to_chain_output_scripts.js +25 -6
- package/test/walletrpc-integration/test_sign_psbt.js +28 -19
- package/test/walletrpc-integration/test_unlock_utxo.js +16 -27
- package/test/walletrpc-integration/test_update_chain_transaction.js +6 -31
|
@@ -1,43 +1,50 @@
|
|
|
1
1
|
const asyncRetry = require('async/retry');
|
|
2
|
+
const {spawnLightningCluster} = require('ln-docker-daemons');
|
|
2
3
|
const {test} = require('@alexbosworth/tap');
|
|
3
4
|
|
|
5
|
+
const {addPeer} = require('./../../');
|
|
4
6
|
const {createChainAddress} = require('./../../');
|
|
5
|
-
const {
|
|
7
|
+
const {getChainBalance} = require('./../../');
|
|
6
8
|
const {openChannel} = require('./../../');
|
|
7
9
|
|
|
8
10
|
const channelCapacityTokens = 1e6;
|
|
11
|
+
const count = 100;
|
|
9
12
|
const defaultFee = 1e3;
|
|
10
13
|
const defaultVout = 0;
|
|
11
|
-
const format = 'p2wpkh';
|
|
12
14
|
const giftTokens = 1000;
|
|
13
15
|
const interval = 250;
|
|
14
|
-
const
|
|
16
|
+
const size = 2;
|
|
17
|
+
const times = 1000;
|
|
15
18
|
const txIdHexLength = 32 * 2;
|
|
16
19
|
|
|
17
20
|
// Opening a channel should open a channel
|
|
18
21
|
test(`Open channel`, async ({end, equal}) => {
|
|
19
|
-
const
|
|
22
|
+
const {kill, nodes} = await spawnLightningCluster({size});
|
|
20
23
|
|
|
21
|
-
const {lnd} =
|
|
24
|
+
const [{generate, lnd}, target] = nodes;
|
|
22
25
|
|
|
23
|
-
const {address} = await createChainAddress({
|
|
26
|
+
const {address} = await createChainAddress({lnd});
|
|
27
|
+
|
|
28
|
+
await generate({count});
|
|
24
29
|
|
|
25
30
|
const channelOpen = await asyncRetry({interval, times}, async () => {
|
|
31
|
+
await addPeer({lnd, public_key: target.id, socket: target.socket});
|
|
32
|
+
|
|
26
33
|
return await openChannel({
|
|
27
34
|
lnd,
|
|
28
35
|
chain_fee_tokens_per_vbyte: defaultFee,
|
|
29
36
|
cooperative_close_address: address,
|
|
30
37
|
give_tokens: giftTokens,
|
|
31
38
|
local_tokens: channelCapacityTokens,
|
|
32
|
-
partner_public_key:
|
|
33
|
-
socket:
|
|
39
|
+
partner_public_key: target.id,
|
|
40
|
+
socket: target.socket,
|
|
34
41
|
});
|
|
35
42
|
});
|
|
36
43
|
|
|
37
44
|
equal(channelOpen.transaction_id.length, txIdHexLength, 'Channel tx id');
|
|
38
45
|
equal(channelOpen.transaction_vout, defaultVout, 'Channel tx output index');
|
|
39
46
|
|
|
40
|
-
await
|
|
47
|
+
await kill({});
|
|
41
48
|
|
|
42
49
|
return end();
|
|
43
50
|
});
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
const asyncRetry = require('async/retry');
|
|
2
2
|
const {extractTransaction} = require('psbt');
|
|
3
3
|
const {finalizePsbt} = require('psbt');
|
|
4
|
+
const {spawnLightningCluster} = require('ln-docker-daemons');
|
|
4
5
|
const {test} = require('@alexbosworth/tap');
|
|
5
6
|
const {transactionAsPsbt} = require('psbt');
|
|
6
7
|
|
|
7
8
|
const {addPeer} = require('./../../');
|
|
8
|
-
const {createCluster} = require('./../macros');
|
|
9
9
|
const {delay} = require('./../macros');
|
|
10
10
|
const {fundPendingChannels} = require('./../../');
|
|
11
|
+
const {getChainBalance} = require('./../../');
|
|
11
12
|
const {getChainTransactions} = require('./../../');
|
|
12
13
|
const {getChannels} = require('./../../');
|
|
13
14
|
const {getPeers} = require('./../../');
|
|
@@ -16,99 +17,98 @@ const {sendToChainAddresses} = require('./../../');
|
|
|
16
17
|
|
|
17
18
|
const capacity = 1e6;
|
|
18
19
|
const count = 10;
|
|
19
|
-
const interval =
|
|
20
|
+
const interval = 1;
|
|
20
21
|
const race = promises => Promise.race(promises);
|
|
22
|
+
const size = 3;
|
|
21
23
|
const timeout = 250 * 10;
|
|
22
|
-
const times =
|
|
24
|
+
const times = 200;
|
|
23
25
|
|
|
24
26
|
// Opening channels should open up channels
|
|
25
27
|
test(`Open channels`, async ({end, equal}) => {
|
|
26
|
-
|
|
27
|
-
const cluster = await createCluster({});
|
|
28
|
+
const {kill, nodes} = await spawnLightningCluster({size});
|
|
28
29
|
|
|
29
|
-
|
|
30
|
-
const {lnd} = cluster.control;
|
|
30
|
+
const [{generate, lnd}, target, remote] = nodes;
|
|
31
31
|
|
|
32
|
-
|
|
32
|
+
await asyncRetry({times}, async () => {
|
|
33
|
+
if (!(await getChainBalance({lnd})).chain_balance) {
|
|
34
|
+
await generate({});
|
|
33
35
|
|
|
34
|
-
|
|
36
|
+
throw new Error('ExpectedChainBalanceToOpenChannel');
|
|
37
|
+
}
|
|
38
|
+
});
|
|
35
39
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
public_key: cluster.remote.public_key,
|
|
39
|
-
socket: cluster.remote.socket,
|
|
40
|
-
});
|
|
40
|
+
try {
|
|
41
|
+
const chainTx = (await getChainTransactions({lnd})).transactions;
|
|
41
42
|
|
|
42
|
-
|
|
43
|
-
capacity,
|
|
44
|
-
partner_public_key: node.public_key,
|
|
45
|
-
}));
|
|
43
|
+
const spending = chainTx.map(({transaction}) => transaction);
|
|
46
44
|
|
|
47
|
-
|
|
45
|
+
await addPeer({lnd, public_key: remote.id, socket: remote.socket});
|
|
48
46
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
public_key: cluster.remote.public_key,
|
|
54
|
-
socket: cluster.remote.socket,
|
|
55
|
-
});
|
|
47
|
+
const channels = [target, remote].map(node => ({
|
|
48
|
+
capacity,
|
|
49
|
+
partner_public_key: node.id,
|
|
50
|
+
}));
|
|
56
51
|
|
|
57
|
-
|
|
58
|
-
throw new Error('ExpectedConnectedPeersToOpenChannels');
|
|
59
|
-
}
|
|
52
|
+
let pending;
|
|
60
53
|
|
|
61
|
-
|
|
62
|
-
|
|
54
|
+
// Wait for peers to be connected
|
|
55
|
+
await asyncRetry({interval, times}, async () => {
|
|
56
|
+
await addPeer({lnd, public_key: remote.id, socket: remote.socket});
|
|
63
57
|
|
|
64
|
-
await
|
|
65
|
-
|
|
66
|
-
}
|
|
58
|
+
if ((await getPeers({lnd})).peers.length !== channels.length) {
|
|
59
|
+
throw new Error('ExpectedConnectedPeersToOpenChannels');
|
|
60
|
+
}
|
|
67
61
|
|
|
68
|
-
|
|
69
|
-
|
|
62
|
+
return;
|
|
63
|
+
});
|
|
70
64
|
|
|
71
|
-
|
|
72
|
-
|
|
65
|
+
await asyncRetry({interval, times}, async () => {
|
|
66
|
+
pending = (await openChannels({channels, lnd})).pending;
|
|
67
|
+
});
|
|
73
68
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
}
|
|
69
|
+
// Normally funding would involve an un-broadcast transaction
|
|
70
|
+
await sendToChainAddresses({lnd, send_to: pending});
|
|
77
71
|
|
|
78
|
-
|
|
79
|
-
});
|
|
72
|
+
await asyncRetry({interval, times}, async() => {
|
|
73
|
+
const {transactions} = await getChainTransactions({lnd});
|
|
80
74
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
75
|
+
if (transactions.length !== pending.length) {
|
|
76
|
+
throw new Error('ExpectedMultipleChainTransactions');
|
|
77
|
+
}
|
|
84
78
|
|
|
85
|
-
|
|
79
|
+
return;
|
|
80
|
+
});
|
|
86
81
|
|
|
87
|
-
|
|
82
|
+
const fundTx = (await getChainTransactions({lnd})).transactions
|
|
83
|
+
.map(({transaction}) => transaction)
|
|
84
|
+
.find(transaction => spending.find(spend => transaction !== spend));
|
|
88
85
|
|
|
89
|
-
|
|
86
|
+
const fundingPsbt = transactionAsPsbt({spending, transaction: fundTx});
|
|
90
87
|
|
|
91
|
-
|
|
92
|
-
lnd,
|
|
93
|
-
channels: pending.map(({id}) => id),
|
|
94
|
-
funding: psbt,
|
|
95
|
-
});
|
|
88
|
+
const {psbt} = finalizePsbt({psbt: fundingPsbt.psbt});
|
|
96
89
|
|
|
97
|
-
|
|
98
|
-
await cluster.generate({count});
|
|
90
|
+
const reconstitutedTransaction = extractTransaction({psbt});
|
|
99
91
|
|
|
100
|
-
|
|
92
|
+
await fundPendingChannels({
|
|
93
|
+
lnd,
|
|
94
|
+
channels: pending.map(({id}) => id),
|
|
95
|
+
funding: psbt,
|
|
96
|
+
});
|
|
101
97
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
}
|
|
98
|
+
await asyncRetry({interval, times}, async () => {
|
|
99
|
+
await generate({count});
|
|
105
100
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
101
|
+
const {channels} = await getChannels({lnd});
|
|
102
|
+
|
|
103
|
+
if (channels.filter(n => !!n.is_active).length !== pending.length) {
|
|
104
|
+
throw new Error('ExpectedNewChannelsCreatedAndActive');
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
return;
|
|
108
|
+
});
|
|
109
|
+
} finally {
|
|
110
|
+
return await kill({});
|
|
111
|
+
}
|
|
112
112
|
|
|
113
113
|
return end();
|
|
114
114
|
});
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
const {randomBytes} = require('crypto');
|
|
2
2
|
|
|
3
|
+
const asyncRetry = require('async/retry');
|
|
4
|
+
const {spawnLightningCluster} = require('ln-docker-daemons');
|
|
3
5
|
const {test} = require('@alexbosworth/tap');
|
|
4
6
|
|
|
5
7
|
const {addPeer} = require('./../../');
|
|
@@ -22,42 +24,37 @@ const channelCapacityTokens = 1e6;
|
|
|
22
24
|
const confirmationCount = 6;
|
|
23
25
|
const defaultFee = 1e3;
|
|
24
26
|
const defaultVout = 0;
|
|
27
|
+
const interval = 10;
|
|
25
28
|
const mtokPadding = '000';
|
|
26
29
|
const reserveRatio = 0.99;
|
|
30
|
+
const size = 3;
|
|
31
|
+
const times = 1000;
|
|
27
32
|
const tokens = 100;
|
|
28
33
|
const txIdHexLength = 32 * 2;
|
|
29
34
|
|
|
30
35
|
// Paying an invoice should settle the invoice
|
|
31
36
|
test(`Pay`, async ({end, equal, strictSame}) => {
|
|
32
|
-
const
|
|
37
|
+
const {kill, nodes} = await spawnLightningCluster({size});
|
|
33
38
|
|
|
34
|
-
const {lnd} =
|
|
39
|
+
const [{generate, lnd}, target, remote] = nodes;
|
|
35
40
|
|
|
36
|
-
const channel = await setupChannel({
|
|
37
|
-
lnd,
|
|
38
|
-
generate: cluster.generate,
|
|
39
|
-
to: cluster.target,
|
|
40
|
-
});
|
|
41
|
+
const channel = await setupChannel({generate, lnd, to: target});
|
|
41
42
|
|
|
42
43
|
const remoteChan = await setupChannel({
|
|
43
|
-
generate:
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
to: cluster.remote,
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
await addPeer({
|
|
50
|
-
lnd,
|
|
51
|
-
public_key: cluster.remote.public_key,
|
|
52
|
-
socket: cluster.remote.socket,
|
|
44
|
+
generate: target.generate,
|
|
45
|
+
lnd: target.lnd,
|
|
46
|
+
to: remote,
|
|
53
47
|
});
|
|
54
48
|
|
|
55
|
-
await
|
|
49
|
+
await addPeer({lnd, public_key: remote.id, socket: remote.socket});
|
|
56
50
|
|
|
57
|
-
const invoice = await createInvoice({tokens, lnd:
|
|
51
|
+
const invoice = await createInvoice({tokens, lnd: remote.lnd});
|
|
58
52
|
|
|
59
53
|
const commitTxFee = channel.commit_transaction_fee;
|
|
60
|
-
|
|
54
|
+
|
|
55
|
+
const paid = await asyncRetry({interval, times}, async () => {
|
|
56
|
+
return await pay({lnd, request: invoice.request});
|
|
57
|
+
});
|
|
61
58
|
|
|
62
59
|
equal(paid.fee, 1, 'Fee paid for hop');
|
|
63
60
|
equal(paid.fee_mtokens, '1000', 'Fee mtokens tokens paid');
|
|
@@ -86,7 +83,7 @@ test(`Pay`, async ({end, equal, strictSame}) => {
|
|
|
86
83
|
fee_mtokens: '1000',
|
|
87
84
|
forward: 100,
|
|
88
85
|
forward_mtokens: `${invoice.tokens}${mtokPadding}`,
|
|
89
|
-
public_key:
|
|
86
|
+
public_key: target.id,
|
|
90
87
|
},
|
|
91
88
|
{
|
|
92
89
|
channel: remoteChan.id,
|
|
@@ -95,35 +92,41 @@ test(`Pay`, async ({end, equal, strictSame}) => {
|
|
|
95
92
|
fee_mtokens: '0',
|
|
96
93
|
forward: 100,
|
|
97
94
|
forward_mtokens: '100000',
|
|
98
|
-
public_key:
|
|
95
|
+
public_key: remote.id,
|
|
99
96
|
},
|
|
100
97
|
];
|
|
101
98
|
|
|
102
99
|
strictSame(paid.hops, expectedHops, 'Hops are returned');
|
|
103
100
|
|
|
104
|
-
const invoice2 = await createInvoice({lnd:
|
|
101
|
+
const invoice2 = await createInvoice({lnd: remote.lnd, tokens: 100});
|
|
105
102
|
|
|
106
103
|
const {destination} = await decodePaymentRequest({
|
|
107
|
-
lnd:
|
|
104
|
+
lnd: remote.lnd,
|
|
108
105
|
request: invoice2.request,
|
|
109
106
|
});
|
|
110
107
|
|
|
111
|
-
await
|
|
108
|
+
await generate({count: confirmationCount});
|
|
112
109
|
|
|
113
|
-
await
|
|
110
|
+
const route = await asyncRetry({interval, times}, async () => {
|
|
111
|
+
const {route} = await getRouteToDestination({
|
|
112
|
+
destination,
|
|
113
|
+
lnd,
|
|
114
|
+
payment: invoice2.payment,
|
|
115
|
+
tokens: invoice2.tokens,
|
|
116
|
+
total_mtokens: !!invoice2.payment ? invoice2.mtokens : undefined,
|
|
117
|
+
});
|
|
114
118
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
total_mtokens: !!invoice2.payment ? invoice2.mtokens : undefined,
|
|
119
|
+
if (!route) {
|
|
120
|
+
throw new Error('ExpectedRouteToDestination');
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
return route;
|
|
121
124
|
});
|
|
122
125
|
|
|
123
126
|
// Test paying to a route, but to an id that isn't known
|
|
124
127
|
try {
|
|
125
128
|
await pay({
|
|
126
|
-
lnd
|
|
129
|
+
lnd,
|
|
127
130
|
path: {routes: [route], id: randomBytes(32).toString('hex')},
|
|
128
131
|
});
|
|
129
132
|
} catch (err) {
|
|
@@ -135,15 +138,15 @@ test(`Pay`, async ({end, equal, strictSame}) => {
|
|
|
135
138
|
|
|
136
139
|
// Test paying regularly to a destination
|
|
137
140
|
const directPay = await pay({
|
|
138
|
-
lnd
|
|
141
|
+
lnd,
|
|
139
142
|
path: {routes: [route], id: invoice2.id},
|
|
140
143
|
});
|
|
141
144
|
|
|
142
|
-
const zeroInvoice = await createInvoice({lnd:
|
|
145
|
+
const zeroInvoice = await createInvoice({lnd: target.lnd});
|
|
143
146
|
|
|
144
147
|
await pay({lnd, request: zeroInvoice.request, mtokens: '1000'});
|
|
145
148
|
|
|
146
|
-
await
|
|
149
|
+
await kill({});
|
|
147
150
|
|
|
148
151
|
return end();
|
|
149
152
|
});
|
|
@@ -1,102 +1,108 @@
|
|
|
1
1
|
const {randomBytes} = require('crypto');
|
|
2
2
|
|
|
3
|
+
const asyncRetry = require('async/retry');
|
|
4
|
+
const {spawnLightningCluster} = require('ln-docker-daemons');
|
|
3
5
|
const {test} = require('@alexbosworth/tap');
|
|
4
6
|
|
|
5
|
-
const {
|
|
6
|
-
const {createCluster} = require('./../macros');
|
|
7
|
+
const {cancelHodlInvoice} = require('./../../');
|
|
7
8
|
const {createInvoice} = require('./../../');
|
|
8
9
|
const {decodePaymentRequest} = require('./../../');
|
|
9
|
-
const {delay} = require('./../macros');
|
|
10
10
|
const {getChannel} = require('./../../');
|
|
11
11
|
const {getChannels} = require('./../../');
|
|
12
12
|
const {getInvoice} = require('./../../');
|
|
13
13
|
const {getRouteToDestination} = require('./../../');
|
|
14
14
|
const {openChannel} = require('./../../');
|
|
15
|
+
const {parsePaymentRequest} = require('./../../');
|
|
15
16
|
const {pay} = require('./../../');
|
|
17
|
+
const {removePeer} = require('./../../');
|
|
16
18
|
const {setupChannel} = require('./../macros');
|
|
17
19
|
const {waitForChannel} = require('./../macros');
|
|
18
20
|
const {waitForPendingChannel} = require('./../macros');
|
|
19
21
|
|
|
20
22
|
const channelCapacityTokens = 1e6;
|
|
21
23
|
const confirmationCount = 6;
|
|
24
|
+
const count = 100;
|
|
22
25
|
const defaultFee = 1e3;
|
|
23
26
|
const defaultVout = 0;
|
|
27
|
+
const interval = 10;
|
|
24
28
|
const mtokPadding = '000';
|
|
25
29
|
const reserveRatio = 0.99;
|
|
30
|
+
const size = 3;
|
|
31
|
+
const times = 1000;
|
|
26
32
|
const tokens = 100;
|
|
27
33
|
const txIdHexLength = 32 * 2;
|
|
28
34
|
|
|
29
35
|
// Paying a private invoice should settle the invoice
|
|
30
36
|
test(`Pay private invoice`, async ({end, equal, strictSame}) => {
|
|
31
|
-
const
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
await
|
|
37
|
+
const {kill, nodes} = await spawnLightningCluster({size});
|
|
38
|
+
|
|
39
|
+
try {
|
|
40
|
+
const [{generate, lnd}, target, remote] = nodes;
|
|
41
|
+
|
|
42
|
+
await generate({count: 400});
|
|
43
|
+
|
|
44
|
+
const channel = await setupChannel({generate, lnd, to: target});
|
|
45
|
+
|
|
46
|
+
const remoteChannel = await setupChannel({
|
|
47
|
+
capacity: channelCapacityTokens,
|
|
48
|
+
generate: target.generate,
|
|
49
|
+
hidden: true,
|
|
50
|
+
lnd: target.lnd,
|
|
51
|
+
to: remote,
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
const invoice = await asyncRetry({interval, times}, async () => {
|
|
55
|
+
const invoice = await createInvoice({
|
|
56
|
+
tokens,
|
|
57
|
+
is_including_private_channels: true,
|
|
58
|
+
lnd: remote.lnd,
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
const {routes} = parsePaymentRequest({request: invoice.request});
|
|
62
|
+
|
|
63
|
+
// Wait for private routes to get picked up
|
|
64
|
+
if (!routes) {
|
|
65
|
+
await cancelHodlInvoice({id: invoice.id, lnd: remote.lnd});
|
|
66
|
+
|
|
67
|
+
throw new Error('ExpectedRouteForInvoice');
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
return invoice;
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
const {id} = invoice;
|
|
74
|
+
const {request} = invoice;
|
|
75
|
+
|
|
76
|
+
const decodedRequest = await decodePaymentRequest({lnd, request});
|
|
77
|
+
|
|
78
|
+
const route = await asyncRetry({interval: 10, times: 1000}, async () => {
|
|
79
|
+
const {route} = await getRouteToDestination({
|
|
80
|
+
lnd,
|
|
81
|
+
destination: decodedRequest.destination,
|
|
82
|
+
payment: invoice.payment,
|
|
83
|
+
routes: decodedRequest.routes,
|
|
84
|
+
tokens: invoice.tokens,
|
|
85
|
+
total_mtokens: !!invoice.payment ? invoice.mtokens : undefined,
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
if (!route) {
|
|
89
|
+
throw new Error('ExpectedRouteToDestination');
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
return route;
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
const payment = await pay({lnd, path: {id, routes: [route]}});
|
|
96
|
+
|
|
97
|
+
const paidInvoice = await getInvoice({id, lnd: remote.lnd});
|
|
98
|
+
|
|
99
|
+
equal(paidInvoice.secret, invoice.secret, 'Paying invoice got secret');
|
|
100
|
+
equal(paidInvoice.is_confirmed, true, 'Private invoice is paid');
|
|
101
|
+
} catch (err) {
|
|
102
|
+
equal(err, null, 'Expected no error paying invoice');
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
await kill({});
|
|
100
106
|
|
|
101
107
|
return end();
|
|
102
108
|
});
|
|
@@ -2,9 +2,9 @@ const asyncRetry = require('async/retry');
|
|
|
2
2
|
const {decodeChanId} = require('bolt07');
|
|
3
3
|
const {hopsFromChannels} = require('bolt07');
|
|
4
4
|
const {routeFromHops} = require('bolt07');
|
|
5
|
+
const {spawnLightningCluster} = require('ln-docker-daemons');
|
|
5
6
|
const {test} = require('@alexbosworth/tap');
|
|
6
7
|
|
|
7
|
-
const {createCluster} = require('./../macros');
|
|
8
8
|
const {createInvoice} = require('./../../');
|
|
9
9
|
const {delay} = require('./../macros');
|
|
10
10
|
const {getChannel} = require('./../../');
|
|
@@ -16,28 +16,30 @@ const {setupChannel} = require('./../macros');
|
|
|
16
16
|
|
|
17
17
|
const interval = retryCount => 50 * Math.pow(2, retryCount);
|
|
18
18
|
const mtok = '000';
|
|
19
|
+
const size = 2;
|
|
19
20
|
const times = 15;
|
|
20
21
|
const tokens = 1e3;
|
|
21
22
|
|
|
22
23
|
// Encountering errors in payment should return valid error codes
|
|
23
24
|
test('Payment errors', async ({end, equal}) => {
|
|
24
|
-
const
|
|
25
|
+
const {kill, nodes} = await spawnLightningCluster({size});
|
|
25
26
|
|
|
26
|
-
const
|
|
27
|
+
const [control, target] = nodes;
|
|
28
|
+
|
|
29
|
+
const {lnd} = control;
|
|
27
30
|
|
|
28
31
|
// Create a channel from the control to the target node
|
|
29
32
|
const controlToTargetChannel = await setupChannel({
|
|
30
33
|
lnd,
|
|
31
|
-
generate:
|
|
32
|
-
to:
|
|
34
|
+
generate: control.generate,
|
|
35
|
+
to: target,
|
|
33
36
|
});
|
|
34
37
|
|
|
35
38
|
// Create a channel from the target back to the control
|
|
36
39
|
const targetToControlChannel = await setupChannel({
|
|
37
|
-
generate:
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
to: cluster.control,
|
|
40
|
+
generate: target.generate,
|
|
41
|
+
lnd: target.lnd,
|
|
42
|
+
to: control,
|
|
41
43
|
});
|
|
42
44
|
|
|
43
45
|
const height = (await getHeight({lnd})).current_block_height;
|
|
@@ -49,7 +51,7 @@ test('Payment errors', async ({end, equal}) => {
|
|
|
49
51
|
|
|
50
52
|
const [inChanId, outChanId] = channels.map(({id}) => id).sort();
|
|
51
53
|
|
|
52
|
-
const destination =
|
|
54
|
+
const destination = control.id;
|
|
53
55
|
|
|
54
56
|
try {
|
|
55
57
|
let route;
|
|
@@ -93,7 +95,7 @@ test('Payment errors', async ({end, equal}) => {
|
|
|
93
95
|
}
|
|
94
96
|
}
|
|
95
97
|
|
|
96
|
-
await
|
|
98
|
+
await kill({});
|
|
97
99
|
|
|
98
100
|
return end();
|
|
99
101
|
});
|