@bitcoinerlab/descriptors 1.1.1 → 2.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/README.md +138 -145
- package/dist/checksum.d.ts +4 -0
- package/dist/checksum.js +4 -0
- package/dist/descriptors.d.ts +415 -37
- package/dist/descriptors.js +283 -130
- package/dist/index.d.ts +25 -5
- package/dist/index.js +12 -2
- package/dist/keyExpressions.d.ts +54 -5
- package/dist/keyExpressions.js +30 -2
- package/dist/ledger.d.ts +89 -12
- package/dist/ledger.js +241 -28
- package/dist/scriptExpressions.d.ts +73 -28
- package/dist/scriptExpressions.js +26 -4
- package/dist/signers.d.ts +34 -1
- package/dist/signers.js +102 -41
- package/dist/types.d.ts +71 -39
- package/package.json +3 -2
package/dist/ledger.js
CHANGED
|
@@ -2,7 +2,30 @@
|
|
|
2
2
|
// Copyright (c) 2023 Jose-Luis Landabaso - https://bitcoinerlab.com
|
|
3
3
|
// Distributed under the MIT software license
|
|
4
4
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
5
|
-
exports.ledgerPolicyFromState = exports.comparePolicies = exports.ledgerPolicyFromStandard = exports.registerLedgerWallet = exports.
|
|
5
|
+
exports.ledgerPolicyFromState = exports.comparePolicies = exports.ledgerPolicyFromStandard = exports.registerLedgerWallet = exports.ledgerPolicyFromOutput = exports.ledgerPolicyFromPsbtInput = exports.getLedgerXpub = exports.getLedgerMasterFingerPrint = exports.assertLedgerApp = exports.importAndValidateLedgerBitcoin = void 0;
|
|
6
|
+
/*
|
|
7
|
+
* Notes on Ledger implementation:
|
|
8
|
+
*
|
|
9
|
+
* Ledger assumes as external all keyRoots that do not have origin information.
|
|
10
|
+
*
|
|
11
|
+
* Some known Ledger Limitations (based on my tests as of Febr 2023):
|
|
12
|
+
*
|
|
13
|
+
* 1) All keyExpressions must be expanded into @i. In other words,
|
|
14
|
+
* this template is not valid:
|
|
15
|
+
* wsh(and_v(v:pk(03ed0b41d808b012b3a77dd7f6a30c4180dfbcab604133d90ce7593ec7f3e4037b),and_v(v:sha256(6c60f404f8167a38fc70eaf8aa17ac351023bef86bcb9d1086a19afe95bd5333),and_v(and_v(v:pk(@0/**),v:pk(@1/**)),older(5)))))
|
|
16
|
+
* (note the fixed 03ed0b41d808b012b3a77dd7f6a30c4180dfbcab604133d90ce7593ec7f3e4037b pubkey)
|
|
17
|
+
*
|
|
18
|
+
* 2) All elements in the keyRoot vector must be xpub-type (no xprv-type, no pubkey-type, ...)
|
|
19
|
+
*
|
|
20
|
+
* 3) All originPaths of the expressions in the keyRoot vector must be the same.
|
|
21
|
+
* On the other hand, an empty originPath is permitted for external keys.
|
|
22
|
+
*
|
|
23
|
+
* 4) Since all originPaths must be the same and originPaths for the Ledger are
|
|
24
|
+
* necessary, a Ledger device can only sign at most 1 key per policy and input.
|
|
25
|
+
*
|
|
26
|
+
* All the conditions above are checked in function ledgerPolicyFromOutput.
|
|
27
|
+
*/
|
|
28
|
+
const descriptors_1 = require("./descriptors");
|
|
6
29
|
const bitcoinjs_lib_1 = require("bitcoinjs-lib");
|
|
7
30
|
const re_1 = require("./re");
|
|
8
31
|
/**
|
|
@@ -62,6 +85,15 @@ async function ledgerAppInfo(transport) {
|
|
|
62
85
|
const flags = r.slice(i, (i += flagLength));
|
|
63
86
|
return { name, version, flags, format };
|
|
64
87
|
}
|
|
88
|
+
/**
|
|
89
|
+
* Verifies if the Ledger device is connected, if the required Bitcoin App is opened,
|
|
90
|
+
* and if the version of the app meets the minimum requirements.
|
|
91
|
+
*
|
|
92
|
+
* @throws Will throw an error if the Ledger device is not connected, the required
|
|
93
|
+
* Bitcoin App is not opened, or if the version is below the required number.
|
|
94
|
+
*
|
|
95
|
+
* @returns Promise<void> - A promise that resolves if all assertions pass, or throws otherwise.
|
|
96
|
+
*/
|
|
65
97
|
async function assertLedgerApp({ transport, name, minVersion }) {
|
|
66
98
|
const { name: openName, version } = await ledgerAppInfo(transport);
|
|
67
99
|
if (openName !== name) {
|
|
@@ -102,7 +134,14 @@ function isLedgerStandard({ ledgerTemplate, keyRoots, network = bitcoinjs_lib_1.
|
|
|
102
134
|
return true;
|
|
103
135
|
return false;
|
|
104
136
|
}
|
|
105
|
-
|
|
137
|
+
/** @hidden */
|
|
138
|
+
async function getLedgerMasterFingerPrint({ ledgerClient, ledgerState, ledgerManager }) {
|
|
139
|
+
if (ledgerManager && (ledgerClient || ledgerState))
|
|
140
|
+
throw new Error(`ledgerClient and ledgerState have been deprecated`);
|
|
141
|
+
if (ledgerManager)
|
|
142
|
+
({ ledgerClient, ledgerState } = ledgerManager);
|
|
143
|
+
if (!ledgerClient || !ledgerState)
|
|
144
|
+
throw new Error(`Could not retrieve ledgerClient or ledgerState`);
|
|
106
145
|
const { AppClient } = (await importAndValidateLedgerBitcoin(ledgerClient));
|
|
107
146
|
if (!(ledgerClient instanceof AppClient))
|
|
108
147
|
throw new Error(`Error: pass a valid ledgerClient`);
|
|
@@ -114,7 +153,14 @@ async function getLedgerMasterFingerPrint({ ledgerClient, ledgerState }) {
|
|
|
114
153
|
return masterFingerprint;
|
|
115
154
|
}
|
|
116
155
|
exports.getLedgerMasterFingerPrint = getLedgerMasterFingerPrint;
|
|
117
|
-
|
|
156
|
+
/** @hidden */
|
|
157
|
+
async function getLedgerXpub({ originPath, ledgerClient, ledgerState, ledgerManager }) {
|
|
158
|
+
if (ledgerManager && (ledgerClient || ledgerState))
|
|
159
|
+
throw new Error(`ledgerClient and ledgerState have been deprecated`);
|
|
160
|
+
if (ledgerManager)
|
|
161
|
+
({ ledgerClient, ledgerState } = ledgerManager);
|
|
162
|
+
if (!ledgerClient || !ledgerState)
|
|
163
|
+
throw new Error(`Could not retrieve ledgerClient or ledgerState`);
|
|
118
164
|
const { AppClient } = (await importAndValidateLedgerBitcoin(ledgerClient));
|
|
119
165
|
if (!(ledgerClient instanceof AppClient))
|
|
120
166
|
throw new Error(`Error: pass a valid ledgerClient`);
|
|
@@ -137,7 +183,151 @@ async function getLedgerXpub({ originPath, ledgerClient, ledgerState }) {
|
|
|
137
183
|
}
|
|
138
184
|
exports.getLedgerXpub = getLedgerXpub;
|
|
139
185
|
/**
|
|
140
|
-
*
|
|
186
|
+
* Checks whether there is a policy in ledgerState that the ledger
|
|
187
|
+
* could use to sign this psbt input.
|
|
188
|
+
*
|
|
189
|
+
* It found return the policy, otherwise, return undefined
|
|
190
|
+
*
|
|
191
|
+
* All considerations in the header of this file are applied
|
|
192
|
+
*/
|
|
193
|
+
async function ledgerPolicyFromPsbtInput({ ledgerManager, psbt, index }) {
|
|
194
|
+
const { ledgerState, ledgerClient, ecc, network } = ledgerManager;
|
|
195
|
+
const { Output } = (0, descriptors_1.DescriptorsFactory)(ecc);
|
|
196
|
+
const input = psbt.data.inputs[index];
|
|
197
|
+
if (!input)
|
|
198
|
+
throw new Error(`Input numer ${index} not set.`);
|
|
199
|
+
let scriptPubKey;
|
|
200
|
+
if (input.nonWitnessUtxo) {
|
|
201
|
+
const vout = psbt.txInputs[index]?.index;
|
|
202
|
+
if (vout === undefined)
|
|
203
|
+
throw new Error(`Could not extract vout from nonWitnessUtxo for input ${index}.`);
|
|
204
|
+
scriptPubKey = bitcoinjs_lib_1.Transaction.fromBuffer(input.nonWitnessUtxo).outs[vout]
|
|
205
|
+
?.script;
|
|
206
|
+
}
|
|
207
|
+
else if (input.witnessUtxo) {
|
|
208
|
+
scriptPubKey = input.witnessUtxo.script;
|
|
209
|
+
}
|
|
210
|
+
if (!scriptPubKey)
|
|
211
|
+
throw new Error(`Could not retrieve scriptPubKey for input ${index}.`);
|
|
212
|
+
const bip32Derivations = input.bip32Derivation;
|
|
213
|
+
if (!bip32Derivations || !bip32Derivations.length)
|
|
214
|
+
throw new Error(`Input ${index} does not contain bip32 derivations.`);
|
|
215
|
+
const ledgerMasterFingerprint = await getLedgerMasterFingerPrint({
|
|
216
|
+
ledgerManager
|
|
217
|
+
});
|
|
218
|
+
for (const bip32Derivation of bip32Derivations) {
|
|
219
|
+
//get the keyRoot and keyPath. If it matches one of our policies then
|
|
220
|
+
//we are still not sure this is the policy that must be used yet
|
|
221
|
+
//So we must use the template and the keyRoot of each policy and compute the
|
|
222
|
+
//scriptPubKey:
|
|
223
|
+
if (Buffer.compare(bip32Derivation.masterFingerprint, ledgerMasterFingerprint) === 0) {
|
|
224
|
+
// Match /m followed by n consecutive hardened levels and then 2 consecutive unhardened levels:
|
|
225
|
+
const match = bip32Derivation.path.match(/m((\/\d+['hH])*)(\/\d+\/\d+)?/);
|
|
226
|
+
const originPath = match ? match[1] : undefined; //n consecutive hardened levels
|
|
227
|
+
const keyPath = match ? match[3] : undefined; //2 unhardened levels or undefined
|
|
228
|
+
if (originPath && keyPath) {
|
|
229
|
+
const [, strChange, strIndex] = keyPath.split('/');
|
|
230
|
+
if (!strChange || !strIndex)
|
|
231
|
+
throw new Error(`keyPath ${keyPath} incorrectly extracted`);
|
|
232
|
+
const change = parseInt(strChange, 10);
|
|
233
|
+
const index = parseInt(strIndex, 10);
|
|
234
|
+
const coinType = network === bitcoinjs_lib_1.networks.bitcoin ? 0 : 1;
|
|
235
|
+
//standard policy candidate. This policy will be added to the pool
|
|
236
|
+
//of policies below and check if it produces the correct scriptPubKey
|
|
237
|
+
let standardPolicy;
|
|
238
|
+
if (change === 0 || change === 1) {
|
|
239
|
+
const standardTemplate = originPath.match(new RegExp(`^/44'/${coinType}'/(\\d+)'$`))
|
|
240
|
+
? 'pkh(@0/**)'
|
|
241
|
+
: originPath.match(new RegExp(`^/84'/${coinType}'/(\\d+)'$`))
|
|
242
|
+
? 'wpkh(@0/**)'
|
|
243
|
+
: originPath.match(new RegExp(`^/49'/${coinType}'/(\\d+)'$`))
|
|
244
|
+
? 'sh(wpkh(@0/**))'
|
|
245
|
+
: originPath.match(new RegExp(`^/86'/${coinType}'/(\\d+)'$`))
|
|
246
|
+
? 'tr(@0/**)'
|
|
247
|
+
: undefined;
|
|
248
|
+
if (standardTemplate) {
|
|
249
|
+
const xpub = await getLedgerXpub({
|
|
250
|
+
originPath,
|
|
251
|
+
ledgerClient,
|
|
252
|
+
ledgerState
|
|
253
|
+
});
|
|
254
|
+
standardPolicy = {
|
|
255
|
+
ledgerTemplate: standardTemplate,
|
|
256
|
+
keyRoots: [
|
|
257
|
+
`[${ledgerMasterFingerprint.toString('hex')}${originPath}]${xpub}`
|
|
258
|
+
]
|
|
259
|
+
};
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
const policies = [...(ledgerState.policies || [])];
|
|
263
|
+
if (standardPolicy)
|
|
264
|
+
policies.push(standardPolicy);
|
|
265
|
+
for (const policy of policies) {
|
|
266
|
+
//Build the descriptor from the ledgerTemplate + keyRoots
|
|
267
|
+
//then get the scriptPubKey
|
|
268
|
+
let descriptor = policy.ledgerTemplate;
|
|
269
|
+
// Replace change (making sure the value in the change level for the
|
|
270
|
+
// template of the policy meets the change in bip32Derivation):
|
|
271
|
+
descriptor = descriptor.replace(/\/\*\*/g, `/<0;1>/*`);
|
|
272
|
+
const regExpMN = new RegExp(`/<(\\d+);(\\d+)>`, 'g');
|
|
273
|
+
let matchMN;
|
|
274
|
+
while (descriptor && (matchMN = regExpMN.exec(descriptor)) !== null) {
|
|
275
|
+
const [M, N] = [
|
|
276
|
+
parseInt(matchMN[1], 10),
|
|
277
|
+
parseInt(matchMN[2], 10)
|
|
278
|
+
];
|
|
279
|
+
if (M === change || N === change)
|
|
280
|
+
descriptor = descriptor.replace(`/<${M};${N}>`, `/${change}`);
|
|
281
|
+
else
|
|
282
|
+
descriptor = undefined;
|
|
283
|
+
}
|
|
284
|
+
if (descriptor) {
|
|
285
|
+
// Replace index:
|
|
286
|
+
descriptor = descriptor.replace(/\/\*/g, `/${index}`);
|
|
287
|
+
// Replace origin in reverse order to prevent
|
|
288
|
+
// misreplacements, e.g., @10 being mistaken for @1 and leaving a 0.
|
|
289
|
+
for (let i = policy.keyRoots.length - 1; i >= 0; i--) {
|
|
290
|
+
const keyRoot = policy.keyRoots[i];
|
|
291
|
+
if (!keyRoot)
|
|
292
|
+
throw new Error(`keyRoot ${keyRoot} invalidly extracted.`);
|
|
293
|
+
const match = keyRoot.match(/\[([^]+)\]/);
|
|
294
|
+
const keyRootOrigin = match && match[1];
|
|
295
|
+
if (keyRootOrigin) {
|
|
296
|
+
const [, ...arrKeyRootOriginPath] = keyRootOrigin.split('/');
|
|
297
|
+
const keyRootOriginPath = '/' + arrKeyRootOriginPath.join('/');
|
|
298
|
+
//We check all origins to be the same even if they do not
|
|
299
|
+
//belong to the ledger (read the header in this file)
|
|
300
|
+
if (descriptor && keyRootOriginPath === originPath)
|
|
301
|
+
descriptor = descriptor.replace(new RegExp(`@${i}`, 'g'), keyRoot);
|
|
302
|
+
else
|
|
303
|
+
descriptor = undefined;
|
|
304
|
+
}
|
|
305
|
+
else
|
|
306
|
+
descriptor = undefined;
|
|
307
|
+
}
|
|
308
|
+
//verify the scriptPubKey from the input vs. the one obtained from
|
|
309
|
+
//the policy after having filled in the keyPath in the template
|
|
310
|
+
if (descriptor) {
|
|
311
|
+
const policyScriptPubKey = new Output({
|
|
312
|
+
descriptor,
|
|
313
|
+
network
|
|
314
|
+
}).getScriptPubKey();
|
|
315
|
+
if (Buffer.compare(policyScriptPubKey, scriptPubKey) === 0) {
|
|
316
|
+
return policy;
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
return;
|
|
325
|
+
}
|
|
326
|
+
exports.ledgerPolicyFromPsbtInput = ledgerPolicyFromPsbtInput;
|
|
327
|
+
/**
|
|
328
|
+
* Given an output, it extracts its descriptor and converts it to a Ledger
|
|
329
|
+
* Wallet Policy, that is, its keyRoots and template.
|
|
330
|
+
*
|
|
141
331
|
* keyRoots and template follow Ledger's specifications:
|
|
142
332
|
* https://github.com/LedgerHQ/app-bitcoin-new/blob/develop/doc/wallet.md
|
|
143
333
|
*
|
|
@@ -161,11 +351,11 @@ exports.getLedgerXpub = getLedgerXpub;
|
|
|
161
351
|
* This function takes into account all the considerations regarding Ledger
|
|
162
352
|
* policy implementation details expressed in the header of this file.
|
|
163
353
|
*/
|
|
164
|
-
async function
|
|
165
|
-
const expandedExpression =
|
|
166
|
-
const expansionMap =
|
|
354
|
+
async function ledgerPolicyFromOutput({ output, ledgerClient, ledgerState }) {
|
|
355
|
+
const expandedExpression = output.expand().expandedExpression;
|
|
356
|
+
const expansionMap = output.expand().expansionMap;
|
|
167
357
|
if (!expandedExpression || !expansionMap)
|
|
168
|
-
throw new Error(`Error: invalid
|
|
358
|
+
throw new Error(`Error: invalid output`);
|
|
169
359
|
const ledgerMasterFingerprint = await getLedgerMasterFingerPrint({
|
|
170
360
|
ledgerClient,
|
|
171
361
|
ledgerState
|
|
@@ -221,34 +411,57 @@ async function descriptorToLedgerFormat({ descriptor, ledgerClient, ledgerState
|
|
|
221
411
|
});
|
|
222
412
|
return { ledgerTemplate, keyRoots };
|
|
223
413
|
}
|
|
224
|
-
exports.
|
|
414
|
+
exports.ledgerPolicyFromOutput = ledgerPolicyFromOutput;
|
|
225
415
|
/**
|
|
226
|
-
*
|
|
227
|
-
*
|
|
228
|
-
*
|
|
229
|
-
* If the policy is standard, it does not register it.
|
|
230
|
-
*
|
|
416
|
+
* To be removed in v3.0 and replaced by a version that does not accept
|
|
417
|
+
* descriptors
|
|
418
|
+
* @hidden
|
|
231
419
|
**/
|
|
232
|
-
async function registerLedgerWallet({ descriptor, ledgerClient, ledgerState, policyName }) {
|
|
420
|
+
async function registerLedgerWallet({ descriptor, ledgerClient, ledgerState, ledgerManager, policyName }) {
|
|
421
|
+
if (typeof descriptor !== 'string' && ledgerManager)
|
|
422
|
+
throw new Error(`Invalid usage: descriptor must be a string`);
|
|
423
|
+
if (ledgerManager && (ledgerClient || ledgerState))
|
|
424
|
+
throw new Error(`Invalid usage: either ledgerManager or ledgerClient + ledgerState`);
|
|
425
|
+
if (ledgerManager)
|
|
426
|
+
({ ledgerClient, ledgerState } = ledgerManager);
|
|
427
|
+
if (!ledgerClient)
|
|
428
|
+
throw new Error(`ledgerManager not provided`);
|
|
429
|
+
if (!ledgerState)
|
|
430
|
+
throw new Error(`ledgerManager not provided`);
|
|
233
431
|
const { WalletPolicy, AppClient } = (await importAndValidateLedgerBitcoin(ledgerClient));
|
|
234
432
|
if (!(ledgerClient instanceof AppClient))
|
|
235
433
|
throw new Error(`Error: pass a valid ledgerClient`);
|
|
236
|
-
|
|
237
|
-
|
|
434
|
+
let output;
|
|
435
|
+
if (typeof descriptor === 'string') {
|
|
436
|
+
if (!ledgerManager)
|
|
437
|
+
throw new Error(`ledgerManager not provided`);
|
|
438
|
+
const { Output } = (0, descriptors_1.DescriptorsFactory)(ledgerManager.ecc);
|
|
439
|
+
output = new Output({
|
|
440
|
+
descriptor,
|
|
441
|
+
...(descriptor.includes('*') ? { index: 0 } : {}),
|
|
442
|
+
network: ledgerManager.network
|
|
443
|
+
});
|
|
444
|
+
}
|
|
445
|
+
else
|
|
446
|
+
output = descriptor;
|
|
447
|
+
if (await ledgerPolicyFromStandard({ output, ledgerClient, ledgerState }))
|
|
448
|
+
return;
|
|
449
|
+
const result = await ledgerPolicyFromOutput({
|
|
450
|
+
output,
|
|
238
451
|
ledgerClient,
|
|
239
452
|
ledgerState
|
|
240
453
|
});
|
|
241
|
-
if (await ledgerPolicyFromStandard({
|
|
454
|
+
if (await ledgerPolicyFromStandard({ output, ledgerClient, ledgerState }))
|
|
242
455
|
return;
|
|
243
456
|
if (!result)
|
|
244
|
-
throw new Error(`Error:
|
|
457
|
+
throw new Error(`Error: output does not have a ledger input`);
|
|
245
458
|
const { ledgerTemplate, keyRoots } = result;
|
|
246
459
|
if (!ledgerState.policies)
|
|
247
460
|
ledgerState.policies = [];
|
|
248
461
|
let walletPolicy, policyHmac;
|
|
249
462
|
//Search in ledgerState first
|
|
250
463
|
const policy = await ledgerPolicyFromState({
|
|
251
|
-
|
|
464
|
+
output,
|
|
252
465
|
ledgerClient,
|
|
253
466
|
ledgerState
|
|
254
467
|
});
|
|
@@ -275,9 +488,9 @@ exports.registerLedgerWallet = registerLedgerWallet;
|
|
|
275
488
|
/**
|
|
276
489
|
* Retrieve a standard ledger policy or null if it does correspond.
|
|
277
490
|
**/
|
|
278
|
-
async function ledgerPolicyFromStandard({
|
|
279
|
-
const result = await
|
|
280
|
-
|
|
491
|
+
async function ledgerPolicyFromStandard({ output, ledgerClient, ledgerState }) {
|
|
492
|
+
const result = await ledgerPolicyFromOutput({
|
|
493
|
+
output,
|
|
281
494
|
ledgerClient,
|
|
282
495
|
ledgerState
|
|
283
496
|
});
|
|
@@ -287,7 +500,7 @@ async function ledgerPolicyFromStandard({ descriptor, ledgerClient, ledgerState
|
|
|
287
500
|
if (isLedgerStandard({
|
|
288
501
|
ledgerTemplate,
|
|
289
502
|
keyRoots,
|
|
290
|
-
network:
|
|
503
|
+
network: output.getNetwork()
|
|
291
504
|
}))
|
|
292
505
|
return { ledgerTemplate, keyRoots };
|
|
293
506
|
return null;
|
|
@@ -312,14 +525,14 @@ exports.comparePolicies = comparePolicies;
|
|
|
312
525
|
/**
|
|
313
526
|
* Retrieve a ledger policy from ledgerState or null if it does not exist yet.
|
|
314
527
|
**/
|
|
315
|
-
async function ledgerPolicyFromState({
|
|
316
|
-
const result = await
|
|
317
|
-
|
|
528
|
+
async function ledgerPolicyFromState({ output, ledgerClient, ledgerState }) {
|
|
529
|
+
const result = await ledgerPolicyFromOutput({
|
|
530
|
+
output,
|
|
318
531
|
ledgerClient,
|
|
319
532
|
ledgerState
|
|
320
533
|
});
|
|
321
534
|
if (!result)
|
|
322
|
-
throw new Error(`Error:
|
|
535
|
+
throw new Error(`Error: output does not have a ledger input`);
|
|
323
536
|
const { ledgerTemplate, keyRoots } = result;
|
|
324
537
|
if (!ledgerState.policies)
|
|
325
538
|
ledgerState.policies = [];
|
|
@@ -1,57 +1,102 @@
|
|
|
1
1
|
import { Network } from 'bitcoinjs-lib';
|
|
2
|
-
import type { LedgerState } from './ledger';
|
|
2
|
+
import type { LedgerState, LedgerManager } from './ledger';
|
|
3
3
|
import type { BIP32Interface } from 'bip32';
|
|
4
4
|
export declare const pkhBIP32: ({ masterNode, network, keyPath, account, change, index, isPublic }: {
|
|
5
5
|
masterNode: BIP32Interface;
|
|
6
|
+
/** @default networks.bitcoin */
|
|
6
7
|
network?: Network;
|
|
7
8
|
account: number;
|
|
8
9
|
change?: number | undefined;
|
|
9
10
|
index?: number | undefined | '*';
|
|
10
11
|
keyPath?: string;
|
|
12
|
+
/**
|
|
13
|
+
* Compute an xpub or xprv
|
|
14
|
+
* @default true
|
|
15
|
+
*/
|
|
11
16
|
isPublic?: boolean;
|
|
12
17
|
}) => string;
|
|
13
18
|
export declare const shWpkhBIP32: ({ masterNode, network, keyPath, account, change, index, isPublic }: {
|
|
14
19
|
masterNode: BIP32Interface;
|
|
20
|
+
/** @default networks.bitcoin */
|
|
15
21
|
network?: Network;
|
|
16
22
|
account: number;
|
|
17
23
|
change?: number | undefined;
|
|
18
24
|
index?: number | undefined | '*';
|
|
19
25
|
keyPath?: string;
|
|
26
|
+
/**
|
|
27
|
+
* Compute an xpub or xprv
|
|
28
|
+
* @default true
|
|
29
|
+
*/
|
|
20
30
|
isPublic?: boolean;
|
|
21
31
|
}) => string;
|
|
22
32
|
export declare const wpkhBIP32: ({ masterNode, network, keyPath, account, change, index, isPublic }: {
|
|
23
33
|
masterNode: BIP32Interface;
|
|
34
|
+
/** @default networks.bitcoin */
|
|
24
35
|
network?: Network;
|
|
25
36
|
account: number;
|
|
26
37
|
change?: number | undefined;
|
|
27
38
|
index?: number | undefined | '*';
|
|
28
39
|
keyPath?: string;
|
|
40
|
+
/**
|
|
41
|
+
* Compute an xpub or xprv
|
|
42
|
+
* @default true
|
|
43
|
+
*/
|
|
29
44
|
isPublic?: boolean;
|
|
30
45
|
}) => string;
|
|
31
|
-
export declare const pkhLedger:
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
})
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
})
|
|
46
|
+
export declare const pkhLedger: {
|
|
47
|
+
({ ledgerManager, account, keyPath, change, index }: {
|
|
48
|
+
ledgerManager: LedgerManager;
|
|
49
|
+
account: number;
|
|
50
|
+
keyPath?: string;
|
|
51
|
+
change?: number | undefined;
|
|
52
|
+
index?: number | undefined | '*';
|
|
53
|
+
}): Promise<string>;
|
|
54
|
+
({ ledgerClient, ledgerState, network, account, keyPath, change, index }: {
|
|
55
|
+
ledgerClient: unknown;
|
|
56
|
+
ledgerState: LedgerState;
|
|
57
|
+
/** @default networks.bitcoin */
|
|
58
|
+
network?: Network;
|
|
59
|
+
account: number;
|
|
60
|
+
keyPath?: string;
|
|
61
|
+
change?: number | undefined;
|
|
62
|
+
index?: number | undefined | '*';
|
|
63
|
+
}): Promise<string>;
|
|
64
|
+
};
|
|
65
|
+
export declare const shWpkhLedger: {
|
|
66
|
+
({ ledgerManager, account, keyPath, change, index }: {
|
|
67
|
+
ledgerManager: LedgerManager;
|
|
68
|
+
account: number;
|
|
69
|
+
keyPath?: string;
|
|
70
|
+
change?: number | undefined;
|
|
71
|
+
index?: number | undefined | '*';
|
|
72
|
+
}): Promise<string>;
|
|
73
|
+
({ ledgerClient, ledgerState, network, account, keyPath, change, index }: {
|
|
74
|
+
ledgerClient: unknown;
|
|
75
|
+
ledgerState: LedgerState;
|
|
76
|
+
/** @default networks.bitcoin */
|
|
77
|
+
network?: Network;
|
|
78
|
+
account: number;
|
|
79
|
+
keyPath?: string;
|
|
80
|
+
change?: number | undefined;
|
|
81
|
+
index?: number | undefined | '*';
|
|
82
|
+
}): Promise<string>;
|
|
83
|
+
};
|
|
84
|
+
export declare const wpkhLedger: {
|
|
85
|
+
({ ledgerManager, account, keyPath, change, index }: {
|
|
86
|
+
ledgerManager: LedgerManager;
|
|
87
|
+
account: number;
|
|
88
|
+
keyPath?: string;
|
|
89
|
+
change?: number | undefined;
|
|
90
|
+
index?: number | undefined | '*';
|
|
91
|
+
}): Promise<string>;
|
|
92
|
+
({ ledgerClient, ledgerState, network, account, keyPath, change, index }: {
|
|
93
|
+
ledgerClient: unknown;
|
|
94
|
+
ledgerState: LedgerState;
|
|
95
|
+
/** @default networks.bitcoin */
|
|
96
|
+
network?: Network;
|
|
97
|
+
account: number;
|
|
98
|
+
keyPath?: string;
|
|
99
|
+
change?: number | undefined;
|
|
100
|
+
index?: number | undefined | '*';
|
|
101
|
+
}): Promise<string>;
|
|
102
|
+
};
|
|
@@ -11,7 +11,20 @@ function assertStandardKeyPath(keyPath) {
|
|
|
11
11
|
}
|
|
12
12
|
}
|
|
13
13
|
function standardExpressionsBIP32Maker(purpose, scriptTemplate) {
|
|
14
|
-
|
|
14
|
+
/**
|
|
15
|
+
* Computes the standard descriptor based on given parameters.
|
|
16
|
+
*
|
|
17
|
+
* You can define the output location either by:
|
|
18
|
+
* - Providing the full `keyPath` (e.g., "/0/2").
|
|
19
|
+
* OR
|
|
20
|
+
* - Specifying the `change` and `index` values separately (e.g., `{change:0, index:2}`).
|
|
21
|
+
*
|
|
22
|
+
* For ranged indexing, the `index` can be set as a wildcard '*'. For example:
|
|
23
|
+
* - `keyPath="/0/*"`
|
|
24
|
+
* OR
|
|
25
|
+
* - `{change:0, index:'*'}`.
|
|
26
|
+
*/
|
|
27
|
+
function standardScriptExpressionBIP32({ masterNode, network = bitcoinjs_lib_1.networks.bitcoin, keyPath, account, change, index, isPublic = true }) {
|
|
15
28
|
const originPath = `/${purpose}'/${network === bitcoinjs_lib_1.networks.bitcoin ? 0 : 1}'/${account}'`;
|
|
16
29
|
if (keyPath !== undefined)
|
|
17
30
|
assertStandardKeyPath(keyPath);
|
|
@@ -25,13 +38,22 @@ function standardExpressionsBIP32Maker(purpose, scriptTemplate) {
|
|
|
25
38
|
});
|
|
26
39
|
return scriptTemplate.replace('KEYEXPRESSION', keyExpression);
|
|
27
40
|
}
|
|
28
|
-
return
|
|
41
|
+
return standardScriptExpressionBIP32;
|
|
29
42
|
}
|
|
30
43
|
exports.pkhBIP32 = standardExpressionsBIP32Maker(44, 'pkh(KEYEXPRESSION)');
|
|
31
44
|
exports.shWpkhBIP32 = standardExpressionsBIP32Maker(49, 'sh(wpkh(KEYEXPRESSION))');
|
|
32
45
|
exports.wpkhBIP32 = standardExpressionsBIP32Maker(84, 'wpkh(KEYEXPRESSION)');
|
|
33
46
|
function standardExpressionsLedgerMaker(purpose, scriptTemplate) {
|
|
34
|
-
|
|
47
|
+
/** @hidden */
|
|
48
|
+
async function standardScriptExpressionLedger({ ledgerClient, ledgerState, ledgerManager, network = bitcoinjs_lib_1.networks.bitcoin, account, keyPath, change, index }) {
|
|
49
|
+
if (ledgerManager && (ledgerClient || ledgerState))
|
|
50
|
+
throw new Error(`ledgerClient and ledgerState have been deprecated`);
|
|
51
|
+
if (ledgerManager && network)
|
|
52
|
+
throw new Error(`ledgerManager already includes the network object`);
|
|
53
|
+
if (ledgerManager)
|
|
54
|
+
({ ledgerClient, ledgerState, network } = ledgerManager);
|
|
55
|
+
if (!ledgerClient || !ledgerState)
|
|
56
|
+
throw new Error(`Could not retrieve ledgerClient or ledgerState`);
|
|
35
57
|
const originPath = `/${purpose}'/${network === bitcoinjs_lib_1.networks.bitcoin ? 0 : 1}'/${account}'`;
|
|
36
58
|
if (keyPath !== undefined)
|
|
37
59
|
assertStandardKeyPath(keyPath);
|
|
@@ -45,7 +67,7 @@ function standardExpressionsLedgerMaker(purpose, scriptTemplate) {
|
|
|
45
67
|
});
|
|
46
68
|
return scriptTemplate.replace('KEYEXPRESSION', keyExpression);
|
|
47
69
|
}
|
|
48
|
-
return
|
|
70
|
+
return standardScriptExpressionLedger;
|
|
49
71
|
}
|
|
50
72
|
exports.pkhLedger = standardExpressionsLedgerMaker(44, 'pkh(KEYEXPRESSION)');
|
|
51
73
|
exports.shWpkhLedger = standardExpressionsLedgerMaker(49, 'sh(wpkh(KEYEXPRESSION))');
|
package/dist/signers.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import type { Psbt } from 'bitcoinjs-lib';
|
|
|
2
2
|
import type { ECPairInterface } from 'ecpair';
|
|
3
3
|
import type { BIP32Interface } from 'bip32';
|
|
4
4
|
import type { DescriptorInstance } from './descriptors';
|
|
5
|
-
import { LedgerState } from './ledger';
|
|
5
|
+
import { LedgerState, LedgerManager } from './ledger';
|
|
6
6
|
export declare function signInputECPair({ psbt, index, ecpair }: {
|
|
7
7
|
psbt: Psbt;
|
|
8
8
|
index: number;
|
|
@@ -21,6 +21,21 @@ export declare function signBIP32({ psbt, masterNode }: {
|
|
|
21
21
|
psbt: Psbt;
|
|
22
22
|
masterNode: BIP32Interface;
|
|
23
23
|
}): void;
|
|
24
|
+
/**
|
|
25
|
+
* Signs an input of the `psbt` where the keys are controlled by a Ledger
|
|
26
|
+
* device.
|
|
27
|
+
*
|
|
28
|
+
* The function will throw an error if it's unable to sign the input.
|
|
29
|
+
*/
|
|
30
|
+
export declare function signInputLedger({ psbt, index, ledgerManager }: {
|
|
31
|
+
psbt: Psbt;
|
|
32
|
+
index: number;
|
|
33
|
+
ledgerManager: LedgerManager;
|
|
34
|
+
}): Promise<void>;
|
|
35
|
+
/**
|
|
36
|
+
* @deprecated
|
|
37
|
+
* @hidden
|
|
38
|
+
*/
|
|
24
39
|
export declare function signInputLedger({ psbt, index, descriptor, ledgerClient, ledgerState }: {
|
|
25
40
|
psbt: Psbt;
|
|
26
41
|
index: number;
|
|
@@ -28,6 +43,24 @@ export declare function signInputLedger({ psbt, index, descriptor, ledgerClient,
|
|
|
28
43
|
ledgerClient: unknown;
|
|
29
44
|
ledgerState: LedgerState;
|
|
30
45
|
}): Promise<void>;
|
|
46
|
+
/**
|
|
47
|
+
* Signs the inputs of the `psbt` where the keys are controlled by a Ledger
|
|
48
|
+
* device.
|
|
49
|
+
*
|
|
50
|
+
* `signLedger` can sign multiple inputs of the same wallet policy in a single
|
|
51
|
+
* pass by grouping inputs by their wallet policy type before the signing
|
|
52
|
+
* process.
|
|
53
|
+
*
|
|
54
|
+
* The function will throw an error if it's unable to sign any input.
|
|
55
|
+
*/
|
|
56
|
+
export declare function signLedger({ psbt, ledgerManager }: {
|
|
57
|
+
psbt: Psbt;
|
|
58
|
+
ledgerManager: LedgerManager;
|
|
59
|
+
}): Promise<void>;
|
|
60
|
+
/**
|
|
61
|
+
* @deprecated
|
|
62
|
+
* @hidden
|
|
63
|
+
*/
|
|
31
64
|
export declare function signLedger({ psbt, descriptors, ledgerClient, ledgerState }: {
|
|
32
65
|
psbt: Psbt;
|
|
33
66
|
descriptors: DescriptorInstance[];
|