@bitcoinerlab/descriptors-core 3.1.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.
Files changed (76) hide show
  1. package/README.md +710 -0
  2. package/dist/adapters/applyPR2137.d.ts +2 -0
  3. package/dist/adapters/applyPR2137.js +150 -0
  4. package/dist/adapters/bitcoinjs.d.ts +8 -0
  5. package/dist/adapters/bitcoinjs.js +36 -0
  6. package/dist/adapters/scure/address.d.ts +2 -0
  7. package/dist/adapters/scure/address.js +50 -0
  8. package/dist/adapters/scure/bip32.d.ts +2 -0
  9. package/dist/adapters/scure/bip32.js +16 -0
  10. package/dist/adapters/scure/common.d.ts +14 -0
  11. package/dist/adapters/scure/common.js +36 -0
  12. package/dist/adapters/scure/ecpair.d.ts +2 -0
  13. package/dist/adapters/scure/ecpair.js +58 -0
  14. package/dist/adapters/scure/payments.d.ts +2 -0
  15. package/dist/adapters/scure/payments.js +216 -0
  16. package/dist/adapters/scure/psbt.d.ts +43 -0
  17. package/dist/adapters/scure/psbt.js +382 -0
  18. package/dist/adapters/scure/script.d.ts +20 -0
  19. package/dist/adapters/scure/script.js +163 -0
  20. package/dist/adapters/scure/transaction.d.ts +2 -0
  21. package/dist/adapters/scure/transaction.js +32 -0
  22. package/dist/adapters/scure.d.ts +6 -0
  23. package/dist/adapters/scure.js +37 -0
  24. package/dist/adapters/scureKeys.d.ts +4 -0
  25. package/dist/adapters/scureKeys.js +135 -0
  26. package/dist/bip174.d.ts +87 -0
  27. package/dist/bip174.js +12 -0
  28. package/dist/bitcoinLib.d.ts +385 -0
  29. package/dist/bitcoinLib.js +19 -0
  30. package/dist/bitcoinjs-lib-internals.d.ts +6 -0
  31. package/dist/bitcoinjs-lib-internals.js +60 -0
  32. package/dist/bitcoinjs.d.ts +12 -0
  33. package/dist/bitcoinjs.js +18 -0
  34. package/dist/checksum.d.ts +6 -0
  35. package/dist/checksum.js +58 -0
  36. package/dist/crypto.d.ts +3 -0
  37. package/dist/crypto.js +79 -0
  38. package/dist/descriptors.d.ts +481 -0
  39. package/dist/descriptors.js +1888 -0
  40. package/dist/index.d.ts +23 -0
  41. package/dist/index.js +87 -0
  42. package/dist/keyExpressions.d.ts +124 -0
  43. package/dist/keyExpressions.js +310 -0
  44. package/dist/keyInterfaces.d.ts +5 -0
  45. package/dist/keyInterfaces.js +50 -0
  46. package/dist/ledger.d.ts +183 -0
  47. package/dist/ledger.js +618 -0
  48. package/dist/miniscript.d.ts +125 -0
  49. package/dist/miniscript.js +310 -0
  50. package/dist/multipath.d.ts +13 -0
  51. package/dist/multipath.js +76 -0
  52. package/dist/networkUtils.d.ts +3 -0
  53. package/dist/networkUtils.js +16 -0
  54. package/dist/networks.d.ts +16 -0
  55. package/dist/networks.js +31 -0
  56. package/dist/parseUtils.d.ts +7 -0
  57. package/dist/parseUtils.js +46 -0
  58. package/dist/psbt.d.ts +40 -0
  59. package/dist/psbt.js +228 -0
  60. package/dist/re.d.ts +31 -0
  61. package/dist/re.js +79 -0
  62. package/dist/resourceLimits.d.ts +28 -0
  63. package/dist/resourceLimits.js +84 -0
  64. package/dist/scriptExpressions.d.ts +95 -0
  65. package/dist/scriptExpressions.js +98 -0
  66. package/dist/scure.d.ts +4 -0
  67. package/dist/scure.js +10 -0
  68. package/dist/signers.d.ts +161 -0
  69. package/dist/signers.js +324 -0
  70. package/dist/tapMiniscript.d.ts +231 -0
  71. package/dist/tapMiniscript.js +524 -0
  72. package/dist/tapTree.d.ts +91 -0
  73. package/dist/tapTree.js +166 -0
  74. package/dist/types.d.ts +296 -0
  75. package/dist/types.js +4 -0
  76. package/package.json +148 -0
@@ -0,0 +1,166 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MAX_TAPTREE_DEPTH = void 0;
4
+ exports.assertTapTreeDepth = assertTapTreeDepth;
5
+ exports.collectTapTreeLeaves = collectTapTreeLeaves;
6
+ exports.selectTapLeafCandidates = selectTapLeafCandidates;
7
+ exports.parseTapTreeExpression = parseTapTreeExpression;
8
+ const bitcoinjs_lib_internals_1 = require("./bitcoinjs-lib-internals");
9
+ const uint8array_tools_1 = require("uint8array-tools");
10
+ const parseUtils_1 = require("./parseUtils");
11
+ // See BIP341 control block limits and Sipa's Miniscript "Resource limitations":
12
+ // https://bitcoin.sipa.be/miniscript/
13
+ // Taproot script path depth is encoded in the control block as 32-byte hashes,
14
+ // with consensus max depth 128.
15
+ exports.MAX_TAPTREE_DEPTH = 128;
16
+ function tapTreeMaxDepth(tapTree, depth = 0) {
17
+ if ('expression' in tapTree)
18
+ return depth;
19
+ return Math.max(tapTreeMaxDepth(tapTree.left, depth + 1), tapTreeMaxDepth(tapTree.right, depth + 1));
20
+ }
21
+ function assertTapTreeDepth(tapTree) {
22
+ const maxDepth = tapTreeMaxDepth(tapTree);
23
+ if (maxDepth > exports.MAX_TAPTREE_DEPTH)
24
+ throw new Error(`Error: taproot tree depth is too large, ${maxDepth} is larger than ${exports.MAX_TAPTREE_DEPTH}`);
25
+ }
26
+ /**
27
+ * Collects taproot leaf metadata with depth from a tree.
28
+ * Traversal is left-first, following the order of `{left,right}` in the
29
+ * expression so tie-breaks are deterministic.
30
+ *
31
+ * Example tree:
32
+ * ```
33
+ * {pk(A),{pk(B),pk(C)}}
34
+ * ```
35
+ * Visual shape:
36
+ * ```
37
+ * root
38
+ * / \
39
+ * pk(A) branch
40
+ * / \
41
+ * pk(B) pk(C)
42
+ * ```
43
+ * Collected leaves with depth:
44
+ * ```
45
+ * [
46
+ * { leaf: pk(A), depth: 1 },
47
+ * { leaf: pk(B), depth: 2 },
48
+ * { leaf: pk(C), depth: 2 }
49
+ * ]
50
+ * ```
51
+ */
52
+ function collectTapTreeLeaves(tapTreeInfo) {
53
+ const leaves = [];
54
+ const walk = (node, depth) => {
55
+ if ('expression' in node) {
56
+ leaves.push({ leaf: node, depth });
57
+ return;
58
+ }
59
+ walk(node.left, depth + 1);
60
+ walk(node.right, depth + 1);
61
+ };
62
+ walk(tapTreeInfo, 0);
63
+ return leaves;
64
+ }
65
+ function computeTapLeafHash(leaf) {
66
+ return (0, bitcoinjs_lib_internals_1.tapleafHash)({ output: leaf.tapScript, version: leaf.version });
67
+ }
68
+ function normalizeExpressionForMatch(expression) {
69
+ return expression.replace(/\s+/g, '');
70
+ }
71
+ /**
72
+ * Resolves taproot leaf candidates based on an optional selector.
73
+ *
74
+ * If `tapLeaf` is undefined, all leaves are returned for auto-selection.
75
+ * If `tapLeaf` is bytes, it is treated as a tapleaf hash and must match
76
+ * exactly one leaf.
77
+ * If `tapLeaf` is a string, it is treated as a raw taproot leaf expression
78
+ * (not expanded). Matching is whitespace-insensitive. If the expression appears
79
+ * more than once, this function throws an error.
80
+ *
81
+ * Example:
82
+ * ```
83
+ * const candidates = selectTapLeafCandidates({ tapTreeInfo, tapLeaf });
84
+ * // tapLeaf can be undefined, bytes (tapleaf hash) or a leaf expression:
85
+ * // f.ex.: 'pk(03bb...)'
86
+ * ```
87
+ */
88
+ function selectTapLeafCandidates({ tapTreeInfo, tapLeaf }) {
89
+ const leaves = collectTapTreeLeaves(tapTreeInfo).map(({ leaf, depth }) => ({
90
+ leaf,
91
+ depth,
92
+ tapLeafHash: computeTapLeafHash(leaf)
93
+ }));
94
+ if (tapLeaf === undefined)
95
+ return leaves;
96
+ if (tapLeaf instanceof Uint8Array) {
97
+ const match = leaves.find(entry => (0, uint8array_tools_1.compare)(entry.tapLeafHash, tapLeaf) === 0);
98
+ if (!match)
99
+ throw new Error(`Error: tapleaf hash not found in tapTreeInfo`);
100
+ return [match];
101
+ }
102
+ const normalizedSelector = normalizeExpressionForMatch(tapLeaf);
103
+ const matches = leaves.filter(entry => normalizeExpressionForMatch(entry.leaf.expression) === normalizedSelector);
104
+ if (matches.length === 0)
105
+ throw new Error(`Error: taproot leaf expression not found in tapTreeInfo: ${tapLeaf}`);
106
+ if (matches.length > 1)
107
+ throw new Error(`Error: taproot leaf expression is ambiguous in tapTreeInfo: ${tapLeaf}`);
108
+ return matches;
109
+ }
110
+ function tapTreeError(expression) {
111
+ return new Error(`Error: invalid taproot tree expression: ${expression}`);
112
+ }
113
+ /**
114
+ * Splits the inner tree expression of a branch into left/right parts.
115
+ * The input must be the contents inside `{}` (no outer braces).
116
+ * Example: `pk(@0),{pk(@1),pk(@2)}` => left: `pk(@0)`, right: `{pk(@1),pk(@2)}`.
117
+ */
118
+ function splitTapTreeExpression(expression) {
119
+ const result = (0, parseUtils_1.splitTopLevelComma)({ expression, onError: tapTreeError });
120
+ if (!result)
121
+ throw tapTreeError(expression);
122
+ return result;
123
+ }
124
+ /**
125
+ * Parses a single taproot tree node expression.
126
+ *
127
+ * Note: the field name is intentionally generic (`expression`) because taproot
128
+ * leaves can contain either miniscript fragments (e.g. `pk(...)`) or
129
+ * descriptor-level script expressions (e.g. `sortedmulti_a(...)`).
130
+ * Examples:
131
+ * - `pk(@0)` => { expression: 'pk(@0)' }
132
+ * - `{pk(@0),pk(@1)}` => { left: { expression: 'pk(@0)' }, right: { expression: 'pk(@1)' } }
133
+ * - `{pk(@0),{pk(@1),pk(@2)}}` =>
134
+ * {
135
+ * left: { expression: 'pk(@0)' },
136
+ * right: { left: { expression: 'pk(@1)' }, right: { expression: 'pk(@2)' } }
137
+ * }
138
+ */
139
+ function parseTapTreeNode(expression) {
140
+ const trimmedExpression = expression.trim();
141
+ if (!trimmedExpression)
142
+ throw tapTreeError(expression);
143
+ if (trimmedExpression.startsWith('{')) {
144
+ if (!trimmedExpression.endsWith('}'))
145
+ throw tapTreeError(expression);
146
+ const inner = trimmedExpression.slice(1, -1).trim();
147
+ if (!inner)
148
+ throw tapTreeError(expression);
149
+ const { left, right } = splitTapTreeExpression(inner);
150
+ return {
151
+ left: parseTapTreeNode(left),
152
+ right: parseTapTreeNode(right)
153
+ };
154
+ }
155
+ if (trimmedExpression.includes('{') || trimmedExpression.includes('}'))
156
+ throw tapTreeError(expression);
157
+ return { expression: trimmedExpression };
158
+ }
159
+ function parseTapTreeExpression(expression) {
160
+ const trimmed = expression.trim();
161
+ if (!trimmed)
162
+ throw tapTreeError(expression);
163
+ const tapTree = parseTapTreeNode(trimmed);
164
+ assertTapTreeDepth(tapTree);
165
+ return tapTree;
166
+ }
@@ -0,0 +1,296 @@
1
+ import type { Payment, ECPairInterfaceLike, BIP32InterfaceLike } from './bitcoinLib';
2
+ import type { Network } from './networks';
3
+ import type { TapTreeNode, TapTreeInfoNode } from './tapTree';
4
+ /**
5
+ * Preimage
6
+ * Preimage material used by descriptor outputs that include hashlocks.
7
+ */
8
+ export type Preimage = {
9
+ /**
10
+ * Use same string expressions as in miniscript. For example: "sha256(cdabb7f2dce7bfbd8a0b9570c6fd1e712e5d64045e9d6b517b3d5072251dc204)" or "ripemd160(095ff41131e5946f3c85f79e44adbcf8e27e080e)"
11
+ *
12
+ * Accepted functions: sha256, hash256, ripemd160, hash160
13
+ *
14
+ * Digest hex lengths by function:
15
+ * - `sha256`, `hash256`: 64 hex chars (32 bytes)
16
+ * - `ripemd160`, `hash160`: 40 hex chars (20 bytes)
17
+ */
18
+ digest: string;
19
+ /**
20
+ * Hex encoded preimage. Preimages are always 32 bytes (so, 64 character in hex).
21
+ */
22
+ preimage: string;
23
+ };
24
+ export type TimeConstraints = {
25
+ nLockTime: number | undefined;
26
+ nSequence: number | undefined;
27
+ };
28
+ /**
29
+ * Parsed key-expression metadata.
30
+ *
31
+ * See {@link KeyExpressionParser}.
32
+ */
33
+ export type KeyInfo = {
34
+ /** Original key expression string. */
35
+ keyExpression: string;
36
+ /**
37
+ * Concrete public key when derivable.
38
+ *
39
+ * This is usually set unless the key expression is ranged (`*`).
40
+ * For taproot keys this is x-only (32 bytes).
41
+ */
42
+ pubkey?: Uint8Array;
43
+ /**
44
+ * bitcoinjs-compatible single-key signer (when derivable from the expression).
45
+ */
46
+ ecpair?: ECPairInterfaceLike;
47
+ /**
48
+ * bitcoinjs-compatible HD node (when derivable from the expression).
49
+ */
50
+ bip32?: BIP32InterfaceLike;
51
+ /** Raw private key bytes, when available. */
52
+ privkey?: Uint8Array;
53
+ /** Parsed extended public key, when present in the expression. */
54
+ xPub?: string;
55
+ /** Parsed extended private key, when present in the expression. */
56
+ xPrv?: string;
57
+ /** BIP32 master fingerprint, when available. */
58
+ masterFingerprint?: Uint8Array;
59
+ /** Path from `masterFingerprint` to the xpub/xprv root. */
60
+ originPath?: string;
61
+ /** Path from the xpub/xprv root. */
62
+ keyPath?: string;
63
+ /**
64
+ * Full path from the master.
65
+ *
66
+ * Format: `m/val/val/...`, where `val` is an integer and hardened elements
67
+ * use `'`.
68
+ */
69
+ path?: string;
70
+ };
71
+ /**
72
+ * An `ExpansionMap` contains destructured information of a descriptor expression.
73
+ *
74
+ * For example, this descriptor `sh(wsh(andor(pk(0252972572d465d016d4c501887b8df303eee3ed602c056b1eb09260dfa0da0ab2),older(8640),pk([d34db33f/49'/0'/0']tpubDCdxmvzJ5QBjTN8oCjjyT2V58AyZvA1fkmCeZRC75QMoaHcVP2m45Bv3hmnR7ttAwkb2UNYyoXdHVt4gwBqRrJqLUU2JrM43HippxiWpHra/1/2/3/4/*))))` has the following
75
+ * `expandedExpression`: `sh(wsh(andor(pk(@0),older(8640),pk(@1))))`
76
+ *
77
+ * `key`'s are set using this format: `@i`, where `i` is an integer starting from `0` assigned by parsing and retrieving keys from the descriptor from left to right.
78
+ *
79
+ * For the given example, the `ExpansionMap` is:
80
+ *
81
+ * ```javascript
82
+ * {
83
+ * '@0': {
84
+ * keyExpression:
85
+ * '0252972572d465d016d4c501887b8df303eee3ed602c056b1eb09260dfa0da0ab2'
86
+ * },
87
+ * '@1': {
88
+ * keyExpression:
89
+ * "[d34db33f/49'/0'/0']tpubDCdxmvzJ5QBjTN8oCjjyT2V58AyZvA1fkmCeZRC75QMoaHcVP2m45Bv3hmnR7ttAwkb2UNYyoXdHVt4gwBqRrJqLUU2JrM43HippxiWpHra/1/2/3/4/*",
90
+ * keyPath: '/1/2/3/4/*',
91
+ * originPath: "/49'/0'/0'",
92
+ * path: "m/49'/0'/0'/1/2/3/4/*",
93
+ * // Other relevant properties of `KeyInfo`: `pubkey`, `ecpair`, `bip32`,
94
+ * // `privkey`, `xPub`, `xPrv`, `masterFingerprint`, etc.
95
+ * }
96
+ * }
97
+ *```
98
+ *
99
+ *
100
+ */
101
+ export type ExpansionMap = {
102
+ [key: string]: KeyInfo;
103
+ };
104
+ /** @ignore */
105
+ interface XOnlyPointAddTweakResult {
106
+ parity: 1 | 0;
107
+ xOnlyPubkey: Uint8Array;
108
+ }
109
+ /** @ignore */
110
+ export interface TinySecp256k1Interface {
111
+ isPoint(p: Uint8Array): boolean;
112
+ pointCompress(p: Uint8Array, compressed?: boolean): Uint8Array;
113
+ isPrivate(d: Uint8Array): boolean;
114
+ pointFromScalar(d: Uint8Array, compressed?: boolean): Uint8Array | null;
115
+ pointAddScalar(p: Uint8Array, tweak: Uint8Array, compressed?: boolean): Uint8Array | null;
116
+ privateAdd(d: Uint8Array, tweak: Uint8Array): Uint8Array | null;
117
+ sign(h: Uint8Array, d: Uint8Array, e?: Uint8Array): Uint8Array;
118
+ signSchnorr?(h: Uint8Array, d: Uint8Array, e?: Uint8Array): Uint8Array;
119
+ verify(h: Uint8Array, Q: Uint8Array, signature: Uint8Array, strict?: boolean): boolean;
120
+ verifySchnorr?(h: Uint8Array, Q: Uint8Array, signature: Uint8Array): boolean;
121
+ xOnlyPointAddTweak(p: Uint8Array, tweak: Uint8Array): XOnlyPointAddTweakResult | null;
122
+ isXOnlyPoint(p: Uint8Array): boolean;
123
+ privateNegate(d: Uint8Array): Uint8Array;
124
+ }
125
+ /**
126
+ * `DescriptorsFactory` creates and returns the {@link DescriptorsFactory | `expand()`}
127
+ * function that parses a descriptor expression and destructures it
128
+ * into its elemental parts. `Expansion` is the type that `expand()` returns.
129
+ */
130
+ export type Expansion = {
131
+ /**
132
+ * The corresponding [bitcoinjs-lib Payment](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/ts_src/payments/index.ts) for the provided expression, if applicable.
133
+ */
134
+ payment?: Payment;
135
+ /**
136
+ * The expanded descriptor expression.
137
+ * See {@link ExpansionMap ExpansionMap} for a detailed explanation.
138
+ */
139
+ expandedExpression?: string;
140
+ /**
141
+ * The extracted miniscript from the expression, if any.
142
+ */
143
+ miniscript?: string;
144
+ /**
145
+ * A map of key expressions in the descriptor to their corresponding expanded keys.
146
+ * See {@link ExpansionMap ExpansionMap} for a detailed explanation.
147
+ */
148
+ expansionMap?: ExpansionMap;
149
+ /**
150
+ * A boolean indicating whether the descriptor uses SegWit.
151
+ */
152
+ isSegwit?: boolean;
153
+ /**
154
+ * A boolean indicating whether the descriptor uses Taproot.
155
+ */
156
+ isTaproot?: boolean;
157
+ /**
158
+ * The expanded miniscript, if any.
159
+ * It corresponds to the `expandedExpression` without the top-level script
160
+ * expression.
161
+ */
162
+ expandedMiniscript?: string;
163
+ /**
164
+ * The taproot tree expression, if any. Only defined for `tr(KEY, TREE)`.
165
+ * Example: `{pk(02aa...),{pk(03bb...),pk(02cc...)}}`.
166
+ */
167
+ tapTreeExpression?: string;
168
+ /**
169
+ * Parsed taproot leaf tree for `tr(KEY, TREE)`, if any.
170
+ *
171
+ * Shape:
172
+ * - Branch nodes: `{ left, right }`
173
+ * - Leaf nodes: `{ expression: string }`
174
+ *
175
+ * Example:
176
+ * ```ts
177
+ * {
178
+ * left: { expression: 'pk(02aa...)' },
179
+ * right: {
180
+ * left: { expression: 'and_v(v:pk(03bb...),older(12960))' },
181
+ * right: { expression: 'pk(02cc...)' }
182
+ * }
183
+ * }
184
+ * ```
185
+ */
186
+ tapTree?: TapTreeNode;
187
+ /**
188
+ * Compiled taproot leaf metadata tree for `tr(KEY, TREE)`, if any.
189
+ *
190
+ * Same branch/leaf tree shape as `tapTree`, but each leaf is enriched with:
191
+ * - `expandedExpression`: descriptor-level expanded leaf expression
192
+ * - optional `expandedMiniscript`: miniscript-expanded leaf
193
+ * - `expansionMap`: resolved keys for that leaf (`@0`, `@1`, ...)
194
+ * - `tapScript`: compiled tapscript bytes
195
+ * - `version`: leaf version (typically tapscript `0xc0`)
196
+ *
197
+ * Note: `@i` placeholders are scoped per leaf, since each leaf is expanded
198
+ * and satisfied independently.
199
+ *
200
+ * Example:
201
+ * ```ts
202
+ * {
203
+ * left: {
204
+ * expression: 'pk(02aa...)',
205
+ * expandedExpression: 'pk(@0)',
206
+ * expandedMiniscript: 'pk(@0)',
207
+ * expansionMap: {
208
+ * '@0': { pubkey: Uint8Array(32), ... }
209
+ * },
210
+ * tapScript: Uint8Array(...),
211
+ * version: 0xc0
212
+ * },
213
+ * right: {
214
+ * left: {
215
+ * expression: 'and_v(v:pk(03bb...),older(12960))',
216
+ * expandedExpression: 'and_v(v:pk(@0),older(12960))',
217
+ * expansionMap: { '@0': { pubkey: Uint8Array(32), ... } },
218
+ * tapScript: Uint8Array(...),
219
+ * version: 0xc0
220
+ * },
221
+ * right: {
222
+ * expression: 'pk(02cc...)',
223
+ * expandedExpression: 'pk(@0)',
224
+ * expansionMap: { '@0': { pubkey: Uint8Array(32), ... } },
225
+ * tapScript: Uint8Array(...),
226
+ * version: 0xc0
227
+ * }
228
+ * }
229
+ * }
230
+ * ```
231
+ */
232
+ tapTreeInfo?: TapTreeInfoNode;
233
+ /**
234
+ * The redeem script for the descriptor, if applicable.
235
+ */
236
+ redeemScript?: Uint8Array;
237
+ /**
238
+ * The witness script for the descriptor, if applicable.
239
+ */
240
+ witnessScript?: Uint8Array;
241
+ /**
242
+ * Whether the descriptor is a ranged-descriptor.
243
+ */
244
+ isRanged: boolean;
245
+ /**
246
+ * This is the preferred or authoritative representation of an output
247
+ * descriptor expression.
248
+ * It removes the checksum and, if it is a ranged-descriptor, it
249
+ * particularizes it to its index.
250
+ */
251
+ canonicalExpression: string;
252
+ };
253
+ /**
254
+ * The {@link DescriptorsFactory | `DescriptorsFactory`} function creates and
255
+ * returns the `parseKeyExpression` function, which is an implementation of this
256
+ * interface.
257
+ *
258
+ * It parses and destructures a key expression string (xpub, xprv, pubkey or
259
+ * wif) into {@link KeyInfo | `KeyInfo`}.
260
+ *
261
+ * For example, given this `keyExpression`: `[d34db33f/49'/0'/0']tpubDCdxmvzJ5QBjTN8oCjjyT2V58AyZvA1fkmCeZRC75QMoaHcVP2m45Bv3hmnR7ttAwkb2UNYyoXdHVt4gwBqRrJqLUU2JrM43HippxiWpHra/1/2/3/4/*`, this is the parsed result:
262
+ *
263
+ * ```javascript
264
+ * {
265
+ * keyExpression:
266
+ * "[d34db33f/49'/0'/0']tpubDCdxmvzJ5QBjTN8oCjjyT2V58AyZvA1fkmCeZRC75QMoaHcVP2m45Bv3hmnR7ttAwkb2UNYyoXdHVt4gwBqRrJqLUU2JrM43HippxiWpHra/1/2/3/4/*",
267
+ * keyPath: '/1/2/3/4/*',
268
+ * originPath: "/49'/0'/0'",
269
+ * path: "m/49'/0'/0'/1/2/3/4/*",
270
+ * // Other relevant properties of `KeyInfo`: `pubkey`, `ecpair`, `bip32`,
271
+ * // `privkey`, `xPub`, `xPrv`, `masterFingerprint`, etc.
272
+ * }
273
+ * ```
274
+ *
275
+ * See {@link KeyInfo} for the complete list of elements retrieved by this function.
276
+ */
277
+ export interface KeyExpressionParser {
278
+ (params: {
279
+ keyExpression: string;
280
+ /**
281
+ * Indicates if this key expression belongs to a a SegWit output. When set,
282
+ * further checks are done to ensure the public key (if present in the
283
+ * expression) is compressed (33 bytes).
284
+ */
285
+ isSegwit?: boolean;
286
+ /**
287
+ * Indicates if this key expression belongs to a Taproot output.
288
+ * For Taproot, the key must be represented as an x-only public key
289
+ * (32 bytes). If a 33-byte compressed pubkey is derived, it is converted to
290
+ * its x-only representation.
291
+ */
292
+ isTaproot?: boolean;
293
+ network?: Network;
294
+ }): KeyInfo;
295
+ }
296
+ export {};
package/dist/types.js ADDED
@@ -0,0 +1,4 @@
1
+ "use strict";
2
+ // Copyright (c) 2023 Jose-Luis Landabaso - https://bitcoinerlab.com
3
+ // Distributed under the MIT software license
4
+ Object.defineProperty(exports, "__esModule", { value: true });
package/package.json ADDED
@@ -0,0 +1,148 @@
1
+ {
2
+ "name": "@bitcoinerlab/descriptors-core",
3
+ "description": "This library parses and creates Bitcoin Miniscript Descriptors and generates Partially Signed Bitcoin Transactions (PSBTs). It provides PSBT finalizers and signers for single-signature, BIP32 and Hardware Wallets, with explicit backend wiring for advanced use cases.",
4
+ "homepage": "https://github.com/bitcoinerlab/descriptors",
5
+ "version": "3.1.0",
6
+ "author": "Jose-Luis Landabaso",
7
+ "license": "MIT",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "git+https://github.com/bitcoinerlab/descriptors.git"
11
+ },
12
+ "keywords": [
13
+ "bitcoin",
14
+ "descriptors",
15
+ "miniscript",
16
+ "psbt",
17
+ "bitcoinjs",
18
+ "scure",
19
+ "noble"
20
+ ],
21
+ "bugs": {
22
+ "url": "https://github.com/bitcoinerlab/descriptors/issues"
23
+ },
24
+ "main": "dist/index.js",
25
+ "types": "dist/index.d.ts",
26
+ "exports": {
27
+ ".": {
28
+ "types": "./dist/index.d.ts",
29
+ "default": "./dist/index.js"
30
+ },
31
+ "./bitcoinjs": {
32
+ "types": "./dist/bitcoinjs.d.ts",
33
+ "default": "./dist/bitcoinjs.js"
34
+ },
35
+ "./scure": {
36
+ "types": "./dist/scure.d.ts",
37
+ "default": "./dist/scure.js"
38
+ }
39
+ },
40
+ "prettier": "@bitcoinerlab/configs/prettierConfig.json",
41
+ "eslintConfig": {
42
+ "extends": "./node_modules/@bitcoinerlab/configs/eslintConfig"
43
+ },
44
+ "jest": {
45
+ "preset": "@bitcoinerlab/configs",
46
+ "transform": {
47
+ "^.+node_modules/(?:@noble|@scure|micro-packed)/.+\\.js$": "<rootDir>/jest-esm-transform.cjs"
48
+ },
49
+ "transformIgnorePatterns": [
50
+ "/node_modules/(?!(@noble|@scure|micro-packed)/)"
51
+ ]
52
+ },
53
+ "scripts": {
54
+ "webdocs": "typedoc --options ./webtypedoc.json && node ./scripts/postprocess-docs.js ./webdocs",
55
+ "docs": "typedoc --options ./typedoc.json && node ./scripts/postprocess-docs.js ./docs",
56
+ "build:src": "tsc --project ./node_modules/@bitcoinerlab/configs/tsconfig.src.json",
57
+ "build:fixtures": "node test/tools/generateBitcoinCoreFixtures.js -i test/fixtures/descriptor_tests.cpp | npx prettier --parser typescript > test/fixtures/bitcoinCore.ts",
58
+ "build:test": "npm run build:fixtures && tsc --project ./node_modules/@bitcoinerlab/configs/tsconfig.test.json --resolveJsonModule",
59
+ "build": "npm run build:src && npm run build:test",
60
+ "lint": "./node_modules/@bitcoinerlab/configs/scripts/lint.sh",
61
+ "ensureTester": "./node_modules/@bitcoinerlab/configs/scripts/ensureTester.sh",
62
+ "test:integration:soft": "npm run ensureTester && node test/integration/standardOutputs.js && echo \"\n\n\" && node test/integration/miniscript.js && echo \"\n\n\" && node test/integration/sortedmulti.js && echo \"\n\n\" && node test/integration/taproot.js && echo \"\n\n\" && node test/integration/scure.js",
63
+ "test:integration:ledger": "npm run ensureTester && node test/integration/ledgerTaproot.js && echo \"\n\n\" && node test/integration/ledger.js",
64
+ "test:unit": "jest",
65
+ "test:unit:scure": "cross-env BITCOIN_LIB=scure jest",
66
+ "test:scure-adapter": "node test/scureAdapter.js",
67
+ "test:integration:soft:scure": "cross-env BITCOIN_LIB=scure bash -c 'npm run test:integration:soft'",
68
+ "test:integration:ledger:scure": "cross-env BITCOIN_LIB=scure bash -c 'npm run ensureTester && node test/integration/ledgerTaproot.js && echo \"\" && echo \"\" && node test/integration/ledger.js'",
69
+ "test:matrix": "npm run test:unit && npm run test:unit:scure && npm run test:scure-adapter && npm run test:integration:soft && npm run test:integration:soft:scure",
70
+ "test": "npm run lint && npm run build && npm run test:matrix",
71
+ "test:ledger": "npm run lint && npm run build && echo \"\n\n\" && npm run test:integration:ledger:scure && echo \"\n\n\" && npm run test:integration:ledger",
72
+ "publish:all": "npm publish --access public && npm publish --access public --prefix ./packages/descriptors && npm publish --access public --prefix ./packages/descriptors-scure",
73
+ "prepublishOnly": "npm run test && echo \"\n\n\" && npm run test:integration:ledger:scure && echo \"\n\n\" && npm run test:integration:ledger"
74
+ },
75
+ "files": [
76
+ "dist"
77
+ ],
78
+ "peerDependencies": {
79
+ "bitcoinjs-lib": "^7.0.1",
80
+ "bip32": "^5.0.1",
81
+ "ecpair": "^3.0.1",
82
+ "@noble/curves": "^2.0.1",
83
+ "@scure/base": "^2.0.0",
84
+ "@scure/bip32": "^2.0.1",
85
+ "@scure/btc-signer": "^2.0.1",
86
+ "@ledgerhq/ledger-bitcoin": "^0.3.0"
87
+ },
88
+ "peerDependenciesMeta": {
89
+ "@ledgerhq/ledger-bitcoin": {
90
+ "optional": true
91
+ },
92
+ "bitcoinjs-lib": {
93
+ "optional": true
94
+ },
95
+ "bip32": {
96
+ "optional": true
97
+ },
98
+ "ecpair": {
99
+ "optional": true
100
+ },
101
+ "@scure/btc-signer": {
102
+ "optional": true
103
+ },
104
+ "@scure/base": {
105
+ "optional": true
106
+ },
107
+ "@scure/bip32": {
108
+ "optional": true
109
+ },
110
+ "@noble/curves": {
111
+ "optional": true
112
+ }
113
+ },
114
+ "devDependencies": {
115
+ "@babel/core": "^7.29.0",
116
+ "@babel/preset-env": "^7.29.0",
117
+ "@bitcoinerlab/configs": "^2.0.0",
118
+ "@bitcoinerlab/miniscript-policies": "^1.0.0",
119
+ "@bitcoinerlab/secp256k1": "^1.2.0",
120
+ "@ledgerhq/hw-transport-node-hid": "^6.30.0",
121
+ "@ledgerhq/ledger-bitcoin": "^0.3.0",
122
+ "@noble/curves": "^2.0.1",
123
+ "@scure/base": "^2.0.0",
124
+ "@scure/bip32": "^2.0.1",
125
+ "@scure/bip39": "^2.0.1",
126
+ "@scure/btc-signer": "^2.0.1",
127
+ "@types/lodash.memoize": "^4.1.9",
128
+ "babel-jest": "^30.3.0",
129
+ "bip32": "^5.0.1",
130
+ "bip39": "^3.0.4",
131
+ "bip65": "^1.0.3",
132
+ "bip68": "^1.0.4",
133
+ "bitcoinjs-lib": "^7.0.1",
134
+ "cross-env": "^10.1.0",
135
+ "ecpair": "^3.0.1",
136
+ "jest": "^30.3.0",
137
+ "regtest-client": "^0.2.1",
138
+ "ts-jest": "^29.4.6",
139
+ "yargs": "^17.7.2"
140
+ },
141
+ "dependencies": {
142
+ "@bitcoinerlab/miniscript": "^2.0.0",
143
+ "@noble/hashes": "^2.0.1",
144
+ "lodash.memoize": "^4.1.2",
145
+ "uint8array-tools": "^0.0.9",
146
+ "varuint-bitcoin": "^2.0.0"
147
+ }
148
+ }