lightning 10.22.3 → 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,5 +1,9 @@
1
1
  # Versions
2
2
 
3
+ ## 10.23.0
4
+
5
+ - `getRoutingFeeEstimate`: Add method to estimate an offchain payment fee
6
+
3
7
  ## 10.22.3
4
8
 
5
9
  - `createFundedPsbt`: Add support for `change_format` for change address type
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
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,
@@ -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
@@ -9,7 +9,7 @@
9
9
  "dependencies": {
10
10
  "@grpc/grpc-js": "1.12.5",
11
11
  "@grpc/proto-loader": "0.7.13",
12
- "@types/node": "22.10.2",
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",
@@ -22,7 +22,7 @@
22
22
  "invoices": "3.0.0",
23
23
  "psbt": "3.0.0",
24
24
  "tiny-secp256k1": "2.2.3",
25
- "type-fest": "4.30.2"
25
+ "type-fest": "4.31.0"
26
26
  },
27
27
  "description": "Lightning Network client library",
28
28
  "devDependencies": {
@@ -53,5 +53,5 @@
53
53
  "directory": "test/typescript"
54
54
  },
55
55
  "types": "index.d.ts",
56
- "version": "10.22.3"
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
+ });