@ledgerhq/hw-app-btc 9.0.1-nightly.0 → 9.1.0-next.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/.turbo/turbo-build.log +1 -1
- package/CHANGELOG.md +15 -2
- package/README.md +33 -111
- package/lib/Btc.d.ts +12 -11
- package/lib/Btc.d.ts.map +1 -1
- package/lib/Btc.js +47 -143
- package/lib/Btc.js.map +1 -1
- package/lib/BtcNew.d.ts +2 -4
- package/lib/BtcNew.d.ts.map +1 -1
- package/lib/BtcNew.js +54 -13
- package/lib/BtcNew.js.map +1 -1
- package/lib/BtcOld.d.ts +2 -37
- package/lib/BtcOld.d.ts.map +1 -1
- package/lib/BtcOld.js +3 -45
- package/lib/BtcOld.js.map +1 -1
- package/lib/getAppAndVersion.d.ts +1 -0
- package/lib/getAppAndVersion.d.ts.map +1 -1
- package/lib/getAppAndVersion.js +21 -1
- package/lib/getAppAndVersion.js.map +1 -1
- package/lib-es/Btc.d.ts +12 -11
- package/lib-es/Btc.d.ts.map +1 -1
- package/lib-es/Btc.js +47 -120
- package/lib-es/Btc.js.map +1 -1
- package/lib-es/BtcNew.d.ts +2 -4
- package/lib-es/BtcNew.d.ts.map +1 -1
- package/lib-es/BtcNew.js +54 -8
- package/lib-es/BtcNew.js.map +1 -1
- package/lib-es/BtcOld.d.ts +2 -37
- package/lib-es/BtcOld.d.ts.map +1 -1
- package/lib-es/BtcOld.js +3 -45
- package/lib-es/BtcOld.js.map +1 -1
- package/lib-es/getAppAndVersion.d.ts +1 -0
- package/lib-es/getAppAndVersion.d.ts.map +1 -1
- package/lib-es/getAppAndVersion.js +19 -0
- package/lib-es/getAppAndVersion.js.map +1 -1
- package/package.json +4 -4
- package/src/Btc.ts +54 -146
- package/src/BtcNew.ts +60 -15
- package/src/BtcOld.ts +4 -59
- package/src/getAppAndVersion.ts +12 -0
- package/tests/{Btc.test.ts → Btc.test.ts.disabled} +16 -132
- package/tests/newops/BtcNew.test.ts +0 -5
- package/tests/newops/integrationtools.ts +4 -4
- package/tests/parseTx.test.ts +1 -1
- package/tests/{trustedInputs.test.ts → trustedInputs.test.ts.disabled} +6 -8
package/src/Btc.ts
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
import type Transport from "@ledgerhq/hw-transport";
|
|
2
|
-
import
|
|
3
|
-
import BtcNew, { canSupportApp } from "./BtcNew";
|
|
2
|
+
import BtcNew from "./BtcNew";
|
|
4
3
|
import BtcOld from "./BtcOld";
|
|
5
4
|
import type { CreateTransactionArg } from "./createTransaction";
|
|
6
|
-
import { getAppAndVersion } from "./getAppAndVersion";
|
|
7
5
|
import { getTrustedInput } from "./getTrustedInput";
|
|
8
6
|
import { getTrustedInputBIP143 } from "./getTrustedInputBIP143";
|
|
9
7
|
import type { AddressFormat } from "./getWalletPublicKey";
|
|
@@ -13,32 +11,51 @@ import type { SignP2SHTransactionArg } from "./signP2SHTransaction";
|
|
|
13
11
|
import { splitTransaction } from "./splitTransaction";
|
|
14
12
|
import type { Transaction } from "./types";
|
|
15
13
|
export type { AddressFormat };
|
|
14
|
+
import { signP2SHTransaction } from "./signP2SHTransaction";
|
|
15
|
+
import { signMessage } from "./signMessage";
|
|
16
|
+
import { checkIsBtcLegacy, getAppAndVersion } from "./getAppAndVersion";
|
|
17
|
+
|
|
16
18
|
/**
|
|
17
19
|
* Bitcoin API.
|
|
18
20
|
*
|
|
19
21
|
* @example
|
|
20
22
|
* import Btc from "@ledgerhq/hw-app-btc";
|
|
21
|
-
* const btc = new Btc(transport)
|
|
23
|
+
* const btc = new Btc({ transport, currency: "bitcoin" });
|
|
22
24
|
*/
|
|
23
25
|
|
|
24
26
|
export default class Btc {
|
|
25
|
-
|
|
27
|
+
private _transport: Transport;
|
|
28
|
+
private _impl: BtcOld | BtcNew;
|
|
26
29
|
|
|
27
|
-
constructor(
|
|
28
|
-
|
|
29
|
-
|
|
30
|
+
constructor({
|
|
31
|
+
transport,
|
|
32
|
+
scrambleKey = "BTC",
|
|
33
|
+
currency = "bitcoin",
|
|
34
|
+
}: {
|
|
35
|
+
transport: Transport;
|
|
36
|
+
scrambleKey?: string;
|
|
37
|
+
currency?: string;
|
|
38
|
+
}) {
|
|
39
|
+
this._transport = transport;
|
|
40
|
+
this._transport.decorateAppAPIMethods(
|
|
30
41
|
this,
|
|
31
42
|
[
|
|
32
43
|
"getWalletXpub",
|
|
33
44
|
"getWalletPublicKey",
|
|
34
45
|
"signP2SHTransaction",
|
|
35
|
-
"
|
|
36
|
-
"
|
|
46
|
+
"signMessage",
|
|
47
|
+
"createPaymentTransaction",
|
|
37
48
|
"getTrustedInput",
|
|
38
49
|
"getTrustedInputBIP143",
|
|
39
50
|
],
|
|
40
51
|
scrambleKey
|
|
41
52
|
);
|
|
53
|
+
// new APDU (nano app API) for bitcoin and old APDU for altcoin
|
|
54
|
+
if (currency === "bitcoin" || currency === "bitcoin_testnet") {
|
|
55
|
+
this._impl = new BtcNew(new AppClient(this._transport));
|
|
56
|
+
} else {
|
|
57
|
+
this._impl = new BtcOld(this._transport);
|
|
58
|
+
}
|
|
42
59
|
}
|
|
43
60
|
|
|
44
61
|
/**
|
|
@@ -49,7 +66,9 @@ export default class Btc {
|
|
|
49
66
|
* @returns XPUB of the account
|
|
50
67
|
*/
|
|
51
68
|
getWalletXpub(arg: { path: string; xpubVersion: number }): Promise<string> {
|
|
52
|
-
return this.
|
|
69
|
+
return this.changeImplIfNecessary().then((impl) => {
|
|
70
|
+
return impl.getWalletXpub(arg);
|
|
71
|
+
});
|
|
53
72
|
}
|
|
54
73
|
|
|
55
74
|
/**
|
|
@@ -98,83 +117,21 @@ export default class Btc {
|
|
|
98
117
|
} else {
|
|
99
118
|
options = opts || {};
|
|
100
119
|
}
|
|
101
|
-
return this.
|
|
102
|
-
|
|
103
|
-
* Definition: A "normal path" is a prefix of a standard path where all
|
|
104
|
-
* the hardened steps of the standard path are included. For example, the
|
|
105
|
-
* paths m/44'/1'/17' and m/44'/1'/17'/1 are normal paths, but m/44'/1'
|
|
106
|
-
* is not. m/'199/1'/17'/0/1 is not a normal path either.
|
|
107
|
-
*
|
|
108
|
-
* There's a compatiblity issue between old and new app: When exporting
|
|
109
|
-
* the key of a non-normal path with verify=false, the new app would
|
|
110
|
-
* return an error, whereas the old app would return the key.
|
|
111
|
-
*
|
|
112
|
-
* See
|
|
113
|
-
* https://github.com/LedgerHQ/app-bitcoin-new/blob/master/doc/bitcoin.md#get_extended_pubkey
|
|
114
|
-
*
|
|
115
|
-
* If format bech32m is used, we'll not use old, because it doesn't
|
|
116
|
-
* support it.
|
|
117
|
-
*
|
|
118
|
-
* When to use new (given the app supports it)
|
|
119
|
-
* * format is bech32m or
|
|
120
|
-
* * path is normal or
|
|
121
|
-
* * verify is true
|
|
122
|
-
*
|
|
123
|
-
* Otherwise use old.
|
|
124
|
-
*/
|
|
125
|
-
if (
|
|
126
|
-
impl instanceof BtcNew &&
|
|
127
|
-
options.format != "bech32m" &&
|
|
128
|
-
(!options.verify || options.verify == false) &&
|
|
129
|
-
!isPathNormal(path)
|
|
130
|
-
) {
|
|
131
|
-
console.warn(`WARNING: Using deprecated device protocol to get the public key because
|
|
132
|
-
|
|
133
|
-
* a non-standard path is requested, and
|
|
134
|
-
* verify flag is false
|
|
135
|
-
|
|
136
|
-
The new protocol only allows export of non-standard paths if the
|
|
137
|
-
verify flag is true. Standard paths are (currently):
|
|
138
|
-
|
|
139
|
-
M/44'/(1|0)'/X'
|
|
140
|
-
M/49'/(1|0)'/X'
|
|
141
|
-
M/84'/(1|0)'/X'
|
|
142
|
-
M/86'/(1|0)'/X'
|
|
143
|
-
M/48'/(1|0)'/X'/Y'
|
|
144
|
-
|
|
145
|
-
followed by "", "(0|1)", or "(0|1)/b", where a and b are
|
|
146
|
-
non-hardened. For example, the following paths are standard
|
|
147
|
-
|
|
148
|
-
M/48'/1'/99'/7'
|
|
149
|
-
M/86'/1'/99'/0
|
|
150
|
-
M/48'/0'/99'/7'/1/17
|
|
151
|
-
|
|
152
|
-
The following paths are non-standard
|
|
153
|
-
|
|
154
|
-
M/48'/0'/99' // Not deepest hardened path
|
|
155
|
-
M/48'/0'/99'/7'/1/17/2 // Too many non-hardened derivation steps
|
|
156
|
-
M/199'/0'/1'/0/88 // Not a known purpose 199
|
|
157
|
-
M/86'/1'/99'/2 // Change path item must be 0 or 1
|
|
158
|
-
|
|
159
|
-
This compatibility safeguard will be removed in the future.
|
|
160
|
-
Please consider calling Btc.getWalletXpub() instead.`);
|
|
161
|
-
return this.old().getWalletPublicKey(path, options);
|
|
162
|
-
} else {
|
|
163
|
-
return impl.getWalletPublicKey(path, options);
|
|
164
|
-
}
|
|
120
|
+
return this.changeImplIfNecessary().then((impl) => {
|
|
121
|
+
return impl.getWalletPublicKey(path, options);
|
|
165
122
|
});
|
|
166
123
|
}
|
|
167
124
|
|
|
168
125
|
/**
|
|
169
126
|
* You can sign a message according to the Bitcoin Signature format and retrieve v, r, s given the message and the BIP 32 path of the account to sign.
|
|
170
127
|
* @example
|
|
171
|
-
btc.
|
|
128
|
+
btc.signMessage("44'/60'/0'/0'/0", Buffer.from("test").toString("hex")).then(function(result) {
|
|
172
129
|
var v = result['v'] + 27 + 4;
|
|
173
130
|
var signature = Buffer.from(v.toString(16) + result['r'] + result['s'], 'hex').toString('base64');
|
|
174
131
|
console.log("Signature : " + signature);
|
|
175
132
|
}).catch(function(ex) {console.log(ex);});
|
|
176
133
|
*/
|
|
177
|
-
|
|
134
|
+
signMessage(
|
|
178
135
|
path: string,
|
|
179
136
|
messageHex: string
|
|
180
137
|
): Promise<{
|
|
@@ -182,7 +139,10 @@ export default class Btc {
|
|
|
182
139
|
r: string;
|
|
183
140
|
s: string;
|
|
184
141
|
}> {
|
|
185
|
-
return this.
|
|
142
|
+
return signMessage(this._transport, {
|
|
143
|
+
path,
|
|
144
|
+
messageHex,
|
|
145
|
+
});
|
|
186
146
|
}
|
|
187
147
|
|
|
188
148
|
/**
|
|
@@ -218,14 +178,14 @@ export default class Btc {
|
|
|
218
178
|
outputScriptHex: "01905f0100000000001976a91472a5d75c8d2d0565b656a5232703b167d50d5a2b88ac"
|
|
219
179
|
}).then(res => ...);
|
|
220
180
|
*/
|
|
221
|
-
|
|
181
|
+
createPaymentTransaction(arg: CreateTransactionArg): Promise<string> {
|
|
222
182
|
if (arguments.length > 1) {
|
|
223
|
-
|
|
224
|
-
"@ledgerhq/hw-app-btc:
|
|
183
|
+
throw new Error(
|
|
184
|
+
"@ledgerhq/hw-app-btc: createPaymentTransaction multi argument signature is deprecated. please switch to named parameters."
|
|
225
185
|
);
|
|
226
186
|
}
|
|
227
|
-
return this.
|
|
228
|
-
return impl.
|
|
187
|
+
return this.changeImplIfNecessary().then((impl) => {
|
|
188
|
+
return impl.createPaymentTransaction(arg);
|
|
229
189
|
});
|
|
230
190
|
}
|
|
231
191
|
|
|
@@ -249,7 +209,7 @@ export default class Btc {
|
|
|
249
209
|
}).then(result => ...);
|
|
250
210
|
*/
|
|
251
211
|
signP2SHTransaction(arg: SignP2SHTransactionArg): Promise<string[]> {
|
|
252
|
-
return this.
|
|
212
|
+
return signP2SHTransaction(this._transport, arg);
|
|
253
213
|
}
|
|
254
214
|
|
|
255
215
|
/**
|
|
@@ -288,7 +248,7 @@ export default class Btc {
|
|
|
288
248
|
additionals: Array<string> = []
|
|
289
249
|
): Promise<string> {
|
|
290
250
|
return getTrustedInput(
|
|
291
|
-
this.
|
|
251
|
+
this._transport,
|
|
292
252
|
indexLookup,
|
|
293
253
|
transaction,
|
|
294
254
|
additionals
|
|
@@ -301,73 +261,21 @@ export default class Btc {
|
|
|
301
261
|
additionals: Array<string> = []
|
|
302
262
|
): string {
|
|
303
263
|
return getTrustedInputBIP143(
|
|
304
|
-
this.
|
|
264
|
+
this._transport,
|
|
305
265
|
indexLookup,
|
|
306
266
|
transaction,
|
|
307
267
|
additionals
|
|
308
268
|
);
|
|
309
269
|
}
|
|
310
270
|
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
return impl;
|
|
319
|
-
}
|
|
320
|
-
|
|
321
|
-
private async inferCorrectImpl(): Promise<BtcOld | BtcNew> {
|
|
322
|
-
const appAndVersion = await getAppAndVersion(this.transport);
|
|
323
|
-
const canUseNewImplementation = canSupportApp(appAndVersion);
|
|
324
|
-
if (!canUseNewImplementation) {
|
|
325
|
-
return this.old();
|
|
326
|
-
} else {
|
|
327
|
-
return this.new();
|
|
271
|
+
async changeImplIfNecessary(): Promise<BtcOld | BtcNew> {
|
|
272
|
+
const appAndVersion = await getAppAndVersion(this._transport);
|
|
273
|
+
if (appAndVersion.name === "Exchange" && this._impl instanceof BtcNew) {
|
|
274
|
+
const isBtcLegacy = await checkIsBtcLegacy(this._transport);
|
|
275
|
+
if (isBtcLegacy) {
|
|
276
|
+
this._impl = new BtcOld(this._transport);
|
|
277
|
+
}
|
|
328
278
|
}
|
|
279
|
+
return this._impl;
|
|
329
280
|
}
|
|
330
|
-
|
|
331
|
-
protected old(): BtcOld {
|
|
332
|
-
return new BtcOld(this.transport);
|
|
333
|
-
}
|
|
334
|
-
|
|
335
|
-
protected new(): BtcNew {
|
|
336
|
-
return new BtcNew(new AppClient(this.transport));
|
|
337
|
-
}
|
|
338
|
-
}
|
|
339
|
-
|
|
340
|
-
function isPathNormal(path: string): boolean {
|
|
341
|
-
//path is not deepest hardened node of a standard path or deeper, use BtcOld
|
|
342
|
-
const h = 0x80000000;
|
|
343
|
-
const pathElems = pathStringToArray(path);
|
|
344
|
-
|
|
345
|
-
const hard = (n: number) => n >= h;
|
|
346
|
-
const soft = (n: number | undefined) => !n || n < h;
|
|
347
|
-
const change = (n: number | undefined) => !n || n == 0 || n == 1;
|
|
348
|
-
|
|
349
|
-
if (
|
|
350
|
-
pathElems.length >= 3 &&
|
|
351
|
-
pathElems.length <= 5 &&
|
|
352
|
-
[44 + h, 49 + h, 84 + h, 86 + h].some((v) => v == pathElems[0]) &&
|
|
353
|
-
[0 + h, 1 + h].some((v) => v == pathElems[1]) &&
|
|
354
|
-
hard(pathElems[2]) &&
|
|
355
|
-
change(pathElems[3]) &&
|
|
356
|
-
soft(pathElems[4])
|
|
357
|
-
) {
|
|
358
|
-
return true;
|
|
359
|
-
}
|
|
360
|
-
if (
|
|
361
|
-
pathElems.length >= 4 &&
|
|
362
|
-
pathElems.length <= 6 &&
|
|
363
|
-
48 + h == pathElems[0] &&
|
|
364
|
-
[0 + h, 1 + h].some((v) => v == pathElems[1]) &&
|
|
365
|
-
hard(pathElems[2]) &&
|
|
366
|
-
hard(pathElems[3]) &&
|
|
367
|
-
change(pathElems[4]) &&
|
|
368
|
-
soft(pathElems[5])
|
|
369
|
-
) {
|
|
370
|
-
return true;
|
|
371
|
-
}
|
|
372
|
-
return false;
|
|
373
281
|
}
|
package/src/BtcNew.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { crypto } from "bitcoinjs-lib";
|
|
2
|
-
import semver from "semver";
|
|
3
2
|
import { pointCompress } from "tiny-secp256k1";
|
|
4
3
|
import {
|
|
5
4
|
getXpubComponents,
|
|
@@ -10,7 +9,6 @@ import {
|
|
|
10
9
|
} from "./bip32";
|
|
11
10
|
import { BufferReader } from "./buffertools";
|
|
12
11
|
import type { CreateTransactionArg } from "./createTransaction";
|
|
13
|
-
import { AppAndVersion } from "./getAppAndVersion";
|
|
14
12
|
import type { AddressFormat } from "./getWalletPublicKey";
|
|
15
13
|
import {
|
|
16
14
|
AccountType,
|
|
@@ -32,15 +30,6 @@ import { psbtIn, PsbtV2 } from "./newops/psbtv2";
|
|
|
32
30
|
import { serializeTransaction } from "./serializeTransaction";
|
|
33
31
|
import type { Transaction } from "./types";
|
|
34
32
|
|
|
35
|
-
const newSupportedApps = ["Bitcoin", "Bitcoin Test"];
|
|
36
|
-
|
|
37
|
-
export function canSupportApp(appAndVersion: AppAndVersion): boolean {
|
|
38
|
-
return (
|
|
39
|
-
newSupportedApps.includes(appAndVersion.name) &&
|
|
40
|
-
semver.major(appAndVersion.version) >= 2
|
|
41
|
-
);
|
|
42
|
-
}
|
|
43
|
-
|
|
44
33
|
/**
|
|
45
34
|
* This class implements the same interface as BtcOld (formerly
|
|
46
35
|
* named Btc), but interacts with Bitcoin hardware app version 2+
|
|
@@ -123,6 +112,9 @@ export default class BtcNew {
|
|
|
123
112
|
bitcoinAddress: string;
|
|
124
113
|
chainCode: string;
|
|
125
114
|
}> {
|
|
115
|
+
if (!isPathNormal(path)) {
|
|
116
|
+
throw Error(`non-standard path: ${path}`);
|
|
117
|
+
}
|
|
126
118
|
const pathElements: number[] = pathStringToArray(path);
|
|
127
119
|
const xpub = await this.client.getExtendedPubkey(false, pathElements);
|
|
128
120
|
|
|
@@ -185,16 +177,14 @@ export default class BtcNew {
|
|
|
185
177
|
}
|
|
186
178
|
|
|
187
179
|
/**
|
|
188
|
-
* Build and sign a transaction. See Btc.
|
|
180
|
+
* Build and sign a transaction. See Btc.createPaymentTransaction for
|
|
189
181
|
* details on how to use this method.
|
|
190
182
|
*
|
|
191
183
|
* This method will convert the legacy arguments, CreateTransactionArg, into
|
|
192
184
|
* a psbt which is finally signed and finalized, and the extracted fully signed
|
|
193
185
|
* transaction is returned.
|
|
194
186
|
*/
|
|
195
|
-
async
|
|
196
|
-
arg: CreateTransactionArg
|
|
197
|
-
): Promise<string> {
|
|
187
|
+
async createPaymentTransaction(arg: CreateTransactionArg): Promise<string> {
|
|
198
188
|
const inputCount = arg.inputs.length;
|
|
199
189
|
if (inputCount == 0) {
|
|
200
190
|
throw Error("No inputs");
|
|
@@ -453,3 +443,58 @@ function accountTypeFromArg(
|
|
|
453
443
|
if (arg.segwit) return new p2wpkhWrapped(psbt, masterFp);
|
|
454
444
|
return new p2pkh(psbt, masterFp);
|
|
455
445
|
}
|
|
446
|
+
|
|
447
|
+
/*
|
|
448
|
+
The new protocol only allows standard path.
|
|
449
|
+
Standard paths are (currently):
|
|
450
|
+
M/44'/(1|0)'/X'
|
|
451
|
+
M/49'/(1|0)'/X'
|
|
452
|
+
M/84'/(1|0)'/X'
|
|
453
|
+
M/86'/(1|0)'/X'
|
|
454
|
+
M/48'/(1|0)'/X'/Y'
|
|
455
|
+
followed by "", "(0|1)", or "(0|1)/b", where a and b are
|
|
456
|
+
non-hardened. For example, the following paths are standard
|
|
457
|
+
M/48'/1'/99'/7'
|
|
458
|
+
M/86'/1'/99'/0
|
|
459
|
+
M/48'/0'/99'/7'/1/17
|
|
460
|
+
The following paths are non-standard
|
|
461
|
+
M/48'/0'/99' // Not deepest hardened path
|
|
462
|
+
M/48'/0'/99'/7'/1/17/2 // Too many non-hardened derivation steps
|
|
463
|
+
M/199'/0'/1'/0/88 // Not a known purpose 199
|
|
464
|
+
M/86'/1'/99'/2 // Change path item must be 0 or 1
|
|
465
|
+
*/
|
|
466
|
+
function isPathNormal(path: string): boolean {
|
|
467
|
+
//path is not deepest hardened node of a standard path or deeper, use BtcOld
|
|
468
|
+
const h = 0x80000000; //HARDENED from bip32
|
|
469
|
+
const pathElems = pathStringToArray(path);
|
|
470
|
+
|
|
471
|
+
const hard = (n: number) => n >= h;
|
|
472
|
+
const soft = (n: number | undefined) => n === undefined || n < h;
|
|
473
|
+
const change = (n: number | undefined) =>
|
|
474
|
+
n === undefined || n === 0 || n === 1;
|
|
475
|
+
|
|
476
|
+
if (
|
|
477
|
+
pathElems.length >= 3 &&
|
|
478
|
+
pathElems.length <= 5 &&
|
|
479
|
+
[44 + h, 49 + h, 84 + h, 86 + h].some((v) => v == pathElems[0]) &&
|
|
480
|
+
[0 + h, 1 + h].some((v) => v == pathElems[1]) &&
|
|
481
|
+
hard(pathElems[2]) &&
|
|
482
|
+
change(pathElems[3]) &&
|
|
483
|
+
soft(pathElems[4])
|
|
484
|
+
) {
|
|
485
|
+
return true;
|
|
486
|
+
}
|
|
487
|
+
if (
|
|
488
|
+
pathElems.length >= 4 &&
|
|
489
|
+
pathElems.length <= 6 &&
|
|
490
|
+
48 + h == pathElems[0] &&
|
|
491
|
+
[0 + h, 1 + h].some((v) => v == pathElems[1]) &&
|
|
492
|
+
hard(pathElems[2]) &&
|
|
493
|
+
hard(pathElems[3]) &&
|
|
494
|
+
change(pathElems[4]) &&
|
|
495
|
+
soft(pathElems[5])
|
|
496
|
+
) {
|
|
497
|
+
return true;
|
|
498
|
+
}
|
|
499
|
+
return false;
|
|
500
|
+
}
|
package/src/BtcOld.ts
CHANGED
|
@@ -6,9 +6,6 @@ import type { CreateTransactionArg } from "./createTransaction";
|
|
|
6
6
|
import { createTransaction } from "./createTransaction";
|
|
7
7
|
import type { AddressFormat } from "./getWalletPublicKey";
|
|
8
8
|
import { getWalletPublicKey } from "./getWalletPublicKey";
|
|
9
|
-
import { signMessage } from "./signMessage";
|
|
10
|
-
import type { SignP2SHTransactionArg } from "./signP2SHTransaction";
|
|
11
|
-
import { signP2SHTransaction } from "./signP2SHTransaction";
|
|
12
9
|
import { pathArrayToString, pathStringToArray } from "./bip32";
|
|
13
10
|
export type { AddressFormat };
|
|
14
11
|
|
|
@@ -17,7 +14,7 @@ export type { AddressFormat };
|
|
|
17
14
|
*
|
|
18
15
|
* @example
|
|
19
16
|
* import Btc from "@ledgerhq/hw-app-btc";
|
|
20
|
-
* const btc = new Btc(transport)
|
|
17
|
+
* const btc = new Btc({ transport, currency: "zcash" });
|
|
21
18
|
*/
|
|
22
19
|
|
|
23
20
|
export default class BtcOld {
|
|
@@ -99,29 +96,6 @@ export default class BtcOld {
|
|
|
99
96
|
return getWalletPublicKey(this.transport, { ...opts, path });
|
|
100
97
|
}
|
|
101
98
|
|
|
102
|
-
/**
|
|
103
|
-
* You can sign a message according to the Bitcoin Signature format and retrieve v, r, s given the message and the BIP 32 path of the account to sign.
|
|
104
|
-
* @example
|
|
105
|
-
btc.signMessageNew_async("44'/60'/0'/0'/0", Buffer.from("test").toString("hex")).then(function(result) {
|
|
106
|
-
var v = result['v'] + 27 + 4;
|
|
107
|
-
var signature = Buffer.from(v.toString(16) + result['r'] + result['s'], 'hex').toString('base64');
|
|
108
|
-
console.log("Signature : " + signature);
|
|
109
|
-
}).catch(function(ex) {console.log(ex);});
|
|
110
|
-
*/
|
|
111
|
-
signMessageNew(
|
|
112
|
-
path: string,
|
|
113
|
-
messageHex: string
|
|
114
|
-
): Promise<{
|
|
115
|
-
v: number;
|
|
116
|
-
r: string;
|
|
117
|
-
s: string;
|
|
118
|
-
}> {
|
|
119
|
-
return signMessage(this.transport, {
|
|
120
|
-
path,
|
|
121
|
-
messageHex,
|
|
122
|
-
});
|
|
123
|
-
}
|
|
124
|
-
|
|
125
99
|
/**
|
|
126
100
|
* To sign a transaction involving standard (P2PKH) inputs, call createTransaction with the following parameters
|
|
127
101
|
* @param inputs is an array of [ transaction, output_index, optional redeem script, optional sequence ] where
|
|
@@ -154,43 +128,14 @@ export default class BtcOld {
|
|
|
154
128
|
outputScriptHex: "01905f0100000000001976a91472a5d75c8d2d0565b656a5232703b167d50d5a2b88ac"
|
|
155
129
|
}).then(res => ...);
|
|
156
130
|
*/
|
|
157
|
-
|
|
131
|
+
createPaymentTransaction(arg: CreateTransactionArg): Promise<string> {
|
|
158
132
|
if (arguments.length > 1) {
|
|
159
|
-
|
|
160
|
-
"@ledgerhq/hw-app-btc:
|
|
133
|
+
throw new Error(
|
|
134
|
+
"@ledgerhq/hw-app-btc: createPaymentTransaction multi argument signature is deprecated. please switch to named parameters."
|
|
161
135
|
);
|
|
162
136
|
}
|
|
163
137
|
return createTransaction(this.transport, arg);
|
|
164
138
|
}
|
|
165
|
-
|
|
166
|
-
/**
|
|
167
|
-
* To obtain the signature of multisignature (P2SH) inputs, call signP2SHTransaction_async with the folowing parameters
|
|
168
|
-
* @param inputs is an array of [ transaction, output_index, redeem script, optional sequence ] where
|
|
169
|
-
* * transaction is the previously computed transaction object for this UTXO
|
|
170
|
-
* * output_index is the output in the transaction used as input for this UTXO (counting from 0)
|
|
171
|
-
* * redeem script is the mandatory redeem script associated to the current P2SH input
|
|
172
|
-
* * sequence is the sequence number to use for this input (when using RBF), or non present
|
|
173
|
-
* @param associatedKeysets is an array of BIP 32 paths pointing to the path to the private key used for each UTXO
|
|
174
|
-
* @param outputScriptHex is the hexadecimal serialized outputs of the transaction to sign
|
|
175
|
-
* @param lockTime is the optional lockTime of the transaction to sign, or default (0)
|
|
176
|
-
* @param sigHashType is the hash type of the transaction to sign, or default (all)
|
|
177
|
-
* @return the signed transaction ready to be broadcast
|
|
178
|
-
* @example
|
|
179
|
-
btc.signP2SHTransaction({
|
|
180
|
-
inputs: [ [tx, 1, "52210289b4a3ad52a919abd2bdd6920d8a6879b1e788c38aa76f0440a6f32a9f1996d02103a3393b1439d1693b063482c04bd40142db97bdf139eedd1b51ffb7070a37eac321030b9a409a1e476b0d5d17b804fcdb81cf30f9b99c6f3ae1178206e08bc500639853ae"] ],
|
|
181
|
-
associatedKeysets: ["0'/0/0"],
|
|
182
|
-
outputScriptHex: "01905f0100000000001976a91472a5d75c8d2d0565b656a5232703b167d50d5a2b88ac"
|
|
183
|
-
}).then(result => ...);
|
|
184
|
-
*/
|
|
185
|
-
signP2SHTransaction(arg: SignP2SHTransactionArg): Promise<string[]> {
|
|
186
|
-
if (arguments.length > 1) {
|
|
187
|
-
console.warn(
|
|
188
|
-
"@ledgerhq/hw-app-btc: signP2SHTransaction multi argument signature is deprecated. please switch to named parameters."
|
|
189
|
-
);
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
return signP2SHTransaction(this.transport, arg);
|
|
193
|
-
}
|
|
194
139
|
}
|
|
195
140
|
|
|
196
141
|
function makeFingerprint(compressedPubKey) {
|
package/src/getAppAndVersion.ts
CHANGED
|
@@ -26,3 +26,15 @@ export const getAppAndVersion = async (
|
|
|
26
26
|
flags,
|
|
27
27
|
};
|
|
28
28
|
};
|
|
29
|
+
|
|
30
|
+
export const checkIsBtcLegacy = async (
|
|
31
|
+
transport: Transport
|
|
32
|
+
): Promise<boolean> => {
|
|
33
|
+
try {
|
|
34
|
+
// Call old btc API, it will throw an exception with new btc app. It is a workaround to differentiate new/old btc nano app
|
|
35
|
+
await transport.send(0xe0, 0xc4, 0, 0);
|
|
36
|
+
} catch (e: unknown) {
|
|
37
|
+
return false;
|
|
38
|
+
}
|
|
39
|
+
return true;
|
|
40
|
+
};
|