lightning 10.11.0 → 10.12.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.11.0
3
+ ## 10.12.0
4
+
5
+ - `createFundedPsbt`: Add method to create a funded PSBT given inputs/outputs
6
+
7
+ ## 10.11.1
4
8
 
5
9
  - `getChannel`, `getNetworkGraph`, `getNode`: Add
6
10
  `inbound_base_discount_mtokens` and `inbound_rate_discount`
package/README.md CHANGED
@@ -103,6 +103,8 @@ variables set:
103
103
  new watchtower.
104
104
  - [createChainAddress](https://github.com/alexbosworth/ln-service#createchainaddress): Generate
105
105
  a chain address to receive on-chain funds.
106
+ - [createFundedPsbt](https://github.com/alexbosworth/ln-service#createfundedpsbt):
107
+ Create a funded PSBT given inputs and outputs
106
108
  - [createHodlInvoice](https://github.com/alexbosworth/ln-service#createhodlinvoice): Make a new
107
109
  off-chain invoice that will not automatically accept payment.
108
110
  - [createInvoice](https://github.com/alexbosworth/ln-service#createinvoice): Make a new off-chain
@@ -4369,6 +4369,16 @@ message FeeReportResponse {
4369
4369
  uint64 month_fee_sum = 4;
4370
4370
  }
4371
4371
 
4372
+ message InboundFee {
4373
+ // The inbound base fee charged regardless of the number of milli-satoshis
4374
+ // received in the channel. By default, only negative values are accepted.
4375
+ int32 base_fee_msat = 1;
4376
+
4377
+ // The effective inbound fee rate in micro-satoshis (parts per million).
4378
+ // By default, only negative values are accepted.
4379
+ int32 fee_rate_ppm = 2;
4380
+ }
4381
+
4372
4382
  message PolicyUpdateRequest {
4373
4383
  oneof scope {
4374
4384
  // If set, then this update applies to all currently active channels.
@@ -4402,8 +4412,9 @@ message PolicyUpdateRequest {
4402
4412
  // If true, min_htlc_msat is applied.
4403
4413
  bool min_htlc_msat_specified = 8;
4404
4414
 
4405
- int32 inbound_base_fee_msat = 10;
4406
- int32 inbound_fee_rate_ppm = 11;
4415
+ // Optional inbound fee. If unset, the previously set value will be
4416
+ // retained [EXPERIMENTAL].
4417
+ InboundFee inbound_fee = 10;
4407
4418
  }
4408
4419
 
4409
4420
  enum UpdateFailure {
package/index.js CHANGED
@@ -10,6 +10,7 @@ const {changePassword} = require('./lnd_methods');
10
10
  const {closeChannel} = require('./lnd_methods');
11
11
  const {connectWatchtower} = require('./lnd_methods');
12
12
  const {createChainAddress} = require('./lnd_methods');
13
+ const {createFundedPsbt} = require('./lnd_methods');
13
14
  const {createHodlInvoice} = require('./lnd_methods');
14
15
  const {createInvoice} = require('./lnd_methods');
15
16
  const {createSeed} = require('./lnd_methods');
@@ -169,6 +170,7 @@ module.exports = {
169
170
  closeChannel,
170
171
  connectWatchtower,
171
172
  createChainAddress,
173
+ createFundedPsbt,
172
174
  createHodlInvoice,
173
175
  createInvoice,
174
176
  createSeed,
@@ -9,6 +9,7 @@ const {changePassword} = require('./unauthenticated');
9
9
  const {closeChannel} = require('./onchain');
10
10
  const {connectWatchtower} = require('./offchain');
11
11
  const {createChainAddress} = require('./address');
12
+ const {createFundedPsbt} = require('./onchain');
12
13
  const {createHodlInvoice} = require('./invoices');
13
14
  const {createInvoice} = require('./invoices');
14
15
  const {createSeed} = require('./unauthenticated');
@@ -167,6 +168,7 @@ module.exports = {
167
168
  closeChannel,
168
169
  connectWatchtower,
169
170
  createChainAddress,
171
+ createFundedPsbt,
170
172
  createHodlInvoice,
171
173
  createInvoice,
172
174
  createSeed,
@@ -1,6 +1,7 @@
1
1
  import {
2
2
  AuthenticatedLightningArgs,
3
3
  AuthenticatedLightningMethod,
4
+ ChannelPolicy,
4
5
  } from '../../typescript';
5
6
 
6
7
  export type GetChannelArgs = AuthenticatedLightningArgs<{
@@ -13,24 +14,7 @@ export type GetChannelResult = {
13
14
  capacity: number;
14
15
  /** Standard Format Channel Id */
15
16
  id: string;
16
- policies: {
17
- /** Base Fee Millitokens */
18
- base_fee_mtokens?: string;
19
- /** Locktime Delta */
20
- cltv_delta?: number;
21
- /** Fees Charged Per Million Millitokens */
22
- fee_rate?: number;
23
- /** Channel Is Disabled */
24
- is_disabled?: boolean;
25
- /** Maximum HTLC Millitokens Value */
26
- max_htlc_mtokens?: string;
27
- /** Minimum HTLC Millitokens Value */
28
- min_htlc_mtokens?: string;
29
- /** Node Public Key */
30
- public_key: string;
31
- /** Policy Last Updated At ISO 8601 Date */
32
- updated_at?: string;
33
- }[];
17
+ policies: ChannelPolicy[];
34
18
  /** Transaction Id Hex */
35
19
  transaction_id: string;
36
20
  /** Transaction Output Index */
@@ -1,43 +1,29 @@
1
- import {AuthenticatedLnd} from '../../lnd_grpc';
2
- import {AuthenticatedLightningMethod} from '../../typescript';
1
+ import type {AuthenticatedLnd} from '../../lnd_grpc';
2
+ import type {
3
+ AuthenticatedLightningMethod,
4
+ ChannelPolicy,
5
+ } from '../../typescript';
3
6
 
4
7
  export type GetNetworkGraphResult = {
5
- channels: {
8
+ channels: Array<{
6
9
  /** Channel Capacity Tokens */
7
10
  capacity: number;
8
11
  /** Standard Format Channel Id */
9
12
  id: string;
10
- policies: {
11
- /** Base Fee Millitokens */
12
- base_fee_mtokens?: string;
13
- /** CLTV Height Delta */
14
- cltv_delta?: number;
15
- /** Fee Rate In Millitokens Per Million */
16
- fee_rate?: number;
17
- /** Edge is Disabled */
18
- is_disabled?: boolean;
19
- /** Maximum HTLC Millitokens */
20
- max_htlc_mtokens?: string;
21
- /** Minimum HTLC Millitokens */
22
- min_htlc_mtokens?: string;
23
- /** Public Key */
24
- public_key: string;
25
- /** Last Update Epoch ISO 8601 Date */
26
- updated_at?: string;
27
- }[];
13
+ policies: ChannelPolicy[];
28
14
  /** Funding Transaction Id */
29
15
  transaction_id: string;
30
16
  /** Funding Transaction Output Index */
31
17
  transaction_vout: number;
32
18
  /** Last Update Epoch ISO 8601 Date */
33
19
  updated_at?: string;
34
- }[];
35
- nodes: {
20
+ }>;
21
+ nodes: Array<{
36
22
  /** Name */
37
23
  alias: string;
38
24
  /** Hex Encoded Color */
39
25
  color: string;
40
- features: {
26
+ features: Array<{
41
27
  /** BOLT 09 Feature Bit */
42
28
  bit: number;
43
29
  /** Feature is Known */
@@ -46,14 +32,14 @@ export type GetNetworkGraphResult = {
46
32
  is_required: boolean;
47
33
  /** Feature Type */
48
34
  type: string;
49
- }[];
35
+ }>;
50
36
  /** Node Public Key */
51
37
  public_key: string;
52
38
  /** Network Addresses and Ports */
53
39
  sockets: string[];
54
40
  /** Last Updated ISO 8601 Date */
55
41
  updated_at: string;
56
- }[];
42
+ }>;
57
43
  };
58
44
 
59
45
  /**
@@ -1,6 +1,7 @@
1
- import {
1
+ import type {
2
2
  AuthenticatedLightningArgs,
3
3
  AuthenticatedLightningMethod,
4
+ ChannelPolicy,
4
5
  } from '../../typescript';
5
6
 
6
7
  export type GetNodeArgs = AuthenticatedLightningArgs<{
@@ -17,39 +18,22 @@ export type GetNodeResult = {
17
18
  capacity: number;
18
19
  /** Known Node Channels */
19
20
  channel_count: number;
20
- channels?: {
21
+ channels?: Array<{
21
22
  /** Maximum Tokens */
22
23
  capacity: number;
23
24
  /** Standard Format Channel Id */
24
25
  id: string;
25
- policies: {
26
- /** Base Fee Millitokens */
27
- base_fee_mtokens?: string;
28
- /** Locktime Delta */
29
- cltv_delta?: number;
30
- /** Fees Charged Per Million Millitokens */
31
- fee_rate?: number;
32
- /** Channel Is Disabled */
33
- is_disabled?: boolean;
34
- /** Maximum HTLC Millitokens Value */
35
- max_htlc_mtokens?: string;
36
- /** Minimum HTLC Millitokens Value */
37
- min_htlc_mtokens?: string;
38
- /** Node Public Key */
39
- public_key: string;
40
- /** Policy Last Updated At ISO 8601 Date */
41
- updated_at?: string;
42
- }[];
26
+ policies: ChannelPolicy[];
43
27
  /** Transaction Id Hex */
44
28
  transaction_id: string;
45
29
  /** Transaction Output Index */
46
30
  transaction_vout: number;
47
31
  /** Channel Last Updated At ISO 8601 Date */
48
32
  updated_at?: string;
49
- }[];
33
+ }>;
50
34
  /** RGB Hex Color */
51
35
  color: string;
52
- features: {
36
+ features: Array<{
53
37
  /** BOLT 09 Feature Bit */
54
38
  bit: number;
55
39
  /** Feature is Known */
@@ -58,13 +42,13 @@ export type GetNodeResult = {
58
42
  is_required: boolean;
59
43
  /** Feature Type */
60
44
  type: string;
61
- }[];
62
- sockets: {
45
+ }>;
46
+ sockets: Array<{
63
47
  /** Host and Port */
64
48
  socket: string;
65
49
  /** Socket Type */
66
50
  type: string;
67
- }[];
51
+ }>;
68
52
  /** Last Known Update ISO 8601 Date */
69
53
  updated_at?: string;
70
54
  };
@@ -42,6 +42,10 @@
42
42
  "method": "NewAddress",
43
43
  "type": "default"
44
44
  },
45
+ "createFundedPsbt": {
46
+ "method": "FundPsbt",
47
+ "type": "wallet"
48
+ },
45
49
  "createHodlInvoice": {
46
50
  "depends_on": ["createChainAddress"],
47
51
  "method": "AddHoldInvoice",
@@ -90,8 +90,29 @@ module.exports = (args, cbk) => {
90
90
  return cbk(null, tokensAsMtokens(args.base_fee_tokens));
91
91
  }],
92
92
 
93
+ // Determine the inbound fee discount policy
94
+ inboundFee: ['validate', ({}, cbk) => {
95
+ const inboundBase = args.inbound_base_discount_mtokens;
96
+ const inboundRate = args.inbound_rate_discount;
97
+
98
+ // Exit early when there is no inbound policy defined
99
+ if (inboundBase === undefined && inboundRate === undefined) {
100
+ return cbk();
101
+ }
102
+
103
+ // Convert discounts into the surcharges format
104
+ return cbk(null, {
105
+ base_fee_msat: surcharge(inboundBase),
106
+ fee_rate_ppm: surcharge(inboundRate)
107
+ });
108
+ }],
109
+
93
110
  // Set the routing fee policy
94
- updateFees: ['baseFeeMillitokens', ({baseFeeMillitokens}, cbk) => {
111
+ updateFees: [
112
+ 'baseFeeMillitokens',
113
+ 'inboundFee',
114
+ ({baseFeeMillitokens, inboundFee}, cbk) =>
115
+ {
95
116
  const id = args.transaction_id || undefined;
96
117
  const rate = args.fee_rate === undefined ? defaultRate : args.fee_rate;
97
118
  const vout = args.transaction_vout;
@@ -108,8 +129,7 @@ module.exports = (args, cbk) => {
108
129
  chan_point: !isGlobal ? chan : undefined,
109
130
  fee_rate: rate / feeRatio,
110
131
  global: isGlobal || undefined,
111
- inbound_base_fee_msat: surcharge(args.inbound_base_discount_mtokens),
112
- inbound_fee_rate_ppm: surcharge(args.inbound_rate_discount),
132
+ inbound_fee: inboundFee,
113
133
  max_htlc_msat: args.max_htlc_mtokens || undefined,
114
134
  min_htlc_msat: args.min_htlc_mtokens || undefined,
115
135
  min_htlc_msat_specified: !!args.min_htlc_mtokens,
@@ -0,0 +1,167 @@
1
+ const asyncAuto = require('async/auto');
2
+ const {createPsbt} = require('psbt');
3
+ const {returnResult} = require('asyncjs-util');
4
+
5
+ const {isLnd} = require('./../../lnd_requests');
6
+
7
+ const bufferAsHex = buffer => buffer.toString('hex');
8
+ const defaultChangeType = 'CHANGE_ADDRESS_TYPE_P2TR';
9
+ const defaultConfirmationTarget = 6;
10
+ const errorUnsupported = 'transaction template missing, need to specify either PSBT or raw TX template';
11
+ const hexAsBuffer = hex => Buffer.from(hex, 'hex');
12
+ const indexNotFound = -1;
13
+ const {isBuffer} = Buffer;
14
+ const method = 'fundPsbt';
15
+ const strategy = type => !type ? undefined : `STRATEGY_${type.toUpperCase()}`;
16
+ const type = 'wallet';
17
+ const unconfirmedConfirmationsCount = 0;
18
+
19
+ /** Create an unsigned funded PSBT given inputs or outputs
20
+
21
+ When specifying local inputs, they must be locked before using
22
+
23
+ `utxo_selection` methods: 'largest', 'random'
24
+
25
+ Requires `onchain:write` permission
26
+
27
+ Requires LND built with `walletrpc` tag
28
+
29
+ This method is not supported on LND 0.17.5 or below
30
+
31
+ {
32
+ [fee_tokens_per_vbyte]: <Chain Fee Tokens Per Virtual Byte Number>
33
+ [inputs]: [{
34
+ [sequence]: <Sequence Number>
35
+ transaction_id: <Unspent Transaction Id Hex String>
36
+ transaction_vout: <Unspent Transaction Output Index Number>
37
+ }]
38
+ lnd: <Authenticated LND API Object>
39
+ [min_confirmations]: <Select Inputs With Minimum Confirmations Number>
40
+ [outputs]: [{
41
+ [is_change]: <Use This Output For Change Bool>
42
+ script: <Output Script Hex String>
43
+ tokens: <Send Tokens Tokens Number>
44
+ }]
45
+ [target_confirmations]: <Blocks To Wait for Confirmation Number>
46
+ [timelock]: <Spendable Lock Time on Transaction Number>
47
+ [utxo_selection]: <Select Inputs Using Selection Methodology Type String>
48
+ [version]: <Transaction Version Number>
49
+ }
50
+
51
+ @returns via cbk or Promise
52
+ {
53
+ psbt: <Unsigned PSBT Hex String>
54
+ }
55
+ */
56
+ module.exports = (args, cbk) => {
57
+ return new Promise((resolve, reject) => {
58
+ return asyncAuto({
59
+ // Check arguments
60
+ validate: cbk => {
61
+ if (!isLnd({method, type, lnd: args.lnd})) {
62
+ return cbk([400, 'ExpectedAuthenticatedLndToCreateFundedPsbt']);
63
+ }
64
+
65
+ return cbk();
66
+ },
67
+
68
+ // Determine the change type
69
+ change: ['validate', ({}, cbk) => {
70
+ const changeIndex = (args.outputs || []).findIndex(n => !!n.is_change);
71
+
72
+ // Exit early when there is no change defined
73
+ if (changeIndex !== indexNotFound) {
74
+ return cbk(null, {existing_output_index: changeIndex});
75
+ }
76
+
77
+ // When there is no change output specified, add a change output
78
+ return cbk(null, {add: true});
79
+ }],
80
+
81
+ // Determine the fee setting for the funded PSBT
82
+ fee: ['validate', ({}, cbk) => {
83
+ // Exit early when the fee is directly specified
84
+ if (!!args.fee_tokens_per_vbyte) {
85
+ return cbk(null, {fee_tokens_per_vbyte: args.fee_tokens_per_vbyte});
86
+ }
87
+
88
+ // Exit early when the confirmation target is directly specified
89
+ if (!!args.target_confirmations) {
90
+ return cbk(null, {target_confirmations: args.target_confirmations});
91
+ }
92
+
93
+ // Use the default confirmations target when there's no preference
94
+ return cbk(null, {target_confirmations: defaultConfirmationTarget});
95
+ }],
96
+
97
+ // Construct the PSBT that is needed for coin select type funding
98
+ funding: ['validate', ({}, cbk) => {
99
+ const {psbt} = createPsbt({
100
+ outputs: args.outputs || [],
101
+ timelock: args.timelock,
102
+ utxos: (args.inputs || []).map(input => ({
103
+ id: input.transaction_id,
104
+ sequence: input.sequence,
105
+ vout: input.transaction_vout,
106
+ })),
107
+ version: args.version,
108
+ });
109
+
110
+ return cbk(null, hexAsBuffer(psbt));
111
+ }],
112
+
113
+ // Determine the minimum confirmations for UTXOs to select
114
+ minConfs: ['validate', ({}, cbk) => {
115
+ // Exit early when using unconfirmed UTXOs is explicitly specified
116
+ if (args.min_confirmations === unconfirmedConfirmationsCount) {
117
+ return cbk(null, unconfirmedConfirmationsCount);
118
+ }
119
+
120
+ return cbk(null, args.min_confirmations || undefined);
121
+ }],
122
+
123
+ // Create the funded PSBT using the coin select strategy
124
+ fund: [
125
+ 'change',
126
+ 'fee',
127
+ 'funding',
128
+ 'minConfs',
129
+ ({change, fee, funding, minConfs}, cbk) =>
130
+ {
131
+ return args.lnd[type][method]({
132
+ change_type: defaultChangeType,
133
+ coin_select: {
134
+ add: change.add,
135
+ psbt: funding,
136
+ existing_output_index: change.existing_output_index,
137
+ },
138
+ coin_selection_strategy: strategy(args.utxo_selection),
139
+ min_confs: minConfs,
140
+ sat_per_vbyte: fee.fee_tokens_per_vbyte,
141
+ spend_unconfirmed: minConfs === unconfirmedConfirmationsCount,
142
+ target_conf: fee.target_confirmations,
143
+ },
144
+ (err, res) => {
145
+ if (!!err && err.details === errorUnsupported) {
146
+ return cbk([501, 'CreateFundedPsbtMethodNotSupported']);
147
+ }
148
+
149
+ if (!!err) {
150
+ return cbk([503, 'UnexpectedErrorCreatingFundedPsbt', {err}]);
151
+ }
152
+
153
+ if (!res) {
154
+ return cbk([503, 'ExpectedResultWhenCreatingFundedPsbt']);
155
+ }
156
+
157
+ if (!isBuffer(res.funded_psbt)) {
158
+ return cbk([503, 'ExpectedFundedTransactionPsbtToBeCreated']);
159
+ }
160
+
161
+ return cbk(null, {psbt: bufferAsHex(res.funded_psbt)});
162
+ });
163
+ }],
164
+ },
165
+ returnResult({reject, resolve, of: 'fund'}, cbk));
166
+ });
167
+ };
@@ -0,0 +1,47 @@
1
+ import {
2
+ AuthenticatedLightningArgs,
3
+ AuthenticatedLightningMethod,
4
+ } from '../../typescript';
5
+
6
+ export type GetPendingSweepsArgs = AuthenticatedLightningArgs;
7
+
8
+ export interface Sweep {
9
+ /** Total Sweep Broadcast Attempts Count Number */
10
+ broadcasts_count: number;
11
+ /** Current Chain Fee Rate Tokens Per VByte Number */
12
+ current_fee_rate?: number;
13
+ /** Requested Chain Fee Rate Tokens per VByte Number */
14
+ initial_fee_rate?: number;
15
+ /** Requested Waiting For Batching Bool */
16
+ is_batching: boolean;
17
+ /** Maximum Total Fee Tokens Allowed Number */
18
+ max_fee?: number;
19
+ /** Targeted Maximum Confirmation Height Number */
20
+ max_height?: number;
21
+ /** Sweep Outpoint Tokens Value Number */
22
+ tokens: number;
23
+ /** Sweeping Outpoint Transaction Id Hex String */
24
+ transaction_id: string;
25
+ /** Sweeping Outpoint Transaction Output Index Number */
26
+ transaction_vout: number;
27
+ /** Outpoint Constraint Script Type String */
28
+ type: string;
29
+ }
30
+
31
+ export interface GetPendingSweepsResult {
32
+ sweeps: Sweep[];
33
+ }
34
+
35
+ /**
36
+ * Get pending self-transfer spends
37
+ *
38
+ * Requires `onchain:read` permission
39
+ *
40
+ * Requires LND built with `walletrpc` build tag
41
+ *
42
+ * This method is not supported in LND 0.17.5 or below
43
+ */
44
+ export const getPendingSweeps: AuthenticatedLightningMethod<
45
+ GetPendingSweepsArgs,
46
+ GetPendingSweepsResult
47
+ >;
@@ -15,6 +15,7 @@ export * from './get_chain_transactions';
15
15
  export * from './get_locked_utxos';
16
16
  export * from './get_master_public_keys';
17
17
  export * from './get_pending_chain_balance';
18
+ export * from './get_pending_sweeps';
18
19
  export * from './get_sweep_transactions';
19
20
  export * from './get_utxos';
20
21
  export * from './lock_utxo';
@@ -23,6 +24,7 @@ export * from './open_channels';
23
24
  export * from './partially_sign_psbt';
24
25
  export * from './prepare_for_channel_proposal';
25
26
  export * from './propose_channel';
27
+ export * from './request_batched_fee_increase';
26
28
  export * from './request_chain_fee_increase';
27
29
  export * from './send_to_chain_address';
28
30
  export * from './send_to_chain_addresses';
@@ -1,6 +1,7 @@
1
1
  const broadcastChainTransaction = require('./broadcast_chain_transaction');
2
2
  const cancelPendingChannel = require('./cancel_pending_channel');
3
3
  const closeChannel = require('./close_channel');
4
+ const createFundedPsbt = require('./create_funded_psbt');
4
5
  const deleteChainTransaction = require('./delete_chain_transaction');
5
6
  const fundPendingChannels = require('./fund_pending_channels');
6
7
  const fundPsbt = require('./fund_psbt');
@@ -44,6 +45,7 @@ module.exports = {
44
45
  broadcastChainTransaction,
45
46
  cancelPendingChannel,
46
47
  closeChannel,
48
+ createFundedPsbt,
47
49
  deleteChainTransaction,
48
50
  fundPendingChannels,
49
51
  fundPsbt,
@@ -0,0 +1,26 @@
1
+ import {
2
+ AuthenticatedLightningArgs,
3
+ AuthenticatedLightningMethod,
4
+ } from '../../typescript';
5
+
6
+ export type RequestBatchedFeeIncreaseArgs = AuthenticatedLightningArgs<{
7
+ /** Maximum Tokens to Pay Into Chain Fees Number */
8
+ max_fee?: number;
9
+ /** Maximum Height To Reach a Confirmation Number */
10
+ max_height?: number;
11
+ /** Unconfirmed UTXO Transaction Id Hex String */
12
+ transaction_id: string;
13
+ /** Unconfirmed UTXO Transaction Index Number */
14
+ transaction_vout: number;
15
+ }>;
16
+
17
+ /**
18
+ * Request batched CPFP fee bumping of an unconfirmed outpoint on a deadline
19
+ *
20
+ * Requires `onchain:write` permission
21
+ *
22
+ * Requires LND built with `walletrpc` build tag
23
+ *
24
+ * This method is unsupported on LND 0.17.5 and below
25
+ */
26
+ export const requestBatchedFeeIncrease: AuthenticatedLightningMethod<RequestBatchedFeeIncreaseArgs>;
package/package.json CHANGED
@@ -7,9 +7,9 @@
7
7
  "url": "https://github.com/alexbosworth/lightning/issues"
8
8
  },
9
9
  "dependencies": {
10
- "@grpc/grpc-js": "1.10.7",
10
+ "@grpc/grpc-js": "1.10.8",
11
11
  "@grpc/proto-loader": "0.7.13",
12
- "@types/node": "20.12.10",
12
+ "@types/node": "20.12.12",
13
13
  "@types/request": "2.48.12",
14
14
  "@types/ws": "8.5.10",
15
15
  "async": "3.2.5",
@@ -53,5 +53,5 @@
53
53
  "directory": "test/typescript"
54
54
  },
55
55
  "types": "index.d.ts",
56
- "version": "10.11.0"
56
+ "version": "10.12.0"
57
57
  }
@@ -163,6 +163,22 @@ const tests = [
163
163
  },
164
164
  description: 'A local channel policy is updated',
165
165
  },
166
+ {
167
+ args: {
168
+ inbound_base_discount_mtokens: '1',
169
+ lnd: makeLnd({
170
+ policy: {
171
+ base_fee_msat: '1000',
172
+ chan_point: undefined,
173
+ fee_rate: 0.000001,
174
+ global: true,
175
+ max_htlc_msat: undefined,
176
+ time_lock_delta: 144,
177
+ },
178
+ }),
179
+ description: 'Set a base discount',
180
+ },
181
+ },
166
182
  ];
167
183
 
168
184
  tests.forEach(({args, description, error, expected}) => {
@@ -0,0 +1,130 @@
1
+ const {deepStrictEqual} = require('node:assert').strict;
2
+ const {rejects} = require('node:assert').strict;
3
+ const test = require('node:test');
4
+
5
+ const {createFundedPsbt} = require('./../../../lnd_methods');
6
+
7
+ const psbt = '70736274ff01009a020000000258e87a21b56daf0c23be8e7070456c336f7cbaa5c8757924f545887bb2abdd750000000000ffffffff838d0427d0ec650a68aa46bb0b098aea4422c071b2ca78352a077959d07cea1d0100000000ffffffff0270aaf00800000000160014d85c2b71d0060b09c9886aeb815e50991dda124d00e1f5050000000016001400aea9a2e5f0f876a588df5546e8742d1d87008f000000000000000000';
8
+ const unsupported = {details: 'transaction template missing, need to specify either PSBT or raw TX template'};
9
+
10
+ const makeLnd = overrides => {
11
+ const res = {
12
+ change_output_index: 0,
13
+ funded_psbt: Buffer.from(psbt, 'hex'),
14
+ locked_utxos: [{
15
+ expiration: 1,
16
+ id: Buffer.alloc(32),
17
+ outpoint: {
18
+ output_index: 0,
19
+ txid_bytes: Buffer.from('75ddabb27b8845f5247975c8a5ba7c6f336c4570708ebe230caf6db5217ae858', 'hex').reverse(),
20
+ },
21
+ }],
22
+ };
23
+
24
+ Object.keys(overrides).forEach(k => res[k] = overrides[k]);
25
+
26
+ return {wallet: {fundPsbt: (args, cbk) => cbk(null, res)}};
27
+ };
28
+
29
+ const makeArgs = overrides => {
30
+ const args = {
31
+ lnd: makeLnd({}),
32
+ outputs: [{script: '00', tokens: 1}],
33
+ };
34
+
35
+ Object.keys(overrides).forEach(key => args[key] = overrides[key]);
36
+
37
+ return args;
38
+ };
39
+
40
+ const makeExpected = overrides => {
41
+ const expected = {
42
+ psbt: '70736274ff01009a020000000258e87a21b56daf0c23be8e7070456c336f7cbaa5c8757924f545887bb2abdd750000000000ffffffff838d0427d0ec650a68aa46bb0b098aea4422c071b2ca78352a077959d07cea1d0100000000ffffffff0270aaf00800000000160014d85c2b71d0060b09c9886aeb815e50991dda124d00e1f5050000000016001400aea9a2e5f0f876a588df5546e8742d1d87008f000000000000000000',
43
+ };
44
+
45
+ Object.keys(overrides).forEach(k => expected[k] = overrides[k]);
46
+
47
+ return expected;
48
+ };
49
+
50
+ const tests = [
51
+ {
52
+ args: makeArgs({lnd: undefined}),
53
+ description: 'An LND object is required',
54
+ error: [400, 'ExpectedAuthenticatedLndToCreateFundedPsbt'],
55
+ },
56
+ {
57
+ args: makeArgs({lnd: {wallet: {fundPsbt: ({}, cbk) => cbk(unsupported)}}}),
58
+ description: 'Unsupported error is passed back',
59
+ error: [501, 'CreateFundedPsbtMethodNotSupported'],
60
+ },
61
+ {
62
+ args: makeArgs({lnd: {wallet: {fundPsbt: ({}, cbk) => cbk('err')}}}),
63
+ description: 'Errors funding are passed back',
64
+ error: [503, 'UnexpectedErrorCreatingFundedPsbt', {err: 'err'}],
65
+ },
66
+ {
67
+ args: makeArgs({lnd: {wallet: {fundPsbt: ({}, cbk) => cbk()}}}),
68
+ description: 'A response is expected',
69
+ error: [503, 'ExpectedResultWhenCreatingFundedPsbt'],
70
+ },
71
+ {
72
+ args: makeArgs({lnd: makeLnd({funded_psbt: undefined})}),
73
+ description: 'A funded PSBT is expected in the response',
74
+ error: [503, 'ExpectedFundedTransactionPsbtToBeCreated'],
75
+ },
76
+ {
77
+ args: makeArgs({}),
78
+ description: 'PSBT funding is executed',
79
+ expected: makeExpected({}),
80
+ },
81
+ {
82
+ args: makeArgs({min_confirmations: 0}),
83
+ description: 'PSBT funding is executed with min confs specified',
84
+ expected: makeExpected({}),
85
+ },
86
+ {
87
+ args: makeArgs({fee_tokens_per_vbyte: 1, outputs: undefined}),
88
+ description: 'PSBT funding can specify fee rate',
89
+ expected: makeExpected({}),
90
+ },
91
+ {
92
+ args: makeArgs({target_confirmations: 1}),
93
+ description: 'PSBT funding can specify conf target',
94
+ expected: makeExpected({}),
95
+ },
96
+ {
97
+ args: makeArgs({
98
+ inputs: [{
99
+ transaction_id: Buffer.alloc(32).toString('hex'),
100
+ transaction_vout: 0,
101
+ }],
102
+ }),
103
+ description: 'Inputs can be specified',
104
+ expected: makeExpected({}),
105
+ },
106
+ {
107
+ args: makeArgs({outputs: [{is_change: true, script: '00', tokens: 1}]}),
108
+ description: 'Outputs can be specified',
109
+ expected: makeExpected({}),
110
+ },
111
+ {
112
+ args: makeArgs({utxo_selection: 'largest'}),
113
+ description: 'PSBT funding can select largest coins',
114
+ expected: makeExpected({}),
115
+ },
116
+ ];
117
+
118
+ tests.forEach(({args, description, error, expected}) => {
119
+ return test(description, async () => {
120
+ if (!!error) {
121
+ await rejects(createFundedPsbt(args), error, 'Got error');
122
+ } else {
123
+ const got = await createFundedPsbt(args);
124
+
125
+ deepStrictEqual(got, expected, 'Got expected result');
126
+ }
127
+
128
+ return;
129
+ });
130
+ });
@@ -19,13 +19,13 @@ export type LightningError<TError = {err: Error}> = TError extends undefined
19
19
 
20
20
  export type LightningCallback<TResult = void, TErrorDetails = any> = (
21
21
  error: LightningError<TErrorDetails> | undefined | null,
22
- result: TResult extends void ? undefined : TResult
22
+ result: TResult extends void ? undefined : TResult,
23
23
  ) => void;
24
24
 
25
25
  export type LightningMethod<
26
26
  TArgs = EmptyObject,
27
27
  TResult = void,
28
- TErrorDetails = any
28
+ TErrorDetails = any,
29
29
  > = {
30
30
  (args: TArgs): Promise<TResult>;
31
31
  (args: TArgs, callback: LightningCallback<TResult, TErrorDetails>): void;
@@ -34,21 +34,21 @@ export type LightningMethod<
34
34
  export type AuthenticatedLightningMethod<
35
35
  TArgs extends {lnd: AuthenticatedLnd} = {lnd: AuthenticatedLnd},
36
36
  TResult = void,
37
- TErrorDetails = any
37
+ TErrorDetails = any,
38
38
  > = LightningMethod<TArgs, TResult, TErrorDetails>;
39
39
 
40
40
  export type UnauthenticatedLightningMethod<
41
41
  TArgs extends {lnd: UnauthenticatedLnd} = {lnd: UnauthenticatedLnd},
42
42
  TResult = void,
43
- TErrorDetails = any
43
+ TErrorDetails = any,
44
44
  > = LightningMethod<TArgs, TResult, TErrorDetails>;
45
45
 
46
46
  export type AuthenticatedLightningSubscription<
47
- TArgs extends {lnd: AuthenticatedLnd} = {lnd: AuthenticatedLnd}
47
+ TArgs extends {lnd: AuthenticatedLnd} = {lnd: AuthenticatedLnd},
48
48
  > = (args: TArgs) => events.EventEmitter;
49
49
 
50
50
  export type UnauthenticatedLightningSubscription<
51
- TArgs extends {lnd: UnauthenticatedLnd} = {lnd: UnauthenticatedLnd}
51
+ TArgs extends {lnd: UnauthenticatedLnd} = {lnd: UnauthenticatedLnd},
52
52
  > = (args: TArgs) => events.EventEmitter;
53
53
 
54
54
  type CommonStatus = 'IN_FLIGHT' | 'SUCCEEDED' | 'FAILED';
@@ -113,10 +113,41 @@ export type RouteNode = {
113
113
  fee_rate?: number;
114
114
  /** Forward Edge Public Key Hex */
115
115
  public_key: string;
116
- }
116
+ };
117
+
118
+ export type Route = RouteNode[];
117
119
 
118
- export type Route = RouteNode[]
120
+ export type Routes = Route[];
119
121
 
120
- export type Routes = Route[]
122
+ export type UtxoSelection = 'largest' | 'random';
121
123
 
122
- export type UtxoSelection = "largest" | "random";
124
+ export interface ChannelPolicy {
125
+ /** Base Fee Millitokens */
126
+ base_fee_mtokens?: string;
127
+ /** Locktime Delta */
128
+ cltv_delta?: number;
129
+ /** Fees Charged Per Million Millitokens */
130
+ fee_rate?: number;
131
+ /**
132
+ * Source Based Base Fee Reduction String
133
+ *
134
+ * Not supported on LND 0.17.5 and below
135
+ */
136
+ inbound_base_discount_mtokens?: string;
137
+ /**
138
+ * Source Based Per Million Rate Reduction Number
139
+ *
140
+ * Not supported on LND 0.17.5 and below
141
+ */
142
+ inbound_rate_discount?: number;
143
+ /** Channel Is Disabled */
144
+ is_disabled?: boolean;
145
+ /** Maximum HTLC Millitokens Value */
146
+ max_htlc_mtokens?: string;
147
+ /** Minimum HTLC Millitokens Value */
148
+ min_htlc_mtokens?: string;
149
+ /** Node Public Key */
150
+ public_key: string;
151
+ /** Policy Last Updated At ISO 8601 Date */
152
+ updated_at?: string;
153
+ }