ln-service 53.7.0 → 53.8.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 (41) hide show
  1. package/CHANGELOG.md +5 -1
  2. package/README.md +38 -2
  3. package/index.js +4 -2
  4. package/package.json +9 -6
  5. package/test/integration/test_add_peer.js +4 -2
  6. package/test/integration/test_delete_pending_channel.js +5 -2
  7. package/test/integration/test_get_closed_channels.js +0 -2
  8. package/test/integration/test_get_invoice.js +0 -1
  9. package/test/integration/test_get_node.js +13 -1
  10. package/test/integration/test_get_peers.js +32 -21
  11. package/test/integration/test_get_pending_force.js +1 -1
  12. package/test/integration/test_get_wallet_info.js +32 -26
  13. package/test/integration/test_open_channels.js +22 -15
  14. package/test/integration/test_pay.js +0 -1
  15. package/test/integration/test_pay_private_invoice.js +0 -1
  16. package/test/integration/test_propose_channel.js +438 -421
  17. package/test/integration/test_remove_peer.js +13 -9
  18. package/test/integration/test_send_message_to_peer.js +39 -28
  19. package/test/integration/test_send_to_chain_address.js +4 -0
  20. package/test/integration/test_subscribe_to_channels.js +0 -1
  21. package/test/integration/test_subscribe_to_invoices.js +80 -78
  22. package/test/integration/test_subscribe_to_peer_messages.js +6 -4
  23. package/test/integration/test_subscribe_to_peers.js +23 -19
  24. package/test/invoicesrpc-integration/test_get_sweep_transactions.js +0 -2
  25. package/test/invoicesrpc-integration/test_subscribe_cancel_invoice.js +0 -1
  26. package/test/macros/wait_for_channel.js +1 -1
  27. package/test/routerrpc-integration/test_delete_forwarding_reputations.js +61 -27
  28. package/test/routerrpc-integration/test_get_forwarding_reputations.js +42 -14
  29. package/test/routerrpc-integration/test_get_route_through_hops.js +33 -22
  30. package/test/routerrpc-integration/test_multipath_payment.js +0 -1
  31. package/test/routerrpc-integration/test_pay_via_payment_details.js +118 -111
  32. package/test/routerrpc-integration/test_pay_via_payment_request.js +92 -80
  33. package/test/routerrpc-integration/test_probe_for_route.js +78 -74
  34. package/test/routerrpc-integration/test_subscribe_to_forward_requests.js +0 -1
  35. package/test/routerrpc-integration/test_subscribe_to_forwards.js +518 -505
  36. package/test/routerrpc-integration/test_subscribe_to_past_payments.js +0 -3
  37. package/test/tower_clientrpc-integration/test_get_connected_watchtowers.js +0 -3
  38. package/test/walletrpc-integration/test_fund_psbt.js +113 -1
  39. package/test/walletrpc-integration/test_get_master_public_keys.js +79 -0
  40. package/test/walletrpc-integration/test_partially_sign_psbt.js +17 -5
  41. package/test/walletrpc-integration/test_sign_psbt.js +4 -1
@@ -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,26 +92,16 @@ 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);
95
+ const res = await asyncRetry({interval, times}, async () => {
96
+ return await getRouteThroughHops({
97
+ lnd,
98
+ messages,
99
+ cltv_delta: decodedRequest.cltv_delta + 6,
100
+ mtokens: (BigInt(invoice.tokens) * BigInt(1e3)).toString(),
101
+ payment: decodedRequest.payment,
102
+ public_keys: route.hops.map(n => n.public_key),
103
+ total_mtokens: invoice.mtokens,
79
104
  });
80
-
81
- if (!!limitedFeatures) {
82
- throw new Error('NetworkGraphSyncIncomplete');
83
- }
84
- });
85
-
86
- const res = await getRouteThroughHops({
87
- lnd,
88
- messages,
89
- cltv_delta: decodedRequest.cltv_delta + 6,
90
- mtokens: (BigInt(invoice.tokens) * BigInt(1e3)).toString(),
91
- payment: decodedRequest.payment,
92
- public_keys: route.hops.map(n => n.public_key),
93
- total_mtokens: invoice.mtokens,
94
105
  });
95
106
 
96
107
  await payViaRoutes({lnd, id: invoice.id, routes: [res.route]});
@@ -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');
@@ -25,140 +24,148 @@ test(`Pay`, async ({end, equal, rejects, strictSame}) => {
25
24
 
26
25
  const [{generate, lnd}, target, remote] = nodes;
27
26
 
28
- const channel = await setupChannel({lnd, generate, to: target});
29
-
30
- const remoteChan = await setupChannel({
31
- generate: target.generate,
32
- lnd: target.lnd,
33
- to: remote,
34
- });
35
-
36
- await addPeer({lnd, public_key: remote.id, socket: remote.socket});
37
-
38
- const height = (await getHeight({lnd})).current_block_height;
39
- const invoice = await createInvoice({tokens, lnd: remote.lnd});
40
-
41
- const {features} = await decodePaymentRequest({
42
- lnd,
43
- request: invoice.request,
44
- });
45
-
46
- const expectedHops = [
47
- {
48
- channel: channel.id,
49
- channel_capacity: 1000000,
50
- fee: 1,
51
- fee_mtokens: '1000',
52
- forward: invoice.tokens,
53
- forward_mtokens: (BigInt(invoice.tokens) * BigInt(1e3)).toString(),
54
- public_key: target.id,
55
- },
56
- {
57
- channel: remoteChan.id,
58
- channel_capacity: 1000000,
59
- fee: 0,
60
- fee_mtokens: '0',
61
- forward: invoice.tokens,
62
- forward_mtokens: '100000',
63
- public_key: remote.id,
64
- },
65
- ];
66
-
67
- await waitForRoute({lnd, destination: remote.id, tokens: invoice.tokens});
68
-
69
27
  try {
70
- const paid = await payViaPaymentDetails({
71
- features,
72
- lnd,
73
- destination: remote.id,
74
- payment: invoice.payment,
75
- tokens: invoice.tokens,
76
- });
77
- } catch (err) {
78
- strictSame(err, [503, 'PaymentRejectedByDestination']);
79
- }
28
+ const channel = await setupChannel({lnd, generate, to: target});
80
29
 
81
- try {
82
- const tooSoonCltv = await payViaPaymentDetails({
83
- features,
84
- lnd,
85
- destination: remote.id,
86
- id: invoice.id,
87
- max_timeout_height: height + 46,
88
- payment: invoice.payment,
89
- tokens: invoice.tokens,
30
+ const remoteChan = await setupChannel({
31
+ generate: target.generate,
32
+ lnd: target.lnd,
33
+ to: remote,
90
34
  });
91
35
 
92
- equal(tooSoonCltv, null, 'Should not be able to pay a too soon CLTV');
93
- } catch (err) {
94
- strictSame(err, [503, 'PaymentPathfindingFailedToFindPossibleRoute'], 'Fail');
95
- }
36
+ await addPeer({lnd, public_key: remote.id, socket: remote.socket});
96
37
 
97
- try {
98
- const paid = await payViaPaymentDetails({
99
- features,
38
+ const height = (await getHeight({lnd})).current_block_height;
39
+ const invoice = await createInvoice({tokens, lnd: remote.lnd});
40
+
41
+ const {features} = await decodePaymentRequest({
100
42
  lnd,
101
- destination: remote.id,
102
- id: invoice.id,
103
- max_timeout_height: height + 90,
104
- messages: [{type: tlvType, value: tlvData}],
105
- payment: invoice.payment,
106
- tokens: invoice.tokens,
43
+ request: invoice.request,
107
44
  });
108
45
 
109
- equal(paid.confirmed_at > start, true, 'Confirm date was received');
110
- equal(paid.fee, 1, 'Fee tokens paid');
111
- equal(paid.fee_mtokens, '1000', 'Fee mtokens tokens paid');
112
- equal(paid.id, invoice.id, 'Payment hash is equal on both sides');
113
- equal(paid.mtokens, '101000', 'Paid mtokens');
114
- equal(paid.secret, invoice.secret, 'Paid for invoice secret');
115
-
116
- paid.hops.forEach(n => {
117
- equal(n.timeout === height + 40 || n.timeout === height + 43, true);
118
-
119
- delete n.timeout;
46
+ const expectedHops = [
47
+ {
48
+ channel: channel.id,
49
+ channel_capacity: 1000000,
50
+ fee: 1,
51
+ fee_mtokens: '1000',
52
+ forward: invoice.tokens,
53
+ forward_mtokens: (BigInt(invoice.tokens) * BigInt(1e3)).toString(),
54
+ public_key: target.id,
55
+ },
56
+ {
57
+ channel: remoteChan.id,
58
+ channel_capacity: 1000000,
59
+ fee: 0,
60
+ fee_mtokens: '0',
61
+ forward: invoice.tokens,
62
+ forward_mtokens: '100000',
63
+ public_key: remote.id,
64
+ },
65
+ ];
66
+
67
+ await waitForRoute({lnd, destination: remote.id, tokens: invoice.tokens});
68
+
69
+ try {
70
+ const paid = await payViaPaymentDetails({
71
+ features,
72
+ lnd,
73
+ destination: remote.id,
74
+ payment: invoice.payment,
75
+ tokens: invoice.tokens,
76
+ });
77
+ } catch (err) {
78
+ strictSame(err, [503, 'PaymentRejectedByDestination']);
79
+ }
120
80
 
121
- return;
122
- });
81
+ try {
82
+ const tooSoonCltv = await payViaPaymentDetails({
83
+ features,
84
+ lnd,
85
+ destination: remote.id,
86
+ id: invoice.id,
87
+ max_timeout_height: height + 46,
88
+ payment: invoice.payment,
89
+ tokens: invoice.tokens,
90
+ });
91
+
92
+ equal(tooSoonCltv, null, 'Should not be able to pay a too soon CLTV');
93
+ } catch (err) {
94
+ strictSame(
95
+ err,
96
+ [503, 'PaymentPathfindingFailedToFindPossibleRoute'],
97
+ 'Fail'
98
+ );
99
+ }
123
100
 
124
- strictSame(paid.hops, expectedHops, 'Hops are returned');
125
- } catch (err) {
126
- equal(err, null, 'No error is thrown when payment is attempted');
127
- }
101
+ try {
102
+ const paid = await payViaPaymentDetails({
103
+ features,
104
+ lnd,
105
+ destination: remote.id,
106
+ id: invoice.id,
107
+ max_timeout_height: height + 90,
108
+ messages: [{type: tlvType, value: tlvData}],
109
+ payment: invoice.payment,
110
+ tokens: invoice.tokens,
111
+ });
112
+
113
+ equal(paid.confirmed_at > start, true, 'Confirm date was received');
114
+ equal(paid.fee, 1, 'Fee tokens paid');
115
+ equal(paid.fee_mtokens, '1000', 'Fee mtokens tokens paid');
116
+ equal(paid.id, invoice.id, 'Payment hash is equal on both sides');
117
+ equal(paid.mtokens, '101000', 'Paid mtokens');
118
+ equal(paid.secret, invoice.secret, 'Paid for invoice secret');
119
+
120
+ paid.hops.forEach(n => {
121
+ equal(n.timeout === height + 40 || n.timeout === height + 43, true);
122
+
123
+ delete n.timeout;
124
+
125
+ return;
126
+ });
127
+
128
+ strictSame(paid.hops, expectedHops, 'Hops are returned');
129
+ } catch (err) {
130
+ equal(err, null, 'No error is thrown when payment is attempted');
131
+ }
128
132
 
129
- {
130
- const {payments} = await getInvoice({id: invoice.id, lnd: remote.lnd});
133
+ {
134
+ const {payments} = await getInvoice({id: invoice.id, lnd: remote.lnd});
131
135
 
132
- if (!!payments) {
133
- const [payment] = payments;
136
+ if (!!payments) {
137
+ const [payment] = payments;
134
138
 
135
- if (!!payment && !!payment.messages.length) {
136
- const [message] = payment.messages;
139
+ if (!!payment && !!payment.messages.length) {
140
+ const [message] = payment.messages;
137
141
 
138
- equal(message.type, tlvType, 'Got TLV type');
139
- equal(message.value, tlvData, 'Got TLV value');
142
+ equal(message.type, tlvType, 'Got TLV type');
143
+ equal(message.value, tlvData, 'Got TLV value');
144
+ }
140
145
  }
141
146
  }
142
- }
143
147
 
144
- {
145
- const {invoices} = await getInvoices({lnd: remote.lnd});
148
+ {
149
+ const {invoices} = await getInvoices({lnd: remote.lnd});
146
150
 
147
- const [{payments}] = invoices;
151
+ const [{payments}] = invoices;
148
152
 
149
- if (!!payments.length) {
150
- const [payment] = payments;
153
+ if (!!payments.length) {
154
+ const [payment] = payments;
151
155
 
152
- if (!!payment && !!payment.messages.length) {
153
- const [message] = payment.messages;
156
+ if (!!payment && !!payment.messages.length) {
157
+ const [message] = payment.messages;
154
158
 
155
- equal(message.type, tlvType, 'Got TLV type');
156
- equal(message.value, tlvData, 'Got TLV value');
159
+ equal(message.type, tlvType, 'Got TLV type');
160
+ equal(message.value, tlvData, 'Got TLV value');
161
+ }
157
162
  }
158
163
  }
164
+ } catch (err) {
165
+ equal(err, null, 'Expected no error');
166
+ } finally {
167
+ await kill({});
159
168
  }
160
169
 
161
- await kill({});
162
-
163
170
  return end();
164
171
  });
@@ -22,99 +22,111 @@ test(`Pay via payment request`, async ({end, equal, rejects, strictSame}) => {
22
22
 
23
23
  const [{generate, lnd}, target, remote] = nodes;
24
24
 
25
- const channel = await setupChannel({generate, lnd, to: target});
26
-
27
- // Make sure that an error is returned when there is no route
28
25
  try {
29
- const {request} = await createInvoice({tokens, lnd: remote.lnd});
26
+ await generate({count: 100});
30
27
 
31
- await rejects(
32
- payViaPaymentRequest({lnd, request}),
33
- [503, 'PaymentPathfindingFailedToFindPossibleRoute'],
34
- 'A payment with no route returns an error'
35
- );
36
- } catch (err) {
37
- equal(err, null, 'Expected no error creating invoice');
38
- }
28
+ const channel = await setupChannel({generate, lnd, to: target});
39
29
 
40
- const remoteChan = await setupChannel({
41
- lnd: target.lnd,
42
- generate: target.generate,
43
- to: remote,
44
- });
30
+ // Make sure that an error is returned when there is no route
31
+ try {
32
+ const {request} = await createInvoice({tokens, lnd: remote.lnd});
45
33
 
46
- await addPeer({lnd, public_key: remote.id, socket: remote.socket});
47
-
48
- await waitForRoute({lnd, tokens, destination: remote.id});
34
+ await rejects(
35
+ payViaPaymentRequest({lnd, request}),
36
+ [503, 'PaymentPathfindingFailedToFindPossibleRoute'],
37
+ 'A payment with no route returns an error'
38
+ );
39
+ } catch (err) {
40
+ equal(err, null, 'Expected no error creating invoice');
41
+ }
49
42
 
50
- // When a route exists, payment is successful
51
- try {
52
- const commitTxFee = channel.commit_transaction_fee;
53
- const height = (await getWalletInfo({lnd})).current_block_height;
54
- const invoice = await createInvoice({tokens, lnd: remote.lnd});
55
-
56
- const paid = await payViaPaymentRequest({
57
- lnd,
58
- max_timeout_height: height + 40 + 43,
59
- messages: [{type: tlvType, value: tlvValue}],
60
- request: invoice.request,
43
+ await addPeer({
44
+ lnd: target.lnd,
45
+ public_key: remote.id,
46
+ socket: remote.socket,
61
47
  });
62
48
 
63
- equal(paid.confirmed_at > start, true, 'Got confirmation date');
64
- equal(paid.fee, 1, 'Fee tokens paid');
65
- equal(paid.fee_mtokens, '1000', 'Fee mtokens tokens paid');
66
- equal(paid.id, invoice.id, 'Payment hash is equal on both sides');
67
- equal(paid.mtokens, '101000', 'Paid mtokens');
68
- equal(paid.secret, invoice.secret, 'Paid for invoice secret');
69
-
70
- paid.hops.forEach(n => {
71
- equal(n.timeout === height + 40 || n.timeout === height + 43, true);
72
-
73
- delete n.timeout;
74
-
75
- return;
49
+ const remoteChan = await setupChannel({
50
+ lnd: target.lnd,
51
+ generate: target.generate,
52
+ to: remote,
76
53
  });
77
54
 
78
- const expectedHops = [
79
- {
80
- channel: channel.id,
81
- channel_capacity: 1000000,
82
- fee: 1,
83
- fee_mtokens: '1000',
84
- forward: 100,
85
- forward_mtokens: invoice.mtokens,
86
- public_key: target.id,
87
- },
88
- {
89
- channel: remoteChan.id,
90
- channel_capacity: 1000000,
91
- fee: 0,
92
- fee_mtokens: '0',
93
- forward: 100,
94
- forward_mtokens: '100000',
95
- public_key: remote.id,
96
- },
97
- ];
98
-
99
- strictSame(paid.hops, expectedHops, 'Hops are returned');
100
-
101
- const {payments} = await getInvoice({id: paid.id, lnd: remote.lnd});
102
-
103
- if (!!payments.length) {
104
- const [payment] = payments;
105
-
106
- if (!!payment.messages.length) {
107
- const [message] = payment.messages;
108
-
109
- equal(message.type, tlvType, 'Got TLV message type');
110
- equal(message.value, tlvValue, 'Got TLV message value');
55
+ await addPeer({lnd, public_key: remote.id, socket: remote.socket});
56
+
57
+ await waitForRoute({lnd, tokens, destination: remote.id});
58
+
59
+ // When a route exists, payment is successful
60
+ try {
61
+ const commitTxFee = channel.commit_transaction_fee;
62
+ const height = (await getWalletInfo({lnd})).current_block_height;
63
+ const invoice = await createInvoice({tokens, lnd: remote.lnd});
64
+
65
+ const paid = await payViaPaymentRequest({
66
+ lnd,
67
+ max_timeout_height: height + 40 + 43,
68
+ messages: [{type: tlvType, value: tlvValue}],
69
+ request: invoice.request,
70
+ });
71
+
72
+ equal(paid.confirmed_at > start, true, 'Got confirmation date');
73
+ equal(paid.fee, 1, 'Fee tokens paid');
74
+ equal(paid.fee_mtokens, '1000', 'Fee mtokens tokens paid');
75
+ equal(paid.id, invoice.id, 'Payment hash is equal on both sides');
76
+ equal(paid.mtokens, '101000', 'Paid mtokens');
77
+ equal(paid.secret, invoice.secret, 'Paid for invoice secret');
78
+
79
+ paid.hops.forEach(n => {
80
+ equal(n.timeout === height + 40 || n.timeout === height + 43, true);
81
+
82
+ delete n.timeout;
83
+
84
+ return;
85
+ });
86
+
87
+ const expectedHops = [
88
+ {
89
+ channel: channel.id,
90
+ channel_capacity: 1000000,
91
+ fee: 1,
92
+ fee_mtokens: '1000',
93
+ forward: 100,
94
+ forward_mtokens: invoice.mtokens,
95
+ public_key: target.id,
96
+ },
97
+ {
98
+ channel: remoteChan.id,
99
+ channel_capacity: 1000000,
100
+ fee: 0,
101
+ fee_mtokens: '0',
102
+ forward: 100,
103
+ forward_mtokens: '100000',
104
+ public_key: remote.id,
105
+ },
106
+ ];
107
+
108
+ strictSame(paid.hops, expectedHops, 'Hops are returned');
109
+
110
+ const {payments} = await getInvoice({id: paid.id, lnd: remote.lnd});
111
+
112
+ if (!!payments.length) {
113
+ const [payment] = payments;
114
+
115
+ if (!!payment.messages.length) {
116
+ const [message] = payment.messages;
117
+
118
+ equal(message.type, tlvType, 'Got TLV message type');
119
+ equal(message.value, tlvValue, 'Got TLV message value');
120
+ }
111
121
  }
122
+ } catch (err) {
123
+ equal(err, null, 'Expected no error paying payment request');
112
124
  }
113
125
  } catch (err) {
114
- equal(err, null, 'Expected no error paying payment request');
126
+ equal(err, 'Expected no errors');
127
+ } finally {
128
+ await kill({});
115
129
  }
116
130
 
117
- await kill({});
118
-
119
131
  return end();
120
132
  });