@onekeyfe/hd-core 1.2.0-alpha.19 → 1.2.0-alpha.20
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/__tests__/AllNetworkGetAddressBase.tracing.test.ts +75 -0
- package/__tests__/DeviceCommands.test.ts +143 -7
- package/__tests__/RequestQueue.test.ts +106 -0
- package/__tests__/UploadPortfolio.test.ts +46 -0
- package/__tests__/core-dispose.test.ts +34 -0
- package/__tests__/core-error-output.test.ts +39 -0
- package/__tests__/device-lifecycle-events.test.ts +117 -0
- package/__tests__/device-pool-state.test.ts +20 -1
- package/__tests__/device-settings.test.ts +184 -6
- package/__tests__/device-state-events.test.ts +1 -2
- package/__tests__/device-state-mapper.test.ts +33 -26
- package/__tests__/device-state-store.test.ts +1 -34
- package/__tests__/device-utils.test.ts +106 -0
- package/__tests__/device-wallet-session-store.test.ts +65 -29
- package/__tests__/deviceSettings.test.ts +21 -12
- package/__tests__/evmLedgerLegacySafety.test.ts +2 -2
- package/__tests__/evmSignTypedData.test.ts +80 -0
- package/__tests__/filesystemValidation.test.ts +53 -0
- package/__tests__/firmware-update/firmware-update-v2-download-before-boot.test.ts +402 -0
- package/__tests__/get-device-state.test.ts +77 -41
- package/__tests__/logBlockEvent.test.ts +24 -11
- package/__tests__/networkUtils.test.ts +386 -0
- package/__tests__/open-wallet-session-error-response.test.ts +43 -0
- package/__tests__/open-wallet-session.test.ts +559 -0
- package/__tests__/protocol-v2.test.ts +756 -452
- package/__tests__/public-device-state-api.test.ts +113 -13
- package/__tests__/public-pro2-api-boundary.test.ts +91 -0
- package/__tests__/search-devices.test.ts +43 -0
- package/dist/api/BaseMethod.d.ts +3 -0
- package/dist/api/BaseMethod.d.ts.map +1 -1
- package/dist/api/CheckBootloaderRelease.d.ts.map +1 -1
- package/dist/api/CheckFirmwareRelease.d.ts.map +1 -1
- package/dist/api/ClearSessionCache.d.ts.map +1 -1
- package/dist/api/DirList.d.ts.map +1 -1
- package/dist/api/FileRead.d.ts.map +1 -1
- package/dist/api/FirmwareUpdateV2.d.ts +2 -2
- package/dist/api/FirmwareUpdateV2.d.ts.map +1 -1
- package/dist/api/FirmwareUpdateV3.d.ts.map +1 -1
- package/dist/api/FirmwareUpdateV4.d.ts +3 -2
- package/dist/api/FirmwareUpdateV4.d.ts.map +1 -1
- package/dist/api/GetPassphraseState.d.ts.map +1 -1
- package/dist/api/OpenWalletSession.d.ts +14 -0
- package/dist/api/OpenWalletSession.d.ts.map +1 -0
- package/dist/api/PathInfo.d.ts.map +1 -1
- package/dist/api/PromptWebDeviceAccess.d.ts.map +1 -1
- package/dist/api/SearchDevices.d.ts +3 -0
- package/dist/api/SearchDevices.d.ts.map +1 -1
- package/dist/api/UploadPortfolio.d.ts.map +1 -1
- package/dist/api/allnetwork/AllNetworkGetAddressBase.d.ts.map +1 -1
- package/dist/api/device/DeviceChangePin.d.ts.map +1 -1
- package/dist/api/device/DeviceFullyUploadResource.d.ts +1 -2
- package/dist/api/device/DeviceFullyUploadResource.d.ts.map +1 -1
- package/dist/api/device/DeviceSettings.d.ts.map +1 -1
- package/dist/api/device/DeviceUpdateBootloader.d.ts.map +1 -1
- package/dist/api/device/DeviceWipe.d.ts.map +1 -1
- package/dist/api/evm/EVMSignTypedData.d.ts.map +1 -1
- package/dist/api/firmware/getBinary.d.ts +7 -3
- package/dist/api/firmware/getBinary.d.ts.map +1 -1
- package/dist/api/helpers/filesystemValidation.d.ts +3 -0
- package/dist/api/helpers/filesystemValidation.d.ts.map +1 -1
- package/dist/api/helpers/paramsValidator.d.ts +1 -0
- package/dist/api/helpers/paramsValidator.d.ts.map +1 -1
- package/dist/api/helpers/protocolV2FileWrite.d.ts.map +1 -1
- package/dist/api/index.d.ts +7 -11
- package/dist/api/index.d.ts.map +1 -1
- package/dist/api/protocol-v2/DeviceGetFirmwareUpdateStatus.d.ts.map +1 -1
- package/dist/api/protocol-v2/DeviceSettingsPageShow.d.ts.map +1 -1
- package/dist/api/protocol-v2/DeviceSettingsSet.d.ts.map +1 -1
- package/dist/api/utils.d.ts.map +1 -1
- package/dist/core/RequestQueue.d.ts +17 -1
- package/dist/core/RequestQueue.d.ts.map +1 -1
- package/dist/core/index.d.ts +3 -1
- package/dist/core/index.d.ts.map +1 -1
- package/dist/device/Device.d.ts +6 -5
- package/dist/device/Device.d.ts.map +1 -1
- package/dist/device/DeviceCommands.d.ts +5 -5
- package/dist/device/DeviceCommands.d.ts.map +1 -1
- package/dist/device/DevicePool.d.ts +1 -0
- package/dist/device/DevicePool.d.ts.map +1 -1
- package/dist/device/DeviceStateMapper.d.ts +2 -2
- package/dist/device/DeviceStateMapper.d.ts.map +1 -1
- package/dist/device/DeviceStateProjector.d.ts +1 -2
- package/dist/device/DeviceStateProjector.d.ts.map +1 -1
- package/dist/device/DeviceStateStore.d.ts +1 -3
- package/dist/device/DeviceStateStore.d.ts.map +1 -1
- package/dist/device/DeviceWalletSessionStore.d.ts +6 -1
- package/dist/device/DeviceWalletSessionStore.d.ts.map +1 -1
- package/dist/device/cloneDeviceState.d.ts +2 -0
- package/dist/device/cloneDeviceState.d.ts.map +1 -0
- package/dist/deviceProfile/buildDeviceFeatures.d.ts +3 -1
- package/dist/deviceProfile/buildDeviceFeatures.d.ts.map +1 -1
- package/dist/events/logBlockEvent.d.ts.map +1 -1
- package/dist/index.d.ts +608 -75
- package/dist/index.js +2287 -1706
- package/dist/inject.d.ts.map +1 -1
- package/dist/protocols/protocol-v2/deviceSession.d.ts +7 -0
- package/dist/protocols/protocol-v2/deviceSession.d.ts.map +1 -0
- package/dist/protocols/protocol-v2/features.d.ts +11 -4
- package/dist/protocols/protocol-v2/features.d.ts.map +1 -1
- package/dist/protocols/protocol-v2/index.d.ts +2 -2
- package/dist/protocols/protocol-v2/index.d.ts.map +1 -1
- package/dist/protocols/protocol-v2/settingsUnlockPolicy.d.ts +16 -0
- package/dist/protocols/protocol-v2/settingsUnlockPolicy.d.ts.map +1 -0
- package/dist/protocols/protocol-v2/uiInteraction.d.ts.map +1 -1
- package/dist/protocols/protocol-v2/walletSession.d.ts +8 -3
- package/dist/protocols/protocol-v2/walletSession.d.ts.map +1 -1
- package/dist/types/api/checkAllFirmwareRelease.d.ts +1 -2
- package/dist/types/api/checkAllFirmwareRelease.d.ts.map +1 -1
- package/dist/types/api/deviceSettings.d.ts +1 -0
- package/dist/types/api/deviceSettings.d.ts.map +1 -1
- package/dist/types/api/deviceUnlock.d.ts +1 -1
- package/dist/types/api/deviceUnlock.d.ts.map +1 -1
- package/dist/types/api/getFeatures.d.ts.map +1 -1
- package/dist/types/api/getOnekeyFeatures.d.ts.map +1 -1
- package/dist/types/api/getPassphraseState.d.ts.map +1 -1
- package/dist/types/api/index.d.ts +13 -15
- package/dist/types/api/index.d.ts.map +1 -1
- package/dist/types/api/openWalletSession.d.ts +41 -0
- package/dist/types/api/openWalletSession.d.ts.map +1 -0
- package/dist/types/api/protocolV2.d.ts +6 -11
- package/dist/types/api/protocolV2.d.ts.map +1 -1
- package/dist/types/device.d.ts +2 -9
- package/dist/types/device.d.ts.map +1 -1
- package/dist/utils/assets.d.ts +2 -1
- package/dist/utils/assets.d.ts.map +1 -1
- package/dist/utils/deviceFeaturesCompat.d.ts +13 -0
- package/dist/utils/deviceFeaturesCompat.d.ts.map +1 -0
- package/dist/utils/deviceFeaturesUtils.d.ts +11 -1
- package/dist/utils/deviceFeaturesUtils.d.ts.map +1 -1
- package/dist/utils/deviceInfoUtils.d.ts +9 -8
- package/dist/utils/deviceInfoUtils.d.ts.map +1 -1
- package/dist/utils/deviceSettings.d.ts +2 -0
- package/dist/utils/deviceSettings.d.ts.map +1 -1
- package/dist/utils/deviceVersionUtils.d.ts +6 -5
- package/dist/utils/deviceVersionUtils.d.ts.map +1 -1
- package/dist/utils/index.d.ts +2 -2
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/networkUtils.d.ts +9 -1
- package/dist/utils/networkUtils.d.ts.map +1 -1
- package/dist/utils/patch.d.ts +1 -1
- package/dist/utils/patch.d.ts.map +1 -1
- package/dist/utils/pro2Wallpaper.d.ts.map +1 -1
- package/package.json +4 -4
- package/src/api/BaseMethod.ts +17 -10
- package/src/api/CheckBootloaderRelease.ts +1 -2
- package/src/api/CheckFirmwareRelease.ts +1 -2
- package/src/api/ClearSessionCache.ts +0 -4
- package/src/api/DirList.ts +5 -3
- package/src/api/DirMake.ts +3 -3
- package/src/api/DirRemove.ts +3 -3
- package/src/api/FileDelete.ts +3 -3
- package/src/api/FileRead.ts +9 -6
- package/src/api/FileWrite.ts +3 -3
- package/src/api/FirmwareUpdate.ts +4 -4
- package/src/api/FirmwareUpdateV2.ts +133 -45
- package/src/api/FirmwareUpdateV3.ts +3 -5
- package/src/api/FirmwareUpdateV4.ts +192 -154
- package/src/api/GetPassphraseState.ts +10 -16
- package/src/api/OpenWalletSession.ts +221 -0
- package/src/api/PathInfo.ts +5 -3
- package/src/api/PromptWebDeviceAccess.ts +2 -3
- package/src/api/SearchDevices.ts +6 -2
- package/src/api/UploadPortfolio.ts +12 -3
- package/src/api/alephium/AlephiumSignTransaction.ts +2 -2
- package/src/api/allnetwork/AllNetworkGetAddressBase.ts +4 -8
- package/src/api/benfen/BenfenGetAddress.ts +1 -1
- package/src/api/btc/BTCGetPublicKey.ts +1 -1
- package/src/api/device/DeviceChangePin.ts +1 -0
- package/src/api/device/DeviceFullyUploadResource.ts +4 -5
- package/src/api/device/DeviceSettings.ts +93 -0
- package/src/api/device/DeviceUpdateBootloader.ts +1 -2
- package/src/api/device/DeviceWipe.ts +1 -0
- package/src/api/evm/EVMSignTypedData.ts +3 -5
- package/src/api/evm/legacyV1/getAddress.ts +2 -2
- package/src/api/evm/legacyV1/getPublicKey.ts +2 -2
- package/src/api/evm/legacyV1/signMessage.ts +2 -2
- package/src/api/evm/legacyV1/signTypedData.ts +2 -2
- package/src/api/evm/legacyV1/signTypedHash.ts +2 -2
- package/src/api/evm/legacyV1/verifyMessage.ts +2 -2
- package/src/api/firmware/FirmwareUpdateBaseMethod.ts +3 -3
- package/src/api/firmware/getBinary.ts +8 -3
- package/src/api/helpers/batchGetPublickeys.ts +2 -2
- package/src/api/helpers/filesystemValidation.ts +61 -0
- package/src/api/helpers/paramsValidator.ts +1 -1
- package/src/api/helpers/protocolV2FileWrite.ts +3 -2
- package/src/api/index.ts +9 -12
- package/src/api/nervos/NervosSignTransaction.ts +2 -2
- package/src/api/nexa/NexaSignTransaction.ts +1 -1
- package/src/api/protocol-v2/DeviceFactoryInfoGet.ts +1 -1
- package/src/api/protocol-v2/DeviceFactoryInfoSet.ts +1 -1
- package/src/api/protocol-v2/DeviceFirmwareUpdate.ts +4 -4
- package/src/api/protocol-v2/DeviceGetFirmwareUpdateStatus.ts +6 -5
- package/src/api/protocol-v2/DeviceInfoGet.ts +4 -4
- package/src/api/protocol-v2/DeviceReboot.ts +1 -1
- package/src/api/protocol-v2/DeviceSettingsPageShow.ts +11 -8
- package/src/api/protocol-v2/DeviceSettingsSet.ts +4 -11
- package/src/api/protocol-v2/FilesystemFormat.ts +1 -1
- package/src/api/protocol-v2/FilesystemPermissionFix.ts +1 -1
- package/src/api/protocol-v2/Ping.ts +1 -1
- package/src/api/protocol-v2/ProtocolInfoRequest.ts +1 -1
- package/src/api/utils.ts +1 -3
- package/src/core/RequestQueue.ts +107 -6
- package/src/core/index.ts +91 -46
- package/src/data/messages/messages-protocol-v2.json +25 -79
- package/src/data-manager/DataManager.ts +6 -6
- package/src/device/Device.ts +186 -102
- package/src/device/DeviceCommands.ts +51 -21
- package/src/device/DeviceFeaturesState.ts +4 -4
- package/src/device/DevicePool.ts +17 -3
- package/src/device/DeviceStateMapper.ts +13 -29
- package/src/device/DeviceStateProjector.ts +11 -8
- package/src/device/DeviceStateStore.ts +11 -52
- package/src/device/DeviceWalletSessionStore.ts +31 -4
- package/src/device/cloneDeviceState.ts +39 -0
- package/src/device/deviceIdentity.ts +2 -2
- package/src/deviceProfile/buildDeviceFeatures.ts +29 -88
- package/src/events/logBlockEvent.ts +8 -1
- package/src/inject.ts +14 -24
- package/src/protocols/protocol-v2/deviceSession.ts +24 -0
- package/src/protocols/protocol-v2/features.ts +37 -49
- package/src/protocols/protocol-v2/firmware.ts +1 -1
- package/src/protocols/protocol-v2/index.ts +2 -3
- package/src/protocols/protocol-v2/settingsUnlockPolicy.ts +61 -0
- package/src/protocols/protocol-v2/uiInteraction.ts +4 -3
- package/src/protocols/protocol-v2/walletSession.ts +57 -146
- package/src/types/api/checkAllFirmwareRelease.ts +1 -2
- package/src/types/api/deviceSettings.ts +1 -0
- package/src/types/api/deviceUnlock.ts +1 -1
- package/src/types/api/firmwareUpdate.ts +5 -5
- package/src/types/api/getDeviceState.ts +1 -1
- package/src/types/api/getFeatures.ts +3 -0
- package/src/types/api/getOnekeyFeatures.ts +3 -0
- package/src/types/api/getPassphraseState.ts +6 -0
- package/src/types/api/index.ts +16 -23
- package/src/types/api/openWalletSession.ts +64 -0
- package/src/types/api/protocolV2.ts +36 -18
- package/src/types/device.ts +20 -14
- package/src/types/params.ts +1 -1
- package/src/types/settings.ts +8 -8
- package/src/utils/assets.ts +4 -1
- package/src/utils/deviceFeaturesCompat.ts +173 -0
- package/src/utils/deviceFeaturesUtils.ts +9 -8
- package/src/utils/deviceInfoUtils.ts +26 -64
- package/src/utils/deviceSettings.ts +18 -11
- package/src/utils/deviceVersionUtils.ts +25 -44
- package/src/utils/findDefectiveBatchDevice.ts +3 -3
- package/src/utils/index.ts +2 -5
- package/src/utils/networkUtils.ts +270 -14
- package/src/utils/pro2Wallpaper.ts +11 -13
- package/src/utils/tracing.ts +2 -2
- package/dist/api/internal.d.ts +0 -4
- package/dist/api/internal.d.ts.map +0 -1
- package/dist/api/protocol-v2/DeviceSessionOpen.d.ts +0 -28
- package/dist/api/protocol-v2/DeviceSessionOpen.d.ts.map +0 -1
- package/src/api/internal.ts +0 -9
- package/src/api/protocol-v2/DeviceSessionOpen.ts +0 -100
package/src/device/Device.ts
CHANGED
|
@@ -16,10 +16,11 @@ import {
|
|
|
16
16
|
LoggerNames,
|
|
17
17
|
getDeviceBLEFirmwareVersion,
|
|
18
18
|
getDeviceBleName,
|
|
19
|
+
getDeviceBootloaderVersion,
|
|
19
20
|
getDeviceFirmwareVersion,
|
|
20
21
|
getDeviceLabel,
|
|
22
|
+
getDeviceSerialNo,
|
|
21
23
|
getDeviceType,
|
|
22
|
-
getDeviceUUID,
|
|
23
24
|
getFirmwareType,
|
|
24
25
|
getLogger,
|
|
25
26
|
} from '../utils';
|
|
@@ -42,6 +43,7 @@ import {
|
|
|
42
43
|
} from './DeviceStateMapper';
|
|
43
44
|
import { projectFeatures } from './DeviceStateProjector';
|
|
44
45
|
import { DeviceStateStore, createPublicDeviceState } from './DeviceStateStore';
|
|
46
|
+
import { cloneDeviceState } from './cloneDeviceState';
|
|
45
47
|
import { deviceWalletSessionStore } from './DeviceWalletSessionStore';
|
|
46
48
|
import {
|
|
47
49
|
type DeviceFirmwareRange,
|
|
@@ -68,6 +70,8 @@ import {
|
|
|
68
70
|
PROTOCOL_V2_FEATURES_DEVICE_INFO_REQUEST,
|
|
69
71
|
PROTOCOL_V2_FULL_DEVICE_INFO_REQUEST,
|
|
70
72
|
PROTOCOL_V2_VERSIONS_DEVICE_INFO_REQUEST,
|
|
73
|
+
type ProtocolV2RuntimeMode,
|
|
74
|
+
getProtocolV2RuntimeMode,
|
|
71
75
|
requestProtocolV2DeviceInfo,
|
|
72
76
|
requestProtocolV2DeviceStatus,
|
|
73
77
|
} from '../protocols/protocol-v2/features';
|
|
@@ -97,7 +101,7 @@ export type InitOptions = {
|
|
|
97
101
|
deriveCardano?: boolean;
|
|
98
102
|
connectProtocol?: HardwareConnectProtocol;
|
|
99
103
|
protocolV2DeviceInfoTimeoutMs?: number;
|
|
100
|
-
/**
|
|
104
|
+
/** Refresh Protocol V2 runtime state before returning discovery results. */
|
|
101
105
|
refreshRuntimeState?: boolean;
|
|
102
106
|
};
|
|
103
107
|
|
|
@@ -206,10 +210,10 @@ export class Device extends EventEmitter {
|
|
|
206
210
|
*/
|
|
207
211
|
private deviceAcquired = false;
|
|
208
212
|
|
|
209
|
-
/**
|
|
213
|
+
/** Canonical device-state cache; legacy Features is a compatibility projection. */
|
|
210
214
|
private stateStore = new DeviceStateStore();
|
|
211
215
|
|
|
212
|
-
/**
|
|
216
|
+
/** Force the next initialization to reload DeviceInfo after reconnect or reboot. */
|
|
213
217
|
private protocolV2StateNeedsReload = false;
|
|
214
218
|
|
|
215
219
|
get state() {
|
|
@@ -217,13 +221,38 @@ export class Device extends EventEmitter {
|
|
|
217
221
|
}
|
|
218
222
|
|
|
219
223
|
get features(): Features | undefined {
|
|
220
|
-
|
|
224
|
+
if (!this.state) return undefined;
|
|
225
|
+
const features = projectFeatures(this.state);
|
|
226
|
+
const sessionCacheDeviceKey =
|
|
227
|
+
this.state.identity.deviceId ||
|
|
228
|
+
(this.isProtocolV2()
|
|
229
|
+
? this.originalDescriptor.path || this.originalDescriptor.id
|
|
230
|
+
: undefined);
|
|
231
|
+
const sessionId =
|
|
232
|
+
sessionCacheDeviceKey && this.passphraseState
|
|
233
|
+
? deviceWalletSessionStore.get(sessionCacheDeviceKey, this.passphraseState)
|
|
234
|
+
: undefined;
|
|
235
|
+
return sessionId
|
|
236
|
+
? {
|
|
237
|
+
...features,
|
|
238
|
+
sessionId,
|
|
239
|
+
session_id: sessionId,
|
|
240
|
+
passphraseState: this.passphraseState,
|
|
241
|
+
}
|
|
242
|
+
: features;
|
|
221
243
|
}
|
|
222
244
|
|
|
223
245
|
set features(features: Features | undefined) {
|
|
224
246
|
this.stateStore = new DeviceStateStore();
|
|
225
247
|
if (features) {
|
|
226
248
|
this.stateStore.update(mapFeaturesToState(features), 'compatibility');
|
|
249
|
+
const { passphraseState } = features;
|
|
250
|
+
const sessionId = features.sessionId ?? features.session_id;
|
|
251
|
+
const deviceKey = this.getSessionCacheDeviceKey(features.deviceId ?? undefined);
|
|
252
|
+
if (passphraseState && sessionId && deviceKey) {
|
|
253
|
+
this.passphraseState = passphraseState;
|
|
254
|
+
deviceWalletSessionStore.set(deviceKey, passphraseState, sessionId);
|
|
255
|
+
}
|
|
227
256
|
}
|
|
228
257
|
}
|
|
229
258
|
|
|
@@ -294,9 +323,11 @@ export class Device extends EventEmitter {
|
|
|
294
323
|
const state = this.state ? createPublicDeviceState(this.state) : undefined;
|
|
295
324
|
|
|
296
325
|
return {
|
|
297
|
-
/** Android uses
|
|
326
|
+
/** Android uses a MAC address, while iOS and USB use transport-specific identifiers. */
|
|
298
327
|
connectId: DataManager.isBleConnect(env) ? this.mainId || null : connectId,
|
|
299
|
-
/**
|
|
328
|
+
/** Stable physical-device identity. */
|
|
329
|
+
serialNo,
|
|
330
|
+
/** @deprecated Use serialNo instead. */
|
|
300
331
|
uuid: serialNo,
|
|
301
332
|
commType: this.originalDescriptor.commType,
|
|
302
333
|
sdkInstanceId: this.sdkInstanceId,
|
|
@@ -308,12 +339,10 @@ export class Device extends EventEmitter {
|
|
|
308
339
|
path: this.originalDescriptor?.path,
|
|
309
340
|
bleName,
|
|
310
341
|
name: bleName || label || `OneKey ${deviceType?.toUpperCase()}`,
|
|
311
|
-
displayName: label || bleName || `OneKey ${deviceType?.toUpperCase()}`,
|
|
312
342
|
label: label || 'OneKey',
|
|
313
343
|
mode: this.getMode(),
|
|
314
344
|
features,
|
|
315
345
|
state,
|
|
316
|
-
sessionId: this.features?.sessionId ?? null,
|
|
317
346
|
firmwareVersion: this.getFirmwareVersion(),
|
|
318
347
|
bleFirmwareVersion: this.getBLEFirmwareVersion(),
|
|
319
348
|
unavailableCapabilities: this.unavailableCapabilities,
|
|
@@ -365,11 +394,10 @@ export class Device extends EventEmitter {
|
|
|
365
394
|
try {
|
|
366
395
|
let acquireResult: unknown;
|
|
367
396
|
if (DataManager.isBleConnect(env)) {
|
|
368
|
-
//
|
|
369
|
-
//
|
|
370
|
-
//
|
|
371
|
-
//
|
|
372
|
-
// 因此对 BLE acquire 恒清理是有意为之。
|
|
397
|
+
// acquire starts a new BLE session. Any previous runPromise belongs to a dead
|
|
398
|
+
// session, such as an interrupted probe or firmware-update reboot, and would
|
|
399
|
+
// otherwise block the new session. Device cannot distinguish recovery from a
|
|
400
|
+
// regular acquire, so BLE always clears it intentionally.
|
|
373
401
|
acquireResult = await this.deviceConnector?.acquire(
|
|
374
402
|
this.originalDescriptor.id,
|
|
375
403
|
undefined,
|
|
@@ -510,12 +538,11 @@ export class Device extends EventEmitter {
|
|
|
510
538
|
}
|
|
511
539
|
|
|
512
540
|
/**
|
|
513
|
-
*
|
|
541
|
+
* Canonical protocol discriminator.
|
|
514
542
|
*
|
|
515
|
-
* descriptor.protocolType
|
|
516
|
-
*
|
|
517
|
-
*
|
|
518
|
-
* 或从 features 反推。
|
|
543
|
+
* descriptor.protocolType is established by active probing; V2 features are mapped
|
|
544
|
+
* from DeviceInfoGet. All protocol branches must use this method instead of reading
|
|
545
|
+
* originalDescriptor.protocolType directly or inferring a protocol from features.
|
|
519
546
|
*/
|
|
520
547
|
getProtocol(): 'V1' | 'V2' {
|
|
521
548
|
return this.originalDescriptor.protocolType === 'V2' ? 'V2' : 'V1';
|
|
@@ -534,15 +561,15 @@ export class Device extends EventEmitter {
|
|
|
534
561
|
}
|
|
535
562
|
|
|
536
563
|
getCurrentSerialNo() {
|
|
537
|
-
return
|
|
564
|
+
return getDeviceSerialNo(this.features);
|
|
538
565
|
}
|
|
539
566
|
|
|
540
567
|
getConnectId() {
|
|
541
568
|
const serialNo = this.getCurrentSerialNo();
|
|
542
569
|
if (serialNo) return serialNo;
|
|
543
570
|
|
|
544
|
-
// connectId
|
|
545
|
-
//
|
|
571
|
+
// connectId is an internal routing key. Falling back to the transport descriptor
|
|
572
|
+
// does not change the business meaning of features.serialNo or deviceId.
|
|
546
573
|
return this.originalDescriptor.path || this.originalDescriptor.id || '';
|
|
547
574
|
}
|
|
548
575
|
|
|
@@ -571,6 +598,11 @@ export class Device extends EventEmitter {
|
|
|
571
598
|
return getDeviceBLEFirmwareVersion(this.features).join('.');
|
|
572
599
|
}
|
|
573
600
|
|
|
601
|
+
getCurrentBootloaderVersionString() {
|
|
602
|
+
if (!this.features) return undefined;
|
|
603
|
+
return getDeviceBootloaderVersion(this.features).join('.');
|
|
604
|
+
}
|
|
605
|
+
|
|
574
606
|
getCurrentSafetyChecks() {
|
|
575
607
|
return this.features?.safetyChecks;
|
|
576
608
|
}
|
|
@@ -636,9 +668,8 @@ export class Device extends EventEmitter {
|
|
|
636
668
|
}
|
|
637
669
|
|
|
638
670
|
supportModifyHomescreen(): SupportFeatureType {
|
|
639
|
-
// Pro2
|
|
640
|
-
//
|
|
641
|
-
// 包含 homescreen 字段,V2 固件从首个版本即支持修改主屏。
|
|
671
|
+
// Pro2 has an independent 1.x version line and must not use the Touch/Pro 3.4.0
|
|
672
|
+
// threshold. ApplySettings includes homescreen from the first V2 firmware version.
|
|
642
673
|
if (this.isProtocolV2()) {
|
|
643
674
|
return { support: true };
|
|
644
675
|
}
|
|
@@ -665,12 +696,22 @@ export class Device extends EventEmitter {
|
|
|
665
696
|
return undefined;
|
|
666
697
|
}
|
|
667
698
|
|
|
699
|
+
private reconcileSessionCacheDeviceIdentity(previousDeviceId?: string) {
|
|
700
|
+
deviceWalletSessionStore.reconcileDeviceIdentity({
|
|
701
|
+
temporaryKey: this.isProtocolV2()
|
|
702
|
+
? this.originalDescriptor.path || this.originalDescriptor.id
|
|
703
|
+
: undefined,
|
|
704
|
+
previousDeviceId,
|
|
705
|
+
nextDeviceId: this.getCurrentDeviceId(),
|
|
706
|
+
});
|
|
707
|
+
}
|
|
708
|
+
|
|
668
709
|
getInternalState(_deviceId?: string) {
|
|
669
710
|
Log.debug(
|
|
670
711
|
'getInternalState session param: ',
|
|
671
712
|
`device_id: ${_deviceId}`,
|
|
672
713
|
`features.deviceId: ${this.features?.deviceId}`,
|
|
673
|
-
`
|
|
714
|
+
`hasPassphraseState: ${Boolean(this.passphraseState)}`
|
|
674
715
|
);
|
|
675
716
|
|
|
676
717
|
const deviceId = this.getSessionCacheDeviceKey(_deviceId);
|
|
@@ -698,7 +739,7 @@ export class Device extends EventEmitter {
|
|
|
698
739
|
'updateInternalState session param: ',
|
|
699
740
|
`device_id: ${deviceId}`,
|
|
700
741
|
`enablePassphrase: ${enablePassphrase}`,
|
|
701
|
-
`
|
|
742
|
+
`hasPassphraseState: ${Boolean(passphraseState)}`,
|
|
702
743
|
`hasSessionId: ${Boolean(sessionId)}`,
|
|
703
744
|
`hasFeaturesSessionId: ${Boolean(featuresSessionId)}`
|
|
704
745
|
);
|
|
@@ -721,7 +762,7 @@ export class Device extends EventEmitter {
|
|
|
721
762
|
`hasState: ${Boolean(state)}`,
|
|
722
763
|
`initSession: ${initSession}`,
|
|
723
764
|
`deviceId: ${this.features?.deviceId}`,
|
|
724
|
-
`
|
|
765
|
+
`hasPassphraseState: ${Boolean(this.passphraseState)}`
|
|
725
766
|
);
|
|
726
767
|
|
|
727
768
|
if (!this.passphraseState && !initSession) return;
|
|
@@ -749,15 +790,15 @@ export class Device extends EventEmitter {
|
|
|
749
790
|
}
|
|
750
791
|
|
|
751
792
|
async initialize(options?: InitOptions) {
|
|
752
|
-
// Protocol V2
|
|
793
|
+
// Protocol V2 does not support legacy Initialize; use its dedicated flow.
|
|
753
794
|
if (this.isProtocolV2()) {
|
|
754
795
|
this.passphraseState = options?.passphraseState;
|
|
755
796
|
if (this.state && !options?.initSession && !this.protocolV2StateNeedsReload) {
|
|
756
797
|
if (this.features?.bootloaderMode) {
|
|
757
798
|
return;
|
|
758
799
|
}
|
|
759
|
-
//
|
|
760
|
-
//
|
|
800
|
+
// Normal calls reuse the cache. Explicit getDeviceState refreshes, unlock flow,
|
|
801
|
+
// and device events update dynamic state without polling on every SDK call.
|
|
761
802
|
return;
|
|
762
803
|
}
|
|
763
804
|
await this._initializeProtocolV2(options);
|
|
@@ -811,23 +852,25 @@ export class Device extends EventEmitter {
|
|
|
811
852
|
/**
|
|
812
853
|
* Device initialization over Protocol V2.
|
|
813
854
|
*
|
|
814
|
-
* Protocol V2
|
|
815
|
-
*
|
|
855
|
+
* Protocol V2 bypasses legacy Initialize/GetFeatures and builds its canonical
|
|
856
|
+
* features state directly from DeviceInfoGet.
|
|
816
857
|
*/
|
|
817
858
|
private async _initializeProtocolV2(options?: InitOptions) {
|
|
818
859
|
Log.debug('Initialize device via Protocol V2 features adapter');
|
|
819
860
|
|
|
820
861
|
try {
|
|
821
|
-
//
|
|
822
|
-
//
|
|
823
|
-
// 且 reject 后底层调用仍会残留。
|
|
862
|
+
// typedCall applies the request timeout. An outer Promise.race would leak its
|
|
863
|
+
// timer and leave the underlying call active after rejection.
|
|
824
864
|
const deviceInfo = await requestProtocolV2DeviceInfo({
|
|
825
865
|
commands: this.commands,
|
|
826
866
|
timeoutMs: options?.protocolV2DeviceInfoTimeoutMs,
|
|
827
867
|
});
|
|
828
|
-
//
|
|
829
|
-
//
|
|
830
|
-
const features = this.
|
|
868
|
+
// The default request excludes SE/hash data and therefore uses basic scope.
|
|
869
|
+
// Full version and verification data require getDeviceState({ scope: 'firmware' }).
|
|
870
|
+
const features = await this.probeProtocolV2RuntimeState(
|
|
871
|
+
deviceInfo,
|
|
872
|
+
options?.protocolV2DeviceInfoTimeoutMs
|
|
873
|
+
);
|
|
831
874
|
Log.debug('Protocol V2 features:', features);
|
|
832
875
|
} catch (error) {
|
|
833
876
|
Log.error('Protocol V2 initialization failed:', error);
|
|
@@ -840,7 +883,7 @@ export class Device extends EventEmitter {
|
|
|
840
883
|
const deviceInfo = await requestProtocolV2DeviceInfo({
|
|
841
884
|
commands: this.commands,
|
|
842
885
|
});
|
|
843
|
-
return this.
|
|
886
|
+
return this.probeProtocolV2RuntimeState(deviceInfo);
|
|
844
887
|
}
|
|
845
888
|
|
|
846
889
|
const { message } = await this.commands.typedCall('GetFeatures', 'Features', {});
|
|
@@ -856,6 +899,7 @@ export class Device extends EventEmitter {
|
|
|
856
899
|
return PROTOCOL_V2_FEATURES_DEVICE_INFO_REQUEST;
|
|
857
900
|
};
|
|
858
901
|
let initializedWithDeviceInfo = false;
|
|
902
|
+
let refreshedDeviceInfo: ProtocolV2DeviceInfo | undefined;
|
|
859
903
|
|
|
860
904
|
if (!this.state) {
|
|
861
905
|
if (this.isProtocolV2()) {
|
|
@@ -863,7 +907,8 @@ export class Device extends EventEmitter {
|
|
|
863
907
|
commands: this.commands,
|
|
864
908
|
request: getProtocolV2DeviceInfoRequest(),
|
|
865
909
|
});
|
|
866
|
-
this.
|
|
910
|
+
await this.probeProtocolV2RuntimeState(deviceInfo);
|
|
911
|
+
refreshedDeviceInfo = deviceInfo;
|
|
867
912
|
initializedWithDeviceInfo = true;
|
|
868
913
|
} else {
|
|
869
914
|
await this.getFeatures();
|
|
@@ -885,15 +930,23 @@ export class Device extends EventEmitter {
|
|
|
885
930
|
commands: this.commands,
|
|
886
931
|
request: getProtocolV2DeviceInfoRequest(),
|
|
887
932
|
});
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
933
|
+
refreshedDeviceInfo = deviceInfo;
|
|
934
|
+
if (!refresh.has('status')) {
|
|
935
|
+
this.updateState(
|
|
936
|
+
mapProtocolV2DeviceInfoToState(deviceInfo, this.state?.status.mode),
|
|
937
|
+
'device-info'
|
|
938
|
+
);
|
|
939
|
+
}
|
|
892
940
|
}
|
|
893
941
|
|
|
894
|
-
if (refresh.has('status') &&
|
|
895
|
-
const
|
|
896
|
-
|
|
942
|
+
if (refresh.has('status') && !initializedWithDeviceInfo) {
|
|
943
|
+
const deviceInfo =
|
|
944
|
+
refreshedDeviceInfo ??
|
|
945
|
+
(await requestProtocolV2DeviceInfo({
|
|
946
|
+
commands: this.commands,
|
|
947
|
+
request: getProtocolV2DeviceInfoRequest(),
|
|
948
|
+
}));
|
|
949
|
+
await this.probeProtocolV2RuntimeState(deviceInfo);
|
|
897
950
|
}
|
|
898
951
|
|
|
899
952
|
if (refresh.has('settings') && this.state?.status.mode === 'normal') {
|
|
@@ -909,11 +962,11 @@ export class Device extends EventEmitter {
|
|
|
909
962
|
if (!this.state) {
|
|
910
963
|
throw ERRORS.TypedError(HardwareErrorCode.DeviceInitializeFailed);
|
|
911
964
|
}
|
|
912
|
-
return params.includeRaw ?
|
|
965
|
+
return params.includeRaw ? cloneDeviceState(this.state) : createPublicDeviceState(this.state);
|
|
913
966
|
}
|
|
914
967
|
|
|
915
968
|
_updateFeatures(protoFeatures: PROTO.Features | Features, initSession?: boolean) {
|
|
916
|
-
const
|
|
969
|
+
const previousDeviceId = this.getCurrentDeviceId();
|
|
917
970
|
let feat =
|
|
918
971
|
'protocol' in protoFeatures
|
|
919
972
|
? protoFeatures
|
|
@@ -928,10 +981,7 @@ export class Device extends EventEmitter {
|
|
|
928
981
|
feat = fixFeaturesFirmwareVersion(feat);
|
|
929
982
|
|
|
930
983
|
this.updateState(mapFeaturesToState(feat), 'initialize');
|
|
931
|
-
|
|
932
|
-
if (previousCacheDeviceKey && nextCacheDeviceKey) {
|
|
933
|
-
deviceWalletSessionStore.migrateDeviceKey(previousCacheDeviceKey, nextCacheDeviceKey);
|
|
934
|
-
}
|
|
984
|
+
this.reconcileSessionCacheDeviceIdentity(previousDeviceId);
|
|
935
985
|
if (feat.deviceId && feat.sessionId) {
|
|
936
986
|
this.setInternalState(feat.sessionId, initSession);
|
|
937
987
|
}
|
|
@@ -959,14 +1009,6 @@ export class Device extends EventEmitter {
|
|
|
959
1009
|
return result.state;
|
|
960
1010
|
}
|
|
961
1011
|
|
|
962
|
-
clearCachedSession(deviceId?: string, passphraseState?: string) {
|
|
963
|
-
const current = this.state;
|
|
964
|
-
if (!current?.session) return false;
|
|
965
|
-
if (deviceId && current.identity.deviceId !== deviceId) return false;
|
|
966
|
-
if (passphraseState && current.session.passphraseState !== passphraseState) return false;
|
|
967
|
-
return this.stateStore.clearSession('session-clear') !== undefined;
|
|
968
|
-
}
|
|
969
|
-
|
|
970
1012
|
updateFeaturesPatch(patch: Partial<Features>, source: DeviceStateUpdateSource) {
|
|
971
1013
|
const currentFeatures = this.features;
|
|
972
1014
|
if (!currentFeatures) return undefined;
|
|
@@ -979,21 +1021,45 @@ export class Device extends EventEmitter {
|
|
|
979
1021
|
return this.features;
|
|
980
1022
|
}
|
|
981
1023
|
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
1024
|
+
async probeProtocolV2RuntimeState(deviceInfo: ProtocolV2DeviceInfo, timeoutMs?: number) {
|
|
1025
|
+
let deviceStatus: DeviceStatus;
|
|
1026
|
+
try {
|
|
1027
|
+
deviceStatus = await requestProtocolV2DeviceStatus({
|
|
1028
|
+
commands: this.commands,
|
|
1029
|
+
timeoutMs,
|
|
1030
|
+
});
|
|
1031
|
+
} catch (error) {
|
|
1032
|
+
const runtimeMode = getProtocolV2RuntimeMode({
|
|
1033
|
+
deviceInfo,
|
|
1034
|
+
deviceStatusAvailable: false,
|
|
1035
|
+
});
|
|
1036
|
+
Log.debug('Protocol V2 DeviceStatusGet unavailable; use temporary loader fallback', {
|
|
1037
|
+
runtimeMode,
|
|
1038
|
+
error: error instanceof Error ? error.message : String(error),
|
|
1039
|
+
});
|
|
1040
|
+
return this.updateProtocolV2Features(deviceInfo, null, runtimeMode);
|
|
986
1041
|
}
|
|
1042
|
+
return this.updateProtocolV2Features(deviceInfo, deviceStatus, 'normal');
|
|
1043
|
+
}
|
|
1044
|
+
|
|
1045
|
+
updateProtocolV2Features(
|
|
1046
|
+
deviceInfo?: ProtocolV2DeviceInfo,
|
|
1047
|
+
deviceStatus?: DeviceStatus | null,
|
|
1048
|
+
runtimeMode?: ProtocolV2RuntimeMode
|
|
1049
|
+
) {
|
|
1050
|
+
const previousDeviceId = this.getCurrentDeviceId();
|
|
1051
|
+
const resolvedMode =
|
|
1052
|
+
runtimeMode ??
|
|
1053
|
+
(deviceStatus
|
|
1054
|
+
? getProtocolV2RuntimeMode({ deviceInfo, deviceStatusAvailable: true })
|
|
1055
|
+
: this.state?.status.mode);
|
|
987
1056
|
if (deviceInfo) {
|
|
988
|
-
this.updateState(
|
|
989
|
-
mapProtocolV2DeviceInfoToState(deviceInfo, this.state?.status.mode),
|
|
990
|
-
'device-info'
|
|
991
|
-
);
|
|
1057
|
+
this.updateState(mapProtocolV2DeviceInfoToState(deviceInfo, resolvedMode), 'device-info');
|
|
992
1058
|
}
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
deviceWalletSessionStore.migrateDeviceKey(previousCacheDeviceKey, nextCacheDeviceKey);
|
|
1059
|
+
if (deviceStatus) {
|
|
1060
|
+
this.updateState(mapProtocolV2DeviceStatusToState(deviceStatus), 'device-status');
|
|
996
1061
|
}
|
|
1062
|
+
this.reconcileSessionCacheDeviceIdentity(previousDeviceId);
|
|
997
1063
|
return this.features as Features;
|
|
998
1064
|
}
|
|
999
1065
|
|
|
@@ -1010,7 +1076,6 @@ export class Device extends EventEmitter {
|
|
|
1010
1076
|
if (!this.isProtocolV2()) return;
|
|
1011
1077
|
this.protocolV2StateNeedsReload = true;
|
|
1012
1078
|
this.clearPreInitialized();
|
|
1013
|
-
this.clearCachedSession();
|
|
1014
1079
|
}
|
|
1015
1080
|
|
|
1016
1081
|
markProtocolV2Reboot(rebootType: DeviceRebootType) {
|
|
@@ -1042,7 +1107,6 @@ export class Device extends EventEmitter {
|
|
|
1042
1107
|
attachToPinEnabled: null,
|
|
1043
1108
|
unlockedAttachPin: null,
|
|
1044
1109
|
},
|
|
1045
|
-
session: null,
|
|
1046
1110
|
raw: { protocolV2DeviceStatus: null },
|
|
1047
1111
|
},
|
|
1048
1112
|
'transport-reconnect'
|
|
@@ -1053,7 +1117,6 @@ export class Device extends EventEmitter {
|
|
|
1053
1117
|
this.updateState(
|
|
1054
1118
|
{
|
|
1055
1119
|
status: { mode: 'normal', unlocked: null },
|
|
1056
|
-
session: null,
|
|
1057
1120
|
raw: { protocolV2DeviceStatus: null },
|
|
1058
1121
|
},
|
|
1059
1122
|
'transport-reconnect'
|
|
@@ -1078,8 +1141,7 @@ export class Device extends EventEmitter {
|
|
|
1078
1141
|
}
|
|
1079
1142
|
|
|
1080
1143
|
if (forceUpdate) {
|
|
1081
|
-
//
|
|
1082
|
-
// 不能让覆盖丢掉已探测的协议结果。
|
|
1144
|
+
// Enumerated descriptors may omit protocolType, so preserve an actively probed value.
|
|
1083
1145
|
this.originalDescriptor = {
|
|
1084
1146
|
...descriptor,
|
|
1085
1147
|
protocolType: descriptor.protocolType ?? this.originalDescriptor.protocolType,
|
|
@@ -1104,19 +1166,37 @@ export class Device extends EventEmitter {
|
|
|
1104
1166
|
|
|
1105
1167
|
options = parseRunOptions(options);
|
|
1106
1168
|
|
|
1107
|
-
|
|
1108
|
-
|
|
1169
|
+
const runPromise = createDeferred<void>();
|
|
1170
|
+
this.runPromise = runPromise;
|
|
1171
|
+
this._runInner(fn, options, runPromise).catch(error => {
|
|
1172
|
+
if (this.runPromise === runPromise) {
|
|
1173
|
+
this.runPromise = null;
|
|
1174
|
+
}
|
|
1175
|
+
runPromise.reject(error);
|
|
1176
|
+
});
|
|
1177
|
+
return runPromise.promise;
|
|
1109
1178
|
}
|
|
1110
1179
|
|
|
1111
|
-
async _runInner<T>(
|
|
1180
|
+
async _runInner<T>(
|
|
1181
|
+
fn: (() => Promise<T>) | undefined,
|
|
1182
|
+
options: RunOptions,
|
|
1183
|
+
runPromise: Deferred<void>
|
|
1184
|
+
) {
|
|
1185
|
+
const clearRunPromise = () => {
|
|
1186
|
+
if (this.runPromise === runPromise) {
|
|
1187
|
+
this.runPromise = null;
|
|
1188
|
+
}
|
|
1189
|
+
};
|
|
1190
|
+
|
|
1112
1191
|
if (!this.isUsedHere() || this.commands.disposed) {
|
|
1113
1192
|
const env = DataManager.getSettings('env');
|
|
1114
1193
|
if (env !== 'react-native') {
|
|
1115
1194
|
try {
|
|
1116
1195
|
await this.acquire(options.connectProtocol);
|
|
1117
1196
|
} catch (error) {
|
|
1118
|
-
|
|
1119
|
-
|
|
1197
|
+
clearRunPromise();
|
|
1198
|
+
runPromise.reject(error);
|
|
1199
|
+
return;
|
|
1120
1200
|
}
|
|
1121
1201
|
|
|
1122
1202
|
try {
|
|
@@ -1127,16 +1207,18 @@ export class Device extends EventEmitter {
|
|
|
1127
1207
|
}
|
|
1128
1208
|
} catch (error) {
|
|
1129
1209
|
await this.release();
|
|
1130
|
-
|
|
1210
|
+
clearRunPromise();
|
|
1131
1211
|
if (error instanceof HardwareError) {
|
|
1132
|
-
|
|
1212
|
+
runPromise.reject(error);
|
|
1213
|
+
return;
|
|
1133
1214
|
}
|
|
1134
|
-
|
|
1215
|
+
runPromise.reject(
|
|
1135
1216
|
ERRORS.TypedError(
|
|
1136
1217
|
HardwareErrorCode.DeviceInitializeFailed,
|
|
1137
1218
|
`Initialize failed: ${error.message as string}, code: ${error.code as string}`
|
|
1138
1219
|
)
|
|
1139
1220
|
);
|
|
1221
|
+
return;
|
|
1140
1222
|
}
|
|
1141
1223
|
} else if (env === 'react-native') {
|
|
1142
1224
|
// TODO: implement react-native acquire
|
|
@@ -1155,9 +1237,7 @@ export class Device extends EventEmitter {
|
|
|
1155
1237
|
try {
|
|
1156
1238
|
await fn();
|
|
1157
1239
|
} catch (e) {
|
|
1158
|
-
|
|
1159
|
-
this.runPromise.reject(e);
|
|
1160
|
-
}
|
|
1240
|
+
runPromise.reject(e);
|
|
1161
1241
|
|
|
1162
1242
|
if (
|
|
1163
1243
|
e instanceof HardwareError &&
|
|
@@ -1170,7 +1250,7 @@ export class Device extends EventEmitter {
|
|
|
1170
1250
|
Log.debug(`error code ${e.errorCode} release device, mainId: ${this.mainId}`);
|
|
1171
1251
|
}
|
|
1172
1252
|
|
|
1173
|
-
|
|
1253
|
+
clearRunPromise();
|
|
1174
1254
|
return;
|
|
1175
1255
|
}
|
|
1176
1256
|
}
|
|
@@ -1184,11 +1264,8 @@ export class Device extends EventEmitter {
|
|
|
1184
1264
|
Log.debug('release device, mainId: ', this.mainId);
|
|
1185
1265
|
}
|
|
1186
1266
|
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
}
|
|
1190
|
-
|
|
1191
|
-
this.runPromise = null;
|
|
1267
|
+
runPromise.resolve();
|
|
1268
|
+
clearRunPromise();
|
|
1192
1269
|
}
|
|
1193
1270
|
|
|
1194
1271
|
async interruptionFromOutside() {
|
|
@@ -1343,7 +1420,7 @@ export class Device extends EventEmitter {
|
|
|
1343
1420
|
}
|
|
1344
1421
|
|
|
1345
1422
|
supportUnlockVersionRange(): DeviceFirmwareRange {
|
|
1346
|
-
//
|
|
1423
|
+
// This range applies to Protocol V1 Pro devices; Pro2 has a dedicated unlock flow.
|
|
1347
1424
|
return {
|
|
1348
1425
|
pro: {
|
|
1349
1426
|
min: '4.15.0',
|
|
@@ -1368,7 +1445,8 @@ export class Device extends EventEmitter {
|
|
|
1368
1445
|
throw error;
|
|
1369
1446
|
}
|
|
1370
1447
|
|
|
1371
|
-
|
|
1448
|
+
const status = await requestProtocolV2DeviceStatus({ commands: this.commands });
|
|
1449
|
+
return this.updateProtocolV2Status(status);
|
|
1372
1450
|
}
|
|
1373
1451
|
|
|
1374
1452
|
const firmwareVersion = this.getCurrentFirmwareVersionString() ?? '0.0.0';
|
|
@@ -1433,21 +1511,27 @@ export class Device extends EventEmitter {
|
|
|
1433
1511
|
) {
|
|
1434
1512
|
if (this.isUnacquired()) return false;
|
|
1435
1513
|
|
|
1514
|
+
const expectedPassphraseState = useEmptyPassphrase ? undefined : passphraseState;
|
|
1436
1515
|
const { passphraseState: newPassphraseState, unlockedAttachPin } =
|
|
1437
1516
|
await getPassphraseStateWithRefreshDeviceInfo(this, {
|
|
1438
|
-
expectPassphraseState:
|
|
1517
|
+
expectPassphraseState: expectedPassphraseState,
|
|
1439
1518
|
onlyMainPin: useEmptyPassphrase,
|
|
1440
1519
|
});
|
|
1441
1520
|
|
|
1442
1521
|
// Main wallet and unlock Attach Pin, throw safe error
|
|
1443
1522
|
const mainWalletUseAttachPin = unlockedAttachPin && useEmptyPassphrase;
|
|
1444
1523
|
const useErrorAttachPin =
|
|
1445
|
-
unlockedAttachPin &&
|
|
1446
|
-
|
|
1524
|
+
unlockedAttachPin &&
|
|
1525
|
+
expectedPassphraseState &&
|
|
1526
|
+
expectedPassphraseState !== newPassphraseState;
|
|
1527
|
+
const passphraseStateMismatch =
|
|
1528
|
+
!!expectedPassphraseState && expectedPassphraseState !== newPassphraseState;
|
|
1447
1529
|
|
|
1448
1530
|
Log.debug('Check passphrase state safety: ', {
|
|
1449
|
-
|
|
1450
|
-
newPassphraseState,
|
|
1531
|
+
hasExpectedPassphraseState: Boolean(expectedPassphraseState),
|
|
1532
|
+
hasNewPassphraseState: Boolean(newPassphraseState),
|
|
1533
|
+
passphraseStateMatches:
|
|
1534
|
+
Boolean(expectedPassphraseState) && expectedPassphraseState === newPassphraseState,
|
|
1451
1535
|
unlockedAttachPin,
|
|
1452
1536
|
useEmptyPassphrase,
|
|
1453
1537
|
});
|