ln-service 53.7.2 → 53.9.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.
Files changed (37) hide show
  1. package/CHANGELOG.md +9 -1
  2. package/README.md +129 -0
  3. package/index.js +4 -0
  4. package/package.json +7 -5
  5. package/test/integration/test_add_peer.js +2 -2
  6. package/test/integration/test_get_closed_channels.js +0 -2
  7. package/test/integration/test_get_invoice.js +0 -1
  8. package/test/integration/test_get_node.js +13 -1
  9. package/test/integration/test_get_peers.js +32 -21
  10. package/test/integration/test_get_pending_payments.js +87 -0
  11. package/test/integration/test_get_wallet_info.js +6 -4
  12. package/test/integration/test_open_channels.js +2 -2
  13. package/test/integration/test_pay.js +0 -1
  14. package/test/integration/test_pay_private_invoice.js +0 -1
  15. package/test/integration/test_remove_peer.js +13 -9
  16. package/test/integration/test_send_message_to_peer.js +39 -28
  17. package/test/integration/test_send_to_chain_address.js +4 -0
  18. package/test/integration/test_subscribe_to_channels.js +0 -1
  19. package/test/integration/test_subscribe_to_invoices.js +80 -78
  20. package/test/integration/test_subscribe_to_peer_messages.js +6 -4
  21. package/test/invoicesrpc-integration/test_get_sweep_transactions.js +0 -2
  22. package/test/invoicesrpc-integration/test_subscribe_cancel_invoice.js +0 -1
  23. package/test/macros/wait_for_channel.js +1 -1
  24. package/test/routerrpc-integration/test_delete_forwarding_reputations.js +61 -27
  25. package/test/routerrpc-integration/test_get_forwarding_reputations.js +42 -14
  26. package/test/routerrpc-integration/test_get_route_through_hops.js +24 -15
  27. package/test/routerrpc-integration/test_multipath_payment.js +0 -1
  28. package/test/routerrpc-integration/test_pay_via_payment_details.js +0 -1
  29. package/test/routerrpc-integration/test_pay_via_payment_request.js +92 -80
  30. package/test/routerrpc-integration/test_probe_for_route.js +5 -5
  31. package/test/routerrpc-integration/test_subscribe_to_forward_requests.js +0 -1
  32. package/test/routerrpc-integration/test_subscribe_to_forwards.js +11 -2
  33. package/test/routerrpc-integration/test_subscribe_to_past_payments.js +0 -3
  34. package/test/tower_clientrpc-integration/test_get_connected_watchtowers.js +0 -3
  35. package/test/walletrpc-integration/test_fund_psbt.js +110 -1
  36. package/test/walletrpc-integration/test_get_master_public_keys.js +79 -0
  37. package/test/walletrpc-integration/test_partially_sign_psbt.js +5 -0
@@ -4,13 +4,9 @@ const {routeFromHops} = require('bolt07');
4
4
  const {spawnLightningCluster} = require('ln-docker-daemons');
5
5
  const {test} = require('@alexbosworth/tap');
6
6
 
7
- const {cancelHodlInvoice} = require('./../../');
8
7
  const {createInvoice} = require('./../../');
9
8
  const {getChannel} = require('./../../');
10
- const {getChannels} = require('./../../');
11
- const {getHeight} = require('./../../');
12
9
  const {pay} = require('./../../');
13
- const {payViaRoutes} = require('./../../');
14
10
  const {setupChannel} = require('./../macros');
15
11
  const {subscribeToInvoices} = require('./../../');
16
12
 
@@ -37,107 +33,113 @@ test('Subscribe to invoices', async ({end, equal, fail}) => {
37
33
 
38
34
  const destination = control.id;
39
35
 
40
- // Create a channel from the control to the target node
41
- const controlToTargetChannel = await setupChannel({
42
- generate,
43
- lnd,
44
- give: 1e5,
45
- to: target,
46
- });
36
+ try {
37
+ await generate({count: 100});
47
38
 
48
- // Create a channel from the target back to the control
49
- const targetToControlChannel = await setupChannel({
50
- lnd: target.lnd,
51
- generate: target.generate,
52
- give: 1e5,
53
- to: control,
54
- });
55
-
56
- // Created invoices are emitted
57
- {
58
- const sub = subscribeToInvoices({lnd, restart_delay_ms: 1});
39
+ // Create a channel from the control to the target node
40
+ const controlToTargetChannel = await setupChannel({
41
+ generate,
42
+ lnd,
43
+ give: 1e5,
44
+ to: target,
45
+ });
59
46
 
60
- const updates = [];
47
+ // Create a channel from the target back to the control
48
+ const targetToControlChannel = await setupChannel({
49
+ lnd: target.lnd,
50
+ generate: target.generate,
51
+ give: 1e5,
52
+ to: control,
53
+ });
61
54
 
62
- sub.on('invoice_updated', updated => updates.push(updated));
55
+ // Created invoices are emitted
56
+ {
57
+ const sub = subscribeToInvoices({lnd, restart_delay_ms: 1});
63
58
 
64
- const update = await asyncRetry({interval, times}, async () => {
65
- await createInvoice({lnd});
59
+ const updates = [];
66
60
 
67
- const [update] = updates;
61
+ sub.on('invoice_updated', updated => updates.push(updated));
68
62
 
69
- if (!update) {
70
- throw new Error('ExpectedInvoiceUpdate');
71
- }
63
+ const update = await asyncRetry({interval, times}, async () => {
64
+ await createInvoice({lnd});
72
65
 
73
- return update;
74
- });
66
+ const [update] = updates;
75
67
 
76
- equal(update.tokens, 0, 'Invoiced zero');
68
+ if (!update) {
69
+ throw new Error('ExpectedInvoiceUpdate');
70
+ }
77
71
 
78
- sub.removeAllListeners();
79
- }
72
+ return update;
73
+ });
80
74
 
81
- // Paid invoices are emitted
82
- {
83
- const sub = subscribeToInvoices({lnd, restart_delay_ms: 1});
75
+ equal(update.tokens, 0, 'Invoiced zero');
84
76
 
85
- const updates = [];
77
+ sub.removeAllListeners();
78
+ }
86
79
 
87
- sub.on('invoice_updated', updated => updates.push(updated));
80
+ // Paid invoices are emitted
81
+ {
82
+ const sub = subscribeToInvoices({lnd, restart_delay_ms: 1});
88
83
 
89
- const update = await asyncRetry({interval, times}, async () => {
90
- await pay({
91
- lnd: target.lnd,
92
- request: (await createInvoice({lnd, tokens})).request,
93
- });
84
+ const updates = [];
94
85
 
95
- const [update] = updates.filter(n => n.is_confirmed);
86
+ sub.on('invoice_updated', updated => updates.push(updated));
96
87
 
97
- if (!update) {
98
- throw new Error('ExpectedPaidInvoiceUpdate');
99
- }
88
+ const update = await asyncRetry({interval, times}, async () => {
89
+ await pay({
90
+ lnd: target.lnd,
91
+ request: (await createInvoice({lnd, tokens})).request,
92
+ });
100
93
 
101
- return update;
102
- });
94
+ const [update] = updates.filter(n => n.is_confirmed);
103
95
 
104
- equal(!!update.confirmed_at, true, 'Got receive date');
105
- equal(!!update.confirmed_index, true, 'Got confirm index');
106
- equal(update.payments.length, 1, 'Got received HTLC');
107
- equal(update.received, tokens, 'Got received tokens');
108
- equal(update.received_mtokens, '10000000', 'Got invoice mtokens');
96
+ if (!update) {
97
+ throw new Error('ExpectedPaidInvoiceUpdate');
98
+ }
109
99
 
110
- sub.removeAllListeners();
111
- }
100
+ return update;
101
+ });
112
102
 
113
- // Old invoices are emitted
114
- {
115
- const sub = subscribeToInvoices({
116
- lnd,
117
- added_after: 1,
118
- restart_delay_ms: 1,
119
- });
103
+ equal(!!update.confirmed_at, true, 'Got receive date');
104
+ equal(!!update.confirmed_index, true, 'Got confirm index');
105
+ equal(update.payments.length, 1, 'Got received HTLC');
106
+ equal(update.received, tokens, 'Got received tokens');
107
+ equal(update.received_mtokens, '10000000', 'Got invoice mtokens');
108
+
109
+ sub.removeAllListeners();
110
+ }
111
+
112
+ // Old invoices are emitted
113
+ {
114
+ const sub = subscribeToInvoices({
115
+ lnd,
116
+ added_after: 1,
117
+ restart_delay_ms: 1,
118
+ });
120
119
 
121
- const updates = [];
120
+ const updates = [];
122
121
 
123
- sub.on('invoice_updated', updated => updates.push(updated));
122
+ sub.on('invoice_updated', updated => updates.push(updated));
124
123
 
125
- const update = await asyncRetry({interval, times}, async () => {
126
- const [update] = updates;
124
+ const update = await asyncRetry({interval, times}, async () => {
125
+ const [update] = updates;
127
126
 
128
- if (!update) {
129
- throw new Error('ExpectedPastInvoiceUpdate');
130
- }
127
+ if (!update) {
128
+ throw new Error('ExpectedPastInvoiceUpdate');
129
+ }
131
130
 
132
- return update;
133
- });
131
+ return update;
132
+ });
134
133
 
135
- equal(update.index, 2, 'Got past update');
134
+ equal(update.index, 2, 'Got past update');
136
135
 
137
- sub.removeAllListeners();
136
+ sub.removeAllListeners();
137
+ }
138
+ } catch (err) {
139
+ equal(err, null, 'Expected no error');
140
+ } finally {
141
+ await kill({});
138
142
  }
139
143
 
140
- await kill({});
141
-
142
144
  return end();
143
145
  });
@@ -17,10 +17,12 @@ test(`Subscribe to peer messages`, async ({end, equal, strictSame}) => {
17
17
  const [{lnd}, target, remote] = nodes;
18
18
 
19
19
  try {
20
- await addPeer({
21
- lnd,
22
- public_key: target.id,
23
- socket: target.socket,
20
+ await asyncRetry({interval, times}, async () => {
21
+ await addPeer({
22
+ lnd,
23
+ public_key: target.id,
24
+ socket: target.socket,
25
+ });
24
26
  });
25
27
 
26
28
  await addPeer({
@@ -10,10 +10,8 @@ const {closeChannel} = require('./../../');
10
10
  const {createHodlInvoice} = require('./../../');
11
11
  const {delay} = require('./../macros');
12
12
  const {getChainTransactions} = require('./../../');
13
- const {getChannels} = require('./../../');
14
13
  const {getClosedChannels} = require('./../../');
15
14
  const {getInvoice} = require('./../../');
16
- const {getInvoices} = require('./../../');
17
15
  const {getPendingChannels} = require('./../../');
18
16
  const {getSweepTransactions} = require('./../../');
19
17
  const {getWalletInfo} = require('./../../');
@@ -8,7 +8,6 @@ const {cancelHodlInvoice} = require('./../../');
8
8
  const {createHodlInvoice} = require('./../../');
9
9
  const {delay} = require('./../macros');
10
10
  const {getInvoice} = require('./../../');
11
- const {getInvoices} = require('./../../');
12
11
  const {pay} = require('./../../');
13
12
  const {setupChannel} = require('./../macros');
14
13
  const {subscribeToInvoice} = require('./../../');
@@ -6,7 +6,7 @@ const {getChannel} = require('./../../');
6
6
  const {getChannels} = require('./../../');
7
7
 
8
8
  const interval = 10;
9
- const times = 6000;
9
+ const times = 10000;
10
10
 
11
11
  /** Wait for channel to be open
12
12
 
@@ -1,3 +1,4 @@
1
+ const asyncRetry = require('async/retry');
1
2
  const {spawnLightningCluster} = require('ln-docker-daemons');
2
3
  const {test} = require('@alexbosworth/tap');
3
4
 
@@ -5,12 +6,17 @@ const {addPeer} = require('./../../');
5
6
  const {createInvoice} = require('./../../');
6
7
  const {deleteForwardingReputations} = require('./../../');
7
8
  const {getForwardingReputations} = require('./../../');
9
+ const {getNetworkGraph} = require('./../../');
8
10
  const {payViaPaymentRequest} = require('./../../');
9
11
  const {probeForRoute} = require('./../../');
10
12
  const {setupChannel} = require('./../macros');
11
13
  const {waitForRoute} = require('./../macros');
12
14
 
15
+ const flatten = arr => [].concat(...arr);
16
+ const interval = 10;
13
17
  const size = 3;
18
+ const times = 1000;
19
+ const tlvOnionBit = 14;
14
20
  const tokens = 1e6 / 2;
15
21
 
16
22
  // Deleting forwarding reputations should eliminate forwarding reputations
@@ -19,45 +25,73 @@ test('Delete forwarding reputations', async ({end, equal}) => {
19
25
 
20
26
  const [{generate, lnd}, target, remote] = nodes;
21
27
 
22
- const controlToTargetChan = await setupChannel({generate, lnd, to: target});
28
+ try {
29
+ const controlToTargetChan = await setupChannel({
30
+ generate,
31
+ lnd,
32
+ to: target,
33
+ });
23
34
 
24
- const targetToRemoteChan = await setupChannel({
25
- generate: target.generate,
26
- lnd: target.lnd,
27
- to: remote,
28
- });
35
+ const targetToRemoteChan = await setupChannel({
36
+ generate: target.generate,
37
+ lnd: target.lnd,
38
+ to: remote,
39
+ });
29
40
 
30
- await addPeer({lnd, public_key: remote.id, socket: remote.socket});
41
+ await addPeer({lnd, public_key: remote.id, socket: remote.socket});
31
42
 
32
- const {id, request} = await createInvoice({tokens, lnd: remote.lnd});
43
+ const {id, request} = await createInvoice({tokens, lnd: remote.lnd});
33
44
 
34
- await waitForRoute({lnd, tokens, destination: remote.id});
45
+ await asyncRetry({interval, times}, async () => {
46
+ const {channels, nodes} = await getNetworkGraph({lnd});
35
47
 
36
- try {
37
- await payViaPaymentRequest({lnd, request});
38
- } catch (err) {
39
- equal(err, null, 'Expected no error paying payment request');
40
- }
48
+ const limitedFeatures = nodes.find(node => {
49
+ return !node.features.find(n => n.bit === tlvOnionBit);
50
+ });
41
51
 
42
- try {
43
- await probeForRoute({lnd, tokens, destination: remote.id});
44
- } catch (err) {}
52
+ const policies = flatten(channels.map(n => n.policies));
45
53
 
46
- {
47
- const {nodes} = await getForwardingReputations({lnd});
54
+ const cltvDeltas = policies.map(n => n.cltv_delta);
48
55
 
49
- equal(nodes.length, 2, 'Reputations should exist');
50
- }
56
+ if (!!cltvDeltas.filter(n => !n).length) {
57
+ throw new Error('ExpectedAllChannelPolicies');
58
+ }
51
59
 
52
- await deleteForwardingReputations({lnd});
60
+ if (!!limitedFeatures) {
61
+ throw new Error('NetworkGraphSyncIncomplete');
62
+ }
63
+ });
53
64
 
54
- {
55
- const {nodes} = await getForwardingReputations({lnd});
65
+ await waitForRoute({lnd, tokens, destination: remote.id});
56
66
 
57
- equal(nodes.length, [].length, 'Reputations should be wiped');
58
- }
67
+ try {
68
+ await payViaPaymentRequest({lnd, request});
69
+ } catch (err) {
70
+ equal(err, null, 'Expected no error paying payment request');
71
+ }
59
72
 
60
- await kill({});
73
+ try {
74
+ await probeForRoute({lnd, tokens, destination: remote.id});
75
+ } catch (err) {}
76
+
77
+ {
78
+ const {nodes} = await getForwardingReputations({lnd});
79
+
80
+ equal(nodes.length, 2, 'Reputations should exist');
81
+ }
82
+
83
+ await deleteForwardingReputations({lnd});
84
+
85
+ {
86
+ const {nodes} = await getForwardingReputations({lnd});
87
+
88
+ equal(nodes.length, [].length, 'Reputations should be wiped');
89
+ }
90
+ } catch (err) {
91
+ equal(err, null, 'Expected no error');
92
+ } finally {
93
+ await kill({});
94
+ }
61
95
 
62
96
  return end();
63
97
  });
@@ -5,7 +5,7 @@ const {test} = require('@alexbosworth/tap');
5
5
  const {addPeer} = require('./../../');
6
6
  const {getChannels} = require('./../../');
7
7
  const {getForwardingReputations} = require('./../../');
8
- const {payViaRoutes} = require('./../../');
8
+ const {getNetworkGraph} = require('./../../');
9
9
  const {probeForRoute} = require('./../../');
10
10
  const {setupChannel} = require('./../macros');
11
11
  const {waitForRoute} = require('./../macros');
@@ -15,9 +15,12 @@ const channelCapacityTokens = 1e6;
15
15
  const confirmationCount = 20;
16
16
  const defaultFee = 1e3;
17
17
  const defaultOdds = 950000;
18
+ const flatten = arr => [].concat(...arr);
18
19
  const interval = 10;
20
+ const maturity = 100;
19
21
  const size = 3;
20
22
  const times = 2000;
23
+ const tlvOnionBit = 14;
21
24
  const tokens = 1e6 / 2;
22
25
 
23
26
  // Getting forwarding reputations should return reputations
@@ -26,9 +29,9 @@ test('Get forwarding reputations', async ({end, equal}) => {
26
29
 
27
30
  const [{generate, id, lnd}, target, remote] = cluster.nodes;
28
31
 
29
- await generate({count: 100});
30
-
31
32
  try {
33
+ await generate({count: maturity});
34
+
32
35
  // Create a channel from the control to the target node
33
36
  await setupChannel({
34
37
  generate,
@@ -45,22 +48,47 @@ test('Get forwarding reputations', async ({end, equal}) => {
45
48
  });
46
49
 
47
50
  await asyncRetry({interval, times}, async () => {
48
- await addPeer({lnd, public_key: remote.id, socket: remote.socket});
51
+ const {channels, nodes} = await getNetworkGraph({lnd});
52
+
53
+ const limitedFeatures = nodes.find(node => {
54
+ return !node.features.find(n => n.bit === tlvOnionBit);
55
+ });
56
+
57
+ const policies = flatten(channels.map(n => n.policies));
58
+
59
+ const cltvDeltas = policies.map(n => n.cltv_delta);
60
+
61
+ if (!!cltvDeltas.filter(n => !n).length) {
62
+ throw new Error('ExpectedAllChannelPolicies');
63
+ }
64
+
65
+ if (!!limitedFeatures) {
66
+ throw new Error('NetworkGraphSyncIncomplete');
67
+ }
68
+ });
69
+
70
+ await asyncRetry({interval, times}, async () => {
71
+ await generate({});
72
+
73
+ await addPeer({
74
+ lnd,
75
+ public_key: remote.id,
76
+ socket: remote.socket,
77
+ retry_count: 1,
78
+ retry_delay: 1,
79
+ timeout: 1,
80
+ });
49
81
 
50
82
  const {channels} = await getChannels({lnd: remote.lnd});
51
83
 
52
84
  await waitForRoute({lnd, tokens, destination: remote.id});
53
85
 
54
- try {
55
- const res = await probeForRoute({
56
- lnd,
57
- tokens,
58
- destination: remote.id,
59
- is_ignoring_past_failures: true,
60
- });
61
- } catch (err) {
62
- equal(err, null, 'Expected no error probing');
63
- }
86
+ await probeForRoute({
87
+ lnd,
88
+ tokens,
89
+ destination: remote.id,
90
+ is_ignoring_past_failures: true,
91
+ });
64
92
 
65
93
  const {nodes} = await getForwardingReputations({lnd});
66
94
 
@@ -12,16 +12,18 @@ const {getNetworkGraph} = require('./../../');
12
12
  const {getRouteThroughHops} = require('./../../');
13
13
  const {getRouteToDestination} = require('./../../');
14
14
  const {getWalletInfo} = require('./../../');
15
- const {getWalletVersion} = require('./../../');
16
15
  const {payViaRoutes} = require('./../../');
17
16
  const {setupChannel} = require('./../macros');
18
17
  const {waitForRoute} = require('./../macros');
19
18
 
20
19
  const confirmationCount = 6;
20
+ const flatten = arr => [].concat(...arr);
21
21
  const interval = 10;
22
+ const maturity = 100;
22
23
  const messages = [{type: '1000000', value: '01'}];
23
24
  const size = 3;
24
25
  const times = 1000;
26
+ const tlvOnionBit = 14;
25
27
  const tokens = 100;
26
28
 
27
29
  // Getting a route through hops should result in a route through specified hops
@@ -30,8 +32,7 @@ test(`Get route through hops`, async ({end, equal, strictSame}) => {
30
32
 
31
33
  const [{generate, lnd}, target, remote] = nodes;
32
34
 
33
- await target.generate({count: 100});
34
- await remote.generate({count: 100});
35
+ await target.generate({count: maturity});
35
36
 
36
37
  const controlToTargetChan = await setupChannel({generate, lnd, to: target});
37
38
 
@@ -53,6 +54,26 @@ test(`Get route through hops`, async ({end, equal, strictSame}) => {
53
54
  }
54
55
  });
55
56
 
57
+ await asyncRetry({interval, times}, async () => {
58
+ const {channels, nodes} = await getNetworkGraph({lnd});
59
+
60
+ const limitedFeatures = nodes.find(node => {
61
+ return !node.features.find(n => n.bit === tlvOnionBit);
62
+ });
63
+
64
+ const policies = flatten(channels.map(n => n.policies));
65
+
66
+ const cltvDeltas = policies.map(n => n.cltv_delta);
67
+
68
+ if (!!cltvDeltas.filter(n => !n).length) {
69
+ throw new Error('ExpectedAllChannelPolicies');
70
+ }
71
+
72
+ if (!!limitedFeatures) {
73
+ throw new Error('NetworkGraphSyncIncomplete');
74
+ }
75
+ });
76
+
56
77
  const invoice = await createInvoice({tokens, lnd: remote.lnd});
57
78
 
58
79
  const {id} = invoice;
@@ -71,18 +92,6 @@ test(`Get route through hops`, async ({end, equal, strictSame}) => {
71
92
  });
72
93
  });
73
94
 
74
- await asyncRetry({interval, times}, async () => {
75
- const {nodes} = await getNetworkGraph({lnd});
76
-
77
- const limitedFeatures = nodes.find(node => {
78
- return !node.features.find(n => n.bit === 14);
79
- });
80
-
81
- if (!!limitedFeatures) {
82
- throw new Error('NetworkGraphSyncIncomplete');
83
- }
84
- });
85
-
86
95
  const res = await asyncRetry({interval, times}, async () => {
87
96
  return await getRouteThroughHops({
88
97
  lnd,
@@ -4,7 +4,6 @@ const {test} = require('@alexbosworth/tap');
4
4
  const {createInvoice} = require('./../../');
5
5
  const {getInvoice} = require('./../../');
6
6
  const {getRouteToDestination} = require('./../../');
7
- const {getWalletVersion} = require('./../../');
8
7
  const {parsePaymentRequest} = require('./../../');
9
8
  const {payViaPaymentRequest} = require('./../../');
10
9
  const {payViaRoutes} = require('./../../');
@@ -8,7 +8,6 @@ const {delay} = require('./../macros');
8
8
  const {getHeight} = require('./../../');
9
9
  const {getInvoice} = require('./../../');
10
10
  const {getInvoices} = require('./../../');
11
- const {getWalletVersion} = require('./../../');
12
11
  const {payViaPaymentDetails} = require('./../../');
13
12
  const {setupChannel} = require('./../macros');
14
13
  const {waitForRoute} = require('./../macros');