@trezor/connect 9.4.2 → 9.4.3-beta.2
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 +90 -9
- package/README.md +1 -1
- package/lib/api/applyFlags.js +1 -1
- package/lib/api/applySettings.js +1 -1
- package/lib/api/authenticateDevice.js +1 -1
- package/lib/api/authorizeCoinjoin.js +1 -1
- package/lib/api/backupDevice.js +1 -1
- package/lib/api/binance/api/binanceGetAddress.js +2 -1
- package/lib/api/binance/api/binanceGetPublicKey.js +2 -1
- package/lib/api/binance/api/binanceSignTransaction.js +2 -1
- package/lib/api/binance/binanceSignTx.js +1 -1
- package/lib/api/bitcoin/Fees.js +2 -2
- package/lib/api/bitcoin/TransactionComposer.d.ts +3 -3
- package/lib/api/bitcoin/TransactionComposer.js +2 -2
- package/lib/api/bitcoin/refTx.js +1 -1
- package/lib/api/blockchainDisconnect.js +1 -1
- package/lib/api/blockchainEvmRpcCall.d.ts +16 -0
- package/lib/api/blockchainEvmRpcCall.js +45 -0
- package/lib/api/cancelCoinjoinAuthorization.js +1 -1
- package/lib/api/cardano/api/cardanoGetAddress.js +2 -1
- package/lib/api/cardano/api/cardanoGetNativeScriptHash.js +2 -1
- package/lib/api/cardano/api/cardanoGetPublicKey.js +2 -1
- package/lib/api/cardano/api/cardanoSignTransaction.js +2 -1
- package/lib/api/cardano/cardanoAddressParameters.js +1 -1
- package/lib/api/cardano/cardanoAuxiliaryData.js +1 -1
- package/lib/api/cardano/cardanoCertificate.js +1 -1
- package/lib/api/cardano/cardanoInputs.d.ts +8 -8
- package/lib/api/cardano/cardanoInputs.js +1 -1
- package/lib/api/cardano/cardanoOutputs.d.ts +22 -22
- package/lib/api/cardano/cardanoOutputs.js +1 -1
- package/lib/api/cardano/cardanoTokenBundle.d.ts +6 -6
- package/lib/api/cardano/cardanoTokenBundle.js +1 -1
- package/lib/api/changeLanguage.js +1 -1
- package/lib/api/changePin.js +1 -1
- package/lib/api/cipherKeyValue.js +1 -1
- package/lib/api/common/paramsValidator.js +1 -1
- package/lib/api/composeTransaction.d.ts +9 -3
- package/lib/api/composeTransaction.js +7 -4
- package/lib/api/eos/api/eosGetPublicKey.js +2 -1
- package/lib/api/eos/api/eosSignTransaction.js +2 -1
- package/lib/api/eos/eosSignTx.d.ts +3 -3
- package/lib/api/ethereum/api/ethereumGetAddress.js +2 -1
- package/lib/api/ethereum/api/ethereumGetPublicKey.js +2 -1
- package/lib/api/ethereum/api/ethereumSignMessage.d.ts +1 -1
- package/lib/api/ethereum/api/ethereumSignMessage.js +2 -1
- package/lib/api/ethereum/api/ethereumSignTransaction.d.ts +1 -1
- package/lib/api/ethereum/api/ethereumSignTransaction.js +13 -7
- package/lib/api/ethereum/api/ethereumSignTypedData.d.ts +58 -57
- package/lib/api/ethereum/api/ethereumSignTypedData.js +3 -2
- package/lib/api/ethereum/api/ethereumVerifyMessage.js +2 -1
- package/lib/api/ethereum/ethereumDefinitions.d.ts +21 -21
- package/lib/api/ethereum/ethereumDefinitions.js +6 -5
- package/lib/api/firmware/getBinary.d.ts +4 -5
- package/lib/api/firmware/getBinary.js +12 -13
- package/lib/api/firmware/getBinaryForFirmwareUpgrade.d.ts +3 -3
- package/lib/api/firmware/getBinaryForFirmwareUpgrade.js +2 -2
- package/lib/api/firmware/index.d.ts +1 -1
- package/lib/api/firmware/index.js +2 -1
- package/lib/api/firmware/x509certificate.js +3 -5
- package/lib/api/getAccountDescriptor.js +1 -1
- package/lib/api/getAddress.js +1 -1
- package/lib/api/getCoinInfo.d.ts +3 -0
- package/lib/api/getCoinInfo.js +1 -1
- package/lib/api/getFirmwareHash.js +1 -1
- package/lib/api/getOwnershipId.js +1 -1
- package/lib/api/getOwnershipProof.js +1 -1
- package/lib/api/getPublicKey.js +1 -1
- package/lib/api/index.d.ts +2 -1
- package/lib/api/index.js +5 -3
- package/lib/api/loadDevice.d.ts +14 -0
- package/lib/api/loadDevice.js +44 -0
- package/lib/api/nem/api/nemGetAddress.js +2 -1
- package/lib/api/nem/api/nemSignTransaction.js +2 -1
- package/lib/api/pushTransaction.js +1 -1
- package/lib/api/rebootToBootloader.js +1 -1
- package/lib/api/recoveryDevice.js +1 -1
- package/lib/api/requestLogin.js +1 -1
- package/lib/api/resetDevice.js +1 -2
- package/lib/api/ripple/api/rippleGetAddress.js +2 -1
- package/lib/api/ripple/api/rippleSignTransaction.js +2 -1
- package/lib/api/setBrightness.js +1 -1
- package/lib/api/setBusy.js +1 -1
- package/lib/api/signMessage.js +1 -1
- package/lib/api/solana/api/solanaGetAddress.js +2 -1
- package/lib/api/solana/api/solanaGetPublicKey.js +2 -1
- package/lib/api/solana/api/solanaSignTransaction.js +2 -1
- package/lib/api/stellar/api/stellarGetAddress.js +2 -1
- package/lib/api/stellar/api/stellarSignTransaction.js +2 -1
- package/lib/api/stellar/stellarSignTx.js +1 -1
- package/lib/api/tezos/api/tezosGetAddress.js +2 -1
- package/lib/api/tezos/api/tezosGetPublicKey.js +2 -1
- package/lib/api/tezos/api/tezosSignTransaction.js +2 -1
- package/lib/api/tezos/tezosSignTx.js +1 -1
- package/lib/api/unlockPath.js +1 -1
- package/lib/api/verifyMessage.js +1 -1
- package/lib/backend/Blockchain.d.ts +3 -0
- package/lib/backend/Blockchain.js +6 -6
- package/lib/constants/errors.d.ts +49 -38
- package/lib/constants/errors.js +10 -0
- package/lib/constants/firmware.d.ts +2 -0
- package/lib/constants/firmware.js +5 -0
- package/lib/constants/index.d.ts +2 -0
- package/lib/constants/index.js +4 -1
- package/lib/constants/nem.d.ts +3 -3
- package/lib/constants/utxo.d.ts +3 -0
- package/lib/constants/utxo.js +5 -0
- package/lib/core/AbstractMethod.d.ts +13 -5
- package/lib/core/AbstractMethod.js +50 -24
- package/lib/core/index.js +41 -30
- package/lib/core/onCallFirmwareUpdate.d.ts +2 -2
- package/lib/core/onCallFirmwareUpdate.js +6 -6
- package/lib/data/DataManager.d.ts +0 -181
- package/lib/data/DataManager.js +40 -6
- package/lib/data/analyticsInfo.js +4 -2
- package/lib/data/coinInfo.d.ts +14 -0
- package/lib/data/config.d.ts +20 -22
- package/lib/data/config.js +15 -40
- package/lib/data/connectSettings.js +10 -4
- package/lib/data/deviceAuthenticityConfig.js +20 -0
- package/lib/data/deviceAuthenticityConfigTypes.d.ts +32 -23
- package/lib/data/firmwareInfo.d.ts +1 -1
- package/lib/data/models.d.ts +9 -0
- package/lib/data/models.js +9 -0
- package/lib/data/version.d.ts +2 -1
- package/lib/data/version.js +3 -2
- package/lib/device/Device.d.ts +144 -36
- package/lib/device/Device.js +270 -113
- package/lib/device/DeviceCommands.js +4 -4
- package/lib/device/DeviceList.d.ts +13 -21
- package/lib/device/DeviceList.js +54 -168
- package/lib/device/checkFirmwareRevision.js +4 -4
- package/lib/device/prompts.js +3 -2
- package/lib/device/resolveDescriptorForTaproot.d.ts +1 -1
- package/lib/events/call.d.ts +5 -5
- package/lib/events/call.js +2 -2
- package/lib/events/core.d.ts +4 -3
- package/lib/events/device.d.ts +0 -6
- package/lib/events/device.js +0 -6
- package/lib/events/transport.d.ts +1 -1
- package/lib/factory.d.ts +6 -6
- package/lib/factory.js +132 -136
- package/lib/impl/dynamic.d.ts +33 -0
- package/lib/impl/dynamic.js +75 -0
- package/lib/index-browser.d.ts +3 -1
- package/lib/index-browser.js +0 -3
- package/lib/index.d.ts +3 -1
- package/lib/index.js +1 -13
- package/lib/types/api/applySettings.d.ts +13 -13
- package/lib/types/api/authenticateDevice.d.ts +33 -24
- package/lib/types/api/authorizeCoinjoin.d.ts +10 -10
- package/lib/types/api/binance/index.d.ts +143 -143
- package/lib/types/api/binance/index.js +1 -1
- package/lib/types/api/bitcoin/index.d.ts +11 -11
- package/lib/types/api/bitcoin/index.js +1 -1
- package/lib/types/api/blockchainEvmRpcCall.d.ts +4 -0
- package/lib/types/api/{checkFirmwareAuthenticity.js → blockchainEvmRpcCall.js} +1 -1
- package/lib/types/api/cancelCoinjoinAuthorization.d.ts +1 -1
- package/lib/types/api/cardano/index.d.ts +507 -507
- package/lib/types/api/changeLanguage.d.ts +6 -6
- package/lib/types/api/cipherKeyValue.d.ts +8 -8
- package/lib/types/api/cipherKeyValue.js +1 -1
- package/lib/types/api/composeTransaction.d.ts +13 -7
- package/lib/types/api/eos/index.d.ts +525 -525
- package/lib/types/api/eos/index.js +1 -1
- package/lib/types/api/ethereum/index.d.ts +100 -100
- package/lib/types/api/firmwareUpdate.d.ts +5 -5
- package/lib/types/api/getAccountDescriptor.d.ts +4 -4
- package/lib/types/api/getAddress.d.ts +32 -32
- package/lib/types/api/getOwnershipId.d.ts +24 -24
- package/lib/types/api/getOwnershipProof.d.ts +28 -28
- package/lib/types/api/getPublicKey.d.ts +24 -24
- package/lib/types/api/getPublicKey.js +1 -1
- package/lib/types/api/index.d.ts +4 -8
- package/lib/types/api/init.d.ts +4 -2
- package/lib/types/api/loadDevice.d.ts +4 -0
- package/lib/types/api/loadDevice.js +3 -0
- package/lib/types/api/nem/index.d.ts +612 -612
- package/lib/types/api/nem/index.js +1 -1
- package/lib/types/api/nemGetAddress.d.ts +6 -6
- package/lib/types/api/pushTransaction.d.ts +3 -3
- package/lib/types/api/recoveryDevice.d.ts +9 -9
- package/lib/types/api/requestLogin.d.ts +25 -25
- package/lib/types/api/ripple/index.d.ts +21 -21
- package/lib/types/api/ripple/index.js +1 -1
- package/lib/types/api/solana/index.d.ts +23 -23
- package/lib/types/api/solana/index.js +1 -1
- package/lib/types/api/stellar/index.d.ts +582 -582
- package/lib/types/api/stellar/index.js +1 -1
- package/lib/types/api/tezos/index.d.ts +120 -120
- package/lib/types/api/tezos/index.js +1 -1
- package/lib/types/api/unlockPath.d.ts +2 -2
- package/lib/types/coinInfo.d.ts +231 -224
- package/lib/types/device.d.ts +33 -14
- package/lib/types/device.js +3 -1
- package/lib/types/fees.d.ts +19 -19
- package/lib/types/firmware.d.ts +1 -1
- package/lib/types/params.d.ts +23 -19
- package/lib/types/settings.d.ts +17 -10
- package/lib/types/utils.d.ts +1 -0
- package/lib/types/utils.js +3 -0
- package/lib/utils/addressUtils.js +2 -2
- package/lib/utils/assetUtils.d.ts +1 -1
- package/lib/utils/assetUtils.js +6 -6
- package/lib/utils/assets.js +1 -1
- package/lib/utils/assets.native.js +1 -1
- package/lib/utils/deviceFeaturesUtils.js +1 -1
- package/lib/utils/proxy-event-emitter.d.ts +21 -0
- package/lib/utils/proxy-event-emitter.js +65 -0
- package/lib/utils/uiPromiseManager.d.ts +2 -1
- package/lib/utils/uiPromiseManager.js +3 -3
- package/package.json +12 -12
- package/lib/api/checkFirmwareAuthenticity.d.ts +0 -11
- package/lib/api/checkFirmwareAuthenticity.js +0 -56
- package/lib/types/api/checkFirmwareAuthenticity.d.ts +0 -11
package/lib/device/Device.js
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.Device = exports.GET_FEATURES_TIMEOUT_REACT_NATIVE = exports.GET_FEATURES_TIMEOUT = void 0;
|
|
4
|
+
const crypto_1 = require("crypto");
|
|
4
5
|
const utils_1 = require("@trezor/utils");
|
|
5
6
|
const protocol_1 = require("@trezor/protocol");
|
|
7
|
+
const transport_1 = require("@trezor/transport");
|
|
6
8
|
const DeviceCommands_1 = require("./DeviceCommands");
|
|
7
9
|
const constants_1 = require("../constants");
|
|
8
10
|
const events_1 = require("../events");
|
|
@@ -11,11 +13,11 @@ const DataManager_1 = require("../data/DataManager");
|
|
|
11
13
|
const firmwareInfo_1 = require("../data/firmwareInfo");
|
|
12
14
|
const deviceFeaturesUtils_1 = require("../utils/deviceFeaturesUtils");
|
|
13
15
|
const debug_1 = require("../utils/debug");
|
|
14
|
-
const transport_1 = require("@trezor/transport");
|
|
15
16
|
const types_1 = require("../types");
|
|
16
17
|
const models_1 = require("../data/models");
|
|
17
18
|
const getLanguage_1 = require("../data/getLanguage");
|
|
18
19
|
const checkFirmwareRevision_1 = require("./checkFirmwareRevision");
|
|
20
|
+
const firmware_1 = require("../api/firmware");
|
|
19
21
|
const _log = (0, debug_1.initLog)('Device');
|
|
20
22
|
exports.GET_FEATURES_TIMEOUT = 3000;
|
|
21
23
|
exports.GET_FEATURES_TIMEOUT_REACT_NATIVE = 20000;
|
|
@@ -25,98 +27,192 @@ const parseRunOptions = (options) => {
|
|
|
25
27
|
return options;
|
|
26
28
|
};
|
|
27
29
|
class Device extends utils_1.TypedEmitter {
|
|
28
|
-
|
|
30
|
+
get firmwareStatus() {
|
|
31
|
+
return this._firmwareStatus;
|
|
32
|
+
}
|
|
33
|
+
get firmwareRelease() {
|
|
34
|
+
return this._firmwareRelease;
|
|
35
|
+
}
|
|
36
|
+
get features() {
|
|
37
|
+
return this._features;
|
|
38
|
+
}
|
|
39
|
+
get unavailableCapabilities() {
|
|
40
|
+
return this._unavailableCapabilities;
|
|
41
|
+
}
|
|
42
|
+
get firmwareType() {
|
|
43
|
+
return this._firmwareType;
|
|
44
|
+
}
|
|
45
|
+
constructor({ id, transport, descriptor, listener }) {
|
|
29
46
|
super();
|
|
30
|
-
this.
|
|
47
|
+
this._featuresNeedsReload = false;
|
|
31
48
|
this.keepTransportSession = false;
|
|
32
49
|
this.loaded = false;
|
|
33
50
|
this.inconsistent = false;
|
|
34
51
|
this.instance = 0;
|
|
35
52
|
this.state = [];
|
|
36
53
|
this.stateStorage = undefined;
|
|
37
|
-
this.
|
|
38
|
-
this.networkTypeState = [];
|
|
54
|
+
this._unavailableCapabilities = {};
|
|
39
55
|
this.name = 'Trezor';
|
|
40
56
|
this.availableTranslations = [];
|
|
41
57
|
this.authenticityChecks = {
|
|
42
58
|
firmwareRevision: null,
|
|
59
|
+
firmwareHash: null,
|
|
43
60
|
};
|
|
44
|
-
this.
|
|
61
|
+
this.emitLifecycle = listener;
|
|
45
62
|
this.protocol = protocol_1.v1;
|
|
63
|
+
this.uniquePath = id;
|
|
46
64
|
this.transport = transport;
|
|
47
|
-
this.
|
|
65
|
+
this.transportPath = descriptor.path;
|
|
66
|
+
this.transportSessionOwner = descriptor.sessionOwner;
|
|
67
|
+
this.transportDescriptorType = descriptor.type;
|
|
68
|
+
this.session = descriptor.session;
|
|
69
|
+
this.lastAcquiredHere = false;
|
|
48
70
|
this.firstRunPromise = (0, utils_1.createDeferred)();
|
|
49
71
|
}
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
catch (error) {
|
|
57
|
-
_log.error('Device.fromDescriptor', error);
|
|
58
|
-
throw error;
|
|
72
|
+
getSessionChangePromise() {
|
|
73
|
+
if (!this.sessionDfd) {
|
|
74
|
+
this.sessionDfd = (0, utils_1.createDeferred)();
|
|
75
|
+
this.sessionDfd.promise.finally(() => {
|
|
76
|
+
this.sessionDfd = undefined;
|
|
77
|
+
});
|
|
59
78
|
}
|
|
79
|
+
return this.sessionDfd.promise;
|
|
60
80
|
}
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
81
|
+
async waitAndCompareSession(response, sessionPromise) {
|
|
82
|
+
if (response.success) {
|
|
83
|
+
try {
|
|
84
|
+
if ((await sessionPromise) !== response.payload) {
|
|
85
|
+
return {
|
|
86
|
+
success: false,
|
|
87
|
+
error: transport_1.TRANSPORT_ERROR.SESSION_WRONG_PREVIOUS,
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
catch {
|
|
92
|
+
return {
|
|
93
|
+
success: false,
|
|
94
|
+
error: transport_1.TRANSPORT_ERROR.DEVICE_DISCONNECTED_DURING_ACTION,
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
return response;
|
|
99
|
+
}
|
|
100
|
+
acquire() {
|
|
101
|
+
const sessionPromise = this.getSessionChangePromise();
|
|
102
|
+
this.acquirePromise = this.transport
|
|
103
|
+
.acquire({ input: { path: this.transportPath, previous: this.session } })
|
|
104
|
+
.then(result => this.waitAndCompareSession(result, sessionPromise))
|
|
105
|
+
.then(result => {
|
|
106
|
+
var _a;
|
|
107
|
+
if (result.success) {
|
|
108
|
+
this.session = result.payload;
|
|
109
|
+
this.lastAcquiredHere = true;
|
|
110
|
+
(_a = this.commands) === null || _a === void 0 ? void 0 : _a.dispose();
|
|
111
|
+
this.commands = new DeviceCommands_1.DeviceCommands(this, this.transport, this.session);
|
|
112
|
+
return result;
|
|
113
|
+
}
|
|
114
|
+
else {
|
|
115
|
+
if (this.runPromise) {
|
|
116
|
+
this.runPromise.reject(new Error(result.error));
|
|
117
|
+
delete this.runPromise;
|
|
118
|
+
}
|
|
119
|
+
throw result.error;
|
|
79
120
|
}
|
|
80
|
-
|
|
121
|
+
})
|
|
122
|
+
.finally(() => {
|
|
123
|
+
this.acquirePromise = undefined;
|
|
124
|
+
});
|
|
125
|
+
return this.acquirePromise;
|
|
126
|
+
}
|
|
127
|
+
async release() {
|
|
128
|
+
const localSession = this.getLocalSession();
|
|
129
|
+
if (!localSession || this.keepTransportSession || this.releasePromise) {
|
|
130
|
+
return;
|
|
81
131
|
}
|
|
82
|
-
const transportSession = acquireResult.payload;
|
|
83
|
-
_log.debug('Expected workflow id:', transportSession);
|
|
84
|
-
this.transportSession = transportSession;
|
|
85
|
-
this.originalDescriptor.session = transportSession;
|
|
86
132
|
if (this.commands) {
|
|
87
133
|
this.commands.dispose();
|
|
134
|
+
if (this.commands.callPromise) {
|
|
135
|
+
await this.commands.callPromise;
|
|
136
|
+
}
|
|
88
137
|
}
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
if (this.commands) {
|
|
97
|
-
this.commands.dispose();
|
|
98
|
-
if (this.commands.callPromise) {
|
|
99
|
-
await this.commands.callPromise;
|
|
100
|
-
}
|
|
138
|
+
const sessionPromise = this.getSessionChangePromise();
|
|
139
|
+
this.releasePromise = this.transport
|
|
140
|
+
.release({ session: localSession, path: this.transportPath })
|
|
141
|
+
.then(result => this.waitAndCompareSession(result, sessionPromise))
|
|
142
|
+
.then(result => {
|
|
143
|
+
if (result.success) {
|
|
144
|
+
this.session = null;
|
|
101
145
|
}
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
});
|
|
106
|
-
const releaseResponse = await this.releasePromise;
|
|
146
|
+
return result;
|
|
147
|
+
})
|
|
148
|
+
.finally(() => {
|
|
107
149
|
this.releasePromise = undefined;
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
150
|
+
});
|
|
151
|
+
return this.releasePromise;
|
|
152
|
+
}
|
|
153
|
+
releaseTransportSession() {
|
|
154
|
+
this.keepTransportSession = false;
|
|
113
155
|
}
|
|
114
156
|
async cleanup() {
|
|
115
|
-
|
|
116
|
-
this.removeAllListeners();
|
|
157
|
+
this.eventNames().forEach(e => this.removeAllListeners(e));
|
|
117
158
|
delete this.runPromise;
|
|
118
159
|
await this.release();
|
|
119
|
-
|
|
160
|
+
}
|
|
161
|
+
async handshake(delay) {
|
|
162
|
+
var _a;
|
|
163
|
+
if (delay) {
|
|
164
|
+
await (0, utils_1.createTimeoutPromise)(501 + delay);
|
|
165
|
+
}
|
|
166
|
+
while (true) {
|
|
167
|
+
if (this.isUsedElsewhere()) {
|
|
168
|
+
this.emitLifecycle(events_1.DEVICE.CONNECT_UNACQUIRED);
|
|
169
|
+
}
|
|
170
|
+
else {
|
|
171
|
+
try {
|
|
172
|
+
await this.run();
|
|
173
|
+
}
|
|
174
|
+
catch (error) {
|
|
175
|
+
if (error.code === 'Device_NotFound' ||
|
|
176
|
+
error.message === transport_1.TRANSPORT_ERROR.DEVICE_NOT_FOUND ||
|
|
177
|
+
error.message === transport_1.TRANSPORT_ERROR.DEVICE_DISCONNECTED_DURING_ACTION ||
|
|
178
|
+
error.message === transport_1.TRANSPORT_ERROR.UNEXPECTED_ERROR ||
|
|
179
|
+
error.message === transport_1.TRANSPORT_ERROR.DESCRIPTOR_NOT_FOUND ||
|
|
180
|
+
error.message === transport_1.TRANSPORT_ERROR.HTTP_ERROR) {
|
|
181
|
+
}
|
|
182
|
+
else if (error.message === transport_1.TRANSPORT_ERROR.SESSION_WRONG_PREVIOUS ||
|
|
183
|
+
error.code === 'Device_UsedElsewhere') {
|
|
184
|
+
this.emitLifecycle(events_1.DEVICE.CONNECT_UNACQUIRED);
|
|
185
|
+
}
|
|
186
|
+
else if (error.message === transport_1.TRANSPORT_ERROR.INTERFACE_UNABLE_TO_OPEN_DEVICE ||
|
|
187
|
+
((_a = error.message) === null || _a === void 0 ? void 0 : _a.indexOf(constants_1.ERRORS.LIBUSB_ERROR_MESSAGE)) >= 0 ||
|
|
188
|
+
error.code === 'Device_InitializeFailed') {
|
|
189
|
+
this.unreadableError = error === null || error === void 0 ? void 0 : error.message;
|
|
190
|
+
this.emitLifecycle(events_1.DEVICE.CONNECT_UNACQUIRED);
|
|
191
|
+
}
|
|
192
|
+
else {
|
|
193
|
+
await (0, utils_1.createTimeoutPromise)(501);
|
|
194
|
+
continue;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
async updateDescriptor(descriptor) {
|
|
202
|
+
var _a, _b;
|
|
203
|
+
(_a = this.sessionDfd) === null || _a === void 0 ? void 0 : _a.resolve(descriptor.session);
|
|
204
|
+
await Promise.all([this.acquirePromise, this.releasePromise]);
|
|
205
|
+
if (descriptor.session && descriptor.session !== this.session) {
|
|
206
|
+
this.usedElsewhere();
|
|
207
|
+
}
|
|
208
|
+
if (!descriptor.session) {
|
|
209
|
+
const methodStillRunning = !((_b = this.commands) === null || _b === void 0 ? void 0 : _b.isDisposed());
|
|
210
|
+
if (methodStillRunning) {
|
|
211
|
+
this.releaseTransportSession();
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
this.session = descriptor.session;
|
|
215
|
+
this.emitLifecycle(events_1.DEVICE.CHANGED);
|
|
120
216
|
}
|
|
121
217
|
run(fn, options) {
|
|
122
218
|
if (this.runPromise) {
|
|
@@ -124,9 +220,16 @@ class Device extends utils_1.TypedEmitter {
|
|
|
124
220
|
throw constants_1.ERRORS.TypedError('Device_CallInProgress');
|
|
125
221
|
}
|
|
126
222
|
options = parseRunOptions(options);
|
|
223
|
+
const wasUnacquired = this.isUnacquired();
|
|
127
224
|
const runPromise = (0, utils_1.createDeferred)();
|
|
128
225
|
this.runPromise = runPromise;
|
|
129
|
-
this._runInner(fn, options)
|
|
226
|
+
this._runInner(fn, options)
|
|
227
|
+
.then(() => {
|
|
228
|
+
if (wasUnacquired && !this.isUnacquired()) {
|
|
229
|
+
this.emitLifecycle(events_1.DEVICE.CONNECT);
|
|
230
|
+
}
|
|
231
|
+
})
|
|
232
|
+
.catch(err => {
|
|
130
233
|
runPromise.reject(err);
|
|
131
234
|
});
|
|
132
235
|
return runPromise.promise;
|
|
@@ -164,7 +267,12 @@ class Device extends utils_1.TypedEmitter {
|
|
|
164
267
|
delete this.runPromise;
|
|
165
268
|
}
|
|
166
269
|
}
|
|
167
|
-
|
|
270
|
+
usedElsewhere() {
|
|
271
|
+
if (!this.lastAcquiredHere) {
|
|
272
|
+
return;
|
|
273
|
+
}
|
|
274
|
+
this.lastAcquiredHere = false;
|
|
275
|
+
this._featuresNeedsReload = true;
|
|
168
276
|
_log.debug('interruptionFromOutside');
|
|
169
277
|
if (this.commands) {
|
|
170
278
|
this.commands.dispose();
|
|
@@ -173,19 +281,20 @@ class Device extends utils_1.TypedEmitter {
|
|
|
173
281
|
this.runPromise.reject(constants_1.ERRORS.TypedError('Device_UsedElsewhere'));
|
|
174
282
|
delete this.runPromise;
|
|
175
283
|
}
|
|
176
|
-
if (this.
|
|
177
|
-
this.transport.releaseDevice(this.
|
|
284
|
+
if (this.session) {
|
|
285
|
+
this.transport.releaseDevice(this.session);
|
|
178
286
|
}
|
|
179
287
|
}
|
|
180
288
|
async _runInner(fn, options) {
|
|
181
|
-
var _a
|
|
289
|
+
var _a;
|
|
182
290
|
if (this.releasePromise) {
|
|
183
291
|
await this.releasePromise;
|
|
184
292
|
}
|
|
293
|
+
const { staticSessionId, deriveCardano } = this.getState() || {};
|
|
185
294
|
if (!this.isUsedHere() ||
|
|
186
295
|
((_a = this.commands) === null || _a === void 0 ? void 0 : _a.disposed) ||
|
|
187
|
-
!
|
|
188
|
-
|
|
296
|
+
!staticSessionId ||
|
|
297
|
+
(!deriveCardano && options.useCardanoDerivation)) {
|
|
189
298
|
await this.acquire();
|
|
190
299
|
try {
|
|
191
300
|
if (fn) {
|
|
@@ -218,9 +327,6 @@ class Device extends utils_1.TypedEmitter {
|
|
|
218
327
|
if (options.keepSession) {
|
|
219
328
|
this.keepTransportSession = true;
|
|
220
329
|
}
|
|
221
|
-
if (this.listeners(events_1.DEVICE.ACQUIRED).length > 0) {
|
|
222
|
-
this.emit(events_1.DEVICE.ACQUIRED);
|
|
223
|
-
}
|
|
224
330
|
if (fn) {
|
|
225
331
|
await fn();
|
|
226
332
|
}
|
|
@@ -250,7 +356,7 @@ class Device extends utils_1.TypedEmitter {
|
|
|
250
356
|
setInstance(instance = 0) {
|
|
251
357
|
if (this.instance !== instance) {
|
|
252
358
|
if (this.keepTransportSession) {
|
|
253
|
-
this.
|
|
359
|
+
this.lastAcquiredHere = false;
|
|
254
360
|
this.keepTransportSession = false;
|
|
255
361
|
}
|
|
256
362
|
}
|
|
@@ -300,19 +406,19 @@ class Device extends utils_1.TypedEmitter {
|
|
|
300
406
|
}
|
|
301
407
|
}
|
|
302
408
|
async initialize(useCardanoDerivation) {
|
|
303
|
-
var _a;
|
|
304
409
|
let payload;
|
|
305
410
|
if (this.features) {
|
|
306
|
-
const sessionId
|
|
307
|
-
payload = {
|
|
308
|
-
|
|
309
|
-
|
|
411
|
+
const { sessionId, deriveCardano } = this.getState() || {};
|
|
412
|
+
payload = {
|
|
413
|
+
derive_cardano: deriveCardano || useCardanoDerivation,
|
|
414
|
+
};
|
|
310
415
|
if (sessionId) {
|
|
311
416
|
payload.session_id = sessionId;
|
|
312
417
|
}
|
|
313
418
|
}
|
|
314
419
|
const { message } = await this.getCommands().typedCall('Initialize', 'Features', payload);
|
|
315
420
|
this._updateFeatures(message);
|
|
421
|
+
this.setState({ deriveCardano: payload === null || payload === void 0 ? void 0 : payload.derive_cardano });
|
|
316
422
|
}
|
|
317
423
|
initStorage(storage) {
|
|
318
424
|
this.stateStorage = storage;
|
|
@@ -321,9 +427,12 @@ class Device extends utils_1.TypedEmitter {
|
|
|
321
427
|
async getFeatures() {
|
|
322
428
|
const { message } = await this.getCommands().typedCall('GetFeatures', 'Features', {});
|
|
323
429
|
this._updateFeatures(message);
|
|
430
|
+
if (this.authenticityChecks.firmwareHash === null) {
|
|
431
|
+
this.authenticityChecks.firmwareHash = await this.checkFirmwareHash();
|
|
432
|
+
}
|
|
324
433
|
if (this.authenticityChecks.firmwareRevision === null ||
|
|
325
434
|
(this.authenticityChecks.firmwareRevision.success === false &&
|
|
326
|
-
|
|
435
|
+
['cannot-perform-check-offline', 'other-error'].includes(this.authenticityChecks.firmwareRevision.error))) {
|
|
327
436
|
await this.checkFirmwareRevision();
|
|
328
437
|
}
|
|
329
438
|
if (!this.features.language_version_matches &&
|
|
@@ -338,6 +447,51 @@ class Device extends utils_1.TypedEmitter {
|
|
|
338
447
|
}
|
|
339
448
|
}
|
|
340
449
|
}
|
|
450
|
+
async checkFirmwareHash() {
|
|
451
|
+
var _a;
|
|
452
|
+
const createFailResult = (error) => ({ success: false, error });
|
|
453
|
+
const baseUrl = DataManager_1.DataManager.getSettings('binFilesBaseUrl');
|
|
454
|
+
const enabled = DataManager_1.DataManager.getSettings('enableFirmwareHashCheck');
|
|
455
|
+
if (!enabled || baseUrl === undefined)
|
|
456
|
+
return createFailResult('check-skipped');
|
|
457
|
+
const firmwareVersion = this.getVersion();
|
|
458
|
+
if (firmwareVersion === undefined || !this.features || this.features.bootloader_mode) {
|
|
459
|
+
return null;
|
|
460
|
+
}
|
|
461
|
+
const checkSupported = this.atLeast(constants_1.FIRMWARE.FW_HASH_SUPPORTED_VERSIONS);
|
|
462
|
+
if (!checkSupported)
|
|
463
|
+
return createFailResult('check-unsupported');
|
|
464
|
+
const release = (0, firmwareInfo_1.getReleases)(this.features.internal_model).find(r => utils_1.versionUtils.isEqual(r.version, firmwareVersion));
|
|
465
|
+
if (release === undefined)
|
|
466
|
+
return createFailResult('unknown-release');
|
|
467
|
+
const btcOnly = this.firmwareType === types_1.FirmwareType.BitcoinOnly;
|
|
468
|
+
const binary = await (0, firmware_1.getBinaryOptional)({ baseUrl, btcOnly, release });
|
|
469
|
+
if (binary === null) {
|
|
470
|
+
return createFailResult('check-unsupported');
|
|
471
|
+
}
|
|
472
|
+
if (binary.byteLength < 200) {
|
|
473
|
+
_log.warn(`Firmware binary for hash check suspiciously small (< 200 b)`);
|
|
474
|
+
return createFailResult('check-unsupported');
|
|
475
|
+
}
|
|
476
|
+
const strippedBinary = (0, firmware_1.stripFwHeaders)(binary);
|
|
477
|
+
const { hash: expectedHash, challenge } = (0, firmware_1.calculateFirmwareHash)(this.features.major_version, strippedBinary, (0, crypto_1.randomBytes)(32));
|
|
478
|
+
const getFirmwareHashOptional = async () => {
|
|
479
|
+
try {
|
|
480
|
+
return await this.getCommands().typedCall('GetFirmwareHash', 'FirmwareHash', {
|
|
481
|
+
challenge,
|
|
482
|
+
});
|
|
483
|
+
}
|
|
484
|
+
catch {
|
|
485
|
+
return null;
|
|
486
|
+
}
|
|
487
|
+
};
|
|
488
|
+
const deviceResponse = await getFirmwareHashOptional();
|
|
489
|
+
if (!((_a = deviceResponse === null || deviceResponse === void 0 ? void 0 : deviceResponse.message) === null || _a === void 0 ? void 0 : _a.hash))
|
|
490
|
+
return createFailResult('other-error');
|
|
491
|
+
if (deviceResponse.message.hash !== expectedHash)
|
|
492
|
+
return createFailResult('hash-mismatch');
|
|
493
|
+
return { success: true };
|
|
494
|
+
}
|
|
341
495
|
async checkFirmwareRevision() {
|
|
342
496
|
const firmwareVersion = this.getVersion();
|
|
343
497
|
if (!firmwareVersion || !this.features) {
|
|
@@ -421,21 +575,21 @@ class Device extends utils_1.TypedEmitter {
|
|
|
421
575
|
feat.patch_version,
|
|
422
576
|
];
|
|
423
577
|
if (!version || !utils_1.versionUtils.isEqual(version, newVersion)) {
|
|
424
|
-
this.
|
|
425
|
-
this.
|
|
426
|
-
this.
|
|
578
|
+
this._unavailableCapabilities = (0, deviceFeaturesUtils_1.getUnavailableCapabilities)(feat, (0, coinInfo_1.getAllNetworks)());
|
|
579
|
+
this._firmwareStatus = (0, firmwareInfo_1.getFirmwareStatus)(feat);
|
|
580
|
+
this._firmwareRelease = (0, firmwareInfo_1.getRelease)(feat);
|
|
427
581
|
this.availableTranslations = (_c = (_b = this.firmwareRelease) === null || _b === void 0 ? void 0 : _b.translations) !== null && _c !== void 0 ? _c : [];
|
|
428
582
|
}
|
|
429
|
-
this.
|
|
430
|
-
this.
|
|
583
|
+
this._features = feat;
|
|
584
|
+
this._featuresNeedsReload = false;
|
|
431
585
|
if (feat.fw_vendor === 'Trezor Bitcoin-only') {
|
|
432
|
-
this.
|
|
586
|
+
this._firmwareType = types_1.FirmwareType.BitcoinOnly;
|
|
433
587
|
}
|
|
434
588
|
else if (feat.fw_vendor === 'Trezor') {
|
|
435
|
-
this.
|
|
589
|
+
this._firmwareType = types_1.FirmwareType.Regular;
|
|
436
590
|
}
|
|
437
591
|
else if (this.getMode() !== 'bootloader') {
|
|
438
|
-
this.
|
|
592
|
+
this._firmwareType =
|
|
439
593
|
feat.capabilities &&
|
|
440
594
|
feat.capabilities.length > 0 &&
|
|
441
595
|
!feat.capabilities.includes('Capability_Bitcoin_like')
|
|
@@ -457,9 +611,15 @@ class Device extends utils_1.TypedEmitter {
|
|
|
457
611
|
isUnacquired() {
|
|
458
612
|
return this.features === undefined;
|
|
459
613
|
}
|
|
614
|
+
isUnreadable() {
|
|
615
|
+
return !!this.unreadableError;
|
|
616
|
+
}
|
|
460
617
|
disconnect() {
|
|
618
|
+
var _a;
|
|
461
619
|
_log.debug('Disconnect cleanup');
|
|
462
|
-
this.
|
|
620
|
+
(_a = this.sessionDfd) === null || _a === void 0 ? void 0 : _a.reject(new Error());
|
|
621
|
+
this.lastAcquiredHere = false;
|
|
622
|
+
this.emitLifecycle(events_1.DEVICE.DISCONNECT);
|
|
463
623
|
return this.interruptionFromUser(constants_1.ERRORS.TypedError('Device_Disconnected'));
|
|
464
624
|
}
|
|
465
625
|
isBootloader() {
|
|
@@ -491,13 +651,13 @@ class Device extends utils_1.TypedEmitter {
|
|
|
491
651
|
return utils_1.versionUtils.isNewerOrEqual(version, modelVersion);
|
|
492
652
|
}
|
|
493
653
|
isUsed() {
|
|
494
|
-
return typeof this.
|
|
654
|
+
return typeof this.session === 'string';
|
|
495
655
|
}
|
|
496
656
|
isUsedHere() {
|
|
497
|
-
return this.isUsed() && this.
|
|
657
|
+
return this.isUsed() && this.lastAcquiredHere;
|
|
498
658
|
}
|
|
499
659
|
isUsedElsewhere() {
|
|
500
|
-
return this.isUsed() && !this.
|
|
660
|
+
return this.isUsed() && !this.lastAcquiredHere;
|
|
501
661
|
}
|
|
502
662
|
isRunning() {
|
|
503
663
|
return !!this.runPromise;
|
|
@@ -508,8 +668,11 @@ class Device extends utils_1.TypedEmitter {
|
|
|
508
668
|
waitForFirstRun() {
|
|
509
669
|
return this.firstRunPromise.promise;
|
|
510
670
|
}
|
|
511
|
-
|
|
512
|
-
return this.
|
|
671
|
+
getLocalSession() {
|
|
672
|
+
return this.lastAcquiredHere ? this.session : null;
|
|
673
|
+
}
|
|
674
|
+
getUniquePath() {
|
|
675
|
+
return this.uniquePath;
|
|
513
676
|
}
|
|
514
677
|
isT1() {
|
|
515
678
|
return this.features ? this.features.major_version === 1 : false;
|
|
@@ -531,28 +694,20 @@ class Device extends utils_1.TypedEmitter {
|
|
|
531
694
|
}
|
|
532
695
|
return null;
|
|
533
696
|
}
|
|
534
|
-
updateDescriptor(descriptor) {
|
|
535
|
-
this.originalDescriptor = {
|
|
536
|
-
session: descriptor.session,
|
|
537
|
-
path: descriptor.path,
|
|
538
|
-
product: descriptor.product,
|
|
539
|
-
type: descriptor.type,
|
|
540
|
-
};
|
|
541
|
-
}
|
|
542
697
|
async dispose() {
|
|
543
698
|
var _a, _b;
|
|
544
699
|
this.removeAllListeners();
|
|
545
|
-
if (this.
|
|
700
|
+
if (this.session && this.lastAcquiredHere) {
|
|
546
701
|
try {
|
|
547
702
|
await ((_a = this.cancelableAction) === null || _a === void 0 ? void 0 : _a.call(this));
|
|
548
703
|
await ((_b = this.commands) === null || _b === void 0 ? void 0 : _b.cancel());
|
|
549
704
|
return this.transport.release({
|
|
550
|
-
session: this.
|
|
551
|
-
path: this.
|
|
705
|
+
session: this.session,
|
|
706
|
+
path: this.transportPath,
|
|
552
707
|
onClose: true,
|
|
553
708
|
});
|
|
554
709
|
}
|
|
555
|
-
catch
|
|
710
|
+
catch {
|
|
556
711
|
}
|
|
557
712
|
}
|
|
558
713
|
}
|
|
@@ -567,38 +722,40 @@ class Device extends utils_1.TypedEmitter {
|
|
|
567
722
|
}
|
|
568
723
|
toMessageObject() {
|
|
569
724
|
var _a;
|
|
725
|
+
const { name, uniquePath: path } = this;
|
|
726
|
+
const base = { path, name };
|
|
570
727
|
if (this.unreadableError) {
|
|
571
728
|
return {
|
|
729
|
+
...base,
|
|
572
730
|
type: 'unreadable',
|
|
573
|
-
path: this.originalDescriptor.path,
|
|
574
731
|
error: this.unreadableError,
|
|
575
732
|
label: 'Unreadable device',
|
|
576
|
-
|
|
733
|
+
transportDescriptorType: this.transportDescriptorType,
|
|
577
734
|
};
|
|
578
735
|
}
|
|
579
736
|
if (this.isUnacquired()) {
|
|
580
737
|
return {
|
|
738
|
+
...base,
|
|
581
739
|
type: 'unacquired',
|
|
582
|
-
path: this.originalDescriptor.path,
|
|
583
740
|
label: 'Unacquired device',
|
|
584
741
|
name: this.name,
|
|
742
|
+
transportSessionOwner: this.transportSessionOwner,
|
|
585
743
|
};
|
|
586
744
|
}
|
|
587
745
|
const defaultLabel = 'My Trezor';
|
|
588
746
|
const label = this.features.label === '' || !this.features.label ? defaultLabel : this.features.label;
|
|
589
747
|
let status = this.isUsedElsewhere() ? 'occupied' : 'available';
|
|
590
|
-
if (this.
|
|
748
|
+
if (this._featuresNeedsReload)
|
|
591
749
|
status = 'used';
|
|
592
750
|
return {
|
|
751
|
+
...base,
|
|
593
752
|
type: 'acquired',
|
|
594
753
|
id: this.features.device_id,
|
|
595
|
-
path: this.originalDescriptor.path,
|
|
596
754
|
label,
|
|
597
755
|
_state: this.getState(),
|
|
598
756
|
state: (_a = this.getState()) === null || _a === void 0 ? void 0 : _a.staticSessionId,
|
|
599
757
|
status,
|
|
600
758
|
mode: this.getMode(),
|
|
601
|
-
name: this.name,
|
|
602
759
|
color: this.color,
|
|
603
760
|
firmware: this.firmwareStatus,
|
|
604
761
|
firmwareRelease: this.firmwareRelease,
|
|
@@ -5,6 +5,7 @@ const tslib_1 = require("tslib");
|
|
|
5
5
|
const crypto_1 = require("crypto");
|
|
6
6
|
const protobuf_1 = require("@trezor/protobuf");
|
|
7
7
|
const utils_1 = require("@trezor/utils");
|
|
8
|
+
const schema_utils_1 = require("@trezor/schema-utils");
|
|
8
9
|
const constants_1 = require("../constants");
|
|
9
10
|
const events_1 = require("../events");
|
|
10
11
|
const hdnodeUtils = tslib_1.__importStar(require("../utils/hdnodeUtils"));
|
|
@@ -12,7 +13,6 @@ const pathUtils_1 = require("../utils/pathUtils");
|
|
|
12
13
|
const accountUtils_1 = require("../utils/accountUtils");
|
|
13
14
|
const coinInfo_1 = require("../data/coinInfo");
|
|
14
15
|
const debug_1 = require("../utils/debug");
|
|
15
|
-
const schema_utils_1 = require("@trezor/schema-utils");
|
|
16
16
|
const resolveDescriptorForTaproot_1 = require("./resolveDescriptorForTaproot");
|
|
17
17
|
const prompts_1 = require("./prompts");
|
|
18
18
|
const logger = (0, debug_1.initLog)('DeviceCommands');
|
|
@@ -26,7 +26,7 @@ const generateEntropy = (len) => {
|
|
|
26
26
|
try {
|
|
27
27
|
return (0, crypto_1.randomBytes)(len);
|
|
28
28
|
}
|
|
29
|
-
catch
|
|
29
|
+
catch {
|
|
30
30
|
throw constants_1.ERRORS.TypedError('Runtime', 'generateEntropy: Environment does not support crypto random');
|
|
31
31
|
}
|
|
32
32
|
};
|
|
@@ -236,10 +236,10 @@ class DeviceCommands {
|
|
|
236
236
|
return response;
|
|
237
237
|
}
|
|
238
238
|
async _commonCall(type, msg) {
|
|
239
|
-
const resp = await this.call(type, msg);
|
|
240
239
|
if (this.disposed) {
|
|
241
240
|
throw constants_1.ERRORS.TypedError('Runtime', 'typedCall: DeviceCommands already disposed');
|
|
242
241
|
}
|
|
242
|
+
const resp = await this.call(type, msg);
|
|
243
243
|
return this._filterCommonTypes(resp);
|
|
244
244
|
}
|
|
245
245
|
_filterCommonTypes(res) {
|
|
@@ -361,7 +361,7 @@ class DeviceCommands {
|
|
|
361
361
|
await this.device.acquire();
|
|
362
362
|
await (0, prompts_1.cancelPrompt)(this.device, false);
|
|
363
363
|
}
|
|
364
|
-
catch
|
|
364
|
+
catch {
|
|
365
365
|
}
|
|
366
366
|
}
|
|
367
367
|
else {
|