@trezor/connect 9.4.8-beta.1 → 9.5.0-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 (97) hide show
  1. package/CHANGELOG.md +33 -6
  2. package/README.md +1 -1
  3. package/lib/api/authorizeCoinjoin.js +1 -1
  4. package/lib/api/binance/api/binanceGetAddress.js +2 -4
  5. package/lib/api/binance/api/binanceGetPublicKey.js +1 -0
  6. package/lib/api/binance/api/binanceSignTransaction.js +1 -2
  7. package/lib/api/bitcoin/Fees.js +4 -1
  8. package/lib/api/bitcoin/TransactionComposer.js +9 -2
  9. package/lib/api/bitcoin/enhanceSignTx.js +1 -2
  10. package/lib/api/bitcoin/refTx.js +4 -6
  11. package/lib/api/blockchainDisconnect.js +1 -1
  12. package/lib/api/blockchainSubscribe.js +1 -2
  13. package/lib/api/blockchainUnsubscribe.js +1 -2
  14. package/lib/api/cardano/api/cardanoComposeTransaction.js +1 -1
  15. package/lib/api/cardano/api/cardanoGetAddress.js +2 -4
  16. package/lib/api/cardano/api/cardanoGetPublicKey.js +1 -0
  17. package/lib/api/cardano/cardanoAuxiliaryData.js +2 -2
  18. package/lib/api/cardano/cardanoUtils.js +5 -6
  19. package/lib/api/cipherKeyValue.js +1 -0
  20. package/lib/api/common/Discovery.js +16 -1
  21. package/lib/api/common/paramsValidator.js +2 -2
  22. package/lib/api/composeTransaction.js +6 -6
  23. package/lib/api/eos/api/eosGetPublicKey.js +1 -0
  24. package/lib/api/ethereum/api/ethereumGetAddress.js +2 -4
  25. package/lib/api/ethereum/api/ethereumGetPublicKey.js +1 -0
  26. package/lib/api/ethereum/api/ethereumSignMessage.js +1 -2
  27. package/lib/api/ethereum/api/ethereumSignTransaction.js +1 -1
  28. package/lib/api/ethereum/api/ethereumSignTypedData.js +1 -1
  29. package/lib/api/ethereum/ethereumDefinitions.js +2 -2
  30. package/lib/api/ethereum/ethereumSignTx.d.ts +2 -2
  31. package/lib/api/ethereum/ethereumSignTx.js +3 -2
  32. package/lib/api/firmware/verifyAuthenticityProof.js +3 -3
  33. package/lib/api/getAccountDescriptor.js +2 -4
  34. package/lib/api/getAccountInfo.js +4 -5
  35. package/lib/api/getAddress.js +5 -8
  36. package/lib/api/getDeviceState.js +1 -1
  37. package/lib/api/getOwnershipId.js +1 -0
  38. package/lib/api/getOwnershipProof.js +1 -0
  39. package/lib/api/getPublicKey.js +3 -2
  40. package/lib/api/nem/api/nemGetAddress.js +2 -4
  41. package/lib/api/nem/api/nemSignTransaction.js +1 -2
  42. package/lib/api/requestLogin.js +1 -0
  43. package/lib/api/ripple/api/rippleGetAddress.js +2 -4
  44. package/lib/api/signMessage.js +1 -2
  45. package/lib/api/signTransaction.js +6 -8
  46. package/lib/api/solana/additionalInfo.js +2 -3
  47. package/lib/api/solana/api/solanaComposeTransaction.js +2 -3
  48. package/lib/api/solana/api/solanaGetAddress.js +2 -4
  49. package/lib/api/solana/api/solanaGetPublicKey.js +1 -0
  50. package/lib/api/solana/solanaUtils.js +6 -5
  51. package/lib/api/stellar/api/stellarGetAddress.js +2 -4
  52. package/lib/api/tezos/api/tezosGetAddress.js +2 -4
  53. package/lib/api/tezos/api/tezosGetPublicKey.js +1 -0
  54. package/lib/backend/BackendManager.js +11 -16
  55. package/lib/backend/Blockchain.js +10 -4
  56. package/lib/backend/BlockchainLink.js +1 -1
  57. package/lib/constants/errors.js +2 -0
  58. package/lib/core/AbstractMethod.js +30 -5
  59. package/lib/core/index.js +24 -34
  60. package/lib/core/onCallFirmwareUpdate.d.ts +3 -2
  61. package/lib/core/onCallFirmwareUpdate.js +12 -59
  62. package/lib/data/DataManager.js +3 -2
  63. package/lib/data/analyticsInfo.js +10 -11
  64. package/lib/data/connectSettings.js +1 -2
  65. package/lib/data/defaultFeeLevels.js +4 -7
  66. package/lib/data/deviceAuthenticityConfig.js +16 -1
  67. package/lib/data/firmwareInfo.js +5 -6
  68. package/lib/data/version.d.ts +1 -1
  69. package/lib/data/version.js +1 -1
  70. package/lib/device/Device.d.ts +10 -2
  71. package/lib/device/Device.js +73 -56
  72. package/lib/device/DeviceCommands.d.ts +5 -1
  73. package/lib/device/DeviceCommands.js +7 -2
  74. package/lib/device/DeviceList.d.ts +2 -0
  75. package/lib/device/DeviceList.js +44 -24
  76. package/lib/device/StateStorage.js +5 -6
  77. package/lib/device/checkFirmwareRevision.js +11 -6
  78. package/lib/device/prompts.js +4 -7
  79. package/lib/events/call.d.ts +1 -0
  80. package/lib/events/call.js +3 -3
  81. package/lib/impl/core-in-module.js +25 -23
  82. package/lib/impl/dynamic.js +7 -1
  83. package/lib/index.js +9 -12
  84. package/lib/types/api/ethereum/index.d.ts +4 -4
  85. package/lib/types/api/ethereum/index.js +2 -2
  86. package/lib/types/api/firmwareUpdate.d.ts +1 -8
  87. package/lib/utils/assets.js +1 -1
  88. package/lib/utils/assets.native.js +1 -1
  89. package/lib/utils/hdnodeUtils.js +1 -2
  90. package/lib/utils/interactionTimeout.js +2 -2
  91. package/lib/utils/popupPromiseManager.js +2 -2
  92. package/lib/utils/proxy-event-emitter.js +1 -0
  93. package/lib/utils/uiPromiseManager.js +3 -4
  94. package/lib/utils/urlUtils.js +5 -8
  95. package/package.json +12 -12
  96. package/lib/utils/abortablePromise.d.ts +0 -5
  97. package/lib/utils/abortablePromise.js +0 -17
@@ -20,46 +20,68 @@ const types_1 = require("../types");
20
20
  const debug_1 = require("../utils/debug");
21
21
  const deviceFeaturesUtils_1 = require("../utils/deviceFeaturesUtils");
22
22
  const _log = (0, debug_1.initLog)('Device');
23
- exports.GET_FEATURES_TIMEOUT = 3000;
24
- exports.GET_FEATURES_TIMEOUT_REACT_NATIVE = 20000;
23
+ exports.GET_FEATURES_TIMEOUT = 3_000;
24
+ exports.GET_FEATURES_TIMEOUT_REACT_NATIVE = 20_000;
25
25
  const parseRunOptions = (options) => {
26
26
  if (!options)
27
27
  options = {};
28
28
  return options;
29
29
  };
30
30
  class Device extends utils_1.TypedEmitter {
31
+ transport;
32
+ protocol;
33
+ transportPath;
34
+ transportSessionOwner;
35
+ transportDescriptorType;
36
+ session;
37
+ lastAcquiredHere;
38
+ unreadableError;
39
+ _firmwareStatus;
31
40
  get firmwareStatus() {
32
41
  return this._firmwareStatus;
33
42
  }
43
+ _firmwareRelease;
34
44
  get firmwareRelease() {
35
45
  return this._firmwareRelease;
36
46
  }
47
+ _features;
37
48
  get features() {
38
49
  return this._features;
39
50
  }
51
+ _featuresNeedsReload = false;
52
+ acquirePromise;
53
+ releasePromise;
54
+ runPromise;
55
+ keepTransportSession = false;
56
+ commands;
57
+ cancelableAction;
58
+ loaded = false;
59
+ inconsistent = false;
60
+ firstRunPromise;
61
+ instance = 0;
62
+ state = [];
63
+ stateStorage = undefined;
64
+ _unavailableCapabilities = {};
40
65
  get unavailableCapabilities() {
41
66
  return this._unavailableCapabilities;
42
67
  }
68
+ _firmwareType;
43
69
  get firmwareType() {
44
70
  return this._firmwareType;
45
71
  }
72
+ name = 'Trezor';
73
+ color;
74
+ availableTranslations = [];
75
+ authenticityChecks = {
76
+ firmwareRevision: null,
77
+ firmwareHash: null,
78
+ };
79
+ uniquePath;
80
+ emitLifecycle;
81
+ sessionDfd;
82
+ handshakeFinished = false;
46
83
  constructor({ id, transport, descriptor, listener }) {
47
84
  super();
48
- this._featuresNeedsReload = false;
49
- this.keepTransportSession = false;
50
- this.loaded = false;
51
- this.inconsistent = false;
52
- this.instance = 0;
53
- this.state = [];
54
- this.stateStorage = undefined;
55
- this._unavailableCapabilities = {};
56
- this.name = 'Trezor';
57
- this.availableTranslations = [];
58
- this.authenticityChecks = {
59
- firmwareRevision: null,
60
- firmwareHash: null,
61
- };
62
- this.handshakeFinished = false;
63
85
  this.emitLifecycle = listener;
64
86
  this.protocol = protocol_1.v1;
65
87
  this.uniquePath = id;
@@ -107,11 +129,10 @@ class Device extends utils_1.TypedEmitter {
107
129
  .acquire({ input: { path: this.transportPath, previous: this.session } })
108
130
  .then(result => this.waitAndCompareSession(result, sessionPromise))
109
131
  .then(result => {
110
- var _a;
111
132
  if (result.success) {
112
133
  this.session = result.payload;
113
134
  this.lastAcquiredHere = true;
114
- (_a = this.commands) === null || _a === void 0 ? void 0 : _a.dispose();
135
+ this.commands?.dispose();
115
136
  this.commands = new DeviceCommands_1.DeviceCommands(this, this.transport, this.session);
116
137
  return result;
117
138
  }
@@ -165,9 +186,8 @@ class Device extends utils_1.TypedEmitter {
165
186
  }
166
187
  }
167
188
  async handshake(delay) {
168
- var _a;
169
189
  if (delay) {
170
- await (0, utils_1.createTimeoutPromise)(501 + delay);
190
+ await (0, utils_1.resolveAfter)(501 + delay);
171
191
  }
172
192
  while (true) {
173
193
  if (this.isUsedElsewhere()) {
@@ -192,12 +212,12 @@ class Device extends utils_1.TypedEmitter {
192
212
  this.emitLifecycle(events_1.DEVICE.CONNECT_UNACQUIRED);
193
213
  }
194
214
  else if (error.message === transport_1.TRANSPORT_ERROR.INTERFACE_UNABLE_TO_OPEN_DEVICE ||
195
- ((_a = error.message) === null || _a === void 0 ? void 0 : _a.indexOf(constants_1.ERRORS.LIBUSB_ERROR_MESSAGE)) >= 0) {
196
- this.unreadableError = error === null || error === void 0 ? void 0 : error.message;
215
+ error.message?.indexOf(constants_1.ERRORS.LIBUSB_ERROR_MESSAGE) >= 0) {
216
+ this.unreadableError = error?.message;
197
217
  this.emitLifecycle(events_1.DEVICE.CONNECT_UNACQUIRED);
198
218
  }
199
219
  else {
200
- await (0, utils_1.createTimeoutPromise)(501);
220
+ await (0, utils_1.resolveAfter)(501);
201
221
  continue;
202
222
  }
203
223
  }
@@ -207,14 +227,13 @@ class Device extends utils_1.TypedEmitter {
207
227
  }
208
228
  }
209
229
  async updateDescriptor(descriptor) {
210
- var _a, _b;
211
- (_a = this.sessionDfd) === null || _a === void 0 ? void 0 : _a.resolve(descriptor.session);
230
+ this.sessionDfd?.resolve(descriptor.session);
212
231
  await Promise.all([this.acquirePromise, this.releasePromise]);
213
232
  if (descriptor.session && descriptor.session !== this.session) {
214
233
  this.usedElsewhere();
215
234
  }
216
235
  if (!descriptor.session) {
217
- const methodStillRunning = !((_b = this.commands) === null || _b === void 0 ? void 0 : _b.isDisposed());
236
+ const methodStillRunning = !this.commands?.isDisposed();
218
237
  if (methodStillRunning) {
219
238
  this.releaseTransportSession();
220
239
  }
@@ -266,10 +285,9 @@ class Device extends utils_1.TypedEmitter {
266
285
  this.cancelableAction = undefined;
267
286
  }
268
287
  async interruptionFromUser(error) {
269
- var _a, _b;
270
288
  _log.debug('interruptionFromUser');
271
- await ((_a = this.cancelableAction) === null || _a === void 0 ? void 0 : _a.call(this, error));
272
- await ((_b = this.commands) === null || _b === void 0 ? void 0 : _b.cancel());
289
+ await this.cancelableAction?.(error);
290
+ await this.commands?.cancel();
273
291
  if (this.runPromise) {
274
292
  this.runPromise.reject(error);
275
293
  delete this.runPromise;
@@ -294,11 +312,10 @@ class Device extends utils_1.TypedEmitter {
294
312
  }
295
313
  }
296
314
  async _runInner(fn, options) {
297
- var _a, _b;
298
315
  if (this.releasePromise) {
299
316
  await this.releasePromise;
300
317
  }
301
- const acquireNeeded = !this.isUsedHere() || ((_a = this.commands) === null || _a === void 0 ? void 0 : _a.disposed);
318
+ const acquireNeeded = !this.isUsedHere() || this.commands?.disposed;
302
319
  if (acquireNeeded) {
303
320
  await this.acquire();
304
321
  }
@@ -312,6 +329,14 @@ class Device extends utils_1.TypedEmitter {
312
329
  const getFeaturesTimeout = DataManager_1.DataManager.getSettings('env') === 'react-native'
313
330
  ? exports.GET_FEATURES_TIMEOUT_REACT_NATIVE
314
331
  : exports.GET_FEATURES_TIMEOUT;
332
+ if (['v1', 'bridge'].includes(this.protocol.name)) {
333
+ _log.debug('sending a preventive cancel on the first encounter with the device');
334
+ try {
335
+ await this.getCommands().typedCall('Cancel', 'Failure', {});
336
+ }
337
+ catch {
338
+ }
339
+ }
315
340
  let getFeaturesTimeoutId;
316
341
  await Promise.race([
317
342
  this.getFeatures().finally(() => clearTimeout(getFeaturesTimeoutId)),
@@ -345,7 +370,7 @@ class Device extends utils_1.TypedEmitter {
345
370
  await this.checkFirmwareRevisionWithRetries();
346
371
  }
347
372
  if (!options.skipLanguageChecks &&
348
- ((_b = this.features) === null || _b === void 0 ? void 0 : _b.language) &&
373
+ this.features?.language &&
349
374
  !this.features.language_version_matches &&
350
375
  this.atLeast('2.7.0')) {
351
376
  _log.info('language version mismatch. silently updating...');
@@ -401,7 +426,6 @@ class Device extends utils_1.TypedEmitter {
401
426
  return this.state[this.instance];
402
427
  }
403
428
  setState(state) {
404
- var _a;
405
429
  if (!state) {
406
430
  delete this.state[this.instance];
407
431
  }
@@ -412,11 +436,10 @@ class Device extends utils_1.TypedEmitter {
412
436
  ...state,
413
437
  };
414
438
  this.state[this.instance] = newState;
415
- (_a = this.stateStorage) === null || _a === void 0 ? void 0 : _a.saveState(this, newState);
439
+ this.stateStorage?.saveState(this, newState);
416
440
  }
417
441
  }
418
442
  async validateState(preauthorized = false) {
419
- var _a;
420
443
  if (!this.features)
421
444
  return;
422
445
  if (!this.features.unlocked && preauthorized) {
@@ -424,7 +447,7 @@ class Device extends utils_1.TypedEmitter {
424
447
  return;
425
448
  }
426
449
  }
427
- const expectedState = (_a = this.getState()) === null || _a === void 0 ? void 0 : _a.staticSessionId;
450
+ const expectedState = this.getState()?.staticSessionId;
428
451
  const state = await this.getCommands().getDeviceState();
429
452
  const uniqueState = `${state}@${this.features.device_id}:${this.instance}`;
430
453
  if (this.features.session_id) {
@@ -450,7 +473,7 @@ class Device extends utils_1.TypedEmitter {
450
473
  }
451
474
  const { message } = await this.getCommands().typedCall('Initialize', 'Features', payload);
452
475
  this._updateFeatures(message);
453
- this.setState({ deriveCardano: payload === null || payload === void 0 ? void 0 : payload.derive_cardano });
476
+ this.setState({ deriveCardano: payload?.derive_cardano });
454
477
  }
455
478
  initStorage(storage) {
456
479
  this.stateStorage = storage;
@@ -461,15 +484,14 @@ class Device extends utils_1.TypedEmitter {
461
484
  this._updateFeatures(message);
462
485
  }
463
486
  async checkFirmwareHashWithRetries() {
464
- var _a;
465
487
  const lastResult = this.authenticityChecks.firmwareHash;
466
488
  const notDoneYet = lastResult === null;
467
- const attemptsDone = (_a = lastResult === null || lastResult === void 0 ? void 0 : lastResult.attemptCount) !== null && _a !== void 0 ? _a : 0;
489
+ const attemptsDone = lastResult?.attemptCount ?? 0;
468
490
  if (attemptsDone >= constants_1.FIRMWARE.HASH_CHECK_MAX_ATTEMPTS)
469
491
  return;
470
492
  const wasError = lastResult !== null && !lastResult.success;
471
493
  const wasErrorRetriable = wasError && (0, utils_1.isArrayMember)(lastResult.error, constants_1.FIRMWARE.HASH_CHECK_RETRIABLE_ERRORS);
472
- const lastErrorPayload = wasError ? lastResult === null || lastResult === void 0 ? void 0 : lastResult.errorPayload : null;
494
+ const lastErrorPayload = wasError ? lastResult?.errorPayload : null;
473
495
  if (notDoneYet || wasErrorRetriable) {
474
496
  const result = await this.checkFirmwareHash();
475
497
  this.authenticityChecks.firmwareHash = result;
@@ -482,7 +504,6 @@ class Device extends utils_1.TypedEmitter {
482
504
  }
483
505
  }
484
506
  async checkFirmwareHash() {
485
- var _a;
486
507
  const createFailResult = (error, errorPayload) => ({
487
508
  success: false,
488
509
  error,
@@ -515,7 +536,7 @@ class Device extends utils_1.TypedEmitter {
515
536
  const { hash: expectedHash, challenge } = (0, firmware_1.calculateFirmwareHash)(this.features.major_version, strippedBinary, (0, crypto_1.randomBytes)(32));
516
537
  try {
517
538
  const deviceResponse = await this.getCommands().typedCall('GetFirmwareHash', 'FirmwareHash', { challenge });
518
- if (!((_a = deviceResponse === null || deviceResponse === void 0 ? void 0 : deviceResponse.message) === null || _a === void 0 ? void 0 : _a.hash)) {
539
+ if (!deviceResponse?.message?.hash) {
519
540
  return createFailResult('other-error', 'Device response is missing hash');
520
541
  }
521
542
  if (deviceResponse.message.hash !== expectedHash) {
@@ -552,7 +573,7 @@ class Device extends utils_1.TypedEmitter {
552
573
  internalModel: this.features.internal_model,
553
574
  deviceRevision: this.features.revision,
554
575
  firmwareVersion,
555
- expectedRevision: release === null || release === void 0 ? void 0 : release.firmware_revision,
576
+ expectedRevision: release?.firmware_revision,
556
577
  });
557
578
  }
558
579
  async changeLanguage({ language, binary, }) {
@@ -597,13 +618,12 @@ class Device extends utils_1.TypedEmitter {
597
618
  return response.message;
598
619
  }
599
620
  _updateFeatures(feat) {
600
- var _a, _b, _c, _d;
601
621
  const capabilities = (0, deviceFeaturesUtils_1.parseCapabilities)(feat);
602
622
  feat.capabilities = capabilities;
603
623
  if (this.features && this.features.session_id && !feat.session_id) {
604
624
  feat.session_id = this.features.session_id;
605
625
  }
606
- feat.unlocked = (_a = feat.unlocked) !== null && _a !== void 0 ? _a : true;
626
+ feat.unlocked = feat.unlocked ?? true;
607
627
  const revision = (0, deviceFeaturesUtils_1.parseRevision)(feat);
608
628
  feat.revision = revision;
609
629
  if (!feat.model && feat.major_version === 1) {
@@ -629,7 +649,7 @@ class Device extends utils_1.TypedEmitter {
629
649
  this._unavailableCapabilities = (0, deviceFeaturesUtils_1.getUnavailableCapabilities)(feat, (0, coinInfo_1.getAllNetworks)());
630
650
  this._firmwareStatus = (0, firmwareInfo_1.getFirmwareStatus)(feat);
631
651
  this._firmwareRelease = (0, firmwareInfo_1.getRelease)(feat);
632
- this.availableTranslations = (_c = (_b = this.firmwareRelease) === null || _b === void 0 ? void 0 : _b.translations) !== null && _c !== void 0 ? _c : [];
652
+ this.availableTranslations = this.firmwareRelease?.translations ?? [];
633
653
  }
634
654
  this._features = feat;
635
655
  this._featuresNeedsReload = false;
@@ -647,12 +667,12 @@ class Device extends utils_1.TypedEmitter {
647
667
  ? types_1.FirmwareType.BitcoinOnly
648
668
  : types_1.FirmwareType.Regular;
649
669
  }
650
- const deviceInfo = (_d = models_1.models[feat.internal_model]) !== null && _d !== void 0 ? _d : {
670
+ const deviceInfo = models_1.models[feat.internal_model] ?? {
651
671
  name: `Unknown ${feat.internal_model}`,
652
672
  colors: {},
653
673
  };
654
674
  this.name = deviceInfo.name;
655
- if (feat === null || feat === void 0 ? void 0 : feat.unit_color) {
675
+ if (feat?.unit_color) {
656
676
  const deviceUnitColor = feat.unit_color.toString();
657
677
  if (deviceUnitColor in deviceInfo.colors) {
658
678
  this.color = deviceInfo.colors[deviceUnitColor];
@@ -666,9 +686,8 @@ class Device extends utils_1.TypedEmitter {
666
686
  return !!this.unreadableError;
667
687
  }
668
688
  disconnect() {
669
- var _a;
670
689
  _log.debug('Disconnect cleanup');
671
- (_a = this.sessionDfd) === null || _a === void 0 ? void 0 : _a.reject(new Error());
690
+ this.sessionDfd?.reject(new Error());
672
691
  this.lastAcquiredHere = false;
673
692
  this.emitLifecycle(events_1.DEVICE.DISCONNECT);
674
693
  return this.interruptionFromUser(constants_1.ERRORS.TypedError('Device_Disconnected'));
@@ -746,12 +765,11 @@ class Device extends utils_1.TypedEmitter {
746
765
  return null;
747
766
  }
748
767
  async dispose() {
749
- var _a, _b;
750
768
  this.removeAllListeners();
751
769
  if (this.session && this.lastAcquiredHere) {
752
770
  try {
753
- await ((_a = this.cancelableAction) === null || _a === void 0 ? void 0 : _a.call(this));
754
- await ((_b = this.commands) === null || _b === void 0 ? void 0 : _b.cancel());
771
+ await this.cancelableAction?.();
772
+ await this.commands?.cancel();
755
773
  return this.transport.release({
756
774
  session: this.session,
757
775
  path: this.transportPath,
@@ -772,7 +790,6 @@ class Device extends utils_1.TypedEmitter {
772
790
  return 'normal';
773
791
  }
774
792
  toMessageObject() {
775
- var _a;
776
793
  const { name, uniquePath: path } = this;
777
794
  const base = { path, name };
778
795
  if (this.unreadableError) {
@@ -804,7 +821,7 @@ class Device extends utils_1.TypedEmitter {
804
821
  id: this.features.device_id,
805
822
  label,
806
823
  _state: this.getState(),
807
- state: (_a = this.getState()) === null || _a === void 0 ? void 0 : _a.staticSessionId,
824
+ state: this.getState()?.staticSessionId,
808
825
  status,
809
826
  mode: this.getMode(),
810
827
  color: this.color,
@@ -80,7 +80,11 @@ export declare class DeviceCommands {
80
80
  cancelWithFallback(): Promise<{
81
81
  readonly success: false;
82
82
  readonly error: "session not found";
83
- } | import("@trezor/transport/lib/types").Success<import("@trezor/protobuf").MessageFromTrezor> | import("@trezor/transport/lib/types").ErrorGeneric<"session not found" | "Network request failed" | "Wrong result type." | "other call in progress" | "Malformed protocol format" | "device disconnected during action" | "unexpected error" | "Aborted by timeout" | "Aborted by signal" | "This transport can not be used in this environment" | "device not found" | "Unable to open device" | "A transfer error has occurred."> | import("@trezor/transport/lib/types").Success<undefined> | undefined>;
83
+ } | import("@trezor/transport/lib/types").Success<import("@trezor/protobuf").MessageFromTrezor> | {
84
+ success: false;
85
+ error: "session not found" | "Network request failed" | "Wrong result type." | "other call in progress" | "Malformed protocol format" | "device disconnected during action" | "unexpected error" | "Aborted by timeout" | "Aborted by signal" | "This transport can not be used in this environment" | "device not found" | "Unable to open device" | "A transfer error has occurred.";
86
+ message?: string;
87
+ } | import("@trezor/transport/lib/types").Success<undefined> | undefined>;
84
88
  cancel(): Promise<void>;
85
89
  }
86
90
  export type TypedCall = DeviceCommands['typedCall'];
@@ -51,6 +51,11 @@ const filterForLog = (type, msg) => {
51
51
  return msg;
52
52
  };
53
53
  class DeviceCommands {
54
+ device;
55
+ transport;
56
+ transportSession;
57
+ disposed;
58
+ callPromise;
54
59
  constructor(device, transport, transportSession) {
55
60
  this.device = device;
56
61
  this.transport = transport;
@@ -234,7 +239,7 @@ class DeviceCommands {
234
239
  if (this.disposed) {
235
240
  throw constants_1.ERRORS.TypedError('Runtime', 'typedCall: DeviceCommands already disposed');
236
241
  }
237
- (0, schema_utils_1.Assert)(protobuf_1.MessagesSchema.MessageType.properties[type], msg !== null && msg !== void 0 ? msg : {});
242
+ (0, schema_utils_1.Assert)(protobuf_1.MessagesSchema.MessageType.properties[type], msg ?? {});
238
243
  const response = await this._commonCall(type, msg);
239
244
  try {
240
245
  assertType(response, resType);
@@ -372,7 +377,7 @@ class DeviceCommands {
372
377
  const { name, version } = this.transport;
373
378
  if (name === 'BridgeTransport' && !utils_1.versionUtils.isNewer(version, '2.0.28')) {
374
379
  try {
375
- await (0, utils_1.createTimeoutPromise)(1);
380
+ await (0, utils_1.resolveAfter)(1);
376
381
  await this.device.acquire();
377
382
  await (0, prompts_1.cancelPrompt)(this.device, false);
378
383
  }
@@ -45,6 +45,7 @@ export declare class DeviceList extends TypedEmitter<DeviceListEvents> implement
45
45
  }[];
46
46
  private readonly locks;
47
47
  private transportLock;
48
+ private readonly scheduledUpgradeChecks;
48
49
  constructor({ messages, priority, debug, _sessionsBackgroundUrl, manifest, }: ConstructorParams);
49
50
  private tryGetTransport;
50
51
  private getOrCreateTransport;
@@ -56,6 +57,7 @@ export declare class DeviceList extends TypedEmitter<DeviceListEvents> implement
56
57
  init(initParams?: InitParams): Promise<void>;
57
58
  private createInitPromise;
58
59
  private createReconnectDelay;
60
+ private scheduleUpgradeCheck;
59
61
  private selectTransport;
60
62
  private initializeTransport;
61
63
  private waitForDevices;
@@ -9,7 +9,6 @@ const Device_1 = require("./Device");
9
9
  const transportInfo_1 = require("../data/transportInfo");
10
10
  const types_1 = require("../types");
11
11
  const utils_2 = require("../types/utils");
12
- const abortablePromise_1 = require("../utils/abortablePromise");
13
12
  const debug_1 = require("../utils/debug");
14
13
  const createAuthPenaltyManager = (priority) => {
15
14
  const penalizedDevices = {};
@@ -68,6 +67,13 @@ const assertDeviceListConnected = deviceList => {
68
67
  };
69
68
  exports.assertDeviceListConnected = assertDeviceListConnected;
70
69
  class DeviceList extends utils_1.TypedEmitter {
70
+ transport = {};
71
+ transports = [];
72
+ devices = createDeviceCollection();
73
+ deviceCounter = Date.now();
74
+ handshakeLock;
75
+ authPenaltyManager;
76
+ transportCommonArgs;
71
77
  isConnected() {
72
78
  return !!Object.keys(this.transport).length;
73
79
  }
@@ -81,13 +87,13 @@ class DeviceList extends utils_1.TypedEmitter {
81
87
  getActiveTransports() {
82
88
  return Object.values(this.transport).map(getTransportInfo);
83
89
  }
90
+ locks = {};
84
91
  async transportLock(apiType, abortMessage, action) {
85
- var _a, _b;
86
- const lock = (_a = this.locks[apiType]) !== null && _a !== void 0 ? _a : (this.locks[apiType] = { sequence: 0 });
92
+ const lock = this.locks[apiType] ?? (this.locks[apiType] = { sequence: 0 });
87
93
  lock.abortMessage = abortMessage;
88
94
  const sequence = ++lock.sequence;
89
95
  while (lock.promise) {
90
- (_b = lock.abort) === null || _b === void 0 ? void 0 : _b.abort(new Error(abortMessage));
96
+ lock.abort?.abort(new Error(abortMessage));
91
97
  await lock.promise.catch(() => { });
92
98
  }
93
99
  if (sequence !== lock.sequence)
@@ -99,13 +105,9 @@ class DeviceList extends utils_1.TypedEmitter {
99
105
  });
100
106
  return lock.promise;
101
107
  }
108
+ scheduledUpgradeChecks = {};
102
109
  constructor({ messages, priority, debug, _sessionsBackgroundUrl, manifest, }) {
103
110
  super();
104
- this.transport = {};
105
- this.transports = [];
106
- this.devices = createDeviceCollection();
107
- this.deviceCounter = Date.now();
108
- this.locks = {};
109
111
  const transportLogger = (0, debug_1.initLog)('@trezor/transport', debug);
110
112
  this.handshakeLock = (0, utils_1.getSynchronize)();
111
113
  this.authPenaltyManager = createAuthPenaltyManager(priority);
@@ -113,14 +115,13 @@ class DeviceList extends utils_1.TypedEmitter {
113
115
  messages,
114
116
  logger: transportLogger,
115
117
  sessionsBackgroundUrl: _sessionsBackgroundUrl,
116
- id: (manifest === null || manifest === void 0 ? void 0 : manifest.appUrl) || 'unknown app',
118
+ id: manifest?.appUrl || 'unknown app',
117
119
  };
118
120
  }
119
121
  tryGetTransport(name) {
120
122
  return this.transports.find(t => t.name === name);
121
123
  }
122
124
  getOrCreateTransport(transportType) {
123
- var _a;
124
125
  const { transportCommonArgs } = this;
125
126
  if (typeof transportType === 'string') {
126
127
  const existing = this.tryGetTransport(transportType);
@@ -143,7 +144,7 @@ class DeviceList extends utils_1.TypedEmitter {
143
144
  else if (typeof transportType === 'function' && 'prototype' in transportType) {
144
145
  const transportInstance = new transportType(transportCommonArgs);
145
146
  if ((0, transport_1.isTransportInstance)(transportInstance)) {
146
- return (_a = this.tryGetTransport(transportInstance.name)) !== null && _a !== void 0 ? _a : transportInstance;
147
+ return this.tryGetTransport(transportInstance.name) ?? transportInstance;
147
148
  }
148
149
  }
149
150
  else if ((0, transport_1.isTransportInstance)(transportType)) {
@@ -158,7 +159,7 @@ class DeviceList extends utils_1.TypedEmitter {
158
159
  throw constants_1.ERRORS.TypedError('Runtime', `DeviceList.init: transports[] of unexpected type: ${transportType}`);
159
160
  }
160
161
  createTransports(transports) {
161
- const transportTypes = (transports === null || transports === void 0 ? void 0 : transports.length) ? transports : ['BridgeTransport'];
162
+ const transportTypes = transports?.length ? transports : ['BridgeTransport'];
162
163
  return transportTypes.map(this.getOrCreateTransport.bind(this));
163
164
  }
164
165
  onDeviceConnected(descriptor, transport) {
@@ -179,15 +180,15 @@ class DeviceList extends utils_1.TypedEmitter {
179
180
  }
180
181
  onDeviceDisconnected(descriptor, transport) {
181
182
  const device = this.devices.remove(descriptor.path, transport);
182
- device === null || device === void 0 ? void 0 : device.disconnect();
183
+ device?.disconnect();
183
184
  }
184
185
  onDeviceSessionChanged(descriptor, transport) {
185
186
  const device = this.devices.get(descriptor.path, transport);
186
- device === null || device === void 0 ? void 0 : device.updateDescriptor(descriptor);
187
+ device?.updateDescriptor(descriptor);
187
188
  }
188
189
  onDeviceRequestRelease(descriptor, transport) {
189
190
  const device = this.devices.get(descriptor.path, transport);
190
- device === null || device === void 0 ? void 0 : device.usedElsewhere();
191
+ device?.usedElsewhere();
191
192
  }
192
193
  async init(initParams = {}) {
193
194
  this.transports = this.createTransports(initParams.transports);
@@ -237,9 +238,12 @@ class DeviceList extends utils_1.TypedEmitter {
237
238
  this.emit(transport_1.TRANSPORT.START, getTransportInfo(transport));
238
239
  }
239
240
  }
241
+ if (transport && transport !== transports[0]) {
242
+ this.scheduleUpgradeCheck(apiType, initParams);
243
+ }
240
244
  }
241
245
  catch (error) {
242
- this.emit(transport_1.TRANSPORT.ERROR, { apiType, error: error === null || error === void 0 ? void 0 : error.message });
246
+ this.emit(transport_1.TRANSPORT.ERROR, { apiType, error: error?.message });
243
247
  if (initParams.transportReconnect && !abortSignal.aborted) {
244
248
  this.transportLock(apiType, 'Reconnecting', async (signal) => {
245
249
  await this.createReconnectDelay(signal);
@@ -249,9 +253,25 @@ class DeviceList extends utils_1.TypedEmitter {
249
253
  }
250
254
  }
251
255
  createReconnectDelay(signal) {
252
- const { promise, resolve } = (0, abortablePromise_1.abortablePromise)(signal);
253
- const timeout = setTimeout(resolve, 1000);
254
- return promise.finally(() => clearTimeout(timeout));
256
+ return (0, utils_1.resolveAfter)(1000, signal);
257
+ }
258
+ scheduleUpgradeCheck(apiType, initParams) {
259
+ clearTimeout(this.scheduledUpgradeChecks[apiType]);
260
+ this.scheduledUpgradeChecks[apiType] = setTimeout(async () => {
261
+ const transport = this.transport[apiType];
262
+ const transports = this.transports.filter(t => t.apiType === apiType);
263
+ if (!transport || transport === transports[0])
264
+ return;
265
+ for (const t of transports) {
266
+ if (t === transport)
267
+ break;
268
+ if (await t.ping()) {
269
+ this.transportLock(apiType, 'Upgrading', signal => this.createInitPromise(apiType, initParams, signal)).catch(() => { });
270
+ return;
271
+ }
272
+ }
273
+ this.scheduleUpgradeCheck(apiType, initParams);
274
+ }, 1000);
255
275
  }
256
276
  async selectTransport([transport, ...rest], signal) {
257
277
  if (signal.aborted)
@@ -324,7 +344,7 @@ class DeviceList extends utils_1.TypedEmitter {
324
344
  }
325
345
  getDeviceByStaticState(state) {
326
346
  const deviceId = state.split('@')[1].split(':')[0];
327
- return this.devices.all().find(d => { var _a; return ((_a = d.features) === null || _a === void 0 ? void 0 : _a.device_id) === deviceId; });
347
+ return this.devices.all().find(d => d.features?.device_id === deviceId);
328
348
  }
329
349
  async dispose() {
330
350
  this.removeAllListeners();
@@ -341,6 +361,7 @@ class DeviceList extends utils_1.TypedEmitter {
341
361
  await Promise.all(promises);
342
362
  }
343
363
  async stopTransport(transport) {
364
+ clearTimeout(this.scheduledUpgradeChecks[transport.apiType]);
344
365
  const devices = this.devices.clear(transport);
345
366
  devices.forEach(device => {
346
367
  this.emit(events_1.DEVICE.DISCONNECT, device);
@@ -349,7 +370,7 @@ class DeviceList extends utils_1.TypedEmitter {
349
370
  this.authPenaltyManager.remove(device);
350
371
  await device.dispose();
351
372
  }));
352
- transport === null || transport === void 0 ? void 0 : transport.stop();
373
+ transport?.stop();
353
374
  }
354
375
  async enumerate() {
355
376
  const promises = Object.values(this.transport).map(async (transport) => {
@@ -358,8 +379,7 @@ class DeviceList extends utils_1.TypedEmitter {
358
379
  return;
359
380
  }
360
381
  res.payload.forEach(d => {
361
- var _a;
362
- (_a = this.devices.get(d.path, transport)) === null || _a === void 0 ? void 0 : _a.updateDescriptor(d);
382
+ this.devices.get(d.path, transport)?.updateDescriptor(d);
363
383
  });
364
384
  });
365
385
  await Promise.all(promises);
@@ -3,15 +3,15 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.WebextensionStateStorage = void 0;
4
4
  const connect_common_1 = require("@trezor/connect-common");
5
5
  class WebextensionStateStorage {
6
+ origin;
6
7
  constructor(origin) {
7
8
  this.origin = origin;
8
9
  }
9
10
  loadState(device) {
10
- var _a;
11
- if (!((_a = device.getState()) === null || _a === void 0 ? void 0 : _a.sessionId)) {
11
+ if (!device.getState()?.sessionId) {
12
12
  const { preferredDevice } = connect_common_1.storage.loadForOrigin(this.origin) || {};
13
- if ((preferredDevice === null || preferredDevice === void 0 ? void 0 : preferredDevice.internalState) &&
14
- (preferredDevice === null || preferredDevice === void 0 ? void 0 : preferredDevice.internalStateExpiration) &&
13
+ if (preferredDevice?.internalState &&
14
+ preferredDevice?.internalStateExpiration &&
15
15
  preferredDevice.internalStateExpiration > new Date().getTime()) {
16
16
  return { sessionId: preferredDevice.internalState };
17
17
  }
@@ -19,8 +19,7 @@ class WebextensionStateStorage {
19
19
  return undefined;
20
20
  }
21
21
  saveState(device, state) {
22
- var _a;
23
- const expirationDelay = Math.max(1000 * 60 * 15, (_a = device.features.auto_lock_delay_ms) !== null && _a !== void 0 ? _a : 0);
22
+ const expirationDelay = Math.max(1000 * 60 * 15, device.features.auto_lock_delay_ms ?? 0);
24
23
  connect_common_1.storage.saveForOrigin(store => ({
25
24
  ...store,
26
25
  preferredDevice: store.preferredDevice
@@ -4,7 +4,13 @@ exports.checkFirmwareRevision = void 0;
4
4
  const versionUtils_1 = require("@trezor/utils/lib/versionUtils");
5
5
  const downloadReleasesMetadata_1 = require("../data/downloadReleasesMetadata");
6
6
  const calculateRevisionForDevice_1 = require("./calculateRevisionForDevice");
7
- const NODE_FETCH_OFFLINE_ERROR_NAMES = ['FetchError', 'AbortError'];
7
+ const isNodeJSNetworkError = (e) => ['FetchError', 'AbortError'].includes(e.name);
8
+ const isReactNativeNetworkError = (e) => e.name === 'TypeError' && e.message.includes('Network request failed');
9
+ const isNetworkError = (e) => {
10
+ if (!(e instanceof Error))
11
+ return false;
12
+ return isNodeJSNetworkError(e) || isReactNativeNetworkError(e);
13
+ };
8
14
  const getOnlineReleaseMetadata = async ({ firmwareVersion, internalModel, }) => {
9
15
  const onlineReleases = await (0, downloadReleasesMetadata_1.downloadReleasesMetadata)({ internal_model: internalModel });
10
16
  return onlineReleases.find(onlineRelease => (0, versionUtils_1.isEqual)(onlineRelease.version, firmwareVersion));
@@ -30,7 +36,7 @@ const checkFirmwareRevision = async ({ firmwareVersion, internalModel, deviceRev
30
36
  firmwareVersion,
31
37
  internalModel,
32
38
  });
33
- if ((onlineRelease === null || onlineRelease === void 0 ? void 0 : onlineRelease.firmware_revision) === undefined) {
39
+ if (onlineRelease?.firmware_revision === undefined) {
34
40
  return failFirmwareRevisionCheck('firmware-version-unknown');
35
41
  }
36
42
  if (!doRevisionsMatch({
@@ -43,10 +49,9 @@ const checkFirmwareRevision = async ({ firmwareVersion, internalModel, deviceRev
43
49
  return { success: true };
44
50
  }
45
51
  catch (e) {
46
- if (NODE_FETCH_OFFLINE_ERROR_NAMES.includes(e.name)) {
47
- return failFirmwareRevisionCheck('cannot-perform-check-offline');
48
- }
49
- return failFirmwareRevisionCheck('other-error');
52
+ return isNetworkError(e)
53
+ ? failFirmwareRevisionCheck('cannot-perform-check-offline')
54
+ : failFirmwareRevisionCheck('other-error');
50
55
  }
51
56
  }
52
57
  if (!doRevisionsMatch({