lightning 5.3.0 → 5.3.4

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,14 @@
1
1
  # Versions
2
2
 
3
- ## 5.3.0
3
+ ## 5.3.4
4
+
5
+ - `getPayments`: Correct paging issue that prevented paging through all results
6
+
7
+ ## 5.3.3
8
+
9
+ - `pay`, `payViaPaymentRequest`: Fix support for `outgoing_channels` constraint
10
+
11
+ ## 5.3.1
4
12
 
5
13
  - `getInvoices`: Add `is_unconfirmed` to filter out canceled/settled invoices
6
14
 
package/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  The MIT License (MIT)
2
2
 
3
- Copyright (c) 2019-2021 Alex Bosworth
3
+ Copyright (c) 2019-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
@@ -7,17 +7,26 @@ Methods for working with the Lightning Network
7
7
  ## Selected Projects using Lightning
8
8
 
9
9
  - [coinos.io](https://coinos.io/) - https://github.com/coinos/coinos-server
10
- - [LNMarkets](https://twitter.com/lnmarkets) - https://github.com/lnmarkets/umbrel
10
+ - [Lightning Shell](https://lightningshell.app/) -
11
+ https://github.com/ibz/lightning-shell
12
+ - [LNMarkets](https://twitter.com/lnmarkets) -
13
+ https://github.com/lnmarkets/umbrel
11
14
  - [Galoy](https://galoy.io/) - https://github.com/GaloyMoney/galoy
12
15
  - [Tarnhelm](https://www.tarnhelm.app/) - https://github.com/bkiac/tarnhelm
13
- - [tbtcswaps](https://tbtcswaps.com/) - https://github.com/keep-community/tbtcswaps
14
- - [stackernews](https://stacker.news/) - https://github.com/stackernews/stacker.news
15
- - [Thunderhub](https://www.thunderhub.io/) - https://github.com/apotdevin/thunderhub
16
- - [Lightning Roulette](https://lightning-roulette.com/) - https://github.com/igreshev/lightning-roulette
17
- - [Lightning Poker](https://lightning-poker.com/) - https://github.com/igreshev/lightning-poker
16
+ - [tbtcswaps](https://tbtcswaps.com/) -
17
+ https://github.com/keep-community/tbtcswaps
18
+ - [stackernews](https://stacker.news/) -
19
+ https://github.com/stackernews/stacker.news
20
+ - [Thunderhub](https://www.thunderhub.io/) -
21
+ https://github.com/apotdevin/thunderhub
22
+ - [Lightning Roulette](https://lightning-roulette.com/) -
23
+ https://github.com/igreshev/lightning-roulette
24
+ - [Lightning Poker](https://lightning-poker.com/) -
25
+ https://github.com/igreshev/lightning-poker
18
26
  - [p2plnbot](https://telegram.me/lnp2pbot) - https://github.com/grunch/p2plnbot
19
27
  - [rekr](https://rekr.app/) - https://github.com/ryan-lingle/rekr
20
- - [Suredbits API](https://suredbits.com/) - https://github.com/Suredbits/sb-api-lnd
28
+ - [Suredbits API](https://suredbits.com/) -
29
+ https://github.com/Suredbits/sb-api-lnd
21
30
 
22
31
  ## LND Authentication
23
32
 
package/index.js CHANGED
@@ -17,6 +17,7 @@ const {deleteFailedPayments} = require('./lnd_methods');
17
17
  const {deleteForwardingReputations} = require('./lnd_methods');
18
18
  const {deletePayment} = require('./lnd_methods');
19
19
  const {deletePayments} = require('./lnd_methods');
20
+ const {deletePendingChannel} = require('./lnd_methods');
20
21
  const {diffieHellmanComputeSecret} = require('./lnd_methods');
21
22
  const {disableChannel} = require('./lnd_methods');
22
23
  const {disconnectWatchtower} = require('./lnd_methods');
@@ -153,6 +154,7 @@ module.exports = {
153
154
  deleteForwardingReputations,
154
155
  deletePayment,
155
156
  deletePayments,
157
+ deletePendingChannel,
156
158
  disableChannel,
157
159
  disconnectWatchtower,
158
160
  enableChannel,
@@ -16,6 +16,7 @@ const {deleteFailedPayments} = require('./offchain');
16
16
  const {deleteForwardingReputations} = require('./offchain');
17
17
  const {deletePayment} = require('./offchain');
18
18
  const {deletePayments} = require('./offchain');
19
+ const {deletePendingChannel} = require('./offchain');
19
20
  const {diffieHellmanComputeSecret} = require('./signer');
20
21
  const {disableChannel} = require('./offchain');
21
22
  const {disconnectWatchtower} = require('./offchain');
@@ -148,6 +149,7 @@ module.exports = {
148
149
  deleteForwardingReputations,
149
150
  deletePayment,
150
151
  deletePayments,
152
+ deletePendingChannel,
151
153
  diffieHellmanComputeSecret,
152
154
  disableChannel,
153
155
  disconnectWatchtower,
@@ -63,6 +63,10 @@
63
63
  "method": "DeleteAllPayments",
64
64
  "type": "default"
65
65
  },
66
+ "deletePendingChannel": {
67
+ "method": "AbandonChannel",
68
+ "type": "default"
69
+ },
66
70
  "diffieHellmanComputeSecret": {
67
71
  "method": "DeriveSharedKey",
68
72
  "type": "signer"
@@ -0,0 +1,109 @@
1
+ const asyncAuto = require('async/auto');
2
+ const {returnResult} = require('asyncjs-util');
3
+ const {Transaction} = require('bitcoinjs-lib');
4
+
5
+ const {fromHex} = Transaction;
6
+ const method = 'abandonChannel';
7
+ const txIdAsHash = id => Buffer.from(id, 'hex').reverse();
8
+ const type = 'default';
9
+
10
+ /** Delete a pending channel
11
+
12
+ Pass the confirmed conflicting transaction that spends the same input to
13
+ make sure that no funds are being deleted.
14
+
15
+ This method is not supported on LND 0.13.3 and below
16
+
17
+ {
18
+ confirmed_transaction: <Hex Encoded Conflicting Transaction String>
19
+ lnd: <Authenticated LND API Object>
20
+ pending_transaction: <Hex Encoded Pending Transaction String>
21
+ pending_transaction_vout: <Pending Channel Output Index Number>
22
+ }
23
+
24
+ @returns via cbk or Promise
25
+ */
26
+ module.exports = (args, cbk) => {
27
+ return new Promise((resolve, reject) => {
28
+ return asyncAuto({
29
+ // Check arguments
30
+ validate: cbk => {
31
+ if (!args.confirmed_transaction) {
32
+ return cbk([400, 'ExpectedConfirmedConflictingTxToDeleteChannel']);
33
+ }
34
+
35
+ try {
36
+ fromHex(args.confirmed_transaction);
37
+ } catch (err) {
38
+ return cbk([400, 'ExpectedValidConfirmedTxToDeleteChannel']);
39
+ }
40
+
41
+ if (args.confirmed_transaction === args.pending_transaction) {
42
+ return cbk([400, 'ExpectedConflictingTransactionToDeleteChannel']);
43
+ }
44
+
45
+ if (!args.lnd) {
46
+ return cbk([400, 'ExpectedAuthenticatedLndToDeleteChannel']);
47
+ }
48
+
49
+ if (!args.pending_transaction) {
50
+ return cbk([400, 'ExpectedPendingTransactionToDeleteChannel']);
51
+ }
52
+
53
+ try {
54
+ fromHex(args.pending_transaction);
55
+ } catch (err) {
56
+ return cbk([400, 'ExpectedValidPendingTxToDeleteChannel']);
57
+ }
58
+
59
+ if (args.pending_transaction_vout === undefined) {
60
+ return cbk([400, 'ExpectedPendingChannelTxVoutToDeleteChannel']);
61
+ }
62
+
63
+ return cbk();
64
+ },
65
+
66
+ // Check for a conflicting input between the confirmed and pending txs
67
+ transactionId: ['validate', ({}, cbk) => {
68
+ const confirmedInputs = fromHex(args.confirmed_transaction).ins;
69
+ const pending = fromHex(args.pending_transaction);
70
+
71
+ const conflictingInput = pending.ins.find(pendingInput => {
72
+ return confirmedInputs.find(confirmedInput => {
73
+ if (!confirmedInput.hash.equals(pendingInput.hash)) {
74
+ return false;
75
+ }
76
+
77
+ return confirmedInput.index === pendingInput.index;
78
+ });
79
+ });
80
+
81
+ if (!conflictingInput) {
82
+ return cbk([400, 'FailedToFindConflictingInputInConfirmedTx']);
83
+ }
84
+
85
+ // The pending transaction conflicts with the confirmed transaction
86
+ return cbk(null, pending.getId());
87
+ }],
88
+
89
+ // Delete the channel
90
+ abandonChannel: ['transactionId', ({transactionId}, cbk) => {
91
+ return args.lnd[type][method]({
92
+ channel_point: {
93
+ funding_txid_bytes: txIdAsHash(transactionId),
94
+ output_index: args.pending_transaction_vout,
95
+ },
96
+ i_know_what_i_am_doing: true,
97
+ },
98
+ err => {
99
+ if (!!err) {
100
+ return cbk([503, 'UnexpectedErrorDeletingPendingChannel', {err}]);
101
+ }
102
+
103
+ return cbk();
104
+ });
105
+ }],
106
+ },
107
+ returnResult({reject, resolve}, cbk));
108
+ });
109
+ };
@@ -8,7 +8,7 @@ const {sortBy} = require('./../../arrays');
8
8
  const defaultLimit = 250;
9
9
  const {isArray} = Array;
10
10
  const isFailed = payment => !!payment && payment.status === 'FAILED';
11
- const lastPageFirstIndexOffset = 0;
11
+ const lastPageFirstIndexOffset = 1;
12
12
  const method = 'listPayments';
13
13
  const {parse} = JSON;
14
14
  const {stringify} = JSON;
@@ -152,7 +152,7 @@ module.exports = ({limit, lnd, token}, cbk) => {
152
152
 
153
153
  return cbk(null, {
154
154
  payments: res.payments.filter(isFailed),
155
- token: offset === lastPageFirstIndexOffset ? undefined : token,
155
+ token: offset <= lastPageFirstIndexOffset ? undefined : token,
156
156
  });
157
157
  });
158
158
  }],
@@ -157,7 +157,7 @@ module.exports = ({limit, lnd, token}, cbk) => {
157
157
 
158
158
  return cbk(null, {
159
159
  payments: res.payments,
160
- token: offset === lastPageFirstIndexOffset ? undefined : token,
160
+ token: offset <= lastPageFirstIndexOffset ? undefined : token,
161
161
  });
162
162
  });
163
163
  }],
@@ -185,7 +185,7 @@ module.exports = ({limit, lnd, token}, cbk) => {
185
185
  });
186
186
 
187
187
  return cbk(null, {
188
- next: !!foundPayments.length ? listPayments.token : undefined,
188
+ next: listPayments.token || undefined,
189
189
  payments: payments.sorted.reverse(),
190
190
  });
191
191
  }],
@@ -5,6 +5,7 @@ const deleteFailedPayments = require('./delete_failed_payments');
5
5
  const deleteForwardingReputations = require('./delete_forwarding_reputations');
6
6
  const deletePayment = require('./delete_payment');
7
7
  const deletePayments = require('./delete_payments');
8
+ const deletePendingChannel = require('./delete_pending_channel');
8
9
  const disableChannel = require('./disable_channel');
9
10
  const disconnectWatchtower = require('./disconnect_watchtower');
10
11
  const enableChannel = require('./enable_channel');
@@ -59,6 +60,7 @@ module.exports = {
59
60
  deleteForwardingReputations,
60
61
  deletePayment,
61
62
  deletePayments,
63
+ deletePendingChannel,
62
64
  disableChannel,
63
65
  disconnectWatchtower,
64
66
  enableChannel,
@@ -99,6 +99,7 @@ module.exports = (args, cbk) => {
99
99
  messages: args.messages,
100
100
  mtokens: args.mtokens,
101
101
  outgoing_channel: args.outgoing_channel,
102
+ outgoing_channels: args.outgoing_channels,
102
103
  pathfinding_timeout: args.pathfinding_timeout,
103
104
  request: args.request,
104
105
  tokens: args.tokens,
@@ -3,6 +3,8 @@ const {returnResult} = require('asyncjs-util');
3
3
 
4
4
  const {isLnd} = require('./../../lnd_requests');
5
5
 
6
+ const bufferAsBase64 = buffer => buffer.toString('base64');
7
+ const {isBuffer} = Buffer;
6
8
  const method = 'initWallet';
7
9
  const type = 'unlocker';
8
10
  const utf8AsBuf = utf8 => Buffer.from(utf8, 'utf8');
@@ -19,6 +21,9 @@ const utf8AsBuf = utf8 => Buffer.from(utf8, 'utf8');
19
21
  }
20
22
 
21
23
  @returns via cbk or Promise
24
+ {
25
+ macaroon: <Base64 Encoded Admin Macaroon String>
26
+ }
22
27
  */
23
28
  module.exports = ({lnd, passphrase, password, seed}, cbk) => {
24
29
  return new Promise((resolve, reject) => {
@@ -47,12 +52,20 @@ module.exports = ({lnd, passphrase, password, seed}, cbk) => {
47
52
  cipher_seed_mnemonic: seed.split(' '),
48
53
  wallet_password: utf8AsBuf(password),
49
54
  },
50
- err => {
55
+ (err, res) => {
51
56
  if (!!err) {
52
57
  return cbk([503, 'UnexpectedInitWalletError', {err}]);
53
58
  }
54
59
 
55
- return cbk();
60
+ if (!res) {
61
+ return cbk([503, 'ExpectedResponseForInitWallet']);
62
+ }
63
+
64
+ if (!isBuffer(res.admin_macaroon)) {
65
+ return cbk([503, 'ExpectedAdminMacaroonToCrateWallet']);
66
+ }
67
+
68
+ return cbk(null, bufferAsBase64(res.admin_macaroon));
56
69
  });
57
70
  }],
58
71
  },
package/package.json CHANGED
@@ -7,32 +7,32 @@
7
7
  "url": "https://github.com/alexbosworth/lightning/issues"
8
8
  },
9
9
  "dependencies": {
10
- "@grpc/grpc-js": "1.5.0",
10
+ "@grpc/grpc-js": "1.5.3",
11
11
  "@grpc/proto-loader": "0.6.9",
12
12
  "@types/express": "4.17.13",
13
- "@types/node": "17.0.8",
13
+ "@types/node": "17.0.10",
14
14
  "@types/request": "2.48.8",
15
15
  "@types/ws": "8.2.2",
16
16
  "async": "3.2.3",
17
- "asyncjs-util": "1.2.7",
17
+ "asyncjs-util": "1.2.8",
18
18
  "bitcoinjs-lib": "6.0.1",
19
19
  "bn.js": "5.2.0",
20
20
  "body-parser": "1.19.1",
21
21
  "bolt07": "1.8.0",
22
- "bolt09": "0.2.0",
22
+ "bolt09": "0.2.1",
23
23
  "cbor": "8.1.0",
24
24
  "express": "4.17.2",
25
- "invoices": "2.0.2",
25
+ "invoices": "2.0.3",
26
26
  "psbt": "1.1.10",
27
- "type-fest": "2.9.0"
27
+ "type-fest": "2.10.0"
28
28
  },
29
29
  "description": "Lightning Network client library",
30
30
  "devDependencies": {
31
31
  "@alexbosworth/node-fetch": "2.6.2",
32
32
  "@alexbosworth/tap": "15.0.10",
33
33
  "tsd": "0.19.1",
34
- "typescript": "4.5.4",
35
- "ws": "8.4.0"
34
+ "typescript": "4.5.5",
35
+ "ws": "8.4.2"
36
36
  },
37
37
  "engines": {
38
38
  "node": ">=12.20"
@@ -57,5 +57,5 @@
57
57
  "directory": "test/typescript"
58
58
  },
59
59
  "types": "index.d.ts",
60
- "version": "5.3.0"
60
+ "version": "5.3.4"
61
61
  }
@@ -0,0 +1,91 @@
1
+ const {test} = require('@alexbosworth/tap');
2
+ const {Transaction} = require('bitcoinjs-lib');
3
+
4
+ const {deletePendingChannel} = require('./../../../lnd_methods');
5
+
6
+ const tx1 = new Transaction();
7
+ const tx2 = new Transaction();
8
+ const tx3 = new Transaction();
9
+
10
+ tx1.addInput(Buffer.alloc(32, 0), 0);
11
+ tx2.addInput(Buffer.alloc(32, 0), 0);
12
+ tx2.addInput(Buffer.alloc(32, 1), 0);
13
+ tx2.addOutput(Buffer.alloc(10), 1);
14
+ tx3.addInput(Buffer.alloc(32, 2), 0);
15
+
16
+ const makeArgs = overrides => {
17
+ const args = {
18
+ confirmed_transaction: tx1.toHex(),
19
+ lnd: {default: {abandonChannel: ({}, cbk) => cbk()}},
20
+ pending_transaction: tx2.toHex(),
21
+ pending_transaction_vout: 0,
22
+ };
23
+
24
+ Object.keys(overrides).forEach(k => args[k] = overrides[k]);
25
+
26
+ return args;
27
+ };
28
+
29
+ const tests = [
30
+ {
31
+ args: makeArgs({confirmed_transaction: undefined}),
32
+ description: 'A conflicting confirmed tx is required',
33
+ error: [400, 'ExpectedConfirmedConflictingTxToDeleteChannel'],
34
+ },
35
+ {
36
+ args: makeArgs({confirmed_transaction: 'confirmed transaction'}),
37
+ description: 'A valid conflicting confirmed tx is required',
38
+ error: [400, 'ExpectedValidConfirmedTxToDeleteChannel'],
39
+ },
40
+ {
41
+ args: makeArgs({confirmed_transaction: tx2.toHex()}),
42
+ description: 'Pending transaction must be different from confirmed tx',
43
+ error: [400, 'ExpectedConflictingTransactionToDeleteChannel'],
44
+ },
45
+ {
46
+ args: makeArgs({lnd: undefined}),
47
+ description: 'Lnd is required',
48
+ error: [400, 'ExpectedAuthenticatedLndToDeleteChannel'],
49
+ },
50
+ {
51
+ args: makeArgs({pending_transaction: undefined}),
52
+ description: 'A pending tx is required',
53
+ error: [400, 'ExpectedPendingTransactionToDeleteChannel'],
54
+ },
55
+ {
56
+ args: makeArgs({pending_transaction: 'pending transaction'}),
57
+ description: 'A valid pending tx is required',
58
+ error: [400, 'ExpectedValidPendingTxToDeleteChannel'],
59
+ },
60
+ {
61
+ args: makeArgs({pending_transaction_vout: undefined}),
62
+ description: 'A pending tx output index is required',
63
+ error: [400, 'ExpectedPendingChannelTxVoutToDeleteChannel'],
64
+ },
65
+ {
66
+ args: makeArgs({confirmed_transaction: tx3.toHex()}),
67
+ description: 'A conflicting tx is required',
68
+ error: [400, 'FailedToFindConflictingInputInConfirmedTx'],
69
+ },
70
+ {
71
+ args: makeArgs({lnd: {default: {abandonChannel: ({}, cbk) => cbk('er')}}}),
72
+ description: 'A server error is passed back',
73
+ error: [503, 'UnexpectedErrorDeletingPendingChannel', {err: 'er'}],
74
+ },
75
+ {
76
+ args: makeArgs({}),
77
+ description: 'A pending channel is deleted',
78
+ },
79
+ ];
80
+
81
+ tests.forEach(({args, description, error, expected}) => {
82
+ return test(description, async ({deepEqual, end, equal, rejects}) => {
83
+ if (!!error) {
84
+ await rejects(() => deletePendingChannel(args), error, 'Got error');
85
+ } else {
86
+ await deletePendingChannel(args);
87
+ }
88
+
89
+ return end();
90
+ });
91
+ });
@@ -30,7 +30,13 @@ const tests = [
30
30
  },
31
31
  {
32
32
  args: {
33
- lnd: {unlocker: {initWallet: ({}, cbk) => cbk()}},
33
+ lnd: {
34
+ unlocker: {
35
+ initWallet: ({}, cbk) => cbk(null, {
36
+ admin_macaroon: Buffer.alloc(1),
37
+ }),
38
+ },
39
+ },
34
40
  password: 'pass',
35
41
  seed: 'seed',
36
42
  },