@taquito/ledger-signer 17.3.2 → 17.4.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.
@@ -18,6 +18,8 @@
18
18
  OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19
19
  PERFORMANCE OF THIS SOFTWARE.
20
20
  ***************************************************************************** */
21
+ /* global Reflect, Promise, SuppressedError, Symbol */
22
+
21
23
 
22
24
  function __awaiter(thisArg, _arguments, P, generator) {
23
25
  function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
@@ -34,360 +36,360 @@
34
36
  return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
35
37
  };
36
38
 
37
- /*
38
- * Some code in this file is adapted from sotez
39
- * Copyright (c) 2018 Andrew Kishino
40
- */
41
- const MAX_CHUNK_SIZE = 230;
42
- /**
43
- *
44
- * @description Convert the path to a buffer that will be used as LC and CDATA in the APDU send to the ledger device (https://github.com/obsidiansystems/ledger-app-tezos/blob/master/APDUs.md)
45
- *
46
- * @param path The ledger derivation path (default is "44'/1729'/0'/0'")
47
- * @returns A buffer where the first element is the length of the path (default is 4), then 3 bytes for each number of the path to which is added 0x8000000
48
- */
49
- function transformPathToBuffer(path) {
50
- const result = [];
51
- const components = path.split('/');
52
- components.forEach((element) => {
53
- let toNumber = parseInt(element, 10);
54
- if (Number.isNaN(toNumber)) {
55
- return;
56
- }
57
- if (element.length > 1 && element[element.length - 1] === "'") {
58
- toNumber += 0x80000000;
59
- }
60
- result.push(toNumber);
61
- });
62
- const buffer = Buffer.alloc(1 + result.length * 4);
63
- buffer[0] = result.length;
64
- result.forEach((element, index) => {
65
- buffer.writeUInt32BE(element, 1 + 4 * index);
66
- });
67
- return buffer;
68
- }
69
- /**
70
- *
71
- * @description Converts uncompressed ledger key to standard tezos binary representation
72
- */
73
- function compressPublicKey(publicKey, curve) {
74
- if (curve === 0x00 || curve === 0x03) {
75
- publicKey = publicKey.slice(1);
76
- }
77
- else {
78
- publicKey[0] = 0x02 + (publicKey[64] & 0x01);
79
- publicKey = publicKey.slice(0, 33);
80
- }
81
- return publicKey;
82
- }
83
- function appendWatermark(bytes, watermark) {
84
- let transactionHex = bytes;
85
- if (typeof watermark !== 'undefined') {
86
- const hexWatermark = Buffer.from(watermark).toString('hex');
87
- transactionHex = hexWatermark.concat(bytes);
88
- }
89
- return transactionHex;
90
- }
91
- /**
92
- *
93
- * @description In order not to exceed the data length allowed by the Ledger device, split the operation into buffers of 230 bytes (max) and add them to the message to send to the Ledger
94
- * @param messageToSend The message to send to the Ledger device
95
- * @param operation The operation which will be chunk if its length is over 230 bytes
96
- * @returns The instruction to send to the Ledger device
97
- */
98
- function chunkOperation(messageToSend, operation) {
99
- let offset = 0;
100
- while (offset !== operation.length) {
101
- const chunkSize = offset + MAX_CHUNK_SIZE >= operation.length ? operation.length - offset : MAX_CHUNK_SIZE;
102
- const buff = Buffer.alloc(chunkSize);
103
- operation.copy(buff, 0, offset, offset + chunkSize);
104
- messageToSend.push(buff);
105
- offset += chunkSize;
106
- }
107
- return messageToSend;
108
- }
109
- /**
110
- *
111
- * @description Verify if the signature returned by the ledger for tz2 and tz3 is valid
112
- * @param response The signature returned by the Ledger (return from the signWithLedger function)
113
- * @returns True if valid, false otherwise
114
- */
115
- function validateResponse(response) {
116
- let valid = true;
117
- if (response[0] !== 0x31 && response[0] !== 0x30) {
118
- valid = false;
119
- }
120
- if (response[1] + 4 !== response.length) {
121
- valid = false;
122
- }
123
- if (response[2] !== 0x02) {
124
- valid = false;
125
- }
126
- const rLength = response[3];
127
- if (response[4 + rLength] !== 0x02) {
128
- valid = false;
129
- }
130
- const idxLengthSVal = 5 + rLength;
131
- const sLength = response[idxLengthSVal];
132
- if (idxLengthSVal + 1 + sLength + 2 !== response.length) {
133
- valid = false;
134
- }
135
- return valid;
136
- }
137
- /**
138
- *
139
- * @description Extract a part of the response returned by the Ledger
140
- * @param idxLength The index in the response from the Ledger that corresponds to the length of the part to extract
141
- * @param response The signature returned by the Ledger (return from the signWithLedger function)
142
- * @returns An object that contains the extracted buffer, the index where it starts in the response and the length of the extracted part
143
- */
144
- function extractValue(idxLength, response) {
145
- const buffer = Buffer.alloc(32);
146
- buffer.fill(0);
147
- let length = response[idxLength];
148
- let idxValueStart = idxLength + 1;
149
- if (length > 32) {
150
- idxValueStart += length - 32;
151
- length = 32;
152
- }
153
- response.copy(buffer, 32 - length, idxValueStart, idxValueStart + length);
154
- return { buffer, idxValueStart, length };
39
+ /*
40
+ * Some code in this file is adapted from sotez
41
+ * Copyright (c) 2018 Andrew Kishino
42
+ */
43
+ const MAX_CHUNK_SIZE = 230;
44
+ /**
45
+ *
46
+ * @description Convert the path to a buffer that will be used as LC and CDATA in the APDU send to the ledger device (https://github.com/obsidiansystems/ledger-app-tezos/blob/master/APDUs.md)
47
+ *
48
+ * @param path The ledger derivation path (default is "44'/1729'/0'/0'")
49
+ * @returns A buffer where the first element is the length of the path (default is 4), then 3 bytes for each number of the path to which is added 0x8000000
50
+ */
51
+ function transformPathToBuffer(path) {
52
+ const result = [];
53
+ const components = path.split('/');
54
+ components.forEach((element) => {
55
+ let toNumber = parseInt(element, 10);
56
+ if (Number.isNaN(toNumber)) {
57
+ return;
58
+ }
59
+ if (element.length > 1 && element[element.length - 1] === "'") {
60
+ toNumber += 0x80000000;
61
+ }
62
+ result.push(toNumber);
63
+ });
64
+ const buffer = Buffer.alloc(1 + result.length * 4);
65
+ buffer[0] = result.length;
66
+ result.forEach((element, index) => {
67
+ buffer.writeUInt32BE(element, 1 + 4 * index);
68
+ });
69
+ return buffer;
70
+ }
71
+ /**
72
+ *
73
+ * @description Converts uncompressed ledger key to standard tezos binary representation
74
+ */
75
+ function compressPublicKey(publicKey, curve) {
76
+ if (curve === 0x00 || curve === 0x03) {
77
+ publicKey = publicKey.slice(1);
78
+ }
79
+ else {
80
+ publicKey[0] = 0x02 + (publicKey[64] & 0x01);
81
+ publicKey = publicKey.slice(0, 33);
82
+ }
83
+ return publicKey;
84
+ }
85
+ function appendWatermark(bytes, watermark) {
86
+ let transactionHex = bytes;
87
+ if (typeof watermark !== 'undefined') {
88
+ const hexWatermark = Buffer.from(watermark).toString('hex');
89
+ transactionHex = hexWatermark.concat(bytes);
90
+ }
91
+ return transactionHex;
92
+ }
93
+ /**
94
+ *
95
+ * @description In order not to exceed the data length allowed by the Ledger device, split the operation into buffers of 230 bytes (max) and add them to the message to send to the Ledger
96
+ * @param messageToSend The message to send to the Ledger device
97
+ * @param operation The operation which will be chunk if its length is over 230 bytes
98
+ * @returns The instruction to send to the Ledger device
99
+ */
100
+ function chunkOperation(messageToSend, operation) {
101
+ let offset = 0;
102
+ while (offset !== operation.length) {
103
+ const chunkSize = offset + MAX_CHUNK_SIZE >= operation.length ? operation.length - offset : MAX_CHUNK_SIZE;
104
+ const buff = Buffer.alloc(chunkSize);
105
+ operation.copy(buff, 0, offset, offset + chunkSize);
106
+ messageToSend.push(buff);
107
+ offset += chunkSize;
108
+ }
109
+ return messageToSend;
110
+ }
111
+ /**
112
+ *
113
+ * @description Verify if the signature returned by the ledger for tz2 and tz3 is valid
114
+ * @param response The signature returned by the Ledger (return from the signWithLedger function)
115
+ * @returns True if valid, false otherwise
116
+ */
117
+ function validateResponse(response) {
118
+ let valid = true;
119
+ if (response[0] !== 0x31 && response[0] !== 0x30) {
120
+ valid = false;
121
+ }
122
+ if (response[1] + 4 !== response.length) {
123
+ valid = false;
124
+ }
125
+ if (response[2] !== 0x02) {
126
+ valid = false;
127
+ }
128
+ const rLength = response[3];
129
+ if (response[4 + rLength] !== 0x02) {
130
+ valid = false;
131
+ }
132
+ const idxLengthSVal = 5 + rLength;
133
+ const sLength = response[idxLengthSVal];
134
+ if (idxLengthSVal + 1 + sLength + 2 !== response.length) {
135
+ valid = false;
136
+ }
137
+ return valid;
138
+ }
139
+ /**
140
+ *
141
+ * @description Extract a part of the response returned by the Ledger
142
+ * @param idxLength The index in the response from the Ledger that corresponds to the length of the part to extract
143
+ * @param response The signature returned by the Ledger (return from the signWithLedger function)
144
+ * @returns An object that contains the extracted buffer, the index where it starts in the response and the length of the extracted part
145
+ */
146
+ function extractValue(idxLength, response) {
147
+ const buffer = Buffer.alloc(32);
148
+ buffer.fill(0);
149
+ let length = response[idxLength];
150
+ let idxValueStart = idxLength + 1;
151
+ if (length > 32) {
152
+ idxValueStart += length - 32;
153
+ length = 32;
154
+ }
155
+ response.copy(buffer, 32 - length, idxValueStart, idxValueStart + length);
156
+ return { buffer, idxValueStart, length };
155
157
  }
156
158
 
157
- /**
158
- * @category Error
159
- * @description Error that indicates an invalid or unparseable ledger response
160
- */
161
- class InvalidLedgerResponseError extends core.TaquitoError {
162
- constructor(message) {
163
- super();
164
- this.message = message;
165
- this.name = 'InvalidLedgerResponseError';
166
- }
167
- }
168
- /**
169
- * @category Error
170
- * @description Error that indicates a failure when trying to retrieve a Public Key from Ledger signer
171
- */
172
- class PublicKeyRetrievalError extends core.TaquitoError {
173
- constructor(cause) {
174
- super();
175
- this.cause = cause;
176
- this.name = 'PublicKeyRetrievalError';
177
- this.message = `Unable to retrieve Public Key from Ledger`;
178
- }
179
- }
180
- /**
181
- * @category Error
182
- * @description Error that indicates a failure when trying to retrieve a Public Key Hash from Ledger signer
183
- */
184
- class PublicKeyHashRetrievalError extends core.TaquitoError {
185
- constructor() {
186
- super();
187
- this.name = 'PublicKeyHashRetrievalError';
188
- this.message = 'Unable to retrieve Public Key Hash from Ledger';
189
- }
190
- }
191
- /**
192
- * @category Error
193
- * @description Error that indicates an invalid derivation type being passed or used
194
- */
195
- class InvalidDerivationTypeError extends core.ParameterValidationError {
196
- constructor(derivationType) {
197
- super();
198
- this.derivationType = derivationType;
199
- this.name = 'InvalidDerivationTypeError';
200
- this.message = `Invalid derivation type ${derivationType} expecting one of the following: DerivationType.ED25519, DerivationType.SECP256K1, DerivationType.P256 or DerivationType.BIP32_ED25519`;
201
- }
159
+ /**
160
+ * @category Error
161
+ * @description Error that indicates an invalid or unparseable ledger response
162
+ */
163
+ class InvalidLedgerResponseError extends core.TaquitoError {
164
+ constructor(message) {
165
+ super();
166
+ this.message = message;
167
+ this.name = 'InvalidLedgerResponseError';
168
+ }
169
+ }
170
+ /**
171
+ * @category Error
172
+ * @description Error that indicates a failure when trying to retrieve a Public Key from Ledger signer
173
+ */
174
+ class PublicKeyRetrievalError extends core.TaquitoError {
175
+ constructor(cause) {
176
+ super();
177
+ this.cause = cause;
178
+ this.name = 'PublicKeyRetrievalError';
179
+ this.message = `Unable to retrieve Public Key from Ledger`;
180
+ }
181
+ }
182
+ /**
183
+ * @category Error
184
+ * @description Error that indicates a failure when trying to retrieve a Public Key Hash from Ledger signer
185
+ */
186
+ class PublicKeyHashRetrievalError extends core.TaquitoError {
187
+ constructor() {
188
+ super();
189
+ this.name = 'PublicKeyHashRetrievalError';
190
+ this.message = 'Unable to retrieve Public Key Hash from Ledger';
191
+ }
192
+ }
193
+ /**
194
+ * @category Error
195
+ * @description Error that indicates an invalid derivation type being passed or used
196
+ */
197
+ class InvalidDerivationTypeError extends core.ParameterValidationError {
198
+ constructor(derivationType) {
199
+ super();
200
+ this.derivationType = derivationType;
201
+ this.name = 'InvalidDerivationTypeError';
202
+ this.message = `Invalid derivation type ${derivationType} expecting one of the following: DerivationType.ED25519, DerivationType.SECP256K1, DerivationType.P256 or DerivationType.BIP32_ED25519`;
203
+ }
202
204
  }
203
205
 
204
- // IMPORTANT: THIS FILE IS AUTO GENERATED! DO NOT MANUALLY EDIT OR CHECKIN!
205
- const VERSION = {
206
- "commitHash": "a97e506efd61b86e39ae30db588401b8fda46553",
207
- "version": "17.3.2"
206
+ // IMPORTANT: THIS FILE IS AUTO GENERATED! DO NOT MANUALLY EDIT OR CHECKIN!
207
+ const VERSION = {
208
+ "commitHash": "a908ab176a8c52c025fd43e7acd452415396f54e",
209
+ "version": "17.4.0"
208
210
  };
209
211
 
210
- /**
211
- * @packageDocumentation
212
- * @module @taquito/ledger-signer
213
- */
214
- exports.DerivationType = void 0;
215
- (function (DerivationType) {
216
- DerivationType[DerivationType["ED25519"] = 0] = "ED25519";
217
- DerivationType[DerivationType["SECP256K1"] = 1] = "SECP256K1";
218
- DerivationType[DerivationType["P256"] = 2] = "P256";
219
- DerivationType[DerivationType["BIP32_ED25519"] = 3] = "BIP32_ED25519";
220
- })(exports.DerivationType || (exports.DerivationType = {}));
221
- const HDPathTemplate = (account) => {
222
- return `44'/1729'/${account}'/0'`;
223
- };
224
- /**
225
- *
226
- * @description Implementation of the Signer interface that will allow signing operation from a Ledger Nano device
227
- *
228
- * @param transport A transport instance from LedgerJS libraries depending on the platform used (e.g. Web, Node)
229
- * @param path The ledger derivation path (default is "44'/1729'/0'/0'")
230
- * @param prompt Whether to prompt the ledger for public key (default is true)
231
- * @param derivationType The value which defines the curve to use (DerivationType.ED25519(default), DerivationType.SECP256K1, DerivationType.P256, DerivationType.BIP32_ED25519)
232
- *
233
- * @example
234
- * ```
235
- * import TransportNodeHid from "@ledgerhq/hw-transport-node-hid";
236
- * const transport = await TransportNodeHid.create();
237
- * const ledgerSigner = new LedgerSigner(transport, "44'/1729'/0'/0'", false, DerivationType.ED25519);
238
- * ```
239
- *
240
- * @example
241
- * ```
242
- * import TransportU2F from "@ledgerhq/hw-transport-u2f";
243
- * const transport = await TransportU2F.create();
244
- * const ledgerSigner = new LedgerSigner(transport, "44'/1729'/0'/0'", true, DerivationType.SECP256K1);
245
- * ```
246
- *
247
- * @example
248
- * ```
249
- * import TransportU2F from "@ledgerhq/hw-transport-u2f";
250
- * const transport = await TransportU2F.create();
251
- * const ledgerSigner = new LedgerSigner(transport, "44'/1729'/6'/0'", true, DerivationType.BIP32_ED25519);
252
- * ```
253
- */
254
- class LedgerSigner {
255
- constructor(transport, path = "44'/1729'/0'/0'", prompt = true, derivationType = exports.DerivationType.ED25519) {
256
- this.transport = transport;
257
- this.path = path;
258
- this.prompt = prompt;
259
- this.derivationType = derivationType;
260
- // constants for APDU requests (https://github.com/obsidiansystems/ledger-app-tezos/blob/master/APDUs.md)
261
- this.CLA = 0x80; // Instruction class (always 0x80)
262
- this.INS_GET_PUBLIC_KEY = 0x02; // Instruction code to get the ledger’s internal public key without prompt
263
- this.INS_PROMPT_PUBLIC_KEY = 0x03; // Instruction code to get the ledger’s internal public key with prompt
264
- this.INS_SIGN = 0x04; // Sign a message with the ledger’s key
265
- this.FIRST_MESSAGE_SEQUENCE = 0x00;
266
- this.LAST_MESSAGE_SEQUENCE = 0x81;
267
- this.OTHER_MESSAGE_SEQUENCE = 0x01;
268
- this.transport.setScrambleKey('XTZ');
269
- if (!path.startsWith(`44'/1729'`)) {
270
- throw new core.InvalidDerivationPathError(path, `${utils.invalidDetail(utils.ValidationResult.NO_PREFIX_MATCHED)} expecting prefix "44'/1729'".`);
271
- }
272
- if (!Object.values(exports.DerivationType).includes(derivationType)) {
273
- throw new InvalidDerivationTypeError(derivationType.toString());
274
- }
275
- }
276
- publicKeyHash() {
277
- return __awaiter(this, void 0, void 0, function* () {
278
- if (!this._publicKeyHash) {
279
- yield this.publicKey();
280
- }
281
- if (this._publicKeyHash) {
282
- return this._publicKeyHash;
283
- }
284
- throw new PublicKeyHashRetrievalError();
285
- });
286
- }
287
- publicKey() {
288
- return __awaiter(this, void 0, void 0, function* () {
289
- if (this._publicKey) {
290
- return this._publicKey;
291
- }
292
- const responseLedger = yield this.getLedgerPublicKey();
293
- const publicKeyLength = responseLedger[0];
294
- const rawPublicKey = responseLedger.slice(1, 1 + publicKeyLength);
295
- const compressedPublicKey = compressPublicKey(rawPublicKey, this.derivationType);
296
- const prefixes = this.getPrefixes();
297
- const publicKey = utils.b58cencode(compressedPublicKey, prefixes.prefPk);
298
- const publicKeyHash = utils.b58cencode(blake2b.hash(compressedPublicKey, 20), prefixes.prefPkh);
299
- this._publicKey = publicKey;
300
- this._publicKeyHash = publicKeyHash;
301
- return publicKey;
302
- });
303
- }
304
- getLedgerPublicKey() {
305
- return __awaiter(this, void 0, void 0, function* () {
306
- try {
307
- let ins = this.INS_PROMPT_PUBLIC_KEY;
308
- if (this.prompt === false) {
309
- ins = this.INS_GET_PUBLIC_KEY;
310
- }
311
- const responseLedger = yield this.transport.send(this.CLA, ins, this.FIRST_MESSAGE_SEQUENCE, this.derivationType, transformPathToBuffer(this.path));
312
- return responseLedger;
313
- }
314
- catch (error) {
315
- throw new PublicKeyRetrievalError(error);
316
- }
317
- });
318
- }
319
- secretKey() {
320
- return __awaiter(this, void 0, void 0, function* () {
321
- throw new core.ProhibitedActionError('Secret key cannot be exposed');
322
- });
323
- }
324
- sign(bytes, watermark) {
325
- return __awaiter(this, void 0, void 0, function* () {
326
- const watermarkedBytes = appendWatermark(bytes, watermark);
327
- const watermarkedBytes2buff = Buffer.from(watermarkedBytes, 'hex');
328
- let messageToSend = [];
329
- messageToSend.push(transformPathToBuffer(this.path));
330
- messageToSend = chunkOperation(messageToSend, watermarkedBytes2buff);
331
- const ledgerResponse = yield this.signWithLedger(messageToSend);
332
- let signature;
333
- if (this.derivationType === exports.DerivationType.ED25519 ||
334
- this.derivationType === exports.DerivationType.BIP32_ED25519) {
335
- signature = ledgerResponse.slice(0, ledgerResponse.length - 2).toString('hex');
336
- }
337
- else {
338
- if (!validateResponse(ledgerResponse)) {
339
- throw new InvalidLedgerResponseError('Invalid signature return by ledger unable to parse the response');
340
- }
341
- const idxLengthRVal = 3; // Third element of response is length of r value
342
- const rValue = extractValue(idxLengthRVal, ledgerResponse);
343
- const idxLengthSVal = rValue.idxValueStart + rValue.length + 1;
344
- const sValue = extractValue(idxLengthSVal, ledgerResponse);
345
- const signatureBuffer = Buffer.concat([rValue.buffer, sValue.buffer]);
346
- signature = signatureBuffer.toString('hex');
347
- }
348
- return {
349
- bytes,
350
- sig: utils.b58cencode(signature, utils.prefix[utils.Prefix.SIG]),
351
- prefixSig: utils.b58cencode(signature, this.getPrefixes().prefSig),
352
- sbytes: bytes + signature,
353
- };
354
- });
355
- }
356
- signWithLedger(message) {
357
- return __awaiter(this, void 0, void 0, function* () {
358
- // first element of the message represents the path
359
- let ledgerResponse = yield this.transport.send(this.CLA, this.INS_SIGN, this.FIRST_MESSAGE_SEQUENCE, this.derivationType, message[0]);
360
- for (let i = 1; i < message.length; i++) {
361
- const p1 = i === message.length - 1 ? this.LAST_MESSAGE_SEQUENCE : this.OTHER_MESSAGE_SEQUENCE;
362
- ledgerResponse = yield this.transport.send(this.CLA, this.INS_SIGN, p1, this.derivationType, message[i]);
363
- }
364
- return ledgerResponse;
365
- });
366
- }
367
- getPrefixes() {
368
- if (this.derivationType === exports.DerivationType.ED25519 ||
369
- this.derivationType === exports.DerivationType.BIP32_ED25519) {
370
- return {
371
- prefPk: utils.prefix[utils.Prefix.EDPK],
372
- prefPkh: utils.prefix[utils.Prefix.TZ1],
373
- prefSig: utils.prefix[utils.Prefix.EDSIG],
374
- };
375
- }
376
- else if (this.derivationType === exports.DerivationType.SECP256K1) {
377
- return {
378
- prefPk: utils.prefix[utils.Prefix.SPPK],
379
- prefPkh: utils.prefix[utils.Prefix.TZ2],
380
- prefSig: utils.prefix[utils.Prefix.SPSIG],
381
- };
382
- }
383
- else {
384
- return {
385
- prefPk: utils.prefix[utils.Prefix.P2PK],
386
- prefPkh: utils.prefix[utils.Prefix.TZ3],
387
- prefSig: utils.prefix[utils.Prefix.P2SIG],
388
- };
389
- }
390
- }
212
+ /**
213
+ * @packageDocumentation
214
+ * @module @taquito/ledger-signer
215
+ */
216
+ exports.DerivationType = void 0;
217
+ (function (DerivationType) {
218
+ DerivationType[DerivationType["ED25519"] = 0] = "ED25519";
219
+ DerivationType[DerivationType["SECP256K1"] = 1] = "SECP256K1";
220
+ DerivationType[DerivationType["P256"] = 2] = "P256";
221
+ DerivationType[DerivationType["BIP32_ED25519"] = 3] = "BIP32_ED25519";
222
+ })(exports.DerivationType || (exports.DerivationType = {}));
223
+ const HDPathTemplate = (account) => {
224
+ return `44'/1729'/${account}'/0'`;
225
+ };
226
+ /**
227
+ *
228
+ * @description Implementation of the Signer interface that will allow signing operation from a Ledger Nano device
229
+ *
230
+ * @param transport A transport instance from LedgerJS libraries depending on the platform used (e.g. Web, Node)
231
+ * @param path The ledger derivation path (default is "44'/1729'/0'/0'")
232
+ * @param prompt Whether to prompt the ledger for public key (default is true)
233
+ * @param derivationType The value which defines the curve to use (DerivationType.ED25519(default), DerivationType.SECP256K1, DerivationType.P256, DerivationType.BIP32_ED25519)
234
+ *
235
+ * @example
236
+ * ```
237
+ * import TransportNodeHid from "@ledgerhq/hw-transport-node-hid";
238
+ * const transport = await TransportNodeHid.create();
239
+ * const ledgerSigner = new LedgerSigner(transport, "44'/1729'/0'/0'", false, DerivationType.ED25519);
240
+ * ```
241
+ *
242
+ * @example
243
+ * ```
244
+ * import TransportU2F from "@ledgerhq/hw-transport-u2f";
245
+ * const transport = await TransportU2F.create();
246
+ * const ledgerSigner = new LedgerSigner(transport, "44'/1729'/0'/0'", true, DerivationType.SECP256K1);
247
+ * ```
248
+ *
249
+ * @example
250
+ * ```
251
+ * import TransportU2F from "@ledgerhq/hw-transport-u2f";
252
+ * const transport = await TransportU2F.create();
253
+ * const ledgerSigner = new LedgerSigner(transport, "44'/1729'/6'/0'", true, DerivationType.BIP32_ED25519);
254
+ * ```
255
+ */
256
+ class LedgerSigner {
257
+ constructor(transport, path = "44'/1729'/0'/0'", prompt = true, derivationType = exports.DerivationType.ED25519) {
258
+ this.transport = transport;
259
+ this.path = path;
260
+ this.prompt = prompt;
261
+ this.derivationType = derivationType;
262
+ // constants for APDU requests (https://github.com/obsidiansystems/ledger-app-tezos/blob/master/APDUs.md)
263
+ this.CLA = 0x80; // Instruction class (always 0x80)
264
+ this.INS_GET_PUBLIC_KEY = 0x02; // Instruction code to get the ledger’s internal public key without prompt
265
+ this.INS_PROMPT_PUBLIC_KEY = 0x03; // Instruction code to get the ledger’s internal public key with prompt
266
+ this.INS_SIGN = 0x04; // Sign a message with the ledger’s key
267
+ this.FIRST_MESSAGE_SEQUENCE = 0x00;
268
+ this.LAST_MESSAGE_SEQUENCE = 0x81;
269
+ this.OTHER_MESSAGE_SEQUENCE = 0x01;
270
+ this.transport.setScrambleKey('XTZ');
271
+ if (!path.startsWith(`44'/1729'`)) {
272
+ throw new core.InvalidDerivationPathError(path, `${utils.invalidDetail(utils.ValidationResult.NO_PREFIX_MATCHED)} expecting prefix "44'/1729'".`);
273
+ }
274
+ if (!Object.values(exports.DerivationType).includes(derivationType)) {
275
+ throw new InvalidDerivationTypeError(derivationType.toString());
276
+ }
277
+ }
278
+ publicKeyHash() {
279
+ return __awaiter(this, void 0, void 0, function* () {
280
+ if (!this._publicKeyHash) {
281
+ yield this.publicKey();
282
+ }
283
+ if (this._publicKeyHash) {
284
+ return this._publicKeyHash;
285
+ }
286
+ throw new PublicKeyHashRetrievalError();
287
+ });
288
+ }
289
+ publicKey() {
290
+ return __awaiter(this, void 0, void 0, function* () {
291
+ if (this._publicKey) {
292
+ return this._publicKey;
293
+ }
294
+ const responseLedger = yield this.getLedgerPublicKey();
295
+ const publicKeyLength = responseLedger[0];
296
+ const rawPublicKey = responseLedger.slice(1, 1 + publicKeyLength);
297
+ const compressedPublicKey = compressPublicKey(rawPublicKey, this.derivationType);
298
+ const prefixes = this.getPrefixes();
299
+ const publicKey = utils.b58cencode(compressedPublicKey, prefixes.prefPk);
300
+ const publicKeyHash = utils.b58cencode(blake2b.hash(compressedPublicKey, 20), prefixes.prefPkh);
301
+ this._publicKey = publicKey;
302
+ this._publicKeyHash = publicKeyHash;
303
+ return publicKey;
304
+ });
305
+ }
306
+ getLedgerPublicKey() {
307
+ return __awaiter(this, void 0, void 0, function* () {
308
+ try {
309
+ let ins = this.INS_PROMPT_PUBLIC_KEY;
310
+ if (this.prompt === false) {
311
+ ins = this.INS_GET_PUBLIC_KEY;
312
+ }
313
+ const responseLedger = yield this.transport.send(this.CLA, ins, this.FIRST_MESSAGE_SEQUENCE, this.derivationType, transformPathToBuffer(this.path));
314
+ return responseLedger;
315
+ }
316
+ catch (error) {
317
+ throw new PublicKeyRetrievalError(error);
318
+ }
319
+ });
320
+ }
321
+ secretKey() {
322
+ return __awaiter(this, void 0, void 0, function* () {
323
+ throw new core.ProhibitedActionError('Secret key cannot be exposed');
324
+ });
325
+ }
326
+ sign(bytes, watermark) {
327
+ return __awaiter(this, void 0, void 0, function* () {
328
+ const watermarkedBytes = appendWatermark(bytes, watermark);
329
+ const watermarkedBytes2buff = Buffer.from(watermarkedBytes, 'hex');
330
+ let messageToSend = [];
331
+ messageToSend.push(transformPathToBuffer(this.path));
332
+ messageToSend = chunkOperation(messageToSend, watermarkedBytes2buff);
333
+ const ledgerResponse = yield this.signWithLedger(messageToSend);
334
+ let signature;
335
+ if (this.derivationType === exports.DerivationType.ED25519 ||
336
+ this.derivationType === exports.DerivationType.BIP32_ED25519) {
337
+ signature = ledgerResponse.slice(0, ledgerResponse.length - 2).toString('hex');
338
+ }
339
+ else {
340
+ if (!validateResponse(ledgerResponse)) {
341
+ throw new InvalidLedgerResponseError('Invalid signature return by ledger unable to parse the response');
342
+ }
343
+ const idxLengthRVal = 3; // Third element of response is length of r value
344
+ const rValue = extractValue(idxLengthRVal, ledgerResponse);
345
+ const idxLengthSVal = rValue.idxValueStart + rValue.length + 1;
346
+ const sValue = extractValue(idxLengthSVal, ledgerResponse);
347
+ const signatureBuffer = Buffer.concat([rValue.buffer, sValue.buffer]);
348
+ signature = signatureBuffer.toString('hex');
349
+ }
350
+ return {
351
+ bytes,
352
+ sig: utils.b58cencode(signature, utils.prefix[utils.Prefix.SIG]),
353
+ prefixSig: utils.b58cencode(signature, this.getPrefixes().prefSig),
354
+ sbytes: bytes + signature,
355
+ };
356
+ });
357
+ }
358
+ signWithLedger(message) {
359
+ return __awaiter(this, void 0, void 0, function* () {
360
+ // first element of the message represents the path
361
+ let ledgerResponse = yield this.transport.send(this.CLA, this.INS_SIGN, this.FIRST_MESSAGE_SEQUENCE, this.derivationType, message[0]);
362
+ for (let i = 1; i < message.length; i++) {
363
+ const p1 = i === message.length - 1 ? this.LAST_MESSAGE_SEQUENCE : this.OTHER_MESSAGE_SEQUENCE;
364
+ ledgerResponse = yield this.transport.send(this.CLA, this.INS_SIGN, p1, this.derivationType, message[i]);
365
+ }
366
+ return ledgerResponse;
367
+ });
368
+ }
369
+ getPrefixes() {
370
+ if (this.derivationType === exports.DerivationType.ED25519 ||
371
+ this.derivationType === exports.DerivationType.BIP32_ED25519) {
372
+ return {
373
+ prefPk: utils.prefix[utils.Prefix.EDPK],
374
+ prefPkh: utils.prefix[utils.Prefix.TZ1],
375
+ prefSig: utils.prefix[utils.Prefix.EDSIG],
376
+ };
377
+ }
378
+ else if (this.derivationType === exports.DerivationType.SECP256K1) {
379
+ return {
380
+ prefPk: utils.prefix[utils.Prefix.SPPK],
381
+ prefPkh: utils.prefix[utils.Prefix.TZ2],
382
+ prefSig: utils.prefix[utils.Prefix.SPSIG],
383
+ };
384
+ }
385
+ else {
386
+ return {
387
+ prefPk: utils.prefix[utils.Prefix.P2PK],
388
+ prefPkh: utils.prefix[utils.Prefix.TZ3],
389
+ prefSig: utils.prefix[utils.Prefix.P2SIG],
390
+ };
391
+ }
392
+ }
391
393
  }
392
394
 
393
395
  Object.defineProperty(exports, 'InvalidDerivationPathError', {
@@ -399,7 +401,5 @@
399
401
  exports.LedgerSigner = LedgerSigner;
400
402
  exports.VERSION = VERSION;
401
403
 
402
- Object.defineProperty(exports, '__esModule', { value: true });
403
-
404
404
  }));
405
405
  //# sourceMappingURL=taquito-ledger-signer.umd.js.map