ln-service 57.23.0 → 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 +8 -0
- package/README.md +4 -1
- package/package.json +8 -5
- package/test/integration/test_close_wait_pending.js +121 -0
package/CHANGELOG.md
CHANGED
package/README.md
CHANGED
|
@@ -9,7 +9,7 @@ through npm.
|
|
|
9
9
|
|
|
10
10
|
Supported LND versions:
|
|
11
11
|
|
|
12
|
-
- v0.18.0-beta to v0.18.
|
|
12
|
+
- v0.18.0-beta to v0.18.5-beta
|
|
13
13
|
- v0.17.0-beta to v0.17.5-beta
|
|
14
14
|
- v0.16.0-beta to v0.16.4-beta
|
|
15
15
|
- v0.15.2-beta to v0.15.5-beta
|
|
@@ -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.
|
|
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.
|
|
27
|
+
"ln-docker-daemons": "6.0.24",
|
|
28
28
|
"p2tr": "2.0.0",
|
|
29
|
-
"portfinder": "1.0.
|
|
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
|
|
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.
|
|
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
|
+
});
|