@onekeyfe/hd-core 1.2.0-alpha.0 → 1.2.0-alpha.10
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__/connectSettings.test.ts +19 -0
- package/__tests__/device-wallet-session-store.test.ts +131 -0
- package/__tests__/preInitialize.test.ts +33 -0
- package/__tests__/protocol-v2-firmware-targets.test.ts +19 -0
- package/__tests__/protocol-v2.test.ts +1930 -765
- package/dist/api/ClearSessionCache.d.ts +9 -0
- package/dist/api/ClearSessionCache.d.ts.map +1 -0
- package/dist/api/FileRead.d.ts.map +1 -1
- package/dist/api/FileWrite.d.ts.map +1 -1
- package/dist/api/FirmwareUpdateV2.d.ts.map +1 -1
- package/dist/api/FirmwareUpdateV3.d.ts.map +1 -1
- package/dist/api/FirmwareUpdateV4.d.ts +26 -5
- package/dist/api/FirmwareUpdateV4.d.ts.map +1 -1
- package/dist/api/GetDeviceInfo.d.ts.map +1 -1
- package/dist/api/GetFeatures.d.ts +1 -1
- package/dist/api/GetOnekeyFeatures.d.ts.map +1 -1
- package/dist/api/GetPassphraseState.d.ts +4 -4
- package/dist/api/GetPassphraseState.d.ts.map +1 -1
- package/dist/api/device/DeviceUnlock.d.ts +1 -1
- package/dist/api/firmware/FirmwareUpdateBaseMethod.d.ts +1 -0
- package/dist/api/firmware/FirmwareUpdateBaseMethod.d.ts.map +1 -1
- package/dist/api/firmware/bootloaderHelper.d.ts.map +1 -1
- package/dist/api/firmware/getBinary.d.ts +4 -0
- package/dist/api/firmware/getBinary.d.ts.map +1 -1
- package/dist/api/firmware/progressThrottle.d.ts +3 -0
- package/dist/api/firmware/progressThrottle.d.ts.map +1 -0
- package/dist/api/firmware/uploadFirmware.d.ts.map +1 -1
- package/dist/api/index.d.ts +8 -10
- package/dist/api/index.d.ts.map +1 -1
- package/dist/api/protocol-v2/DeviceFactoryInfoGet.d.ts +6 -0
- package/dist/api/protocol-v2/DeviceFactoryInfoGet.d.ts.map +1 -0
- package/dist/api/protocol-v2/DeviceFactoryInfoSet.d.ts +7 -0
- package/dist/api/protocol-v2/DeviceFactoryInfoSet.d.ts.map +1 -0
- package/dist/api/protocol-v2/DeviceFirmwareUpdate.d.ts +1 -1
- package/dist/api/protocol-v2/DeviceFirmwareUpdate.d.ts.map +1 -1
- package/dist/api/protocol-v2/DeviceGetFirmwareUpdateStatus.d.ts +3 -2
- package/dist/api/protocol-v2/DeviceGetFirmwareUpdateStatus.d.ts.map +1 -1
- package/dist/api/protocol-v2/{DeviceGetDeviceInfo.d.ts → DeviceInfoGet.d.ts} +10 -10
- package/dist/api/protocol-v2/DeviceInfoGet.d.ts.map +1 -0
- package/dist/api/protocol-v2/DeviceSessionGet.d.ts +9 -0
- package/dist/api/protocol-v2/DeviceSessionGet.d.ts.map +1 -0
- package/dist/api/protocol-v2/DeviceStatusGet.d.ts +6 -0
- package/dist/api/protocol-v2/DeviceStatusGet.d.ts.map +1 -0
- package/dist/api/protocol-v2/FilesystemFormat.d.ts.map +1 -1
- package/dist/api/protocol-v2/{FilesystemFixPermission.d.ts → FilesystemPermissionFix.d.ts} +2 -2
- package/dist/api/protocol-v2/FilesystemPermissionFix.d.ts.map +1 -0
- package/dist/api/protocol-v2/ProtocolInfoRequest.d.ts +6 -0
- package/dist/api/protocol-v2/ProtocolInfoRequest.d.ts.map +1 -0
- package/dist/api/protocol-v2/helpers.d.ts +27 -19
- package/dist/api/protocol-v2/helpers.d.ts.map +1 -1
- package/dist/api/ton/TonSignData.d.ts +1 -5
- package/dist/api/ton/TonSignData.d.ts.map +1 -1
- package/dist/api/tron/TronSignMessage.d.ts +0 -1
- package/dist/api/tron/TronSignMessage.d.ts.map +1 -1
- package/dist/api/tron/TronSignTransaction.d.ts +0 -1
- package/dist/api/tron/TronSignTransaction.d.ts.map +1 -1
- package/dist/constants/index.d.ts +2 -1
- package/dist/constants/index.d.ts.map +1 -1
- package/dist/core/index.d.ts.map +1 -1
- package/dist/data-manager/DataManager.d.ts +1 -1
- package/dist/data-manager/DataManager.d.ts.map +1 -1
- package/dist/data-manager/connectSettings.d.ts.map +1 -1
- package/dist/device/Device.d.ts +17 -18
- package/dist/device/Device.d.ts.map +1 -1
- package/dist/device/DeviceWalletSessionStore.d.ts +15 -0
- package/dist/device/DeviceWalletSessionStore.d.ts.map +1 -0
- package/dist/deviceProfile/buildDeviceFeatures.d.ts +6 -0
- package/dist/deviceProfile/buildDeviceFeatures.d.ts.map +1 -0
- package/dist/deviceProfile/buildDeviceProfile.d.ts +3 -4
- package/dist/deviceProfile/buildDeviceProfile.d.ts.map +1 -1
- package/dist/deviceProfile/index.d.ts +1 -1
- package/dist/deviceProfile/index.d.ts.map +1 -1
- package/dist/index.d.ts +657 -539
- package/dist/index.js +2579 -2161
- package/dist/inject.d.ts.map +1 -1
- package/dist/protocols/protocol-v2/features.d.ts +12 -14
- package/dist/protocols/protocol-v2/features.d.ts.map +1 -1
- package/dist/protocols/protocol-v2/firmware.d.ts +11 -9
- package/dist/protocols/protocol-v2/firmware.d.ts.map +1 -1
- package/dist/protocols/protocol-v2/index.d.ts +1 -0
- package/dist/protocols/protocol-v2/index.d.ts.map +1 -1
- package/dist/protocols/protocol-v2/walletSession.d.ts +13 -0
- package/dist/protocols/protocol-v2/walletSession.d.ts.map +1 -0
- package/dist/types/api/firmwareUpdate.d.ts +4 -6
- package/dist/types/api/firmwareUpdate.d.ts.map +1 -1
- package/dist/types/api/getDeviceInfo.d.ts +4 -2
- package/dist/types/api/getDeviceInfo.d.ts.map +1 -1
- package/dist/types/api/getPassphraseState.d.ts +4 -4
- package/dist/types/api/getPassphraseState.d.ts.map +1 -1
- package/dist/types/api/index.d.ts +11 -11
- package/dist/types/api/index.d.ts.map +1 -1
- package/dist/types/api/protocolV2.d.ts +16 -17
- package/dist/types/api/protocolV2.d.ts.map +1 -1
- package/dist/types/api/sessionCache.d.ts +10 -0
- package/dist/types/api/sessionCache.d.ts.map +1 -0
- package/dist/types/device.d.ts +88 -8
- package/dist/types/device.d.ts.map +1 -1
- package/dist/types/params.d.ts +1 -0
- package/dist/types/params.d.ts.map +1 -1
- package/dist/types/settings.d.ts +21 -1
- package/dist/types/settings.d.ts.map +1 -1
- package/dist/utils/capabilitieUtils.d.ts.map +1 -1
- package/dist/utils/deviceFeaturesUtils.d.ts +2 -0
- package/dist/utils/deviceFeaturesUtils.d.ts.map +1 -1
- package/dist/utils/deviceInfoUtils.d.ts.map +1 -1
- package/dist/utils/deviceVersionUtils.d.ts.map +1 -1
- package/dist/utils/findDefectiveBatchDevice.d.ts +1 -1
- package/dist/utils/patch.d.ts +1 -1
- package/dist/utils/patch.d.ts.map +1 -1
- package/package.json +4 -4
- package/src/api/ClearSessionCache.ts +28 -0
- package/src/api/FileRead.ts +16 -3
- package/src/api/FileWrite.ts +14 -1
- package/src/api/FirmwareUpdateV2.ts +9 -2
- package/src/api/FirmwareUpdateV3.ts +2 -1
- package/src/api/FirmwareUpdateV4.ts +1089 -285
- package/src/api/GetDeviceInfo.ts +6 -13
- package/src/api/GetOnekeyFeatures.ts +3 -14
- package/src/api/GetPassphraseState.ts +7 -4
- package/src/api/device/DeviceRebootToBoardloader.ts +4 -4
- package/src/api/device/DeviceRebootToBootloader.ts +4 -4
- package/src/api/firmware/FirmwareUpdateBaseMethod.ts +18 -4
- package/src/api/firmware/bootloaderHelper.ts +3 -2
- package/src/api/firmware/getBinary.ts +1 -1
- package/src/api/firmware/progressThrottle.ts +44 -0
- package/src/api/firmware/releaseHelper.ts +3 -3
- package/src/api/firmware/uploadFirmware.ts +5 -2
- package/src/api/index.ts +8 -10
- package/src/api/protocol-v2/{FactoryGetDeviceInfo.ts → DeviceFactoryInfoGet.ts} +3 -3
- package/src/api/protocol-v2/DeviceFactoryInfoSet.ts +32 -0
- package/src/api/protocol-v2/DeviceFirmwareUpdate.ts +3 -5
- package/src/api/protocol-v2/DeviceGetFirmwareUpdateStatus.ts +39 -5
- package/src/api/protocol-v2/{DeviceGetDeviceInfo.ts → DeviceInfoGet.ts} +52 -22
- package/src/api/protocol-v2/DeviceReboot.ts +2 -2
- package/src/api/protocol-v2/DeviceSessionGet.ts +26 -0
- package/src/api/protocol-v2/DeviceStatusGet.ts +14 -0
- package/src/api/protocol-v2/FilesystemFormat.ts +4 -1
- package/src/api/protocol-v2/{FilesystemFixPermission.ts → FilesystemPermissionFix.ts} +2 -2
- package/src/api/protocol-v2/{GetProtoVersion.ts → ProtocolInfoRequest.ts} +2 -2
- package/src/api/protocol-v2/helpers.ts +58 -59
- package/src/api/ton/TonSignData.ts +1 -5
- package/src/api/tron/TronSignMessage.ts +0 -1
- package/src/api/tron/TronSignTransaction.ts +0 -1
- package/src/constants/index.ts +10 -1
- package/src/core/index.ts +22 -10
- package/src/data/messages/messages-protocol-v2.json +992 -1420
- package/src/data/messages/messages.json +8 -0
- package/src/data-manager/DataManager.ts +11 -4
- package/src/data-manager/connectSettings.ts +4 -0
- package/src/device/Device.ts +158 -294
- package/src/device/DevicePool.ts +9 -9
- package/src/device/DeviceWalletSessionStore.ts +78 -0
- package/src/deviceProfile/buildDeviceFeatures.ts +365 -0
- package/src/deviceProfile/buildDeviceProfile.ts +165 -200
- package/src/deviceProfile/index.ts +4 -1
- package/src/inject.ts +13 -16
- package/src/protocols/protocol-v2/features.ts +28 -67
- package/src/protocols/protocol-v2/firmware.ts +12 -36
- package/src/protocols/protocol-v2/index.ts +1 -0
- package/src/protocols/protocol-v2/walletSession.ts +83 -0
- package/src/types/api/firmwareUpdate.ts +16 -20
- package/src/types/api/getDeviceInfo.ts +4 -2
- package/src/types/api/getPassphraseState.ts +4 -4
- package/src/types/api/index.ts +17 -20
- package/src/types/api/protocolV2.ts +35 -40
- package/src/types/api/sessionCache.ts +14 -0
- package/src/types/device.ts +98 -34
- package/src/types/params.ts +4 -0
- package/src/types/settings.ts +42 -30
- package/src/utils/capabilitieUtils.ts +1 -2
- package/src/utils/deviceFeaturesUtils.ts +54 -29
- package/src/utils/deviceInfoUtils.ts +11 -29
- package/src/utils/deviceVersionUtils.ts +7 -25
- package/src/utils/findDefectiveBatchDevice.ts +6 -6
- package/dist/api/protocol-v2/DevReboot.d.ts +0 -7
- package/dist/api/protocol-v2/DevReboot.d.ts.map +0 -1
- package/dist/api/protocol-v2/DeviceGetDeviceInfo.d.ts.map +0 -1
- package/dist/api/protocol-v2/DeviceGetOnboardingStatus.d.ts +0 -6
- package/dist/api/protocol-v2/DeviceGetOnboardingStatus.d.ts.map +0 -1
- package/dist/api/protocol-v2/FactoryDeviceInfoSettings.d.ts +0 -7
- package/dist/api/protocol-v2/FactoryDeviceInfoSettings.d.ts.map +0 -1
- package/dist/api/protocol-v2/FactoryGetDeviceInfo.d.ts +0 -6
- package/dist/api/protocol-v2/FactoryGetDeviceInfo.d.ts.map +0 -1
- package/dist/api/protocol-v2/FilesystemFixPermission.d.ts.map +0 -1
- package/dist/api/protocol-v2/GetProtoVersion.d.ts +0 -6
- package/dist/api/protocol-v2/GetProtoVersion.d.ts.map +0 -1
- package/dist/deviceProfile/legacyFeaturesView.d.ts +0 -5
- package/dist/deviceProfile/legacyFeaturesView.d.ts.map +0 -1
- package/src/api/protocol-v2/DevReboot.ts +0 -24
- package/src/api/protocol-v2/DeviceGetOnboardingStatus.ts +0 -16
- package/src/api/protocol-v2/FactoryDeviceInfoSettings.ts +0 -29
- package/src/deviceProfile/legacyFeaturesView.ts +0 -123
package/src/device/Device.ts
CHANGED
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
HardwareError,
|
|
10
10
|
HardwareErrorCode,
|
|
11
11
|
createDeferred,
|
|
12
|
+
createDeviceNotSupportMethodError,
|
|
12
13
|
} from '@onekeyfe/hd-shared';
|
|
13
14
|
|
|
14
15
|
import {
|
|
@@ -31,6 +32,7 @@ import {
|
|
|
31
32
|
import { generateInstanceId } from '../utils/tracing';
|
|
32
33
|
// eslint-disable-next-line import/no-cycle
|
|
33
34
|
import { DeviceCommands } from './DeviceCommands';
|
|
35
|
+
import { deviceWalletSessionStore } from './DeviceWalletSessionStore';
|
|
34
36
|
import {
|
|
35
37
|
type DeviceFirmwareRange,
|
|
36
38
|
DeviceModelToTypes,
|
|
@@ -40,7 +42,6 @@ import {
|
|
|
40
42
|
type Features,
|
|
41
43
|
type IDeviceModel,
|
|
42
44
|
type IDeviceType,
|
|
43
|
-
type IVersionArray,
|
|
44
45
|
type IVersionRange,
|
|
45
46
|
type SupportFeatureType,
|
|
46
47
|
type UnavailableCapabilities,
|
|
@@ -54,11 +55,8 @@ import {
|
|
|
54
55
|
PROTOCOL_V2_STATUS_DEVICE_INFO_REQUEST,
|
|
55
56
|
requestProtocolV2DeviceInfo,
|
|
56
57
|
} from '../protocols/protocol-v2/features';
|
|
57
|
-
import {
|
|
58
|
-
|
|
59
|
-
buildProfileFromProtocolV2,
|
|
60
|
-
buildProtocolV2GetFeaturesPayload,
|
|
61
|
-
} from '../deviceProfile';
|
|
58
|
+
import { refreshProtocolV2DeviceStatus } from '../protocols/protocol-v2/walletSession';
|
|
59
|
+
import { buildProtocolV1FeaturesPayload, buildProtocolV2FeaturesPayload } from '../deviceProfile';
|
|
62
60
|
|
|
63
61
|
import type { PROTO } from '../constants';
|
|
64
62
|
import type {
|
|
@@ -70,11 +68,11 @@ import type { PassphrasePromptResponse } from './DeviceCommands';
|
|
|
70
68
|
import type { Deferred, HardwareConnectProtocol } from '@onekeyfe/hd-shared';
|
|
71
69
|
import type {
|
|
72
70
|
OneKeyDeviceInfo as DeviceDescriptor,
|
|
71
|
+
DeviceStatus,
|
|
73
72
|
ProtocolV2DeviceInfo,
|
|
74
73
|
Success,
|
|
75
74
|
} from '@onekeyfe/hd-transport';
|
|
76
75
|
import type DeviceConnector from './DeviceConnector';
|
|
77
|
-
import type { DeviceProfile } from '../types/api/getDeviceInfo';
|
|
78
76
|
|
|
79
77
|
export type InitOptions = {
|
|
80
78
|
initSession?: boolean;
|
|
@@ -82,6 +80,7 @@ export type InitOptions = {
|
|
|
82
80
|
passphraseState?: string;
|
|
83
81
|
deriveCardano?: boolean;
|
|
84
82
|
connectProtocol?: HardwareConnectProtocol;
|
|
83
|
+
protocolV2DeviceInfoTimeoutMs?: number;
|
|
85
84
|
};
|
|
86
85
|
|
|
87
86
|
export type RunOptions = {
|
|
@@ -96,11 +95,6 @@ const parseRunOptions = (options?: RunOptions): RunOptions => {
|
|
|
96
95
|
|
|
97
96
|
const Log = getLogger(LoggerNames.Device);
|
|
98
97
|
|
|
99
|
-
const profileVersionToArray = (version?: string | null): IVersionArray | null => {
|
|
100
|
-
if (!version) return null;
|
|
101
|
-
return version.split('.').map(part => Number(part) || 0) as IVersionArray;
|
|
102
|
-
};
|
|
103
|
-
|
|
104
98
|
export interface DeviceEvents {
|
|
105
99
|
[DEVICE.PIN]: [Device, PROTO.PinMatrixRequestType | undefined, (err: any, pin: string) => void];
|
|
106
100
|
[DEVICE.PASSPHRASE_ON_DEVICE]: [Device, ((response: any) => void)?];
|
|
@@ -129,8 +123,6 @@ export interface Device {
|
|
|
129
123
|
emit<K extends keyof DeviceEvents>(type: K, ...args: DeviceEvents[K]): boolean;
|
|
130
124
|
}
|
|
131
125
|
|
|
132
|
-
const deviceSessionCache: Record<string, string> = {};
|
|
133
|
-
|
|
134
126
|
/**
|
|
135
127
|
* Pre-populate the device session cache with a known session ID.
|
|
136
128
|
*
|
|
@@ -148,8 +140,7 @@ export function preloadSessionCache(
|
|
|
148
140
|
passphraseState: string,
|
|
149
141
|
sessionId: string
|
|
150
142
|
): void {
|
|
151
|
-
|
|
152
|
-
deviceSessionCache[key] = sessionId;
|
|
143
|
+
deviceWalletSessionStore.set(deviceId, passphraseState, sessionId);
|
|
153
144
|
}
|
|
154
145
|
|
|
155
146
|
export class Device extends EventEmitter {
|
|
@@ -198,37 +189,17 @@ export class Device extends EventEmitter {
|
|
|
198
189
|
/**
|
|
199
190
|
* 唯一设备状态缓存。
|
|
200
191
|
*
|
|
201
|
-
* V1 直接保存原生 Features;V2 保存由
|
|
202
|
-
*
|
|
203
|
-
*
|
|
192
|
+
* V1 直接保存原生 Features;V2 保存由 DeviceInfoGet 映射出的
|
|
193
|
+
* Features 视图。Device 不再保存 profile,结构化 DeviceProfile 只作为
|
|
194
|
+
* getDeviceInfo() 的 API 返回值存在。
|
|
204
195
|
*/
|
|
205
196
|
features: Features | undefined = undefined;
|
|
206
197
|
|
|
207
|
-
private getFeaturesProfile(): DeviceProfile | undefined {
|
|
208
|
-
if (!this.features) return undefined;
|
|
209
|
-
const protocol = this.originalDescriptor.protocolType === 'V2' ? 'V2' : 'V1';
|
|
210
|
-
return buildProfileFromProtocolV1({
|
|
211
|
-
protocol,
|
|
212
|
-
features: this.features,
|
|
213
|
-
onekeyFeatures: this.features as Parameters<typeof buildProfileFromProtocolV1>[0]['onekeyFeatures'],
|
|
214
|
-
sources: ['features'],
|
|
215
|
-
scope: 'verify',
|
|
216
|
-
});
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
get profile(): DeviceProfile | undefined {
|
|
220
|
-
return this.getFeaturesProfile();
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
set profile(profile: DeviceProfile | undefined) {
|
|
224
|
-
this.updateProfile(profile);
|
|
225
|
-
}
|
|
226
|
-
|
|
227
198
|
/**
|
|
228
199
|
* 是否需要更新设备信息。
|
|
229
200
|
*
|
|
230
201
|
* 历史名称保留用于兼容现有调用语义;对 V2 表示 features 需要由
|
|
231
|
-
*
|
|
202
|
+
* DeviceInfoGet 刷新。
|
|
232
203
|
*/
|
|
233
204
|
featuresNeedsReload = false;
|
|
234
205
|
|
|
@@ -292,13 +263,14 @@ export class Device extends EventEmitter {
|
|
|
292
263
|
const bleName = this.getCurrentBleName();
|
|
293
264
|
const label = this.getCurrentLabel();
|
|
294
265
|
const serialNo = this.getCurrentSerialNo();
|
|
266
|
+
const connectId = this.getConnectId();
|
|
295
267
|
const deviceId = this.getCurrentDeviceId() || null;
|
|
296
268
|
|
|
297
|
-
const features = this
|
|
269
|
+
const { features } = this;
|
|
298
270
|
|
|
299
271
|
return {
|
|
300
272
|
/** Android uses Mac address, iOS uses uuid, USB uses uuid */
|
|
301
|
-
connectId: DataManager.isBleConnect(env) ? this.mainId || null :
|
|
273
|
+
connectId: DataManager.isBleConnect(env) ? this.mainId || null : connectId,
|
|
302
274
|
/** Hardware ID, will not change at any time */
|
|
303
275
|
uuid: serialNo,
|
|
304
276
|
commType: this.originalDescriptor.commType,
|
|
@@ -314,8 +286,7 @@ export class Device extends EventEmitter {
|
|
|
314
286
|
label: label || 'OneKey',
|
|
315
287
|
mode: this.getMode(),
|
|
316
288
|
features,
|
|
317
|
-
|
|
318
|
-
sessionId: this.features?.session_id ?? null,
|
|
289
|
+
sessionId: this.features?.sessionId ?? null,
|
|
319
290
|
firmwareVersion: this.getFirmwareVersion(),
|
|
320
291
|
bleFirmwareVersion: this.getBLEFirmwareVersion(),
|
|
321
292
|
unavailableCapabilities: this.unavailableCapabilities,
|
|
@@ -357,7 +328,10 @@ export class Device extends EventEmitter {
|
|
|
357
328
|
});
|
|
358
329
|
}
|
|
359
330
|
|
|
360
|
-
async acquire(
|
|
331
|
+
async acquire(
|
|
332
|
+
connectProtocol?: HardwareConnectProtocol,
|
|
333
|
+
options?: { throwOnRunPromiseError?: boolean }
|
|
334
|
+
) {
|
|
361
335
|
const env = DataManager.getSettings('env');
|
|
362
336
|
const mainIdKey = DataManager.isBleConnect(env) ? 'id' : 'session';
|
|
363
337
|
const expectedProtocol = connectProtocol ?? this.originalDescriptor.protocolType;
|
|
@@ -406,6 +380,9 @@ export class Device extends EventEmitter {
|
|
|
406
380
|
|
|
407
381
|
this.commands = new DeviceCommands(this, this.mainId ?? '');
|
|
408
382
|
} catch (error) {
|
|
383
|
+
if (options?.throwOnRunPromiseError) {
|
|
384
|
+
throw error;
|
|
385
|
+
}
|
|
409
386
|
if (this.runPromise) {
|
|
410
387
|
this.runPromise.reject(error);
|
|
411
388
|
} else {
|
|
@@ -508,10 +485,10 @@ export class Device extends EventEmitter {
|
|
|
508
485
|
/**
|
|
509
486
|
* 唯一协议判别器。
|
|
510
487
|
*
|
|
511
|
-
* descriptor.protocolType 是协议探测后的结果;V2 features 由
|
|
512
|
-
*
|
|
488
|
+
* descriptor.protocolType 是协议探测后的结果;V2 features 由 DeviceInfoGet
|
|
489
|
+
* 映射产生。
|
|
513
490
|
* 全 SDK 的协议分支都必须走这里,不要直接读 originalDescriptor.protocolType
|
|
514
|
-
*
|
|
491
|
+
* 或从 features 反推。
|
|
515
492
|
*/
|
|
516
493
|
getProtocol(): 'V1' | 'V2' {
|
|
517
494
|
return this.originalDescriptor.protocolType === 'V2' ? 'V2' : 'V1';
|
|
@@ -522,57 +499,53 @@ export class Device extends EventEmitter {
|
|
|
522
499
|
}
|
|
523
500
|
|
|
524
501
|
getCurrentDeviceType() {
|
|
525
|
-
return
|
|
502
|
+
return getDeviceType(this.features);
|
|
526
503
|
}
|
|
527
504
|
|
|
528
505
|
getCurrentDeviceId() {
|
|
529
|
-
|
|
530
|
-
return this.profile.deviceId || undefined;
|
|
531
|
-
}
|
|
532
|
-
return this.features?.device_id || undefined;
|
|
506
|
+
return this.features?.deviceId || undefined;
|
|
533
507
|
}
|
|
534
508
|
|
|
535
509
|
getCurrentSerialNo() {
|
|
536
|
-
if (this.profile) {
|
|
537
|
-
return this.profile.serialNo || '';
|
|
538
|
-
}
|
|
539
510
|
return this.features ? getDeviceUUID(this.features) : '';
|
|
540
511
|
}
|
|
541
512
|
|
|
513
|
+
getConnectId() {
|
|
514
|
+
const serialNo = this.getCurrentSerialNo();
|
|
515
|
+
if (serialNo) return serialNo;
|
|
516
|
+
|
|
517
|
+
// connectId 是 SDK 内部连接路由 key。这里兜底到 transport descriptor,
|
|
518
|
+
// 不改变 features.serialNo / deviceId 的业务语义。
|
|
519
|
+
return this.originalDescriptor.path || this.originalDescriptor.id || '';
|
|
520
|
+
}
|
|
521
|
+
|
|
542
522
|
getCurrentBleName() {
|
|
543
|
-
|
|
544
|
-
if (this.isProtocolV2()) return this.profile?.bleName ?? null;
|
|
545
|
-
return this.profile?.bleName ?? getDeviceBleName(this.features);
|
|
523
|
+
return getDeviceBleName(this.features);
|
|
546
524
|
}
|
|
547
525
|
|
|
548
526
|
getCurrentLabel() {
|
|
549
|
-
|
|
550
|
-
return this.profile?.label ?? getDeviceLabel(this.features);
|
|
527
|
+
return getDeviceLabel(this.features);
|
|
551
528
|
}
|
|
552
529
|
|
|
553
530
|
getCurrentPassphraseProtection() {
|
|
554
|
-
|
|
555
|
-
return this.profile.status.passphraseProtection;
|
|
556
|
-
}
|
|
557
|
-
return this.features?.passphrase_protection;
|
|
531
|
+
return this.features?.passphraseProtection;
|
|
558
532
|
}
|
|
559
533
|
|
|
560
534
|
getCurrentFirmwareType() {
|
|
561
|
-
return
|
|
535
|
+
return getFirmwareType(this.features);
|
|
562
536
|
}
|
|
563
537
|
|
|
564
538
|
getCurrentFirmwareVersionString() {
|
|
565
|
-
return
|
|
539
|
+
return getDeviceFirmwareVersion(this.features)?.join('.');
|
|
566
540
|
}
|
|
567
541
|
|
|
568
542
|
getCurrentBLEFirmwareVersionString() {
|
|
569
|
-
if (this.profile?.versions.ble) return this.profile.versions.ble;
|
|
570
543
|
if (!this.features) return undefined;
|
|
571
544
|
return getDeviceBLEFirmwareVersion(this.features).join('.');
|
|
572
545
|
}
|
|
573
546
|
|
|
574
547
|
getCurrentSafetyChecks() {
|
|
575
|
-
return this.features?.
|
|
548
|
+
return this.features?.safetyChecks;
|
|
576
549
|
}
|
|
577
550
|
|
|
578
551
|
getCurrentMethodVersionRange(
|
|
@@ -656,24 +629,24 @@ export class Device extends EventEmitter {
|
|
|
656
629
|
};
|
|
657
630
|
}
|
|
658
631
|
|
|
659
|
-
private
|
|
660
|
-
|
|
661
|
-
|
|
632
|
+
private getSessionCacheDeviceKey(_deviceId?: string) {
|
|
633
|
+
const deviceId = _deviceId || this.getCurrentDeviceId();
|
|
634
|
+
if (deviceId) return deviceId;
|
|
635
|
+
if (this.isProtocolV2()) {
|
|
636
|
+
return this.originalDescriptor.path || this.originalDescriptor.id;
|
|
662
637
|
}
|
|
663
|
-
return
|
|
638
|
+
return undefined;
|
|
664
639
|
}
|
|
665
640
|
|
|
666
641
|
getInternalState(_deviceId?: string) {
|
|
667
|
-
Log.debug('getInternalState session cache: ', deviceSessionCache);
|
|
668
642
|
Log.debug(
|
|
669
643
|
'getInternalState session param: ',
|
|
670
644
|
`device_id: ${_deviceId}`,
|
|
671
|
-
`features.
|
|
672
|
-
`profile.deviceId: ${this.profile?.deviceId}`,
|
|
645
|
+
`features.deviceId: ${this.features?.deviceId}`,
|
|
673
646
|
`passphraseState: ${this.passphraseState}`
|
|
674
647
|
);
|
|
675
648
|
|
|
676
|
-
const deviceId =
|
|
649
|
+
const deviceId = this.getSessionCacheDeviceKey(_deviceId);
|
|
677
650
|
if (!deviceId) return undefined;
|
|
678
651
|
// Security invariant: no passphraseState → no session lookup.
|
|
679
652
|
// A previous fallback that scanned `${deviceId}@*` keys could silently
|
|
@@ -683,15 +656,14 @@ export class Device extends EventEmitter {
|
|
|
683
656
|
// downstream call carries it and hits the primary lookup below.
|
|
684
657
|
if (!this.passphraseState) return undefined;
|
|
685
658
|
|
|
686
|
-
|
|
687
|
-
return deviceSessionCache[usePassKey];
|
|
659
|
+
return deviceWalletSessionStore.get(deviceId, this.passphraseState);
|
|
688
660
|
}
|
|
689
661
|
|
|
690
662
|
// attach to pin to fix internal state
|
|
691
663
|
updateInternalState(
|
|
692
664
|
enablePassphrase: boolean,
|
|
693
665
|
passphraseState: string | undefined,
|
|
694
|
-
deviceId: string,
|
|
666
|
+
deviceId: string | undefined,
|
|
695
667
|
sessionId: string | null = null,
|
|
696
668
|
featuresSessionId: string | null = null
|
|
697
669
|
) {
|
|
@@ -700,62 +672,52 @@ export class Device extends EventEmitter {
|
|
|
700
672
|
`device_id: ${deviceId}`,
|
|
701
673
|
`enablePassphrase: ${enablePassphrase}`,
|
|
702
674
|
`passphraseState: ${passphraseState}`,
|
|
703
|
-
`
|
|
704
|
-
`
|
|
675
|
+
`hasSessionId: ${Boolean(sessionId)}`,
|
|
676
|
+
`hasFeaturesSessionId: ${Boolean(featuresSessionId)}`
|
|
705
677
|
);
|
|
706
678
|
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
if (sessionId) {
|
|
710
|
-
deviceSessionCache[this.generateStateKey(deviceId, passphraseState)] = sessionId;
|
|
711
|
-
} else if (featuresSessionId) {
|
|
712
|
-
deviceSessionCache[this.generateStateKey(deviceId, passphraseState)] = featuresSessionId;
|
|
713
|
-
}
|
|
714
|
-
}
|
|
679
|
+
const cacheDeviceKey = this.getSessionCacheDeviceKey(deviceId);
|
|
680
|
+
if (!cacheDeviceKey) return;
|
|
715
681
|
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
682
|
+
if (enablePassphrase) {
|
|
683
|
+
const walletSessionId =
|
|
684
|
+
sessionId || featuresSessionId || deviceWalletSessionStore.getPending(cacheDeviceKey);
|
|
685
|
+
deviceWalletSessionStore.set(cacheDeviceKey, passphraseState, walletSessionId ?? undefined);
|
|
720
686
|
}
|
|
721
687
|
|
|
722
|
-
|
|
688
|
+
deviceWalletSessionStore.deletePending(cacheDeviceKey);
|
|
723
689
|
}
|
|
724
690
|
|
|
725
691
|
private setInternalState(state: string, initSession?: boolean) {
|
|
726
692
|
Log.debug(
|
|
727
693
|
'setInternalState session param: ',
|
|
728
|
-
`
|
|
694
|
+
`hasState: ${Boolean(state)}`,
|
|
729
695
|
`initSession: ${initSession}`,
|
|
730
|
-
`
|
|
731
|
-
`profile.deviceId: ${this.profile?.deviceId}`,
|
|
696
|
+
`deviceId: ${this.features?.deviceId}`,
|
|
732
697
|
`passphraseState: ${this.passphraseState}`
|
|
733
698
|
);
|
|
734
699
|
|
|
735
700
|
if (!this.passphraseState && !initSession) return;
|
|
736
701
|
|
|
737
|
-
const deviceId = this.
|
|
702
|
+
const deviceId = this.getSessionCacheDeviceKey();
|
|
738
703
|
if (!deviceId) return;
|
|
739
704
|
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
if (
|
|
743
|
-
|
|
705
|
+
if (this.passphraseState) {
|
|
706
|
+
deviceWalletSessionStore.set(deviceId, this.passphraseState, state);
|
|
707
|
+
} else if (initSession) {
|
|
708
|
+
deviceWalletSessionStore.setPending(deviceId, state);
|
|
744
709
|
}
|
|
745
|
-
Log.debug('setInternalState done session cache: ', deviceSessionCache);
|
|
746
710
|
}
|
|
747
711
|
|
|
748
712
|
clearInternalState(_deviceId?: string) {
|
|
749
713
|
Log.debug('clearInternalState param: ', _deviceId);
|
|
750
714
|
|
|
751
|
-
const deviceId =
|
|
715
|
+
const deviceId = this.getSessionCacheDeviceKey(_deviceId);
|
|
752
716
|
if (!deviceId) return;
|
|
753
|
-
|
|
754
|
-
delete deviceSessionCache[key];
|
|
717
|
+
deviceWalletSessionStore.deletePending(deviceId);
|
|
755
718
|
|
|
756
719
|
if (this.passphraseState) {
|
|
757
|
-
|
|
758
|
-
delete deviceSessionCache[usePassKey];
|
|
720
|
+
deviceWalletSessionStore.delete(deviceId, this.passphraseState);
|
|
759
721
|
}
|
|
760
722
|
}
|
|
761
723
|
|
|
@@ -763,15 +725,17 @@ export class Device extends EventEmitter {
|
|
|
763
725
|
// Protocol V2 不支持传统 Initialize,直接使用协议专用初始化流程。
|
|
764
726
|
if (this.isProtocolV2()) {
|
|
765
727
|
this.passphraseState = options?.passphraseState;
|
|
766
|
-
if (this.
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
//
|
|
771
|
-
|
|
728
|
+
if (this.features && !this.featuresNeedsReload && !options?.initSession) {
|
|
729
|
+
if (this.features.bootloaderMode) {
|
|
730
|
+
return;
|
|
731
|
+
}
|
|
732
|
+
// 不能直接信任缓存 features:设备端 wipe / 完成初始化 / 改 label 后
|
|
733
|
+
// features 会永久陈旧。每次 run 做一次轻量 status 刷新(不含 fw/SE),
|
|
734
|
+
// 用字段级合并保留已有版本和 SE 信息。
|
|
735
|
+
await this._refreshProtocolV2Status(options);
|
|
772
736
|
return;
|
|
773
737
|
}
|
|
774
|
-
await this._initializeProtocolV2();
|
|
738
|
+
await this._initializeProtocolV2(options);
|
|
775
739
|
return;
|
|
776
740
|
}
|
|
777
741
|
|
|
@@ -821,11 +785,11 @@ export class Device extends EventEmitter {
|
|
|
821
785
|
/**
|
|
822
786
|
* Device initialization over Protocol V2.
|
|
823
787
|
*
|
|
824
|
-
* Protocol V2 不走传统 Initialize/GetFeatures
|
|
825
|
-
*
|
|
788
|
+
* Protocol V2 不走传统 Initialize/GetFeatures;直接用 DeviceInfoGet
|
|
789
|
+
* 生成唯一的 features 状态。
|
|
826
790
|
*/
|
|
827
|
-
private async _initializeProtocolV2() {
|
|
828
|
-
Log.debug('Initialize device via Protocol V2
|
|
791
|
+
private async _initializeProtocolV2(options?: InitOptions) {
|
|
792
|
+
Log.debug('Initialize device via Protocol V2 features adapter');
|
|
829
793
|
|
|
830
794
|
try {
|
|
831
795
|
// 超时由 requestProtocolV2DeviceInfo 内部的 typedCall timeoutMs(默认 10s)负责,
|
|
@@ -833,19 +797,12 @@ export class Device extends EventEmitter {
|
|
|
833
797
|
// 且 reject 后底层调用仍会残留。
|
|
834
798
|
const deviceInfo = await requestProtocolV2DeviceInfo({
|
|
835
799
|
commands: this.commands,
|
|
800
|
+
timeoutMs: options?.protocolV2DeviceInfoTimeoutMs,
|
|
836
801
|
});
|
|
837
802
|
// 默认请求不含 SE/hash 数据,scope 如实标注为 basic;
|
|
838
803
|
// 完整数据由 getDeviceInfo(scope:'verify'|'full') 获取。
|
|
839
|
-
const
|
|
840
|
-
|
|
841
|
-
deviceInfo,
|
|
842
|
-
sources: ['deviceInfo'],
|
|
843
|
-
scope: 'basic',
|
|
844
|
-
fallbackSerialNo: this.originalDescriptor?.path,
|
|
845
|
-
}),
|
|
846
|
-
deviceInfo
|
|
847
|
-
);
|
|
848
|
-
Log.debug('Protocol V2 profile:', profile);
|
|
804
|
+
const features = this.updateProtocolV2Features(deviceInfo);
|
|
805
|
+
Log.debug('Protocol V2 features:', features);
|
|
849
806
|
this.featuresNeedsReload = false;
|
|
850
807
|
} catch (error) {
|
|
851
808
|
Log.error('Protocol V2 initialization failed:', error);
|
|
@@ -856,27 +813,19 @@ export class Device extends EventEmitter {
|
|
|
856
813
|
/**
|
|
857
814
|
* Protocol V2 的轻量状态刷新(每次 run 前调用)。
|
|
858
815
|
*
|
|
859
|
-
* 请求 hw +
|
|
860
|
-
*
|
|
861
|
-
* 避免 applyProfileUpdate 的顶层字段覆盖把已有身份字段清空。
|
|
816
|
+
* 请求 hw + coprocessor + status(不含 fw/SE target):status 提供 init_states / label /
|
|
817
|
+
* passphrase_enabled 等会在设备端变化的字段;hw/coprocessor 提供 serialNo / bleName。
|
|
862
818
|
* versions 为空时按字段级合并保留旧值,verify 数据不会被降级。
|
|
863
819
|
*/
|
|
864
|
-
private async _refreshProtocolV2Status() {
|
|
820
|
+
private async _refreshProtocolV2Status(options?: InitOptions) {
|
|
865
821
|
try {
|
|
866
822
|
const deviceInfo = await requestProtocolV2DeviceInfo({
|
|
867
823
|
commands: this.commands,
|
|
868
824
|
request: PROTOCOL_V2_STATUS_DEVICE_INFO_REQUEST,
|
|
825
|
+
timeoutMs: options?.protocolV2DeviceInfoTimeoutMs,
|
|
869
826
|
});
|
|
870
|
-
const
|
|
871
|
-
|
|
872
|
-
deviceInfo,
|
|
873
|
-
sources: ['deviceInfo'],
|
|
874
|
-
scope: 'basic',
|
|
875
|
-
fallbackSerialNo: this.originalDescriptor?.path,
|
|
876
|
-
}),
|
|
877
|
-
deviceInfo
|
|
878
|
-
);
|
|
879
|
-
Log.debug('Protocol V2 profile (status refresh):', profile);
|
|
827
|
+
const features = this.updateProtocolV2Features(deviceInfo);
|
|
828
|
+
Log.debug('Protocol V2 features (status refresh):', features);
|
|
880
829
|
} catch (error) {
|
|
881
830
|
Log.error('Protocol V2 status refresh failed:', error);
|
|
882
831
|
throw error;
|
|
@@ -888,109 +837,67 @@ export class Device extends EventEmitter {
|
|
|
888
837
|
const deviceInfo = await requestProtocolV2DeviceInfo({
|
|
889
838
|
commands: this.commands,
|
|
890
839
|
});
|
|
891
|
-
|
|
892
|
-
buildProfileFromProtocolV2({
|
|
893
|
-
deviceInfo,
|
|
894
|
-
sources: ['deviceInfo'],
|
|
895
|
-
scope: 'basic',
|
|
896
|
-
fallbackSerialNo: this.originalDescriptor?.path,
|
|
897
|
-
}),
|
|
898
|
-
deviceInfo
|
|
899
|
-
);
|
|
900
|
-
return this.features ?? this.updateProtocolV2Features(profile, deviceInfo);
|
|
840
|
+
return this.updateProtocolV2Features(deviceInfo);
|
|
901
841
|
}
|
|
902
842
|
|
|
903
843
|
const { message } = await this.commands.typedCall('GetFeatures', 'Features', {});
|
|
904
844
|
this._updateFeatures(message);
|
|
905
|
-
return
|
|
845
|
+
return this.features;
|
|
906
846
|
}
|
|
907
847
|
|
|
908
|
-
_updateFeatures(
|
|
848
|
+
_updateFeatures(protoFeatures: PROTO.Features | Features, initSession?: boolean) {
|
|
849
|
+
const previousCacheDeviceKey = this.getSessionCacheDeviceKey();
|
|
850
|
+
let feat =
|
|
851
|
+
'protocol' in protoFeatures
|
|
852
|
+
? protoFeatures
|
|
853
|
+
: buildProtocolV1FeaturesPayload(protoFeatures, this.features);
|
|
854
|
+
|
|
909
855
|
// GetFeatures doesn't return 'session_id'
|
|
910
|
-
if (this.features &&
|
|
911
|
-
feat.
|
|
912
|
-
}
|
|
913
|
-
if (this.getCurrentDeviceId() && feat.session_id) {
|
|
914
|
-
this.setInternalState(feat.session_id, initSession);
|
|
856
|
+
if (this.features?.sessionId && !feat.sessionId) {
|
|
857
|
+
feat.sessionId = this.features.sessionId;
|
|
915
858
|
}
|
|
916
859
|
feat.unlocked = feat.unlocked ?? true;
|
|
917
860
|
|
|
918
861
|
feat = fixFeaturesFirmwareVersion(feat);
|
|
919
862
|
|
|
920
863
|
this.features = feat;
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
);
|
|
864
|
+
const nextCacheDeviceKey = this.getSessionCacheDeviceKey();
|
|
865
|
+
if (previousCacheDeviceKey && nextCacheDeviceKey) {
|
|
866
|
+
deviceWalletSessionStore.migrateDeviceKey(previousCacheDeviceKey, nextCacheDeviceKey);
|
|
867
|
+
}
|
|
868
|
+
if (feat.deviceId && feat.sessionId) {
|
|
869
|
+
this.setInternalState(feat.sessionId, initSession);
|
|
928
870
|
}
|
|
929
871
|
this.featuresNeedsReload = false;
|
|
930
872
|
this.emit(DEVICE.FEATURES, this, feat);
|
|
931
873
|
}
|
|
932
874
|
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
if (profile.raw?.features) {
|
|
943
|
-
this.features = fixFeaturesFirmwareVersion(profile.raw.features);
|
|
875
|
+
updateProtocolV2Features(deviceInfo?: ProtocolV2DeviceInfo) {
|
|
876
|
+
const previousCacheDeviceKey = this.getSessionCacheDeviceKey();
|
|
877
|
+
const features = fixFeaturesFirmwareVersion(
|
|
878
|
+
buildProtocolV2FeaturesPayload(deviceInfo, this.features)
|
|
879
|
+
);
|
|
880
|
+
this.features = features;
|
|
881
|
+
const nextCacheDeviceKey = this.getSessionCacheDeviceKey();
|
|
882
|
+
if (previousCacheDeviceKey && nextCacheDeviceKey) {
|
|
883
|
+
deviceWalletSessionStore.migrateDeviceKey(previousCacheDeviceKey, nextCacheDeviceKey);
|
|
944
884
|
}
|
|
885
|
+
this.featuresNeedsReload = false;
|
|
886
|
+
this.emit(DEVICE.FEATURES, this, features);
|
|
887
|
+
return features;
|
|
945
888
|
}
|
|
946
889
|
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
this.updateProfile({
|
|
957
|
-
...next,
|
|
958
|
-
raw: {
|
|
959
|
-
...next.raw,
|
|
960
|
-
...(deviceInfo ? { protocolV2DeviceInfo: deviceInfo } : {}),
|
|
961
|
-
},
|
|
962
|
-
});
|
|
963
|
-
return next;
|
|
964
|
-
}
|
|
965
|
-
|
|
966
|
-
const versions = { ...prev.versions };
|
|
967
|
-
for (const [key, value] of Object.entries(next.versions)) {
|
|
968
|
-
if (value != null) {
|
|
969
|
-
(versions as Record<string, string | null | undefined>)[key] = value;
|
|
970
|
-
}
|
|
971
|
-
}
|
|
972
|
-
|
|
973
|
-
const merged: DeviceProfile = {
|
|
974
|
-
...prev,
|
|
975
|
-
...next,
|
|
976
|
-
versions,
|
|
977
|
-
verify: next.verify ?? prev.verify,
|
|
978
|
-
raw: {
|
|
979
|
-
...prev.raw,
|
|
980
|
-
...next.raw,
|
|
981
|
-
...(deviceInfo ? { protocolV2DeviceInfo: deviceInfo } : {}),
|
|
890
|
+
updateProtocolV2Status(status: DeviceStatus) {
|
|
891
|
+
const previousDeviceInfo = this.features?.raw?.protocolV2DeviceInfo;
|
|
892
|
+
const previousStatus = previousDeviceInfo?.status;
|
|
893
|
+
return this.updateProtocolV2Features({
|
|
894
|
+
...(previousDeviceInfo ?? {}),
|
|
895
|
+
protocol_version: previousDeviceInfo?.protocol_version ?? this.features?.protocolVersion ?? 2,
|
|
896
|
+
status: {
|
|
897
|
+
...previousStatus,
|
|
898
|
+
...status,
|
|
982
899
|
},
|
|
983
|
-
};
|
|
984
|
-
this.updateProfile(merged);
|
|
985
|
-
return merged;
|
|
986
|
-
}
|
|
987
|
-
|
|
988
|
-
private updateProtocolV2Features(profile: DeviceProfile, deviceInfo?: ProtocolV2DeviceInfo) {
|
|
989
|
-
const features = fixFeaturesFirmwareVersion(
|
|
990
|
-
buildProtocolV2GetFeaturesPayload(profile, deviceInfo)
|
|
991
|
-
);
|
|
992
|
-
this._updateFeatures(features);
|
|
993
|
-
return features;
|
|
900
|
+
});
|
|
994
901
|
}
|
|
995
902
|
|
|
996
903
|
/**
|
|
@@ -1027,7 +934,6 @@ export class Device extends EventEmitter {
|
|
|
1027
934
|
if (device.features) {
|
|
1028
935
|
this._updateFeatures(device.features);
|
|
1029
936
|
}
|
|
1030
|
-
this.updateProfile(device.profile);
|
|
1031
937
|
}
|
|
1032
938
|
|
|
1033
939
|
async run(fn?: () => Promise<void>, options?: RunOptions) {
|
|
@@ -1160,17 +1066,7 @@ export class Device extends EventEmitter {
|
|
|
1160
1066
|
}
|
|
1161
1067
|
|
|
1162
1068
|
getMode() {
|
|
1163
|
-
if (this.
|
|
1164
|
-
if (this.profile.status.mode === 'bootloader') return EOneKeyDeviceMode.bootloader;
|
|
1165
|
-
if (this.profile.status.mode === 'notInitialized') return EOneKeyDeviceMode.notInitialized;
|
|
1166
|
-
if (this.profile.status.noBackup === true) return EOneKeyDeviceMode.backupMode;
|
|
1167
|
-
if (this.profile.status.mode === 'normal') return EOneKeyDeviceMode.normal;
|
|
1168
|
-
// mode 'unknown'(V2 设备未上报 init_states)保守按未初始化处理,
|
|
1169
|
-
// 与 isInitialized() 的 fail-closed 行为保持一致。
|
|
1170
|
-
if (this.isProtocolV2()) return EOneKeyDeviceMode.notInitialized;
|
|
1171
|
-
}
|
|
1172
|
-
|
|
1173
|
-
if (this.features?.bootloader_mode) {
|
|
1069
|
+
if (this.features?.bootloaderMode) {
|
|
1174
1070
|
// bootloader mode
|
|
1175
1071
|
return EOneKeyDeviceMode.bootloader;
|
|
1176
1072
|
}
|
|
@@ -1180,7 +1076,7 @@ export class Device extends EventEmitter {
|
|
|
1180
1076
|
return EOneKeyDeviceMode.notInitialized;
|
|
1181
1077
|
}
|
|
1182
1078
|
|
|
1183
|
-
if (this.features?.
|
|
1079
|
+
if (this.features?.noBackup) {
|
|
1184
1080
|
// backup mode
|
|
1185
1081
|
return EOneKeyDeviceMode.backupMode;
|
|
1186
1082
|
}
|
|
@@ -1190,17 +1086,11 @@ export class Device extends EventEmitter {
|
|
|
1190
1086
|
}
|
|
1191
1087
|
|
|
1192
1088
|
getFirmwareVersion() {
|
|
1193
|
-
const profileVersion = profileVersionToArray(this.profile?.versions.firmware);
|
|
1194
|
-
if (profileVersion) return profileVersion;
|
|
1195
|
-
if (this.isProtocolV2()) return null;
|
|
1196
1089
|
if (!this.features) return null;
|
|
1197
1090
|
return getDeviceFirmwareVersion(this.features);
|
|
1198
1091
|
}
|
|
1199
1092
|
|
|
1200
1093
|
getBLEFirmwareVersion() {
|
|
1201
|
-
const profileVersion = profileVersionToArray(this.profile?.versions.ble);
|
|
1202
|
-
if (profileVersion) return profileVersion;
|
|
1203
|
-
if (this.isProtocolV2()) return null;
|
|
1204
1094
|
if (!this.features) return null;
|
|
1205
1095
|
return getDeviceBLEFirmwareVersion(this.features);
|
|
1206
1096
|
}
|
|
@@ -1230,37 +1120,19 @@ export class Device extends EventEmitter {
|
|
|
1230
1120
|
}
|
|
1231
1121
|
|
|
1232
1122
|
isBootloader() {
|
|
1233
|
-
|
|
1234
|
-
return (
|
|
1235
|
-
this.profile.status.mode === 'bootloader' || this.profile.status.bootloaderMode === true
|
|
1236
|
-
);
|
|
1237
|
-
}
|
|
1238
|
-
return this.features && !!this.features.bootloader_mode;
|
|
1123
|
+
return this.features && !!this.features.bootloaderMode;
|
|
1239
1124
|
}
|
|
1240
1125
|
|
|
1241
1126
|
isInitialized() {
|
|
1242
|
-
if (this.profile) {
|
|
1243
|
-
if (this.profile.status.initialized != null) return this.profile.status.initialized;
|
|
1244
|
-
if (this.profile.status.mode === 'normal') return true;
|
|
1245
|
-
if (this.profile.status.mode === 'notInitialized') return false;
|
|
1246
|
-
// V2 设备未上报 init_states 时按未初始化处理(fail-closed):
|
|
1247
|
-
// 未知状态放行会让未初始化设备绕过 NOT_INITIALIZE 门禁。
|
|
1248
|
-
if (this.isProtocolV2()) return false;
|
|
1249
|
-
if (this.features) return !!this.features.initialized;
|
|
1250
|
-
return false;
|
|
1251
|
-
}
|
|
1252
1127
|
return this.features && !!this.features.initialized;
|
|
1253
1128
|
}
|
|
1254
1129
|
|
|
1255
1130
|
isSeedless() {
|
|
1256
|
-
|
|
1257
|
-
return this.profile.status.noBackup === true;
|
|
1258
|
-
}
|
|
1259
|
-
return this.features && !!this.features.no_backup;
|
|
1131
|
+
return this.features && !!this.features.noBackup;
|
|
1260
1132
|
}
|
|
1261
1133
|
|
|
1262
1134
|
isUnacquired(): boolean {
|
|
1263
|
-
return this.features === undefined
|
|
1135
|
+
return this.features === undefined;
|
|
1264
1136
|
}
|
|
1265
1137
|
|
|
1266
1138
|
hasUnexpectedMode(allow: string[], require: string[]) {
|
|
@@ -1291,7 +1163,7 @@ export class Device extends EventEmitter {
|
|
|
1291
1163
|
deviceType === EDeviceType.Touch ||
|
|
1292
1164
|
deviceType === EDeviceType.Pro ||
|
|
1293
1165
|
deviceType === EDeviceType.Pro2;
|
|
1294
|
-
const unlocked = this.
|
|
1166
|
+
const unlocked = this.features?.unlocked;
|
|
1295
1167
|
const preCheckTouch = isModeT && unlocked === false;
|
|
1296
1168
|
const passphraseProtection = this.getCurrentPassphraseProtection();
|
|
1297
1169
|
|
|
@@ -1308,8 +1180,7 @@ export class Device extends EventEmitter {
|
|
|
1308
1180
|
}
|
|
1309
1181
|
|
|
1310
1182
|
supportUnlockVersionRange(): DeviceFirmwareRange {
|
|
1311
|
-
// 仅适用于 Protocol V1 的 Pro 系列;Pro2
|
|
1312
|
-
// 且 Protocol V2 固件从首个版本即支持 UnLockDevice(见 unlockDevice 的 isProtocolV2 短路)。
|
|
1183
|
+
// 仅适用于 Protocol V1 的 Pro 系列;Pro2 走独立的 Protocol V2 解锁流程。
|
|
1313
1184
|
return {
|
|
1314
1185
|
pro: {
|
|
1315
1186
|
min: '4.15.0',
|
|
@@ -1318,8 +1189,24 @@ export class Device extends EventEmitter {
|
|
|
1318
1189
|
}
|
|
1319
1190
|
|
|
1320
1191
|
async unlockDevice() {
|
|
1192
|
+
if (this.isProtocolV2()) {
|
|
1193
|
+
try {
|
|
1194
|
+
await this.commands.typedCall('DeviceSessionAskPin', 'DeviceSessionPinResult');
|
|
1195
|
+
} catch (error) {
|
|
1196
|
+
const errorText =
|
|
1197
|
+
error instanceof Error
|
|
1198
|
+
? `${error.name} ${error.message}`
|
|
1199
|
+
: String((error as { message?: unknown } | null)?.message ?? error ?? '');
|
|
1200
|
+
if (errorText.includes('Failure_UnexpectedMessage')) {
|
|
1201
|
+
throw createDeviceNotSupportMethodError('deviceUnlock', this.getCurrentFirmwareType());
|
|
1202
|
+
}
|
|
1203
|
+
throw error;
|
|
1204
|
+
}
|
|
1205
|
+
|
|
1206
|
+
return refreshProtocolV2DeviceStatus(this);
|
|
1207
|
+
}
|
|
1208
|
+
|
|
1321
1209
|
const firmwareVersion = this.getCurrentFirmwareVersionString() ?? '0.0.0';
|
|
1322
|
-
// profile 优先的版本范围解析;features 仅作为 V1 capability 判断来源
|
|
1323
1210
|
const versionRange = this.getCurrentMethodVersionRange(
|
|
1324
1211
|
type => this.supportUnlockVersionRange()[type]
|
|
1325
1212
|
);
|
|
@@ -1328,9 +1215,7 @@ export class Device extends EventEmitter {
|
|
|
1328
1215
|
this.features,
|
|
1329
1216
|
Enum_Capability.Capability_AttachToPin
|
|
1330
1217
|
);
|
|
1331
|
-
// Pro2 (Protocol V2) 版本线独立于 Pro 系列,固件从首个版本即支持 UnLockDevice
|
|
1332
1218
|
const supportUnlock =
|
|
1333
|
-
this.isProtocolV2() ||
|
|
1334
1219
|
supportAttachPinCapability ||
|
|
1335
1220
|
(versionRange &&
|
|
1336
1221
|
semver.valid(firmwareVersion) &&
|
|
@@ -1338,24 +1223,11 @@ export class Device extends EventEmitter {
|
|
|
1338
1223
|
|
|
1339
1224
|
if (supportUnlock) {
|
|
1340
1225
|
const res = await this.commands.typedCall('UnLockDevice', 'UnLockDeviceResponse');
|
|
1341
|
-
// 解锁结果同步到 profile(标准模型),features 仅在 V1 缓存存在时回写
|
|
1342
|
-
if (this.profile) {
|
|
1343
|
-
this.updateProfile({
|
|
1344
|
-
...this.profile,
|
|
1345
|
-
status: {
|
|
1346
|
-
...this.profile.status,
|
|
1347
|
-
unlocked: res.message.unlocked == null ? null : res.message.unlocked,
|
|
1348
|
-
...(res.message.passphrase_protection != null
|
|
1349
|
-
? { passphraseProtection: res.message.passphrase_protection }
|
|
1350
|
-
: {}),
|
|
1351
|
-
},
|
|
1352
|
-
});
|
|
1353
|
-
}
|
|
1354
1226
|
if (this.features) {
|
|
1355
1227
|
this.features.unlocked = res.message.unlocked == null ? null : res.message.unlocked;
|
|
1356
|
-
this.features.
|
|
1228
|
+
this.features.unlockedAttachPin =
|
|
1357
1229
|
res.message.unlocked_attach_pin == null ? undefined : res.message.unlocked_attach_pin;
|
|
1358
|
-
this.features.
|
|
1230
|
+
this.features.passphraseProtection =
|
|
1359
1231
|
res.message.passphrase_protection == null ? null : res.message.passphrase_protection;
|
|
1360
1232
|
|
|
1361
1233
|
return Promise.resolve(this.features);
|
|
@@ -1365,14 +1237,6 @@ export class Device extends EventEmitter {
|
|
|
1365
1237
|
return Promise.resolve(features);
|
|
1366
1238
|
}
|
|
1367
1239
|
|
|
1368
|
-
// legacy 解锁探测仅适用于 Protocol V1 老固件;V2 固件必然支持 UnLockDevice
|
|
1369
|
-
if (this.isProtocolV2()) {
|
|
1370
|
-
throw ERRORS.TypedError(
|
|
1371
|
-
HardwareErrorCode.RuntimeError,
|
|
1372
|
-
'unlock device error: device firmware does not support UnLockDevice'
|
|
1373
|
-
);
|
|
1374
|
-
}
|
|
1375
|
-
|
|
1376
1240
|
const { type } = await this.commands.typedCall('GetAddress', 'Address', {
|
|
1377
1241
|
address_n: [toHardened(44), toHardened(1), toHardened(0), 0, 0],
|
|
1378
1242
|
coin_name: 'Testnet',
|