@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,98 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.trLedger = exports.wpkhLedger = exports.shWpkhLedger = exports.pkhLedger = exports.trBIP32 = exports.wpkhBIP32 = exports.shWpkhBIP32 = exports.pkhBIP32 = void 0;
4
+ const keyExpressions_1 = require("./keyExpressions");
5
+ const networkUtils_1 = require("./networkUtils");
6
+ const networks_1 = require("./networks");
7
+ function assertStandardKeyPath(keyPath) {
8
+ // Regular expression to match "/change/index" or "/change/*" format
9
+ const regex = /^\/[01]\/(\d+|\*)$/;
10
+ if (!regex.test(keyPath)) {
11
+ throw new Error("Error: Key path must be in the format '/change/index', where change is either 0 or 1 and index is a non-negative integer.");
12
+ }
13
+ }
14
+ function standardExpressionsBIP32Maker(purpose, scriptTemplate) {
15
+ /**
16
+ * Computes the standard descriptor based on given parameters.
17
+ *
18
+ * You can define the output location either by:
19
+ * - Providing the full `keyPath` (e.g., "/0/2").
20
+ * OR
21
+ * - Specifying the `change` and `index` values separately (e.g., `{change:0, index:2}`).
22
+ *
23
+ * For ranged indexing, the `index` can be set as a wildcard '*'. For example:
24
+ * - `keyPath="/0/*"`
25
+ * OR
26
+ * - `{change:0, index:'*'}`.
27
+ *
28
+ * @param {Object} params - The parameters object.
29
+ * @param {BIP32InterfaceLike | ScureHDKeyLike} params.masterNode - Root HD node.
30
+ * Pass a bitcoinjs {@link https://github.com/bitcoinjs/bip32 | `BIP32`} node
31
+ * or a scure {@link https://github.com/paulmillr/scure-bip32 | `HDKey`}.
32
+ * @param {number} params.account - BIP32 account index.
33
+ * @param {number} [params.change] - Branch index (0 receive / 1 change).
34
+ * @param {number | '*'} [params.index] - Address index or wildcard for ranged descriptors.
35
+ * @param {string} [params.keyPath] - Full path suffix (`/change/index`) alternative.
36
+ */
37
+ function standardScriptExpressionBIP32({ masterNode, network = networks_1.networks.bitcoin, keyPath, account, change, index, isPublic = true }) {
38
+ const originPath = `/${purpose}'/${(0, networkUtils_1.coinTypeFromNetwork)(network)}'/${account}'`;
39
+ if (keyPath !== undefined)
40
+ assertStandardKeyPath(keyPath);
41
+ const keyExpression = (0, keyExpressions_1.keyExpressionBIP32)({
42
+ masterNode,
43
+ originPath,
44
+ keyPath,
45
+ change,
46
+ index,
47
+ isPublic
48
+ });
49
+ return scriptTemplate.replace('KEYEXPRESSION', keyExpression);
50
+ }
51
+ return standardScriptExpressionBIP32;
52
+ }
53
+ /** @function */
54
+ exports.pkhBIP32 = standardExpressionsBIP32Maker(44, 'pkh(KEYEXPRESSION)');
55
+ /** @function */
56
+ exports.shWpkhBIP32 = standardExpressionsBIP32Maker(49, 'sh(wpkh(KEYEXPRESSION))');
57
+ /** @function */
58
+ exports.wpkhBIP32 = standardExpressionsBIP32Maker(84, 'wpkh(KEYEXPRESSION)');
59
+ /** @function */
60
+ exports.trBIP32 = standardExpressionsBIP32Maker(86, 'tr(KEYEXPRESSION)');
61
+ function standardExpressionsLedgerMaker(purpose, scriptTemplate) {
62
+ /**
63
+ * Computes the standard descriptor based on given parameters.
64
+ *
65
+ * You can define the output location either by:
66
+ * - Providing the full `keyPath` (e.g., "/0/2").
67
+ * OR
68
+ * - Specifying the `change` and `index` values separately (e.g., `{change:0, index:2}`).
69
+ *
70
+ * For ranged indexing, the `index` can be set as a wildcard '*'. For example:
71
+ * - `keyPath="/0/*"`
72
+ * OR
73
+ * - `{change:0, index:'*'}`.
74
+ */
75
+ async function standardScriptExpressionLedger({ ledgerManager, account, keyPath, change, index }) {
76
+ const { network } = ledgerManager;
77
+ const originPath = `/${purpose}'/${(0, networkUtils_1.coinTypeFromNetwork)(network)}'/${account}'`;
78
+ if (keyPath !== undefined)
79
+ assertStandardKeyPath(keyPath);
80
+ const keyExpression = await (0, keyExpressions_1.keyExpressionLedger)({
81
+ ledgerManager,
82
+ originPath,
83
+ keyPath,
84
+ change,
85
+ index
86
+ });
87
+ return scriptTemplate.replace('KEYEXPRESSION', keyExpression);
88
+ }
89
+ return standardScriptExpressionLedger;
90
+ }
91
+ /** @function */
92
+ exports.pkhLedger = standardExpressionsLedgerMaker(44, 'pkh(KEYEXPRESSION)');
93
+ /** @function */
94
+ exports.shWpkhLedger = standardExpressionsLedgerMaker(49, 'sh(wpkh(KEYEXPRESSION))');
95
+ /** @function */
96
+ exports.wpkhLedger = standardExpressionsLedgerMaker(84, 'wpkh(KEYEXPRESSION)');
97
+ /** @function */
98
+ exports.trLedger = standardExpressionsLedgerMaker(86, 'tr(KEYEXPRESSION)');
@@ -0,0 +1,4 @@
1
+ /**
2
+ * Separate entry point for the @scure/btc-signer adapter.
3
+ */
4
+ export { createScureLib } from './adapters/scure';
package/dist/scure.js ADDED
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+ // Copyright (c) 2026 Jose-Luis Landabaso - https://bitcoinerlab.com
3
+ // Distributed under the MIT software license
4
+ Object.defineProperty(exports, "__esModule", { value: true });
5
+ exports.createScureLib = void 0;
6
+ /**
7
+ * Separate entry point for the @scure/btc-signer adapter.
8
+ */
9
+ var scure_1 = require("./adapters/scure");
10
+ Object.defineProperty(exports, "createScureLib", { enumerable: true, get: function () { return scure_1.createScureLib; } });
@@ -0,0 +1,161 @@
1
+ import { type ScureTransactionLike, type ECPairInterfaceLike, type BIP32InterfaceLike, type ScureHDKeyLike, type PsbtLike } from './bitcoinLib';
2
+ import { LedgerManager } from './ledger';
3
+ /**
4
+ * Signs a specific input of a transaction with a bitcoinjs-lib `ECPair` signer.
5
+ *
6
+ * It detects Taproot inputs and applies key tweaking when needed before
7
+ * signing.
8
+ *
9
+ * For `@scure/btc-signer` transactions and raw private keys, use
10
+ * {@link signInputPrivKey}.
11
+ *
12
+ * @see https://github.com/bitcoinjs/bitcoinjs-lib/pull/2137#issuecomment-2713264848
13
+ *
14
+ * @param {Object} params - The parameters object
15
+ * @param {PsbtLike} params.psbt - A bitcoinjs-lib
16
+ * {@link https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/ts_src/psbt.ts | `Psbt`}.
17
+ * @param {number} params.index - The input index to sign
18
+ * @param {ECPairInterfaceLike} params.ecpair - A bitcoinjs
19
+ * {@link https://github.com/bitcoinjs/ecpair | `ECPair`} signer.
20
+ */
21
+ export declare function signInputECPair({ psbt, index, ecpair }: {
22
+ psbt: PsbtLike;
23
+ index: number;
24
+ ecpair: ECPairInterfaceLike;
25
+ }): void;
26
+ /**
27
+ * Signs all inputs of a transaction with a bitcoinjs-lib `ECPair` signer.
28
+ *
29
+ * For each input, it detects Taproot and applies key tweaking when needed
30
+ * before signing.
31
+ *
32
+ * For `@scure/btc-signer` transactions and raw private keys, use
33
+ * {@link signPrivKey}.
34
+ *
35
+ * @see https://github.com/bitcoinjs/bitcoinjs-lib/pull/2137#issuecomment-2713264848
36
+ *
37
+ * @param {Object} params - The parameters object
38
+ * @param {PsbtLike} params.psbt - A bitcoinjs-lib
39
+ * {@link https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/ts_src/psbt.ts | `Psbt`}.
40
+ * @param {ECPairInterfaceLike} params.ecpair - A bitcoinjs
41
+ * {@link https://github.com/bitcoinjs/ecpair | `ECPair`} signer.
42
+ */
43
+ export declare function signECPair({ psbt, ecpair }: {
44
+ psbt: PsbtLike;
45
+ ecpair: ECPairInterfaceLike;
46
+ }): void;
47
+ /**
48
+ * Signs one input of a `@scure/btc-signer` transaction with a raw private key.
49
+ *
50
+ * This helper is intended for scure users that work directly with a `Uint8Array`
51
+ * private key and may not use bitcoinjs-lib `ECPair` types.
52
+ *
53
+ * If you are signing a bitcoinjs-lib PSBT input, use {@link signInputECPair}
54
+ * and pass a bitcoinjs
55
+ * {@link https://github.com/bitcoinjs/ecpair | `ECPair`} signer.
56
+ *
57
+ * @param {Object} params - The parameters object
58
+ * @param {ScureTransactionLike} params.psbt - A scure
59
+ * {@link https://github.com/paulmillr/scure-btc-signer | `Transaction`}.
60
+ * @param {number} params.index - The input index to sign
61
+ * @param {Uint8Array} params.privKey - The secp256k1 private key (32 bytes)
62
+ * @throws If `psbt` is not a scure transaction
63
+ */
64
+ export declare function signInputPrivKey({ psbt, index, privKey }: {
65
+ psbt: ScureTransactionLike;
66
+ index: number;
67
+ privKey: Uint8Array;
68
+ }): void;
69
+ /**
70
+ * Signs all inputs of a `@scure/btc-signer` transaction with a raw private key.
71
+ *
72
+ * This helper is intended for scure users that work directly with a `Uint8Array`
73
+ * private key and may not use bitcoinjs-lib `ECPair` types.
74
+ *
75
+ * If you are signing a bitcoinjs-lib PSBT, use {@link signECPair} and pass a
76
+ * bitcoinjs {@link https://github.com/bitcoinjs/ecpair | `ECPair`} signer.
77
+ *
78
+ * @param {Object} params - The parameters object
79
+ * @param {ScureTransactionLike} params.psbt - A scure
80
+ * {@link https://github.com/paulmillr/scure-btc-signer | `Transaction`}.
81
+ * @param {Uint8Array} params.privKey - The secp256k1 private key (32 bytes)
82
+ * @throws If `psbt` is not a scure transaction
83
+ */
84
+ export declare function signPrivKey({ psbt, privKey }: {
85
+ psbt: ScureTransactionLike;
86
+ privKey: Uint8Array;
87
+ }): void;
88
+ /**
89
+ * Signs one input of a transaction using an HD node.
90
+ * Supports both bitcoinjs PSBT and scure Transaction inputs; bitcoinjs calls
91
+ * also apply the local HD-signing compatibility patch before signing.
92
+ *
93
+ * @param {Object} params - The parameters object
94
+ * @param {PsbtLike | ScureTransactionLike} params.psbt - Pass a
95
+ * bitcoinjs-lib {@link https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/ts_src/psbt.ts | `Psbt`}
96
+ * or a scure {@link https://github.com/paulmillr/scure-btc-signer | `Transaction`}.
97
+ * @param {number} params.index - The input index to sign
98
+ * @param {BIP32InterfaceLike | ScureHDKeyLike} params.node - Pass a bitcoinjs
99
+ * {@link https://github.com/bitcoinjs/bip32 | `BIP32`} node or a scure
100
+ * {@link https://github.com/paulmillr/scure-bip32 | `HDKey`} node.
101
+ */
102
+ export declare function signInputBIP32({ psbt, index, node }: {
103
+ psbt: PsbtLike | ScureTransactionLike;
104
+ index: number;
105
+ node: BIP32InterfaceLike | ScureHDKeyLike;
106
+ }): void;
107
+ /**
108
+ * Signs all signable inputs of a transaction using an HD node.
109
+ * Supports both bitcoinjs PSBT and scure Transaction inputs; bitcoinjs calls
110
+ * also apply the local HD-signing compatibility patch before signing.
111
+ *
112
+ * @param {Object} params - The parameters object
113
+ * @param {PsbtLike | ScureTransactionLike} params.psbt - Pass a
114
+ * bitcoinjs-lib {@link https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/ts_src/psbt.ts | `Psbt`}
115
+ * or a scure {@link https://github.com/paulmillr/scure-btc-signer | `Transaction`}.
116
+ * @param {BIP32InterfaceLike | ScureHDKeyLike} params.masterNode - Pass a
117
+ * bitcoinjs {@link https://github.com/bitcoinjs/bip32 | `BIP32`} node or a
118
+ * scure {@link https://github.com/paulmillr/scure-bip32 | `HDKey`} node.
119
+ */
120
+ export declare function signBIP32({ psbt, masterNode }: {
121
+ psbt: PsbtLike | ScureTransactionLike;
122
+ masterNode: BIP32InterfaceLike | ScureHDKeyLike;
123
+ }): void;
124
+ /**
125
+ * Signs an input of the `psbt` where the keys are controlled by a Ledger
126
+ * device.
127
+ *
128
+ * The function will throw an error if it's unable to sign the input.
129
+ *
130
+ * @param {Object} params - The parameters object
131
+ * @param {PsbtLike | ScureTransactionLike} params.psbt - Pass a bitcoinjs-lib
132
+ * {@link https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/ts_src/psbt.ts | `Psbt`}
133
+ * or a scure {@link https://github.com/paulmillr/scure-btc-signer | `Transaction`}.
134
+ * @param {number} params.index - The input index to sign.
135
+ * @param {LedgerManager} params.ledgerManager - Ledger client/state manager.
136
+ */
137
+ export declare function signInputLedger({ psbt, index, ledgerManager }: {
138
+ psbt: PsbtLike | ScureTransactionLike;
139
+ index: number;
140
+ ledgerManager: LedgerManager;
141
+ }): Promise<void>;
142
+ /**
143
+ * Signs the inputs of the `psbt` where the keys are controlled by a Ledger
144
+ * device.
145
+ *
146
+ * `signLedger` can sign multiple inputs of the same wallet policy in a single
147
+ * pass by grouping inputs by their wallet policy type before the signing
148
+ * process.
149
+ *
150
+ * The function will throw an error if it's unable to sign any input.
151
+ *
152
+ * @param {Object} params - The parameters object
153
+ * @param {PsbtLike | ScureTransactionLike} params.psbt - Pass a bitcoinjs-lib
154
+ * {@link https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/ts_src/psbt.ts | `Psbt`}
155
+ * or a scure {@link https://github.com/paulmillr/scure-btc-signer | `Transaction`}.
156
+ * @param {LedgerManager} params.ledgerManager - Ledger client/state manager.
157
+ */
158
+ export declare function signLedger({ psbt, ledgerManager }: {
159
+ psbt: PsbtLike | ScureTransactionLike;
160
+ ledgerManager: LedgerManager;
161
+ }): Promise<void>;
@@ -0,0 +1,324 @@
1
+ "use strict";
2
+ // Copyright (c) 2025 Jose-Luis Landabaso - https://bitcoinerlab.com
3
+ // Distributed under the MIT software license
4
+ Object.defineProperty(exports, "__esModule", { value: true });
5
+ exports.signInputECPair = signInputECPair;
6
+ exports.signECPair = signECPair;
7
+ exports.signInputPrivKey = signInputPrivKey;
8
+ exports.signPrivKey = signPrivKey;
9
+ exports.signInputBIP32 = signInputBIP32;
10
+ exports.signBIP32 = signBIP32;
11
+ exports.signInputLedger = signInputLedger;
12
+ exports.signLedger = signLedger;
13
+ const bitcoinLib_1 = require("./bitcoinLib");
14
+ const psbt_1 = require("./psbt");
15
+ const keyInterfaces_1 = require("./keyInterfaces");
16
+ const bitcoinjs_lib_internals_1 = require("./bitcoinjs-lib-internals");
17
+ const ledger_1 = require("./ledger");
18
+ /**
19
+ * This applies a bitcoinjs-lib speciffic patch.
20
+ * This won't be run if using the scure lib
21
+ */
22
+ function ensureBitcoinjsHdPatch(psbt) {
23
+ let BitcoinjsPsbt;
24
+ try {
25
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
26
+ ({ Psbt: BitcoinjsPsbt } = require('bitcoinjs-lib'));
27
+ }
28
+ catch (error) {
29
+ void error;
30
+ return;
31
+ }
32
+ if (!BitcoinjsPsbt || !(psbt instanceof BitcoinjsPsbt))
33
+ return;
34
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
35
+ const { applyPR2137 } = require('./adapters/applyPR2137');
36
+ applyPR2137(psbt);
37
+ }
38
+ function signInputSingleKey({ psbt, index, ecpair }) {
39
+ //psbt.signInput(index, ecpair); <- Replaced for the code below
40
+ //that can handle taproot inputs automatically.
41
+ //See https://github.com/bitcoinjs/bitcoinjs-lib/pull/2137#issuecomment-2713264848
42
+ const input = psbt.data.inputs[index];
43
+ if (!input)
44
+ throw new Error('Invalid index');
45
+ if ((0, bitcoinjs_lib_internals_1.isTaprootInput)(input)) {
46
+ // If script-path (tapLeafScript present) -> DO NOT TWEAK
47
+ if (input.tapLeafScript && input.tapLeafScript.length > 0)
48
+ psbt.signInput(index, ecpair);
49
+ else {
50
+ const hash = (0, bitcoinjs_lib_internals_1.tapTweakHash)(ecpair.publicKey.slice(1, 33), undefined);
51
+ const tweakedEcpair = ecpair.tweak(hash);
52
+ psbt.signInput(index, tweakedEcpair);
53
+ }
54
+ }
55
+ else
56
+ psbt.signInput(index, ecpair);
57
+ }
58
+ function signSingleKey({ psbt, ecpair }) {
59
+ let signedAny = false;
60
+ for (let index = 0; index < psbt.data.inputs.length; index++) {
61
+ try {
62
+ signInputSingleKey({ psbt, index, ecpair });
63
+ signedAny = true;
64
+ }
65
+ catch (err) {
66
+ void err;
67
+ }
68
+ }
69
+ if (!signedAny)
70
+ throw new Error('No inputs were signed');
71
+ }
72
+ /**
73
+ * Signs a specific input of a transaction with a bitcoinjs-lib `ECPair` signer.
74
+ *
75
+ * It detects Taproot inputs and applies key tweaking when needed before
76
+ * signing.
77
+ *
78
+ * For `@scure/btc-signer` transactions and raw private keys, use
79
+ * {@link signInputPrivKey}.
80
+ *
81
+ * @see https://github.com/bitcoinjs/bitcoinjs-lib/pull/2137#issuecomment-2713264848
82
+ *
83
+ * @param {Object} params - The parameters object
84
+ * @param {PsbtLike} params.psbt - A bitcoinjs-lib
85
+ * {@link https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/ts_src/psbt.ts | `Psbt`}.
86
+ * @param {number} params.index - The input index to sign
87
+ * @param {ECPairInterfaceLike} params.ecpair - A bitcoinjs
88
+ * {@link https://github.com/bitcoinjs/ecpair | `ECPair`} signer.
89
+ */
90
+ function signInputECPair({ psbt, index, ecpair }) {
91
+ if ((0, bitcoinLib_1.isScureTransaction)(psbt))
92
+ throw new Error('Error: signInputECPair is only supported with bitcoinjs-lib PSBTs. ' +
93
+ 'Use signInputPrivKey for @scure/btc-signer transactions.');
94
+ signInputSingleKey({ psbt, index, ecpair });
95
+ }
96
+ /**
97
+ * Signs all inputs of a transaction with a bitcoinjs-lib `ECPair` signer.
98
+ *
99
+ * For each input, it detects Taproot and applies key tweaking when needed
100
+ * before signing.
101
+ *
102
+ * For `@scure/btc-signer` transactions and raw private keys, use
103
+ * {@link signPrivKey}.
104
+ *
105
+ * @see https://github.com/bitcoinjs/bitcoinjs-lib/pull/2137#issuecomment-2713264848
106
+ *
107
+ * @param {Object} params - The parameters object
108
+ * @param {PsbtLike} params.psbt - A bitcoinjs-lib
109
+ * {@link https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/ts_src/psbt.ts | `Psbt`}.
110
+ * @param {ECPairInterfaceLike} params.ecpair - A bitcoinjs
111
+ * {@link https://github.com/bitcoinjs/ecpair | `ECPair`} signer.
112
+ */
113
+ function signECPair({ psbt, ecpair }) {
114
+ if ((0, bitcoinLib_1.isScureTransaction)(psbt))
115
+ throw new Error('Error: signECPair is only supported with bitcoinjs-lib PSBTs. ' +
116
+ 'Use signPrivKey for @scure/btc-signer transactions.');
117
+ signSingleKey({ psbt, ecpair });
118
+ }
119
+ /**
120
+ * Signs one input of a `@scure/btc-signer` transaction with a raw private key.
121
+ *
122
+ * This helper is intended for scure users that work directly with a `Uint8Array`
123
+ * private key and may not use bitcoinjs-lib `ECPair` types.
124
+ *
125
+ * If you are signing a bitcoinjs-lib PSBT input, use {@link signInputECPair}
126
+ * and pass a bitcoinjs
127
+ * {@link https://github.com/bitcoinjs/ecpair | `ECPair`} signer.
128
+ *
129
+ * @param {Object} params - The parameters object
130
+ * @param {ScureTransactionLike} params.psbt - A scure
131
+ * {@link https://github.com/paulmillr/scure-btc-signer | `Transaction`}.
132
+ * @param {number} params.index - The input index to sign
133
+ * @param {Uint8Array} params.privKey - The secp256k1 private key (32 bytes)
134
+ * @throws If `psbt` is not a scure transaction
135
+ */
136
+ function signInputPrivKey({ psbt, index, privKey }) {
137
+ if (!(0, bitcoinLib_1.isScureTransaction)(psbt)) {
138
+ throw new Error('Error: signInputPrivKey is only supported with @scure/btc-signer transactions. ' +
139
+ 'Use signInputECPair for bitcoinjs-lib PSBTs.');
140
+ }
141
+ signInputSingleKey({
142
+ psbt: (0, psbt_1.toPsbt)(psbt),
143
+ index,
144
+ ecpair: (0, keyInterfaces_1.toECPairInterface)(privKey)
145
+ });
146
+ }
147
+ /**
148
+ * Signs all inputs of a `@scure/btc-signer` transaction with a raw private key.
149
+ *
150
+ * This helper is intended for scure users that work directly with a `Uint8Array`
151
+ * private key and may not use bitcoinjs-lib `ECPair` types.
152
+ *
153
+ * If you are signing a bitcoinjs-lib PSBT, use {@link signECPair} and pass a
154
+ * bitcoinjs {@link https://github.com/bitcoinjs/ecpair | `ECPair`} signer.
155
+ *
156
+ * @param {Object} params - The parameters object
157
+ * @param {ScureTransactionLike} params.psbt - A scure
158
+ * {@link https://github.com/paulmillr/scure-btc-signer | `Transaction`}.
159
+ * @param {Uint8Array} params.privKey - The secp256k1 private key (32 bytes)
160
+ * @throws If `psbt` is not a scure transaction
161
+ */
162
+ function signPrivKey({ psbt, privKey }) {
163
+ if (!(0, bitcoinLib_1.isScureTransaction)(psbt)) {
164
+ throw new Error('Error: signPrivKey is only supported with @scure/btc-signer transactions. ' +
165
+ 'Use signECPair for bitcoinjs-lib PSBTs.');
166
+ }
167
+ signSingleKey({ psbt: (0, psbt_1.toPsbt)(psbt), ecpair: (0, keyInterfaces_1.toECPairInterface)(privKey) });
168
+ }
169
+ /**
170
+ * Signs one input of a transaction using an HD node.
171
+ * Supports both bitcoinjs PSBT and scure Transaction inputs; bitcoinjs calls
172
+ * also apply the local HD-signing compatibility patch before signing.
173
+ *
174
+ * @param {Object} params - The parameters object
175
+ * @param {PsbtLike | ScureTransactionLike} params.psbt - Pass a
176
+ * bitcoinjs-lib {@link https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/ts_src/psbt.ts | `Psbt`}
177
+ * or a scure {@link https://github.com/paulmillr/scure-btc-signer | `Transaction`}.
178
+ * @param {number} params.index - The input index to sign
179
+ * @param {BIP32InterfaceLike | ScureHDKeyLike} params.node - Pass a bitcoinjs
180
+ * {@link https://github.com/bitcoinjs/bip32 | `BIP32`} node or a scure
181
+ * {@link https://github.com/paulmillr/scure-bip32 | `HDKey`} node.
182
+ */
183
+ function signInputBIP32({ psbt, index, node }) {
184
+ node = (0, keyInterfaces_1.toBIP32Interface)(node);
185
+ psbt = (0, psbt_1.toPsbt)(psbt);
186
+ ensureBitcoinjsHdPatch(psbt);
187
+ psbt.signInputHD(index, node);
188
+ }
189
+ /**
190
+ * Signs all signable inputs of a transaction using an HD node.
191
+ * Supports both bitcoinjs PSBT and scure Transaction inputs; bitcoinjs calls
192
+ * also apply the local HD-signing compatibility patch before signing.
193
+ *
194
+ * @param {Object} params - The parameters object
195
+ * @param {PsbtLike | ScureTransactionLike} params.psbt - Pass a
196
+ * bitcoinjs-lib {@link https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/ts_src/psbt.ts | `Psbt`}
197
+ * or a scure {@link https://github.com/paulmillr/scure-btc-signer | `Transaction`}.
198
+ * @param {BIP32InterfaceLike | ScureHDKeyLike} params.masterNode - Pass a
199
+ * bitcoinjs {@link https://github.com/bitcoinjs/bip32 | `BIP32`} node or a
200
+ * scure {@link https://github.com/paulmillr/scure-bip32 | `HDKey`} node.
201
+ */
202
+ function signBIP32({ psbt, masterNode }) {
203
+ masterNode = (0, keyInterfaces_1.toBIP32Interface)(masterNode);
204
+ psbt = (0, psbt_1.toPsbt)(psbt);
205
+ ensureBitcoinjsHdPatch(psbt);
206
+ psbt.signAllInputsHD(masterNode);
207
+ }
208
+ const ledgerSignaturesForInputIndex = (index, ledgerSignatures) => ledgerSignatures
209
+ .filter(([i]) => i === index)
210
+ .map(([_i, partialSignature]) => partialSignature);
211
+ function addLedgerSignaturesToInput({ psbt, index, ledgerSignatures }) {
212
+ const input = psbt.data.inputs[index];
213
+ if (!input)
214
+ throw new Error(`Error: input ${index} not available`);
215
+ const signatures = ledgerSignaturesForInputIndex(index, ledgerSignatures);
216
+ if (signatures.length === 0)
217
+ throw new Error(`Error: no ledger signatures found for input ${index}`);
218
+ if ((0, bitcoinjs_lib_internals_1.isTaprootInput)(input)) {
219
+ // Ledger returns per-input signatures as [pubkey, signature, tapleafHash?].
220
+ // For taproot we must map them to PSBT taproot fields (not partialSig):
221
+ // - signatures with tapleafHash -> tapScriptSig[] (script-path)
222
+ // - signature without tapleafHash -> tapKeySig (key-path)
223
+ // A taproot input may contain script-path signatures, key-path signature,
224
+ // or both in edge cases; each must be written to its corresponding field.
225
+ const tapScriptSig = signatures
226
+ .filter((sig) => sig.tapleafHash)
227
+ .map((sig) => ({
228
+ pubkey: sig.pubkey,
229
+ signature: sig.signature,
230
+ leafHash: sig.tapleafHash
231
+ }));
232
+ const tapKeySigs = signatures.filter((sig) => !sig.tapleafHash);
233
+ if (tapScriptSig.length > 0) {
234
+ psbt.updateInput(index, { tapScriptSig });
235
+ }
236
+ if (tapKeySigs.length > 1)
237
+ throw new Error(`Error: expected at most one tapKeySig for input ${index}`);
238
+ const tapKeySig = tapKeySigs[0]?.signature;
239
+ if (tapKeySig) {
240
+ psbt.updateInput(index, { tapKeySig });
241
+ }
242
+ if (tapScriptSig.length === 0 && !tapKeySig)
243
+ throw new Error(`Error: no valid taproot ledger signatures found for input ${index}`);
244
+ }
245
+ else {
246
+ const partialSig = signatures.map((sig) => ({
247
+ pubkey: sig.pubkey,
248
+ signature: sig.signature
249
+ }));
250
+ psbt.updateInput(index, { partialSig });
251
+ }
252
+ }
253
+ async function signInputLedger({ psbt, index, ledgerManager }) {
254
+ psbt = (0, psbt_1.toPsbt)(psbt);
255
+ const { ledgerClient } = ledgerManager;
256
+ const { DefaultWalletPolicy, WalletPolicy, AppClient } = (await (0, ledger_1.importAndValidateLedgerBitcoin)(ledgerClient));
257
+ if (!(ledgerClient instanceof AppClient))
258
+ throw new Error(`Error: pass a valid ledgerClient`);
259
+ const policy = await (0, ledger_1.ledgerPolicyFromPsbtInput)({
260
+ psbt,
261
+ index,
262
+ ledgerManager
263
+ });
264
+ if (!policy)
265
+ throw new Error(`Error: the ledger cannot sign this pstb input`);
266
+ let ledgerSignatures;
267
+ if (policy.policyName && policy.policyHmac && policy.policyId) {
268
+ //non-standard policy
269
+ const walletPolicy = new WalletPolicy(policy.policyName, policy.ledgerTemplate, policy.keyRoots);
270
+ const walletHmac = policy.policyHmac;
271
+ ledgerSignatures = await ledgerClient.signPsbt(psbt.toBase64(), walletPolicy, walletHmac);
272
+ }
273
+ else {
274
+ //standard policy
275
+ ledgerSignatures = await ledgerClient.signPsbt(psbt.toBase64(), new DefaultWalletPolicy(policy.ledgerTemplate, policy.keyRoots[0]), null);
276
+ }
277
+ addLedgerSignaturesToInput({ psbt, index, ledgerSignatures });
278
+ }
279
+ async function signLedger({ psbt, ledgerManager }) {
280
+ psbt = (0, psbt_1.toPsbt)(psbt);
281
+ const { ledgerClient } = ledgerManager;
282
+ const { DefaultWalletPolicy, WalletPolicy, AppClient } = (await (0, ledger_1.importAndValidateLedgerBitcoin)(ledgerClient));
283
+ if (!(ledgerClient instanceof AppClient))
284
+ throw new Error(`Error: pass a valid ledgerClient`);
285
+ const ledgerPolicies = [];
286
+ for (let index = 0; index < psbt.data.inputs.length; index++) {
287
+ const policy = await (0, ledger_1.ledgerPolicyFromPsbtInput)({
288
+ psbt,
289
+ index,
290
+ ledgerManager
291
+ });
292
+ if (policy)
293
+ ledgerPolicies.push(policy);
294
+ }
295
+ if (ledgerPolicies.length === 0)
296
+ throw new Error(`Error: there are no inputs which could be signed`);
297
+ //cluster unique LedgerPolicies
298
+ const uniquePolicies = [];
299
+ for (const policy of ledgerPolicies) {
300
+ if (!uniquePolicies.find((uniquePolicy) => (0, ledger_1.comparePolicies)(uniquePolicy, policy)))
301
+ uniquePolicies.push(policy);
302
+ }
303
+ for (const uniquePolicy of uniquePolicies) {
304
+ let ledgerSignatures;
305
+ if (uniquePolicy.policyName &&
306
+ uniquePolicy.policyHmac &&
307
+ uniquePolicy.policyId) {
308
+ //non-standard policy
309
+ const walletPolicy = new WalletPolicy(uniquePolicy.policyName, uniquePolicy.ledgerTemplate, uniquePolicy.keyRoots);
310
+ const walletHmac = uniquePolicy.policyHmac;
311
+ ledgerSignatures = await ledgerClient.signPsbt(psbt.toBase64(), walletPolicy, walletHmac);
312
+ }
313
+ else {
314
+ //standard policy
315
+ ledgerSignatures = await ledgerClient.signPsbt(psbt.toBase64(), new DefaultWalletPolicy(uniquePolicy.ledgerTemplate, uniquePolicy.keyRoots[0]), null);
316
+ }
317
+ const signedIndexes = [
318
+ ...new Set(ledgerSignatures.map(([index]) => index))
319
+ ];
320
+ for (const index of signedIndexes) {
321
+ addLedgerSignaturesToInput({ psbt, index, ledgerSignatures });
322
+ }
323
+ }
324
+ }