@trezor/connect 9.0.11 → 9.1.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 (61) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/README.md +19 -2
  3. package/lib/api/bitcoin/createPendingTx.d.ts +1 -0
  4. package/lib/api/bitcoin/createPendingTx.js +1 -0
  5. package/lib/api/cancelCoinjoinAuthorization.d.ts +7 -0
  6. package/lib/api/cancelCoinjoinAuthorization.js +25 -0
  7. package/lib/api/cardanoGetPublicKey.d.ts +1 -0
  8. package/lib/api/cardanoGetPublicKey.js +9 -0
  9. package/lib/api/cipherKeyValue.js +3 -2
  10. package/lib/api/getAccountInfo.d.ts +2 -0
  11. package/lib/api/getPublicKey.d.ts +1 -0
  12. package/lib/api/getPublicKey.js +9 -0
  13. package/lib/api/index.d.ts +2 -0
  14. package/lib/api/index.js +6 -2
  15. package/lib/api/rebootToBootloader.js +1 -1
  16. package/lib/api/showDeviceTutorial.d.ts +7 -0
  17. package/lib/api/showDeviceTutorial.js +21 -0
  18. package/lib/constants/errors.d.ts +0 -3
  19. package/lib/constants/errors.js +1 -4
  20. package/lib/core/index.d.ts +5 -6
  21. package/lib/core/index.js +44 -50
  22. package/lib/core/method.d.ts +1 -1
  23. package/lib/data/coinInfo.d.ts +0 -1
  24. package/lib/data/coinInfo.js +7 -14
  25. package/lib/data/config.js +7 -1
  26. package/lib/data/version.d.ts +1 -1
  27. package/lib/data/version.js +1 -1
  28. package/lib/device/Device.d.ts +8 -10
  29. package/lib/device/Device.js +60 -95
  30. package/lib/device/DeviceCommands.d.ts +4 -3
  31. package/lib/device/DeviceCommands.js +40 -18
  32. package/lib/device/DeviceList.d.ts +15 -25
  33. package/lib/device/DeviceList.js +224 -258
  34. package/lib/events/transport.d.ts +2 -9
  35. package/lib/events/transport.js +3 -10
  36. package/lib/factory.js +2 -0
  37. package/lib/index.js +7 -7
  38. package/lib/types/api/cancelCoinjoinAuthorization.d.ts +8 -0
  39. package/lib/types/api/cancelCoinjoinAuthorization.js +3 -0
  40. package/lib/types/api/index.d.ts +4 -0
  41. package/lib/types/api/showDeviceTutorial.d.ts +4 -0
  42. package/lib/types/api/showDeviceTutorial.js +3 -0
  43. package/lib/types/device.d.ts +1 -1
  44. package/lib/types/device.js +3 -0
  45. package/lib/types/settings.d.ts +1 -1
  46. package/lib/utils/debug.js +2 -1
  47. package/lib/utils/deviceFeaturesUtils.d.ts +2 -1
  48. package/lib/utils/deviceFeaturesUtils.js +12 -1
  49. package/lib/workers/workers-browser.d.ts +1 -3
  50. package/lib/workers/workers-browser.js +1 -7
  51. package/lib/workers/workers-react-native.d.ts +1 -3
  52. package/lib/workers/workers-react-native.js +1 -7
  53. package/lib/workers/workers.d.ts +1 -5
  54. package/lib/workers/workers.js +1 -5
  55. package/package.json +15 -12
  56. package/lib/device/DescriptorStream.d.ts +0 -28
  57. package/lib/device/DescriptorStream.js +0 -139
  58. package/lib/utils/objectUtils.d.ts +0 -10
  59. package/lib/utils/objectUtils.js +0 -37
  60. package/lib/workers/RNUsbPlugin.d.ts +0 -31
  61. package/lib/workers/RNUsbPlugin.js +0 -65
@@ -1,21 +1,14 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getAllNetworks = exports.getUniqueNetworks = exports.parseCoinsJson = exports.getCoinName = exports.getCoinInfo = exports.getCoinInfoByHash = exports.fixCoinInfoNetwork = exports.getBech32Network = exports.getSegwitNetwork = exports.getMiscNetwork = exports.getEthereumNetwork = exports.getBitcoinNetwork = exports.cloneCoinInfo = void 0;
3
+ exports.getAllNetworks = exports.getUniqueNetworks = exports.parseCoinsJson = exports.getCoinName = exports.getCoinInfo = exports.getCoinInfoByHash = exports.fixCoinInfoNetwork = exports.getBech32Network = exports.getSegwitNetwork = exports.getMiscNetwork = exports.getEthereumNetwork = exports.getBitcoinNetwork = void 0;
4
4
  const constants_1 = require("../constants");
5
5
  const pathUtils_1 = require("../utils/pathUtils");
6
+ const utils_1 = require("@trezor/utils");
6
7
  const bitcoinNetworks = [];
7
8
  const ethereumNetworks = [];
8
9
  const miscNetworks = [];
9
- function cloneCoinInfo(info) {
10
- const jsonString = JSON.stringify(info);
11
- if (jsonString === undefined) {
12
- return info;
13
- }
14
- return JSON.parse(jsonString);
15
- }
16
- exports.cloneCoinInfo = cloneCoinInfo;
17
10
  const getBitcoinNetwork = (pathOrName) => {
18
- const networks = cloneCoinInfo(bitcoinNetworks);
11
+ const networks = (0, utils_1.cloneObject)(bitcoinNetworks);
19
12
  if (typeof pathOrName === 'string') {
20
13
  const name = pathOrName.toLowerCase();
21
14
  return networks.find(n => n.name.toLowerCase() === name ||
@@ -27,7 +20,7 @@ const getBitcoinNetwork = (pathOrName) => {
27
20
  };
28
21
  exports.getBitcoinNetwork = getBitcoinNetwork;
29
22
  const getEthereumNetwork = (pathOrName) => {
30
- const networks = cloneCoinInfo(ethereumNetworks);
23
+ const networks = (0, utils_1.cloneObject)(ethereumNetworks);
31
24
  if (typeof pathOrName === 'string') {
32
25
  const name = pathOrName.toLowerCase();
33
26
  return networks.find(n => n.name.toLowerCase() === name || n.shortcut.toLowerCase() === name);
@@ -37,7 +30,7 @@ const getEthereumNetwork = (pathOrName) => {
37
30
  };
38
31
  exports.getEthereumNetwork = getEthereumNetwork;
39
32
  const getMiscNetwork = (pathOrName) => {
40
- const networks = cloneCoinInfo(miscNetworks);
33
+ const networks = (0, utils_1.cloneObject)(miscNetworks);
41
34
  if (typeof pathOrName === 'string') {
42
35
  const name = pathOrName.toLowerCase();
43
36
  return networks.find(n => n.name.toLowerCase() === name || n.shortcut.toLowerCase() === name);
@@ -73,7 +66,7 @@ const getBech32Network = (coin) => {
73
66
  };
74
67
  exports.getBech32Network = getBech32Network;
75
68
  const fixCoinInfoNetwork = (ci, path) => {
76
- const coinInfo = cloneCoinInfo(ci);
69
+ const coinInfo = (0, utils_1.cloneObject)(ci);
77
70
  if (path[0] === (0, pathUtils_1.toHardened)(84)) {
78
71
  const bech32Network = (0, exports.getBech32Network)(coinInfo);
79
72
  if (bech32Network) {
@@ -108,7 +101,7 @@ const detectBtcVersion = (data) => {
108
101
  return 'btc';
109
102
  };
110
103
  const getCoinInfoByHash = (hash, networkInfo) => {
111
- const networks = cloneCoinInfo(bitcoinNetworks);
104
+ const networks = (0, utils_1.cloneObject)(bitcoinNetworks);
112
105
  const result = networks.find(info => hash.toLowerCase() === info.hashGenesisBlock.toLowerCase());
113
106
  if (!result) {
114
107
  throw constants_1.ERRORS.TypedError('Method_UnknownCoin', `Coin info not found for hash: ${hash} ${networkInfo.hashGenesisBlock}`);
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.config = void 0;
4
4
  const constants_1 = require("@trezor/transport/lib/constants");
5
5
  exports.config = {
6
- webusb: constants_1.TREZOR_DESCS,
6
+ webusb: constants_1.TREZOR_USB_DESCRIPTORS,
7
7
  whitelist: [
8
8
  { origin: 'chrome-extension://imloifkgjagghnncjkhggdhalmcnfklk', priority: 1 },
9
9
  { origin: 'chrome-extension://niebkpllfhmpfbffbfifagfgoamhpflf', priority: 1 },
@@ -184,6 +184,7 @@ exports.config = {
184
184
  capabilities: ['coinjoin'],
185
185
  methods: [
186
186
  'authorizeCoinjoin',
187
+ 'cancelCoinjoinAuthorization',
187
188
  'getOwnershipId',
188
189
  'getOwnershipProof',
189
190
  'setBusy',
@@ -191,6 +192,11 @@ exports.config = {
191
192
  ],
192
193
  min: ['1.12.1', '2.5.3'],
193
194
  },
195
+ {
196
+ methods: ['showDeviceTutorial'],
197
+ min: ['0', '2.6.1'],
198
+ comment: ['Only on T2B1'],
199
+ },
194
200
  ],
195
201
  };
196
202
  //# sourceMappingURL=config.js.map
@@ -1,3 +1,3 @@
1
- export declare const VERSION = "9.0.11";
1
+ export declare const VERSION = "9.1.1";
2
2
  export declare const DEFAULT_DOMAIN: string;
3
3
  //# sourceMappingURL=version.d.ts.map
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.DEFAULT_DOMAIN = exports.VERSION = void 0;
4
- exports.VERSION = '9.0.11';
4
+ exports.VERSION = '9.1.1';
5
5
  const versionN = exports.VERSION.split('.').map(s => parseInt(s, 10));
6
6
  exports.DEFAULT_DOMAIN = `https://connect.trezor.io/${versionN[0]}/`;
7
7
  //# sourceMappingURL=version.js.map
@@ -3,7 +3,7 @@ import { DeviceCommands } from './DeviceCommands';
3
3
  import { PROTO, NETWORK } from '../constants';
4
4
  import { DEVICE, DeviceButtonRequestPayload } from '../events';
5
5
  import { Deferred } from '../utils/deferred';
6
- import type { Transport, TrezorDeviceInfoWithSession as DeviceDescriptor } from '@trezor/transport';
6
+ import type { Transport, Descriptor } from '@trezor/transport';
7
7
  import type { Device as DeviceTyped, DeviceFirmwareStatus, Features, ReleaseInfo, UnavailableCapabilities } from '../types';
8
8
  export type RunOptions = {
9
9
  skipFinalReload?: boolean;
@@ -24,15 +24,14 @@ export interface DeviceEvents {
24
24
  }
25
25
  export declare class Device extends TypedEmitter<DeviceEvents> {
26
26
  transport: Transport;
27
- originalDescriptor: DeviceDescriptor;
27
+ originalDescriptor: Descriptor;
28
28
  unreadableError?: string;
29
29
  firmwareStatus: DeviceFirmwareStatus;
30
30
  firmwareRelease?: ReleaseInfo | null;
31
31
  features: Features;
32
32
  featuresNeedsReload: boolean;
33
- deferredActions: {
34
- [key: string]: Deferred<void>;
35
- };
33
+ acquirePromise?: ReturnType<Transport['acquire']>;
34
+ releasePromise?: ReturnType<Transport['release']>;
36
35
  runPromise?: Deferred<void> | null;
37
36
  loaded: boolean;
38
37
  inconsistent: boolean;
@@ -46,9 +45,9 @@ export declare class Device extends TypedEmitter<DeviceEvents> {
46
45
  unavailableCapabilities: UnavailableCapabilities;
47
46
  networkTypeState: NETWORK.NetworkType[];
48
47
  firmwareType: 'regular' | 'bitcoin-only';
49
- constructor(transport: Transport, descriptor: DeviceDescriptor);
50
- static fromDescriptor(transport: Transport, originalDescriptor: DeviceDescriptor): Device;
51
- static createUnacquired(transport: Transport, descriptor: DeviceDescriptor, unreadableError?: string): Device;
48
+ constructor(transport: Transport, descriptor: Descriptor);
49
+ static fromDescriptor(transport: Transport, originalDescriptor: Descriptor): Device;
50
+ static createUnacquired(transport: Transport, descriptor: Descriptor, unreadableError?: string): Device;
52
51
  acquire(): Promise<void>;
53
52
  release(): Promise<void>;
54
53
  cleanup(): Promise<void>;
@@ -70,7 +69,6 @@ export declare class Device extends TypedEmitter<DeviceEvents> {
70
69
  getFeatures(): Promise<void>;
71
70
  _updateFeatures(feat: Features): void;
72
71
  isUnacquired(): boolean;
73
- updateDescriptor(upcomingDescriptor: DeviceDescriptor): Promise<void>;
74
72
  disconnect(): void;
75
73
  isBootloader(): boolean;
76
74
  isInitialized(): boolean;
@@ -87,7 +85,7 @@ export declare class Device extends TypedEmitter<DeviceEvents> {
87
85
  getDevicePath(): string;
88
86
  isT1(): boolean;
89
87
  hasUnexpectedMode(allow: string[], require: string[]): "ui-device_bootloader_mode" | "ui-device_not_in_bootloader_mode" | "ui-device_not_initialized" | "ui-device_seedless" | null;
90
- dispose(): Promise<void> | undefined;
88
+ dispose(): import("packages/transport/lib/types").AbortableCall<void, "Network request failed" | "Wrong result type." | "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" | "wrong previous session" | "session not found"> | undefined;
91
89
  getMode(): "normal" | "bootloader" | "initialize" | "seedless";
92
90
  toMessageObject(): DeviceTyped;
93
91
  _getNetworkTypeState(): "bitcoin" | "ethereum" | "nem" | "eos" | "stellar" | "cardano" | "ripple" | "tezos" | "binance";
@@ -21,7 +21,8 @@ class Device extends typedEventEmitter_1.TypedEmitter {
21
21
  constructor(transport, descriptor) {
22
22
  super();
23
23
  this.featuresNeedsReload = false;
24
- this.deferredActions = {};
24
+ this.acquirePromise = undefined;
25
+ this.releasePromise = undefined;
25
26
  this.loaded = false;
26
27
  this.inconsistent = false;
27
28
  this.keepSession = false;
@@ -52,54 +53,53 @@ class Device extends typedEventEmitter_1.TypedEmitter {
52
53
  return device;
53
54
  }
54
55
  async acquire() {
55
- this.deferredActions[events_1.DEVICE.ACQUIRE] = (0, deferred_1.create)();
56
- this.deferredActions[events_1.DEVICE.ACQUIRED] = (0, deferred_1.create)();
57
- try {
58
- const sessionID = await this.transport.acquire({
56
+ this.acquirePromise = this.transport.acquire({
57
+ input: {
59
58
  path: this.originalDescriptor.path,
60
59
  previous: this.originalDescriptor.session,
61
- }, false);
62
- _log.debug('Expected session id:', sessionID);
63
- this.activitySessionID = sessionID;
64
- this.deferredActions[events_1.DEVICE.ACQUIRED].resolve();
65
- delete this.deferredActions[events_1.DEVICE.ACQUIRED];
66
- if (this.commands) {
67
- this.commands.dispose();
68
- }
69
- this.commands = new DeviceCommands_1.DeviceCommands(this, this.transport, sessionID);
70
- this.deferredActions[events_1.DEVICE.RELEASE] = (0, deferred_1.create)();
71
- }
72
- catch (error) {
73
- this.deferredActions[events_1.DEVICE.ACQUIRED].resolve();
74
- delete this.deferredActions[events_1.DEVICE.ACQUIRED];
60
+ },
61
+ });
62
+ const acquireResult = await this.acquirePromise.promise;
63
+ this.acquirePromise = undefined;
64
+ if (!acquireResult.success) {
75
65
  if (this.runPromise) {
76
- this.runPromise.reject(error);
77
- }
78
- else {
79
- throw error;
66
+ this.runPromise.reject(new Error(acquireResult.error));
67
+ this.runPromise = null;
80
68
  }
81
- this.runPromise = null;
69
+ throw acquireResult.error;
70
+ }
71
+ const sessionID = acquireResult.payload;
72
+ _log.debug('Expected session id:', sessionID);
73
+ this.activitySessionID = sessionID;
74
+ this.originalDescriptor.session = sessionID;
75
+ if (this.commands) {
76
+ this.commands.dispose();
82
77
  }
78
+ this.commands = new DeviceCommands_1.DeviceCommands(this, this.transport, sessionID);
83
79
  }
84
80
  async release() {
85
- if (this.isUsedHere() && !this.keepSession && this.activitySessionID) {
81
+ if (this.isUsedHere() &&
82
+ !this.keepSession &&
83
+ this.activitySessionID &&
84
+ !this.releasePromise) {
86
85
  if (this.commands) {
87
86
  this.commands.dispose();
88
87
  if (this.commands.callPromise) {
89
- try {
90
- await this.commands.callPromise;
91
- }
92
- catch (error) {
93
- this.commands.callPromise = undefined;
94
- }
88
+ await this.commands.callPromise.promise;
95
89
  }
96
90
  }
97
- try {
98
- await this.transport.release(this.activitySessionID, false, false);
99
- if (this.deferredActions[events_1.DEVICE.RELEASE])
100
- await this.deferredActions[events_1.DEVICE.RELEASE].promise;
91
+ if (this.releasePromise) {
92
+ await this.releasePromise;
101
93
  }
102
- catch (err) {
94
+ this.releasePromise = this.transport.release({
95
+ session: this.activitySessionID,
96
+ path: this.originalDescriptor.path,
97
+ });
98
+ const releaseResponse = await this.releasePromise.promise;
99
+ this.releasePromise = undefined;
100
+ if (releaseResponse.success) {
101
+ this.activitySessionID = null;
102
+ this.originalDescriptor.session = null;
103
103
  }
104
104
  }
105
105
  }
@@ -118,26 +118,25 @@ class Device extends typedEventEmitter_1.TypedEmitter {
118
118
  return this.runPromise.promise;
119
119
  }
120
120
  async override(error) {
121
- if (this.deferredActions[events_1.DEVICE.ACQUIRE]) {
122
- await this.deferredActions[events_1.DEVICE.ACQUIRE].promise;
121
+ if (this.acquirePromise) {
122
+ await this.acquirePromise.promise;
123
123
  }
124
124
  if (this.runPromise) {
125
125
  await this.interruptionFromUser(error);
126
126
  }
127
- if (!this.keepSession && this.deferredActions[events_1.DEVICE.RELEASE]) {
128
- await this.deferredActions[events_1.DEVICE.RELEASE].promise;
127
+ if (this.releasePromise) {
128
+ await this.releasePromise.promise;
129
129
  }
130
130
  }
131
131
  async interruptionFromUser(error) {
132
132
  _log.debug('interruptionFromUser');
133
- if (this.commands) {
134
- await this.commands.cancel();
135
- this.commands.dispose();
136
- }
137
133
  if (this.runPromise) {
138
134
  this.runPromise.reject(error);
139
135
  this.runPromise = null;
140
136
  }
137
+ if (this.commands) {
138
+ await this.commands.cancel();
139
+ }
141
140
  }
142
141
  interruptionFromOutside() {
143
142
  _log.debug('interruptionFromOutside');
@@ -148,9 +147,13 @@ class Device extends typedEventEmitter_1.TypedEmitter {
148
147
  this.runPromise.reject(constants_1.ERRORS.TypedError('Device_UsedElsewhere'));
149
148
  this.runPromise = null;
150
149
  }
150
+ this.transport.releaseDevice(this.originalDescriptor.path);
151
151
  }
152
152
  async _runInner(fn, options) {
153
153
  var _a;
154
+ if (this.releasePromise) {
155
+ await this.releasePromise.promise;
156
+ }
154
157
  if (!this.isUsedHere() || ((_a = this.commands) === null || _a === void 0 ? void 0 : _a.disposed) || !this.getExternalState()) {
155
158
  await this.acquire();
156
159
  try {
@@ -170,15 +173,16 @@ class Device extends typedEventEmitter_1.TypedEmitter {
170
173
  return this._runInner(() => Promise.resolve({}), options);
171
174
  }
172
175
  this.inconsistent = true;
173
- await this.deferredActions[events_1.DEVICE.ACQUIRE].promise;
174
176
  this.runPromise = null;
175
- return Promise.reject(constants_1.ERRORS.TypedError('Device_InitializeFailed', `Initialize failed: ${error.message}, code: ${error.code}`));
177
+ return Promise.reject(constants_1.ERRORS.TypedError('Device_InitializeFailed', `Initialize failed: ${error.message} ${error.code ? `, code: ${error.code}` : ''}`));
176
178
  }
177
179
  }
178
180
  if (options.keepSession) {
179
181
  this.keepSession = true;
180
182
  }
181
- await this.deferredActions[events_1.DEVICE.ACQUIRE].promise;
183
+ if (this.listeners(events_1.DEVICE.ACQUIRED).length > 0) {
184
+ this.emit(events_1.DEVICE.ACQUIRED);
185
+ }
182
186
  if (fn) {
183
187
  await fn();
184
188
  }
@@ -315,6 +319,9 @@ class Device extends typedEventEmitter_1.TypedEmitter {
315
319
  if (!feat.model && feat.major_version === 1) {
316
320
  feat.model = '1';
317
321
  }
322
+ if (!feat.internal_model) {
323
+ feat.internal_model = (0, deviceFeaturesUtils_1.ensureInternalModelFeature)(feat.model);
324
+ }
318
325
  this.features = feat;
319
326
  this.featuresNeedsReload = false;
320
327
  this.firmwareType =
@@ -327,55 +334,9 @@ class Device extends typedEventEmitter_1.TypedEmitter {
327
334
  isUnacquired() {
328
335
  return this.features === undefined;
329
336
  }
330
- async updateDescriptor(upcomingDescriptor) {
331
- const originalSession = this.originalDescriptor.session;
332
- const upcomingSession = upcomingDescriptor.session;
333
- _log.debug('updateDescriptor', 'currentSession', originalSession, 'upcoming', upcomingSession, 'lastUsedID', this.activitySessionID);
334
- if (!originalSession && !upcomingSession && !this.activitySessionID) {
335
- return;
336
- }
337
- if (this.deferredActions[events_1.DEVICE.ACQUIRED]) {
338
- await this.deferredActions[events_1.DEVICE.ACQUIRED].promise;
339
- }
340
- if (!upcomingSession) {
341
- if (this.listeners(events_1.DEVICE.ACQUIRED).length > 0) {
342
- this.emit(events_1.DEVICE.ACQUIRED);
343
- }
344
- }
345
- const methodStillRunning = this.commands && !this.commands.disposed;
346
- if (!upcomingSession && !methodStillRunning) {
347
- if (originalSession === this.activitySessionID) {
348
- _log.debug('Session released by this app');
349
- if (this.deferredActions[events_1.DEVICE.RELEASE]) {
350
- this.deferredActions[events_1.DEVICE.RELEASE].resolve();
351
- delete this.deferredActions[events_1.DEVICE.RELEASE];
352
- }
353
- this.activitySessionID = null;
354
- }
355
- else {
356
- _log.debug('Session released by other app');
357
- this.featuresNeedsReload = true;
358
- }
359
- this.keepSession = false;
360
- }
361
- else if (upcomingSession === this.activitySessionID) {
362
- _log.debug('Session acquired by this app');
363
- if (this.deferredActions[events_1.DEVICE.ACQUIRE]) {
364
- this.deferredActions[events_1.DEVICE.ACQUIRE].resolve();
365
- }
366
- }
367
- else {
368
- _log.debug('Session acquired by other app');
369
- this.interruptionFromOutside();
370
- }
371
- this.originalDescriptor = upcomingDescriptor;
372
- }
373
337
  disconnect() {
374
338
  _log.debug('Disconnect cleanup');
375
- if (this.deferredActions[events_1.DEVICE.RELEASE]) {
376
- this.deferredActions[events_1.DEVICE.RELEASE].resolve();
377
- delete this.deferredActions[events_1.DEVICE.RELEASE];
378
- }
339
+ this.activitySessionID = null;
379
340
  this.interruptionFromUser(constants_1.ERRORS.TypedError('Device_Disconnected'));
380
341
  this.runPromise = null;
381
342
  }
@@ -454,7 +415,11 @@ class Device extends typedEventEmitter_1.TypedEmitter {
454
415
  if (this.commands) {
455
416
  this.commands.cancel();
456
417
  }
457
- return this.transport.release(this.activitySessionID, true);
418
+ return this.transport.release({
419
+ session: this.activitySessionID,
420
+ path: this.originalDescriptor.path,
421
+ onClose: true,
422
+ });
458
423
  }
459
424
  catch (err) {
460
425
  }
@@ -11,7 +11,7 @@ export type TypedResponseMessage<T extends MessageKey> = {
11
11
  type TypedCallResponseMap = {
12
12
  [K in keyof MessageType]: TypedResponseMessage<K>;
13
13
  };
14
- export type DefaultMessageResponse = TypedCallResponseMap[keyof MessageType];
14
+ type DefaultMessageResponse = TypedCallResponseMap[keyof MessageType];
15
15
  export type PassphrasePromptResponse = {
16
16
  passphrase?: string;
17
17
  passphraseOnDevice?: boolean;
@@ -22,8 +22,9 @@ export declare class DeviceCommands {
22
22
  transport: Transport;
23
23
  sessionId: string;
24
24
  disposed: boolean;
25
- callPromise?: Promise<DefaultMessageResponse>;
25
+ callPromise?: ReturnType<Transport['call']>;
26
26
  _cancelableRequest?: (error?: any) => void;
27
+ _cancelableRequestBySend?: boolean;
27
28
  constructor(device: Device, transport: Transport, sessionId: string);
28
29
  dispose(): void;
29
30
  isDisposed(): boolean;
@@ -48,7 +49,7 @@ export declare class DeviceCommands {
48
49
  ethereumGetPublicKey({ address_n, show_display, }: Messages.EthereumGetPublicKey): Promise<HDNodeResponse>;
49
50
  preauthorize(throwError: boolean): Promise<boolean>;
50
51
  getDeviceState(networkType?: string): Promise<string>;
51
- call(type: MessageKey, msg?: DefaultMessageResponse['message']): Promise<DefaultMessageResponse>;
52
+ private call;
52
53
  typedCall<T extends MessageKey, R extends MessageKey[]>(type: T, resType: R, msg?: MessageType[T]): Promise<TypedCallResponseMap[R[number]]>;
53
54
  typedCall<T extends MessageKey, R extends MessageKey>(type: T, resType: R, msg?: MessageType[T]): Promise<TypedResponseMessage<R>>;
54
55
  _commonCall(type: MessageKey, msg?: DefaultMessageResponse['message']): Promise<DefaultMessageResponse>;
@@ -240,20 +240,20 @@ class DeviceCommands {
240
240
  return this._getAddressForNetworkType();
241
241
  }
242
242
  async call(type, msg = {}) {
243
- const logMessage = filterForLog(type, msg);
244
- logger.debug('Sending', type, logMessage);
245
- try {
246
- const promise = this.transport.call(this.sessionId, type, msg, false);
247
- this.callPromise = promise;
248
- const res = await promise;
249
- const logMessage = filterForLog(res.type, res.message);
250
- logger.debug('Received', res.type, logMessage);
251
- return res;
252
- }
253
- catch (error) {
254
- logger.warn('Received error', error);
255
- throw error;
256
- }
243
+ logger.debug('Sending', type, filterForLog(type, msg));
244
+ this.callPromise = this.transport.call({
245
+ session: this.sessionId,
246
+ name: type,
247
+ data: msg,
248
+ });
249
+ const res = await this.callPromise.promise;
250
+ this.callPromise = undefined;
251
+ if (!res.success) {
252
+ logger.warn('Received error', res.error);
253
+ throw new Error(res.error);
254
+ }
255
+ logger.debug('Received', res.payload.type, filterForLog(res.payload.type, res.payload.message));
256
+ return res.payload;
257
257
  }
258
258
  async typedCall(type, resType, msg) {
259
259
  if (this.disposed) {
@@ -264,16 +264,20 @@ class DeviceCommands {
264
264
  assertType(response, resType);
265
265
  }
266
266
  catch (error) {
267
- await this.transport.read(this.sessionId, false);
267
+ await this.transport.receive({ session: this.sessionId });
268
268
  throw error;
269
269
  }
270
270
  return response;
271
271
  }
272
272
  async _commonCall(type, msg) {
273
273
  const resp = await this.call(type, msg);
274
+ if (this.disposed) {
275
+ throw constants_1.ERRORS.TypedError('Runtime', 'typedCall: DeviceCommands already disposed');
276
+ }
274
277
  return this._filterCommonTypes(resp);
275
278
  }
276
279
  _filterCommonTypes(res) {
280
+ this._cancelableRequestBySend = false;
277
281
  if (res.type === 'Failure') {
278
282
  const { code } = res.message;
279
283
  let { message } = res.message;
@@ -289,6 +293,7 @@ class DeviceCommands {
289
293
  return Promise.resolve(res);
290
294
  }
291
295
  if (res.type === 'ButtonRequest') {
296
+ this._cancelableRequestBySend = true;
292
297
  if (res.message.code === '_Deprecated_ButtonRequest_PassphraseType') {
293
298
  res.message.code = 'ButtonRequest_PassphraseType';
294
299
  }
@@ -475,13 +480,30 @@ class DeviceCommands {
475
480
  if (this.disposed) {
476
481
  return;
477
482
  }
483
+ this.dispose();
484
+ if (!this._cancelableRequestBySend) {
485
+ if (this.callPromise) {
486
+ await this.callPromise.promise;
487
+ }
488
+ return;
489
+ }
478
490
  const { name, version } = this.transport;
479
491
  if (name === 'BridgeTransport' && (0, versionUtils_1.versionCompare)(version, '2.0.28') < 1) {
480
- await this.device.legacyForceRelease();
492
+ try {
493
+ await this.device.legacyForceRelease();
494
+ }
495
+ catch (err) {
496
+ }
481
497
  }
482
498
  else {
483
- await this.transport.post(this.sessionId, 'Cancel', {}, false).catch(() => { });
484
- await this.transport.read(this.sessionId, false).catch(() => { });
499
+ await this.transport.send({
500
+ session: this.sessionId,
501
+ name: 'Cancel',
502
+ data: {},
503
+ }).promise;
504
+ if (this.callPromise) {
505
+ await this.callPromise.promise;
506
+ }
485
507
  }
486
508
  }
487
509
  }
@@ -1,20 +1,11 @@
1
1
  import { TypedEmitter } from '@trezor/utils/lib/typedEventEmitter';
2
- import { Transport, TrezorDeviceInfoWithSession as DeviceDescriptor } from '@trezor/transport';
3
- import { TRANSPORT, DEVICE, TransportInfo } from '../events';
4
- import { DescriptorStream } from './DescriptorStream';
2
+ import { Transport, TRANSPORT, Descriptor } from '@trezor/transport';
3
+ import { DEVICE, TransportInfo } from '../events';
5
4
  import { Device } from './Device';
6
5
  import type { Device as DeviceTyped } from '../types';
7
- type LowLevelPlugin = {
8
- name: 'WebUsbPlugin' | 'ReactNativePlugin';
9
- unreadableHidDeviceChange: {
10
- on: (event: string, fn: any) => void;
11
- };
12
- unreadableHidDevice: boolean;
13
- };
14
6
  interface DeviceListEvents {
15
7
  [TRANSPORT.START]: TransportInfo;
16
8
  [TRANSPORT.ERROR]: string;
17
- [TRANSPORT.STREAM]: DescriptorStream;
18
9
  [DEVICE.CONNECT]: DeviceTyped;
19
10
  [DEVICE.CONNECT_UNACQUIRED]: DeviceTyped;
20
11
  [DEVICE.DISCONNECT]: DeviceTyped;
@@ -24,42 +15,41 @@ interface DeviceListEvents {
24
15
  }
25
16
  export declare class DeviceList extends TypedEmitter<DeviceListEvents> {
26
17
  transport: Transport;
27
- transportPlugin: LowLevelPlugin | typeof undefined;
28
- stream: DescriptorStream;
18
+ transports: Transport[];
29
19
  devices: {
30
20
  [path: string]: Device;
31
21
  };
22
+ messages: JSON | Record<string, any>;
32
23
  creatingDevicesDescriptors: {
33
- [k: string]: DeviceDescriptor;
24
+ [k: string]: Descriptor;
34
25
  };
35
- messages: JSON | Record<string, any>;
36
26
  transportStartPending: number;
37
27
  penalizedDevices: {
38
28
  [deviceID: string]: number;
39
29
  };
40
- fetchController?: AbortController | null;
41
30
  constructor();
42
31
  init(): Promise<void>;
43
- resolveTransportEvent(): void;
32
+ private resolveTransportEvent;
44
33
  waitForTransportFirstEvent(): Promise<void>;
45
- _initStream(): void;
46
- _createAndSaveDevice(descriptor: DeviceDescriptor): Promise<void>;
47
- _createUnacquiredDevice(descriptor: DeviceDescriptor): Device;
48
- _createUnreadableDevice(descriptor: DeviceDescriptor, unreadableError: string): Device;
34
+ private _createAndSaveDevice;
35
+ private _createUnacquiredDevice;
36
+ private _createUnreadableDevice;
49
37
  getDevice(path: string): Device;
50
38
  getFirstDevicePath(): string;
51
39
  asArray(): DeviceTyped[];
52
40
  allDevices(): Device[];
53
41
  length(): number;
54
- transportType(): string;
42
+ transportType(): "BridgeTransport" | "NodeUsbTransport" | "WebUsbTransport";
55
43
  getTransportInfo(): TransportInfo;
56
44
  dispose(): Promise<void>;
57
45
  disconnectDevices(): void;
58
- enumerate(): void;
46
+ enumerate(): Promise<void>;
59
47
  addAuthPenalty(device: Device): void;
60
- getAuthPenalty(): number;
48
+ private getAuthPenalty;
61
49
  removeAuthPenalty(device: Device): void;
50
+ private handle;
51
+ private _takeAndCreateDevice;
52
+ private _handleUsedElsewhere;
62
53
  }
63
- export declare const getDeviceList: () => Promise<DeviceList>;
64
54
  export {};
65
55
  //# sourceMappingURL=DeviceList.d.ts.map