lightning 10.9.2 → 10.10.1

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.
Files changed (31) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/README.md +4 -0
  3. package/grpc/protos/lightning.proto +6 -0
  4. package/grpc/protos/walletkit.proto +84 -37
  5. package/index.js +4 -0
  6. package/lnd_messages/close_channel_request.js +2 -2
  7. package/lnd_methods/index.js +4 -0
  8. package/lnd_methods/macaroon/methods.json +9 -0
  9. package/lnd_methods/offchain/delete_payments.js +1 -1
  10. package/lnd_methods/offchain/get_connected_watchtowers.js +3 -3
  11. package/lnd_methods/onchain/close_channel.js +24 -3
  12. package/lnd_methods/onchain/get_chain_fee_estimate.js +4 -15
  13. package/lnd_methods/onchain/get_pending_sweeps.js +81 -0
  14. package/lnd_methods/onchain/index.js +4 -0
  15. package/lnd_methods/onchain/open_channel.js +4 -1
  16. package/lnd_methods/onchain/request_batched_fee_increase.js +108 -0
  17. package/lnd_methods/onchain/request_chain_fee_increase.js +3 -2
  18. package/lnd_methods/onchain/send_to_chain_address.js +14 -3
  19. package/lnd_methods/onchain/send_to_chain_addresses.js +14 -3
  20. package/lnd_responses/index.js +2 -0
  21. package/lnd_responses/rpc_sweep_as_sweep.js +96 -0
  22. package/package.json +6 -6
  23. package/test/lnd_messages/test_close_channel_request.js +2 -2
  24. package/test/lnd_methods/macaroon/test_handle_rpc_request_update.js +1 -1
  25. package/test/lnd_methods/offchain/test_get_connected_watchtowers.js +2 -2
  26. package/test/lnd_methods/onchain/test_get_chain_fee_estimate.js +0 -41
  27. package/test/lnd_methods/onchain/test_get_pending_sweeps.js +92 -0
  28. package/test/lnd_methods/onchain/test_request_batched_fee_increase.js +111 -0
  29. package/test/lnd_methods/onchain/test_send_to_chain_address.js +27 -44
  30. package/test/lnd_methods/onchain/test_send_to_chain_addresses.js +25 -42
  31. package/test/lnd_responses/test_rpc_sweep_as_sweep.js +135 -0
@@ -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
+ };
@@ -54,7 +54,7 @@ module.exports = (args, cbk) => {
54
54
  feeRate: ['validate', ({}, cbk) => {
55
55
  // Exit early when the fee rate is specified
56
56
  if (!!args.fee_tokens_per_vbyte) {
57
- return cbk(null, {sat_per_byte: args.fee_tokens_per_vbyte});
57
+ return cbk(null, {sat_per_vbyte: args.fee_tokens_per_vbyte});
58
58
  }
59
59
 
60
60
  // Exit early when the confirmation target is specified
@@ -69,11 +69,12 @@ 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,
75
76
  },
76
- sat_per_byte: feeRate.sat_per_byte,
77
+ sat_per_vbyte: feeRate.sat_per_vbyte,
77
78
  target_conf: feeRate.target_conf,
78
79
  },
79
80
  (err, res) => {
@@ -3,6 +3,7 @@ const {returnResult} = require('asyncjs-util');
3
3
 
4
4
  const {isLnd} = require('./../../lnd_requests');
5
5
 
6
+ const defaultConfTarget = 6;
6
7
  const initialConfirmationCount = 0;
7
8
  const {isArray} = Array;
8
9
  const {isInteger} = Number;
@@ -83,18 +84,28 @@ module.exports = (args, cbk) => {
83
84
  return cbk();
84
85
  },
85
86
 
87
+ // Determine what the confirmations to confirm should be
88
+ targetConf: ['validate', ({}, cbk) => {
89
+ // Exit early when there is a chain fee rate specified
90
+ if (!!args.fee_tokens_per_vbyte) {
91
+ return cbk();
92
+ }
93
+
94
+ return cbk(null, args.target_confirmations || defaultConfTarget);
95
+ }],
96
+
86
97
  // Send coins
87
- send: ['validate', ({}, cbk) => {
98
+ send: ['targetConf', ({targetConf}, cbk) => {
88
99
  return args.lnd.default.sendCoins({
89
100
  addr: args.address,
90
101
  amount: args.tokens || undefined,
91
102
  coin_selection_strategy: strategy(args.utxo_selection),
92
103
  min_confs: args.utxo_confirmations || undefined,
93
104
  label: args.description || undefined,
94
- sat_per_byte: args.fee_tokens_per_vbyte || undefined,
105
+ sat_per_vbyte: args.fee_tokens_per_vbyte || undefined,
95
106
  send_all: args.is_send_all || undefined,
96
107
  spend_unconfirmed: args.utxo_confirmations === unconfirmedConfCount,
97
- target_conf: args.target_confirmations || undefined,
108
+ target_conf: targetConf,
98
109
  },
99
110
  (err, res) => {
100
111
  if (!!err && err.details === lowBalanceErr) {
@@ -3,6 +3,7 @@ const {returnResult} = require('asyncjs-util');
3
3
 
4
4
  const {isLnd} = require('./../../lnd_requests');
5
5
 
6
+ const defaultConfTarget = 6;
6
7
  const initialConfirmationCount = 0;
7
8
  const {isArray} = Array;
8
9
  const method = 'sendMany';
@@ -74,7 +75,17 @@ module.exports = (args, cbk) => {
74
75
  return cbk();
75
76
  },
76
77
 
77
- send: ['validate', ({}, cbk) => {
78
+ // Determine what the confirmations to confirm should be
79
+ targetConf: ['validate', ({}, cbk) => {
80
+ // Exit early when there is a chain fee rate specified
81
+ if (!!args.fee_tokens_per_vbyte) {
82
+ return cbk();
83
+ }
84
+
85
+ return cbk(null, args.target_confirmations || defaultConfTarget);
86
+ }],
87
+
88
+ send: ['targetConf', ({targetConf}, cbk) => {
78
89
  const AddrToAmount = {};
79
90
 
80
91
  args.send_to
@@ -85,9 +96,9 @@ module.exports = (args, cbk) => {
85
96
  coin_selection_strategy: strategy(args.utxo_selection),
86
97
  label: args.description || undefined,
87
98
  min_confs: args.utxo_confirmations || undefined,
88
- sat_per_byte: args.fee_tokens_per_vbyte || undefined,
99
+ sat_per_vbyte: args.fee_tokens_per_vbyte || undefined,
89
100
  spend_unconfirmed: args.utxo_confirmations === unconfirmedConfCount,
90
- target_conf: args.target_confirmations || undefined,
101
+ target_conf: targetConf,
91
102
  };
92
103
 
93
104
  return args.lnd.default.sendMany(send, (err, res) => {
@@ -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.17.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.2"
56
+ "version": "10.10.1"
57
57
  }
@@ -12,7 +12,7 @@ const makeArgs = overrides => {
12
12
  },
13
13
  delivery_address: 'delivery_address',
14
14
  force: true,
15
- sat_per_byte: '1',
15
+ sat_per_vbyte: '1',
16
16
  target_conf: 1,
17
17
  };
18
18
 
@@ -47,7 +47,7 @@ const tests = [
47
47
  args: makeArgs({
48
48
  delivery_address: '',
49
49
  force: false,
50
- sat_per_byte: '0',
50
+ sat_per_vbyte: '0',
51
51
  target_conf: 0,
52
52
  }),
53
53
  description: 'Defaults are selected',
@@ -19,7 +19,7 @@ const tests = [
19
19
  },
20
20
  delivery_address: 'delivery_address',
21
21
  force: true,
22
- sat_per_byte: '1',
22
+ sat_per_vbyte: '1',
23
23
  target_conf: 1,
24
24
  }),
25
25
  },
@@ -28,7 +28,7 @@ const makeTower = overrides => {
28
28
  max_backups: 1,
29
29
  num_backups: 1,
30
30
  num_pending_backups: 1,
31
- sweep_sat_per_byte: 1,
31
+ sweep_sat_per_vbyte: 1,
32
32
  }],
33
33
  };
34
34
 
@@ -60,7 +60,7 @@ const makeLnd = args => {
60
60
  return cbk(null, args.policyRes);
61
61
  }
62
62
 
63
- return cbk(null, {max_updates: 1, sweep_sat_per_byte: 1});
63
+ return cbk(null, {max_updates: 1, sweep_sat_per_vbyte: 1});
64
64
  },
65
65
  stats: ({}, cbk) => {
66
66
  if (!!args.statsErr) {
@@ -57,52 +57,12 @@ const tests = [
57
57
  description: 'Fee sat is expected in estimate fee response',
58
58
  error: [503, 'ExpectedChainFeeInResponseToChainFeeEstimate'],
59
59
  },
60
- {
61
- args: {
62
- lnd: {default: {estimateFee: ({}, cbk) => cbk(null, {fee_sat: '1'})}},
63
- send_to: [{address: 'address', tokens: 1}],
64
- },
65
- description: 'Fee rate is expected in estimate fee response',
66
- error: [503, 'ExpectedFeeRateValueInChainFeeEstimateQuery'],
67
- },
68
- {
69
- args: {
70
- lnd: {
71
- default: {
72
- estimateFee: ({}, cbk) => cbk(null, {
73
- fee_sat: '1',
74
- feerate_sat_per_byte: '1',
75
- }),
76
- },
77
- },
78
- send_to: [{address: 'address', tokens: 1}],
79
- },
80
- description: 'Fee rate and fee are given in chain response',
81
- expected: {fee: 1, tokens_per_vbyte: 1},
82
- },
83
- {
84
- args: {
85
- lnd: {
86
- default: {
87
- estimateFee: ({}, cbk) => cbk(null, {
88
- fee_sat: '1',
89
- feerate_sat_per_byte: '1',
90
- }),
91
- },
92
- },
93
- send_to: [{address: 'address', tokens: 1}],
94
- utxo_confirmations: 0,
95
- },
96
- description: 'Passing 0 UTXO confirmations is supported',
97
- expected: {fee: 1, tokens_per_vbyte: 1},
98
- },
99
60
  {
100
61
  args: {
101
62
  lnd: {
102
63
  default: {
103
64
  estimateFee: ({}, cbk) => cbk(null, {
104
65
  fee_sat: '1',
105
- feerate_sat_per_byte: '1',
106
66
  sat_per_vbyte: '2',
107
67
  }),
108
68
  },
@@ -119,7 +79,6 @@ const tests = [
119
79
  default: {
120
80
  estimateFee: ({}, cbk) => cbk(null, {
121
81
  fee_sat: '1',
122
- feerate_sat_per_byte: '1',
123
82
  sat_per_vbyte: '2',
124
83
  }),
125
84
  },
@@ -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
+ });