lightning 10.22.2 → 10.23.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,6 +1,10 @@
1
1
  # Versions
2
2
 
3
- ## 10.22.2
3
+ ## 10.23.0
4
+
5
+ - `getRoutingFeeEstimate`: Add method to estimate an offchain payment fee
6
+
7
+ ## 10.22.3
4
8
 
5
9
  - `createFundedPsbt`: Add support for `change_format` for change address type
6
10
 
package/README.md CHANGED
@@ -234,6 +234,8 @@ variables set:
234
234
  Calculate a route through specified nodes.
235
235
  - [getRouteToDestination](https://github.com/alexbosworth/ln-service#getroutetodestination):
236
236
  Calculate a route through the graph to a destination.
237
+ - [getRoutingFeeEstimate](https://github.com/alexbosworth/ln-service#getroutingfeeestimate):
238
+ Make a test payment to find a working routing fee for a payment request
237
239
  - [getSettlementStatus](https://github.com/alexbosworth/ln-service#getsettlementstatus):
238
240
  Lookup the status of a received payment output
239
241
  - [getSweepTransactions](https://github.com/alexbosworth/ln-service#getsweeptransactions): List
@@ -643,6 +643,8 @@ message SendCustomMessageRequest {
643
643
  }
644
644
 
645
645
  message SendCustomMessageResponse {
646
+ // The status of the send operation.
647
+ string status = 1;
646
648
  }
647
649
 
648
650
  message Utxo {
@@ -755,11 +757,35 @@ message GetTransactionsRequest {
755
757
 
756
758
  // An optional filter to only include transactions relevant to an account.
757
759
  string account = 3;
760
+
761
+ /*
762
+ The index of a transaction that will be used in a query to determine which
763
+ transaction should be returned in the response.
764
+ */
765
+ uint32 index_offset = 4;
766
+
767
+ /*
768
+ The maximal number of transactions returned in the response to this query.
769
+ This value should be set to 0 to return all transactions.
770
+ */
771
+ uint32 max_transactions = 5;
758
772
  }
759
773
 
760
774
  message TransactionDetails {
761
775
  // The list of transactions relevant to the wallet.
762
776
  repeated Transaction transactions = 1;
777
+
778
+ /*
779
+ The index of the last item in the set of returned transactions. This can be
780
+ used to seek further, pagination style.
781
+ */
782
+ uint64 last_index = 2;
783
+
784
+ /*
785
+ The index of the last item in the set of returned transactions. This can be
786
+ used to seek backwards, pagination style.
787
+ */
788
+ uint64 first_index = 3;
763
789
  }
764
790
 
765
791
  message FeeLimit {
@@ -1317,6 +1343,8 @@ message ConnectPeerRequest {
1317
1343
  uint64 timeout = 3;
1318
1344
  }
1319
1345
  message ConnectPeerResponse {
1346
+ // The status of the connect operation.
1347
+ string status = 1;
1320
1348
  }
1321
1349
 
1322
1350
  message DisconnectPeerRequest {
@@ -1324,6 +1352,8 @@ message DisconnectPeerRequest {
1324
1352
  string pub_key = 1;
1325
1353
  }
1326
1354
  message DisconnectPeerResponse {
1355
+ // The status of the disconnect operation.
1356
+ string status = 1;
1327
1357
  }
1328
1358
 
1329
1359
  message HTLC {
@@ -3542,6 +3572,8 @@ message NetworkInfo {
3542
3572
  message StopRequest {
3543
3573
  }
3544
3574
  message StopResponse {
3575
+ // The status of the stop operation.
3576
+ string status = 1;
3545
3577
  }
3546
3578
 
3547
3579
  message GraphTopologySubscription {
@@ -4366,9 +4398,13 @@ message DeleteAllPaymentsRequest {
4366
4398
  }
4367
4399
 
4368
4400
  message DeletePaymentResponse {
4401
+ // The status of the delete operation.
4402
+ string status = 1;
4369
4403
  }
4370
4404
 
4371
4405
  message DeleteAllPaymentsResponse {
4406
+ // The status of the delete operation.
4407
+ string status = 1;
4372
4408
  }
4373
4409
 
4374
4410
  message AbandonChannelRequest {
@@ -4385,6 +4421,8 @@ message AbandonChannelRequest {
4385
4421
  }
4386
4422
 
4387
4423
  message AbandonChannelResponse {
4424
+ // The status of the abandon operation.
4425
+ string status = 1;
4388
4426
  }
4389
4427
 
4390
4428
  message DebugLevelRequest {
@@ -4544,6 +4582,15 @@ message PolicyUpdateRequest {
4544
4582
  // Optional inbound fee. If unset, the previously set value will be
4545
4583
  // retained [EXPERIMENTAL].
4546
4584
  InboundFee inbound_fee = 10;
4585
+
4586
+ // Under unknown circumstances a channel can exist with a missing edge in
4587
+ // the graph database. This can cause an 'edge not found' error when calling
4588
+ // `getchaninfo` and/or cause the default channel policy to be used during
4589
+ // forwards. Setting this flag will recreate the edge if not found, allowing
4590
+ // updating this channel policy and fixing the missing edge problem for this
4591
+ // channel permanently. For fields not set in this command, the default
4592
+ // policy will be created.
4593
+ bool create_missing_edge = 11;
4547
4594
  }
4548
4595
 
4549
4596
  enum UpdateFailure {
@@ -4724,12 +4771,15 @@ message RestoreChanBackupRequest {
4724
4771
  }
4725
4772
  }
4726
4773
  message RestoreBackupResponse {
4774
+ // The number of channels successfully restored.
4775
+ uint32 num_restored = 1;
4727
4776
  }
4728
4777
 
4729
4778
  message ChannelBackupSubscription {
4730
4779
  }
4731
4780
 
4732
4781
  message VerifyChanBackupResponse {
4782
+ repeated string chan_points = 1;
4733
4783
  }
4734
4784
 
4735
4785
  message MacaroonPermission {
@@ -1064,13 +1064,9 @@ message ForwardHtlcInterceptResponse {
1064
1064
  // the resumed HTLC. This field is ignored if the action is not
1065
1065
  // RESUME_MODIFIED.
1066
1066
  //
1067
- // If this map is populated, it will overwrite any of the wire custom
1068
- // records set by LND. It is the caller's responsibility to copy any desired
1069
- // records across. If the map is empty, no action will be taken and existing
1070
- // custom records will be propagated.
1071
- //
1072
- // The API does not currently support deleting custom records, unless they
1073
- // are overwritten by a new set.
1067
+ // This map will merge with the existing set of custom records (if any),
1068
+ // replacing any conflicting types. Note that there currently is no support
1069
+ // for deleting existing custom records (they can only be replaced).
1074
1070
  map<uint64, bytes> out_wire_custom_records = 8;
1075
1071
  }
1076
1072
 
@@ -414,6 +414,8 @@ message ReleaseOutputRequest {
414
414
  }
415
415
 
416
416
  message ReleaseOutputResponse {
417
+ // The status of the release operation.
418
+ string status = 1;
417
419
  }
418
420
 
419
421
  message KeyReq {
@@ -699,6 +701,8 @@ message ImportPublicKeyRequest {
699
701
  AddressType address_type = 2;
700
702
  }
701
703
  message ImportPublicKeyResponse {
704
+ // The status of the import operation.
705
+ string status = 1;
702
706
  }
703
707
 
704
708
  message ImportTapscriptRequest {
@@ -1318,6 +1322,8 @@ message LabelTransactionRequest {
1318
1322
  }
1319
1323
 
1320
1324
  message LabelTransactionResponse {
1325
+ // The status of the label operation.
1326
+ string status = 1;
1321
1327
  }
1322
1328
 
1323
1329
  // The possible change address types for default accounts and single imported
@@ -1388,6 +1394,12 @@ message FundPsbtRequest {
1388
1394
  input with.
1389
1395
  */
1390
1396
  uint64 sat_per_vbyte = 4;
1397
+
1398
+ /*
1399
+ The fee rate, expressed in sat/kWU, that should be used to spend the
1400
+ input with.
1401
+ */
1402
+ uint64 sat_per_kw = 11;
1391
1403
  }
1392
1404
 
1393
1405
  /*
@@ -1411,6 +1423,9 @@ message FundPsbtRequest {
1411
1423
 
1412
1424
  // The strategy to use for selecting coins during funding the PSBT.
1413
1425
  lnrpc.CoinSelectionStrategy coin_selection_strategy = 10;
1426
+
1427
+ // The max fee to total output amount ratio that this psbt should adhere to.
1428
+ double max_fee_ratio = 12;
1414
1429
  }
1415
1430
  message FundPsbtResponse {
1416
1431
  /*
package/index.js CHANGED
@@ -78,6 +78,7 @@ const {getPublicKey} = require('./lnd_methods');
78
78
  const {getRouteConfidence} = require('./lnd_methods');
79
79
  const {getRouteThroughHops} = require('./lnd_methods');
80
80
  const {getRouteToDestination} = require('./lnd_methods');
81
+ const {getRoutingFeeEstimate} = require('./lnd_methods');
81
82
  const {getSettlementStatus} = require('./lnd_methods');
82
83
  const {getSweepTransactions} = require('./lnd_methods');
83
84
  const {getTowerServerInfo} = require('./lnd_methods');
@@ -239,6 +240,7 @@ module.exports = {
239
240
  getRouteConfidence,
240
241
  getRouteThroughHops,
241
242
  getRouteToDestination,
243
+ getRoutingFeeEstimate,
242
244
  getSettlementStatus,
243
245
  getSweepTransactions,
244
246
  getTowerServerInfo,
@@ -77,6 +77,7 @@ const {getPublicKey} = require('./address');
77
77
  const {getRouteConfidence} = require('./generic');
78
78
  const {getRouteThroughHops} = require('./offchain');
79
79
  const {getRouteToDestination} = require('./info');
80
+ const {getRoutingFeeEstimate} = require('./offchain');
80
81
  const {getSettlementStatus} = require('./offchain');
81
82
  const {getSweepTransactions} = require('./onchain');
82
83
  const {getTowerServerInfo} = require('./info');
@@ -237,6 +238,7 @@ module.exports = {
237
238
  getRouteConfidence,
238
239
  getRouteThroughHops,
239
240
  getRouteToDestination,
241
+ getRoutingFeeEstimate,
240
242
  getSettlementStatus,
241
243
  getSweepTransactions,
242
244
  getTowerServerInfo,
@@ -47,6 +47,7 @@
47
47
  "b4e7131bdb47531ad2f00ce345ddcdb58935bba5": "0.15.3-beta",
48
48
  "bd0c46b4fcb027af1915bd67a3da70e8ca5c6efe": "0.14.3-beta",
49
49
  "c0a09209782b1c62c3393fcea0844e095c25046b": "0.15.5-beta",
50
+ "ddeb8351684a611f6c27f16f09be75d5c039f08c": "0.18.4-beta",
50
51
  "d176d2d65fc06e6631c4dc9478592be8545a21de": "0.12.0-beta",
51
52
  "d22b3937eae91d33cd8c035e8fa894e3793e1636": "0.18.2-beta",
52
53
  "d233f61383f2f950aa06f5b09da5b0e78e784fae": "0.12.1-beta",
@@ -312,6 +312,10 @@
312
312
  "method": "QueryRoutes",
313
313
  "type": "default"
314
314
  },
315
+ "getRoutingFeeEstimate": {
316
+ "method": "EstimateRouteFee",
317
+ "type": "router"
318
+ },
315
319
  "getSettlementStatus": {
316
320
  "method": "LookupHtlcResolution",
317
321
  "type": "default"
@@ -0,0 +1,32 @@
1
+ import {AuthenticatedLnd} from '../../lnd_grpc';
2
+ import {
3
+ AuthenticatedLightningArgs,
4
+ AuthenticatedLightningMethod
5
+ } from '../../typescript';
6
+
7
+ export type GetRoutingFeeEstimateRequest = AuthenticatedLightningArgs<{
8
+ lnd: AuthenticatedLnd;
9
+ /** BOLT 11 Encoded Payment Request */
10
+ request: string;
11
+ /** Optional Timeout in Milliseconds */
12
+ timeout?: number;
13
+ }>;
14
+
15
+ export type GetRoutingFeeEstimateResponse = {
16
+ /** (Minimum Routing Fee Millitokens) */
17
+ fee_mtokens: string;
18
+ /** Timeout (Time Lock Delay) */
19
+ timeout: number;
20
+ };
21
+
22
+ /**
23
+ * Estimate routing fees based on an invoice.
24
+ *
25
+ * Requires `offchain:read` permission
26
+ *
27
+ * This method is not supported before LND 0.18.4
28
+ */
29
+ export const getRoutingFeeEstimate: AuthenticatedLightningMethod<
30
+ GetRoutingFeeEstimateRequest,
31
+ GetRoutingFeeEstimateResponse
32
+ >;
@@ -0,0 +1,86 @@
1
+ const asyncAuto = require('async/auto');
2
+ const {returnResult} = require('asyncjs-util');
3
+
4
+ const {isLnd} = require('./../../lnd_requests');
5
+
6
+ const defaultTimeoutSeconds = 60;
7
+ const method = 'estimateRouteFee';
8
+ const msAsSecs = ms => Math.round(ms / 1e3);
9
+ const type = 'router';
10
+
11
+ /** Estimate routing fees and timeout required to pay a payment request
12
+
13
+ Requires `offchain:read` permission
14
+
15
+ This method is not supported on LND 0.18.3 and below
16
+
17
+ {
18
+ lnd: <Authenticated LND API Object>
19
+ request: <BOLT 11 Payment Request String>
20
+ [timeout]: <Maximum Route Pathfinding Time in Milliseconds Number>
21
+ }
22
+
23
+ @returns via cbk or Promise
24
+ {
25
+ fee_mtokens: <Estimated Minimum Required Route Fee Millitokens String>
26
+ timeout: <Estimated Minimum Time Lock Block Height Delay Number>
27
+ }
28
+ */
29
+ module.exports = ({lnd, request, timeout}, cbk) => {
30
+ return new Promise((resolve, reject) => {
31
+ return asyncAuto({
32
+ // Check arguments
33
+ validate: cbk => {
34
+ if (!isLnd({lnd, method, type})) {
35
+ return cbk([400, 'ExpectedAuthenticatedLndToGetRoutingFeeEstimate']);
36
+ }
37
+
38
+ if (!request) {
39
+ return cbk([400, 'ExpectedPaymentRequestToGetRoutingFeeEstimate']);
40
+ }
41
+
42
+ return cbk();
43
+ },
44
+
45
+ // Request a probe of the request to determine a needed fee and delay
46
+ getEstimate: ['validate', ({}, cbk) => {
47
+ return lnd[type][method]({
48
+ payment_request: request,
49
+ timeout: msAsSecs(timeout) || defaultTimeoutSeconds,
50
+ },
51
+ (err, res) => {
52
+ if (!!err) {
53
+ return cbk([503, 'UnexpectedGetRoutingFeeEstimateError', {err}]);
54
+ }
55
+
56
+ if (!res) {
57
+ return cbk([503, 'ExpectedGetRoutingFeeEstimateResponse']);
58
+ }
59
+
60
+ if (!res.routing_fee_msat) {
61
+ return cbk([503, 'ExpectedFeeInGetRoutingFeeEstimateResponse']);
62
+ }
63
+
64
+ if (!res.time_lock_delay) {
65
+ return cbk([503, 'ExpectedTimeoutInGetRouteFeeEstimateResponse']);
66
+ }
67
+
68
+ // Exit early with error when the estimate response has failure code
69
+ if (res.failure_reason !== 'FAILURE_REASON_NONE') {
70
+ return cbk([
71
+ 404,
72
+ 'RouteToDestinationNotFound',
73
+ {failure: res.failure_reason},
74
+ ]);
75
+ }
76
+
77
+ return cbk(null, {
78
+ fee_mtokens: res.routing_fee_msat,
79
+ timeout: Number(res.time_lock_delay),
80
+ });
81
+ });
82
+ }],
83
+ },
84
+ returnResult({reject, resolve, of: 'getEstimate'}, cbk));
85
+ });
86
+ };
@@ -27,6 +27,7 @@ export * from './get_payments';
27
27
  export * from './get_pending_channels';
28
28
  export * from './get_pending_payments';
29
29
  export * from './get_route_through_hops';
30
+ export * from './get_routing_fee_estimate';
30
31
  export * from './get_settlement_status';
31
32
  export * from './is_destination_payable';
32
33
  export * from './pay_via_payment_details';
@@ -27,6 +27,7 @@ const getPayments = require('./get_payments');
27
27
  const getPendingChannels = require('./get_pending_channels');
28
28
  const getPendingPayments = require('./get_pending_payments');
29
29
  const getRouteThroughHops = require('./get_route_through_hops');
30
+ const getRoutingFeeEstimate = require('./get_routing_fee_estimate');
30
31
  const getSettlementStatus = require('./get_settlement_status');
31
32
  const isDestinationPayable = require('./is_destination_payable');
32
33
  const pay = require('./pay');
@@ -86,6 +87,7 @@ module.exports = {
86
87
  getPendingChannels,
87
88
  getPendingPayments,
88
89
  getRouteThroughHops,
90
+ getRoutingFeeEstimate,
89
91
  getSettlementStatus,
90
92
  isDestinationPayable,
91
93
  pay,
package/package.json CHANGED
@@ -7,14 +7,14 @@
7
7
  "url": "https://github.com/alexbosworth/lightning/issues"
8
8
  },
9
9
  "dependencies": {
10
- "@grpc/grpc-js": "1.12.2",
10
+ "@grpc/grpc-js": "1.12.5",
11
11
  "@grpc/proto-loader": "0.7.13",
12
- "@types/node": "22.9.1",
12
+ "@types/node": "22.10.5",
13
13
  "@types/request": "2.48.12",
14
14
  "@types/ws": "8.5.13",
15
15
  "async": "3.2.6",
16
16
  "asyncjs-util": "1.2.12",
17
- "bitcoinjs-lib": "6.1.6",
17
+ "bitcoinjs-lib": "6.1.7",
18
18
  "bn.js": "5.2.1",
19
19
  "bolt07": "1.9.4",
20
20
  "bolt09": "2.1.0",
@@ -22,12 +22,12 @@
22
22
  "invoices": "3.0.0",
23
23
  "psbt": "3.0.0",
24
24
  "tiny-secp256k1": "2.2.3",
25
- "type-fest": "4.27.0"
25
+ "type-fest": "4.31.0"
26
26
  },
27
27
  "description": "Lightning Network client library",
28
28
  "devDependencies": {
29
29
  "tsd": "0.31.2",
30
- "typescript": "5.6.3"
30
+ "typescript": "5.7.2"
31
31
  },
32
32
  "engines": {
33
33
  "node": ">=18"
@@ -53,5 +53,5 @@
53
53
  "directory": "test/typescript"
54
54
  },
55
55
  "types": "index.d.ts",
56
- "version": "10.22.2"
56
+ "version": "10.23.0"
57
57
  }
@@ -0,0 +1,82 @@
1
+ const {rejects, deepStrictEqual} = require('node:assert').strict;
2
+ const test = require('node:test');
3
+ const {getRoutingFeeEstimate} = require('../../../');
4
+
5
+ const makeLnd = ({err, res}) => {
6
+ const r = {
7
+ routing_fee_msat: '1',
8
+ time_lock_delay: '1',
9
+ failure_reason: 'FAILURE_REASON_NONE',
10
+ };
11
+
12
+ return {
13
+ router: {
14
+ estimateRouteFee: ({}, cbk) => cbk(err, res !== undefined ? res : r),
15
+ },
16
+ };
17
+ };
18
+
19
+ const makeArgs = override => {
20
+ const args = {lnd: makeLnd({}), request: 'request'};
21
+
22
+ Object.keys(override || {}).forEach(key => args[key] = override[key]);
23
+
24
+ return args;
25
+ };
26
+
27
+ const tests = [
28
+ {
29
+ args: makeArgs({lnd: undefined}),
30
+ description: 'LND is required',
31
+ error: [400, 'ExpectedAuthenticatedLndToGetRoutingFeeEstimate'],
32
+ },
33
+ {
34
+ args: makeArgs({request: undefined}),
35
+ description: 'Request is required',
36
+ error: [400, 'ExpectedPaymentRequestToGetRoutingFeeEstimate'],
37
+ },
38
+ {
39
+ args: makeArgs({}),
40
+ description: 'A route fee estimate is returned',
41
+ expected: {fee_mtokens: '1', timeout: 1},
42
+ },
43
+ {
44
+ args: makeArgs({lnd: makeLnd({err: 'err'})}),
45
+ description: 'An error is not expected',
46
+ error: [503, 'UnexpectedGetRoutingFeeEstimateError', {err: 'err'}],
47
+ },
48
+ {
49
+ args: makeArgs({lnd: makeLnd({res: null})}),
50
+ description: 'A result is expected',
51
+ error: [503, 'ExpectedGetRoutingFeeEstimateResponse'],
52
+ },
53
+ {
54
+ args: makeArgs({lnd: makeLnd({res: {}})}),
55
+ description: 'A result fee is expected',
56
+ error: [503, 'ExpectedFeeInGetRoutingFeeEstimateResponse'],
57
+ },
58
+ {
59
+ args: makeArgs({lnd: makeLnd({res: {routing_fee_msat: '1'}})}),
60
+ description: 'A result timeout is expected',
61
+ error: [503, 'ExpectedTimeoutInGetRouteFeeEstimateResponse'],
62
+ },
63
+ {
64
+ args: makeArgs({
65
+ lnd: makeLnd({res: {routing_fee_msat: '1', time_lock_delay: '1'}}),
66
+ }),
67
+ description: 'A result non failure code is expected',
68
+ error: [404, 'RouteToDestinationNotFound', {failure: undefined}],
69
+ },
70
+ ];
71
+
72
+ tests.forEach(({args, description, error, expected}) => {
73
+ return test(description, async () => {
74
+ if (!!error) {
75
+ await rejects(getRoutingFeeEstimate(args), error, 'Got expected error');
76
+ } else {
77
+ deepStrictEqual(await getRoutingFeeEstimate(args), expected, 'Got res');
78
+ }
79
+
80
+ return;
81
+ });
82
+ });