@trezor/connect 9.0.10 → 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.
- package/CHANGELOG.md +13 -0
- package/README.md +19 -2
- package/lib/api/bitcoin/createPendingTx.d.ts +1 -0
- package/lib/api/bitcoin/createPendingTx.js +1 -0
- package/lib/api/cancelCoinjoinAuthorization.d.ts +7 -0
- package/lib/api/cancelCoinjoinAuthorization.js +25 -0
- package/lib/api/cardanoGetPublicKey.d.ts +1 -0
- package/lib/api/cardanoGetPublicKey.js +9 -0
- package/lib/api/cipherKeyValue.js +3 -2
- package/lib/api/getAccountInfo.d.ts +2 -0
- package/lib/api/getPublicKey.d.ts +1 -0
- package/lib/api/getPublicKey.js +9 -0
- package/lib/api/index.d.ts +2 -0
- package/lib/api/index.js +6 -2
- package/lib/api/rebootToBootloader.js +1 -1
- package/lib/api/showDeviceTutorial.d.ts +7 -0
- package/lib/api/showDeviceTutorial.js +21 -0
- package/lib/constants/errors.d.ts +0 -3
- package/lib/constants/errors.js +1 -4
- package/lib/core/index.d.ts +5 -6
- package/lib/core/index.js +44 -50
- package/lib/core/method.d.ts +1 -1
- package/lib/data/coinInfo.d.ts +0 -1
- package/lib/data/coinInfo.js +7 -14
- package/lib/data/config.js +7 -1
- package/lib/data/version.d.ts +1 -1
- package/lib/data/version.js +1 -1
- package/lib/device/Device.d.ts +16 -24
- package/lib/device/Device.js +71 -107
- package/lib/device/DeviceCommands.d.ts +4 -3
- package/lib/device/DeviceCommands.js +42 -20
- package/lib/device/DeviceList.d.ts +17 -33
- package/lib/device/DeviceList.js +230 -264
- package/lib/events/transport.d.ts +2 -9
- package/lib/events/transport.js +3 -10
- package/lib/factory.js +2 -0
- package/lib/index.js +7 -7
- package/lib/types/api/cancelCoinjoinAuthorization.d.ts +8 -0
- package/lib/types/api/cancelCoinjoinAuthorization.js +3 -0
- package/lib/types/api/index.d.ts +4 -0
- package/lib/types/api/showDeviceTutorial.d.ts +4 -0
- package/lib/types/api/showDeviceTutorial.js +3 -0
- package/lib/types/device.d.ts +1 -1
- package/lib/types/device.js +3 -0
- package/lib/types/settings.d.ts +1 -1
- package/lib/utils/debug.js +2 -1
- package/lib/utils/deviceFeaturesUtils.d.ts +2 -1
- package/lib/utils/deviceFeaturesUtils.js +12 -1
- package/lib/workers/workers-browser.d.ts +1 -3
- package/lib/workers/workers-browser.js +1 -7
- package/lib/workers/workers-react-native.d.ts +1 -3
- package/lib/workers/workers-react-native.js +1 -7
- package/lib/workers/workers.d.ts +1 -5
- package/lib/workers/workers.js +1 -5
- package/package.json +21 -18
- package/lib/device/DescriptorStream.d.ts +0 -28
- package/lib/device/DescriptorStream.js +0 -139
- package/lib/utils/objectUtils.d.ts +0 -10
- package/lib/utils/objectUtils.js +0 -37
- package/lib/workers/RNUsbPlugin.d.ts +0 -31
- package/lib/workers/RNUsbPlugin.js +0 -65
package/lib/data/coinInfo.js
CHANGED
|
@@ -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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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}`);
|
package/lib/data/config.js
CHANGED
|
@@ -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.
|
|
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
|
package/lib/data/version.d.ts
CHANGED
package/lib/data/version.js
CHANGED
|
@@ -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.
|
|
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
|
package/lib/device/Device.d.ts
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
import EventEmitter from 'events';
|
|
1
|
+
import { TypedEmitter } from '@trezor/utils/lib/typedEventEmitter';
|
|
3
2
|
import { DeviceCommands } from './DeviceCommands';
|
|
4
3
|
import { PROTO, NETWORK } from '../constants';
|
|
5
4
|
import { DEVICE, DeviceButtonRequestPayload } from '../events';
|
|
6
5
|
import { Deferred } from '../utils/deferred';
|
|
7
|
-
import type { Transport,
|
|
6
|
+
import type { Transport, Descriptor } from '@trezor/transport';
|
|
8
7
|
import type { Device as DeviceTyped, DeviceFirmwareStatus, Features, ReleaseInfo, UnavailableCapabilities } from '../types';
|
|
9
8
|
export type RunOptions = {
|
|
10
9
|
skipFinalReload?: boolean;
|
|
@@ -16,29 +15,23 @@ export type RunOptions = {
|
|
|
16
15
|
useCardanoDerivation?: boolean;
|
|
17
16
|
};
|
|
18
17
|
export interface DeviceEvents {
|
|
19
|
-
[DEVICE.PIN]:
|
|
20
|
-
[DEVICE.WORD]:
|
|
21
|
-
[DEVICE.PASSPHRASE]:
|
|
22
|
-
[DEVICE.PASSPHRASE_ON_DEVICE]:
|
|
23
|
-
[DEVICE.BUTTON]:
|
|
24
|
-
[DEVICE.ACQUIRED]:
|
|
18
|
+
[DEVICE.PIN]: (device: Device, b: PROTO.PinMatrixRequestType | undefined, callback: (err: any, pin: string) => void) => void;
|
|
19
|
+
[DEVICE.WORD]: (device: Device, b: PROTO.WordRequestType, callback: (err: any, word: string) => void) => void;
|
|
20
|
+
[DEVICE.PASSPHRASE]: (device: Device, callback: (response: any) => void) => void;
|
|
21
|
+
[DEVICE.PASSPHRASE_ON_DEVICE]: () => void;
|
|
22
|
+
[DEVICE.BUTTON]: (device: Device, payload: DeviceButtonRequestPayload) => void;
|
|
23
|
+
[DEVICE.ACQUIRED]: () => void;
|
|
25
24
|
}
|
|
26
|
-
export
|
|
27
|
-
on<K extends keyof DeviceEvents>(type: K, listener: (...event: DeviceEvents[K]) => void): this;
|
|
28
|
-
off<K extends keyof DeviceEvents>(type: K, listener: (...event: DeviceEvents[K]) => void): this;
|
|
29
|
-
emit<K extends keyof DeviceEvents>(type: K, ...args: DeviceEvents[K]): boolean;
|
|
30
|
-
}
|
|
31
|
-
export declare class Device extends EventEmitter {
|
|
25
|
+
export declare class Device extends TypedEmitter<DeviceEvents> {
|
|
32
26
|
transport: Transport;
|
|
33
|
-
originalDescriptor:
|
|
27
|
+
originalDescriptor: Descriptor;
|
|
34
28
|
unreadableError?: string;
|
|
35
29
|
firmwareStatus: DeviceFirmwareStatus;
|
|
36
30
|
firmwareRelease?: ReleaseInfo | null;
|
|
37
31
|
features: Features;
|
|
38
32
|
featuresNeedsReload: boolean;
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
};
|
|
33
|
+
acquirePromise?: ReturnType<Transport['acquire']>;
|
|
34
|
+
releasePromise?: ReturnType<Transport['release']>;
|
|
42
35
|
runPromise?: Deferred<void> | null;
|
|
43
36
|
loaded: boolean;
|
|
44
37
|
inconsistent: boolean;
|
|
@@ -52,9 +45,9 @@ export declare class Device extends EventEmitter {
|
|
|
52
45
|
unavailableCapabilities: UnavailableCapabilities;
|
|
53
46
|
networkTypeState: NETWORK.NetworkType[];
|
|
54
47
|
firmwareType: 'regular' | 'bitcoin-only';
|
|
55
|
-
constructor(transport: Transport, descriptor:
|
|
56
|
-
static fromDescriptor(transport: Transport, originalDescriptor:
|
|
57
|
-
static createUnacquired(transport: Transport, descriptor:
|
|
48
|
+
constructor(transport: Transport, descriptor: Descriptor);
|
|
49
|
+
static fromDescriptor(transport: Transport, originalDescriptor: Descriptor): Device;
|
|
50
|
+
static createUnacquired(transport: Transport, descriptor: Descriptor, unreadableError?: string): Device;
|
|
58
51
|
acquire(): Promise<void>;
|
|
59
52
|
release(): Promise<void>;
|
|
60
53
|
cleanup(): Promise<void>;
|
|
@@ -76,7 +69,6 @@ export declare class Device extends EventEmitter {
|
|
|
76
69
|
getFeatures(): Promise<void>;
|
|
77
70
|
_updateFeatures(feat: Features): void;
|
|
78
71
|
isUnacquired(): boolean;
|
|
79
|
-
updateDescriptor(upcomingDescriptor: DeviceDescriptor): Promise<void>;
|
|
80
72
|
disconnect(): void;
|
|
81
73
|
isBootloader(): boolean;
|
|
82
74
|
isInitialized(): boolean;
|
|
@@ -93,7 +85,7 @@ export declare class Device extends EventEmitter {
|
|
|
93
85
|
getDevicePath(): string;
|
|
94
86
|
isT1(): boolean;
|
|
95
87
|
hasUnexpectedMode(allow: string[], require: string[]): "ui-device_bootloader_mode" | "ui-device_not_in_bootloader_mode" | "ui-device_not_initialized" | "ui-device_seedless" | null;
|
|
96
|
-
dispose():
|
|
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;
|
|
97
89
|
getMode(): "normal" | "bootloader" | "initialize" | "seedless";
|
|
98
90
|
toMessageObject(): DeviceTyped;
|
|
99
91
|
_getNetworkTypeState(): "bitcoin" | "ethereum" | "nem" | "eos" | "stellar" | "cardano" | "ripple" | "tezos" | "binance";
|
package/lib/device/Device.js
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.Device = void 0;
|
|
4
|
-
const
|
|
5
|
-
const events_1 = tslib_1.__importDefault(require("events"));
|
|
4
|
+
const typedEventEmitter_1 = require("@trezor/utils/lib/typedEventEmitter");
|
|
6
5
|
const DeviceCommands_1 = require("./DeviceCommands");
|
|
7
6
|
const constants_1 = require("../constants");
|
|
8
|
-
const
|
|
7
|
+
const events_1 = require("../events");
|
|
9
8
|
const coinInfo_1 = require("../data/coinInfo");
|
|
10
9
|
const firmwareInfo_1 = require("../data/firmwareInfo");
|
|
11
10
|
const deviceFeaturesUtils_1 = require("../utils/deviceFeaturesUtils");
|
|
@@ -18,11 +17,12 @@ const parseRunOptions = (options) => {
|
|
|
18
17
|
options = {};
|
|
19
18
|
return options;
|
|
20
19
|
};
|
|
21
|
-
class Device extends
|
|
20
|
+
class Device extends typedEventEmitter_1.TypedEmitter {
|
|
22
21
|
constructor(transport, descriptor) {
|
|
23
22
|
super();
|
|
24
23
|
this.featuresNeedsReload = false;
|
|
25
|
-
this.
|
|
24
|
+
this.acquirePromise = undefined;
|
|
25
|
+
this.releasePromise = undefined;
|
|
26
26
|
this.loaded = false;
|
|
27
27
|
this.inconsistent = false;
|
|
28
28
|
this.keepSession = false;
|
|
@@ -53,54 +53,53 @@ class Device extends events_1.default {
|
|
|
53
53
|
return device;
|
|
54
54
|
}
|
|
55
55
|
async acquire() {
|
|
56
|
-
this.
|
|
57
|
-
|
|
58
|
-
try {
|
|
59
|
-
const sessionID = await this.transport.acquire({
|
|
56
|
+
this.acquirePromise = this.transport.acquire({
|
|
57
|
+
input: {
|
|
60
58
|
path: this.originalDescriptor.path,
|
|
61
59
|
previous: this.originalDescriptor.session,
|
|
62
|
-
},
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
if (this.commands) {
|
|
68
|
-
this.commands.dispose();
|
|
69
|
-
}
|
|
70
|
-
this.commands = new DeviceCommands_1.DeviceCommands(this, this.transport, sessionID);
|
|
71
|
-
this.deferredActions[events_2.DEVICE.RELEASE] = (0, deferred_1.create)();
|
|
72
|
-
}
|
|
73
|
-
catch (error) {
|
|
74
|
-
this.deferredActions[events_2.DEVICE.ACQUIRED].resolve();
|
|
75
|
-
delete this.deferredActions[events_2.DEVICE.ACQUIRED];
|
|
60
|
+
},
|
|
61
|
+
});
|
|
62
|
+
const acquireResult = await this.acquirePromise.promise;
|
|
63
|
+
this.acquirePromise = undefined;
|
|
64
|
+
if (!acquireResult.success) {
|
|
76
65
|
if (this.runPromise) {
|
|
77
|
-
this.runPromise.reject(error);
|
|
78
|
-
|
|
79
|
-
else {
|
|
80
|
-
throw error;
|
|
66
|
+
this.runPromise.reject(new Error(acquireResult.error));
|
|
67
|
+
this.runPromise = null;
|
|
81
68
|
}
|
|
82
|
-
|
|
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();
|
|
83
77
|
}
|
|
78
|
+
this.commands = new DeviceCommands_1.DeviceCommands(this, this.transport, sessionID);
|
|
84
79
|
}
|
|
85
80
|
async release() {
|
|
86
|
-
if (this.isUsedHere() &&
|
|
81
|
+
if (this.isUsedHere() &&
|
|
82
|
+
!this.keepSession &&
|
|
83
|
+
this.activitySessionID &&
|
|
84
|
+
!this.releasePromise) {
|
|
87
85
|
if (this.commands) {
|
|
88
86
|
this.commands.dispose();
|
|
89
87
|
if (this.commands.callPromise) {
|
|
90
|
-
|
|
91
|
-
await this.commands.callPromise;
|
|
92
|
-
}
|
|
93
|
-
catch (error) {
|
|
94
|
-
this.commands.callPromise = undefined;
|
|
95
|
-
}
|
|
88
|
+
await this.commands.callPromise.promise;
|
|
96
89
|
}
|
|
97
90
|
}
|
|
98
|
-
|
|
99
|
-
await this.
|
|
100
|
-
if (this.deferredActions[events_2.DEVICE.RELEASE])
|
|
101
|
-
await this.deferredActions[events_2.DEVICE.RELEASE].promise;
|
|
91
|
+
if (this.releasePromise) {
|
|
92
|
+
await this.releasePromise;
|
|
102
93
|
}
|
|
103
|
-
|
|
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;
|
|
104
103
|
}
|
|
105
104
|
}
|
|
106
105
|
}
|
|
@@ -119,26 +118,25 @@ class Device extends events_1.default {
|
|
|
119
118
|
return this.runPromise.promise;
|
|
120
119
|
}
|
|
121
120
|
async override(error) {
|
|
122
|
-
if (this.
|
|
123
|
-
await this.
|
|
121
|
+
if (this.acquirePromise) {
|
|
122
|
+
await this.acquirePromise.promise;
|
|
124
123
|
}
|
|
125
124
|
if (this.runPromise) {
|
|
126
125
|
await this.interruptionFromUser(error);
|
|
127
126
|
}
|
|
128
|
-
if (
|
|
129
|
-
await this.
|
|
127
|
+
if (this.releasePromise) {
|
|
128
|
+
await this.releasePromise.promise;
|
|
130
129
|
}
|
|
131
130
|
}
|
|
132
131
|
async interruptionFromUser(error) {
|
|
133
132
|
_log.debug('interruptionFromUser');
|
|
134
|
-
if (this.commands) {
|
|
135
|
-
await this.commands.cancel();
|
|
136
|
-
this.commands.dispose();
|
|
137
|
-
}
|
|
138
133
|
if (this.runPromise) {
|
|
139
134
|
this.runPromise.reject(error);
|
|
140
135
|
this.runPromise = null;
|
|
141
136
|
}
|
|
137
|
+
if (this.commands) {
|
|
138
|
+
await this.commands.cancel();
|
|
139
|
+
}
|
|
142
140
|
}
|
|
143
141
|
interruptionFromOutside() {
|
|
144
142
|
_log.debug('interruptionFromOutside');
|
|
@@ -149,9 +147,13 @@ class Device extends events_1.default {
|
|
|
149
147
|
this.runPromise.reject(constants_1.ERRORS.TypedError('Device_UsedElsewhere'));
|
|
150
148
|
this.runPromise = null;
|
|
151
149
|
}
|
|
150
|
+
this.transport.releaseDevice(this.originalDescriptor.path);
|
|
152
151
|
}
|
|
153
152
|
async _runInner(fn, options) {
|
|
154
153
|
var _a;
|
|
154
|
+
if (this.releasePromise) {
|
|
155
|
+
await this.releasePromise.promise;
|
|
156
|
+
}
|
|
155
157
|
if (!this.isUsedHere() || ((_a = this.commands) === null || _a === void 0 ? void 0 : _a.disposed) || !this.getExternalState()) {
|
|
156
158
|
await this.acquire();
|
|
157
159
|
try {
|
|
@@ -171,15 +173,16 @@ class Device extends events_1.default {
|
|
|
171
173
|
return this._runInner(() => Promise.resolve({}), options);
|
|
172
174
|
}
|
|
173
175
|
this.inconsistent = true;
|
|
174
|
-
await this.deferredActions[events_2.DEVICE.ACQUIRE].promise;
|
|
175
176
|
this.runPromise = null;
|
|
176
|
-
return Promise.reject(constants_1.ERRORS.TypedError('Device_InitializeFailed', `Initialize failed: ${error.message}
|
|
177
|
+
return Promise.reject(constants_1.ERRORS.TypedError('Device_InitializeFailed', `Initialize failed: ${error.message} ${error.code ? `, code: ${error.code}` : ''}`));
|
|
177
178
|
}
|
|
178
179
|
}
|
|
179
180
|
if (options.keepSession) {
|
|
180
181
|
this.keepSession = true;
|
|
181
182
|
}
|
|
182
|
-
|
|
183
|
+
if (this.listeners(events_1.DEVICE.ACQUIRED).length > 0) {
|
|
184
|
+
this.emit(events_1.DEVICE.ACQUIRED);
|
|
185
|
+
}
|
|
183
186
|
if (fn) {
|
|
184
187
|
await fn();
|
|
185
188
|
}
|
|
@@ -316,6 +319,9 @@ class Device extends events_1.default {
|
|
|
316
319
|
if (!feat.model && feat.major_version === 1) {
|
|
317
320
|
feat.model = '1';
|
|
318
321
|
}
|
|
322
|
+
if (!feat.internal_model) {
|
|
323
|
+
feat.internal_model = (0, deviceFeaturesUtils_1.ensureInternalModelFeature)(feat.model);
|
|
324
|
+
}
|
|
319
325
|
this.features = feat;
|
|
320
326
|
this.featuresNeedsReload = false;
|
|
321
327
|
this.firmwareType =
|
|
@@ -328,55 +334,9 @@ class Device extends events_1.default {
|
|
|
328
334
|
isUnacquired() {
|
|
329
335
|
return this.features === undefined;
|
|
330
336
|
}
|
|
331
|
-
async updateDescriptor(upcomingDescriptor) {
|
|
332
|
-
const originalSession = this.originalDescriptor.session;
|
|
333
|
-
const upcomingSession = upcomingDescriptor.session;
|
|
334
|
-
_log.debug('updateDescriptor', 'currentSession', originalSession, 'upcoming', upcomingSession, 'lastUsedID', this.activitySessionID);
|
|
335
|
-
if (!originalSession && !upcomingSession && !this.activitySessionID) {
|
|
336
|
-
return;
|
|
337
|
-
}
|
|
338
|
-
if (this.deferredActions[events_2.DEVICE.ACQUIRED]) {
|
|
339
|
-
await this.deferredActions[events_2.DEVICE.ACQUIRED].promise;
|
|
340
|
-
}
|
|
341
|
-
if (!upcomingSession) {
|
|
342
|
-
if (this.listeners(events_2.DEVICE.ACQUIRED).length > 0) {
|
|
343
|
-
this.emit(events_2.DEVICE.ACQUIRED);
|
|
344
|
-
}
|
|
345
|
-
}
|
|
346
|
-
const methodStillRunning = this.commands && !this.commands.disposed;
|
|
347
|
-
if (!upcomingSession && !methodStillRunning) {
|
|
348
|
-
if (originalSession === this.activitySessionID) {
|
|
349
|
-
_log.debug('Session released by this app');
|
|
350
|
-
if (this.deferredActions[events_2.DEVICE.RELEASE]) {
|
|
351
|
-
this.deferredActions[events_2.DEVICE.RELEASE].resolve();
|
|
352
|
-
delete this.deferredActions[events_2.DEVICE.RELEASE];
|
|
353
|
-
}
|
|
354
|
-
this.activitySessionID = null;
|
|
355
|
-
}
|
|
356
|
-
else {
|
|
357
|
-
_log.debug('Session released by other app');
|
|
358
|
-
this.featuresNeedsReload = true;
|
|
359
|
-
}
|
|
360
|
-
this.keepSession = false;
|
|
361
|
-
}
|
|
362
|
-
else if (upcomingSession === this.activitySessionID) {
|
|
363
|
-
_log.debug('Session acquired by this app');
|
|
364
|
-
if (this.deferredActions[events_2.DEVICE.ACQUIRE]) {
|
|
365
|
-
this.deferredActions[events_2.DEVICE.ACQUIRE].resolve();
|
|
366
|
-
}
|
|
367
|
-
}
|
|
368
|
-
else {
|
|
369
|
-
_log.debug('Session acquired by other app');
|
|
370
|
-
this.interruptionFromOutside();
|
|
371
|
-
}
|
|
372
|
-
this.originalDescriptor = upcomingDescriptor;
|
|
373
|
-
}
|
|
374
337
|
disconnect() {
|
|
375
338
|
_log.debug('Disconnect cleanup');
|
|
376
|
-
|
|
377
|
-
this.deferredActions[events_2.DEVICE.RELEASE].resolve();
|
|
378
|
-
delete this.deferredActions[events_2.DEVICE.RELEASE];
|
|
379
|
-
}
|
|
339
|
+
this.activitySessionID = null;
|
|
380
340
|
this.interruptionFromUser(constants_1.ERRORS.TypedError('Device_Disconnected'));
|
|
381
341
|
this.runPromise = null;
|
|
382
342
|
}
|
|
@@ -433,17 +393,17 @@ class Device extends events_1.default {
|
|
|
433
393
|
}
|
|
434
394
|
hasUnexpectedMode(allow, require) {
|
|
435
395
|
if (this.features) {
|
|
436
|
-
if (this.isBootloader() && !allow.includes(
|
|
437
|
-
return
|
|
396
|
+
if (this.isBootloader() && !allow.includes(events_1.UI.BOOTLOADER)) {
|
|
397
|
+
return events_1.UI.BOOTLOADER;
|
|
438
398
|
}
|
|
439
|
-
if (!this.isInitialized() && !allow.includes(
|
|
440
|
-
return
|
|
399
|
+
if (!this.isInitialized() && !allow.includes(events_1.UI.INITIALIZE)) {
|
|
400
|
+
return events_1.UI.INITIALIZE;
|
|
441
401
|
}
|
|
442
|
-
if (this.isSeedless() && !allow.includes(
|
|
443
|
-
return
|
|
402
|
+
if (this.isSeedless() && !allow.includes(events_1.UI.SEEDLESS)) {
|
|
403
|
+
return events_1.UI.SEEDLESS;
|
|
444
404
|
}
|
|
445
|
-
if (!this.isBootloader() && require.includes(
|
|
446
|
-
return
|
|
405
|
+
if (!this.isBootloader() && require.includes(events_1.UI.BOOTLOADER)) {
|
|
406
|
+
return events_1.UI.NOT_IN_BOOTLOADER;
|
|
447
407
|
}
|
|
448
408
|
}
|
|
449
409
|
return null;
|
|
@@ -455,7 +415,11 @@ class Device extends events_1.default {
|
|
|
455
415
|
if (this.commands) {
|
|
456
416
|
this.commands.cancel();
|
|
457
417
|
}
|
|
458
|
-
return this.transport.release(
|
|
418
|
+
return this.transport.release({
|
|
419
|
+
session: this.activitySessionID,
|
|
420
|
+
path: this.originalDescriptor.path,
|
|
421
|
+
onClose: true,
|
|
422
|
+
});
|
|
459
423
|
}
|
|
460
424
|
catch (err) {
|
|
461
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
|
-
|
|
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?:
|
|
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
|
|
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
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
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.
|
|
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,11 +293,12 @@ 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
|
}
|
|
295
300
|
if (res.message.code === 'ButtonRequest_PassphraseEntry') {
|
|
296
|
-
this.device.emit(events_1.DEVICE.PASSPHRASE_ON_DEVICE
|
|
301
|
+
this.device.emit(events_1.DEVICE.PASSPHRASE_ON_DEVICE);
|
|
297
302
|
}
|
|
298
303
|
else {
|
|
299
304
|
this.device.emit(events_1.DEVICE.BUTTON, this.device, res.message);
|
|
@@ -316,7 +321,7 @@ class DeviceCommands {
|
|
|
316
321
|
return this._commonCall('PassphraseAck', { passphrase: state });
|
|
317
322
|
}
|
|
318
323
|
if (legacy && res.message._on_device) {
|
|
319
|
-
this.device.emit(events_1.DEVICE.PASSPHRASE_ON_DEVICE
|
|
324
|
+
this.device.emit(events_1.DEVICE.PASSPHRASE_ON_DEVICE);
|
|
320
325
|
return this._commonCall('PassphraseAck', { _state: state });
|
|
321
326
|
}
|
|
322
327
|
return this._promptPassphrase().then(response => {
|
|
@@ -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
|
-
|
|
492
|
+
try {
|
|
493
|
+
await this.device.legacyForceRelease();
|
|
494
|
+
}
|
|
495
|
+
catch (err) {
|
|
496
|
+
}
|
|
481
497
|
}
|
|
482
498
|
else {
|
|
483
|
-
await this.transport.
|
|
484
|
-
|
|
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
|
}
|