lightning 10.9.1 → 10.10.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,11 @@
1
1
  # Versions
2
2
 
3
- ## 10.9.1
3
+ ## 10.10.0
4
+
5
+ - `getPendingSweeps`: Add method to get the list of pending outpoints to sweep
6
+ - `requestBatchedFeeIncrease`: Add method to batch a CPFP sweep of an outpoint
7
+
8
+ ## 10.9.2
4
9
 
5
10
  - Add support for LND v0.17.5-beta
6
11
 
package/README.md CHANGED
@@ -220,6 +220,8 @@ variables set:
220
220
  details of opening or closing channels.
221
221
  - [getPendingPayments](https://github.com/alexbosworth/ln-service#getpendingpayments): List out
222
222
  past pending payments.
223
+ - [getPendingSweeps](https://github.com/alexbosworth/ln-service#getpendingsweeps):
224
+ List out queued outpoints that are being swept
223
225
  - [getPublicKey](https://github.com/alexbosworth/ln-service#getpublickey): Derive a public key at
224
226
  a given index.
225
227
  - [getRouteConfidence](https://github.com/alexbosworth/ln-service#getrouteconfidence): Check a
@@ -277,6 +279,8 @@ variables set:
277
279
  Remove a LN p2p network socket from the node advertisement
278
280
  - [removePeer](https://github.com/alexbosworth/ln-service#removepeer): Disconnect from a
279
281
  connected peer.
282
+ - [requestBatchedFeeIncrease](https://github.com/alexbosworth/ln-service#requestbatchedfeeincrease):
283
+ Ask for a batched CPFP chain fee rate increase on a pending confirm UTXO
280
284
  - [requestChainFeeIncrease](https://github.com/alexbosworth/ln-service#requestchainfeeincrease):
281
285
  Ask for a CPFP chain fee rate increase on a pending confirm UTXO.
282
286
  - [revokeAccess](https://github.com/alexbosworth/ln-service#revokeaccess): Remove the access
@@ -4231,6 +4231,10 @@ message DeleteAllPaymentsRequest {
4231
4231
  Only delete failed HTLCs from payments, not the payment itself.
4232
4232
  */
4233
4233
  bool failed_htlcs_only = 2;
4234
+
4235
+ // Delete all payments. NOTE: Using this option requires careful
4236
+ // consideration as it is a destructive operation.
4237
+ bool all_payments = 3;
4234
4238
  }
4235
4239
 
4236
4240
  message DeletePaymentResponse {
@@ -4307,6 +4311,8 @@ enum FeatureBit {
4307
4311
  ANCHORS_OPT = 21;
4308
4312
  ANCHORS_ZERO_FEE_HTLC_REQ = 22;
4309
4313
  ANCHORS_ZERO_FEE_HTLC_OPT = 23;
4314
+ ROUTE_BLINDING_REQUIRED = 24;
4315
+ ROUTE_BLINDING_OPTIONAL = 25;
4310
4316
  AMP_REQ = 30;
4311
4317
  AMP_OPT = 31;
4312
4318
  }
@@ -242,31 +242,34 @@ service WalletKit {
242
242
  rpc PendingSweeps (PendingSweepsRequest) returns (PendingSweepsResponse);
243
243
 
244
244
  /* lncli: `wallet bumpfee`
245
- BumpFee bumps the fee of an arbitrary input within a transaction. This RPC
246
- takes a different approach than bitcoind's bumpfee command. lnd has a
247
- central batching engine in which inputs with similar fee rates are batched
248
- together to save on transaction fees. Due to this, we cannot rely on
249
- bumping the fee on a specific transaction, since transactions can change at
250
- any point with the addition of new inputs. The list of inputs that
251
- currently exist within lnd's central batching engine can be retrieved
252
- through the PendingSweeps RPC.
253
-
254
- When bumping the fee of an input that currently exists within lnd's central
255
- batching engine, a higher fee transaction will be created that replaces the
256
- lower fee transaction through the Replace-By-Fee (RBF) policy. If it
245
+ BumpFee is an endpoint that allows users to interact with lnd's sweeper
246
+ directly. It takes an outpoint from an unconfirmed transaction and sends it
247
+ to the sweeper for potential fee bumping. Depending on whether the outpoint
248
+ has been registered in the sweeper (an existing input, e.g., an anchor
249
+ output) or not (a new input, e.g., an unconfirmed wallet utxo), this will
250
+ either be an RBF or CPFP attempt.
251
+
252
+ When receiving an input, lnd’s sweeper needs to understand its time
253
+ sensitivity to make economical fee bumps - internally a fee function is
254
+ created using the deadline and budget to guide the process. When the
255
+ deadline is approaching, the fee function will increase the fee rate and
256
+ perform an RBF.
257
+
258
+ When a force close happens, all the outputs from the force closing
259
+ transaction will be registered in the sweeper. The sweeper will then handle
260
+ the creation, publish, and fee bumping of the sweeping transactions.
261
+ Everytime a new block comes in, unless the sweeping transaction is
262
+ confirmed, an RBF is attempted. To interfere with this automatic process,
263
+ users can use BumpFee to specify customized fee rate, budget, deadline, and
264
+ whether the sweep should happen immediately. It's recommended to call
265
+ `ListSweeps` to understand the shape of the existing sweeping transaction
266
+ first - depending on the number of inputs in this transaction, the RBF
267
+ requirements can be quite different.
257
268
 
258
269
  This RPC also serves useful when wanting to perform a Child-Pays-For-Parent
259
270
  (CPFP), where the child transaction pays for its parent's fee. This can be
260
271
  done by specifying an outpoint within the low fee transaction that is under
261
272
  the control of the wallet.
262
-
263
- The fee preference can be expressed either as a specific fee rate or a delta
264
- of blocks in which the output should be swept on-chain within. If a fee
265
- preference is not explicitly specified, then an error is returned.
266
-
267
- Note that this RPC currently doesn't perform any validation checks on the
268
- fee preference being provided. For now, the responsibility of ensuring that
269
- the new fee preference is sufficient is delegated to the user.
270
273
  */
271
274
  rpc BumpFee (BumpFeeRequest) returns (BumpFeeResponse);
272
275
 
@@ -280,7 +283,7 @@ service WalletKit {
280
283
  /* lncli: `wallet labeltx`
281
284
  LabelTransaction adds a label to a transaction. If the transaction already
282
285
  has a label the call will fail unless the overwrite bool is set. This will
283
- overwrite the exiting transaction label. Labels must not be empty, and
286
+ overwrite the existing transaction label. Labels must not be empty, and
284
287
  cannot exceed 500 characters.
285
288
  */
286
289
  rpc LabelTransaction (LabelTransactionRequest)
@@ -1105,33 +1108,56 @@ message PendingSweep {
1105
1108
  uint32 broadcast_attempts = 5;
1106
1109
 
1107
1110
  /*
1111
+ Deprecated.
1108
1112
  The next height of the chain at which we'll attempt to broadcast the
1109
1113
  sweep transaction of the output.
1110
1114
  */
1111
- uint32 next_broadcast_height = 6;
1115
+ uint32 next_broadcast_height = 6 [deprecated = true];
1112
1116
 
1113
- // The requested confirmation target for this output.
1114
- uint32 requested_conf_target = 8;
1117
+ /*
1118
+ Deprecated, use immediate.
1119
+ Whether this input must be force-swept. This means that it is swept
1120
+ immediately.
1121
+ */
1122
+ bool force = 7 [deprecated = true];
1123
+
1124
+ /*
1125
+ Deprecated, use deadline.
1126
+ The requested confirmation target for this output, which is the deadline
1127
+ used by the sweeper.
1128
+ */
1129
+ uint32 requested_conf_target = 8 [deprecated = true];
1115
1130
 
1116
1131
  // Deprecated, use requested_sat_per_vbyte.
1117
1132
  // The requested fee rate, expressed in sat/vbyte, for this output.
1118
1133
  uint32 requested_sat_per_byte = 9 [deprecated = true];
1119
1134
 
1120
1135
  /*
1121
- The fee rate we'll use to sweep the output, expressed in sat/vbyte. The fee
1122
- rate is only determined once a sweeping transaction for the output is
1123
- created, so it's possible for this to be 0 before this.
1136
+ The current fee rate we'll use to sweep the output, expressed in sat/vbyte.
1137
+ The fee rate is only determined once a sweeping transaction for the output
1138
+ is created, so it's possible for this to be 0 before this.
1124
1139
  */
1125
1140
  uint64 sat_per_vbyte = 10;
1126
1141
 
1127
- // The requested fee rate, expressed in sat/vbyte, for this output.
1142
+ // The requested starting fee rate, expressed in sat/vbyte, for this
1143
+ // output. When not requested, this field will be 0.
1128
1144
  uint64 requested_sat_per_vbyte = 11;
1129
1145
 
1130
1146
  /*
1131
- Whether this input must be force-swept. This means that it is swept even
1132
- if it has a negative yield.
1147
+ Whether this input will be swept immediately.
1133
1148
  */
1134
- bool force = 7;
1149
+ bool immediate = 12;
1150
+
1151
+ /*
1152
+ The budget for this sweep, expressed in satoshis. This is the maximum amount
1153
+ that can be spent as fees to sweep this output.
1154
+ */
1155
+ uint64 budget = 13;
1156
+
1157
+ /*
1158
+ The deadline height used for this output when perform fee bumping.
1159
+ */
1160
+ uint32 deadline_height = 14;
1135
1161
  }
1136
1162
 
1137
1163
  message PendingSweepsRequest {
@@ -1148,7 +1174,9 @@ message BumpFeeRequest {
1148
1174
  // The input we're attempting to bump the fee of.
1149
1175
  lnrpc.OutPoint outpoint = 1;
1150
1176
 
1151
- // The target number of blocks that the input should be spent within.
1177
+ // Optional. The deadline in number of blocks that the input should be spent
1178
+ // within. When not set, for new inputs, the default value (1008) is used;
1179
+ // for existing inputs, their current values will be retained.
1152
1180
  uint32 target_conf = 2;
1153
1181
 
1154
1182
  /*
@@ -1159,16 +1187,35 @@ message BumpFeeRequest {
1159
1187
  uint32 sat_per_byte = 3 [deprecated = true];
1160
1188
 
1161
1189
  /*
1162
- Whether this input must be force-swept. This means that it is swept even
1163
- if it has a negative yield.
1190
+ Deprecated, use immediate.
1191
+ Whether this input must be force-swept. This means that it is swept
1192
+ immediately.
1164
1193
  */
1165
- bool force = 4;
1194
+ bool force = 4 [deprecated = true];
1166
1195
 
1167
1196
  /*
1168
- The fee rate, expressed in sat/vbyte, that should be used to spend the input
1169
- with.
1197
+ Optional. The starting fee rate, expressed in sat/vbyte, that will be used
1198
+ to spend the input with initially. This value will be used by the sweeper's
1199
+ fee function as its starting fee rate. When not set, the sweeper will use
1200
+ the estimated fee rate using the `target_conf` as the starting fee rate.
1170
1201
  */
1171
1202
  uint64 sat_per_vbyte = 5;
1203
+
1204
+ /*
1205
+ Optional. Whether this input will be swept immediately. When set to true,
1206
+ the sweeper will sweep this input without waiting for the next batch.
1207
+ */
1208
+ bool immediate = 6;
1209
+
1210
+ /*
1211
+ Optional. The max amount in sats that can be used as the fees. Setting this
1212
+ value greater than the input's value may result in CPFP - one or more wallet
1213
+ utxos will be used to pay the fees specified by the budget. If not set, for
1214
+ new inputs, by default 50% of the input's value will be treated as the
1215
+ budget for fee bumping; for existing inputs, their current budgets will be
1216
+ retained.
1217
+ */
1218
+ uint64 budget = 7;
1172
1219
  }
1173
1220
 
1174
1221
  message BumpFeeResponse {
package/index.js CHANGED
@@ -71,6 +71,7 @@ const {getPeers} = require('./lnd_methods');
71
71
  const {getPendingChainBalance} = require('./lnd_methods');
72
72
  const {getPendingChannels} = require('./lnd_methods');
73
73
  const {getPendingPayments} = require('./lnd_methods');
74
+ const {getPendingSweeps} = require('./lnd_methods');
74
75
  const {getPublicKey} = require('./lnd_methods');
75
76
  const {getRouteConfidence} = require('./lnd_methods');
76
77
  const {getRouteThroughHops} = require('./lnd_methods');
@@ -100,6 +101,7 @@ const {recoverFundsFromChannels} = require('./lnd_methods');
100
101
  const {removeAdvertisedFeature} = require('./lnd_methods');
101
102
  const {removeExternalSocket} = require('./lnd_methods');
102
103
  const {removePeer} = require('./lnd_methods');
104
+ const {requestBatchedFeeIncrease} = require('./lnd_methods');
103
105
  const {requestChainFeeIncrease} = require('./lnd_methods');
104
106
  const {revokeAccess} = require('./lnd_methods');
105
107
  const {sendMessageToPeer} = require('./lnd_methods');
@@ -228,6 +230,7 @@ module.exports = {
228
230
  getPendingChainBalance,
229
231
  getPendingChannels,
230
232
  getPendingPayments,
233
+ getPendingSweeps,
231
234
  getPublicKey,
232
235
  getRouteConfidence,
233
236
  getRouteThroughHops,
@@ -257,6 +260,7 @@ module.exports = {
257
260
  removeAdvertisedFeature,
258
261
  removeExternalSocket,
259
262
  removePeer,
263
+ requestBatchedFeeIncrease,
260
264
  requestChainFeeIncrease,
261
265
  revokeAccess,
262
266
  sendMessageToPeer,
@@ -70,6 +70,7 @@ const {getPeers} = require('./peers');
70
70
  const {getPendingChainBalance} = require('./onchain');
71
71
  const {getPendingChannels} = require('./offchain');
72
72
  const {getPendingPayments} = require('./offchain');
73
+ const {getPendingSweeps} = require('./onchain');
73
74
  const {getPublicKey} = require('./address');
74
75
  const {getRouteConfidence} = require('./generic');
75
76
  const {getRouteThroughHops} = require('./offchain');
@@ -100,6 +101,7 @@ const {recoverFundsFromChannels} = require('./offchain');
100
101
  const {removeAdvertisedFeature} = require('./peers');
101
102
  const {removeExternalSocket} = require('./peers');
102
103
  const {removePeer} = require('./peers');
104
+ const {requestBatchedFeeIncrease} = require('./onchain');
103
105
  const {requestChainFeeIncrease} = require('./onchain');
104
106
  const {revokeAccess} = require('./macaroon');
105
107
  const {sendMessageToPeer} = require('./offchain');
@@ -226,6 +228,7 @@ module.exports = {
226
228
  getPendingChainBalance,
227
229
  getPendingChannels,
228
230
  getPendingPayments,
231
+ getPendingSweeps,
229
232
  getPublicKey,
230
233
  getRouteConfidence,
231
234
  getRouteThroughHops,
@@ -256,6 +259,7 @@ module.exports = {
256
259
  removeAdvertisedFeature,
257
260
  removeExternalSocket,
258
261
  removePeer,
262
+ requestBatchedFeeIncrease,
259
263
  requestChainFeeIncrease,
260
264
  revokeAccess,
261
265
  sendMessageToPeer,
@@ -280,6 +280,10 @@
280
280
  "method": "ListPayments",
281
281
  "type": "default"
282
282
  },
283
+ "getPendingSweeps": {
284
+ "method": "PendingSweeps",
285
+ "type": "wallet"
286
+ },
283
287
  "getPublicKey": {
284
288
  "methods": ["DeriveKey", "DeriveNextKey"],
285
289
  "type": "wallet"
@@ -400,6 +404,11 @@
400
404
  "method": "DisconnectPeer",
401
405
  "type": "default"
402
406
  },
407
+ "requestBatchedFeeIncrease": {
408
+ "depends_on": ["getHeight"],
409
+ "method": "BumpFee",
410
+ "type": "wallet"
411
+ },
403
412
  "requestChainFeeIncrease": {
404
413
  "method": "BumpFee",
405
414
  "type": "wallet"
@@ -30,7 +30,7 @@ module.exports = ({lnd}, cbk) => {
30
30
 
31
31
  // Delete all payments
32
32
  deletePayments: ['validate', ({}, cbk) => {
33
- return lnd[type][method]({}, err => {
33
+ return lnd[type][method]({all_payments: true}, err => {
34
34
  if (!!err) {
35
35
  return cbk([503, 'UnexpectedErrorDeletingAllPayments', {err}]);
36
36
  }
@@ -1,6 +1,7 @@
1
1
  import {
2
2
  AuthenticatedLightningArgs,
3
3
  AuthenticatedLightningMethod,
4
+ UtxoSelection,
4
5
  } from '../../typescript';
5
6
  import {MergeExclusive} from 'type-fest';
6
7
 
@@ -57,6 +58,8 @@ export type FundPsbtResult = {
57
58
  }[];
58
59
  /** Unsigned PSBT Hex */
59
60
  psbt: string;
61
+ /** Select UTXOs Using Method String */
62
+ utxo_selection?: UtxoSelection;
60
63
  };
61
64
 
62
65
  /**
@@ -73,6 +76,8 @@ export type FundPsbtResult = {
73
76
  * This method is not supported in LND 0.11.1 and below
74
77
  *
75
78
  * Specifying 0 for `min_confirmations` is not supported in LND 0.13.0 and below
79
+ *
80
+ * `utxo_selection` is not supported in LND 0.17.5 and below
76
81
  */
77
82
  export const fundPsbt: AuthenticatedLightningMethod<
78
83
  FundPsbtArgs,
@@ -1,6 +1,7 @@
1
1
  import {
2
2
  AuthenticatedLightningArgs,
3
3
  AuthenticatedLightningMethod,
4
+ UtxoSelection,
4
5
  } from '../../typescript';
5
6
 
6
7
  export type GetChainFeeEstimateArgs = AuthenticatedLightningArgs<{
@@ -14,6 +15,8 @@ export type GetChainFeeEstimateArgs = AuthenticatedLightningArgs<{
14
15
  target_confirmations?: number;
15
16
  /** Minimum Confirmations for UTXO Selection */
16
17
  utxo_confirmations?: number;
18
+ /** Select UTXOs Using Method String */
19
+ utxo_selection?: UtxoSelection;
17
20
  }>;
18
21
 
19
22
  export type GetChainFeeEstimateResult = {
@@ -27,6 +30,8 @@ export type GetChainFeeEstimateResult = {
27
30
  * Get a chain fee estimate for a prospective chain send
28
31
  *
29
32
  * Requires `onchain:read` permission
33
+ *
34
+ * `utxo_selection` is not supported in LND 0.17.5 and below
30
35
  */
31
36
  export const getChainFeeEstimate: AuthenticatedLightningMethod<
32
37
  GetChainFeeEstimateArgs,
@@ -0,0 +1,81 @@
1
+ const asyncAuto = require('async/auto');
2
+ const {returnResult} = require('asyncjs-util');
3
+ const {Transaction} = require('bitcoinjs-lib');
4
+
5
+ const {isLnd} = require('./../../lnd_requests');
6
+ const {rpcSweepAsSweep} = require('./../../lnd_responses');
7
+
8
+ const {fromHex} = Transaction;
9
+ const {isArray} = Array;
10
+ const method = 'pendingSweeps';
11
+ const notSupportedError = 'unknown service walletrpc.WalletKit';
12
+ const type = 'wallet';
13
+
14
+ /** Get pending self-transfer spends
15
+
16
+ Requires `onchain:read` permission
17
+
18
+ Requires LND built with `walletrpc` build tag
19
+
20
+ This method is not supported in LND 0.17.5 or below
21
+
22
+ {
23
+ lnd: <Authenticated LND API Object>
24
+ }
25
+
26
+ @returns via cbk or Promise
27
+ {
28
+ sweeps: [{
29
+ broadcasts_count: <Total Sweep Broadcast Attempts Count Number>
30
+ [current_fee_rate]: <Current Chain Fee Rate Tokens Per VByte Number>
31
+ [initial_fee_rate]: <Requested Chain Fee Rate Tokens per VByte Number>
32
+ is_batching: <Requested Waiting For Batching Bool>
33
+ [max_fee]: <Maximum Total Fee Tokens Allowed Number>
34
+ [max_height]: <Targeted Maximum Confirmation Height Number>
35
+ tokens: <Sweep Outpoint Tokens Value Number>
36
+ transaction_id: <Sweeping Outpoint Transaction Id Hex String>
37
+ transaction_vout: <Sweeping Outpoint Transaction Output Index Number>
38
+ type: <Outpoint Constraint Script Type String>
39
+ }]
40
+ }
41
+ */
42
+ module.exports = ({lnd}, cbk) => {
43
+ return new Promise((resolve, reject) => {
44
+ return asyncAuto({
45
+ // Check arguments
46
+ validate: cbk => {
47
+ if (!isLnd({lnd, method, type})) {
48
+ return cbk([400, 'ExpectedLndToGetPendingSweeps']);
49
+ }
50
+
51
+ return cbk();
52
+ },
53
+
54
+ // Get sweep transaction ids
55
+ getSweeps: ['validate', ({}, cbk) => {
56
+ return lnd[type][method]({}, (err, res) => {
57
+ if (!!err) {
58
+ return cbk([503, 'UnexpectedGetPendingSweepsError', {err}]);
59
+ }
60
+
61
+ if (!res) {
62
+ return cbk([503, 'ExpectedResponseToGetPendingSweepsRequest']);
63
+ }
64
+
65
+ if (!isArray(res.pending_sweeps)) {
66
+ return cbk([503, 'ExpectedArrayOfPendingSweepsInSweepsResponse']);
67
+ }
68
+
69
+ try {
70
+ const sweeps = res.pending_sweeps.map(rpcSweepAsSweep);
71
+
72
+ return cbk(null, {sweeps});
73
+ } catch (err) {
74
+ return cbk([503, err.message]);
75
+ }
76
+ });
77
+ }],
78
+ },
79
+ returnResult({reject, resolve, of: 'getSweeps'}, cbk));
80
+ });
81
+ };
@@ -15,6 +15,7 @@ const getChainTransactions = require('./get_chain_transactions');
15
15
  const getLockedUtxos = require('./get_locked_utxos');
16
16
  const getMasterPublicKeys = require('./get_master_public_keys');
17
17
  const getPendingChainBalance = require('./get_pending_chain_balance');
18
+ const getPendingSweeps = require('./get_pending_sweeps');
18
19
  const getSweepTransactions = require('./get_sweep_transactions');
19
20
  const getUtxos = require('./get_utxos');
20
21
  const lockUtxo = require('./lock_utxo');
@@ -23,6 +24,7 @@ const openChannels = require('./open_channels');
23
24
  const partiallySignPsbt = require('./partially_sign_psbt');
24
25
  const prepareForChannelProposal = require('./prepare_for_channel_proposal');
25
26
  const proposeChannel = require('./propose_channel');
27
+ const requestBatchedFeeIncrease = require('./request_batched_fee_increase');
26
28
  const requestChainFeeIncrease = require('./request_chain_fee_increase');
27
29
  const sendToChainAddress = require('./send_to_chain_address');
28
30
  const sendToChainAddresses = require('./send_to_chain_addresses');
@@ -56,6 +58,7 @@ module.exports = {
56
58
  getLockedUtxos,
57
59
  getMasterPublicKeys,
58
60
  getPendingChainBalance,
61
+ getPendingSweeps,
59
62
  getSweepTransactions,
60
63
  getUtxos,
61
64
  lockUtxo,
@@ -64,6 +67,7 @@ module.exports = {
64
67
  partiallySignPsbt,
65
68
  prepareForChannelProposal,
66
69
  proposeChannel,
70
+ requestBatchedFeeIncrease,
67
71
  requestChainFeeIncrease,
68
72
  sendToChainAddress,
69
73
  sendToChainAddresses,
@@ -0,0 +1,108 @@
1
+ const asyncAuto = require('async/auto');
2
+ const {returnResult} = require('asyncjs-util');
3
+
4
+ const {getHeight} = require('./../generic');
5
+ const {isLnd} = require('./../../lnd_requests');
6
+
7
+ const defaultTargetConfirmations = 1008;
8
+ const isHash = n => /^[0-9A-F]{64}$/i.test(n);
9
+ const isNumber = n => !isNaN(n);
10
+ const messageExternalUtxo = 'the passed output does not belong to the wallet';
11
+ const method = 'bumpFee';
12
+ const positive = number => number > 0 ? number : 1;
13
+ const type = 'wallet';
14
+
15
+ /** Request batched CPFP fee bumping of an unconfirmed outpoint on a deadline
16
+
17
+ Requires `onchain:write` permission
18
+
19
+ Requires LND built with `walletrpc` build tag
20
+
21
+ This method is unsupported on LND 0.17.5 and below
22
+
23
+ {
24
+ lnd: <Authenticated LND API Object>
25
+ [max_fee]: <Maximum Tokens to Pay Into Chain Fees Number>
26
+ [max_height]: <Maximum Height To Reach a Confirmation Number>
27
+ transaction_id: <Unconfirmed UTXO Transaction Id Hex String>
28
+ transaction_vout: <Unconfirmed UTXO Transaction Index Number>
29
+ }
30
+
31
+ @returns via cbk or Promise
32
+ */
33
+ module.exports = (args, cbk) => {
34
+ return new Promise((resolve, reject) => {
35
+ return asyncAuto({
36
+ // Check arguments
37
+ validate: cbk => {
38
+ if (!isLnd({method, type, lnd: args.lnd})) {
39
+ return cbk([400, 'ExpectedLndToRequestChainFeeIncrease']);
40
+ }
41
+
42
+ if (!isHash(args.transaction_id)) {
43
+ return cbk([400, 'ExpectedTransactionIdToRequestChainFeeIncrease']);
44
+ }
45
+
46
+ if (!isNumber(args.transaction_vout)) {
47
+ return cbk([400, 'ExpectedTransactionOutputIndexToRequestFeeBump']);
48
+ }
49
+
50
+ return cbk();
51
+ },
52
+
53
+ // Get the current height to adjust max height to a conf target delta
54
+ getHeight: ['validate', ({}, cbk) => {
55
+ // Exit early when there is no max height specified
56
+ if (!args.max_height) {
57
+ return cbk();
58
+ }
59
+
60
+ return getHeight({lnd: args.lnd}, cbk);
61
+ }],
62
+
63
+ // Determine the confirmation target
64
+ targetConf: ['getHeight', ({getHeight}, cbk) => {
65
+ // Exit early when there is no max height
66
+ if (!getHeight) {
67
+ return cbk(null, defaultTargetConfirmations);
68
+ }
69
+
70
+ const currentBlockHeight = getHeight.current_block_height;
71
+
72
+ return cbk(null, positive(args.max_height - currentBlockHeight));
73
+ }],
74
+
75
+ // Make the request to submit the input to the batch sweeper
76
+ request: ['targetConf', ({targetConf}, cbk) => {
77
+ return args.lnd[type][method]({
78
+ budget: args.max_fee,
79
+ outpoint: {
80
+ output_index: args.transaction_vout,
81
+ txid_str: args.transaction_id,
82
+ },
83
+ target_conf: targetConf,
84
+ },
85
+ (err, res) => {
86
+ if (!!err && err.details === messageExternalUtxo) {
87
+ return cbk([404, 'SpecifiedUtxoNotFoundInWalletUtxos']);
88
+ }
89
+
90
+ if (!!err) {
91
+ return cbk([503, 'UnexpectedErrorRequestingBatchIncrease', {err}]);
92
+ }
93
+
94
+ if (!res) {
95
+ return cbk([503, 'ExpectedResponseToBatchedFeeIncreaseRequest']);
96
+ }
97
+
98
+ if (res.status === undefined) {
99
+ return cbk([503, 'ExpectedStatusOfBatchedFeeIncrease']);
100
+ }
101
+
102
+ return cbk();
103
+ });
104
+ }],
105
+ },
106
+ returnResult({reject, resolve}, cbk));
107
+ });
108
+ };
@@ -69,6 +69,7 @@ module.exports = (args, cbk) => {
69
69
  request: ['feeRate', ({feeRate}, cbk) => {
70
70
  return args.lnd[type][method]({
71
71
  force: true,
72
+ immediate: true,
72
73
  outpoint: {
73
74
  output_index: args.transaction_vout,
74
75
  txid_str: args.transaction_id,
@@ -3,6 +3,7 @@ import {
3
3
  AuthenticatedLightningArgs,
4
4
  AuthenticatedLightningMethod,
5
5
  LightningError,
6
+ UtxoSelection,
6
7
  } from '../../typescript';
7
8
  import {MergeExclusive} from 'type-fest';
8
9
 
@@ -38,6 +39,8 @@ export type SendToChainAddressArgs = AuthenticatedLightningArgs<
38
39
  target_confirmations?: number;
39
40
  /** Minimum Confirmations for UTXO Selection */
40
41
  utxo_confirmations?: number;
42
+ /** Select UTXOs Using Method String */
43
+ utxo_selection?: UtxoSelection;
41
44
  } & ExpectedNoTokensSpecifiedWhenSendingAllFunds &
42
45
  ExpectedLogFunctionForChainSendSocketAnnounce
43
46
  >;
@@ -61,6 +64,8 @@ export type SendToChainAddressResult = {
61
64
  * Requires `onchain:write` permission
62
65
  *
63
66
  * `utxo_confirmations` is not supported on LND 0.11.1 or below
67
+ *
68
+ * `utxo_selection` is not supported in LND 0.17.5 and below
64
69
  */
65
70
  export const sendToChainAddress: AuthenticatedLightningMethod<
66
71
  SendToChainAddressArgs,
@@ -3,6 +3,7 @@ import {
3
3
  AuthenticatedLightningArgs,
4
4
  AuthenticatedLightningMethod,
5
5
  LightningError,
6
+ UtxoSelection,
6
7
  } from '../../typescript';
7
8
  import {MergeExclusive} from 'type-fest';
8
9
 
@@ -32,6 +33,8 @@ export type SendToChainAddressesArgs = AuthenticatedLightningArgs<
32
33
  target_confirmations?: number;
33
34
  /** Minimum Confirmations for UTXO Selection */
34
35
  utxo_confirmations?: number;
36
+ /** Select UTXOs Using Method String */
37
+ utxo_selection?: UtxoSelection;
35
38
  } & ExpectedLogForChainSendWebSocketAnnouncement
36
39
  >;
37
40
 
@@ -54,6 +57,8 @@ export type SendToChainAddressesResult = {
54
57
  * Requires `onchain:write` permission
55
58
  *
56
59
  * `utxo_confirmations` is not supported on LND 0.11.1 or below
60
+ *
61
+ * `utxo_selection` is not supported in LND 0.17.5 and below
57
62
  */
58
63
  export const sendToChainAddresses: AuthenticatedLightningMethod<
59
64
  SendToChainAddressesArgs,
@@ -1,6 +1,7 @@
1
1
  import {
2
2
  AuthenticatedLightningArgs,
3
3
  AuthenticatedLightningMethod,
4
+ UtxoSelection,
4
5
  } from '../../typescript';
5
6
  import {MergeExclusive} from 'type-fest';
6
7
 
@@ -17,6 +18,8 @@ export type SendToChainOutputScriptsArgs = AuthenticatedLightningArgs<{
17
18
  }[];
18
19
  /** Minimum Confirmations for UTXO Selection Number */
19
20
  utxo_confirmations?: number;
21
+ /** Select UTXOs Using Method String */
22
+ utxo_selection?: UtxoSelection;
20
23
  }>;
21
24
 
22
25
  export type SendToChainOutputScriptsResult = {
@@ -40,6 +43,8 @@ export type SendToChainOutputScriptsResult = {
40
43
  * Requires `onchain:write` permission
41
44
  *
42
45
  * Requires LND compiled with `walletrpc` build tag
46
+ *
47
+ * `utxo_selection` is not supported in LND 0.17.5 and below
43
48
  */
44
49
  export const sendToChainOutputScripts: AuthenticatedLightningMethod<
45
50
  SendToChainOutputScriptsArgs,
@@ -38,6 +38,7 @@ const rpcPeerMessageAsMessage = require('./rpc_peer_message_as_message');
38
38
  const rpcRequestUpdateAsEvent = require('./rpc_request_update_as_event');
39
39
  const rpcResolutionAsResolution = require('./rpc_resolution_as_resolution');
40
40
  const rpcRouteAsRoute = require('./rpc_route_as_route');
41
+ const rpcSweepAsSweep = require('./rpc_sweep_as_sweep');
41
42
  const rpcTxAsTransaction = require('./rpc_tx_as_transaction');
42
43
  const rpcUtxoAsUtxo = require('./rpc_utxo_as_utxo');
43
44
  const rpcWalletStateAsState = require('./rpc_wallet_state_as_state');
@@ -83,6 +84,7 @@ module.exports = {
83
84
  rpcRequestUpdateAsEvent,
84
85
  rpcResolutionAsResolution,
85
86
  rpcRouteAsRoute,
87
+ rpcSweepAsSweep,
86
88
  rpcTxAsTransaction,
87
89
  rpcUtxoAsUtxo,
88
90
  rpcWalletStateAsState,
@@ -0,0 +1,96 @@
1
+ const isBoolean = n => n === false || n === true;
2
+ const isHash = n => !!n && /^[0-9A-F]{64}$/i.test(n);
3
+ const isNumber = n => !isNaN(n);
4
+
5
+ /** Convert an RPC sweep into a sweep
6
+
7
+ {
8
+ amount_sat: <Outpoint Value Tokens Number>
9
+ broadcast_attempts: <Count of Past Sweep Broadcasts Number>
10
+ budget: <Maximum Fee Tokens to Spend On Sweeping String>
11
+ deadline_height: <Maximum Confirmation Height Number>
12
+ immediate: <Sweep Was Specified To Skip Waiting For Batching Bool>
13
+ outpoint: {
14
+ output_index: <Transaction Output Index Number>
15
+ txid_str: <Transaction Id Hex String>
16
+ }
17
+ requested_sat_per_vbyte: <Requested Chain Fee Rate Tokens Per VByte String>
18
+ sat_per_vbyte: <Current Sweeping Chain Fee Rate Tokens Per VByte String>
19
+ witness_type: <Witness Type String>
20
+ }
21
+
22
+ @throws
23
+ <Error>
24
+
25
+ @returns
26
+ {
27
+ broadcasts_count: <Total Sweep Broadcast Attempts Count Number>
28
+ [current_fee_rate]: <Current Chain Fee Rate Tokens Per VByte Number>
29
+ [initial_fee_rate]: <Requested Chain Fee Rate Tokens per VByte Number>
30
+ is_batching: <Requested Waiting For Batching Bool>
31
+ [max_fee]: <Maximum Total Fee Tokens Allowed Number>
32
+ [max_height]: <Targeted Maximum Confirmation Height Number>
33
+ tokens: <Sweep Outpoint Tokens Value Number>
34
+ transaction_id: <Sweeping Outpoint Transaction Id Hex String>
35
+ transaction_vout: <Sweeping Outpoint Transaction Output Index Number>
36
+ type: <Outpoint Constraint Script Type String>
37
+ }
38
+ */
39
+ module.exports = args => {
40
+ if (!args) {
41
+ throw new Error('ExpectedSweepDetailsToDerivePendingSweep');
42
+ }
43
+
44
+ if (args.amount_sat === undefined) {
45
+ throw new Error('ExpectedSweepOutpointValueAmountInPendingSweep');
46
+ }
47
+
48
+ if (!isNumber(args.broadcast_attempts)) {
49
+ throw new Error('ExpectedBroadcastAttemptsForSweepInPendingSweep');
50
+ }
51
+
52
+ if (!args.budget) {
53
+ throw new Error('ExpectedSweepBudgetAmountForSweepInPendingSweeps');
54
+ }
55
+
56
+ if (!isNumber(args.deadline_height)) {
57
+ throw new Error('ExpectedSweepConfirmationDeadlineHeightInPendingSweep');
58
+ }
59
+
60
+ if (!isBoolean(args.immediate)) {
61
+ throw new Error('ExpectedImmediateStatusOfSweepInPendingSweeps');
62
+ }
63
+
64
+ if (!args.outpoint) {
65
+ throw new Error('ExpectedUnspentOutpointOfSweepInPendingSweeps');
66
+ }
67
+
68
+ if (!isNumber(args.outpoint.output_index)) {
69
+ throw new Error('ExpectedOutputIndexOfSweepInPendingSweeps');
70
+ }
71
+
72
+ if (!isHash(args.outpoint.txid_str)) {
73
+ throw new Error('ExpectedOutpointTransactionIdHexStringInSweep');
74
+ }
75
+
76
+ if (!args.requested_sat_per_vbyte) {
77
+ throw new Error('ExpectedRequestedSatPerVByteForSweepInPendingSweeps');
78
+ }
79
+
80
+ if (!args.sat_per_vbyte) {
81
+ throw new Error('ExpectedSatPerVByteForSweepInPendingSweeps');
82
+ }
83
+
84
+ return {
85
+ broadcasts_count: args.broadcast_attempts,
86
+ current_fee_rate: Number(args.sat_per_vbyte) || undefined,
87
+ initial_fee_rate: Number(args.requested_sat_per_vbyte) || undefined,
88
+ is_batching: !args.immediate,
89
+ max_fee: Number(args.budget) || undefined,
90
+ max_height: args.deadline_height || undefined,
91
+ tokens: args.amount_sat,
92
+ transaction_id: args.outpoint.txid_str,
93
+ transaction_vout: args.outpoint.output_index,
94
+ type: args.witness_type.toLowerCase(),
95
+ };
96
+ };
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.6",
11
- "@grpc/proto-loader": "0.7.12",
12
- "@types/node": "20.12.7",
10
+ "@grpc/grpc-js": "1.10.7",
11
+ "@grpc/proto-loader": "0.7.13",
12
+ "@types/node": "20.12.8",
13
13
  "@types/request": "2.48.12",
14
14
  "@types/ws": "8.5.10",
15
15
  "async": "3.2.5",
@@ -17,12 +17,12 @@
17
17
  "bitcoinjs-lib": "6.1.5",
18
18
  "bn.js": "5.2.1",
19
19
  "bolt07": "1.8.4",
20
- "bolt09": "2.0.0",
20
+ "bolt09": "2.1.0",
21
21
  "ecpair": "2.1.0",
22
22
  "invoices": "3.0.0",
23
23
  "psbt": "3.0.0",
24
24
  "tiny-secp256k1": "2.2.3",
25
- "type-fest": "4.16.0"
25
+ "type-fest": "4.18.1"
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.9.1"
56
+ "version": "10.10.0"
57
57
  }
@@ -0,0 +1,92 @@
1
+ const {strictEqual} = require('node:assert').strict;
2
+ const {rejects} = require('node:assert').strict;
3
+ const test = require('node:test');
4
+
5
+ const {getPendingSweeps} = require('./../../../lnd_methods');
6
+
7
+ const tests = [
8
+ {
9
+ args: {},
10
+ description: 'LND Object is required to get pending sweeps',
11
+ error: [400, 'ExpectedLndToGetPendingSweeps'],
12
+ },
13
+ {
14
+ args: {lnd: {wallet: {pendingSweeps: ({}, cbk) => cbk('err')}}},
15
+ description: 'Errors are passed back from method',
16
+ error: [503, 'UnexpectedGetPendingSweepsError', {err: 'err'}],
17
+ },
18
+ {
19
+ args: {lnd: {wallet: {pendingSweeps: ({}, cbk) => cbk()}}},
20
+ description: 'A result is expected from the method',
21
+ error: [503, 'ExpectedResponseToGetPendingSweepsRequest'],
22
+ },
23
+ {
24
+ args: {lnd: {wallet: {pendingSweeps: ({}, cbk) => cbk(null, {})}}},
25
+ description: 'An array of sweeps is expected in response',
26
+ error: [503, 'ExpectedArrayOfPendingSweepsInSweepsResponse'],
27
+ },
28
+ {
29
+ args: {
30
+ lnd: {
31
+ wallet: {
32
+ pendingSweeps: ({}, cbk) => cbk(null, {pending_sweeps: [null]}),
33
+ },
34
+ },
35
+ },
36
+ description: 'An array of sweeps is expected in response',
37
+ error: [503, 'ExpectedSweepDetailsToDerivePendingSweep'],
38
+ },
39
+ {
40
+ args: {
41
+ lnd: {
42
+ wallet: {
43
+ pendingSweeps: ({}, cbk) => cbk(null, {
44
+ pending_sweeps: [{
45
+ amount_sat: 0,
46
+ broadcast_attempts: 0,
47
+ budget: '0',
48
+ deadline_height: 0,
49
+ immediate: true,
50
+ outpoint: {
51
+ output_index: 0,
52
+ txid_str: Buffer.alloc(32).toString('hex'),
53
+ },
54
+ requested_sat_per_vbyte: '0',
55
+ sat_per_vbyte: '0',
56
+ witness_type: 'witness_type',
57
+ }],
58
+ }),
59
+ },
60
+ },
61
+ },
62
+ description: 'Pending sweeps are returned',
63
+ expected: {
64
+ sweeps: [{
65
+ broadcasts_count: 0,
66
+ current_fee_rate: undefined,
67
+ initial_fee_rate: undefined,
68
+ is_batching: false,
69
+ max_fee: undefined,
70
+ max_height: undefined,
71
+ tokens: 0,
72
+ transaction_id: Buffer.alloc(32).toString('hex'),
73
+ transaction_vout: 0,
74
+ type: 'witness_type',
75
+ }],
76
+ },
77
+ },
78
+ ];
79
+
80
+ tests.forEach(({args, description, error, expected}) => {
81
+ return test(description, async () => {
82
+ if (!!error) {
83
+ await rejects(() => getPendingSweeps(args), error, 'Got expected error');
84
+ } else {
85
+ const res = await getPendingSweeps(args);
86
+
87
+ strictEqual(res.chain_balance, expected.chain_balance, 'Got balance');
88
+ }
89
+
90
+ return;
91
+ });
92
+ });
@@ -0,0 +1,111 @@
1
+ const EventEmitter = require('events');
2
+ const {rejects} = require('node:assert').strict;
3
+ const test = require('node:test');
4
+
5
+ const {requestBatchedFeeIncrease} = require('./../../../lnd_methods');
6
+
7
+ const makeLnd = overrides => {
8
+ const res = {status: 'status'};
9
+
10
+ Object.keys(overrides).forEach(k => res[k] = overrides[k]);
11
+
12
+ return {
13
+ chain: {
14
+ registerBlockEpochNtfn: ({}) => {
15
+ const emitter = new EventEmitter();
16
+
17
+ emitter.cancel = () => {};
18
+
19
+ process.nextTick(() => emitter.emit('data', {
20
+ hash: Buffer.alloc(32),
21
+ height: 500,
22
+ }));
23
+
24
+ return emitter;
25
+ },
26
+ },
27
+ wallet: {bumpFee: (args, cbk) => cbk(null, res)},
28
+ };
29
+ };
30
+
31
+ const makeArgs = overrides => {
32
+ const args = {
33
+ lnd: makeLnd({}),
34
+ transaction_id: Buffer.alloc(32).toString('hex'),
35
+ transaction_vout: 0,
36
+ };
37
+
38
+ Object.keys(overrides).forEach(key => args[key] = overrides[key]);
39
+
40
+ return args;
41
+ };
42
+
43
+ const tests = [
44
+ {
45
+ args: makeArgs({lnd: undefined}),
46
+ description: 'An LND object is required',
47
+ error: [400, 'ExpectedLndToRequestChainFeeIncrease'],
48
+ },
49
+ {
50
+ args: makeArgs({transaction_id: undefined}),
51
+ description: 'A transaction id is required',
52
+ error: [400, 'ExpectedTransactionIdToRequestChainFeeIncrease'],
53
+ },
54
+ {
55
+ args: makeArgs({transaction_vout: undefined}),
56
+ description: 'A tx output index is required',
57
+ error: [400, 'ExpectedTransactionOutputIndexToRequestFeeBump'],
58
+ },
59
+ {
60
+ args: makeArgs({
61
+ lnd: {
62
+ wallet: {
63
+ bumpFee: ({}, cbk) => cbk({
64
+ details: 'the passed output does not belong to the wallet',
65
+ }),
66
+ },
67
+ },
68
+ }),
69
+ description: 'Unknown UTXO error is passed back',
70
+ error: [404, 'SpecifiedUtxoNotFoundInWalletUtxos'],
71
+ },
72
+ {
73
+ args: makeArgs({lnd: {wallet: {bumpFee: ({}, cbk) => cbk('err')}}}),
74
+ description: 'Errors are passed back',
75
+ error: [503, 'UnexpectedErrorRequestingBatchIncrease', {err: 'err'}],
76
+ },
77
+ {
78
+ args: makeArgs({lnd: {wallet: {bumpFee: ({}, cbk) => cbk()}}}),
79
+ description: 'A response is expected',
80
+ error: [503, 'ExpectedResponseToBatchedFeeIncreaseRequest'],
81
+ },
82
+ {
83
+ args: makeArgs({lnd: {wallet: {bumpFee: ({}, cbk) => cbk(null, {})}}}),
84
+ description: 'A response status is expected',
85
+ error: [503, 'ExpectedStatusOfBatchedFeeIncrease'],
86
+ },
87
+ {
88
+ args: makeArgs({}),
89
+ description: 'Fee bump is requested',
90
+ },
91
+ {
92
+ args: makeArgs({max_height: 1000}),
93
+ description: 'Fee bump is requested with a height',
94
+ },
95
+ {
96
+ args: makeArgs({max_height: 2}),
97
+ description: 'Fee bump is requested with a low height',
98
+ },
99
+ ];
100
+
101
+ tests.forEach(({args, description, error, expected}) => {
102
+ return test(description, async () => {
103
+ if (!!error) {
104
+ await rejects(requestBatchedFeeIncrease(args), error, 'Got error');
105
+ } else {
106
+ await requestBatchedFeeIncrease(args);
107
+ }
108
+
109
+ return;
110
+ });
111
+ });
@@ -0,0 +1,135 @@
1
+ const {deepEqual} = require('node:assert').strict;
2
+ const test = require('node:test');
3
+ const {throws} = require('node:assert').strict;
4
+
5
+ const {rpcSweepAsSweep} = require('./../../lnd_responses');
6
+
7
+ const makeArgs = overrides => {
8
+ const response = {
9
+ amount_sat: 0,
10
+ broadcast_attempts: 0,
11
+ budget: '0',
12
+ deadline_height: 0,
13
+ immediate: true,
14
+ outpoint: {
15
+ output_index: 0,
16
+ txid_str: Buffer.alloc(32).toString('hex'),
17
+ },
18
+ requested_sat_per_vbyte: '0',
19
+ sat_per_vbyte: '0',
20
+ witness_type: 'witness_type',
21
+ };
22
+
23
+ Object.keys(overrides || {}).forEach(key => response[key] = overrides[key]);
24
+
25
+ return response;
26
+ };
27
+
28
+
29
+ const makeExpected = overrides => {
30
+ const expected = {
31
+ broadcasts_count: 0,
32
+ current_fee_rate: undefined,
33
+ initial_fee_rate: undefined,
34
+ is_batching: false,
35
+ max_fee: undefined,
36
+ max_height: undefined,
37
+ tokens: 0,
38
+ transaction_id: Buffer.alloc(32).toString('hex'),
39
+ transaction_vout: 0,
40
+ type: 'witness_type',
41
+ };
42
+
43
+ Object.keys(overrides || {}).forEach(key => expected[key] = overrides[key]);
44
+
45
+ return expected;
46
+ };
47
+
48
+ const tests = [
49
+ {
50
+ description: 'Pending sweep details are expected',
51
+ error: 'ExpectedSweepDetailsToDerivePendingSweep',
52
+ },
53
+ {
54
+ args: makeArgs({amount_sat: undefined}),
55
+ description: 'The sweep amount is expected',
56
+ error: 'ExpectedSweepOutpointValueAmountInPendingSweep',
57
+ },
58
+ {
59
+ args: makeArgs({broadcast_attempts: undefined}),
60
+ description: 'The broadcasts count is expected',
61
+ error: 'ExpectedBroadcastAttemptsForSweepInPendingSweep',
62
+ },
63
+ {
64
+ args: makeArgs({budget: undefined}),
65
+ description: 'The sweep budget is expected',
66
+ error: 'ExpectedSweepBudgetAmountForSweepInPendingSweeps',
67
+ },
68
+ {
69
+ args: makeArgs({deadline_height: undefined}),
70
+ description: 'The target deadline is expected',
71
+ error: 'ExpectedSweepConfirmationDeadlineHeightInPendingSweep',
72
+ },
73
+ {
74
+ args: makeArgs({immediate: undefined}),
75
+ description: 'The immediate status is expected',
76
+ error: 'ExpectedImmediateStatusOfSweepInPendingSweeps',
77
+ },
78
+ {
79
+ args: makeArgs({outpoint: undefined}),
80
+ description: 'The outpoint being swept is expected',
81
+ error: 'ExpectedUnspentOutpointOfSweepInPendingSweeps',
82
+ },
83
+ {
84
+ args: makeArgs({outpoint: {}}),
85
+ description: 'The outpoint vout being swept is expected',
86
+ error: 'ExpectedOutputIndexOfSweepInPendingSweeps',
87
+ },
88
+ {
89
+ args: makeArgs({outpoint: {output_index: 0}}),
90
+ description: 'The outpoint transaction id being swept is expected',
91
+ error: 'ExpectedOutpointTransactionIdHexStringInSweep',
92
+ },
93
+ {
94
+ args: makeArgs({requested_sat_per_vbyte: undefined}),
95
+ description: 'The requested sweeping chain fee rate is expected',
96
+ error: 'ExpectedRequestedSatPerVByteForSweepInPendingSweeps',
97
+ },
98
+ {
99
+ args: makeArgs({sat_per_vbyte: undefined}),
100
+ description: 'The sweeping chain fee rate is expected',
101
+ error: 'ExpectedSatPerVByteForSweepInPendingSweeps',
102
+ },
103
+ {
104
+ args: makeArgs({}),
105
+ description: 'RPC sweep is mapped to pending sweep details',
106
+ expected: makeExpected({}),
107
+ },
108
+ {
109
+ args: makeArgs({
110
+ budget: '1',
111
+ deadline_height: 1,
112
+ requested_sat_per_vbyte: '1',
113
+ sat_per_vbyte: '1',
114
+ }),
115
+ description: 'RPC sweep with all details is mapped to pending sweep ',
116
+ expected: makeExpected({
117
+ current_fee_rate: 1,
118
+ initial_fee_rate: 1,
119
+ max_fee: 1,
120
+ max_height: 1,
121
+ }),
122
+ },
123
+ ];
124
+
125
+ tests.forEach(({args, description, error, expected}) => {
126
+ return test(description, (t, end) => {
127
+ if (!!error) {
128
+ throws(() => rpcSweepAsSweep(args), new Error(error), 'Got err');
129
+ } else {
130
+ deepEqual(rpcSweepAsSweep(args), expected, 'RPC sweep mapped');
131
+ }
132
+
133
+ return end();
134
+ });
135
+ });
@@ -118,3 +118,5 @@ export type RouteNode = {
118
118
  export type Route = RouteNode[]
119
119
 
120
120
  export type Routes = Route[]
121
+
122
+ export type UtxoSelection = "largest" | "random";