@trezor/connect 9.5.3 → 9.5.4-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. package/CHANGELOG.md +40 -6
  2. package/README.md +1 -1
  3. package/lib/api/binance/api/binanceSignTransaction.js +1 -1
  4. package/lib/api/bitcoin/BitcoinFees.d.ts +4 -6
  5. package/lib/api/bitcoin/BitcoinFees.js +8 -2
  6. package/lib/api/bitcoin/signtxVerify.d.ts +1 -1
  7. package/lib/api/bitcoin/signtxVerify.js +3 -3
  8. package/lib/api/blockchainEstimateFee.js +13 -13
  9. package/lib/api/cardano/api/cardanoSignTransaction.js +1 -1
  10. package/lib/api/common/Discovery.d.ts +4 -4
  11. package/lib/api/common/Discovery.js +3 -4
  12. package/lib/api/common/MiscFees.d.ts +5 -9
  13. package/lib/api/common/MiscFees.js +6 -21
  14. package/lib/api/composeTransaction.js +4 -3
  15. package/lib/api/eos/api/eosSignTransaction.js +1 -1
  16. package/lib/api/eos/eosSignTx.d.ts +2 -2
  17. package/lib/api/ethereum/EthereumFees.d.ts +5 -8
  18. package/lib/api/ethereum/EthereumFees.js +24 -38
  19. package/lib/api/ethereum/api/ethereumGetAddress.d.ts +1 -5
  20. package/lib/api/ethereum/api/ethereumGetAddress.js +7 -8
  21. package/lib/api/ethereum/api/ethereumGetPublicKey.d.ts +11 -7
  22. package/lib/api/ethereum/api/ethereumGetPublicKey.js +12 -5
  23. package/lib/api/ethereum/api/ethereumSignTransaction.js +2 -2
  24. package/lib/api/ethereum/api/ethereumSignTypedData.d.ts +2 -4
  25. package/lib/api/ethereum/api/ethereumSignTypedData.js +1 -1
  26. package/lib/api/firmware/uploadFirmware.d.ts +2 -2
  27. package/lib/api/getAccountDescriptor.js +1 -3
  28. package/lib/api/getAccountInfo.js +4 -9
  29. package/lib/api/getAddress.js +6 -7
  30. package/lib/api/getCoinInfo.d.ts +12 -18
  31. package/lib/api/getPublicKey.d.ts +11 -7
  32. package/lib/api/resetDevice.js +1 -3
  33. package/lib/api/signTransaction.js +3 -3
  34. package/lib/api/stellar/api/stellarSignTransaction.js +1 -1
  35. package/lib/constants/errors.d.ts +1 -2
  36. package/lib/constants/errors.js +8 -3
  37. package/lib/core/index.js +36 -15
  38. package/lib/core/onCallFirmwareUpdate.js +6 -3
  39. package/lib/data/coinInfo.d.ts +44 -66
  40. package/lib/data/config.d.ts +10 -0
  41. package/lib/data/config.js +10 -0
  42. package/lib/data/deviceAuthenticityConfig.js +4 -1
  43. package/lib/data/version.d.ts +1 -1
  44. package/lib/data/version.js +1 -1
  45. package/lib/device/Device.d.ts +82 -16
  46. package/lib/device/Device.js +51 -61
  47. package/lib/device/DeviceCommands.d.ts +37 -4549
  48. package/lib/device/DeviceCommands.js +55 -264
  49. package/lib/device/DeviceCurrentSession.d.ts +4531 -0
  50. package/lib/device/DeviceCurrentSession.js +209 -0
  51. package/lib/device/DeviceList.js +4 -6
  52. package/lib/device/TransportManager.d.ts +1 -1
  53. package/lib/device/TransportManager.js +5 -4
  54. package/lib/events/ui-response.d.ts +3 -3
  55. package/lib/impl/dynamic.d.ts +4 -1
  56. package/lib/impl/dynamic.js +17 -4
  57. package/lib/tsconfig.lib.tsbuildinfo +1 -1
  58. package/lib/types/api/getPublicKey.d.ts +5 -3
  59. package/lib/types/api/getPublicKey.js +13 -12
  60. package/lib/types/coinInfo.d.ts +12 -24
  61. package/lib/types/fees.d.ts +2 -11
  62. package/lib/types/fees.js +3 -11
  63. package/lib/utils/versionCheck.js +1 -1
  64. package/package.json +7 -7
  65. package/lib/device/prompts.d.ts +0 -866
  66. package/lib/device/prompts.js +0 -60
@@ -8,8 +8,8 @@ const transport_1 = require("@trezor/transport");
8
8
  const utils_1 = require("@trezor/utils");
9
9
  const DeviceCommands_1 = require("./DeviceCommands");
10
10
  const constants_1 = require("../constants");
11
+ const DeviceCurrentSession_1 = require("./DeviceCurrentSession");
11
12
  const checkFirmwareRevision_1 = require("./checkFirmwareRevision");
12
- const prompts_1 = require("./prompts");
13
13
  const firmware_1 = require("../api/firmware");
14
14
  const DataManager_1 = require("../data/DataManager");
15
15
  const coinInfo_1 = require("../data/coinInfo");
@@ -20,6 +20,7 @@ const events_1 = require("../events");
20
20
  const types_1 = require("../types");
21
21
  const debug_1 = require("../utils/debug");
22
22
  const deviceFeaturesUtils_1 = require("../utils/deviceFeaturesUtils");
23
+ const pathUtils_1 = require("../utils/pathUtils");
23
24
  const _log = (0, debug_1.initLog)('Device');
24
25
  exports.CANCEL_TIMEOUT = 1_000;
25
26
  exports.GET_FEATURES_TIMEOUT = 3_000;
@@ -33,10 +34,10 @@ class Device extends utils_1.TypedEmitter {
33
34
  transport;
34
35
  protocol;
35
36
  transportPath;
36
- transportSessionOwner;
37
37
  transportDescriptorType;
38
38
  bluetoothProps;
39
39
  session;
40
+ transportSessionOwner;
40
41
  lastAcquiredHere;
41
42
  unreadableError;
42
43
  _firmwareStatus;
@@ -56,8 +57,7 @@ class Device extends utils_1.TypedEmitter {
56
57
  releasePromise;
57
58
  runPromise;
58
59
  keepTransportSession = false;
59
- commands;
60
- cancelableAction;
60
+ currentSession;
61
61
  loaded = false;
62
62
  inconsistent = false;
63
63
  firstRunPromise;
@@ -136,8 +136,8 @@ class Device extends utils_1.TypedEmitter {
136
136
  if (result.success) {
137
137
  this.session = result.payload;
138
138
  this.lastAcquiredHere = true;
139
- this.commands?.dispose();
140
- this.commands = new DeviceCommands_1.DeviceCommands(this, this.transport, this.session);
139
+ this.currentSession?.dispose();
140
+ this.currentSession = new DeviceCurrentSession_1.DeviceCurrentSession(this, this.transport, this.protocol, this.session);
141
141
  return result;
142
142
  }
143
143
  else {
@@ -154,16 +154,11 @@ class Device extends utils_1.TypedEmitter {
154
154
  return this.acquirePromise;
155
155
  }
156
156
  async release() {
157
- const localSession = this.getLocalSession();
157
+ const localSession = this.lastAcquiredHere ? this.session : null;
158
158
  if (!localSession || this.keepTransportSession || this.releasePromise) {
159
159
  return;
160
160
  }
161
- if (this.commands) {
162
- this.commands.dispose();
163
- if (this.commands.callPromise) {
164
- await this.commands.callPromise;
165
- }
166
- }
161
+ await this.currentSession?.dispose();
167
162
  const sessionPromise = this.getSessionChangePromise();
168
163
  this.releasePromise = this.transport
169
164
  .release({ session: localSession, path: this.transportPath })
@@ -237,12 +232,13 @@ class Device extends utils_1.TypedEmitter {
237
232
  this.usedElsewhere();
238
233
  }
239
234
  if (!descriptor.session) {
240
- const methodStillRunning = !this.commands?.isDisposed();
235
+ const methodStillRunning = !this.currentSession?.isDisposed();
241
236
  if (methodStillRunning) {
242
237
  this.releaseTransportSession();
243
238
  }
244
239
  }
245
240
  this.session = descriptor.session;
241
+ this.transportSessionOwner = descriptor.sessionOwner;
246
242
  this.emitLifecycle(events_1.DEVICE.CHANGED);
247
243
  }
248
244
  run(fn, options) {
@@ -276,22 +272,10 @@ class Device extends utils_1.TypedEmitter {
276
272
  await this.releasePromise;
277
273
  }
278
274
  }
279
- setCancelableAction(callback) {
280
- this.cancelableAction = (e) => callback(e)
281
- .catch(e2 => {
282
- _log.debug('cancelableAction error', e2);
283
- })
284
- .finally(() => {
285
- this.clearCancelableAction();
286
- });
287
- }
288
- clearCancelableAction() {
289
- this.cancelableAction = undefined;
290
- }
291
275
  async interruptionFromUser(error) {
292
276
  _log.debug('interruptionFromUser');
293
- await this.cancelableAction?.(error.toString());
294
- await this.commands?.cancel();
277
+ await this.currentSession?.abort(error);
278
+ await this.currentSession?.dispose();
295
279
  if (this.runPromise) {
296
280
  this.runPromise.reject(error);
297
281
  delete this.runPromise;
@@ -304,9 +288,7 @@ class Device extends utils_1.TypedEmitter {
304
288
  this.lastAcquiredHere = false;
305
289
  this._featuresNeedsReload = true;
306
290
  _log.debug('interruptionFromOutside');
307
- if (this.commands) {
308
- this.commands.dispose();
309
- }
291
+ this.currentSession?.dispose();
310
292
  if (this.runPromise) {
311
293
  this.runPromise.reject(constants_1.ERRORS.TypedError('Device_UsedElsewhere'));
312
294
  delete this.runPromise;
@@ -319,7 +301,7 @@ class Device extends utils_1.TypedEmitter {
319
301
  if (this.releasePromise) {
320
302
  await this.releasePromise;
321
303
  }
322
- const acquireNeeded = !this.isUsedHere() || this.commands?.disposed;
304
+ const acquireNeeded = !this.isUsedHere() || this.currentSession?.isDisposed();
323
305
  if (acquireNeeded) {
324
306
  await this.acquire();
325
307
  }
@@ -341,9 +323,7 @@ class Device extends utils_1.TypedEmitter {
341
323
  ![0, 2].includes(this.transportDescriptorType)) {
342
324
  _log.debug('sending a preventive cancel on the first encounter with the device');
343
325
  await Promise.race([
344
- this.getCommands()
345
- .typedCall('Cancel', 'Failure', {})
346
- .catch(() => { }),
326
+ this.getCurrentSession().cancelCall(),
347
327
  new Promise((_, reject) => setTimeout(reject, cancelTimeout)),
348
328
  ]).catch(() => this.acquire());
349
329
  }
@@ -351,10 +331,9 @@ class Device extends utils_1.TypedEmitter {
351
331
  await Promise.race([
352
332
  this.getFeatures().finally(() => clearTimeout(getFeaturesTimeoutId)),
353
333
  new Promise((_resolve, reject) => {
354
- getFeaturesTimeoutId = setTimeout(() => {
355
- (0, prompts_1.cancelPrompt)(this, false).finally(() => {
356
- reject(new Error('GetFeatures timeout'));
357
- });
334
+ getFeaturesTimeoutId = setTimeout(async () => {
335
+ await this.getCurrentSession().cancelCall(false);
336
+ reject(new Error('GetFeatures timeout'));
358
337
  }, getFeaturesTimeout);
359
338
  }),
360
339
  ]);
@@ -414,11 +393,14 @@ class Device extends utils_1.TypedEmitter {
414
393
  this.firstRunPromise.resolve(true);
415
394
  }
416
395
  }
417
- getCommands() {
418
- if (!this.commands) {
396
+ getCurrentSession() {
397
+ if (!this.currentSession) {
419
398
  throw constants_1.ERRORS.TypedError('Runtime', `Device: commands not defined`);
420
399
  }
421
- return this.commands;
400
+ return this.currentSession;
401
+ }
402
+ getCommands() {
403
+ return (0, DeviceCommands_1.DeviceCommands)(this.getCurrentSession());
422
404
  }
423
405
  setInstance(instance = 0) {
424
406
  if (this.instance !== instance) {
@@ -458,8 +440,12 @@ class Device extends utils_1.TypedEmitter {
458
440
  }
459
441
  }
460
442
  const expectedState = this.getState()?.staticSessionId;
461
- const state = await this.getCommands().getDeviceState();
462
- const uniqueState = `${state}@${this.features.device_id}:${this.instance}`;
443
+ const { message } = await this.getCurrentSession().typedCall('GetAddress', 'Address', {
444
+ address_n: [(0, pathUtils_1.toHardened)(44), (0, pathUtils_1.toHardened)(1), (0, pathUtils_1.toHardened)(0), 0, 0],
445
+ coin_name: 'Testnet',
446
+ script_type: 'SPENDADDRESS',
447
+ });
448
+ const uniqueState = `${message.address}@${this.features.device_id}:${this.instance}`;
463
449
  if (this.features.session_id) {
464
450
  this.setState({ sessionId: this.features.session_id });
465
451
  }
@@ -481,7 +467,7 @@ class Device extends utils_1.TypedEmitter {
481
467
  payload.session_id = sessionId;
482
468
  }
483
469
  }
484
- const { message } = await this.getCommands().typedCall('Initialize', 'Features', payload);
470
+ const { message } = await this.getCurrentSession().typedCall('Initialize', 'Features', payload);
485
471
  this._updateFeatures(message);
486
472
  this.setState({ deriveCardano: payload?.derive_cardano });
487
473
  }
@@ -490,7 +476,7 @@ class Device extends utils_1.TypedEmitter {
490
476
  this.setState(storage.loadState(this));
491
477
  }
492
478
  async getFeatures() {
493
- const { message } = await this.getCommands().typedCall('GetFeatures', 'Features', {});
479
+ const { message } = await this.getCurrentSession().typedCall('GetFeatures', 'Features', {});
494
480
  this._updateFeatures(message);
495
481
  }
496
482
  async checkFirmwareHashWithRetries() {
@@ -548,7 +534,7 @@ class Device extends utils_1.TypedEmitter {
548
534
  const strippedBinary = (0, firmware_1.stripFwHeaders)(binary);
549
535
  const { hash: expectedHash, challenge } = (0, firmware_1.calculateFirmwareHash)(this.features.major_version, strippedBinary, (0, crypto_1.randomBytes)(32));
550
536
  try {
551
- const deviceResponse = await this.getCommands().typedCall('GetFirmwareHash', 'FirmwareHash', { challenge });
537
+ const deviceResponse = await this.getCurrentSession().typedCall('GetFirmwareHash', 'FirmwareHash', { challenge });
552
538
  if (!deviceResponse?.message?.hash) {
553
539
  return createFailResult('other-error', 'Device response is missing hash');
554
540
  }
@@ -612,20 +598,17 @@ class Device extends utils_1.TypedEmitter {
612
598
  return this._uploadTranslationData(downloadedBinary);
613
599
  }
614
600
  async _uploadTranslationData(payload) {
615
- if (!this.commands) {
616
- throw constants_1.ERRORS.TypedError('Runtime', 'uploadTranslationData: device.commands is not set');
617
- }
618
601
  if (payload === null) {
619
- const response = await this.commands.typedCall('ChangeLanguage', ['Success'], { data_length: 0 });
602
+ const response = await this.getCurrentSession().typedCall('ChangeLanguage', ['Success'], { data_length: 0 });
620
603
  return response.message;
621
604
  }
622
605
  const length = payload.byteLength;
623
- let response = await this.commands.typedCall('ChangeLanguage', ['TranslationDataRequest', 'Success'], { data_length: length });
606
+ let response = await this.getCurrentSession().typedCall('ChangeLanguage', ['TranslationDataRequest', 'Success'], { data_length: length });
624
607
  while (response.type !== 'Success') {
625
608
  const start = response.message.data_offset;
626
609
  const end = response.message.data_offset + response.message.data_length;
627
610
  const chunk = payload.slice(start, end);
628
- response = await this.commands.typedCall('TranslationDataAck', ['TranslationDataRequest', 'Success'], {
611
+ response = await this.getCurrentSession().typedCall('TranslationDataAck', ['TranslationDataRequest', 'Success'], {
629
612
  data_chunk: Buffer.from(chunk).toString('hex'),
630
613
  });
631
614
  }
@@ -693,6 +676,20 @@ class Device extends utils_1.TypedEmitter {
693
676
  }
694
677
  }
695
678
  }
679
+ prompt(type, args) {
680
+ return new Promise(callback => {
681
+ if (!this.listenerCount(type)) {
682
+ const payload = {
683
+ success: false,
684
+ error: new Error(`${type} callback not configured`),
685
+ };
686
+ callback(payload);
687
+ }
688
+ else {
689
+ this.emit(type, { callback, ...args });
690
+ }
691
+ });
692
+ }
696
693
  isUnacquired() {
697
694
  return this.features === undefined;
698
695
  }
@@ -752,9 +749,6 @@ class Device extends utils_1.TypedEmitter {
752
749
  waitForFirstRun() {
753
750
  return this.firstRunPromise.promise;
754
751
  }
755
- getLocalSession() {
756
- return this.lastAcquiredHere ? this.session : null;
757
- }
758
752
  getUniquePath() {
759
753
  return this.uniquePath;
760
754
  }
@@ -781,11 +775,7 @@ class Device extends utils_1.TypedEmitter {
781
775
  dispose() {
782
776
  this.removeAllListeners();
783
777
  if (this.session && this.lastAcquiredHere) {
784
- return this.transport.release({
785
- session: this.session,
786
- path: this.transportPath,
787
- onClose: true,
788
- });
778
+ this.transport.releaseSync(this.session);
789
779
  }
790
780
  }
791
781
  getMode() {