@onekeyfe/hd-core 1.2.0-alpha.2 → 1.2.0-alpha.4

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.
Files changed (121) hide show
  1. package/__tests__/preInitialize.test.ts +33 -0
  2. package/__tests__/protocol-v2.test.ts +1577 -624
  3. package/dist/api/FileRead.d.ts.map +1 -1
  4. package/dist/api/FileWrite.d.ts.map +1 -1
  5. package/dist/api/FirmwareUpdateV4.d.ts +20 -2
  6. package/dist/api/FirmwareUpdateV4.d.ts.map +1 -1
  7. package/dist/api/GetPassphraseState.d.ts +4 -4
  8. package/dist/api/GetPassphraseState.d.ts.map +1 -1
  9. package/dist/api/firmware/FirmwareUpdateBaseMethod.d.ts.map +1 -1
  10. package/dist/api/firmware/getBinary.d.ts +4 -0
  11. package/dist/api/firmware/getBinary.d.ts.map +1 -1
  12. package/dist/api/index.d.ts +5 -10
  13. package/dist/api/index.d.ts.map +1 -1
  14. package/dist/api/protocol-v2/DeviceFactoryInfoGet.d.ts +6 -0
  15. package/dist/api/protocol-v2/DeviceFactoryInfoGet.d.ts.map +1 -0
  16. package/dist/api/protocol-v2/DeviceFactoryInfoSet.d.ts +7 -0
  17. package/dist/api/protocol-v2/DeviceFactoryInfoSet.d.ts.map +1 -0
  18. package/dist/api/protocol-v2/DeviceFirmwareUpdate.d.ts +1 -1
  19. package/dist/api/protocol-v2/DeviceFirmwareUpdate.d.ts.map +1 -1
  20. package/dist/api/protocol-v2/DeviceGetFirmwareUpdateStatus.d.ts +1 -1
  21. package/dist/api/protocol-v2/{DeviceGetDeviceInfo.d.ts → DeviceInfoGet.d.ts} +10 -10
  22. package/dist/api/protocol-v2/DeviceInfoGet.d.ts.map +1 -0
  23. package/dist/api/protocol-v2/{FilesystemFixPermission.d.ts → FilesystemPermissionFix.d.ts} +2 -2
  24. package/dist/api/protocol-v2/FilesystemPermissionFix.d.ts.map +1 -0
  25. package/dist/api/protocol-v2/ProtocolInfoRequest.d.ts +6 -0
  26. package/dist/api/protocol-v2/ProtocolInfoRequest.d.ts.map +1 -0
  27. package/dist/api/protocol-v2/helpers.d.ts +24 -19
  28. package/dist/api/protocol-v2/helpers.d.ts.map +1 -1
  29. package/dist/api/ton/TonSignData.d.ts +1 -5
  30. package/dist/api/ton/TonSignData.d.ts.map +1 -1
  31. package/dist/constants/index.d.ts +2 -1
  32. package/dist/constants/index.d.ts.map +1 -1
  33. package/dist/core/index.d.ts.map +1 -1
  34. package/dist/data-manager/DataManager.d.ts +1 -1
  35. package/dist/data-manager/DataManager.d.ts.map +1 -1
  36. package/dist/device/Device.d.ts +5 -1
  37. package/dist/device/Device.d.ts.map +1 -1
  38. package/dist/deviceProfile/buildDeviceFeatures.d.ts.map +1 -1
  39. package/dist/deviceProfile/buildDeviceProfile.d.ts.map +1 -1
  40. package/dist/index.d.ts +85 -58
  41. package/dist/index.js +1672 -1640
  42. package/dist/inject.d.ts.map +1 -1
  43. package/dist/protocols/protocol-v2/features.d.ts +12 -14
  44. package/dist/protocols/protocol-v2/features.d.ts.map +1 -1
  45. package/dist/protocols/protocol-v2/firmware.d.ts +10 -9
  46. package/dist/protocols/protocol-v2/firmware.d.ts.map +1 -1
  47. package/dist/types/api/firmwareUpdate.d.ts +1 -6
  48. package/dist/types/api/firmwareUpdate.d.ts.map +1 -1
  49. package/dist/types/api/getDeviceInfo.d.ts +2 -0
  50. package/dist/types/api/getDeviceInfo.d.ts.map +1 -1
  51. package/dist/types/api/getPassphraseState.d.ts +4 -4
  52. package/dist/types/api/getPassphraseState.d.ts.map +1 -1
  53. package/dist/types/api/index.d.ts +6 -11
  54. package/dist/types/api/index.d.ts.map +1 -1
  55. package/dist/types/api/protocolV2.d.ts +12 -17
  56. package/dist/types/api/protocolV2.d.ts.map +1 -1
  57. package/dist/types/device.d.ts +1 -0
  58. package/dist/types/device.d.ts.map +1 -1
  59. package/dist/types/params.d.ts +1 -0
  60. package/dist/types/params.d.ts.map +1 -1
  61. package/dist/types/settings.d.ts +29 -1
  62. package/dist/types/settings.d.ts.map +1 -1
  63. package/dist/utils/deviceFeaturesUtils.d.ts +2 -0
  64. package/dist/utils/deviceFeaturesUtils.d.ts.map +1 -1
  65. package/dist/utils/patch.d.ts +1 -1
  66. package/dist/utils/patch.d.ts.map +1 -1
  67. package/package.json +4 -4
  68. package/src/api/FileRead.ts +14 -1
  69. package/src/api/FileWrite.ts +14 -1
  70. package/src/api/FirmwareUpdateV4.ts +933 -197
  71. package/src/api/GetOnekeyFeatures.ts +1 -1
  72. package/src/api/GetPassphraseState.ts +7 -4
  73. package/src/api/device/DeviceRebootToBoardloader.ts +4 -4
  74. package/src/api/device/DeviceRebootToBootloader.ts +4 -4
  75. package/src/api/firmware/FirmwareUpdateBaseMethod.ts +11 -4
  76. package/src/api/index.ts +5 -10
  77. package/src/api/protocol-v2/{FactoryGetDeviceInfo.ts → DeviceFactoryInfoGet.ts} +3 -3
  78. package/src/api/protocol-v2/DeviceFactoryInfoSet.ts +32 -0
  79. package/src/api/protocol-v2/DeviceFirmwareUpdate.ts +3 -5
  80. package/src/api/protocol-v2/DeviceGetFirmwareUpdateStatus.ts +2 -2
  81. package/src/api/protocol-v2/{DeviceGetDeviceInfo.ts → DeviceInfoGet.ts} +52 -22
  82. package/src/api/protocol-v2/DeviceReboot.ts +2 -2
  83. package/src/api/protocol-v2/{FilesystemFixPermission.ts → FilesystemPermissionFix.ts} +2 -2
  84. package/src/api/protocol-v2/{GetProtoVersion.ts → ProtocolInfoRequest.ts} +2 -2
  85. package/src/api/protocol-v2/helpers.ts +48 -57
  86. package/src/api/ton/TonSignData.ts +1 -5
  87. package/src/constants/index.ts +10 -1
  88. package/src/core/index.ts +19 -3
  89. package/src/data/messages/messages-protocol-v2.json +1224 -1804
  90. package/src/data-manager/DataManager.ts +7 -0
  91. package/src/device/Device.ts +34 -12
  92. package/src/device/DevicePool.ts +6 -6
  93. package/src/deviceProfile/buildDeviceFeatures.ts +61 -63
  94. package/src/deviceProfile/buildDeviceProfile.ts +78 -60
  95. package/src/inject.ts +10 -16
  96. package/src/protocols/protocol-v2/features.ts +26 -62
  97. package/src/protocols/protocol-v2/firmware.ts +11 -36
  98. package/src/types/api/firmwareUpdate.ts +10 -20
  99. package/src/types/api/getDeviceInfo.ts +2 -0
  100. package/src/types/api/getPassphraseState.ts +4 -4
  101. package/src/types/api/index.ts +10 -20
  102. package/src/types/api/protocolV2.ts +21 -42
  103. package/src/types/device.ts +1 -0
  104. package/src/types/params.ts +4 -0
  105. package/src/types/settings.ts +44 -30
  106. package/src/utils/deviceFeaturesUtils.ts +52 -11
  107. package/dist/api/protocol-v2/DevReboot.d.ts +0 -7
  108. package/dist/api/protocol-v2/DevReboot.d.ts.map +0 -1
  109. package/dist/api/protocol-v2/DeviceGetDeviceInfo.d.ts.map +0 -1
  110. package/dist/api/protocol-v2/DeviceGetOnboardingStatus.d.ts +0 -6
  111. package/dist/api/protocol-v2/DeviceGetOnboardingStatus.d.ts.map +0 -1
  112. package/dist/api/protocol-v2/FactoryDeviceInfoSettings.d.ts +0 -7
  113. package/dist/api/protocol-v2/FactoryDeviceInfoSettings.d.ts.map +0 -1
  114. package/dist/api/protocol-v2/FactoryGetDeviceInfo.d.ts +0 -6
  115. package/dist/api/protocol-v2/FactoryGetDeviceInfo.d.ts.map +0 -1
  116. package/dist/api/protocol-v2/FilesystemFixPermission.d.ts.map +0 -1
  117. package/dist/api/protocol-v2/GetProtoVersion.d.ts +0 -6
  118. package/dist/api/protocol-v2/GetProtoVersion.d.ts.map +0 -1
  119. package/src/api/protocol-v2/DevReboot.ts +0 -24
  120. package/src/api/protocol-v2/DeviceGetOnboardingStatus.ts +0 -16
  121. package/src/api/protocol-v2/FactoryDeviceInfoSettings.ts +0 -29
@@ -34,6 +34,7 @@ const Log = getLogger(LoggerNames.Core);
34
34
 
35
35
  export const FIRMWARE_FIELDS = [
36
36
  'firmware',
37
+ 'firmware-v1',
37
38
  'firmware-v2',
38
39
  'firmware-v8',
39
40
  'firmware-btc-v8',
@@ -46,6 +47,7 @@ export type ProtobufMessageSchema = ProtocolV1MessageSchema | 'v2Schema';
46
47
 
47
48
  const FIRMWARE_FIELD_TYPE_MAP: Readonly<Record<IFirmwareField, EFirmwareType>> = {
48
49
  firmware: EFirmwareType.Universal,
50
+ 'firmware-v1': EFirmwareType.Universal,
49
51
  'firmware-v2': EFirmwareType.Universal,
50
52
  'firmware-v8': EFirmwareType.Universal,
51
53
  'firmware-btc-v8': EFirmwareType.BitcoinOnly,
@@ -87,6 +89,10 @@ export default class DataManager {
87
89
  firmware: [],
88
90
  ble: [],
89
91
  },
92
+ [EDeviceType.Pro2]: {
93
+ firmware: [],
94
+ ble: [],
95
+ },
90
96
  [EDeviceType.ClassicPure]: {
91
97
  firmware: [],
92
98
  ble: [],
@@ -447,6 +453,7 @@ export default class DataManager {
447
453
  [EDeviceType.Mini]: this.enrichFirmwareReleaseInfo(data.mini),
448
454
  [EDeviceType.Touch]: this.enrichFirmwareReleaseInfo(data.touch),
449
455
  [EDeviceType.Pro]: this.enrichFirmwareReleaseInfo(data.pro),
456
+ [EDeviceType.Pro2]: this.enrichFirmwareReleaseInfo(data.pro2),
450
457
  };
451
458
  this.assets = {
452
459
  bridge: data.bridge,
@@ -76,6 +76,7 @@ export type InitOptions = {
76
76
  passphraseState?: string;
77
77
  deriveCardano?: boolean;
78
78
  connectProtocol?: HardwareConnectProtocol;
79
+ protocolV2DeviceInfoTimeoutMs?: number;
79
80
  };
80
81
 
81
82
  export type RunOptions = {
@@ -187,7 +188,7 @@ export class Device extends EventEmitter {
187
188
  /**
188
189
  * 唯一设备状态缓存。
189
190
  *
190
- * V1 直接保存原生 Features;V2 保存由 DevGetDeviceInfo 映射出的
191
+ * V1 直接保存原生 Features;V2 保存由 DeviceInfoGet 映射出的
191
192
  * Features 视图。Device 不再保存 profile,结构化 DeviceProfile 只作为
192
193
  * getDeviceInfo() 的 API 返回值存在。
193
194
  */
@@ -197,7 +198,7 @@ export class Device extends EventEmitter {
197
198
  * 是否需要更新设备信息。
198
199
  *
199
200
  * 历史名称保留用于兼容现有调用语义;对 V2 表示 features 需要由
200
- * DevGetDeviceInfo 刷新。
201
+ * DeviceInfoGet 刷新。
201
202
  */
202
203
  featuresNeedsReload = false;
203
204
 
@@ -261,13 +262,14 @@ export class Device extends EventEmitter {
261
262
  const bleName = this.getCurrentBleName();
262
263
  const label = this.getCurrentLabel();
263
264
  const serialNo = this.getCurrentSerialNo();
265
+ const connectId = this.getConnectId();
264
266
  const deviceId = this.getCurrentDeviceId() || null;
265
267
 
266
268
  const features = this.features;
267
269
 
268
270
  return {
269
271
  /** Android uses Mac address, iOS uses uuid, USB uses uuid */
270
- connectId: DataManager.isBleConnect(env) ? this.mainId || null : serialNo,
272
+ connectId: DataManager.isBleConnect(env) ? this.mainId || null : connectId,
271
273
  /** Hardware ID, will not change at any time */
272
274
  uuid: serialNo,
273
275
  commType: this.originalDescriptor.commType,
@@ -325,7 +327,10 @@ export class Device extends EventEmitter {
325
327
  });
326
328
  }
327
329
 
328
- async acquire(connectProtocol?: HardwareConnectProtocol) {
330
+ async acquire(
331
+ connectProtocol?: HardwareConnectProtocol,
332
+ options?: { throwOnRunPromiseError?: boolean }
333
+ ) {
329
334
  const env = DataManager.getSettings('env');
330
335
  const mainIdKey = DataManager.isBleConnect(env) ? 'id' : 'session';
331
336
  const expectedProtocol = connectProtocol ?? this.originalDescriptor.protocolType;
@@ -374,6 +379,9 @@ export class Device extends EventEmitter {
374
379
 
375
380
  this.commands = new DeviceCommands(this, this.mainId ?? '');
376
381
  } catch (error) {
382
+ if (options?.throwOnRunPromiseError) {
383
+ throw error;
384
+ }
377
385
  if (this.runPromise) {
378
386
  this.runPromise.reject(error);
379
387
  } else {
@@ -476,7 +484,7 @@ export class Device extends EventEmitter {
476
484
  /**
477
485
  * 唯一协议判别器。
478
486
  *
479
- * descriptor.protocolType 是协议探测后的结果;V2 features 由 DevGetDeviceInfo
487
+ * descriptor.protocolType 是协议探测后的结果;V2 features 由 DeviceInfoGet
480
488
  * 映射产生。
481
489
  * 全 SDK 的协议分支都必须走这里,不要直接读 originalDescriptor.protocolType
482
490
  * 或从 features 反推。
@@ -501,6 +509,15 @@ export class Device extends EventEmitter {
501
509
  return this.features ? getDeviceUUID(this.features) : '';
502
510
  }
503
511
 
512
+ getConnectId() {
513
+ const serialNo = this.getCurrentSerialNo();
514
+ if (serialNo) return serialNo;
515
+
516
+ // connectId 是 SDK 内部连接路由 key。这里兜底到 transport descriptor,
517
+ // 不改变 features.serialNo / deviceId 的业务语义。
518
+ return this.originalDescriptor.path || this.originalDescriptor.id || '';
519
+ }
520
+
504
521
  getCurrentBleName() {
505
522
  return getDeviceBleName(this.features);
506
523
  }
@@ -730,13 +747,16 @@ export class Device extends EventEmitter {
730
747
  if (this.isProtocolV2()) {
731
748
  this.passphraseState = options?.passphraseState;
732
749
  if (this.features && !this.featuresNeedsReload && !options?.initSession) {
750
+ if (this.features.bootloaderMode) {
751
+ return;
752
+ }
733
753
  // 不能直接信任缓存 features:设备端 wipe / 完成初始化 / 改 label 后
734
754
  // features 会永久陈旧。每次 run 做一次轻量 status 刷新(不含 fw/SE),
735
755
  // 用字段级合并保留已有版本和 SE 信息。
736
- await this._refreshProtocolV2Status();
756
+ await this._refreshProtocolV2Status(options);
737
757
  return;
738
758
  }
739
- await this._initializeProtocolV2();
759
+ await this._initializeProtocolV2(options);
740
760
  return;
741
761
  }
742
762
 
@@ -786,10 +806,10 @@ export class Device extends EventEmitter {
786
806
  /**
787
807
  * Device initialization over Protocol V2.
788
808
  *
789
- * Protocol V2 不走传统 Initialize/GetFeatures;直接用 DevGetDeviceInfo
809
+ * Protocol V2 不走传统 Initialize/GetFeatures;直接用 DeviceInfoGet
790
810
  * 生成唯一的 features 状态。
791
811
  */
792
- private async _initializeProtocolV2() {
812
+ private async _initializeProtocolV2(options?: InitOptions) {
793
813
  Log.debug('Initialize device via Protocol V2 features adapter');
794
814
 
795
815
  try {
@@ -798,6 +818,7 @@ export class Device extends EventEmitter {
798
818
  // 且 reject 后底层调用仍会残留。
799
819
  const deviceInfo = await requestProtocolV2DeviceInfo({
800
820
  commands: this.commands,
821
+ timeoutMs: options?.protocolV2DeviceInfoTimeoutMs,
801
822
  });
802
823
  // 默认请求不含 SE/hash 数据,scope 如实标注为 basic;
803
824
  // 完整数据由 getDeviceInfo(scope:'verify'|'full') 获取。
@@ -813,15 +834,16 @@ export class Device extends EventEmitter {
813
834
  /**
814
835
  * Protocol V2 的轻量状态刷新(每次 run 前调用)。
815
836
  *
816
- * 请求 hw + bt + status(不含 fw/SE target):status 提供 init_states / label /
817
- * passphrase_protection 等会在设备端变化的字段;hw/bt 提供 serialNo / bleName。
837
+ * 请求 hw + coprocessor + status(不含 fw/SE target):status 提供 init_states / label /
838
+ * passphrase_enabled 等会在设备端变化的字段;hw/coprocessor 提供 serialNo / bleName。
818
839
  * versions 为空时按字段级合并保留旧值,verify 数据不会被降级。
819
840
  */
820
- private async _refreshProtocolV2Status() {
841
+ private async _refreshProtocolV2Status(options?: InitOptions) {
821
842
  try {
822
843
  const deviceInfo = await requestProtocolV2DeviceInfo({
823
844
  commands: this.commands,
824
845
  request: PROTOCOL_V2_STATUS_DEVICE_INFO_REQUEST,
846
+ timeoutMs: options?.protocolV2DeviceInfoTimeoutMs,
825
847
  });
826
848
  const features = this.updateProtocolV2Features(deviceInfo);
827
849
  Log.debug('Protocol V2 features (status refresh):', features);
@@ -118,14 +118,14 @@ export class DevicePool extends EventEmitter {
118
118
  for await (const descriptor of descriptorList) {
119
119
  const device = await this._createDevice(descriptor, initOptions);
120
120
 
121
- const uuid = device.getCurrentSerialNo();
122
- if (uuid) {
123
- if (this.devicesCache[uuid]) {
124
- const cache = this.devicesCache[uuid];
121
+ const connectId = device.getConnectId();
122
+ if (connectId) {
123
+ if (this.devicesCache[connectId]) {
124
+ const cache = this.devicesCache[connectId];
125
125
  cache.updateDescriptor(descriptor, true);
126
126
  }
127
- this.devicesCache[uuid] = device;
128
- devices[uuid] = device;
127
+ this.devicesCache[connectId] = device;
128
+ devices[connectId] = device;
129
129
  }
130
130
 
131
131
  deviceList.push(device);
@@ -2,22 +2,8 @@ import { EDeviceType, EFirmwareType } from '@onekeyfe/hd-shared';
2
2
 
3
3
  import type { Features } from '../types';
4
4
  import type { PROTO } from '../constants';
5
- import type { DevFirmwareImageInfo, ProtocolV2DeviceInfo } from '@onekeyfe/hd-transport';
6
-
7
- type ProtocolV2DeviceInfoCompat = ProtocolV2DeviceInfo & {
8
- fw?: ProtocolV2DeviceInfo['fw'] & {
9
- application?: DevFirmwareImageInfo | null;
10
- application_data?: DevFirmwareImageInfo | null;
11
- bootloader?: DevFirmwareImageInfo | null;
12
- romloader?: DevFirmwareImageInfo | null;
13
- };
14
- coprocessor?: {
15
- application?: DevFirmwareImageInfo | null;
16
- bootloader?: DevFirmwareImageInfo | null;
17
- bt_adv_name?: string | null;
18
- bt_mac?: unknown;
19
- } | null;
20
- };
5
+ import type { DeviceFirmwareImageInfo, ProtocolV2DeviceInfo } from '@onekeyfe/hd-transport';
6
+ import { isProtocolV2BootloaderDeviceInfo } from '../protocols/protocol-v2/features';
21
7
 
22
8
  type ProtocolV1FeaturesCompat = PROTO.Features &
23
9
  Partial<PROTO.OnekeyFeatures> & {
@@ -26,7 +12,7 @@ type ProtocolV1FeaturesCompat = PROTO.Features &
26
12
  onekey_serial?: string;
27
13
  };
28
14
 
29
- const getImageVersion = (image?: DevFirmwareImageInfo | null) => image?.version ?? null;
15
+ const getImageVersion = (image?: DeviceFirmwareImageInfo | null) => image?.version ?? null;
30
16
 
31
17
  const bytesToHex = (value: unknown): string | undefined => {
32
18
  if (!value) return undefined;
@@ -42,9 +28,9 @@ const bytesToHex = (value: unknown): string | undefined => {
42
28
  return undefined;
43
29
  };
44
30
 
45
- const getImageBuildId = (image?: DevFirmwareImageInfo | null) => image?.build_id ?? undefined;
31
+ const getImageBuildId = (image?: DeviceFirmwareImageInfo | null) => image?.build_id ?? undefined;
46
32
 
47
- const getImageHash = (image?: DevFirmwareImageInfo | null) => bytesToHex(image?.hash);
33
+ const getImageHash = (image?: DeviceFirmwareImageInfo | null) => bytesToHex(image?.hash);
48
34
 
49
35
  const firstValue = <T>(...values: Array<T | null | undefined>) =>
50
36
  values.find(value => value !== undefined && value !== null);
@@ -226,7 +212,7 @@ export const buildProtocolV1FeaturesPayload = (
226
212
  /**
227
213
  * Protocol V2 的结构化 `Features` 构建器。
228
214
  *
229
- * 这是 Device 内部唯一缓存状态。字段只来自 DevGetDeviceInfo 或前一次 features
215
+ * 这是 Device 内部唯一缓存状态。字段只来自 DeviceInfoGet 或前一次 features
230
216
  * 缓存的同名字段级合并;不存在协议等价语义的字段保持 null/空值,不再通过
231
217
  * DeviceProfile 或 transport path 做身份兜底。
232
218
  */
@@ -234,11 +220,12 @@ export const buildProtocolV2FeaturesPayload = (
234
220
  deviceInfo?: ProtocolV2DeviceInfo,
235
221
  previous?: Features
236
222
  ): Features => {
237
- const info = deviceInfo as ProtocolV2DeviceInfoCompat | undefined;
238
- const fwApplication = firstValue(info?.fw?.application, info?.fw?.app);
239
- const fwBootloader = firstValue(info?.fw?.bootloader, info?.fw?.boot);
240
- const fwBoard = firstValue(info?.fw?.application_data, info?.fw?.board);
241
- const bleApplication = firstValue(info?.coprocessor?.application, info?.bt?.app);
223
+ const info = deviceInfo;
224
+ const fwApplication = info?.fw?.application;
225
+ const fwBootloader = info?.fw?.bootloader;
226
+ const fwBoard = firstValue(info?.fw?.application_data, info?.fw?.romloader);
227
+ const bleApplication = info?.coprocessor?.application;
228
+ const status = info?.status;
242
229
 
243
230
  const firmwareVersion = firstMeaningfulVersion(
244
231
  getImageVersion(fwApplication),
@@ -250,16 +237,26 @@ export const buildProtocolV2FeaturesPayload = (
250
237
  );
251
238
  const boardVersion = firstMeaningfulVersion(getImageVersion(fwBoard), previous?.boardVersion);
252
239
  const bleVersion = firstMeaningfulVersion(getImageVersion(bleApplication), previous?.bleVersion);
240
+ const deviceId = status?.device_id ?? null;
253
241
  const serialNo = firstValue(info?.hw?.serial_no, previous?.serialNo) ?? '';
254
- const label = firstValue(deviceInfo?.status?.label, previous?.label) ?? null;
255
- const bleName = firstValue(info?.coprocessor?.bt_adv_name, info?.bt?.adv_name, previous?.bleName);
256
- const initialized = firstValue(deviceInfo?.status?.init_states, previous?.initialized) ?? null;
257
- const passphraseProtection =
258
- firstValue(deviceInfo?.status?.passphrase_protection, previous?.passphraseProtection) ?? null;
259
- const language = firstValue(deviceInfo?.status?.language, previous?.language) ?? null;
260
- const backupRequired =
261
- firstValue(deviceInfo?.status?.backup_required, previous?.backupRequired) ?? null;
262
- const bleEnabled = firstValue(deviceInfo?.status?.bt_enable, previous?.bleEnabled);
242
+ const label = previous?.label ?? null;
243
+ const bleName = firstValue(info?.coprocessor?.bt_adv_name, previous?.bleName);
244
+ const initialized = firstValue(status?.init_states, previous?.initialized) ?? null;
245
+ const passphraseProtection = status?.passphrase_enabled ?? null;
246
+ const language = previous?.language ?? null;
247
+ const backupRequired = firstValue(status?.backup_required, previous?.backupRequired) ?? null;
248
+ const bleEnabled = previous?.bleEnabled;
249
+ const unlocked = firstValue(status?.unlocked, previous?.unlocked) ?? null;
250
+ const attachToPinEnabled = status?.attach_to_pin_enabled ?? null;
251
+ const unlockedAttachPin = status?.unlocked_by_attach_to_pin ?? undefined;
252
+ const bootloaderMode = isProtocolV2BootloaderDeviceInfo(info);
253
+ const mode = bootloaderMode
254
+ ? 'bootloader'
255
+ : initialized === false
256
+ ? 'notInitialized'
257
+ : initialized === true
258
+ ? 'normal'
259
+ : 'unknown';
263
260
 
264
261
  return {
265
262
  protocol: 'V2',
@@ -268,15 +265,15 @@ export const buildProtocolV2FeaturesPayload = (
268
265
  firmwareType: previous?.firmwareType ?? EFirmwareType.Universal,
269
266
  model: 'pro2',
270
267
  vendor: 'onekey.so',
271
- deviceId: null,
268
+ deviceId,
272
269
  serialNo,
273
270
  label,
274
271
  bleName: bleName ?? null,
275
272
  capabilities: [],
276
- mode: initialized === false ? 'notInitialized' : initialized === true ? 'normal' : 'unknown',
273
+ mode,
277
274
  initialized,
278
- bootloaderMode: false,
279
- unlocked: previous?.unlocked ?? null,
275
+ bootloaderMode,
276
+ unlocked,
280
277
  firmwarePresent: previous?.firmwarePresent ?? null,
281
278
  passphraseProtection,
282
279
  pinProtection: null,
@@ -290,6 +287,7 @@ export const buildProtocolV2FeaturesPayload = (
290
287
  sdProtection: null,
291
288
  wipeCodeProtection: null,
292
289
  passphraseAlwaysOnDevice: null,
290
+ attachToPinEnabled,
293
291
  safetyChecks: null,
294
292
  autoLockDelayMs: null,
295
293
  displayRotation: null,
@@ -299,35 +297,35 @@ export const buildProtocolV2FeaturesPayload = (
299
297
  boardVersion,
300
298
  bleVersion,
301
299
  se01Version: firstMeaningfulVersion(
302
- getImageVersion(deviceInfo?.se1?.app),
300
+ getImageVersion(info?.se1?.application),
303
301
  previous?.se01Version
304
302
  ),
305
303
  se02Version: firstMeaningfulVersion(
306
- getImageVersion(deviceInfo?.se2?.app),
304
+ getImageVersion(info?.se2?.application),
307
305
  previous?.se02Version
308
306
  ),
309
307
  se03Version: firstMeaningfulVersion(
310
- getImageVersion(deviceInfo?.se3?.app),
308
+ getImageVersion(info?.se3?.application),
311
309
  previous?.se03Version
312
310
  ),
313
311
  se04Version: firstMeaningfulVersion(
314
- getImageVersion(deviceInfo?.se4?.app),
312
+ getImageVersion(info?.se4?.application),
315
313
  previous?.se04Version
316
314
  ),
317
315
  se01BootVersion: firstMeaningfulVersion(
318
- getImageVersion(deviceInfo?.se1?.boot),
316
+ getImageVersion(info?.se1?.bootloader),
319
317
  previous?.se01BootVersion
320
318
  ),
321
319
  se02BootVersion: firstMeaningfulVersion(
322
- getImageVersion(deviceInfo?.se2?.boot),
320
+ getImageVersion(info?.se2?.bootloader),
323
321
  previous?.se02BootVersion
324
322
  ),
325
323
  se03BootVersion: firstMeaningfulVersion(
326
- getImageVersion(deviceInfo?.se3?.boot),
324
+ getImageVersion(info?.se3?.bootloader),
327
325
  previous?.se03BootVersion
328
326
  ),
329
327
  se04BootVersion: firstMeaningfulVersion(
330
- getImageVersion(deviceInfo?.se4?.boot),
328
+ getImageVersion(info?.se4?.bootloader),
331
329
  previous?.se04BootVersion
332
330
  ),
333
331
  seVersion: previous?.seVersion ?? null,
@@ -340,26 +338,26 @@ export const buildProtocolV2FeaturesPayload = (
340
338
  boardHash: getImageHash(fwBoard) ?? previous?.verify?.boardHash,
341
339
  bleBuildId: getImageBuildId(bleApplication) ?? previous?.verify?.bleBuildId,
342
340
  bleHash: getImageHash(bleApplication) ?? previous?.verify?.bleHash,
343
- se01BuildId: getImageBuildId(deviceInfo?.se1?.app) ?? previous?.verify?.se01BuildId,
344
- se01Hash: getImageHash(deviceInfo?.se1?.app) ?? previous?.verify?.se01Hash,
345
- se02BuildId: getImageBuildId(deviceInfo?.se2?.app) ?? previous?.verify?.se02BuildId,
346
- se02Hash: getImageHash(deviceInfo?.se2?.app) ?? previous?.verify?.se02Hash,
347
- se03BuildId: getImageBuildId(deviceInfo?.se3?.app) ?? previous?.verify?.se03BuildId,
348
- se03Hash: getImageHash(deviceInfo?.se3?.app) ?? previous?.verify?.se03Hash,
349
- se04BuildId: getImageBuildId(deviceInfo?.se4?.app) ?? previous?.verify?.se04BuildId,
350
- se04Hash: getImageHash(deviceInfo?.se4?.app) ?? previous?.verify?.se04Hash,
351
- se01BootBuildId: getImageBuildId(deviceInfo?.se1?.boot) ?? previous?.verify?.se01BootBuildId,
352
- se01BootHash: getImageHash(deviceInfo?.se1?.boot) ?? previous?.verify?.se01BootHash,
353
- se02BootBuildId: getImageBuildId(deviceInfo?.se2?.boot) ?? previous?.verify?.se02BootBuildId,
354
- se02BootHash: getImageHash(deviceInfo?.se2?.boot) ?? previous?.verify?.se02BootHash,
355
- se03BootBuildId: getImageBuildId(deviceInfo?.se3?.boot) ?? previous?.verify?.se03BootBuildId,
356
- se03BootHash: getImageHash(deviceInfo?.se3?.boot) ?? previous?.verify?.se03BootHash,
357
- se04BootBuildId: getImageBuildId(deviceInfo?.se4?.boot) ?? previous?.verify?.se04BootBuildId,
358
- se04BootHash: getImageHash(deviceInfo?.se4?.boot) ?? previous?.verify?.se04BootHash,
341
+ se01BuildId: getImageBuildId(info?.se1?.application) ?? previous?.verify?.se01BuildId,
342
+ se01Hash: getImageHash(info?.se1?.application) ?? previous?.verify?.se01Hash,
343
+ se02BuildId: getImageBuildId(info?.se2?.application) ?? previous?.verify?.se02BuildId,
344
+ se02Hash: getImageHash(info?.se2?.application) ?? previous?.verify?.se02Hash,
345
+ se03BuildId: getImageBuildId(info?.se3?.application) ?? previous?.verify?.se03BuildId,
346
+ se03Hash: getImageHash(info?.se3?.application) ?? previous?.verify?.se03Hash,
347
+ se04BuildId: getImageBuildId(info?.se4?.application) ?? previous?.verify?.se04BuildId,
348
+ se04Hash: getImageHash(info?.se4?.application) ?? previous?.verify?.se04Hash,
349
+ se01BootBuildId: getImageBuildId(info?.se1?.bootloader) ?? previous?.verify?.se01BootBuildId,
350
+ se01BootHash: getImageHash(info?.se1?.bootloader) ?? previous?.verify?.se01BootHash,
351
+ se02BootBuildId: getImageBuildId(info?.se2?.bootloader) ?? previous?.verify?.se02BootBuildId,
352
+ se02BootHash: getImageHash(info?.se2?.bootloader) ?? previous?.verify?.se02BootHash,
353
+ se03BootBuildId: getImageBuildId(info?.se3?.bootloader) ?? previous?.verify?.se03BootBuildId,
354
+ se03BootHash: getImageHash(info?.se3?.bootloader) ?? previous?.verify?.se03BootHash,
355
+ se04BootBuildId: getImageBuildId(info?.se4?.bootloader) ?? previous?.verify?.se04BootBuildId,
356
+ se04BootHash: getImageHash(info?.se4?.bootloader) ?? previous?.verify?.se04BootHash,
359
357
  },
360
358
  sessionId: previous?.sessionId ?? null,
361
359
  passphraseState: previous?.passphraseState,
362
- unlockedAttachPin: previous?.unlockedAttachPin,
360
+ unlockedAttachPin,
363
361
  raw: {
364
362
  protocolV2DeviceInfo: deviceInfo,
365
363
  },
@@ -25,7 +25,8 @@ import type {
25
25
  GetDeviceInfoParams,
26
26
  } from '../types/api/getDeviceInfo';
27
27
  import type { Features, OnekeyFeatures } from '../types';
28
- import type { DevFirmwareImageInfo, ProtocolV2DeviceInfo } from '@onekeyfe/hd-transport';
28
+ import type { DeviceFirmwareImageInfo, ProtocolV2DeviceInfo } from '@onekeyfe/hd-transport';
29
+ import { isProtocolV2BootloaderDeviceInfo } from '../protocols/protocol-v2/features';
29
30
 
30
31
  type BuildProtocolV1ProfileParams = {
31
32
  protocol?: DeviceInfoProtocol;
@@ -68,11 +69,11 @@ const bytesToHex = (value: unknown): string | undefined => {
68
69
  return undefined;
69
70
  };
70
71
 
71
- const getImageVersion = (image?: DevFirmwareImageInfo | null) => image?.version ?? null;
72
+ const getImageVersion = (image?: DeviceFirmwareImageInfo | null) => image?.version ?? null;
72
73
 
73
- const getImageBuildId = (image?: DevFirmwareImageInfo | null) => image?.build_id ?? undefined;
74
+ const getImageBuildId = (image?: DeviceFirmwareImageInfo | null) => image?.build_id ?? undefined;
74
75
 
75
- const getImageHash = (image?: DevFirmwareImageInfo | null) => bytesToHex(image?.hash);
76
+ const getImageHash = (image?: DeviceFirmwareImageInfo | null) => bytesToHex(image?.hash);
76
77
 
77
78
  const shouldIncludeVerify = (scope?: GetDeviceInfoParams['scope']) =>
78
79
  scope === 'verify' || scope === 'full';
@@ -86,6 +87,7 @@ const getDeviceMode = (features?: Features): DeviceInfoStatus['mode'] => {
86
87
  };
87
88
 
88
89
  const getProtocolV2Mode = (deviceInfo?: ProtocolV2DeviceInfo): DeviceInfoStatus['mode'] => {
90
+ if (isProtocolV2BootloaderDeviceInfo(deviceInfo)) return 'bootloader';
89
91
  const initialized = deviceInfo?.status?.init_states;
90
92
  if (initialized === false) return 'notInitialized';
91
93
  if (initialized === true) return 'normal';
@@ -147,20 +149,25 @@ const normalizeV1Versions = (
147
149
  ),
148
150
  });
149
151
 
150
- const normalizeV2Versions = (deviceInfo?: ProtocolV2DeviceInfo): DeviceProfileVersions => ({
151
- firmware: firstMeaningfulVersion(getImageVersion(deviceInfo?.fw?.app)),
152
- bootloader: firstMeaningfulVersion(getImageVersion(deviceInfo?.fw?.boot)),
153
- board: firstMeaningfulVersion(getImageVersion(deviceInfo?.fw?.board)),
154
- ble: firstMeaningfulVersion(getImageVersion(deviceInfo?.bt?.app)),
155
- se01: firstMeaningfulVersion(getImageVersion(deviceInfo?.se1?.app)),
156
- se02: firstMeaningfulVersion(getImageVersion(deviceInfo?.se2?.app)),
157
- se03: firstMeaningfulVersion(getImageVersion(deviceInfo?.se3?.app)),
158
- se04: firstMeaningfulVersion(getImageVersion(deviceInfo?.se4?.app)),
159
- se01Boot: firstMeaningfulVersion(getImageVersion(deviceInfo?.se1?.boot)),
160
- se02Boot: firstMeaningfulVersion(getImageVersion(deviceInfo?.se2?.boot)),
161
- se03Boot: firstMeaningfulVersion(getImageVersion(deviceInfo?.se3?.boot)),
162
- se04Boot: firstMeaningfulVersion(getImageVersion(deviceInfo?.se4?.boot)),
163
- });
152
+ const normalizeV2Versions = (deviceInfo?: ProtocolV2DeviceInfo): DeviceProfileVersions => {
153
+ const info = deviceInfo;
154
+ return {
155
+ firmware: firstMeaningfulVersion(getImageVersion(info?.fw?.application)),
156
+ bootloader: firstMeaningfulVersion(getImageVersion(info?.fw?.bootloader)),
157
+ board: firstMeaningfulVersion(
158
+ getImageVersion(info?.fw?.application_data ?? info?.fw?.romloader)
159
+ ),
160
+ ble: firstMeaningfulVersion(getImageVersion(info?.coprocessor?.application)),
161
+ se01: firstMeaningfulVersion(getImageVersion(info?.se1?.application)),
162
+ se02: firstMeaningfulVersion(getImageVersion(info?.se2?.application)),
163
+ se03: firstMeaningfulVersion(getImageVersion(info?.se3?.application)),
164
+ se04: firstMeaningfulVersion(getImageVersion(info?.se4?.application)),
165
+ se01Boot: firstMeaningfulVersion(getImageVersion(info?.se1?.bootloader)),
166
+ se02Boot: firstMeaningfulVersion(getImageVersion(info?.se2?.bootloader)),
167
+ se03Boot: firstMeaningfulVersion(getImageVersion(info?.se3?.bootloader)),
168
+ se04Boot: firstMeaningfulVersion(getImageVersion(info?.se4?.bootloader)),
169
+ };
170
+ };
164
171
 
165
172
  // V2 状态由 normalizeV2Status 处理,这里只服务 buildProfileFromProtocolV1 的 V1 路径。
166
173
  const normalizeV1Status = (features?: Features): DeviceInfoStatus => ({
@@ -169,23 +176,31 @@ const normalizeV1Status = (features?: Features): DeviceInfoStatus => ({
169
176
  bootloaderMode: features?.bootloaderMode ?? null,
170
177
  unlocked: features?.unlocked ?? null,
171
178
  passphraseProtection: features?.passphraseProtection ?? null,
179
+ attachToPinEnabled: features?.attachToPinEnabled ?? null,
180
+ unlockedAttachPin: features?.unlockedAttachPin ?? null,
172
181
  backupRequired: features?.backupRequired ?? null,
173
182
  noBackup: features?.noBackup ?? null,
174
183
  language: features?.language ?? null,
175
184
  bleEnabled: features?.bleEnabled ?? null,
176
185
  });
177
186
 
178
- const normalizeV2Status = (deviceInfo?: ProtocolV2DeviceInfo): DeviceInfoStatus => ({
179
- mode: getProtocolV2Mode(deviceInfo),
180
- initialized: deviceInfo?.status?.init_states ?? null,
181
- bootloaderMode: false,
182
- unlocked: null,
183
- passphraseProtection: deviceInfo?.status?.passphrase_protection ?? null,
184
- backupRequired: deviceInfo?.status?.backup_required ?? null,
185
- noBackup: null,
186
- language: deviceInfo?.status?.language ?? null,
187
- bleEnabled: deviceInfo?.status?.bt_enable ?? null,
188
- });
187
+ const normalizeV2Status = (deviceInfo?: ProtocolV2DeviceInfo): DeviceInfoStatus => {
188
+ const status = deviceInfo?.status;
189
+ const bootloaderMode = isProtocolV2BootloaderDeviceInfo(deviceInfo);
190
+ return {
191
+ mode: getProtocolV2Mode(deviceInfo),
192
+ initialized: status?.init_states ?? null,
193
+ bootloaderMode,
194
+ unlocked: status?.unlocked ?? null,
195
+ passphraseProtection: status?.passphrase_enabled ?? null,
196
+ attachToPinEnabled: status?.attach_to_pin_enabled ?? null,
197
+ unlockedAttachPin: status?.unlocked_by_attach_to_pin ?? null,
198
+ backupRequired: status?.backup_required ?? null,
199
+ noBackup: null,
200
+ language: null,
201
+ bleEnabled: null,
202
+ };
203
+ };
189
204
 
190
205
  const normalizeV1Verify = (
191
206
  features?: Features,
@@ -223,32 +238,35 @@ const normalizeV1Verify = (
223
238
  se04BootHash: protocolV1OneKeyFeatures?.onekey_se04_boot_hash ?? features?.verify?.se04BootHash,
224
239
  });
225
240
 
226
- const normalizeV2Verify = (deviceInfo?: ProtocolV2DeviceInfo): DeviceProfileVerify => ({
227
- firmwareBuildId: getImageBuildId(deviceInfo?.fw?.app),
228
- firmwareHash: getImageHash(deviceInfo?.fw?.app),
229
- bootloaderBuildId: getImageBuildId(deviceInfo?.fw?.boot),
230
- bootloaderHash: getImageHash(deviceInfo?.fw?.boot),
231
- boardBuildId: getImageBuildId(deviceInfo?.fw?.board),
232
- boardHash: getImageHash(deviceInfo?.fw?.board),
233
- bleBuildId: getImageBuildId(deviceInfo?.bt?.app),
234
- bleHash: getImageHash(deviceInfo?.bt?.app),
235
- se01BuildId: getImageBuildId(deviceInfo?.se1?.app),
236
- se01Hash: getImageHash(deviceInfo?.se1?.app),
237
- se02BuildId: getImageBuildId(deviceInfo?.se2?.app),
238
- se02Hash: getImageHash(deviceInfo?.se2?.app),
239
- se03BuildId: getImageBuildId(deviceInfo?.se3?.app),
240
- se03Hash: getImageHash(deviceInfo?.se3?.app),
241
- se04BuildId: getImageBuildId(deviceInfo?.se4?.app),
242
- se04Hash: getImageHash(deviceInfo?.se4?.app),
243
- se01BootBuildId: getImageBuildId(deviceInfo?.se1?.boot),
244
- se01BootHash: getImageHash(deviceInfo?.se1?.boot),
245
- se02BootBuildId: getImageBuildId(deviceInfo?.se2?.boot),
246
- se02BootHash: getImageHash(deviceInfo?.se2?.boot),
247
- se03BootBuildId: getImageBuildId(deviceInfo?.se3?.boot),
248
- se03BootHash: getImageHash(deviceInfo?.se3?.boot),
249
- se04BootBuildId: getImageBuildId(deviceInfo?.se4?.boot),
250
- se04BootHash: getImageHash(deviceInfo?.se4?.boot),
251
- });
241
+ const normalizeV2Verify = (deviceInfo?: ProtocolV2DeviceInfo): DeviceProfileVerify => {
242
+ const info = deviceInfo;
243
+ return {
244
+ firmwareBuildId: getImageBuildId(info?.fw?.application),
245
+ firmwareHash: getImageHash(info?.fw?.application),
246
+ bootloaderBuildId: getImageBuildId(info?.fw?.bootloader),
247
+ bootloaderHash: getImageHash(info?.fw?.bootloader),
248
+ boardBuildId: getImageBuildId(info?.fw?.application_data ?? info?.fw?.romloader),
249
+ boardHash: getImageHash(info?.fw?.application_data ?? info?.fw?.romloader),
250
+ bleBuildId: getImageBuildId(info?.coprocessor?.application),
251
+ bleHash: getImageHash(info?.coprocessor?.application),
252
+ se01BuildId: getImageBuildId(info?.se1?.application),
253
+ se01Hash: getImageHash(info?.se1?.application),
254
+ se02BuildId: getImageBuildId(info?.se2?.application),
255
+ se02Hash: getImageHash(info?.se2?.application),
256
+ se03BuildId: getImageBuildId(info?.se3?.application),
257
+ se03Hash: getImageHash(info?.se3?.application),
258
+ se04BuildId: getImageBuildId(info?.se4?.application),
259
+ se04Hash: getImageHash(info?.se4?.application),
260
+ se01BootBuildId: getImageBuildId(info?.se1?.bootloader),
261
+ se01BootHash: getImageHash(info?.se1?.bootloader),
262
+ se02BootBuildId: getImageBuildId(info?.se2?.bootloader),
263
+ se02BootHash: getImageHash(info?.se2?.bootloader),
264
+ se03BootBuildId: getImageBuildId(info?.se3?.bootloader),
265
+ se03BootHash: getImageHash(info?.se3?.bootloader),
266
+ se04BootBuildId: getImageBuildId(info?.se4?.bootloader),
267
+ se04BootHash: getImageHash(info?.se4?.bootloader),
268
+ };
269
+ };
252
270
 
253
271
  const normalizeRaw = ({
254
272
  features,
@@ -304,9 +322,11 @@ export function buildProfileFromProtocolV2({
304
322
  scope = 'basic',
305
323
  includeRaw = false,
306
324
  }: BuildProtocolV2ProfileParams): DeviceProfile {
325
+ const info = deviceInfo;
326
+ const deviceId = info?.status?.device_id || '';
307
327
  const serialNo = deviceInfo?.hw?.serial_no || '';
308
- const label = deviceInfo?.status?.label ?? null;
309
- const bleName = deviceInfo?.bt?.adv_name ?? null;
328
+ const label = null;
329
+ const bleName = info?.coprocessor?.bt_adv_name ?? null;
310
330
  const verify = normalizeV2Verify(deviceInfo);
311
331
 
312
332
  return {
@@ -314,9 +334,7 @@ export function buildProfileFromProtocolV2({
314
334
  sources,
315
335
  deviceType: EDeviceType.Pro2,
316
336
  firmwareType: EFirmwareType.Universal,
317
- // Protocol V2 的 DevGetDeviceInfo 没有 device_id 字段;serialNo 与 deviceId
318
- // 不是等价语义,这里保持空值,避免把稳定硬件序列号误当会随 wipe 轮换的身份。
319
- deviceId: '',
337
+ deviceId,
320
338
  serialNo,
321
339
  label,
322
340
  bleName,