lightning 6.5.0 → 6.6.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
+ ## 6.6.0
4
+
5
+ - `getBlock`: Add method to get a raw block from the chain
6
+
3
7
  ## 6.5.0
4
8
 
5
9
  - `getFailedPayments`, `getInvoices`, `getPayments`, `getPendingPayments`: add
package/README.md CHANGED
@@ -139,6 +139,7 @@ variables set:
139
139
  specific channel.
140
140
  - [getBackups](https://github.com/alexbosworth/ln-service#getbackups): Get recovery details for
141
141
  all channels.
142
+ - [getBlock](https://github.com/alexbosworth/ln-service#getblock): Get a block
142
143
  - [getChainBalance](https://github.com/alexbosworth/ln-service#getchainbalance): Get the amount
143
144
  of on-chain funds.
144
145
  - [getChainFeeEstimate](https://github.com/alexbosworth/ln-service#getchainfeeestimate):
@@ -4,6 +4,7 @@
4
4
  "maxReceiveMessageLength": 924288000,
5
5
  "packageTypes": {
6
6
  "Autopilot": "autopilotrpc",
7
+ "ChainKit": "chainrpc",
7
8
  "ChainNotifier": "chainrpc",
8
9
  "Invoices": "invoicesrpc",
9
10
  "Lightning": "lnrpc",
@@ -19,6 +20,7 @@
19
20
  },
20
21
  "protoFiles": {
21
22
  "Autopilot": "autopilot.proto",
23
+ "ChainKit": "chainkit.proto",
22
24
  "ChainNotifier": "chainnotifier.proto",
23
25
  "Invoices": "invoices.proto",
24
26
  "Lightning": "lightning.proto",
@@ -35,6 +37,7 @@
35
37
  "protosDir": "../grpc/protos",
36
38
  "serviceTypes": {
37
39
  "autopilot": "Autopilot",
40
+ "blocks": "ChainKit",
38
41
  "chain": "ChainNotifier",
39
42
  "default": "Lightning",
40
43
  "invoices": "Invoices",
@@ -0,0 +1,59 @@
1
+ syntax = "proto3";
2
+
3
+ package chainrpc;
4
+
5
+ option go_package = "github.com/lightningnetwork/lnd/lnrpc/chainrpc";
6
+
7
+ // ChainKit is a service that can be used to get information from the
8
+ // chain backend.
9
+ service ChainKit {
10
+ /* lncli: `chain getblock`
11
+ GetBlock returns a block given the corresponding block hash.
12
+ */
13
+ rpc GetBlock (GetBlockRequest) returns (GetBlockResponse);
14
+
15
+ /* lncli: `chain getbestblock`
16
+ GetBestBlock returns the block hash and current height from the valid
17
+ most-work chain.
18
+ */
19
+ rpc GetBestBlock (GetBestBlockRequest) returns (GetBestBlockResponse);
20
+
21
+ /* lncli: `chain getblockhash`
22
+ GetBlockHash returns the hash of the block in the best blockchain
23
+ at the given height.
24
+ */
25
+ rpc GetBlockHash (GetBlockHashRequest) returns (GetBlockHashResponse);
26
+ }
27
+
28
+ message GetBlockRequest {
29
+ // The hash of the requested block.
30
+ bytes block_hash = 1;
31
+ }
32
+
33
+ // TODO(ffranr): The neutrino GetBlock response includes many
34
+ // additional helpful fields. Consider adding them here also.
35
+ message GetBlockResponse {
36
+ // The raw bytes of the requested block.
37
+ bytes raw_block = 1;
38
+ }
39
+
40
+ message GetBestBlockRequest {
41
+ }
42
+
43
+ message GetBestBlockResponse {
44
+ // The hash of the best block.
45
+ bytes block_hash = 1;
46
+
47
+ // The height of the best block.
48
+ int32 block_height = 2;
49
+ }
50
+
51
+ message GetBlockHashRequest {
52
+ // Block height of the target best chain block.
53
+ int64 block_height = 1;
54
+ }
55
+
56
+ message GetBlockHashResponse {
57
+ // The hash of the best block at the specified height.
58
+ bytes block_hash = 1;
59
+ }
package/index.js CHANGED
@@ -32,6 +32,7 @@ const {getAccessIds} = require('./lnd_methods');
32
32
  const {getAutopilot} = require('./lnd_methods');
33
33
  const {getBackup} = require('./lnd_methods');
34
34
  const {getBackups} = require('./lnd_methods');
35
+ const {getBlock} = require('./lnd_methods');
35
36
  const {getChainBalance} = require('./lnd_methods');
36
37
  const {getChainFeeEstimate} = require('./lnd_methods');
37
38
  const {getChainFeeRate} = require('./lnd_methods');
@@ -182,6 +183,7 @@ module.exports = {
182
183
  getAutopilot,
183
184
  getBackup,
184
185
  getBackups,
186
+ getBlock,
185
187
  getChainBalance,
186
188
  getChainFeeEstimate,
187
189
  getChainFeeRate,
@@ -30,6 +30,7 @@ const {getAccessIds} = require('./macaroon');
30
30
  const {getAutopilot} = require('./info');
31
31
  const {getBackup} = require('./offchain');
32
32
  const {getBackups} = require('./offchain');
33
+ const {getBlock} = require('./onchain');
33
34
  const {getChainBalance} = require('./onchain');
34
35
  const {getChainFeeEstimate} = require('./onchain');
35
36
  const {getChainFeeRate} = require('./onchain');
@@ -176,6 +177,7 @@ module.exports = {
176
177
  getAutopilot,
177
178
  getBackup,
178
179
  getBackups,
180
+ getBlock,
179
181
  getChainBalance,
180
182
  getChainFeeEstimate,
181
183
  getChainFeeRate,
@@ -1,6 +1,7 @@
1
1
  import {
2
2
  AuthenticatedLightningArgs,
3
3
  AuthenticatedLightningMethod,
4
+ DateRangeFilterArgs,
4
5
  PaginationArgs,
5
6
  } from '../../typescript';
6
7
 
@@ -8,7 +9,7 @@ export type GetInvoicesArgs = AuthenticatedLightningArgs<
8
9
  PaginationArgs & {
9
10
  /** Omit Canceled and Settled Invoices Bool */
10
11
  is_unconfirmed?: boolean;
11
- }
12
+ } & DateRangeFilterArgs
12
13
  >;
13
14
 
14
15
  export type GetInvoicesResult = {
@@ -121,6 +121,10 @@
121
121
  "method": "ExportAllChannelBackups",
122
122
  "type": "default"
123
123
  },
124
+ "getBlock": {
125
+ "method": "GetBlock",
126
+ "type": "blocks"
127
+ },
124
128
  "getChainBalance": {
125
129
  "method": "WalletBalance",
126
130
  "type": "default"
@@ -77,6 +77,10 @@ export type SubscribeToRpcRequestsOpenChannelRequestEvent =
77
77
  partner_public_key: string;
78
78
  /** Peer Output CSV Delay Number */
79
79
  partner_csv_delay?: number;
80
+ /** Routing Base Fee Millitokens Charged String */
81
+ base_fee_mtokens?: string;
82
+ /** Routing Fee Rate In Millitokens Per Million Number */
83
+ fee_rate?: number;
80
84
  }>;
81
85
 
82
86
  /** A pay to route request was intercepted: by default it will be rejected */
@@ -1,10 +1,13 @@
1
1
  import {
2
2
  AuthenticatedLightningArgs,
3
3
  AuthenticatedLightningMethod,
4
+ DateRangeFilterArgs,
4
5
  PaginationArgs,
5
6
  } from '../../typescript';
6
7
 
7
- export type GetFailedPaymentsArgs = AuthenticatedLightningArgs<PaginationArgs>;
8
+ export type GetFailedPaymentsArgs = AuthenticatedLightningArgs<
9
+ PaginationArgs & DateRangeFilterArgs
10
+ >;
8
11
 
9
12
  export type GetFailedPaymentsResult = {
10
13
  payments: {
@@ -91,7 +91,7 @@ export type GetPaymentResult = {
91
91
  tokens: number;
92
92
  /** Total Millitokens Paid On All Paths */
93
93
  total_mtokens: string;
94
- }[]
94
+ }[];
95
95
  /** BOLT 11 Payment Request */
96
96
  request?: string;
97
97
  /** Payment Forwarding Fee Rounded Up Tokens */
@@ -147,7 +147,7 @@ export type GetPaymentResult = {
147
147
  tokens: number;
148
148
  /** Total Millitokens Pending */
149
149
  total_mtokens: string;
150
- }[]
150
+ }[];
151
151
  /** BOLT 11 Payment Request */
152
152
  request?: string;
153
153
  /** Payment Tokens Rounded Up */
@@ -1,10 +1,13 @@
1
1
  import {
2
2
  AuthenticatedLightningArgs,
3
3
  AuthenticatedLightningMethod,
4
+ DateRangeFilterArgs,
4
5
  PaginationArgs,
5
6
  } from '../../typescript';
6
7
 
7
- export type GetPaymentsArgs = AuthenticatedLightningArgs<PaginationArgs>;
8
+ export type GetPaymentsArgs = AuthenticatedLightningArgs<
9
+ PaginationArgs & DateRangeFilterArgs
10
+ >;
8
11
 
9
12
  export type GetPaymentsResult = {
10
13
  payments: {
@@ -1,10 +1,13 @@
1
1
  import {
2
2
  AuthenticatedLightningArgs,
3
3
  AuthenticatedLightningMethod,
4
+ DateRangeFilterArgs,
4
5
  PaginationArgs,
5
6
  } from '../../typescript';
6
7
 
7
- export type GetPendingPaymentsArgs = AuthenticatedLightningArgs<PaginationArgs>;
8
+ export type GetPendingPaymentsArgs = AuthenticatedLightningArgs<
9
+ PaginationArgs & DateRangeFilterArgs
10
+ >;
8
11
 
9
12
  export type GetPendingPaymentsResult = {
10
13
  payments: {
@@ -0,0 +1,78 @@
1
+ const asyncAuto = require('async/auto');
2
+ const {returnResult} = require('asyncjs-util');
3
+
4
+ const {isLnd} = require('./../../lnd_requests');
5
+
6
+ const bufferAsHex = buffer => buffer.toString('hex');
7
+ const errorNotFound = '-5: Block not found';
8
+ const errorUnknownMethod = 'unknown service chainrpc.ChainKit';
9
+ const hexAsBuffer = hex => Buffer.from(hex, 'hex').reverse();
10
+ const {isBuffer} = Buffer;
11
+ const isHash = n => /^[0-9A-F]{64}$/i.test(n);
12
+ const method = 'getBlock';
13
+ const type = 'blocks';
14
+
15
+ /** Get a block in the chain
16
+
17
+ This method requires LND built with `chainkit` build tag
18
+
19
+ Requires `onchain:read` permission
20
+
21
+ This method is not supported on LND 0.15.5 and below
22
+
23
+ {
24
+ id: <Block Hash Hex String>
25
+ lnd: <Authenticated LND API Object>
26
+ }
27
+
28
+ @returns via cbk or Promise
29
+ {
30
+ block: <Raw Block Bytes Hex String>
31
+ }
32
+ */
33
+ module.exports = ({id, lnd}, cbk) => {
34
+ return new Promise((resolve, reject) => {
35
+ return asyncAuto({
36
+ // Check arguments
37
+ validate: cbk => {
38
+ if (!isHash(id)) {
39
+ return cbk([400, 'ExpectedIdentifyingBlockHashOfBlockToRetrieve']);
40
+ }
41
+
42
+ if (!isLnd({lnd, method, type})) {
43
+ return cbk([400, 'ExpectedAuthenticatedLndToRetrieveBlock']);
44
+ }
45
+
46
+ return cbk();
47
+ },
48
+
49
+ // Get the block
50
+ getBlock: ['validate', ({}, cbk) => {
51
+ return lnd[type][method]({block_hash: hexAsBuffer(id)}, (err, res) => {
52
+ if (!!err && err.details === errorNotFound) {
53
+ return cbk([404, 'BlockNotFound']);
54
+ }
55
+
56
+ if (!!err && err.details === errorUnknownMethod) {
57
+ return cbk([501, 'GetBlockMethodNotSupported']);
58
+ }
59
+
60
+ if (!!err) {
61
+ return cbk([503, 'UnexpectedErrorWhenGettingChainBlock', {err}]);
62
+ }
63
+
64
+ if (!res) {
65
+ return cbk([503, 'ExpectedResponseForChainBlockRequest']);
66
+ }
67
+
68
+ if (!isBuffer(res.raw_block)) {
69
+ return cbk([503, 'ExpectedRawBlockInChainBlockResponse']);
70
+ }
71
+
72
+ return cbk(null, {block: bufferAsHex(res.raw_block)});
73
+ });
74
+ }],
75
+ },
76
+ returnResult({reject, resolve, of: 'getBlock'}, cbk));
77
+ });
78
+ };
@@ -3,6 +3,7 @@ const cancelPendingChannel = require('./cancel_pending_channel');
3
3
  const closeChannel = require('./close_channel');
4
4
  const fundPendingChannels = require('./fund_pending_channels');
5
5
  const fundPsbt = require('./fund_psbt');
6
+ const getBlock = require('./get_block');
6
7
  const getChainBalance = require('./get_chain_balance');
7
8
  const getChainFeeEstimate = require('./get_chain_fee_estimate');
8
9
  const getChainFeeRate = require('./get_chain_fee_rate');
@@ -37,6 +38,7 @@ module.exports = {
37
38
  closeChannel,
38
39
  fundPendingChannels,
39
40
  fundPsbt,
41
+ getBlock,
40
42
  getChainBalance,
41
43
  getChainFeeEstimate,
42
44
  getChainFeeRate,
package/package.json CHANGED
@@ -9,8 +9,8 @@
9
9
  "dependencies": {
10
10
  "@grpc/grpc-js": "1.8.0",
11
11
  "@grpc/proto-loader": "0.7.4",
12
- "@types/express": "4.17.14",
13
- "@types/node": "18.11.13",
12
+ "@types/express": "4.17.15",
13
+ "@types/node": "18.11.15",
14
14
  "@types/request": "2.48.8",
15
15
  "@types/ws": "8.5.3",
16
16
  "async": "3.2.4",
@@ -26,7 +26,7 @@
26
26
  "invoices": "2.2.2",
27
27
  "psbt": "2.7.1",
28
28
  "tiny-secp256k1": "2.2.1",
29
- "type-fest": "3.3.0"
29
+ "type-fest": "3.4.0"
30
30
  },
31
31
  "description": "Lightning Network client library",
32
32
  "devDependencies": {
@@ -59,5 +59,5 @@
59
59
  "directory": "test/typescript"
60
60
  },
61
61
  "types": "index.d.ts",
62
- "version": "6.5.0"
62
+ "version": "6.6.0"
63
63
  }
@@ -4,6 +4,7 @@ const {authenticatedLndGrpc} = require('./../../');
4
4
 
5
5
  const expectedServices = [
6
6
  'autopilot',
7
+ 'blocks',
7
8
  'chain',
8
9
  'default',
9
10
  'invoices',
@@ -0,0 +1,92 @@
1
+ const {test} = require('@alexbosworth/tap');
2
+
3
+ const {getBlock} = require('./../../../lnd_methods');
4
+
5
+ const tests = [
6
+ {
7
+ args: {},
8
+ description: 'An id is expected to get a block',
9
+ error: [400, 'ExpectedIdentifyingBlockHashOfBlockToRetrieve'],
10
+ },
11
+ {
12
+ args: {id: Buffer.alloc(32).toString('hex')},
13
+ description: 'An lnd object is required to get a block',
14
+ error: [400, 'ExpectedAuthenticatedLndToRetrieveBlock'],
15
+ },
16
+ {
17
+ args: {
18
+ id: Buffer.alloc(32).toString('hex'),
19
+ lnd: {
20
+ blocks: {
21
+ getBlock: ({}, cbk) => cbk({details: '-5: Block not found'}),
22
+ },
23
+ },
24
+ },
25
+ description: 'An error is returned when a block is not found',
26
+ error: [404, 'BlockNotFound'],
27
+ },
28
+ {
29
+ args: {
30
+ id: Buffer.alloc(32).toString('hex'),
31
+ lnd: {
32
+ blocks: {
33
+ getBlock: ({}, cbk) => cbk({
34
+ details: 'unknown service chainrpc.ChainKit',
35
+ }),
36
+ },
37
+ },
38
+ },
39
+ description: 'An error is returned when the method is not supported',
40
+ error: [501, 'GetBlockMethodNotSupported'],
41
+ },
42
+ {
43
+ args: {
44
+ id: Buffer.alloc(32).toString('hex'),
45
+ lnd: {blocks: {getBlock: ({}, cbk) => cbk('err')}},
46
+ },
47
+ description: 'An error is returned',
48
+ error: [503, 'UnexpectedErrorWhenGettingChainBlock', {err: 'err'}],
49
+ },
50
+ {
51
+ args: {
52
+ id: Buffer.alloc(32).toString('hex'),
53
+ lnd: {blocks: {getBlock: ({}, cbk) => cbk()}},
54
+ },
55
+ description: 'A result is expected',
56
+ error: [503, 'ExpectedResponseForChainBlockRequest'],
57
+ },
58
+ {
59
+ args: {
60
+ id: Buffer.alloc(32).toString('hex'),
61
+ lnd: {blocks: {getBlock: ({}, cbk) => cbk(null, {})}},
62
+ },
63
+ description: 'A resulting block is expected',
64
+ error: [503, 'ExpectedRawBlockInChainBlockResponse'],
65
+ },
66
+ {
67
+ args: {
68
+ id: Buffer.alloc(32).toString('hex'),
69
+ lnd: {
70
+ blocks: {
71
+ getBlock: ({}, cbk) => cbk(null, {raw_block: Buffer.alloc(1)}),
72
+ },
73
+ },
74
+ },
75
+ description: 'A block is returned',
76
+ expected: {block: '00'},
77
+ },
78
+ ];
79
+
80
+ tests.forEach(({args, description, error, expected}) => {
81
+ return test(description, async ({deepEqual, end, rejects, strictSame}) => {
82
+ if (!!error) {
83
+ await rejects(() => getBlock(args), error, 'Got expected error');
84
+ } else {
85
+ const res = await getBlock(args);
86
+
87
+ strictSame(res, expected, 'Got expected result');
88
+ }
89
+
90
+ return end();
91
+ });
92
+ });
@@ -94,3 +94,10 @@ export type PaginationArgs = MergeExclusive<
94
94
  token?: string;
95
95
  }
96
96
  >;
97
+
98
+ export type DateRangeFilterArgs = {
99
+ /** Creation Date After or Equal to ISO 8601 Date String */
100
+ created_after?: string;
101
+ /** Creation Date Before or Equal to ISO 8601 Date String */
102
+ created_before?: string;
103
+ };