ln-docker-daemons 2.2.11 → 2.3.1

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,6 +1,10 @@
1
1
  # Versions
2
2
 
3
- ## 2.2.11
3
+ ## 2.3.1
4
+
5
+ - `setupChannel`: Add method to setup a channel between LND nodes
6
+
7
+ ## 2.2.12
4
8
 
5
9
  - Change default LND version to v0.14.3-beta
6
10
 
package/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  The MIT License (MIT)
2
2
 
3
- Copyright (c) 2020 Alex Bosworth
3
+ Copyright (c) 2020-2022 Alex Bosworth
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
package/README.md CHANGED
@@ -18,6 +18,19 @@ const publicKey = (await getIdentity({lnd})).public_key;
18
18
  await kill({});
19
19
  ```
20
20
 
21
+ Supported methods:
22
+
23
+ - setupChannel: Create a channel between lnds
24
+ - spawnBitcoindDocker: Run a Bitcoin Core container
25
+ - spawnLightningCluster: Spin up a group of nodes
26
+ - spawnLightningDocker: Run lnd + bitcoind
27
+
28
+ One liner for killing all running Docker containers:
29
+
30
+ ```
31
+ docker container kill $(docker ps -q)
32
+ ```
33
+
21
34
  ## Environment Variables
22
35
 
23
36
  - `DOCKER_LND_VERSION`: set this to use a custom LND docker image
@@ -31,7 +44,48 @@ export DOCKER_LND_VERSION="v0.14.0-beta"
31
44
  A list of available tags can be found here:
32
45
  https://hub.docker.com/r/lightninglabs/lnd/tags
33
46
 
34
- ## spawnBitcoindDocker
47
+ ## `setupChannel`
48
+
49
+ Setup channel
50
+
51
+ {
52
+ [capacity]: <Channel Capacity Tokens Number>
53
+ generate: <Generate Blocks Promise>
54
+ [give_tokens]: <Gift Tokens Number>
55
+ lnd: <Authenticated LND API Object>
56
+ [partner_csv_delay]: <Partner CSV Delay Number>
57
+ to: {
58
+ id: <Partner Public Key Hex String>
59
+ socket: <Network Address String>
60
+ }
61
+ }
62
+
63
+ @returns via cbk or Promise
64
+ {
65
+ id: <Standard Format Channel Id String>
66
+ transaction_id: <Funding Transaction Id Hex String>
67
+ transaction_vout: <Funding Transaction Output Index Number>
68
+ }
69
+
70
+ Example:
71
+
72
+ ```node
73
+ const {getNetworkInfo} = require('ln-service');
74
+ const {spawnLightningCluster} = require('ln-docker-daemons');
75
+
76
+ const {kill, nodes} = await spawnLightningCluster({size: 2});
77
+
78
+ const [alice, bob] = nodes;
79
+
80
+ await setupChannel({generate: alice.generate, lnd: alice.lnd, to: bob});
81
+
82
+ const networkInfo = await getNetworkInfo({lnd: alice.lnd});
83
+ // networkInfo.channel_count now equals 1
84
+
85
+ await kill({});
86
+ ```
87
+
88
+ ## `spawnBitcoindDocker`
35
89
 
36
90
  Spawn a Bitcoin Core Docker image
37
91
 
@@ -106,7 +160,7 @@ await generate({count: 500});
106
160
  await kill({});
107
161
  ```
108
162
 
109
- ## spawnLightningDocker
163
+ ## `spawnLightningDocker`
110
164
 
111
165
  Spawn an LND Docker
112
166
 
package/index.js CHANGED
@@ -1,8 +1,10 @@
1
+ const {setupChannel} = require('./setup');
1
2
  const {spawnBitcoindDocker} = require('./bitcoind');
2
3
  const {spawnLightningCluster} = require('./cluster');
3
4
  const {spawnLightningDocker} = require('./lnd');
4
5
 
5
6
  module.exports = {
7
+ setupChannel,
6
8
  spawnBitcoindDocker,
7
9
  spawnLightningCluster,
8
10
  spawnLightningDocker,
package/package.json CHANGED
@@ -8,11 +8,11 @@
8
8
  },
9
9
  "dependencies": {
10
10
  "@alexbosworth/node-fetch": "2.6.2",
11
- "async": "3.2.3",
12
- "asyncjs-util": "1.2.9",
13
- "dockerode": "3.3.1",
11
+ "async": "3.2.4",
12
+ "asyncjs-util": "1.2.10",
13
+ "dockerode": "3.3.2",
14
14
  "find-free-ports": "3.0.0",
15
- "lightning": "5.16.0",
15
+ "lightning": "5.16.3",
16
16
  "tar-stream": "2.2.0"
17
17
  },
18
18
  "description": "Spawn and control LN Docker daemons",
@@ -35,5 +35,5 @@
35
35
  "scripts": {
36
36
  "test": "tap --branches=1 --functions=1 --lines=1 --statements=1 -j 1 test/bitcoind/*.js test/lnd/*.js"
37
37
  },
38
- "version": "2.2.11"
38
+ "version": "2.3.1"
39
39
  }
package/setup/index.js ADDED
@@ -0,0 +1,3 @@
1
+ const setupChannel = require('./setup_channel');
2
+
3
+ module.exports = {setupChannel};
@@ -0,0 +1,98 @@
1
+ const {addPeer} = require('lightning');
2
+ const asyncAuto = require('async/auto');
3
+ const asyncRetry = require('async/retry');
4
+ const {getChainBalance} = require('lightning');
5
+ const {openChannel} = require('lightning');
6
+ const {returnResult} = require('asyncjs-util');
7
+
8
+ const waitForChannel = require('./wait_for_channel');
9
+ const waitForPendingChannel = require('./wait_for_pending_channel');
10
+
11
+ const channelCapacityTokens = 1e6;
12
+ const confCount = 6;
13
+ const count = 100;
14
+ const defaultFee = 1e3;
15
+ const interval = 100;
16
+ const times = 1500;
17
+
18
+ /** Setup channel
19
+
20
+ {
21
+ [capacity]: <Channel Capacity Tokens Number>
22
+ generate: <Generate Blocks Promise>
23
+ [give_tokens]: <Gift Tokens Number>
24
+ lnd: <Authenticated LND API Object>
25
+ [partner_csv_delay]: <Partner CSV Delay Number>
26
+ to: {
27
+ id: <Partner Public Key Hex String>
28
+ socket: <Network Address String>
29
+ }
30
+ }
31
+
32
+ @returns via cbk or Promise
33
+ {
34
+ id: <Standard Format Channel Id String>
35
+ transaction_id: <Funding Transaction Id Hex String>
36
+ transaction_vout: <Funding Transaction Output Index Number>
37
+ }
38
+ */
39
+ module.exports = (args, cbk) => {
40
+ return new Promise((resolve, reject) => {
41
+ return asyncAuto({
42
+ // Make sure the node is connected
43
+ addPeer: cbk => {
44
+ return addPeer({
45
+ lnd: args.lnd,
46
+ public_key: args.to.id || args.to.public_key,
47
+ socket: args.to.socket,
48
+ },
49
+ cbk);
50
+ },
51
+
52
+ // Make sure the node has funds
53
+ generateFunds: async () => await args.generate({count}),
54
+
55
+ // Open channel
56
+ chanOpen: cbk => {
57
+ return asyncRetry({interval, times}, cbk => {
58
+ return openChannel({
59
+ chain_fee_tokens_per_vbyte: defaultFee,
60
+ give_tokens: args.give_tokens,
61
+ lnd: args.lnd,
62
+ local_tokens: args.capacity || channelCapacityTokens,
63
+ partner_csv_delay: args.partner_csv_delay,
64
+ partner_public_key: args.to.public_key || args.to.id,
65
+ socket: args.to.socket,
66
+ },
67
+ cbk);
68
+ },
69
+ cbk);
70
+ },
71
+
72
+ // Wait for pending
73
+ waitPending: ['chanOpen', ({chanOpen}, cbk) => {
74
+ return waitForPendingChannel({
75
+ id: chanOpen.transaction_id,
76
+ lnd: args.lnd,
77
+ },
78
+ cbk);
79
+ }],
80
+
81
+ // Generate blocks to confirm the pending channel
82
+ generate: ['waitPending', async ({}) => {
83
+ return await args.generate({count: confCount});
84
+ }],
85
+
86
+ // Wait for open
87
+ channel: ['chanOpen', ({chanOpen}, cbk) => {
88
+ return waitForChannel({
89
+ id: chanOpen.transaction_id,
90
+ lnd: args.lnd,
91
+ vout: chanOpen.transaction_vout,
92
+ },
93
+ cbk);
94
+ }],
95
+ },
96
+ returnResult({reject, resolve, of: 'channel'}, cbk));
97
+ });
98
+ };
@@ -0,0 +1,96 @@
1
+ const asyncAuto = require('async/auto');
2
+ const asyncRetry = require('async/retry');
3
+ const {returnResult} = require('asyncjs-util');
4
+
5
+ const {getChannel} = require('lightning');
6
+ const {getChannels} = require('lightning');
7
+
8
+ const interval = 20;
9
+ const times = 10000;
10
+
11
+ /** Wait for channel to be open
12
+
13
+ {
14
+ id: <Channel Transaction Id Hex String>
15
+ lnd: <Authenticated LND API Object>
16
+ vout: <Channel Output Index Number>
17
+ }
18
+
19
+ @returns via cbk or Promise
20
+ {
21
+ capacity: <Channel Token Capacity Number>
22
+ commit_transaction_fee: <Commit Transaction Fee Number>
23
+ commit_transaction_weight: <Commit Transaction Weight Number>
24
+ id: <Standard Format Channel Id String>
25
+ is_active: <Channel Active Bool>
26
+ is_closing: <Channel Is Closing Bool>
27
+ is_opening: <Channel Is Opening Bool>
28
+ is_partner_initiated: <Channel Partner Opened Channel>
29
+ is_private: <Channel Is Private Bool>
30
+ local_balance: <Local Balance Tokens Number>
31
+ partner_public_key: <Channel Partner Public Key String>
32
+ pending_payments: [{
33
+ id: <Payment Preimage Hash Hex String>
34
+ is_outgoing: <Payment Is Outgoing Bool>
35
+ timeout: <Chain Height Expiration Number>
36
+ tokens: <Payment Tokens Number>
37
+ }]
38
+ received: <Received Tokens Number>
39
+ remote_balance: <Remote Balance Tokens Number>
40
+ sent: <Sent Tokens Number>
41
+ transaction_id: <Blockchain Transaction Id String>
42
+ transaction_vout: <Blockchain Transaction Vout Number>
43
+ unsettled_balance: <Unsettled Balance Tokens Number>
44
+ }
45
+ */
46
+ module.exports = (args, cbk) => {
47
+ return new Promise((resolve, reject) => {
48
+ return asyncAuto({
49
+ // Check arguments
50
+ validate: cbk => {
51
+ if (!args.id) {
52
+ return cbk([400, 'ExpectedTransactionIdToWaitForChannelOpen']);
53
+ }
54
+
55
+ if (!args.lnd || !args.lnd.default) {
56
+ return cbk([400, 'ExpectedAuthenticatedLndToWaitForChannelOpen']);
57
+ }
58
+
59
+ return cbk();
60
+ },
61
+
62
+ // Find channel in channels list
63
+ channel: ['validate', async () => {
64
+ return await asyncRetry({interval, times}, async () => {
65
+ const {channels} = await getChannels({lnd: args.lnd});
66
+
67
+ const chan = channels.find(channel => {
68
+ const txVout = channel.transaction_vout;
69
+
70
+ return channel.transaction_id === args.id && txVout === args.vout;
71
+ });
72
+
73
+ if (!chan) {
74
+ throw new Error('FailedToFindChannelWithTransactionId');
75
+ }
76
+
77
+ return chan;
78
+ });
79
+ }],
80
+
81
+ // Check channel fully created
82
+ gotChannel: ['channel', async ({channel}) => {
83
+ return await asyncRetry({interval, times}, async () => {
84
+ const {policies} = await getChannel({id: channel.id, lnd: args.lnd});
85
+
86
+ if (!!policies.find(n => !n.cltv_delta)) {
87
+ throw new Error('FailedToFindChannelWithFullPolicyDetails');
88
+ }
89
+
90
+ return;
91
+ });
92
+ }],
93
+ },
94
+ returnResult({reject, resolve, of: 'channel'}, cbk));
95
+ });
96
+ };
@@ -0,0 +1,43 @@
1
+ const asyncRetry = require('async/retry');
2
+ const {getPendingChannels} = require('lightning');
3
+
4
+ const interval = 10;
5
+ const times = 20000;
6
+
7
+ /** Wait for a pending channel to appear
8
+
9
+ {
10
+ id: <Channel Transaction Id Hex String>
11
+ lnd: <Authenticated LND API Object>
12
+ }
13
+
14
+ @returns via cbk
15
+ */
16
+ module.exports = (args, cbk) => {
17
+ if (!args.id) {
18
+ return cbk([400, 'ExpectedTransactionIdToWaitForChannelPending']);
19
+ }
20
+
21
+ if (!args.lnd || !args.lnd.default) {
22
+ return cbk([400, 'ExpectedAuthenticatedLndToWaitForChannelPending']);
23
+ }
24
+
25
+ const {id} = args;
26
+
27
+ return asyncRetry({interval, times}, cbk => {
28
+ return getPendingChannels({lnd: args.lnd}, (err, res) => {
29
+ if (!!err) {
30
+ return cbk(err);
31
+ }
32
+
33
+ const channel = res.pending_channels.find(n => n.transaction_id === id);
34
+
35
+ if (!channel) {
36
+ return cbk([503, 'FailedToFindPendingChannelWithTransactionId']);
37
+ }
38
+
39
+ return cbk(null, {channel});
40
+ });
41
+ },
42
+ cbk);
43
+ };