ln-service 57.23.1 → 57.24.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 CHANGED
@@ -1,5 +1,9 @@
1
1
  # Versions
2
2
 
3
+ ## 57.24.0
4
+
5
+ - `closeChannel`: Add `is_graceful_close` option to wait for pending resolution
6
+
3
7
  ## 57.23.1
4
8
 
5
9
  - Add support for LND 0.18.5
package/README.md CHANGED
@@ -613,10 +613,13 @@ permissions
613
613
 
614
614
  `max_tokens_per_vbyte` is not supported in LND 0.15.0 and below
615
615
 
616
+ `is_graceful_close` is not supported in LND 0.17.5 and below
617
+
616
618
  {
617
619
  [address]: <Request Sending Local Channel Funds To Address String>
618
620
  [id]: <Standard Format Channel Id String>
619
621
  [is_force_close]: <Is Force Close Bool>
622
+ [is_graceful_close]: <Is Waiting For Pending Payments to Coop Close Bool>
620
623
  lnd: <Authenticated LND API Object>
621
624
  [max_tokens_per_vbyte]: <Fail Cooperative Close Above Fee Rate Number>
622
625
  [public_key]: <Peer Public Key String>
package/package.json CHANGED
@@ -9,7 +9,7 @@
9
9
  "dependencies": {
10
10
  "bolt07": "1.9.4",
11
11
  "invoices": "3.0.0",
12
- "lightning": "10.23.1",
12
+ "lightning": "10.24.0",
13
13
  "macaroon": "3.0.4"
14
14
  },
15
15
  "description": "Interaction helper for your Lightning Network daemon",
@@ -24,13 +24,13 @@
24
24
  "bn.js": "5.2.1",
25
25
  "bs58check": "4.0.0",
26
26
  "ecpair": "2.1.0",
27
- "ln-docker-daemons": "6.0.23",
27
+ "ln-docker-daemons": "6.0.24",
28
28
  "p2tr": "2.0.0",
29
- "portfinder": "1.0.32",
29
+ "portfinder": "1.0.34",
30
30
  "psbt": "3.0.0",
31
31
  "rimraf": "6.0.1",
32
32
  "tiny-secp256k1": "2.2.3",
33
- "uuid": "11.0.5",
33
+ "uuid": "11.1.0",
34
34
  "varuint-bitcoin": "2.0.0"
35
35
  },
36
36
  "engines": {
@@ -51,6 +51,9 @@
51
51
  "url": "https://github.com/alexbosworth/ln-service.git"
52
52
  },
53
53
  "scripts": {
54
+ "integration-test-0.18.5": "DOCKER_LND_VERSION=v0.18.5-beta npm run test",
55
+ "integration-test-0.18.4": "DOCKER_LND_VERSION=v0.18.4-beta npm run test",
56
+ "integration-test-0.18.3": "DOCKER_LND_VERSION=v0.18.3-beta npm run test",
54
57
  "integration-test-0.18.2": "DOCKER_LND_VERSION=v0.18.2-beta npm run test",
55
58
  "integration-test-0.18.1": "DOCKER_LND_VERSION=v0.18.1-beta npm run test",
56
59
  "integration-test-0.18.0": "DOCKER_LND_VERSION=v0.18.0-beta npm run test",
@@ -73,5 +76,5 @@
73
76
  "integration-test-0.14.4": "DOCKER_LND_VERSION=v0.14.4-beta npm run test",
74
77
  "test": "echo $DOCKER_LND_VERSION && node test/runner"
75
78
  },
76
- "version": "57.23.1"
79
+ "version": "57.24.0"
77
80
  }
@@ -0,0 +1,121 @@
1
+ const {equal} = require('node:assert').strict;
2
+ const test = require('node:test');
3
+
4
+ const asyncAuto = require('async/auto');
5
+ const asyncRetry = require('async/retry');
6
+ const {cancelHodlInvoice} = require('./../../');
7
+ const {createHodlInvoice} = require('./../../');
8
+ const {getInvoice} = require('./../../');
9
+ const {getChannels} = require('./../../');
10
+ const {getClosedChannels} = require('./../../');
11
+ const {pay} = require('./../../');
12
+ const {setupChannel} = require('ln-docker-daemons');
13
+ const {spawnLightningCluster} = require('ln-docker-daemons');
14
+
15
+ const {closeChannel} = require('./../../');
16
+
17
+ const interval = 100;
18
+ const size = 2;
19
+ const times = 1000;
20
+ const tokens = 10;
21
+
22
+ // Closing a pending payments channel should close the channel after a wait
23
+ test(`Close channel with wait for pending`, async () => {
24
+ const {kill, nodes} = await spawnLightningCluster({size});
25
+
26
+ const [control, target] = nodes;
27
+
28
+ try {
29
+ // Open a channel from control to target
30
+ const channelOpen = await setupChannel({
31
+ generate: control.generate,
32
+ lnd: control.lnd,
33
+ to: target,
34
+ });
35
+
36
+ // Create a hold invoice to create the pending state
37
+ const invoice = await createHodlInvoice({tokens, lnd: target.lnd});
38
+
39
+ await asyncAuto({
40
+ makePayment: async () => {
41
+ // Pay to the hold invoice
42
+ try {
43
+ await pay({lnd: control.lnd, request: invoice.request});
44
+ } catch (err) {
45
+ const [, type] = err;
46
+
47
+ // We expect that it would be canceled back
48
+ equal(type, 'PaymentRejectedByDestination');
49
+ }
50
+ },
51
+
52
+ // Wait for the payment to be held
53
+ lookForPayment: async () => {
54
+ await asyncRetry({interval, times}, async () => {
55
+ const received = await getInvoice({id: invoice.id, lnd: target.lnd});
56
+
57
+ if (!received.is_held) {
58
+ throw new Error('ExpectedPaymentHeld');
59
+ }
60
+ });
61
+ },
62
+
63
+ // Start the closing process
64
+ closeChannel: ['lookForPayment', async () => {
65
+ try {
66
+ await closeChannel({
67
+ id: channelOpen.id,
68
+ is_graceful_close: true,
69
+ lnd: control.lnd,
70
+ });
71
+ } catch (err) {
72
+ const [,, error] = err;
73
+
74
+ const {details} = error.err;
75
+
76
+ // LND 0.17.5 and below do not support graceful closes
77
+ if (details === 'cannot co-op close channel with active htlcs') {
78
+ throw new Error('FeatureUnsupported');
79
+ }
80
+
81
+ throw err;
82
+ }
83
+ }],
84
+
85
+ // Wait for channel to be in closing mode
86
+ confirmClosing: ['lookForPayment', async () => {
87
+ await asyncRetry({interval, times}, async () => {
88
+ const {channels} = await getChannels({lnd: control.lnd});
89
+
90
+ if (!channels.filter(n => !n.is_active).length) {
91
+ throw new Error('ExpectedInactiveChannels');
92
+ }
93
+ });
94
+ }],
95
+
96
+ // Stop the payment to void the pending state
97
+ cancelPayment: ['confirmClosing', async () => {
98
+ await cancelHodlInvoice({id: invoice.id, lnd: target.lnd});
99
+ }],
100
+
101
+ // Confirm that the channel closed cleanly
102
+ confirmClosed: ['cancelPayment', async () => {
103
+ await asyncRetry({interval, times}, async () => {
104
+ const {channels} = await getClosedChannels({lnd: control.lnd});
105
+
106
+ await control.generate({});
107
+
108
+ if (!channels.filter(n => !!n.is_cooperative_close).length) {
109
+ throw new Error('ExpectedCooperativelyClosedChannels');
110
+ }
111
+ });
112
+ }],
113
+ });
114
+ } catch (err) {
115
+ equal(err.message, 'FeatureUnsupported', 'Expected no error');
116
+ } finally {
117
+ await kill({});
118
+ }
119
+
120
+ return;
121
+ });