lightning 6.8.0 → 7.0.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,14 @@
1
1
  # Versions
2
2
 
3
- ## 6.8.0
3
+ ## 7.0.0
4
+
5
+ - `getAddresses`: Add method to get the list of chain addresses
6
+
7
+ ### Breaking Changes
8
+
9
+ - Incorrect TypeScript settings for probe and fee rates was corrected
10
+
11
+ ## 6.8.1
4
12
 
5
13
  - `subscribeToRpcRequests`: add `max_tokens_per_vbyte` to RPC close requests
6
14
 
package/README.md CHANGED
@@ -106,7 +106,6 @@ variables set:
106
106
  - [createWallet](https://github.com/alexbosworth/ln-service#createwallet): Make a new wallet.
107
107
  - [decodePaymentRequest](https://github.com/alexbosworth/ln-service#decodepaymentrequest):
108
108
  Get parsed details for a payment request.
109
- - [createWallet](https://github.com/alexbosworth/ln-service#createwallet): Make a new wallet.
110
109
  - [deleteFailedPayAttempts](https://github.com/alexbosworth/ln-service#deletefailedpayattempts)
111
110
  Remove failed payment paths from database.
112
111
  - [deleteFailedPayments](https://github.com/alexbosworth/ln-service#deletefailedpayments)
@@ -94,8 +94,8 @@ service Router {
94
94
  returns (SetMissionControlConfigResponse);
95
95
 
96
96
  /*
97
- QueryProbability returns the current success probability estimate for a
98
- given node pair and amount.
97
+ Deprecated. QueryProbability returns the current success probability
98
+ estimate for a given node pair and amount.
99
99
  */
100
100
  rpc QueryProbability (QueryProbabilityRequest)
101
101
  returns (QueryProbabilityResponse);
@@ -64,6 +64,21 @@ service WalletKit {
64
64
  */
65
65
  rpc ListAccounts (ListAccountsRequest) returns (ListAccountsResponse);
66
66
 
67
+ /*
68
+ RequiredReserve returns the minimum amount of satoshis that should be kept
69
+ in the wallet in order to fee bump anchor channels if necessary. The value
70
+ scales with the number of public anchor channels but is capped at a maximum.
71
+ */
72
+ rpc RequiredReserve (RequiredReserveRequest)
73
+ returns (RequiredReserveResponse);
74
+
75
+ /*
76
+ ListAddresses retrieves all the addresses along with their balance. An
77
+ account name filter can be provided to filter through all of the
78
+ wallet accounts and return the addresses of only those matching.
79
+ */
80
+ rpc ListAddresses (ListAddressesRequest) returns (ListAddressesResponse);
81
+
67
82
  /*
68
83
  ImportAccount imports an account backed by an account extended public key.
69
84
  The master key fingerprint denotes the fingerprint of the root key
@@ -92,7 +107,11 @@ service WalletKit {
92
107
  rpc ImportAccount (ImportAccountRequest) returns (ImportAccountResponse);
93
108
 
94
109
  /*
95
- ImportPublicKey imports a public key as watch-only into the wallet.
110
+ ImportPublicKey imports a public key as watch-only into the wallet. The
111
+ public key is converted into a simple address of the given type and that
112
+ address script is watched on chain. For Taproot keys, this will only watch
113
+ the BIP-0086 style output script. Use ImportTapscript for more advanced key
114
+ spend or script spend outputs.
96
115
 
97
116
  NOTE: Events (deposits/spends) for a key will only be detected by lnd if
98
117
  they happen after the import. Rescans to detect past events will be
@@ -101,6 +120,22 @@ service WalletKit {
101
120
  rpc ImportPublicKey (ImportPublicKeyRequest)
102
121
  returns (ImportPublicKeyResponse);
103
122
 
123
+ /*
124
+ ImportTapscript imports a Taproot script and internal key and adds the
125
+ resulting Taproot output key as a watch-only output script into the wallet.
126
+ For BIP-0086 style Taproot keys (no root hash commitment and no script spend
127
+ path) use ImportPublicKey.
128
+
129
+ NOTE: Events (deposits/spends) for a key will only be detected by lnd if
130
+ they happen after the import. Rescans to detect past events will be
131
+ supported later on.
132
+
133
+ NOTE: Taproot keys imported through this RPC currently _cannot_ be used for
134
+ funding PSBTs. Only tracking the balance and UTXOs is currently supported.
135
+ */
136
+ rpc ImportTapscript (ImportTapscriptRequest)
137
+ returns (ImportTapscriptResponse);
138
+
104
139
  /*
105
140
  PublishTransaction attempts to publish the passed transaction to the
106
141
  network. Once this returns without an error, the wallet will continually
@@ -340,14 +375,7 @@ message Account {
340
375
  // The name used to identify the account.
341
376
  string name = 1;
342
377
 
343
- /*
344
- The type of addresses the account supports.
345
- AddressType | External Branch | Internal Branch
346
- ---------------------------------------------------------------------
347
- WITNESS_PUBKEY_HASH | P2WPKH | P2WPKH
348
- NESTED_WITNESS_PUBKEY_HASH | NP2WPKH | NP2WPKH
349
- HYBRID_NESTED_WITNESS_PUBKEY_HASH | NP2WPKH | P2WPKH
350
- */
378
+ // The type of addresses the account supports.
351
379
  AddressType address_type = 2;
352
380
 
353
381
  /*
@@ -389,6 +417,50 @@ message Account {
389
417
  // Whether the wallet stores private keys for the account.
390
418
  bool watch_only = 8;
391
419
  }
420
+
421
+ message AddressProperty {
422
+ /*
423
+ The address encoded using the appropriate format depending on the
424
+ address type (base58, bech32, bech32m).
425
+
426
+ Note that lnd's internal/custom keys for channels and other
427
+ functionality are derived from the same scope. Since they
428
+ aren't really used as addresses and will never have an
429
+ on-chain balance, we'll show the public key instead (only if
430
+ the show_custom_accounts flag is provided).
431
+ */
432
+ string address = 1;
433
+
434
+ // Denotes if the address is a change address.
435
+ bool is_internal = 2;
436
+
437
+ // The balance of the address.
438
+ int64 balance = 3;
439
+ }
440
+
441
+ message AccountWithAddresses {
442
+ // The name used to identify the account.
443
+ string name = 1;
444
+
445
+ // The type of addresses the account supports.
446
+ AddressType address_type = 2;
447
+
448
+ /*
449
+ The derivation path corresponding to the account public key. This will
450
+ always be empty for the default imported account in which single public keys
451
+ are imported into.
452
+ */
453
+ string derivation_path = 3;
454
+
455
+ /*
456
+ List of address, its type internal/external & balance.
457
+ Note that the order of addresses will be random and not according to the
458
+ derivation index, since that information is not stored by the underlying
459
+ wallet.
460
+ */
461
+ repeated AddressProperty addresses = 4;
462
+ }
463
+
392
464
  message ListAccountsRequest {
393
465
  // An optional filter to only return accounts matching this name.
394
466
  string name = 1;
@@ -396,10 +468,35 @@ message ListAccountsRequest {
396
468
  // An optional filter to only return accounts matching this address type.
397
469
  AddressType address_type = 2;
398
470
  }
471
+
399
472
  message ListAccountsResponse {
400
473
  repeated Account accounts = 1;
401
474
  }
402
475
 
476
+ message RequiredReserveRequest {
477
+ // The number of additional channels the user would like to open.
478
+ uint32 additional_public_channels = 1;
479
+ }
480
+
481
+ message RequiredReserveResponse {
482
+ // The amount of reserve required.
483
+ int64 required_reserve = 1;
484
+ }
485
+
486
+ message ListAddressesRequest {
487
+ // An optional filter to only return addresses matching this account.
488
+ string account_name = 1;
489
+
490
+ // An optional flag to return LND's custom accounts (Purpose=1017)
491
+ // public key along with other addresses.
492
+ bool show_custom_accounts = 2;
493
+ }
494
+
495
+ message ListAddressesResponse {
496
+ // A list of all the accounts and their addresses.
497
+ repeated AccountWithAddresses account_with_addresses = 1;
498
+ }
499
+
403
500
  message ImportAccountRequest {
404
501
  // A name to identify the account with.
405
502
  string name = 1;
@@ -464,6 +561,77 @@ message ImportPublicKeyRequest {
464
561
  message ImportPublicKeyResponse {
465
562
  }
466
563
 
564
+ message ImportTapscriptRequest {
565
+ /*
566
+ The internal public key, serialized as 32-byte x-only public key.
567
+ */
568
+ bytes internal_public_key = 1;
569
+
570
+ oneof script {
571
+ /*
572
+ The full script tree with all individual leaves is known and the root
573
+ hash can be constructed from the full tree directly.
574
+ */
575
+ TapscriptFullTree full_tree = 2;
576
+
577
+ /*
578
+ Only a single script leaf is known. To construct the root hash, the full
579
+ inclusion proof must also be provided.
580
+ */
581
+ TapscriptPartialReveal partial_reveal = 3;
582
+
583
+ /*
584
+ Only the root hash of the Taproot script tree (or other form of Taproot
585
+ commitment) is known.
586
+ */
587
+ bytes root_hash_only = 4;
588
+
589
+ /*
590
+ Only the final, tweaked Taproot key is known and no additional
591
+ information about the internal key or type of tweak that was used to
592
+ derive it. When this is set, the wallet treats the key in
593
+ internal_public_key as the Taproot key directly. This can be useful for
594
+ tracking arbitrary Taproot outputs without the goal of ever being able
595
+ to spend from them through the internal wallet.
596
+ */
597
+ bool full_key_only = 5;
598
+ }
599
+ }
600
+
601
+ message TapscriptFullTree {
602
+ /*
603
+ The complete, ordered list of all tap leaves of the tree.
604
+ */
605
+ repeated TapLeaf all_leaves = 1;
606
+ }
607
+
608
+ message TapLeaf {
609
+ // The leaf version. Should be 0xc0 (192) in case of a SegWit v1 script.
610
+ uint32 leaf_version = 1;
611
+
612
+ // The script of the tap leaf.
613
+ bytes script = 2;
614
+ }
615
+
616
+ message TapscriptPartialReveal {
617
+ // The tap leaf that is known and will be revealed.
618
+ TapLeaf revealed_leaf = 1;
619
+
620
+ // The BIP-0341 serialized inclusion proof that is required to prove that
621
+ // the revealed leaf is part of the tree. This contains 0..n blocks of 32
622
+ // bytes. If the tree only contained a single leaf (which is the revealed
623
+ // leaf), this can be empty.
624
+ bytes full_inclusion_proof = 2;
625
+ }
626
+
627
+ message ImportTapscriptResponse {
628
+ /*
629
+ The resulting pay-to-Taproot address that represents the imported internal
630
+ key with the script committed to it.
631
+ */
632
+ string p2tr_address = 1;
633
+ }
634
+
467
635
  message Transaction {
468
636
  /*
469
637
  The raw serialized transaction.
@@ -867,6 +1035,9 @@ message SignPsbtRequest {
867
1035
  message SignPsbtResponse {
868
1036
  // The signed transaction in PSBT format.
869
1037
  bytes signed_psbt = 1;
1038
+
1039
+ // The indices of signed inputs.
1040
+ repeated uint32 signed_inputs = 2;
870
1041
  }
871
1042
 
872
1043
  message FinalizePsbtRequest {
package/index.js CHANGED
@@ -33,6 +33,7 @@ const {getAutopilot} = require('./lnd_methods');
33
33
  const {getBackup} = require('./lnd_methods');
34
34
  const {getBackups} = require('./lnd_methods');
35
35
  const {getBlock} = require('./lnd_methods');
36
+ const {getChainAddresses} = require('./lnd_methods');
36
37
  const {getChainBalance} = require('./lnd_methods');
37
38
  const {getChainFeeEstimate} = require('./lnd_methods');
38
39
  const {getChainFeeRate} = require('./lnd_methods');
@@ -184,6 +185,7 @@ module.exports = {
184
185
  getBackup,
185
186
  getBackups,
186
187
  getBlock,
188
+ getChainAddresses,
187
189
  getChainBalance,
188
190
  getChainFeeEstimate,
189
191
  getChainFeeRate,
@@ -31,6 +31,7 @@ const {getAutopilot} = require('./info');
31
31
  const {getBackup} = require('./offchain');
32
32
  const {getBackups} = require('./offchain');
33
33
  const {getBlock} = require('./onchain');
34
+ const {getChainAddresses} = require('./onchain');
34
35
  const {getChainBalance} = require('./onchain');
35
36
  const {getChainFeeEstimate} = require('./onchain');
36
37
  const {getChainFeeRate} = require('./onchain');
@@ -178,6 +179,7 @@ module.exports = {
178
179
  getBackup,
179
180
  getBackups,
180
181
  getBlock,
182
+ getChainAddresses,
181
183
  getChainBalance,
182
184
  getChainFeeEstimate,
183
185
  getChainFeeRate,
@@ -50,7 +50,7 @@ const type = 'invoices';
50
50
  created_at: <ISO 8601 Date String>
51
51
  description: <Description String>
52
52
  id: <Payment Hash Hex String>
53
- mtokens: <Millitokens Number>
53
+ mtokens: <Millitokens Number String>
54
54
  request: <BOLT 11 Encoded Payment Request String>
55
55
  [secret]: <Hex Encoded Payment Secret String>
56
56
  tokens: <Tokens Number>
@@ -69,13 +69,6 @@ const updateEvent = 'invoice_updated';
69
69
  received: <Received Tokens Number>
70
70
  received_mtokens: <Received Millitokens String>
71
71
  request: <Bolt 11 Invoice String>
72
- routes: [[{
73
- base_fee_mtokens: <Base Routing Fee In Millitokens Number>
74
- channel: <Standard Format Channel Id String>
75
- cltv_delta: <CLTV Blocks Delta Number>
76
- fee_rate: <Fee Rate In Millitokens Per Million Number>
77
- public_key: <Public Key Hex String>
78
- }]]
79
72
  secret: <Secret Preimage Hex String>
80
73
  tokens: <Tokens Number>
81
74
  }
@@ -46,6 +46,8 @@ export type SubscribeToRpcRequestsCloseChannelRequestEvent =
46
46
  address?: string;
47
47
  /** Is Force Close Bool */
48
48
  is_force_close?: boolean;
49
+ /** Max Tokens Per VByte Number */
50
+ max_tokens_per_vbyte?: number;
49
51
  /** Confirmation Target Number */
50
52
  target_confirmations?: number;
51
53
  /** Tokens Per Virtual Byte Number */
@@ -1,4 +1,4 @@
1
- import {
1
+ import type {
2
2
  AuthenticatedLightningArgs,
3
3
  AuthenticatedLightningMethod,
4
4
  } from '../../typescript';
@@ -8,6 +8,21 @@ export type DecodePaymentRequestArgs = AuthenticatedLightningArgs<{
8
8
  request: string;
9
9
  }>;
10
10
 
11
+ export type DecodePaymentRouteEdge = {
12
+ /** Base Routing Fee In Millitokens */
13
+ base_fee_mtokens?: string;
14
+ /** Standard Format Channel Id */
15
+ channel?: string;
16
+ /** CLTV Blocks Delta */
17
+ cltv_delta?: number;
18
+ /** Fees Charged in Millitokens Per Million */
19
+ fee_rate?: number;
20
+ /** Forward Edge Public Key Hex */
21
+ public_key: string;
22
+ };
23
+
24
+ export type DecodePaymentRoutes = DecodePaymentRouteEdge[][];
25
+
11
26
  export type DecodePaymentRequestResult = {
12
27
  /** Fallback Chain Address */
13
28
  chain_address: string;
@@ -37,18 +52,7 @@ export type DecodePaymentRequestResult = {
37
52
  mtokens: string;
38
53
  /** Payment Identifier Hex Encoded */
39
54
  payment?: string;
40
- routes: {
41
- /** Base Routing Fee In Millitokens */
42
- base_fee_mtokens?: string;
43
- /** Standard Format Channel Id */
44
- channel?: string;
45
- /** CLTV Blocks Delta */
46
- cltv_delta?: number;
47
- /** Fees Charged in Millitokens Per Million */
48
- fee_rate?: number;
49
- /** Forward Edge Public Key Hex */
50
- public_key: string;
51
- }[][];
55
+ routes: DecodePaymentRoutes;
52
56
  /** Requested Tokens Rounded Up */
53
57
  safe_tokens: number;
54
58
  /** Requested Tokens Rounded Down */
@@ -7,6 +7,8 @@ export type GetFeeRatesResult = {
7
7
  base_fee: number;
8
8
  /** Base Flat Fee Millitokens */
9
9
  base_fee_mtokens: string;
10
+ /** Fee Rate in Millitokens Per Million Number */
11
+ fee_rate: number;
10
12
  /** Standard Format Channel Id */
11
13
  id: string;
12
14
  /** Channel Funding Transaction Id Hex */
@@ -1,70 +1,73 @@
1
- import {
1
+ import type {MergeExclusive} from 'type-fest';
2
+ import type {
2
3
  AuthenticatedLightningArgs,
3
4
  AuthenticatedLightningMethod,
4
5
  } from '../../typescript';
6
+ import type {DecodePaymentRouteEdge} from './decode_payment_request';
5
7
 
6
- export type ProbeForRouteArgs = AuthenticatedLightningArgs<{
7
- /** Final CLTV Delta Number */
8
- cltv_delta?: number;
9
- /** Destination Public Key Hex String */
10
- destination: string;
11
- features?: {
12
- /** Feature Bit Number */
13
- bit: number;
14
- }[];
15
- ignore?: {
16
- /** Channel Id String */
17
- channel?: string;
18
- /** Public Key Hex String */
19
- from_public_key: string;
20
- /** To Public Key Hex String */
21
- to_public_key?: string;
22
- }[];
23
- /** Incoming Peer Public Key Hex String */
24
- incoming_peer?: string;
25
- /** Adjust Probe For Past Routing Failures Bool */
26
- is_ignoring_past_failures?: boolean;
27
- /** Maximum Fee Tokens Number */
28
- max_fee?: number;
29
- /** Maximum Fee Millitokens to Pay String */
30
- max_fee_mtokens?: string;
31
- /** Maximum Height of Payment Timeout Number */
32
- max_timeout_height?: number;
33
- messages?: {
34
- /** Message To Final Destination Type Number String */
35
- type: string;
36
- /** Message To Final Destination Raw Value Hex Encoded String */
37
- value: string;
38
- }[];
39
- /** Millitokens to Pay String */
40
- mtokens?: string;
41
- /** Outgoing Channel Id String */
42
- outgoing_channel?: string;
43
- /** Time to Spend On A Path Milliseconds Number */
44
- path_timeout_ms?: number;
45
- /** Payment Identifier Hex String */
46
- payment?: string;
47
- /** Probe Timeout Milliseconds Number */
48
- probe_timeout_ms?: number;
49
- routes?: {
50
- /** Base Routing Fee In Millitokens Number */
51
- base_fee_mtokens?: number;
52
- /** Channel Capacity Tokens Number */
53
- channel_capacity?: number;
54
- /** Standard Format Channel Id String */
55
- channel?: string;
56
- /** CLTV Blocks Delta Number */
8
+ export type ProbeForRouteRouteEdge = DecodePaymentRouteEdge & {
9
+ /** Channel Capacity Tokens Number */
10
+ channel_capacity?: number;
11
+ };
12
+
13
+ export type ProbeForRouteRoutes = ProbeForRouteRouteEdge[][];
14
+
15
+ export type ProbeForRouteArgs = AuthenticatedLightningArgs<
16
+ {
17
+ /** Final CLTV Delta Number */
57
18
  cltv_delta?: number;
58
- /** Fee Rate In Millitokens Per Million Number */
59
- fee_rate?: number;
60
- /** Forward Edge Public Key Hex String */
61
- public_key: string;
62
- }[][];
63
- /** Tokens Number */
64
- tokens: number;
65
- /** Total Millitokens Across Paths String */
66
- total_mtokens?: string;
67
- }>;
19
+ /** Destination Public Key Hex String */
20
+ destination: string;
21
+ features?: {
22
+ /** Feature Bit Number */
23
+ bit: number;
24
+ }[];
25
+ ignore?: {
26
+ /** Channel Id String */
27
+ channel?: string;
28
+ /** Public Key Hex String */
29
+ from_public_key: string;
30
+ /** To Public Key Hex String */
31
+ to_public_key?: string;
32
+ }[];
33
+ /** Incoming Peer Public Key Hex String */
34
+ incoming_peer?: string;
35
+ /** Adjust Probe For Past Routing Failures Bool */
36
+ is_ignoring_past_failures?: boolean;
37
+ /** Maximum Fee Tokens Number */
38
+ max_fee?: number;
39
+ /** Maximum Fee Millitokens to Pay String */
40
+ max_fee_mtokens?: string;
41
+ /** Maximum Height of Payment Timeout Number */
42
+ max_timeout_height?: number;
43
+ messages?: {
44
+ /** Message To Final Destination Type Number String */
45
+ type: string;
46
+ /** Message To Final Destination Raw Value Hex Encoded String */
47
+ value: string;
48
+ }[];
49
+ /** Outgoing Channel Id String */
50
+ outgoing_channel?: string;
51
+ /** Time to Spend On A Path Milliseconds Number */
52
+ path_timeout_ms?: number;
53
+ /** Payment Identifier Hex String */
54
+ payment?: string;
55
+ /** Probe Timeout Milliseconds Number */
56
+ probe_timeout_ms?: number;
57
+ routes?: ProbeForRouteRoutes;
58
+ /** Total Millitokens Across Paths String */
59
+ total_mtokens?: string;
60
+ } & MergeExclusive<
61
+ {
62
+ /** Millitokens to Pay String */
63
+ mtokens: string;
64
+ },
65
+ {
66
+ /** Tokens Number */
67
+ tokens: number;
68
+ }
69
+ >
70
+ >;
68
71
 
69
72
  export type ProbeForRouteResult = {
70
73
  route?: {
@@ -47,7 +47,7 @@ const isHex = n => !(n.length % 2) && /^[0-9A-F]*$/i.test(n);
47
47
  [payment]: <Payment Identifier Hex String>
48
48
  [probe_timeout_ms]: <Probe Timeout Milliseconds Number>
49
49
  [routes]: [[{
50
- [base_fee_mtokens]: <Base Routing Fee In Millitokens Number>
50
+ [base_fee_mtokens]: <Base Routing Fee In Millitokens String>
51
51
  [channel_capacity]: <Channel Capacity Tokens Number>
52
52
  [channel]: <Standard Format Channel Id String>
53
53
  [cltv_delta]: <CLTV Blocks Delta Number>
@@ -0,0 +1,37 @@
1
+ import type {MergeExclusive} from 'type-fest';
2
+ import {
3
+ AuthenticatedLightningArgs,
4
+ AuthenticatedLightningMethod,
5
+ } from '../../typescript';
6
+
7
+ export type GetBlockArgs = AuthenticatedLightningArgs<
8
+ MergeExclusive<
9
+ {
10
+ /** Block Height Number */
11
+ height: number;
12
+ },
13
+ {
14
+ /** Block Hash Hex String */
15
+ id: string;
16
+ }
17
+ >
18
+ >;
19
+
20
+ export type GetBlockResult = {
21
+ /** Raw Block Bytes Hex String */
22
+ block: string;
23
+ };
24
+
25
+ /**
26
+ * Get a block in the chain
27
+ *
28
+ * This method requires LND built with `chainkit` build tag
29
+ *
30
+ * Requires `onchain:read` permission
31
+ *
32
+ * This method is not supported on LND 0.15.5 and below
33
+ */
34
+ export const getBlock: AuthenticatedLightningMethod<
35
+ GetBlockArgs,
36
+ GetBlockResult
37
+ >;
@@ -0,0 +1,83 @@
1
+ const asyncAuto = require('async/auto');
2
+ const {returnResult} = require('asyncjs-util');
3
+
4
+ const {isLnd} = require('./../../lnd_requests');
5
+ const {rpcAddressesAsAddresses} = require('./../../lnd_responses');
6
+
7
+ const err404 = 'unknown method ListAddresses for service walletrpc.WalletKit';
8
+ const {isArray} = Array;
9
+ const method = 'listAddresses';
10
+ const type = 'wallet';
11
+ const unsupportedErrorMessage = 'unknown service walletrpc.WalletKit';
12
+
13
+ /** Get the wallet chain addresses
14
+
15
+ Requires `onchain:read` permission
16
+
17
+ This method is not supported on LND 0.15.5 and below
18
+
19
+ {
20
+ lnd: <Authenticated LND API Object>
21
+ }
22
+
23
+ @returns via cbk or Promise
24
+ {
25
+ addresses: [{
26
+ address: <Chain Address String>
27
+ is_change: <Is Internal Change Address Bool>
28
+ tokens: <Balance of Funds Controlled by Output Script Tokens Number>
29
+ }]
30
+ }
31
+ */
32
+ module.exports = ({lnd}, cbk) => {
33
+ return new Promise((resolve, reject) => {
34
+ return asyncAuto({
35
+ // Check arguments
36
+ validate: cbk => {
37
+ if (!isLnd({lnd, method, type})) {
38
+ return cbk([400, 'ExpectedAuthenticatedLndToGetChainAddresses']);
39
+ }
40
+
41
+ return cbk();
42
+ },
43
+
44
+ // Get the list of accounts with addresses
45
+ getAddresses: ['validate', ({}, cbk) => {
46
+ return lnd[type][method]({}, (err, res) => {
47
+ // LND 0.15.5 and below do not support listing account addresses
48
+ if (!!err && err.details === err404) {
49
+ return cbk([501, 'BackingLndDoesNotSupportGettingChainAddresses']);
50
+ }
51
+
52
+ if (!!err) {
53
+ return cbk([503, 'UnexpectedErrorListingAccountAddresses', {err}]);
54
+ }
55
+
56
+ if (!res) {
57
+ return cbk([503, 'ExpectedResponseForGetAccountAddressesRequest']);
58
+ }
59
+
60
+ if (!isArray(res.account_with_addresses)) {
61
+ return cbk([503, 'ExpectedSetOfAccountAddressesInAddrsResponse']);
62
+ }
63
+
64
+ return cbk(null, res.account_with_addresses);
65
+ });
66
+ }],
67
+
68
+ // Map the accounts to a list of addresses
69
+ addresses: ['getAddresses', ({getAddresses}, cbk) => {
70
+ try {
71
+ const {addresses} = rpcAddressesAsAddresses({
72
+ accounts: getAddresses,
73
+ });
74
+
75
+ return cbk(null, {addresses});
76
+ } catch (err) {
77
+ return cbk([503, err.message]);
78
+ }
79
+ }],
80
+ },
81
+ returnResult({reject, resolve, of: 'addresses'}, cbk));
82
+ });
83
+ };
@@ -3,6 +3,7 @@ export * from './cancel_pending_channel';
3
3
  export * from './close_channel';
4
4
  export * from './fund_pending_channels';
5
5
  export * from './fund_psbt';
6
+ export * from './get_block';
6
7
  export * from './get_chain_balance';
7
8
  export * from './get_chain_fee_estimate';
8
9
  export * from './get_chain_fee_rate';
@@ -4,6 +4,7 @@ const closeChannel = require('./close_channel');
4
4
  const fundPendingChannels = require('./fund_pending_channels');
5
5
  const fundPsbt = require('./fund_psbt');
6
6
  const getBlock = require('./get_block');
7
+ const getChainAddresses = require('./get_chain_addresses');
7
8
  const getChainBalance = require('./get_chain_balance');
8
9
  const getChainFeeEstimate = require('./get_chain_fee_estimate');
9
10
  const getChainFeeRate = require('./get_chain_fee_rate');
@@ -39,6 +40,7 @@ module.exports = {
39
40
  fundPendingChannels,
40
41
  fundPsbt,
41
42
  getBlock,
43
+ getChainAddresses,
42
44
  getChainBalance,
43
45
  getChainFeeEstimate,
44
46
  getChainFeeRate,
@@ -129,7 +129,6 @@ module.exports = (args, cbk) => {
129
129
  channelOpen.cancel();
130
130
 
131
131
  return cbk(null, {});
132
- break;
133
132
 
134
133
  case 'confirmation':
135
134
  break;
@@ -15,6 +15,7 @@ const pendingFromPayment = require('./pending_from_payment');
15
15
  const policyFromChannelUpdate = require('./policy_from_channel_update');
16
16
  const routesFromQueryRoutes = require('./routes_from_query_routes');
17
17
  const routingFailureFromHtlc = require('./routing_failure_from_htlc');
18
+ const rpcAddressesAsAddresses = require('./rpc_addresses_as_addresses');
18
19
  const rpcAttemptHtlcAsAttempt = require('./rpc_attempt_htlc_as_attempt');
19
20
  const rpcChannelAsChannel = require('./rpc_channel_as_channel');
20
21
  const rpcChannelAsOldRpcChannel = require('./rpc_channel_as_old_rpc_channel');
@@ -60,6 +61,7 @@ module.exports = {
60
61
  policyFromChannelUpdate,
61
62
  routesFromQueryRoutes,
62
63
  routingFailureFromHtlc,
64
+ rpcAddressesAsAddresses,
63
65
  rpcAttemptHtlcAsAttempt,
64
66
  rpcChannelAsChannel,
65
67
  rpcChannelAsOldRpcChannel,
@@ -0,0 +1,62 @@
1
+ const flatten = arr => [].concat(...arr);
2
+ const {isArray} = Array;
3
+ const isBoolean = n => n === false || n === true;
4
+
5
+ /** Derive a list of addresses from a list of accounts with addresses
6
+
7
+ {
8
+ accounts: [{
9
+ addresses: [{
10
+ address: <Chain Address String>
11
+ balance: <Balance Tokens Number String>
12
+ is_internal: <Is Change Address Bool>
13
+ }]
14
+ }]
15
+ }
16
+
17
+ @throws
18
+ <Error>
19
+
20
+ @returns
21
+ {
22
+ addresses: [{
23
+ address: <Chain Address String>
24
+ is_change: <Is Internal Change Address Bool>
25
+ tokens: <Balance of Funds Controlled by Output Script Tokens Number>
26
+ }]
27
+ }
28
+ */
29
+ module.exports = ({accounts}) => {
30
+ if (!isArray(accounts)) {
31
+ throw new Error('ExpectedArrayOfAccountsWithAddresses');
32
+ }
33
+
34
+ // Map the accounts addresses to a list of addresses
35
+ const addresses = flatten(accounts.map(account => {
36
+ if (!isArray(account.addresses)) {
37
+ throw new Error('ExpectedArrayOfAddressesInAccountWithAddresses');
38
+ }
39
+
40
+ return account.addresses.map(accountAddress => {
41
+ if (!accountAddress.address) {
42
+ throw new Error('ExpectedChainAddressInAccountAddress');
43
+ }
44
+
45
+ if (!accountAddress.balance) {
46
+ throw new Error('ExpectedBalanceTotalForAccountAddress');
47
+ }
48
+
49
+ if (!isBoolean(accountAddress.is_internal)) {
50
+ throw new Error('ExpectedInternalAddressMarkerInAccountAddress');
51
+ }
52
+
53
+ return {
54
+ address: accountAddress.address,
55
+ is_change: accountAddress.is_internal,
56
+ tokens: Number(accountAddress.balance),
57
+ };
58
+ });
59
+ }));
60
+
61
+ return {addresses};
62
+ };
package/package.json CHANGED
@@ -7,12 +7,12 @@
7
7
  "url": "https://github.com/alexbosworth/lightning/issues"
8
8
  },
9
9
  "dependencies": {
10
- "@grpc/grpc-js": "1.8.0",
10
+ "@grpc/grpc-js": "1.8.1",
11
11
  "@grpc/proto-loader": "0.7.4",
12
12
  "@types/express": "4.17.15",
13
- "@types/node": "18.11.16",
13
+ "@types/node": "18.11.18",
14
14
  "@types/request": "2.48.8",
15
- "@types/ws": "8.5.3",
15
+ "@types/ws": "8.5.4",
16
16
  "async": "3.2.4",
17
17
  "asyncjs-util": "1.2.10",
18
18
  "bitcoinjs-lib": "6.1.0",
@@ -26,7 +26,7 @@
26
26
  "invoices": "2.2.2",
27
27
  "psbt": "2.7.1",
28
28
  "tiny-secp256k1": "2.2.1",
29
- "type-fest": "3.4.0"
29
+ "type-fest": "3.5.1"
30
30
  },
31
31
  "description": "Lightning Network client library",
32
32
  "devDependencies": {
@@ -59,5 +59,5 @@
59
59
  "directory": "test/typescript"
60
60
  },
61
61
  "types": "index.d.ts",
62
- "version": "6.8.0"
62
+ "version": "7.0.0"
63
63
  }
@@ -0,0 +1,75 @@
1
+ const {test} = require('@alexbosworth/tap');
2
+
3
+ const {getChainAddresses} = require('./../../../lnd_methods');
4
+
5
+ const makeLnd = ({err, res}) => {
6
+ return {
7
+ wallet: {
8
+ listAddresses: ({}, cbk) => {
9
+ if (res !== undefined) {
10
+ return cbk(null, res);
11
+ }
12
+
13
+ return cbk(err, {account_with_addresses: []});
14
+ },
15
+ },
16
+ };
17
+ };
18
+
19
+ const tests = [
20
+ {
21
+ args: {},
22
+ description: 'LND Object is required to get chain addresses',
23
+ error: [400, 'ExpectedAuthenticatedLndToGetChainAddresses'],
24
+ },
25
+ {
26
+ args: {lnd: makeLnd({err: 'err'})},
27
+ description: 'LND errors are passed back',
28
+ error: [503, 'UnexpectedErrorListingAccountAddresses', {err: 'err'}],
29
+ },
30
+ {
31
+ args: {
32
+ lnd: makeLnd({
33
+ err: {
34
+ details: 'unknown method ListAddresses for service walletrpc.WalletKit',
35
+ },
36
+ }),
37
+ },
38
+ description: 'Unknown method is handled',
39
+ error: [501, 'BackingLndDoesNotSupportGettingChainAddresses'],
40
+ },
41
+ {
42
+ args: {lnd: makeLnd({res: null})},
43
+ description: 'A response is expected',
44
+ error: [503, 'ExpectedResponseForGetAccountAddressesRequest'],
45
+ },
46
+ {
47
+ args: {lnd: makeLnd({res: {}})},
48
+ description: 'A response with accounts is expected',
49
+ error: [503, 'ExpectedSetOfAccountAddressesInAddrsResponse'],
50
+ },
51
+ {
52
+ args: {lnd: makeLnd({res: {account_with_addresses: [{}]}})},
53
+ description: 'A valid response with accounts is expected',
54
+ error: [503, 'ExpectedArrayOfAddressesInAccountWithAddresses'],
55
+ },
56
+ {
57
+ args: {lnd: makeLnd({})},
58
+ description: 'Get a list of chain addresses',
59
+ expected: {addresses: []},
60
+ },
61
+ ];
62
+
63
+ tests.forEach(({args, description, error, expected}) => {
64
+ return test(description, async ({end, rejects, strictSame}) => {
65
+ if (!!error) {
66
+ await rejects(() => getChainAddresses(args), error, 'Got error');
67
+ } else {
68
+ const res = await getChainAddresses(args);
69
+
70
+ strictSame(res, expected, 'Got expected result');
71
+ }
72
+
73
+ return end();
74
+ });
75
+ });
@@ -0,0 +1,190 @@
1
+ const EventEmitter = require('events');
2
+
3
+ const {test} = require('@alexbosworth/tap');
4
+
5
+ const {proposeChannel} = require('./../../../lnd_methods');
6
+
7
+ const makeLnd = ({err, data}) => {
8
+ const lnd = {
9
+ default: {
10
+ openChannel: ({}) => {
11
+ const emitter = new EventEmitter();
12
+
13
+ emitter.cancel = () => {};
14
+
15
+ process.nextTick(() => {
16
+ if (!!err) {
17
+ return emitter.emit('error', err);
18
+ }
19
+
20
+ emitter.emit('data', {update: 'chan_close'});
21
+ emitter.emit('data', {update: 'confirmation'});
22
+ emitter.emit('data', {update: 'unknown'});
23
+ emitter.emit('end', {});
24
+
25
+ if (!!data) {
26
+ emitter.emit('data', data);
27
+ } else {
28
+ emitter.emit('data', {
29
+ chan_pending: {
30
+ output_index: 0,
31
+ txid: Buffer.from('01020304', 'hex'),
32
+ },
33
+ update: 'chan_pending',
34
+ });
35
+ emitter.emit('error', 'err');
36
+ emitter.emit('status', {});
37
+ emitter.emit('data', {
38
+ chan_pending: {
39
+ output_index: 0,
40
+ txid: Buffer.from('01020304', 'hex'),
41
+ },
42
+ update: 'chan_pending',
43
+ });
44
+ emitter.emit('data', {update: 'chan_open'});
45
+ }
46
+ });
47
+
48
+
49
+ return emitter;
50
+ },
51
+ connectPeer: ({}, cbk) => cbk(null, {}),
52
+ listPeers: ({}, cbk) => cbk(null, {
53
+ peers: [{
54
+ address: 'address',
55
+ bytes_recv: '0',
56
+ bytes_sent: '0',
57
+ features: {},
58
+ inbound: false,
59
+ ping_time: '0',
60
+ pub_key: Buffer.alloc(33).toString('hex'),
61
+ sat_recv: '0',
62
+ sat_sent: '0',
63
+ sync_type: 'ACTIVE_SYNC',
64
+ }],
65
+ }),
66
+ },
67
+ wallet: {
68
+ deriveKey: ({}, cbk) => cbk(null, {
69
+ key_loc: {key_index: 0},
70
+ raw_key_bytes: Buffer.alloc(1),
71
+ }),
72
+ },
73
+ };
74
+
75
+ return lnd;
76
+ };
77
+
78
+ const makeArgs = overrides => {
79
+ const args = {
80
+ capacity: 1e6,
81
+ chain_fee_tokens_per_vbyte: 1,
82
+ close_address: 'close_address',
83
+ id: Buffer.alloc(32).toString('hex'),
84
+ key_index: 0,
85
+ lnd: makeLnd({}),
86
+ give_tokens: 1,
87
+ partner_public_key: Buffer.alloc(33).toString('hex'),
88
+ remote_key: Buffer.alloc(33, 2).toString('hex'),
89
+ transaction_id: Buffer.alloc(32).toString('hex'),
90
+ transaction_vout: 0,
91
+ };
92
+
93
+ Object.keys(overrides).forEach(k => args[k] = overrides[k]);
94
+
95
+ return args;
96
+ };
97
+
98
+ const makeStatus = details => {
99
+ return makeArgs({
100
+ lnd: {
101
+ default: {
102
+ openChannel: ({}) => {
103
+ const emitter = new EventEmitter();
104
+
105
+ process.nextTick(() => emitter.emit('status', {details}));
106
+
107
+ return emitter;
108
+ },
109
+ },
110
+ wallet: {
111
+ deriveKey: ({}, cbk) => cbk(null, {
112
+ key_loc: {key_index: 0},
113
+ raw_key_bytes: Buffer.alloc(1),
114
+ }),
115
+ },
116
+ },
117
+ });
118
+ };
119
+
120
+ const tests = [
121
+ {
122
+ args: makeArgs({capacity: undefined}),
123
+ description: 'Channel capacity is required',
124
+ error: [400, 'ExpectedCapacityTokensToProposeChannelOpen'],
125
+ },
126
+ {
127
+ args: makeArgs({id: undefined}),
128
+ description: 'Pending channel id is required',
129
+ error: [400, 'ExpectedPendingChannelIdToProposeChannelOpen'],
130
+ },
131
+ {
132
+ args: makeArgs({key_index: undefined}),
133
+ description: 'Key index is required',
134
+ error: [400, 'ExpectedMultiSigKeyIndexToProposeChannelOpen'],
135
+ },
136
+ {
137
+ args: makeArgs({lnd: undefined}),
138
+ description: 'LND is required',
139
+ error: [400, 'ExpectedLndToProposeChannelOpen'],
140
+ },
141
+ {
142
+ args: makeArgs({partner_public_key: undefined}),
143
+ description: 'A public key is required',
144
+ error: [400, 'ExpectedPartnerPublicKeyToProposeChannelOpen'],
145
+ },
146
+ {
147
+ args: makeArgs({remote_key: undefined}),
148
+ description: 'The remote multisig key is required',
149
+ error: [400, 'ExpectedRemoteMultiSigKeyToProposeChannelOpen'],
150
+ },
151
+ {
152
+ args: makeArgs({transaction_id: undefined}),
153
+ description: 'The transaction id is required',
154
+ error: [400, 'ExpectedFundingTransactionIdToProposeChanOpen'],
155
+ },
156
+ {
157
+ args: makeArgs({transaction_vout: undefined}),
158
+ description: 'The transaction output index is required',
159
+ error: [400, 'ExpectedFundingTransactionVoutToProposeChanOpen'],
160
+ },
161
+ {
162
+ args: makeArgs({lnd: makeLnd({err: 'err'})}),
163
+ description: 'An error is encountered',
164
+ error: [503, 'UnexpectedErrorProposingChannelToPeer'],
165
+ },
166
+ {
167
+ args: makeArgs({}),
168
+ description: 'A channel is proposed',
169
+ expected: {},
170
+ },
171
+ {
172
+ args: makeArgs({give_tokens: undefined}),
173
+ description: 'A channel is proposed with no gift',
174
+ expected: {},
175
+ },
176
+ ];
177
+
178
+ tests.forEach(({args, description, error, expected}) => {
179
+ return test(description, async ({end, rejects, strictSame}) => {
180
+ if (!!error) {
181
+ await rejects(proposeChannel(args), error, 'Got expected error');
182
+ } else {
183
+ const res = await proposeChannel(args);
184
+
185
+ strictSame(res, expected, 'Got expected result');
186
+ }
187
+
188
+ return end();
189
+ });
190
+ });
@@ -0,0 +1,82 @@
1
+ const {test} = require('@alexbosworth/tap');
2
+
3
+ const {rpcAddressesAsAddresses} = require('./../../lnd_responses');
4
+
5
+ const makeAddress = overrides => {
6
+ const args = {address: 'address', balance: '0', is_internal: false};
7
+
8
+ Object.keys(overrides).forEach(k => args[k] = overrides[k]);
9
+
10
+ return args;
11
+ };
12
+
13
+ const makeArgs = overrides => {
14
+ const args = {accounts: [{addresses: [makeAddress({})]}]};
15
+
16
+ Object.keys(overrides).forEach(k => args[k] = overrides[k]);
17
+
18
+ return args;
19
+ };
20
+
21
+ const makeExpected = overrides => {
22
+ const expected = {
23
+ addresses: [{address: 'address', is_change: false, tokens: 0}],
24
+ };
25
+
26
+ Object.keys(overrides).forEach(k => expected[k] = overrides[k]);
27
+
28
+ return expected;
29
+ };
30
+
31
+ const tests = [
32
+ {
33
+ args: makeArgs({accounts: undefined}),
34
+ description: 'Accounts with addresses are expected',
35
+ error: 'ExpectedArrayOfAccountsWithAddresses',
36
+ },
37
+ {
38
+ args: makeArgs({accounts: [{addresses: undefined}]}),
39
+ description: 'Accounts with addresses are expected',
40
+ error: 'ExpectedArrayOfAddressesInAccountWithAddresses',
41
+ },
42
+ {
43
+ args: makeArgs({
44
+ accounts: [{addresses: [makeAddress({address: undefined})]}],
45
+ }),
46
+ description: 'Accounts with address are expected',
47
+ error: 'ExpectedChainAddressInAccountAddress',
48
+ },
49
+ {
50
+ args: makeArgs({
51
+ accounts: [{addresses: [makeAddress({balance: undefined})]}],
52
+ }),
53
+ description: 'Accounts with balances are expected',
54
+ error: 'ExpectedBalanceTotalForAccountAddress',
55
+ },
56
+ {
57
+ args: makeArgs({
58
+ accounts: [{addresses: [makeAddress({is_internal: undefined})]}],
59
+ }),
60
+ description: 'Accounts with internal markers are expected',
61
+ error: 'ExpectedInternalAddressMarkerInAccountAddress',
62
+ },
63
+ {
64
+ args: makeArgs({}),
65
+ description: 'RPC addresses are mapped to addresses',
66
+ expected: makeExpected({}),
67
+ },
68
+ ];
69
+
70
+ tests.forEach(({args, description, error, expected}) => {
71
+ return test(description, ({end, strictSame, throws}) => {
72
+ if (!!error) {
73
+ throws(() => rpcAddressesAsAddresses(args), new Error(error), 'Got err');
74
+ } else {
75
+ const res = rpcAddressesAsAddresses(args);
76
+
77
+ strictSame(res, expected, 'Got expected result');
78
+ }
79
+
80
+ return end();
81
+ });
82
+ });
@@ -0,0 +1,26 @@
1
+ import {expectError, expectType} from 'tsd';
2
+ import {getBlock, GetBlockResult} from '../../lnd_methods';
3
+ import {AuthenticatedLnd} from '../../lnd_grpc';
4
+
5
+ const lnd = {} as AuthenticatedLnd;
6
+ const height = 0;
7
+ const id = 'id';
8
+
9
+ expectError(getBlock());
10
+ expectError(getBlock({}));
11
+ expectError(getBlock({lnd}));
12
+ expectError(getBlock({height, id}));
13
+
14
+ expectType<GetBlockResult>(await getBlock({lnd, height}));
15
+ expectType<GetBlockResult>(await getBlock({lnd, id}));
16
+
17
+ expectType<void>(
18
+ getBlock({lnd, height}, (error, result) => {
19
+ expectType<GetBlockResult>(result);
20
+ })
21
+ );
22
+ expectType<void>(
23
+ getBlock({lnd, id}, (error, result) => {
24
+ expectType<GetBlockResult>(result);
25
+ })
26
+ );
@@ -6,21 +6,34 @@ const lnd = {} as AuthenticatedLnd;
6
6
 
7
7
  const destination = 'destination';
8
8
  const tokens = 21;
9
+ const mtokens = '21';
9
10
 
10
11
  expectError(probeForRoute());
11
12
  expectError(probeForRoute({}));
13
+
12
14
  expectError(probeForRoute({lnd}));
13
15
  expectError(probeForRoute({destination}));
14
16
  expectError(probeForRoute({tokens}));
17
+ expectError(probeForRoute({mtokens}));
18
+
15
19
  expectError(probeForRoute({lnd, destination}));
16
20
  expectError(probeForRoute({lnd, tokens}));
21
+ expectError(probeForRoute({lnd, mtokens}));
17
22
 
18
23
  expectType<ProbeForRouteResult>(
19
24
  await probeForRoute({lnd, destination, tokens})
20
25
  );
26
+ expectType<ProbeForRouteResult>(
27
+ await probeForRoute({lnd, destination, mtokens})
28
+ );
21
29
 
22
30
  expectType<void>(
23
31
  probeForRoute({lnd, destination, tokens}, (error, result) => {
24
32
  expectType<ProbeForRouteResult>(result);
25
33
  })
26
34
  );
35
+ expectType<void>(
36
+ probeForRoute({lnd, destination, mtokens}, (error, result) => {
37
+ expectType<ProbeForRouteResult>(result);
38
+ })
39
+ );