@trezor/connect 9.2.3 → 9.2.4-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 +77 -5
- package/README.md +1 -1
- package/lib/api/applyFlags.d.ts +8 -1
- package/lib/api/applyFlags.js +3 -8
- package/lib/api/applySettings.d.ts +8 -1
- package/lib/api/applySettings.js +3 -8
- package/lib/api/backupDevice.d.ts +10 -2
- package/lib/api/backupDevice.js +12 -9
- package/lib/api/binance/api/binanceGetAddress.d.ts +4 -3
- package/lib/api/binance/api/binanceGetAddress.js +8 -22
- package/lib/api/binance/api/binanceGetPublicKey.d.ts +4 -2
- package/lib/api/binance/api/binanceGetPublicKey.js +6 -18
- package/lib/api/blockchainGetCurrentFiatRates.d.ts +1 -1
- package/lib/api/blockchainGetFiatRatesForTimestamps.d.ts +1 -1
- package/lib/api/cardano/api/cardanoGetAddress.d.ts +4 -4
- package/lib/api/cardano/api/cardanoGetAddress.js +9 -39
- package/lib/api/cardano/api/cardanoGetPublicKey.d.ts +4 -3
- package/lib/api/cardano/api/cardanoGetPublicKey.js +9 -31
- package/lib/api/cardano/api/cardanoSignTransaction.d.ts +1 -13
- package/lib/api/cardano/api/cardanoSignTransaction.js +2 -75
- package/lib/api/cardano/cardanoAddressParameters.d.ts +1 -2
- package/lib/api/cardano/cardanoAddressParameters.js +4 -10
- package/lib/api/cardano/cardanoAuxiliaryData.d.ts +1 -2
- package/lib/api/cardano/cardanoAuxiliaryData.js +2 -2
- package/lib/api/changeLanguage.d.ts +8 -1
- package/lib/api/changeLanguage.js +3 -7
- package/lib/api/eos/api/eosGetPublicKey.d.ts +4 -2
- package/lib/api/eos/api/eosGetPublicKey.js +6 -18
- package/lib/api/ethereum/api/ethereumGetAddress.d.ts +4 -3
- package/lib/api/ethereum/api/ethereumGetAddress.js +4 -20
- package/lib/api/ethereum/api/ethereumGetPublicKey.d.ts +4 -2
- package/lib/api/ethereum/api/ethereumGetPublicKey.js +3 -10
- package/lib/api/firmware/index.d.ts +2 -0
- package/lib/api/firmware/index.js +5 -1
- package/lib/api/firmware/parseFirmwareHeaders.d.ts +5 -0
- package/lib/api/firmware/parseFirmwareHeaders.js +35 -0
- package/lib/api/firmware/uploadFirmware.d.ts +1 -1
- package/lib/api/firmware/uploadFirmware.js +9 -1
- package/lib/api/getAccountDescriptor.d.ts +5 -3
- package/lib/api/getAccountDescriptor.js +8 -21
- package/lib/api/getAccountInfo.d.ts +23 -7
- package/lib/api/getAccountInfo.js +12 -25
- package/lib/api/getAddress.d.ts +4 -3
- package/lib/api/getAddress.js +8 -22
- package/lib/api/getFeatures.d.ts +1 -0
- package/lib/api/getOwnershipId.d.ts +4 -2
- package/lib/api/getOwnershipId.js +4 -15
- package/lib/api/getOwnershipProof.d.ts +4 -2
- package/lib/api/getOwnershipProof.js +4 -15
- package/lib/api/getPublicKey.d.ts +5 -4
- package/lib/api/getPublicKey.js +12 -35
- package/lib/api/index.d.ts +0 -1
- package/lib/api/index.js +1 -3
- package/lib/api/nem/api/nemGetAddress.d.ts +4 -3
- package/lib/api/nem/api/nemGetAddress.js +4 -20
- package/lib/api/rebootToBootloader.d.ts +8 -2
- package/lib/api/rebootToBootloader.js +3 -10
- package/lib/api/recoveryDevice.d.ts +8 -1
- package/lib/api/recoveryDevice.js +3 -7
- package/lib/api/resetDevice.d.ts +4 -2
- package/lib/api/resetDevice.js +3 -10
- package/lib/api/ripple/api/rippleGetAddress.d.ts +4 -3
- package/lib/api/ripple/api/rippleGetAddress.js +4 -20
- package/lib/api/solana/api/solanaGetAddress.d.ts +4 -3
- package/lib/api/solana/api/solanaGetAddress.js +7 -28
- package/lib/api/solana/api/solanaGetPublicKey.d.ts +4 -3
- package/lib/api/solana/api/solanaGetPublicKey.js +7 -27
- package/lib/api/stellar/api/stellarGetAddress.d.ts +4 -3
- package/lib/api/stellar/api/stellarGetAddress.js +4 -20
- package/lib/api/tezos/api/tezosGetAddress.d.ts +4 -3
- package/lib/api/tezos/api/tezosGetAddress.js +4 -20
- package/lib/api/tezos/api/tezosGetPublicKey.d.ts +4 -2
- package/lib/api/tezos/api/tezosGetPublicKey.js +6 -18
- package/lib/api/wipeDevice.d.ts +8 -2
- package/lib/api/wipeDevice.js +3 -10
- package/lib/backend/Blockchain.d.ts +2 -2
- package/lib/constants/errors.d.ts +1 -0
- package/lib/constants/errors.js +1 -0
- package/lib/core/AbstractMethod.d.ts +4 -8
- package/lib/core/AbstractMethod.js +6 -28
- package/lib/core/index.d.ts +2 -1
- package/lib/core/index.js +258 -226
- package/lib/core/onCallFirmwareUpdate.d.ts +31 -0
- package/lib/core/onCallFirmwareUpdate.js +266 -0
- package/lib/data/DataManager.d.ts +10 -0
- package/lib/data/analyticsInfo.d.ts +2 -2
- package/lib/data/analyticsInfo.js +6 -7
- package/lib/data/config.d.ts +10 -0
- package/lib/data/config.js +15 -5
- package/lib/data/deviceAuthenticityConfig.js +8 -4
- package/lib/data/firmwareInfo.js +1 -1
- package/lib/data/version.d.ts +1 -1
- package/lib/data/version.js +5 -2
- package/lib/device/Device.d.ts +2 -2
- package/lib/device/Device.js +4 -4
- package/lib/device/DeviceCommands.d.ts +4 -16
- package/lib/device/DeviceCommands.js +10 -72
- package/lib/device/DeviceList.d.ts +7 -4
- package/lib/device/DeviceList.js +46 -40
- package/lib/events/blockchain.d.ts +2 -2
- package/lib/events/index.d.ts +1 -0
- package/lib/events/ui-request.d.ts +13 -1
- package/lib/events/ui-request.js +1 -0
- package/lib/index.js +2 -2
- package/lib/types/api/backupDevice.d.ts +2 -2
- package/lib/types/api/dispose.d.ts +1 -1
- package/lib/types/api/firmwareUpdate.d.ts +7 -6
- package/lib/types/api/firmwareUpdate.js +1 -3
- package/lib/types/index.d.ts +1 -1
- package/lib/types/settings.d.ts +1 -1
- package/lib/utils/popupPromiseManager.d.ts +8 -0
- package/lib/utils/popupPromiseManager.js +21 -0
- package/lib/utils/uiPromiseManager.d.ts +38 -0
- package/lib/utils/uiPromiseManager.js +47 -0
- package/lib/workers/workers-browser.d.ts +3 -1
- package/lib/workers/workers-browser.js +2 -2
- package/package.json +9 -9
- package/lib/api/firmwareUpdate.d.ts +0 -19
- package/lib/api/firmwareUpdate.js +0 -78
package/lib/core/index.js
CHANGED
|
@@ -14,13 +14,14 @@ const constants_1 = require("../constants");
|
|
|
14
14
|
const events_2 = require("../events");
|
|
15
15
|
const method_1 = require("./method");
|
|
16
16
|
const promiseUtils_1 = require("../utils/promiseUtils");
|
|
17
|
+
const uiPromiseManager_1 = require("../utils/uiPromiseManager");
|
|
18
|
+
const popupPromiseManager_1 = require("../utils/popupPromiseManager");
|
|
17
19
|
const debug_1 = require("../utils/debug");
|
|
18
20
|
const BlockchainLink_1 = require("../backend/BlockchainLink");
|
|
19
21
|
const interactionTimeout_1 = require("../utils/interactionTimeout");
|
|
22
|
+
const onCallFirmwareUpdate_1 = require("./onCallFirmwareUpdate");
|
|
20
23
|
let _core;
|
|
21
24
|
let _deviceList;
|
|
22
|
-
let _popupPromise;
|
|
23
|
-
const _uiPromises = [];
|
|
24
25
|
const _callMethods = [];
|
|
25
26
|
let _interactionTimeout;
|
|
26
27
|
let _deviceListInitTimeout;
|
|
@@ -40,71 +41,16 @@ const postMessage = (message) => {
|
|
|
40
41
|
}
|
|
41
42
|
_core.emit(events_2.CORE_EVENT, message);
|
|
42
43
|
};
|
|
43
|
-
const
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
if (!_popupPromise) {
|
|
48
|
-
_popupPromise = (0, utils_1.createDeferred)();
|
|
49
|
-
}
|
|
50
|
-
return _popupPromise;
|
|
44
|
+
const popupPromise = (0, popupPromiseManager_1.createPopupPromiseManager)();
|
|
45
|
+
const waitForPopup = () => {
|
|
46
|
+
postMessage((0, events_2.createUiMessage)(events_2.UI.REQUEST_UI_WINDOW));
|
|
47
|
+
return popupPromise.wait();
|
|
51
48
|
};
|
|
52
49
|
const interactionTimeout = () => _interactionTimeout.start(() => {
|
|
53
50
|
onPopupClosed('Interaction timeout');
|
|
54
51
|
});
|
|
55
|
-
const
|
|
56
|
-
|
|
57
|
-
...(0, utils_1.createDeferred)(promiseEvent),
|
|
58
|
-
device,
|
|
59
|
-
};
|
|
60
|
-
_uiPromises.push(uiPromise);
|
|
61
|
-
interactionTimeout();
|
|
62
|
-
return uiPromise;
|
|
63
|
-
};
|
|
64
|
-
const findUiPromise = (promiseEvent) => _uiPromises.find(p => p.id === promiseEvent);
|
|
65
|
-
const removeUiPromise = (promise) => {
|
|
66
|
-
_uiPromises.splice(0).push(..._uiPromises.filter(p => p !== promise));
|
|
67
|
-
};
|
|
68
|
-
const handleMessage = (message) => {
|
|
69
|
-
_log.debug('handleMessage', message);
|
|
70
|
-
switch (message.type) {
|
|
71
|
-
case events_2.POPUP.HANDSHAKE:
|
|
72
|
-
getPopupPromise(false).resolve();
|
|
73
|
-
break;
|
|
74
|
-
case events_2.POPUP.CLOSED:
|
|
75
|
-
onPopupClosed(message.payload ? message.payload.error : null);
|
|
76
|
-
break;
|
|
77
|
-
case transport_1.TRANSPORT.DISABLE_WEBUSB:
|
|
78
|
-
disableWebUSBTransport();
|
|
79
|
-
break;
|
|
80
|
-
case transport_1.TRANSPORT.REQUEST_DEVICE:
|
|
81
|
-
_deviceList === null || _deviceList === void 0 ? void 0 : _deviceList.enumerate();
|
|
82
|
-
break;
|
|
83
|
-
case events_2.UI.RECEIVE_DEVICE:
|
|
84
|
-
case events_2.UI.RECEIVE_CONFIRMATION:
|
|
85
|
-
case events_2.UI.RECEIVE_PERMISSION:
|
|
86
|
-
case events_2.UI.RECEIVE_PIN:
|
|
87
|
-
case events_2.UI.RECEIVE_PASSPHRASE:
|
|
88
|
-
case events_2.UI.INVALID_PASSPHRASE_ACTION:
|
|
89
|
-
case events_2.UI.RECEIVE_ACCOUNT:
|
|
90
|
-
case events_2.UI.RECEIVE_FEE:
|
|
91
|
-
case events_2.UI.RECEIVE_WORD:
|
|
92
|
-
case events_2.UI.LOGIN_CHALLENGE_RESPONSE: {
|
|
93
|
-
const uiPromise = findUiPromise(message.type);
|
|
94
|
-
if (uiPromise) {
|
|
95
|
-
uiPromise.resolve(message);
|
|
96
|
-
removeUiPromise(uiPromise);
|
|
97
|
-
}
|
|
98
|
-
break;
|
|
99
|
-
}
|
|
100
|
-
case events_2.IFRAME.CALL:
|
|
101
|
-
onCall(message).catch(error => {
|
|
102
|
-
_log.error('onCall', error);
|
|
103
|
-
});
|
|
104
|
-
break;
|
|
105
|
-
}
|
|
106
|
-
};
|
|
107
|
-
const initDevice = async (method) => {
|
|
52
|
+
const uiPromises = (0, uiPromiseManager_1.createUiPromiseManager)(interactionTimeout);
|
|
53
|
+
const initDevice = async (devicePath) => {
|
|
108
54
|
if (!_deviceList) {
|
|
109
55
|
throw constants_1.ERRORS.TypedError('Transport_Missing');
|
|
110
56
|
}
|
|
@@ -123,8 +69,8 @@ const initDevice = async (method) => {
|
|
|
123
69
|
return store;
|
|
124
70
|
});
|
|
125
71
|
}
|
|
126
|
-
if (
|
|
127
|
-
device = _deviceList.getDevice(
|
|
72
|
+
if (devicePath) {
|
|
73
|
+
device = _deviceList.getDevice(devicePath);
|
|
128
74
|
showDeviceSelection =
|
|
129
75
|
!device || !!(device === null || device === void 0 ? void 0 : device.unreadableError) || (device.isUnacquired() && !!isUsingPopup);
|
|
130
76
|
}
|
|
@@ -140,8 +86,8 @@ const initDevice = async (method) => {
|
|
|
140
86
|
}
|
|
141
87
|
}
|
|
142
88
|
if (showDeviceSelection) {
|
|
143
|
-
|
|
144
|
-
await
|
|
89
|
+
uiPromises.create(events_2.UI.RECEIVE_DEVICE);
|
|
90
|
+
await waitForPopup();
|
|
145
91
|
if (!_deviceList) {
|
|
146
92
|
throw constants_1.ERRORS.TypedError('Transport_Missing');
|
|
147
93
|
}
|
|
@@ -158,9 +104,8 @@ const initDevice = async (method) => {
|
|
|
158
104
|
webusb: isWebUsb,
|
|
159
105
|
devices: _deviceList.asArray(),
|
|
160
106
|
}));
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
const { payload } = await uiPromise.promise;
|
|
107
|
+
if (uiPromises.exists(events_2.UI.RECEIVE_DEVICE)) {
|
|
108
|
+
const { payload } = await uiPromises.get(events_2.UI.RECEIVE_DEVICE);
|
|
164
109
|
if (payload.remember) {
|
|
165
110
|
const { label, path, state } = payload.device;
|
|
166
111
|
connect_common_1.storage.save(store => {
|
|
@@ -180,14 +125,164 @@ const initDevice = async (method) => {
|
|
|
180
125
|
}
|
|
181
126
|
return device;
|
|
182
127
|
};
|
|
128
|
+
const MAX_PIN_TRIES = 3;
|
|
129
|
+
const getInvalidDeviceState = async (device, preauthorized) => {
|
|
130
|
+
for (let i = 0; i < MAX_PIN_TRIES - 1; ++i) {
|
|
131
|
+
try {
|
|
132
|
+
return await device.validateState(preauthorized);
|
|
133
|
+
}
|
|
134
|
+
catch (error) {
|
|
135
|
+
if (error.message.includes('PIN invalid')) {
|
|
136
|
+
postMessage((0, events_2.createUiMessage)(events_2.UI.INVALID_PIN, { device: device.toMessageObject() }));
|
|
137
|
+
}
|
|
138
|
+
else {
|
|
139
|
+
throw error;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
return device.validateState(preauthorized);
|
|
144
|
+
};
|
|
145
|
+
const inner = async (method, device) => {
|
|
146
|
+
var _a;
|
|
147
|
+
const trustedHost = DataManager_1.DataManager.getSettings('trustedHost');
|
|
148
|
+
const isUsingPopup = (_a = DataManager_1.DataManager.getSettings('popup')) !== null && _a !== void 0 ? _a : false;
|
|
149
|
+
const firmwareException = method.checkFirmwareRange();
|
|
150
|
+
if (firmwareException) {
|
|
151
|
+
if (isUsingPopup) {
|
|
152
|
+
if (firmwareException === events_2.UI.FIRMWARE_NOT_COMPATIBLE) {
|
|
153
|
+
await waitForPopup();
|
|
154
|
+
const uiPromise = uiPromises.create(events_2.UI.RECEIVE_CONFIRMATION, device);
|
|
155
|
+
postMessage((0, events_2.createUiMessage)(events_2.UI.FIRMWARE_NOT_COMPATIBLE, device.toMessageObject()));
|
|
156
|
+
const uiResp = await uiPromise.promise;
|
|
157
|
+
if (!uiResp.payload) {
|
|
158
|
+
throw constants_1.ERRORS.TypedError('Method_PermissionsNotGranted');
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
else {
|
|
162
|
+
await waitForPopup();
|
|
163
|
+
postMessage((0, events_2.createUiMessage)(firmwareException, device.toMessageObject()));
|
|
164
|
+
await uiPromises.create(events_2.DEVICE.DISCONNECT, device).promise;
|
|
165
|
+
return Promise.reject(constants_1.ERRORS.TypedError('Method_Cancel'));
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
else {
|
|
169
|
+
return Promise.reject(constants_1.ERRORS.TypedError('Device_FwException', firmwareException));
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
const unexpectedMode = device.hasUnexpectedMode(method.allowDeviceMode, method.requireDeviceMode);
|
|
173
|
+
if (unexpectedMode) {
|
|
174
|
+
device.keepSession = false;
|
|
175
|
+
if (isUsingPopup) {
|
|
176
|
+
await waitForPopup();
|
|
177
|
+
postMessage((0, events_2.createUiMessage)(unexpectedMode, device.toMessageObject()));
|
|
178
|
+
await uiPromises.create(events_2.DEVICE.DISCONNECT, device).promise;
|
|
179
|
+
return Promise.reject(constants_1.ERRORS.TypedError('Device_ModeException', unexpectedMode));
|
|
180
|
+
}
|
|
181
|
+
return Promise.reject(constants_1.ERRORS.TypedError('Device_ModeException', unexpectedMode));
|
|
182
|
+
}
|
|
183
|
+
method.checkPermissions();
|
|
184
|
+
if (!trustedHost && method.requiredPermissions.length > 0) {
|
|
185
|
+
await waitForPopup();
|
|
186
|
+
const uiPromise = uiPromises.create(events_2.UI.RECEIVE_PERMISSION, device);
|
|
187
|
+
postMessage((0, events_2.createUiMessage)(events_2.UI.REQUEST_PERMISSION, {
|
|
188
|
+
permissions: method.requiredPermissions,
|
|
189
|
+
device: device.toMessageObject(),
|
|
190
|
+
}));
|
|
191
|
+
const { granted, remember } = await uiPromise.promise.then(({ payload }) => payload);
|
|
192
|
+
if (granted) {
|
|
193
|
+
method.savePermissions(!remember);
|
|
194
|
+
}
|
|
195
|
+
else {
|
|
196
|
+
return Promise.reject(constants_1.ERRORS.TypedError('Method_PermissionsNotGranted'));
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
const deviceNeedsBackup = device.features.needs_backup;
|
|
200
|
+
if (deviceNeedsBackup) {
|
|
201
|
+
if (method.noBackupConfirmationMode === 'always' ||
|
|
202
|
+
(method.noBackupConfirmationMode === 'popup-only' && isUsingPopup)) {
|
|
203
|
+
await waitForPopup();
|
|
204
|
+
const uiPromise = uiPromises.create(events_2.UI.RECEIVE_CONFIRMATION, device);
|
|
205
|
+
postMessage((0, analyticsInfo_1.enhanceMessageWithAnalytics)((0, events_2.createUiMessage)(events_2.UI.REQUEST_CONFIRMATION, {
|
|
206
|
+
view: 'no-backup',
|
|
207
|
+
}), { device: device.toMessageObject() }));
|
|
208
|
+
const permitted = await uiPromise.promise.then(({ payload }) => payload);
|
|
209
|
+
if (!permitted) {
|
|
210
|
+
return Promise.reject(constants_1.ERRORS.TypedError('Method_PermissionsNotGranted'));
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
await waitForPopup();
|
|
214
|
+
postMessage((0, events_2.createUiMessage)(events_2.UI.DEVICE_NEEDS_BACKUP, device.toMessageObject()));
|
|
215
|
+
}
|
|
216
|
+
if (device.firmwareStatus === 'outdated') {
|
|
217
|
+
await waitForPopup();
|
|
218
|
+
postMessage((0, events_2.createUiMessage)(events_2.UI.FIRMWARE_OUTDATED, device.toMessageObject()));
|
|
219
|
+
}
|
|
220
|
+
if (!trustedHost) {
|
|
221
|
+
const requestConfirmation = method.confirmation;
|
|
222
|
+
if (requestConfirmation) {
|
|
223
|
+
await waitForPopup();
|
|
224
|
+
const uiPromise = uiPromises.create(events_2.UI.RECEIVE_CONFIRMATION, device);
|
|
225
|
+
postMessage((0, analyticsInfo_1.enhanceMessageWithAnalytics)((0, events_2.createUiMessage)(events_2.UI.REQUEST_CONFIRMATION, requestConfirmation), { device: device.toMessageObject() }));
|
|
226
|
+
const confirmed = await uiPromise.promise.then(({ payload }) => payload);
|
|
227
|
+
if (!confirmed) {
|
|
228
|
+
return Promise.reject(constants_1.ERRORS.TypedError('Method_Cancel'));
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
const isDeviceUnlocked = device.features.unlocked;
|
|
233
|
+
if (method.useDeviceState) {
|
|
234
|
+
try {
|
|
235
|
+
let invalidDeviceState = await getInvalidDeviceState(device, method.preauthorized);
|
|
236
|
+
if (isUsingPopup) {
|
|
237
|
+
while (invalidDeviceState) {
|
|
238
|
+
const uiPromise = uiPromises.create(events_2.UI.INVALID_PASSPHRASE_ACTION, device);
|
|
239
|
+
postMessage((0, events_2.createUiMessage)(events_2.UI.INVALID_PASSPHRASE, {
|
|
240
|
+
device: device.toMessageObject(),
|
|
241
|
+
}));
|
|
242
|
+
const uiResp = await uiPromise.promise;
|
|
243
|
+
if (uiResp.payload) {
|
|
244
|
+
device.setInternalState(undefined);
|
|
245
|
+
await device.initialize(method.useEmptyPassphrase, method.useCardanoDerivation);
|
|
246
|
+
invalidDeviceState = await getInvalidDeviceState(device, method.preauthorized);
|
|
247
|
+
}
|
|
248
|
+
else {
|
|
249
|
+
device.setExternalState(invalidDeviceState);
|
|
250
|
+
break;
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
else if (invalidDeviceState) {
|
|
255
|
+
throw constants_1.ERRORS.TypedError('Device_InvalidState');
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
catch (error) {
|
|
259
|
+
device.setInternalState(undefined);
|
|
260
|
+
return Promise.reject(error);
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
if (!isDeviceUnlocked && device.features.unlocked) {
|
|
264
|
+
postMessage((0, events_2.createDeviceMessage)(events_2.DEVICE.CHANGED, device.toMessageObject()));
|
|
265
|
+
}
|
|
266
|
+
if (method.useUi) {
|
|
267
|
+
await waitForPopup();
|
|
268
|
+
}
|
|
269
|
+
else {
|
|
270
|
+
postMessage((0, events_2.createPopupMessage)(events_2.POPUP.CANCEL_POPUP_REQUEST));
|
|
271
|
+
}
|
|
272
|
+
try {
|
|
273
|
+
const response = await method.run();
|
|
274
|
+
return (0, events_2.createResponseMessage)(method.responseID, true, response);
|
|
275
|
+
}
|
|
276
|
+
catch (error) {
|
|
277
|
+
return Promise.reject(error);
|
|
278
|
+
}
|
|
279
|
+
};
|
|
183
280
|
const onCall = async (message) => {
|
|
184
281
|
var _a;
|
|
185
282
|
if (!message.id || !message.payload || message.type !== events_2.IFRAME.CALL) {
|
|
186
283
|
throw constants_1.ERRORS.TypedError('Method_InvalidParameter', 'onCall: message.id or message.payload is missing');
|
|
187
284
|
}
|
|
188
285
|
const responseID = message.id;
|
|
189
|
-
const trustedHost = DataManager_1.DataManager.getSettings('trustedHost');
|
|
190
|
-
const isUsingPopup = DataManager_1.DataManager.getSettings('popup');
|
|
191
286
|
const origin = DataManager_1.DataManager.getSettings('origin');
|
|
192
287
|
const env = DataManager_1.DataManager.getSettings('env');
|
|
193
288
|
const useCoreInPopup = DataManager_1.DataManager.getSettings('useCoreInPopup');
|
|
@@ -204,8 +299,7 @@ const onCall = async (message) => {
|
|
|
204
299
|
const method = await (0, method_1.getMethod)(message);
|
|
205
300
|
_log.debug('method selected', method.name);
|
|
206
301
|
method.postMessage = postMessage;
|
|
207
|
-
method.
|
|
208
|
-
method.createUiPromise = createUiPromise;
|
|
302
|
+
method.createUiPromise = uiPromises.create;
|
|
209
303
|
method.init();
|
|
210
304
|
await ((_a = method.initAsync) === null || _a === void 0 ? void 0 : _a.call(method));
|
|
211
305
|
return method;
|
|
@@ -221,7 +315,7 @@ const onCall = async (message) => {
|
|
|
221
315
|
if (!method.useDevice) {
|
|
222
316
|
try {
|
|
223
317
|
if (method.useUi) {
|
|
224
|
-
await
|
|
318
|
+
await waitForPopup();
|
|
225
319
|
}
|
|
226
320
|
else {
|
|
227
321
|
postMessage((0, events_2.createPopupMessage)(events_2.POPUP.CANCEL_POPUP_REQUEST));
|
|
@@ -247,11 +341,11 @@ const onCall = async (message) => {
|
|
|
247
341
|
}
|
|
248
342
|
let device;
|
|
249
343
|
try {
|
|
250
|
-
device = await initDevice(method);
|
|
344
|
+
device = await initDevice(method.devicePath);
|
|
251
345
|
}
|
|
252
346
|
catch (error) {
|
|
253
347
|
if (error.code === 'Transport_Missing') {
|
|
254
|
-
await
|
|
348
|
+
await waitForPopup();
|
|
255
349
|
postMessage((0, events_2.createUiMessage)(events_2.UI.TRANSPORT));
|
|
256
350
|
}
|
|
257
351
|
else {
|
|
@@ -260,7 +354,6 @@ const onCall = async (message) => {
|
|
|
260
354
|
postMessage((0, events_2.createResponseMessage)(responseID, false, { error }));
|
|
261
355
|
throw error;
|
|
262
356
|
}
|
|
263
|
-
method.postMessage = (message) => (0, analyticsInfo_1.enhancePostMessageWithAnalytics)(postMessage, message, { device: device.toMessageObject() });
|
|
264
357
|
method.setDevice(device);
|
|
265
358
|
const previousCall = _callMethods.filter(call => call && call !== method && call.devicePath === method.devicePath);
|
|
266
359
|
if (previousCall.length > 0 && method.overridePreviousCall) {
|
|
@@ -324,112 +417,13 @@ const onCall = async (message) => {
|
|
|
324
417
|
}
|
|
325
418
|
}
|
|
326
419
|
try {
|
|
327
|
-
let PIN_TRIES = 1;
|
|
328
|
-
const MAX_PIN_TRIES = 3;
|
|
329
|
-
const inner = async () => {
|
|
330
|
-
const firmwareException = await method.checkFirmwareRange(isUsingPopup);
|
|
331
|
-
if (firmwareException) {
|
|
332
|
-
if (isUsingPopup) {
|
|
333
|
-
await getPopupPromise().promise;
|
|
334
|
-
postMessage((0, events_2.createUiMessage)(firmwareException, device.toMessageObject()));
|
|
335
|
-
await createUiPromise(events_2.DEVICE.DISCONNECT, device).promise;
|
|
336
|
-
return Promise.reject(constants_1.ERRORS.TypedError('Method_Cancel'));
|
|
337
|
-
}
|
|
338
|
-
return Promise.reject(constants_1.ERRORS.TypedError('Device_FwException', firmwareException));
|
|
339
|
-
}
|
|
340
|
-
const unexpectedMode = device.hasUnexpectedMode(method.allowDeviceMode, method.requireDeviceMode);
|
|
341
|
-
if (unexpectedMode) {
|
|
342
|
-
device.keepSession = false;
|
|
343
|
-
if (isUsingPopup) {
|
|
344
|
-
await getPopupPromise().promise;
|
|
345
|
-
postMessage((0, events_2.createUiMessage)(unexpectedMode, device.toMessageObject()));
|
|
346
|
-
await createUiPromise(events_2.DEVICE.DISCONNECT, device).promise;
|
|
347
|
-
return Promise.reject(constants_1.ERRORS.TypedError('Device_ModeException', unexpectedMode));
|
|
348
|
-
}
|
|
349
|
-
return Promise.reject(constants_1.ERRORS.TypedError('Device_ModeException', unexpectedMode));
|
|
350
|
-
}
|
|
351
|
-
method.checkPermissions();
|
|
352
|
-
if (!trustedHost && method.requiredPermissions.length > 0) {
|
|
353
|
-
const permitted = await method.requestPermissions();
|
|
354
|
-
if (!permitted) {
|
|
355
|
-
return Promise.reject(constants_1.ERRORS.TypedError('Method_PermissionsNotGranted'));
|
|
356
|
-
}
|
|
357
|
-
}
|
|
358
|
-
const deviceNeedsBackup = device.features.needs_backup;
|
|
359
|
-
if (deviceNeedsBackup && typeof method.noBackupConfirmation === 'function') {
|
|
360
|
-
const permitted = await method.noBackupConfirmation(!isUsingPopup);
|
|
361
|
-
if (!permitted) {
|
|
362
|
-
return Promise.reject(constants_1.ERRORS.TypedError('Method_PermissionsNotGranted'));
|
|
363
|
-
}
|
|
364
|
-
}
|
|
365
|
-
if (deviceNeedsBackup) {
|
|
366
|
-
await getPopupPromise().promise;
|
|
367
|
-
postMessage((0, events_2.createUiMessage)(events_2.UI.DEVICE_NEEDS_BACKUP, device.toMessageObject()));
|
|
368
|
-
}
|
|
369
|
-
if (device.firmwareStatus === 'outdated') {
|
|
370
|
-
await getPopupPromise().promise;
|
|
371
|
-
postMessage((0, events_2.createUiMessage)(events_2.UI.FIRMWARE_OUTDATED, device.toMessageObject()));
|
|
372
|
-
}
|
|
373
|
-
if (!trustedHost && typeof method.confirmation === 'function') {
|
|
374
|
-
const confirmed = await method.confirmation();
|
|
375
|
-
if (!confirmed) {
|
|
376
|
-
return Promise.reject(constants_1.ERRORS.TypedError('Method_Cancel'));
|
|
377
|
-
}
|
|
378
|
-
}
|
|
379
|
-
const isDeviceUnlocked = device.features.unlocked;
|
|
380
|
-
try {
|
|
381
|
-
const invalidDeviceState = method.useDeviceState
|
|
382
|
-
? await device.validateState(method.network, method.preauthorized)
|
|
383
|
-
: undefined;
|
|
384
|
-
if (invalidDeviceState) {
|
|
385
|
-
if (isUsingPopup) {
|
|
386
|
-
const uiPromise = createUiPromise(events_2.UI.INVALID_PASSPHRASE_ACTION, device);
|
|
387
|
-
postMessage((0, events_2.createUiMessage)(events_2.UI.INVALID_PASSPHRASE, {
|
|
388
|
-
device: device.toMessageObject(),
|
|
389
|
-
}));
|
|
390
|
-
const uiResp = await uiPromise.promise;
|
|
391
|
-
if (uiResp.payload) {
|
|
392
|
-
device.setInternalState(undefined);
|
|
393
|
-
await device.initialize(method.useEmptyPassphrase, method.useCardanoDerivation);
|
|
394
|
-
return inner();
|
|
395
|
-
}
|
|
396
|
-
device.setExternalState(invalidDeviceState);
|
|
397
|
-
}
|
|
398
|
-
else {
|
|
399
|
-
throw constants_1.ERRORS.TypedError('Device_InvalidState');
|
|
400
|
-
}
|
|
401
|
-
}
|
|
402
|
-
}
|
|
403
|
-
catch (error) {
|
|
404
|
-
if (error.message.includes('PIN invalid') && PIN_TRIES < MAX_PIN_TRIES) {
|
|
405
|
-
PIN_TRIES++;
|
|
406
|
-
postMessage((0, events_2.createUiMessage)(events_2.UI.INVALID_PIN, { device: device.toMessageObject() }));
|
|
407
|
-
return inner();
|
|
408
|
-
}
|
|
409
|
-
device.setInternalState(undefined);
|
|
410
|
-
return Promise.reject(error);
|
|
411
|
-
}
|
|
412
|
-
if (!isDeviceUnlocked && device.features.unlocked) {
|
|
413
|
-
postMessage((0, events_2.createDeviceMessage)(events_2.DEVICE.CHANGED, device.toMessageObject()));
|
|
414
|
-
}
|
|
415
|
-
if (method.useUi) {
|
|
416
|
-
await getPopupPromise().promise;
|
|
417
|
-
}
|
|
418
|
-
else {
|
|
419
|
-
postMessage((0, events_2.createPopupMessage)(events_2.POPUP.CANCEL_POPUP_REQUEST));
|
|
420
|
-
}
|
|
421
|
-
try {
|
|
422
|
-
const response = await method.run();
|
|
423
|
-
messageResponse = (0, events_2.createResponseMessage)(method.responseID, true, response);
|
|
424
|
-
}
|
|
425
|
-
catch (error) {
|
|
426
|
-
return Promise.reject(error);
|
|
427
|
-
}
|
|
428
|
-
};
|
|
429
420
|
if (_overridePromise) {
|
|
430
421
|
await _overridePromise;
|
|
431
422
|
}
|
|
432
|
-
|
|
423
|
+
const innerAction = () => inner(method, device).then(response => {
|
|
424
|
+
messageResponse = response;
|
|
425
|
+
});
|
|
426
|
+
await device.run(innerAction, {
|
|
433
427
|
keepSession: method.keepSession,
|
|
434
428
|
useEmptyPassphrase: method.useEmptyPassphrase,
|
|
435
429
|
skipFinalReload: method.skipFinalReload,
|
|
@@ -477,13 +471,13 @@ const onCall = async (message) => {
|
|
|
477
471
|
}
|
|
478
472
|
};
|
|
479
473
|
const cleanup = () => {
|
|
480
|
-
|
|
481
|
-
|
|
474
|
+
popupPromise.clear();
|
|
475
|
+
uiPromises.clear();
|
|
482
476
|
_interactionTimeout.stop();
|
|
483
477
|
_log.debug('Cleanup...');
|
|
484
478
|
};
|
|
485
479
|
const closePopup = () => {
|
|
486
|
-
if (
|
|
480
|
+
if (popupPromise.isWaiting()) {
|
|
487
481
|
postMessage((0, events_2.createPopupMessage)(events_2.POPUP.CANCEL_POPUP_REQUEST));
|
|
488
482
|
}
|
|
489
483
|
postMessage((0, events_2.createUiMessage)(events_2.UI.CLOSE_UI_WINDOW));
|
|
@@ -491,7 +485,7 @@ const closePopup = () => {
|
|
|
491
485
|
const onDeviceButtonHandler = async (...[device, request, method]) => {
|
|
492
486
|
const addressRequest = request.code === 'ButtonRequest_Address';
|
|
493
487
|
if (!addressRequest || (addressRequest && method.useUi)) {
|
|
494
|
-
await
|
|
488
|
+
await waitForPopup();
|
|
495
489
|
}
|
|
496
490
|
const data = typeof method.getButtonRequestData === 'function' && request.code
|
|
497
491
|
? method.getButtonRequestData(request.code)
|
|
@@ -508,22 +502,22 @@ const onDeviceButtonHandler = async (...[device, request, method]) => {
|
|
|
508
502
|
}
|
|
509
503
|
};
|
|
510
504
|
const onDevicePinHandler = async (...[device, type, callback]) => {
|
|
511
|
-
await
|
|
512
|
-
const uiPromise =
|
|
505
|
+
await waitForPopup();
|
|
506
|
+
const uiPromise = uiPromises.create(events_2.UI.RECEIVE_PIN, device);
|
|
513
507
|
postMessage((0, events_2.createUiMessage)(events_2.UI.REQUEST_PIN, { device: device.toMessageObject(), type }));
|
|
514
508
|
const uiResp = await uiPromise.promise;
|
|
515
509
|
callback(null, uiResp.payload);
|
|
516
510
|
};
|
|
517
511
|
const onDeviceWordHandler = async (...[device, type, callback]) => {
|
|
518
|
-
await
|
|
519
|
-
const uiPromise =
|
|
512
|
+
await waitForPopup();
|
|
513
|
+
const uiPromise = uiPromises.create(events_2.UI.RECEIVE_WORD, device);
|
|
520
514
|
postMessage((0, events_2.createUiMessage)(events_2.UI.REQUEST_WORD, { device: device.toMessageObject(), type }));
|
|
521
515
|
const uiResp = await uiPromise.promise;
|
|
522
516
|
callback(null, uiResp.payload);
|
|
523
517
|
};
|
|
524
518
|
const onDevicePassphraseHandler = async (...[device, callback]) => {
|
|
525
|
-
await
|
|
526
|
-
const uiPromise =
|
|
519
|
+
await waitForPopup();
|
|
520
|
+
const uiPromise = uiPromises.create(events_2.UI.RECEIVE_PASSPHRASE, device);
|
|
527
521
|
postMessage((0, events_2.createUiMessage)(events_2.UI.REQUEST_PASSPHRASE, { device: device.toMessageObject() }));
|
|
528
522
|
const uiResp = await uiPromise.promise;
|
|
529
523
|
const { value, passphraseOnDevice, save } = uiResp.payload;
|
|
@@ -547,11 +541,8 @@ const onPopupClosed = (customErrorMessage) => {
|
|
|
547
541
|
_overridePromise = d.interruptionFromUser(error);
|
|
548
542
|
}
|
|
549
543
|
else {
|
|
550
|
-
const
|
|
551
|
-
if (
|
|
552
|
-
uiPromise.resolve({ type: events_2.DEVICE.DISCONNECT, payload: undefined });
|
|
553
|
-
}
|
|
554
|
-
else {
|
|
544
|
+
const success = uiPromises.resolve({ type: events_2.DEVICE.DISCONNECT, payload: undefined });
|
|
545
|
+
if (!success) {
|
|
555
546
|
_callMethods.forEach(m => {
|
|
556
547
|
postMessage((0, events_2.createResponseMessage)(m.responseID, false, { error }));
|
|
557
548
|
});
|
|
@@ -560,33 +551,23 @@ const onPopupClosed = (customErrorMessage) => {
|
|
|
560
551
|
}
|
|
561
552
|
}
|
|
562
553
|
});
|
|
563
|
-
cleanup();
|
|
564
554
|
}
|
|
565
555
|
else {
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
p.reject(error);
|
|
569
|
-
});
|
|
570
|
-
_uiPromises.splice(0);
|
|
571
|
-
}
|
|
572
|
-
if (_popupPromise) {
|
|
573
|
-
_popupPromise.reject(error);
|
|
574
|
-
_popupPromise = undefined;
|
|
575
|
-
}
|
|
576
|
-
cleanup();
|
|
556
|
+
uiPromises.rejectAll(error);
|
|
557
|
+
popupPromise.reject(error);
|
|
577
558
|
}
|
|
559
|
+
cleanup();
|
|
578
560
|
};
|
|
579
561
|
const handleDeviceSelectionChanges = (interruptDevice) => {
|
|
580
|
-
const
|
|
581
|
-
if (
|
|
562
|
+
const promiseExists = uiPromises.exists(events_2.UI.RECEIVE_DEVICE);
|
|
563
|
+
if (promiseExists && _deviceList) {
|
|
582
564
|
const list = _deviceList.asArray();
|
|
583
565
|
const isWebUsb = _deviceList.transportType() === 'WebUsbTransport';
|
|
584
566
|
if (list.length === 1 && !isWebUsb) {
|
|
585
|
-
|
|
567
|
+
uiPromises.resolve({
|
|
586
568
|
type: events_2.UI.RECEIVE_DEVICE,
|
|
587
569
|
payload: { device: list[0] },
|
|
588
570
|
});
|
|
589
|
-
removeUiPromise(uiPromise);
|
|
590
571
|
}
|
|
591
572
|
else {
|
|
592
573
|
postMessage((0, events_2.createUiMessage)(events_2.UI.SELECT_DEVICE, {
|
|
@@ -597,15 +578,7 @@ const handleDeviceSelectionChanges = (interruptDevice) => {
|
|
|
597
578
|
}
|
|
598
579
|
if (interruptDevice) {
|
|
599
580
|
const { path } = interruptDevice;
|
|
600
|
-
|
|
601
|
-
_uiPromises.forEach(p => {
|
|
602
|
-
if (p.device && p.device.getDevicePath() === path) {
|
|
603
|
-
if (p.id === events_2.DEVICE.DISCONNECT) {
|
|
604
|
-
p.resolve({ type: events_2.DEVICE.DISCONNECT });
|
|
605
|
-
}
|
|
606
|
-
shouldClosePopup = true;
|
|
607
|
-
}
|
|
608
|
-
});
|
|
581
|
+
const shouldClosePopup = uiPromises.disconnected(path);
|
|
609
582
|
if (shouldClosePopup) {
|
|
610
583
|
closePopup();
|
|
611
584
|
cleanup();
|
|
@@ -614,7 +587,10 @@ const handleDeviceSelectionChanges = (interruptDevice) => {
|
|
|
614
587
|
};
|
|
615
588
|
const initDeviceList = async (transportReconnect) => {
|
|
616
589
|
try {
|
|
617
|
-
_deviceList = new DeviceList_1.DeviceList(
|
|
590
|
+
_deviceList = new DeviceList_1.DeviceList({
|
|
591
|
+
settings: DataManager_1.DataManager.getSettings(),
|
|
592
|
+
messages: DataManager_1.DataManager.getProtobufMessages(),
|
|
593
|
+
});
|
|
618
594
|
_deviceList.on(events_2.DEVICE.CONNECT, device => {
|
|
619
595
|
handleDeviceSelectionChanges();
|
|
620
596
|
postMessage((0, events_2.createDeviceMessage)(events_2.DEVICE.CONNECT, device));
|
|
@@ -667,17 +643,73 @@ const initDeviceList = async (transportReconnect) => {
|
|
|
667
643
|
}
|
|
668
644
|
};
|
|
669
645
|
class Core extends events_1.default {
|
|
646
|
+
constructor() {
|
|
647
|
+
super(...arguments);
|
|
648
|
+
this.abortController = new AbortController();
|
|
649
|
+
}
|
|
670
650
|
handleMessage(message) {
|
|
671
|
-
handleMessage
|
|
651
|
+
_log.debug('handleMessage', message);
|
|
652
|
+
switch (message.type) {
|
|
653
|
+
case events_2.POPUP.HANDSHAKE:
|
|
654
|
+
popupPromise.resolve();
|
|
655
|
+
break;
|
|
656
|
+
case events_2.POPUP.CLOSED:
|
|
657
|
+
onPopupClosed(message.payload ? message.payload.error : null);
|
|
658
|
+
break;
|
|
659
|
+
case transport_1.TRANSPORT.DISABLE_WEBUSB:
|
|
660
|
+
disableWebUSBTransport();
|
|
661
|
+
break;
|
|
662
|
+
case transport_1.TRANSPORT.REQUEST_DEVICE:
|
|
663
|
+
_deviceList === null || _deviceList === void 0 ? void 0 : _deviceList.enumerate();
|
|
664
|
+
break;
|
|
665
|
+
case events_2.UI.RECEIVE_DEVICE:
|
|
666
|
+
case events_2.UI.RECEIVE_CONFIRMATION:
|
|
667
|
+
case events_2.UI.RECEIVE_PERMISSION:
|
|
668
|
+
case events_2.UI.RECEIVE_PIN:
|
|
669
|
+
case events_2.UI.RECEIVE_PASSPHRASE:
|
|
670
|
+
case events_2.UI.INVALID_PASSPHRASE_ACTION:
|
|
671
|
+
case events_2.UI.RECEIVE_ACCOUNT:
|
|
672
|
+
case events_2.UI.RECEIVE_FEE:
|
|
673
|
+
case events_2.UI.RECEIVE_WORD:
|
|
674
|
+
case events_2.UI.LOGIN_CHALLENGE_RESPONSE:
|
|
675
|
+
uiPromises.resolve(message);
|
|
676
|
+
break;
|
|
677
|
+
case events_2.IFRAME.CALL:
|
|
678
|
+
if (message.payload.method === 'firmwareUpdate') {
|
|
679
|
+
(0, onCallFirmwareUpdate_1.onCallFirmwareUpdate)({
|
|
680
|
+
params: message.payload,
|
|
681
|
+
context: {
|
|
682
|
+
deviceList: _deviceList,
|
|
683
|
+
postMessage,
|
|
684
|
+
initDevice,
|
|
685
|
+
log: _log,
|
|
686
|
+
abortSignal: this.abortController.signal,
|
|
687
|
+
},
|
|
688
|
+
})
|
|
689
|
+
.then(payload => {
|
|
690
|
+
postMessage((0, events_2.createResponseMessage)(message.id, true, payload));
|
|
691
|
+
})
|
|
692
|
+
.catch(error => {
|
|
693
|
+
postMessage((0, events_2.createResponseMessage)(message.id, false, { error }));
|
|
694
|
+
_log.error('onCallFirmwareUpdate', error);
|
|
695
|
+
});
|
|
696
|
+
}
|
|
697
|
+
else {
|
|
698
|
+
onCall(message).catch(error => {
|
|
699
|
+
_log.error('onCall', error);
|
|
700
|
+
});
|
|
701
|
+
}
|
|
702
|
+
}
|
|
672
703
|
}
|
|
673
|
-
|
|
704
|
+
dispose() {
|
|
674
705
|
(0, BlockchainLink_1.dispose)();
|
|
675
706
|
if (_deviceListInitTimeout) {
|
|
676
707
|
clearTimeout(_deviceListInitTimeout);
|
|
677
708
|
}
|
|
678
709
|
this.removeAllListeners();
|
|
710
|
+
this.abortController.abort();
|
|
679
711
|
if (_deviceList) {
|
|
680
|
-
|
|
712
|
+
_deviceList.dispose();
|
|
681
713
|
}
|
|
682
714
|
}
|
|
683
715
|
async getCurrentMethod() {
|
|
@@ -745,7 +777,7 @@ const disableWebUSBTransport = async () => {
|
|
|
745
777
|
}
|
|
746
778
|
}
|
|
747
779
|
try {
|
|
748
|
-
|
|
780
|
+
_deviceList.dispose();
|
|
749
781
|
await initDeviceList(settings.transportReconnect);
|
|
750
782
|
}
|
|
751
783
|
catch (error) {
|