@bitcoinerlab/descriptors 1.1.1 → 2.0.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.
package/dist/index.d.ts CHANGED
@@ -1,23 +1,43 @@
1
1
  export type { KeyInfo, Expansion } from './types';
2
2
  import type { Psbt } from 'bitcoinjs-lib';
3
- import type { DescriptorInstance } from './descriptors';
4
- export { DescriptorsFactory, DescriptorInstance, DescriptorConstructor } from './descriptors';
3
+ import type { DescriptorInstance, OutputInstance } from './descriptors';
4
+ export { DescriptorsFactory, DescriptorInstance, DescriptorConstructor, OutputInstance, OutputConstructor } from './descriptors';
5
5
  export { DescriptorChecksum as checksum } from './checksum';
6
6
  import * as signers from './signers';
7
7
  export { signers };
8
- export declare function finalizePsbt({ psbt, descriptors, validate }: {
8
+ /**
9
+ * @hidden @deprecated
10
+ * To finalize the `psbt`, you can either call the method
11
+ * `output.finalizePsbtInput({ index, psbt })` on each descriptor, passing as
12
+ * arguments the `psbt` and its input `index`, or call this helper function:
13
+ * `finalizePsbt({psbt, outputs })`. In the latter case, `outputs` is an
14
+ * array of {@link _Internal_.Output | Output elements} ordered in the array by
15
+ * their respective input index in the `psbt`.
16
+ */
17
+ declare function finalizePsbt(params: {
18
+ psbt: Psbt;
19
+ outputs: OutputInstance[];
20
+ validate?: boolean | undefined;
21
+ }): void;
22
+ /**
23
+ * @deprecated
24
+ * @hidden
25
+ * To be removed in version 3.0
26
+ */
27
+ declare function finalizePsbt(params: {
9
28
  psbt: Psbt;
10
29
  descriptors: DescriptorInstance[];
11
30
  validate?: boolean | undefined;
12
31
  }): void;
32
+ export { finalizePsbt };
13
33
  export { keyExpressionBIP32, keyExpressionLedger } from './keyExpressions';
14
34
  import * as scriptExpressions from './scriptExpressions';
15
35
  export { scriptExpressions };
16
- import { LedgerState, getLedgerMasterFingerPrint, getLedgerXpub, registerLedgerWallet, assertLedgerApp } from './ledger';
36
+ import { LedgerState, getLedgerMasterFingerPrint, getLedgerXpub, registerLedgerWallet, assertLedgerApp, LedgerManager } from './ledger';
17
37
  export declare const ledger: {
18
38
  getLedgerMasterFingerPrint: typeof getLedgerMasterFingerPrint;
19
39
  getLedgerXpub: typeof getLedgerXpub;
20
40
  registerLedgerWallet: typeof registerLedgerWallet;
21
41
  assertLedgerApp: typeof assertLedgerApp;
22
42
  };
23
- export type { LedgerState };
43
+ export type { LedgerState, LedgerManager };
package/dist/index.js CHANGED
@@ -32,8 +32,18 @@ var checksum_1 = require("./checksum");
32
32
  Object.defineProperty(exports, "checksum", { enumerable: true, get: function () { return checksum_1.DescriptorChecksum; } });
33
33
  const signers = __importStar(require("./signers"));
34
34
  exports.signers = signers;
35
- function finalizePsbt({ psbt, descriptors, validate = true }) {
36
- descriptors.forEach((descriptor, inputIndex) => descriptor.finalizePsbtInput({ index: inputIndex, psbt, validate }));
35
+ /**
36
+ * @hidden
37
+ * To be removed in v3.0 and replaced by the version with the signature that
38
+ * does not accept descriptors
39
+ */
40
+ function finalizePsbt({ psbt, outputs, descriptors, validate = true }) {
41
+ if (descriptors && outputs)
42
+ throw new Error(`descriptors param has been deprecated`);
43
+ outputs = descriptors || outputs;
44
+ if (!outputs)
45
+ throw new Error(`outputs not provided`);
46
+ outputs.forEach((output, inputIndex) => output.finalizePsbtInput({ index: inputIndex, psbt, validate }));
37
47
  }
38
48
  exports.finalizePsbt = finalizePsbt;
39
49
  var keyExpressions_1 = require("./keyExpressions");
@@ -2,22 +2,59 @@ import { Network } from 'bitcoinjs-lib';
2
2
  import type { ECPairAPI } from 'ecpair';
3
3
  import type { BIP32API, BIP32Interface } from 'bip32';
4
4
  import type { KeyInfo } from './types';
5
- import { LedgerState } from './ledger';
5
+ import { LedgerState, LedgerManager } from './ledger';
6
6
  /**
7
- * Parses a key expression (xpub, xprv, pubkey or wif) into KeyInfo
7
+ * Parses a key expression (xpub, xprv, pubkey or wif) into {@link KeyInfo | `KeyInfo`}.
8
+ *
9
+ * For example, given this `keyExpression`: `"[d34db33f/49'/0'/0']tpubDCdxmvzJ5QBjTN8oCjjyT2V58AyZvA1fkmCeZRC75QMoaHcVP2m45Bv3hmnR7ttAwkb2UNYyoXdHVt4gwBqRrJqLUU2JrM43HippxiWpHra/1/2/3/4/*"`, this is its parsed result:
10
+ *
11
+ * ```javascript
12
+ * {
13
+ * keyExpression:
14
+ * "[d34db33f/49'/0'/0']tpubDCdxmvzJ5QBjTN8oCjjyT2V58AyZvA1fkmCeZRC75QMoaHcVP2m45Bv3hmnR7ttAwkb2UNYyoXdHVt4gwBqRrJqLUU2JrM43HippxiWpHra/1/2/3/4/*",
15
+ * keyPath: '/1/2/3/4/*',
16
+ * originPath: "/49'/0'/0'",
17
+ * path: "m/49'/0'/0'/1/2/3/4/*",
18
+ * // Other relevant properties of the type `KeyInfo`: `pubkey`, `ecpair` & `bip32` interfaces, `masterFingerprint`, etc.
19
+ * }
20
+ * ```
8
21
  */
9
22
  export declare function parseKeyExpression({ keyExpression, isSegwit, ECPair, BIP32, network }: {
10
23
  keyExpression: string;
24
+ /** @default networks.bitcoin */
11
25
  network?: Network;
12
26
  /**
13
- * Indicates if this is a SegWit key expression. When set, further checks
14
- * ensure the public key (if present in the expression) is compressed
15
- * (33 bytes).
27
+ * Indicates if this key expression belongs to a a SegWit output. When set,
28
+ * further checks are done to ensure the public key (if present in the
29
+ * expression) is compressed (33 bytes).
16
30
  */
17
31
  isSegwit?: boolean;
18
32
  ECPair: ECPairAPI;
19
33
  BIP32: BIP32API;
20
34
  }): KeyInfo;
35
+ /**
36
+ * Constructs a key expression string for a Ledger device from the provided
37
+ * components.
38
+ *
39
+ * This function assists in crafting key expressions tailored for Ledger
40
+ * hardware wallets. It fetches the master fingerprint and xpub for a
41
+ * specified origin path and then combines them with the input parameters.
42
+ *
43
+ * For detailed understanding and examples of terms like `originPath`,
44
+ * `change`, and `keyPath`, refer to the documentation of
45
+ * {@link _Internal_.ParseKeyExpression | ParseKeyExpression}, which consists
46
+ * of the reverse procedure.
47
+ *
48
+ * @returns {string} - The formed key expression for the Ledger device.
49
+ */
50
+ export declare function keyExpressionLedger({ ledgerManager, originPath, keyPath, change, index }: {
51
+ ledgerManager: LedgerManager;
52
+ originPath: string;
53
+ change?: number | undefined;
54
+ index?: number | undefined | '*';
55
+ keyPath?: string | undefined;
56
+ }): Promise<string>;
57
+ /** @deprecated @hidden */
21
58
  export declare function keyExpressionLedger({ ledgerClient, ledgerState, originPath, keyPath, change, index }: {
22
59
  ledgerClient: unknown;
23
60
  ledgerState: LedgerState;
@@ -26,11 +63,23 @@ export declare function keyExpressionLedger({ ledgerClient, ledgerState, originP
26
63
  index?: number | undefined | '*';
27
64
  keyPath?: string | undefined;
28
65
  }): Promise<string>;
66
+ /**
67
+ * Constructs a key expression string from its constituent components.
68
+ *
69
+ * This function essentially performs the reverse operation of
70
+ * {@link _Internal_.ParseKeyExpression | ParseKeyExpression}. For detailed
71
+ * explanations and examples of the terms used here, refer to
72
+ * {@link _Internal_.ParseKeyExpression | ParseKeyExpression}.
73
+ */
29
74
  export declare function keyExpressionBIP32({ masterNode, originPath, keyPath, change, index, isPublic }: {
30
75
  masterNode: BIP32Interface;
31
76
  originPath: string;
32
77
  change?: number | undefined;
33
78
  index?: number | undefined | '*';
34
79
  keyPath?: string | undefined;
80
+ /**
81
+ * Compute an xpub or xprv
82
+ * @default true
83
+ */
35
84
  isPublic?: boolean;
36
85
  }): string;
@@ -44,7 +44,20 @@ const derivePath = (node, path) => {
44
44
  return node.derivePath(parsedPath);
45
45
  };
46
46
  /**
47
- * Parses a key expression (xpub, xprv, pubkey or wif) into KeyInfo
47
+ * Parses a key expression (xpub, xprv, pubkey or wif) into {@link KeyInfo | `KeyInfo`}.
48
+ *
49
+ * For example, given this `keyExpression`: `"[d34db33f/49'/0'/0']tpubDCdxmvzJ5QBjTN8oCjjyT2V58AyZvA1fkmCeZRC75QMoaHcVP2m45Bv3hmnR7ttAwkb2UNYyoXdHVt4gwBqRrJqLUU2JrM43HippxiWpHra/1/2/3/4/*"`, this is its parsed result:
50
+ *
51
+ * ```javascript
52
+ * {
53
+ * keyExpression:
54
+ * "[d34db33f/49'/0'/0']tpubDCdxmvzJ5QBjTN8oCjjyT2V58AyZvA1fkmCeZRC75QMoaHcVP2m45Bv3hmnR7ttAwkb2UNYyoXdHVt4gwBqRrJqLUU2JrM43HippxiWpHra/1/2/3/4/*",
55
+ * keyPath: '/1/2/3/4/*',
56
+ * originPath: "/49'/0'/0'",
57
+ * path: "m/49'/0'/0'/1/2/3/4/*",
58
+ * // Other relevant properties of the type `KeyInfo`: `pubkey`, `ecpair` & `bip32` interfaces, `masterFingerprint`, etc.
59
+ * }
60
+ * ```
48
61
  */
49
62
  function parseKeyExpression({ keyExpression, isSegwit, ECPair, BIP32, network = bitcoinjs_lib_1.networks.bitcoin }) {
50
63
  let pubkey; //won't be computed for ranged keyExpressions
@@ -167,7 +180,14 @@ function assertChangeIndexKeyPath({ change, index, keyPath }) {
167
180
  if ((change !== undefined) === (keyPath !== undefined))
168
181
  throw new Error(`Error: Pass either change and index or a keyPath`);
169
182
  }
170
- async function keyExpressionLedger({ ledgerClient, ledgerState, originPath, keyPath, change, index }) {
183
+ /** @hidden */
184
+ async function keyExpressionLedger({ ledgerClient, ledgerState, ledgerManager, originPath, keyPath, change, index }) {
185
+ if (ledgerManager && (ledgerClient || ledgerState))
186
+ throw new Error(`ledgerClient and ledgerState have been deprecated`);
187
+ if (ledgerManager)
188
+ ({ ledgerClient, ledgerState } = ledgerManager);
189
+ if (!ledgerClient || !ledgerState)
190
+ throw new Error(`Could not retrieve ledgerClient or ledgerState`);
171
191
  assertChangeIndexKeyPath({ change, index, keyPath });
172
192
  const masterFingerprint = await (0, ledger_1.getLedgerMasterFingerPrint)({
173
193
  ledgerClient,
@@ -182,6 +202,14 @@ async function keyExpressionLedger({ ledgerClient, ledgerState, originPath, keyP
182
202
  return `${keyRoot}/${change}/${index}`;
183
203
  }
184
204
  exports.keyExpressionLedger = keyExpressionLedger;
205
+ /**
206
+ * Constructs a key expression string from its constituent components.
207
+ *
208
+ * This function essentially performs the reverse operation of
209
+ * {@link _Internal_.ParseKeyExpression | ParseKeyExpression}. For detailed
210
+ * explanations and examples of the terms used here, refer to
211
+ * {@link _Internal_.ParseKeyExpression | ParseKeyExpression}.
212
+ */
185
213
  function keyExpressionBIP32({ masterNode, originPath, keyPath, change, index, isPublic = true }) {
186
214
  assertChangeIndexKeyPath({ change, index, keyPath });
187
215
  const masterFingerprint = masterNode.fingerprint;
package/dist/ledger.d.ts CHANGED
@@ -1,5 +1,7 @@
1
1
  /// <reference types="node" />
2
- import type { DescriptorInstance } from './descriptors';
2
+ import { DescriptorInstance, OutputInstance } from './descriptors';
3
+ import { Network, Psbt } from 'bitcoinjs-lib';
4
+ import type { TinySecp256k1Interface } from './types';
3
5
  /**
4
6
  * Dynamically imports the 'ledger-bitcoin' module and, if provided, checks if `ledgerClient` is an instance of `AppClient`.
5
7
  *
@@ -19,9 +21,28 @@ import type { DescriptorInstance } from './descriptors';
19
21
  * .catch((error) => console.error(error));
20
22
  */
21
23
  export declare function importAndValidateLedgerBitcoin(ledgerClient?: unknown): Promise<unknown>;
24
+ /**
25
+ * Verifies if the Ledger device is connected, if the required Bitcoin App is opened,
26
+ * and if the version of the app meets the minimum requirements.
27
+ *
28
+ * @throws Will throw an error if the Ledger device is not connected, the required
29
+ * Bitcoin App is not opened, or if the version is below the required number.
30
+ *
31
+ * @returns Promise<void> - A promise that resolves if all assertions pass, or throws otherwise.
32
+ */
22
33
  export declare function assertLedgerApp({ transport, name, minVersion }: {
34
+ /**
35
+ * Connection transport with the Ledger device.
36
+ * One of these: https://github.com/LedgerHQ/ledger-live#libs---libraries
37
+ */
23
38
  transport: any;
39
+ /**
40
+ * The name of the Bitcoin App. "Bitcoin" for mainnet or "Bitcoin Test" for testnet.
41
+ */
24
42
  name: string;
43
+ /**
44
+ * The minimum acceptable version of the Bitcoin App in semver format (major.minor.patch).
45
+ */
25
46
  minVersion: string;
26
47
  }): Promise<void>;
27
48
  export type LedgerPolicy = {
@@ -31,6 +52,11 @@ export type LedgerPolicy = {
31
52
  policyId?: Buffer;
32
53
  policyHmac?: Buffer;
33
54
  };
55
+ /**
56
+ * Ledger devices operate in a state-less manner. Therefore, policy information
57
+ * needs to be maintained in a separate data structure, `ledgerState`. For optimization,
58
+ * `ledgerState` also stores cached xpubs and the masterFingerprint.
59
+ */
34
60
  export type LedgerState = {
35
61
  masterFingerprint?: Buffer;
36
62
  policies?: LedgerPolicy[];
@@ -38,17 +64,49 @@ export type LedgerState = {
38
64
  [key: string]: string;
39
65
  };
40
66
  };
67
+ export type LedgerManager = {
68
+ ledgerClient: unknown;
69
+ ledgerState: LedgerState;
70
+ ecc: TinySecp256k1Interface;
71
+ network: Network;
72
+ };
73
+ /** Retrieves the masterFingerPrint of a Ledger device */
74
+ export declare function getLedgerMasterFingerPrint({ ledgerManager }: {
75
+ ledgerManager: LedgerManager;
76
+ }): Promise<Buffer>;
77
+ /** @deprecated @hidden */
41
78
  export declare function getLedgerMasterFingerPrint({ ledgerClient, ledgerState }: {
42
79
  ledgerClient: unknown;
43
80
  ledgerState: LedgerState;
44
81
  }): Promise<Buffer>;
82
+ /** Retrieves the xpub of a certain originPath of a Ledger device */
83
+ export declare function getLedgerXpub({ originPath, ledgerManager }: {
84
+ originPath: string;
85
+ ledgerManager: LedgerManager;
86
+ }): Promise<string>;
87
+ /** @deprecated @hidden */
45
88
  export declare function getLedgerXpub({ originPath, ledgerClient, ledgerState }: {
46
89
  originPath: string;
47
90
  ledgerClient: unknown;
48
91
  ledgerState: LedgerState;
49
92
  }): Promise<string>;
50
93
  /**
51
- * Takes a descriptor and gets its Ledger Wallet Policy, that is, its keyRoots and template.
94
+ * Checks whether there is a policy in ledgerState that the ledger
95
+ * could use to sign this psbt input.
96
+ *
97
+ * It found return the policy, otherwise, return undefined
98
+ *
99
+ * All considerations in the header of this file are applied
100
+ */
101
+ export declare function ledgerPolicyFromPsbtInput({ ledgerManager, psbt, index }: {
102
+ ledgerManager: LedgerManager;
103
+ psbt: Psbt;
104
+ index: number;
105
+ }): Promise<LedgerPolicy | undefined>;
106
+ /**
107
+ * Given an output, it extracts its descriptor and converts it to a Ledger
108
+ * Wallet Policy, that is, its keyRoots and template.
109
+ *
52
110
  * keyRoots and template follow Ledger's specifications:
53
111
  * https://github.com/LedgerHQ/app-bitcoin-new/blob/develop/doc/wallet.md
54
112
  *
@@ -72,8 +130,8 @@ export declare function getLedgerXpub({ originPath, ledgerClient, ledgerState }:
72
130
  * This function takes into account all the considerations regarding Ledger
73
131
  * policy implementation details expressed in the header of this file.
74
132
  */
75
- export declare function descriptorToLedgerFormat({ descriptor, ledgerClient, ledgerState }: {
76
- descriptor: DescriptorInstance;
133
+ export declare function ledgerPolicyFromOutput({ output, ledgerClient, ledgerState }: {
134
+ output: OutputInstance;
77
135
  ledgerClient: unknown;
78
136
  ledgerState: LedgerState;
79
137
  }): Promise<{
@@ -81,12 +139,31 @@ export declare function descriptorToLedgerFormat({ descriptor, ledgerClient, led
81
139
  keyRoots: string[];
82
140
  } | null>;
83
141
  /**
84
- * It registers a policy based on a descriptor. It stores it in ledgerState.
142
+ * Registers a policy based on a provided descriptor.
85
143
  *
86
- * If the policy was already registered, it does not register it.
87
- * If the policy is standard, it does not register it.
144
+ * This function will:
145
+ * 1. Store the policy in `ledgerState` inside the `ledgerManager`.
146
+ * 2. Avoid re-registering if the policy was previously registered.
147
+ * 3. Skip registration if the policy is considered "standard".
88
148
  *
89
- **/
149
+ * It's important to understand the nature of the Ledger Policy being registered:
150
+ * - While a descriptor might point to a specific output index of a particular change address,
151
+ * the corresponding Ledger Policy abstracts this and represents potential outputs for
152
+ * all addresses (both external and internal).
153
+ * - This means that the registered Ledger Policy is a generalized version of the descriptor,
154
+ * not assuming specific values for the keyPath.
155
+ *
156
+ */
157
+ export declare function registerLedgerWallet({ descriptor, ledgerManager, policyName }: {
158
+ descriptor: string;
159
+ ledgerManager: LedgerManager;
160
+ /** The Name we want to assign to this specific policy */
161
+ policyName: string;
162
+ }): Promise<void>;
163
+ /**
164
+ * @deprecated
165
+ * @hidden
166
+ */
90
167
  export declare function registerLedgerWallet({ descriptor, ledgerClient, ledgerState, policyName }: {
91
168
  descriptor: DescriptorInstance;
92
169
  ledgerClient: unknown;
@@ -96,8 +173,8 @@ export declare function registerLedgerWallet({ descriptor, ledgerClient, ledgerS
96
173
  /**
97
174
  * Retrieve a standard ledger policy or null if it does correspond.
98
175
  **/
99
- export declare function ledgerPolicyFromStandard({ descriptor, ledgerClient, ledgerState }: {
100
- descriptor: DescriptorInstance;
176
+ export declare function ledgerPolicyFromStandard({ output, ledgerClient, ledgerState }: {
177
+ output: OutputInstance;
101
178
  ledgerClient: unknown;
102
179
  ledgerState: LedgerState;
103
180
  }): Promise<LedgerPolicy | null>;
@@ -105,8 +182,8 @@ export declare function comparePolicies(policyA: LedgerPolicy, policyB: LedgerPo
105
182
  /**
106
183
  * Retrieve a ledger policy from ledgerState or null if it does not exist yet.
107
184
  **/
108
- export declare function ledgerPolicyFromState({ descriptor, ledgerClient, ledgerState }: {
109
- descriptor: DescriptorInstance;
185
+ export declare function ledgerPolicyFromState({ output, ledgerClient, ledgerState }: {
186
+ output: OutputInstance;
110
187
  ledgerClient: unknown;
111
188
  ledgerState: LedgerState;
112
189
  }): Promise<LedgerPolicy | null>;