@bitcoinerlab/descriptors 0.2.1 → 0.3.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.
@@ -44,17 +44,17 @@ const derivePath = (node, path) => {
44
44
  return node.derivePath(parsedPath);
45
45
  };
46
46
  /*
47
- * Takes a key expression (xpub, xprv, pubkey or wif) and returns a pubkey in
48
- * binary format
47
+ * Parses a key expression (xpub, xprv, pubkey or wif) into KeyInfo
49
48
  */
50
49
  function parseKeyExpression({ keyExpression, isSegwit, ECPair, BIP32, network = bitcoinjs_lib_1.networks.bitcoin }) {
51
- let pubkey;
50
+ let pubkey; //won't be computed for ranged keyExpressions
52
51
  let ecpair;
53
52
  let bip32;
54
53
  let masterFingerprint;
55
54
  let originPath;
56
55
  let keyPath;
57
56
  let path;
57
+ const isRanged = keyExpression.indexOf('*') !== -1;
58
58
  //Validate the keyExpression:
59
59
  const keyExpressions = keyExpression.match(RE.reKeyExp);
60
60
  if (keyExpressions === null || keyExpressions[0] !== keyExpression) {
@@ -115,7 +115,8 @@ function parseKeyExpression({ keyExpression, isSegwit, ECPair, BIP32, network =
115
115
  if (!keyPath)
116
116
  throw new Error(`Error: could not extract a path`);
117
117
  //fromBase58 and derivePath will throw if xPub or path are not valid
118
- pubkey = derivePath(bip32, keyPath).publicKey;
118
+ if (!isRanged)
119
+ pubkey = derivePath(bip32, keyPath).publicKey;
119
120
  }
120
121
  else {
121
122
  pubkey = bip32.publicKey;
@@ -134,7 +135,8 @@ function parseKeyExpression({ keyExpression, isSegwit, ECPair, BIP32, network =
134
135
  if (!keyPath)
135
136
  throw new Error(`Error: could not extract a path`);
136
137
  //fromBase58 and derivePath will throw if xPrv or path are not valid
137
- pubkey = derivePath(bip32, keyPath).publicKey;
138
+ if (!isRanged)
139
+ pubkey = derivePath(bip32, keyPath).publicKey;
138
140
  }
139
141
  else {
140
142
  pubkey = bip32.publicKey;
@@ -143,12 +145,12 @@ function parseKeyExpression({ keyExpression, isSegwit, ECPair, BIP32, network =
143
145
  else {
144
146
  throw new Error(`Error: could not get pubkey for keyExpression ${keyExpression}`);
145
147
  }
146
- if (masterFingerprint && (originPath || keyPath)) {
147
- path = 'm' + originPath + keyPath;
148
+ if (originPath || keyPath) {
149
+ path = `m${originPath ?? ''}${keyPath ?? ''}`;
148
150
  }
149
151
  return {
150
- pubkey,
151
152
  keyExpression,
153
+ ...(pubkey !== undefined ? { pubkey } : {}),
152
154
  ...(ecpair !== undefined ? { ecpair } : {}),
153
155
  ...(bip32 !== undefined ? { bip32 } : {}),
154
156
  ...(masterFingerprint !== undefined ? { masterFingerprint } : {}),
@@ -161,7 +163,7 @@ exports.parseKeyExpression = parseKeyExpression;
161
163
  function assertChangeIndexKeyPath({ change, index, keyPath }) {
162
164
  if (!((change === undefined && index === undefined) ||
163
165
  (change !== undefined && index !== undefined)))
164
- throw new Error(`Error: Pass change, index and network or neither`);
166
+ throw new Error(`Error: Pass change and index or neither`);
165
167
  if ((change !== undefined) === (keyPath !== undefined))
166
168
  throw new Error(`Error: Pass either change and index or a keyPath`);
167
169
  }
package/dist/ledger.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  /// <reference types="node" />
2
2
  import type { DescriptorInterface } from './types';
3
- import { AppClient } from '@bitcoinerlab/ledger';
3
+ import { AppClient } from 'ledger-bitcoin';
4
4
  export declare function assertLedgerApp({ transport, name, minVersion }: {
5
5
  transport: any;
6
6
  name: string;
package/dist/ledger.js CHANGED
@@ -3,7 +3,7 @@
3
3
  // Distributed under the MIT software license
4
4
  Object.defineProperty(exports, "__esModule", { value: true });
5
5
  exports.ledgerPolicyFromState = exports.comparePolicies = exports.ledgerPolicyFromStandard = exports.registerLedgerWallet = exports.descriptorToLedgerFormat = exports.getLedgerXpub = exports.getLedgerMasterFingerPrint = exports.assertLedgerApp = void 0;
6
- const ledger_1 = require("@bitcoinerlab/ledger");
6
+ const ledger_bitcoin_1 = require("ledger-bitcoin");
7
7
  const bitcoinjs_lib_1 = require("bitcoinjs-lib");
8
8
  const re_1 = require("./re");
9
9
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -204,7 +204,7 @@ async function registerLedgerWallet({ descriptor, ledgerClient, ledgerState, pol
204
204
  //It already existed. No need to register it again.
205
205
  }
206
206
  else {
207
- walletPolicy = new ledger_1.WalletPolicy(policyName, ledgerTemplate, keyRoots);
207
+ walletPolicy = new ledger_bitcoin_1.WalletPolicy(policyName, ledgerTemplate, keyRoots);
208
208
  let policyId;
209
209
  [policyId, policyHmac] = await ledgerClient.registerWallet(walletPolicy);
210
210
  const policy = {
@@ -51,8 +51,11 @@ function expandMiniscript({ miniscript, isSegwit, network = bitcoinjs_lib_1.netw
51
51
  return key;
52
52
  });
53
53
  //Do some assertions. Miniscript must not have duplicate keys, also all
54
- //keyExpressions must produce a valid pubkey
55
- const pubkeysHex = Object.values(expansionMap).map(keyInfo => {
54
+ //keyExpressions must produce a valid pubkey (unless it's ranged and we want
55
+ //to expand a generalized form, then we don't check)
56
+ const pubkeysHex = Object.values(expansionMap)
57
+ .filter(keyInfo => keyInfo.keyExpression.indexOf('*') === -1)
58
+ .map(keyInfo => {
56
59
  if (!keyInfo.pubkey)
57
60
  throw new Error(`Error: keyExpression ${keyInfo.keyExpression} does not have a pubkey`);
58
61
  return keyInfo.pubkey.toString('hex');
@@ -91,7 +94,7 @@ function substituteAsm({ expandedAsm, expansionMap }) {
91
94
  //enclosed in <>, since <> represents hex code already encoded.
92
95
  //The regex below will match one or more digits within a string,
93
96
  //except if the sequence is surrounded by "<" and ">"
94
- .replace(/(?<![<])\b\d+\b(?![>])/g, (num) => numberEncodeAsm(Number(num)))
97
+ .replace(/(<\d+>)|\b\d+\b/g, match => match.startsWith('<') ? match : numberEncodeAsm(Number(match)))
95
98
  //we don't have numbers anymore, now it's safe to remove < and > since we
96
99
  //know that every remaining is either an op_code or a hex encoded number
97
100
  .replace(/[<>]/g, '');
@@ -133,7 +136,7 @@ function satisfyMiniscript({ expandedMiniscript, expansionMap, signatures = [],
133
136
  const expandedSignatureMap = {};
134
137
  signatures.forEach(signature => {
135
138
  const pubkeyHex = signature.pubkey.toString('hex');
136
- const keyExpression = Object.keys(expansionMap).find(k => expansionMap[k]?.pubkey.toString('hex') === pubkeyHex);
139
+ const keyExpression = Object.keys(expansionMap).find(k => expansionMap[k]?.pubkey?.toString('hex') === pubkeyHex);
137
140
  expandedSignatureMap['<sig(' + keyExpression + ')>'] =
138
141
  '<' + signature.signature.toString('hex') + '>';
139
142
  });
package/dist/psbt.js CHANGED
@@ -144,26 +144,20 @@ function updatePsbt({ psbt, vout, txHex, txId, value, sequence, locktime, keysIn
144
144
  }
145
145
  if (txId === undefined || !value)
146
146
  throw new Error(`Error: txHex+vout required. Alternatively, but ONLY for Segwit inputs, txId+value can also be passed.`);
147
- if (locktime !== undefined) {
148
- if (psbt.locktime !== 0 && psbt.locktime !== undefined)
149
- throw new Error(`Error: transaction locktime has already been set: ${psbt.locktime}`);
150
- psbt.setLocktime(locktime);
151
- }
152
- let inputSequence;
153
- if (locktime !== undefined) {
147
+ if (locktime) {
148
+ if (psbt.locktime && psbt.locktime !== locktime)
149
+ throw new Error(`Error: transaction locktime was already set with a different value: ${locktime} != ${psbt.locktime}`);
150
+ // nLockTime only works if at least one of the transaction inputs has an
151
+ // nSequence value that is below 0xffffffff. Let's make sure that at least
152
+ // this input's sequence < 0xffffffff
154
153
  if (sequence === undefined) {
155
- // for CTV nSequence MUST be <= 0xfffffffe otherwise OP_CHECKLOCKTIMEVERIFY will fail.
156
- inputSequence = 0xfffffffe;
154
+ //NOTE: if sequence is undefined, bitcoinjs-lib uses 0xffffffff as default
155
+ sequence = 0xfffffffe;
157
156
  }
158
157
  else if (sequence > 0xfffffffe) {
159
- throw new Error(`Error: incompatible sequence: ${inputSequence} and locktime: ${locktime}`);
160
- }
161
- else {
162
- inputSequence = sequence;
158
+ throw new Error(`Error: incompatible sequence: ${sequence} and locktime: ${locktime}`);
163
159
  }
164
- }
165
- else {
166
- inputSequence = sequence;
160
+ psbt.setLocktime(locktime);
167
161
  }
168
162
  const input = {
169
163
  hash: reverseBuffer(Buffer.from(txId, 'hex')),
@@ -174,19 +168,24 @@ function updatePsbt({ psbt, vout, txHex, txId, value, sequence, locktime, keysIn
174
168
  }
175
169
  const bip32Derivation = keysInfo
176
170
  .filter((keyInfo) => keyInfo.pubkey && keyInfo.masterFingerprint && keyInfo.path)
177
- .map((keyInfo) => ({
178
- masterFingerprint: keyInfo.masterFingerprint,
179
- pubkey: keyInfo.pubkey,
180
- path: keyInfo.path
181
- }));
171
+ .map((keyInfo) => {
172
+ const pubkey = keyInfo.pubkey;
173
+ if (!pubkey)
174
+ throw new Error(`key ${keyInfo.keyExpression} missing pubkey`);
175
+ return {
176
+ masterFingerprint: keyInfo.masterFingerprint,
177
+ pubkey,
178
+ path: keyInfo.path
179
+ };
180
+ });
182
181
  if (bip32Derivation.length)
183
182
  input.bip32Derivation = bip32Derivation;
184
183
  if (isSegwit && txHex !== undefined) {
185
184
  //There's no need to put both witnessUtxo and nonWitnessUtxo
186
185
  input.witnessUtxo = { script: scriptPubKey, value };
187
186
  }
188
- if (inputSequence !== undefined)
189
- input.sequence = inputSequence;
187
+ if (sequence !== undefined)
188
+ input.sequence = sequence;
190
189
  if (witnessScript)
191
190
  input.witnessScript = witnessScript;
192
191
  if (redeemScript)
@@ -1,4 +1,4 @@
1
- import type { AppClient } from '@bitcoinerlab/ledger';
1
+ import type { AppClient } from 'ledger-bitcoin';
2
2
  import { Network } from 'bitcoinjs-lib';
3
3
  import type { LedgerState } from './ledger';
4
4
  import type { BIP32Interface } from 'bip32';
package/dist/signers.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import type { Psbt } from 'bitcoinjs-lib';
2
2
  import type { ECPairInterface } from 'ecpair';
3
3
  import type { BIP32Interface } from 'bip32';
4
- import { AppClient } from '@bitcoinerlab/ledger';
4
+ import { AppClient } from 'ledger-bitcoin';
5
5
  import type { DescriptorInterface } from './types';
6
6
  import { LedgerState } from './ledger';
7
7
  export declare function signInputECPair({ psbt, index, ecpair }: {
package/dist/signers.js CHANGED
@@ -3,8 +3,8 @@
3
3
  // Distributed under the MIT software license
4
4
  Object.defineProperty(exports, "__esModule", { value: true });
5
5
  exports.signLedger = exports.signInputLedger = exports.signBIP32 = exports.signInputBIP32 = exports.signECPair = exports.signInputECPair = void 0;
6
- const ledger_1 = require("@bitcoinerlab/ledger");
7
- const ledger_2 = require("./ledger");
6
+ const ledger_bitcoin_1 = require("ledger-bitcoin");
7
+ const ledger_1 = require("./ledger");
8
8
  function signInputECPair({ psbt, index, ecpair }) {
9
9
  psbt.signInput(index, ecpair);
10
10
  }
@@ -23,12 +23,12 @@ function signBIP32({ psbt, masterNode }) {
23
23
  exports.signBIP32 = signBIP32;
24
24
  const ledgerSignaturesForInputIndex = (index, ledgerSignatures) => ledgerSignatures
25
25
  .filter(([i]) => i === index)
26
- .map(([_i, pubkey, signature]) => ({
27
- pubkey,
28
- signature
26
+ .map(([_i, partialSignature]) => ({
27
+ pubkey: partialSignature.pubkey,
28
+ signature: partialSignature.signature
29
29
  }));
30
30
  async function signInputLedger({ psbt, index, descriptor, ledgerClient, ledgerState }) {
31
- const result = await (0, ledger_2.descriptorToLedgerFormat)({
31
+ const result = await (0, ledger_1.descriptorToLedgerFormat)({
32
32
  descriptor,
33
33
  ledgerClient,
34
34
  ledgerState
@@ -37,24 +37,24 @@ async function signInputLedger({ psbt, index, descriptor, ledgerClient, ledgerSt
37
37
  throw new Error(`Error: descriptor does not have a ledger input`);
38
38
  const { ledgerTemplate, keyRoots } = result;
39
39
  let ledgerSignatures;
40
- const standardPolicy = await (0, ledger_2.ledgerPolicyFromStandard)({
40
+ const standardPolicy = await (0, ledger_1.ledgerPolicyFromStandard)({
41
41
  descriptor,
42
42
  ledgerClient,
43
43
  ledgerState
44
44
  });
45
45
  if (standardPolicy) {
46
- ledgerSignatures = await ledgerClient.signPsbt(new ledger_1.PsbtV2().fromBitcoinJS(psbt), new ledger_1.DefaultWalletPolicy(ledgerTemplate, keyRoots[0]), null);
46
+ ledgerSignatures = await ledgerClient.signPsbt(new ledger_bitcoin_1.PsbtV2().fromBitcoinJS(psbt), new ledger_bitcoin_1.DefaultWalletPolicy(ledgerTemplate, keyRoots[0]), null);
47
47
  }
48
48
  else {
49
- const policy = await (0, ledger_2.ledgerPolicyFromState)({
49
+ const policy = await (0, ledger_1.ledgerPolicyFromState)({
50
50
  descriptor,
51
51
  ledgerClient,
52
52
  ledgerState
53
53
  });
54
54
  if (!policy || !policy.policyName || !policy.policyHmac)
55
55
  throw new Error(`Error: the descriptor's policy is not registered`);
56
- const walletPolicy = new ledger_1.WalletPolicy(policy.policyName, ledgerTemplate, keyRoots);
57
- ledgerSignatures = await ledgerClient.signPsbt(new ledger_1.PsbtV2().fromBitcoinJS(psbt), walletPolicy, policy.policyHmac);
56
+ const walletPolicy = new ledger_bitcoin_1.WalletPolicy(policy.policyName, ledgerTemplate, keyRoots);
57
+ ledgerSignatures = await ledgerClient.signPsbt(new ledger_bitcoin_1.PsbtV2().fromBitcoinJS(psbt), walletPolicy, policy.policyHmac);
58
58
  }
59
59
  //Add the signatures to the Psbt object using PartialSig format:
60
60
  psbt.updateInput(index, {
@@ -68,12 +68,12 @@ exports.signInputLedger = signInputLedger;
68
68
  async function signLedger({ psbt, descriptors, ledgerClient, ledgerState }) {
69
69
  const ledgerPolicies = [];
70
70
  for (const descriptor of descriptors) {
71
- const policy = (await (0, ledger_2.ledgerPolicyFromState)({
71
+ const policy = (await (0, ledger_1.ledgerPolicyFromState)({
72
72
  descriptor,
73
73
  ledgerClient,
74
74
  ledgerState
75
75
  })) ||
76
- (await (0, ledger_2.ledgerPolicyFromStandard)({
76
+ (await (0, ledger_1.ledgerPolicyFromStandard)({
77
77
  descriptor,
78
78
  ledgerClient,
79
79
  ledgerState
@@ -86,7 +86,7 @@ async function signLedger({ psbt, descriptors, ledgerClient, ledgerState }) {
86
86
  //cluster unique LedgerPolicies
87
87
  const uniquePolicies = [];
88
88
  for (const policy of ledgerPolicies) {
89
- if (!uniquePolicies.find((uniquePolicy) => (0, ledger_2.comparePolicies)(uniquePolicy, policy)))
89
+ if (!uniquePolicies.find((uniquePolicy) => (0, ledger_1.comparePolicies)(uniquePolicy, policy)))
90
90
  uniquePolicies.push(policy);
91
91
  }
92
92
  for (const uniquePolicy of uniquePolicies) {
@@ -95,12 +95,12 @@ async function signLedger({ psbt, descriptors, ledgerClient, ledgerState }) {
95
95
  uniquePolicy.policyHmac &&
96
96
  uniquePolicy.policyId) {
97
97
  //non-standard policy
98
- const walletPolicy = new ledger_1.WalletPolicy(uniquePolicy.policyName, uniquePolicy.ledgerTemplate, uniquePolicy.keyRoots);
99
- ledgerSignatures = await ledgerClient.signPsbt(new ledger_1.PsbtV2().fromBitcoinJS(psbt), walletPolicy, uniquePolicy.policyHmac);
98
+ const walletPolicy = new ledger_bitcoin_1.WalletPolicy(uniquePolicy.policyName, uniquePolicy.ledgerTemplate, uniquePolicy.keyRoots);
99
+ ledgerSignatures = await ledgerClient.signPsbt(new ledger_bitcoin_1.PsbtV2().fromBitcoinJS(psbt), walletPolicy, uniquePolicy.policyHmac);
100
100
  }
101
101
  else {
102
102
  //standard policy
103
- ledgerSignatures = await ledgerClient.signPsbt(new ledger_1.PsbtV2().fromBitcoinJS(psbt), new ledger_1.DefaultWalletPolicy(uniquePolicy.ledgerTemplate, uniquePolicy.keyRoots[0]), null);
103
+ ledgerSignatures = await ledgerClient.signPsbt(new ledger_bitcoin_1.PsbtV2().fromBitcoinJS(psbt), new ledger_bitcoin_1.DefaultWalletPolicy(uniquePolicy.ledgerTemplate, uniquePolicy.keyRoots[0]), null);
104
104
  }
105
105
  for (const [index, ,] of ledgerSignatures) {
106
106
  psbt.updateInput(index, {
package/dist/types.d.ts CHANGED
@@ -3,17 +3,30 @@ import type { ECPairInterface } from 'ecpair';
3
3
  import type { BIP32Interface } from 'bip32';
4
4
  import type { Network, Payment, Psbt } from 'bitcoinjs-lib';
5
5
  import type { PartialSig } from 'bip174/src/lib/interfaces';
6
- export interface Preimage {
6
+ /**
7
+ * Preimage
8
+ * @alias Preimage
9
+ * @memberof Descriptor
10
+ */
11
+ export type Preimage = {
12
+ /**
13
+ * Use same expressions as in miniscript. For example: "sha256(cdabb7f2dce7bfbd8a0b9570c6fd1e712e5d64045e9d6b517b3d5072251dc204)" or "ripemd160(095ff41131e5946f3c85f79e44adbcf8e27e080e)"
14
+ * Accepted functions: sha256, hash256, ripemd160, hash160
15
+ * Digests must be: 64-character HEX for sha256, hash160 or 30-character HEX for ripemd160 or hash160.
16
+ */
7
17
  digest: string;
18
+ /**
19
+ * Hex encoded preimate. Preimages are always 32 bytes (so, 64 character in hex).
20
+ */
8
21
  preimage: string;
9
- }
22
+ };
10
23
  export type TimeConstraints = {
11
24
  nLockTime: number | undefined;
12
25
  nSequence: number | undefined;
13
26
  };
14
27
  export type KeyInfo = {
15
28
  keyExpression: string;
16
- pubkey: Buffer;
29
+ pubkey?: Buffer;
17
30
  ecpair?: ECPairInterface;
18
31
  bip32?: BIP32Interface;
19
32
  masterFingerprint?: Buffer;
@@ -31,6 +44,23 @@ export interface ParseKeyExpression {
31
44
  network?: Network;
32
45
  }): KeyInfo;
33
46
  }
47
+ export interface Expand {
48
+ (params: {
49
+ expression: string;
50
+ loggedExpression?: string;
51
+ network?: Network;
52
+ allowMiniscriptInP2SH?: boolean;
53
+ }): {
54
+ payment?: Payment;
55
+ expandedExpression?: string;
56
+ miniscript?: string;
57
+ expansionMap?: ExpansionMap;
58
+ isSegwit?: boolean;
59
+ expandedMiniscript?: string;
60
+ redeemScript?: Buffer;
61
+ witnessScript?: Buffer;
62
+ };
63
+ }
34
64
  interface XOnlyPointAddTweakResult {
35
65
  parity: 1 | 0;
36
66
  xOnlyPubkey: Uint8Array;
@@ -49,6 +79,12 @@ export interface TinySecp256k1Interface {
49
79
  xOnlyPointAddTweak(p: Uint8Array, tweak: Uint8Array): XOnlyPointAddTweakResult | null;
50
80
  privateNegate(d: Uint8Array): Uint8Array;
51
81
  }
82
+ /**
83
+ * DescriptorInfo
84
+ * What defines a Descriptor. This is the type needed in the constructor.
85
+ * @alias DescriptorInfo
86
+ * @memberof Descriptor
87
+ */
52
88
  export type DescriptorInfo = {
53
89
  expression: string;
54
90
  index?: number;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@bitcoinerlab/descriptors",
3
3
  "homepage": "https://github.com/bitcoinerlab/descriptors",
4
- "version": "0.2.1",
4
+ "version": "0.3.0",
5
5
  "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.",
6
6
  "main": "dist/index.js",
7
7
  "types": "dist/index.d.ts",
@@ -9,7 +9,7 @@
9
9
  "build": "npx tsc",
10
10
  "prepublishOnly": "npm run build && npm test && echo \"\\n\\n\" && npm run test:integration:ledger",
11
11
  "docs": "jsdoc -c jsdoc.json",
12
- "regtest-docker": "docker ps | grep bitcoinjs-regtest-server > /dev/null || (docker pull junderw/bitcoinjs-regtest-server && docker run -d -p 8080:8080 junderw/bitcoinjs-regtest-server && sleep 5)",
12
+ "regtest-docker": "docker ps | grep bitcoinerlab/tester > /dev/null || (docker pull bitcoinerlab/tester && docker run -d -p 8080:8080 -p 60401:60401 -p 3002:3002 bitcoinerlab/tester && sleep 5)",
13
13
  "test:integration:soft": "npm run regtest-docker && npx ts-node test/integration/standardOutputs.ts && echo \"\\n\\n\" && npx ts-node test/integration/miniscript.ts",
14
14
  "test:integration:ledger": "npm run regtest-docker && npx ts-node test/integration/ledger.ts",
15
15
  "test:unit": "npm run build && node test/tools/generateBitcoinCoreFixtures.js && jest",
@@ -52,13 +52,14 @@
52
52
  "files": [
53
53
  "dist"
54
54
  ],
55
+ "COMMENT wrt ledger-bitcoin below": "ledger-bitcoin is installed using an alias. This package can be replaced with the official `ledger-bitcoin` npm package once [this PR](https://github.com/LedgerHQ/app-bitcoin-new/pull/147) is published to npm (likely in version > 0.2.1)",
55
56
  "dependencies": {
56
- "@bitcoinerlab/ledger": "^0.1.7",
57
57
  "@bitcoinerlab/miniscript": "^1.2.1",
58
58
  "@bitcoinerlab/secp256k1": "^1.0.2",
59
59
  "bip32": "^3.1.0",
60
60
  "bitcoinjs-lib": "^6.1.0",
61
- "ecpair": "^2.1.0"
61
+ "ecpair": "^2.1.0",
62
+ "ledger-bitcoin": "npm:@bitcoinerlab/ledger@^0.2.0"
62
63
  },
63
64
  "devDependencies": {
64
65
  "@babel/plugin-transform-modules-commonjs": "^7.20.11",
@@ -66,6 +67,7 @@
66
67
  "@typescript-eslint/eslint-plugin": "^5.53.0",
67
68
  "@typescript-eslint/parser": "^5.53.0",
68
69
  "babel-plugin-transform-import-meta": "^2.2.0",
70
+ "better-docs": "^2.7.2",
69
71
  "bip39": "^3.0.4",
70
72
  "bip65": "^1.0.3",
71
73
  "bip68": "^1.0.4",
@@ -74,9 +76,9 @@
74
76
  "eslint-plugin-prettier": "^4.2.1",
75
77
  "fs": "^0.0.1-security",
76
78
  "jest": "^29.4.3",
77
- "jsdoc": "^4.0.0",
79
+ "jsdoc": "^3.6.11",
78
80
  "path": "^0.12.7",
79
- "prettier": "^2.8.4",
81
+ "prettier": "^2.8.8",
80
82
  "regtest-client": "^0.2.0",
81
83
  "ts-node-dev": "^2.0.0"
82
84
  }