@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.
Files changed (192) hide show
  1. package/__tests__/connectSettings.test.ts +19 -0
  2. package/__tests__/device-wallet-session-store.test.ts +131 -0
  3. package/__tests__/preInitialize.test.ts +33 -0
  4. package/__tests__/protocol-v2-firmware-targets.test.ts +19 -0
  5. package/__tests__/protocol-v2.test.ts +1930 -765
  6. package/dist/api/ClearSessionCache.d.ts +9 -0
  7. package/dist/api/ClearSessionCache.d.ts.map +1 -0
  8. package/dist/api/FileRead.d.ts.map +1 -1
  9. package/dist/api/FileWrite.d.ts.map +1 -1
  10. package/dist/api/FirmwareUpdateV2.d.ts.map +1 -1
  11. package/dist/api/FirmwareUpdateV3.d.ts.map +1 -1
  12. package/dist/api/FirmwareUpdateV4.d.ts +26 -5
  13. package/dist/api/FirmwareUpdateV4.d.ts.map +1 -1
  14. package/dist/api/GetDeviceInfo.d.ts.map +1 -1
  15. package/dist/api/GetFeatures.d.ts +1 -1
  16. package/dist/api/GetOnekeyFeatures.d.ts.map +1 -1
  17. package/dist/api/GetPassphraseState.d.ts +4 -4
  18. package/dist/api/GetPassphraseState.d.ts.map +1 -1
  19. package/dist/api/device/DeviceUnlock.d.ts +1 -1
  20. package/dist/api/firmware/FirmwareUpdateBaseMethod.d.ts +1 -0
  21. package/dist/api/firmware/FirmwareUpdateBaseMethod.d.ts.map +1 -1
  22. package/dist/api/firmware/bootloaderHelper.d.ts.map +1 -1
  23. package/dist/api/firmware/getBinary.d.ts +4 -0
  24. package/dist/api/firmware/getBinary.d.ts.map +1 -1
  25. package/dist/api/firmware/progressThrottle.d.ts +3 -0
  26. package/dist/api/firmware/progressThrottle.d.ts.map +1 -0
  27. package/dist/api/firmware/uploadFirmware.d.ts.map +1 -1
  28. package/dist/api/index.d.ts +8 -10
  29. package/dist/api/index.d.ts.map +1 -1
  30. package/dist/api/protocol-v2/DeviceFactoryInfoGet.d.ts +6 -0
  31. package/dist/api/protocol-v2/DeviceFactoryInfoGet.d.ts.map +1 -0
  32. package/dist/api/protocol-v2/DeviceFactoryInfoSet.d.ts +7 -0
  33. package/dist/api/protocol-v2/DeviceFactoryInfoSet.d.ts.map +1 -0
  34. package/dist/api/protocol-v2/DeviceFirmwareUpdate.d.ts +1 -1
  35. package/dist/api/protocol-v2/DeviceFirmwareUpdate.d.ts.map +1 -1
  36. package/dist/api/protocol-v2/DeviceGetFirmwareUpdateStatus.d.ts +3 -2
  37. package/dist/api/protocol-v2/DeviceGetFirmwareUpdateStatus.d.ts.map +1 -1
  38. package/dist/api/protocol-v2/{DeviceGetDeviceInfo.d.ts → DeviceInfoGet.d.ts} +10 -10
  39. package/dist/api/protocol-v2/DeviceInfoGet.d.ts.map +1 -0
  40. package/dist/api/protocol-v2/DeviceSessionGet.d.ts +9 -0
  41. package/dist/api/protocol-v2/DeviceSessionGet.d.ts.map +1 -0
  42. package/dist/api/protocol-v2/DeviceStatusGet.d.ts +6 -0
  43. package/dist/api/protocol-v2/DeviceStatusGet.d.ts.map +1 -0
  44. package/dist/api/protocol-v2/FilesystemFormat.d.ts.map +1 -1
  45. package/dist/api/protocol-v2/{FilesystemFixPermission.d.ts → FilesystemPermissionFix.d.ts} +2 -2
  46. package/dist/api/protocol-v2/FilesystemPermissionFix.d.ts.map +1 -0
  47. package/dist/api/protocol-v2/ProtocolInfoRequest.d.ts +6 -0
  48. package/dist/api/protocol-v2/ProtocolInfoRequest.d.ts.map +1 -0
  49. package/dist/api/protocol-v2/helpers.d.ts +27 -19
  50. package/dist/api/protocol-v2/helpers.d.ts.map +1 -1
  51. package/dist/api/ton/TonSignData.d.ts +1 -5
  52. package/dist/api/ton/TonSignData.d.ts.map +1 -1
  53. package/dist/api/tron/TronSignMessage.d.ts +0 -1
  54. package/dist/api/tron/TronSignMessage.d.ts.map +1 -1
  55. package/dist/api/tron/TronSignTransaction.d.ts +0 -1
  56. package/dist/api/tron/TronSignTransaction.d.ts.map +1 -1
  57. package/dist/constants/index.d.ts +2 -1
  58. package/dist/constants/index.d.ts.map +1 -1
  59. package/dist/core/index.d.ts.map +1 -1
  60. package/dist/data-manager/DataManager.d.ts +1 -1
  61. package/dist/data-manager/DataManager.d.ts.map +1 -1
  62. package/dist/data-manager/connectSettings.d.ts.map +1 -1
  63. package/dist/device/Device.d.ts +17 -18
  64. package/dist/device/Device.d.ts.map +1 -1
  65. package/dist/device/DeviceWalletSessionStore.d.ts +15 -0
  66. package/dist/device/DeviceWalletSessionStore.d.ts.map +1 -0
  67. package/dist/deviceProfile/buildDeviceFeatures.d.ts +6 -0
  68. package/dist/deviceProfile/buildDeviceFeatures.d.ts.map +1 -0
  69. package/dist/deviceProfile/buildDeviceProfile.d.ts +3 -4
  70. package/dist/deviceProfile/buildDeviceProfile.d.ts.map +1 -1
  71. package/dist/deviceProfile/index.d.ts +1 -1
  72. package/dist/deviceProfile/index.d.ts.map +1 -1
  73. package/dist/index.d.ts +657 -539
  74. package/dist/index.js +2579 -2161
  75. package/dist/inject.d.ts.map +1 -1
  76. package/dist/protocols/protocol-v2/features.d.ts +12 -14
  77. package/dist/protocols/protocol-v2/features.d.ts.map +1 -1
  78. package/dist/protocols/protocol-v2/firmware.d.ts +11 -9
  79. package/dist/protocols/protocol-v2/firmware.d.ts.map +1 -1
  80. package/dist/protocols/protocol-v2/index.d.ts +1 -0
  81. package/dist/protocols/protocol-v2/index.d.ts.map +1 -1
  82. package/dist/protocols/protocol-v2/walletSession.d.ts +13 -0
  83. package/dist/protocols/protocol-v2/walletSession.d.ts.map +1 -0
  84. package/dist/types/api/firmwareUpdate.d.ts +4 -6
  85. package/dist/types/api/firmwareUpdate.d.ts.map +1 -1
  86. package/dist/types/api/getDeviceInfo.d.ts +4 -2
  87. package/dist/types/api/getDeviceInfo.d.ts.map +1 -1
  88. package/dist/types/api/getPassphraseState.d.ts +4 -4
  89. package/dist/types/api/getPassphraseState.d.ts.map +1 -1
  90. package/dist/types/api/index.d.ts +11 -11
  91. package/dist/types/api/index.d.ts.map +1 -1
  92. package/dist/types/api/protocolV2.d.ts +16 -17
  93. package/dist/types/api/protocolV2.d.ts.map +1 -1
  94. package/dist/types/api/sessionCache.d.ts +10 -0
  95. package/dist/types/api/sessionCache.d.ts.map +1 -0
  96. package/dist/types/device.d.ts +88 -8
  97. package/dist/types/device.d.ts.map +1 -1
  98. package/dist/types/params.d.ts +1 -0
  99. package/dist/types/params.d.ts.map +1 -1
  100. package/dist/types/settings.d.ts +21 -1
  101. package/dist/types/settings.d.ts.map +1 -1
  102. package/dist/utils/capabilitieUtils.d.ts.map +1 -1
  103. package/dist/utils/deviceFeaturesUtils.d.ts +2 -0
  104. package/dist/utils/deviceFeaturesUtils.d.ts.map +1 -1
  105. package/dist/utils/deviceInfoUtils.d.ts.map +1 -1
  106. package/dist/utils/deviceVersionUtils.d.ts.map +1 -1
  107. package/dist/utils/findDefectiveBatchDevice.d.ts +1 -1
  108. package/dist/utils/patch.d.ts +1 -1
  109. package/dist/utils/patch.d.ts.map +1 -1
  110. package/package.json +4 -4
  111. package/src/api/ClearSessionCache.ts +28 -0
  112. package/src/api/FileRead.ts +16 -3
  113. package/src/api/FileWrite.ts +14 -1
  114. package/src/api/FirmwareUpdateV2.ts +9 -2
  115. package/src/api/FirmwareUpdateV3.ts +2 -1
  116. package/src/api/FirmwareUpdateV4.ts +1089 -285
  117. package/src/api/GetDeviceInfo.ts +6 -13
  118. package/src/api/GetOnekeyFeatures.ts +3 -14
  119. package/src/api/GetPassphraseState.ts +7 -4
  120. package/src/api/device/DeviceRebootToBoardloader.ts +4 -4
  121. package/src/api/device/DeviceRebootToBootloader.ts +4 -4
  122. package/src/api/firmware/FirmwareUpdateBaseMethod.ts +18 -4
  123. package/src/api/firmware/bootloaderHelper.ts +3 -2
  124. package/src/api/firmware/getBinary.ts +1 -1
  125. package/src/api/firmware/progressThrottle.ts +44 -0
  126. package/src/api/firmware/releaseHelper.ts +3 -3
  127. package/src/api/firmware/uploadFirmware.ts +5 -2
  128. package/src/api/index.ts +8 -10
  129. package/src/api/protocol-v2/{FactoryGetDeviceInfo.ts → DeviceFactoryInfoGet.ts} +3 -3
  130. package/src/api/protocol-v2/DeviceFactoryInfoSet.ts +32 -0
  131. package/src/api/protocol-v2/DeviceFirmwareUpdate.ts +3 -5
  132. package/src/api/protocol-v2/DeviceGetFirmwareUpdateStatus.ts +39 -5
  133. package/src/api/protocol-v2/{DeviceGetDeviceInfo.ts → DeviceInfoGet.ts} +52 -22
  134. package/src/api/protocol-v2/DeviceReboot.ts +2 -2
  135. package/src/api/protocol-v2/DeviceSessionGet.ts +26 -0
  136. package/src/api/protocol-v2/DeviceStatusGet.ts +14 -0
  137. package/src/api/protocol-v2/FilesystemFormat.ts +4 -1
  138. package/src/api/protocol-v2/{FilesystemFixPermission.ts → FilesystemPermissionFix.ts} +2 -2
  139. package/src/api/protocol-v2/{GetProtoVersion.ts → ProtocolInfoRequest.ts} +2 -2
  140. package/src/api/protocol-v2/helpers.ts +58 -59
  141. package/src/api/ton/TonSignData.ts +1 -5
  142. package/src/api/tron/TronSignMessage.ts +0 -1
  143. package/src/api/tron/TronSignTransaction.ts +0 -1
  144. package/src/constants/index.ts +10 -1
  145. package/src/core/index.ts +22 -10
  146. package/src/data/messages/messages-protocol-v2.json +992 -1420
  147. package/src/data/messages/messages.json +8 -0
  148. package/src/data-manager/DataManager.ts +11 -4
  149. package/src/data-manager/connectSettings.ts +4 -0
  150. package/src/device/Device.ts +158 -294
  151. package/src/device/DevicePool.ts +9 -9
  152. package/src/device/DeviceWalletSessionStore.ts +78 -0
  153. package/src/deviceProfile/buildDeviceFeatures.ts +365 -0
  154. package/src/deviceProfile/buildDeviceProfile.ts +165 -200
  155. package/src/deviceProfile/index.ts +4 -1
  156. package/src/inject.ts +13 -16
  157. package/src/protocols/protocol-v2/features.ts +28 -67
  158. package/src/protocols/protocol-v2/firmware.ts +12 -36
  159. package/src/protocols/protocol-v2/index.ts +1 -0
  160. package/src/protocols/protocol-v2/walletSession.ts +83 -0
  161. package/src/types/api/firmwareUpdate.ts +16 -20
  162. package/src/types/api/getDeviceInfo.ts +4 -2
  163. package/src/types/api/getPassphraseState.ts +4 -4
  164. package/src/types/api/index.ts +17 -20
  165. package/src/types/api/protocolV2.ts +35 -40
  166. package/src/types/api/sessionCache.ts +14 -0
  167. package/src/types/device.ts +98 -34
  168. package/src/types/params.ts +4 -0
  169. package/src/types/settings.ts +42 -30
  170. package/src/utils/capabilitieUtils.ts +1 -2
  171. package/src/utils/deviceFeaturesUtils.ts +54 -29
  172. package/src/utils/deviceInfoUtils.ts +11 -29
  173. package/src/utils/deviceVersionUtils.ts +7 -25
  174. package/src/utils/findDefectiveBatchDevice.ts +6 -6
  175. package/dist/api/protocol-v2/DevReboot.d.ts +0 -7
  176. package/dist/api/protocol-v2/DevReboot.d.ts.map +0 -1
  177. package/dist/api/protocol-v2/DeviceGetDeviceInfo.d.ts.map +0 -1
  178. package/dist/api/protocol-v2/DeviceGetOnboardingStatus.d.ts +0 -6
  179. package/dist/api/protocol-v2/DeviceGetOnboardingStatus.d.ts.map +0 -1
  180. package/dist/api/protocol-v2/FactoryDeviceInfoSettings.d.ts +0 -7
  181. package/dist/api/protocol-v2/FactoryDeviceInfoSettings.d.ts.map +0 -1
  182. package/dist/api/protocol-v2/FactoryGetDeviceInfo.d.ts +0 -6
  183. package/dist/api/protocol-v2/FactoryGetDeviceInfo.d.ts.map +0 -1
  184. package/dist/api/protocol-v2/FilesystemFixPermission.d.ts.map +0 -1
  185. package/dist/api/protocol-v2/GetProtoVersion.d.ts +0 -6
  186. package/dist/api/protocol-v2/GetProtoVersion.d.ts.map +0 -1
  187. package/dist/deviceProfile/legacyFeaturesView.d.ts +0 -5
  188. package/dist/deviceProfile/legacyFeaturesView.d.ts.map +0 -1
  189. package/src/api/protocol-v2/DevReboot.ts +0 -24
  190. package/src/api/protocol-v2/DeviceGetOnboardingStatus.ts +0 -16
  191. package/src/api/protocol-v2/FactoryDeviceInfoSettings.ts +0 -29
  192. package/src/deviceProfile/legacyFeaturesView.ts +0 -123
@@ -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);
@@ -166,7 +166,7 @@ export class DevicePool extends EventEmitter {
166
166
  for (let i = this.connectedPool.length - 1; i >= 0; i--) {
167
167
  const descriptor = this.connectedPool[i];
168
168
  const device = await this._createDevice(descriptor, initOptions);
169
- Log.debug('emit DEVICE.CONNECT: ', device?.profile ?? device?.features);
169
+ Log.debug('emit DEVICE.CONNECT: ', device?.features);
170
170
  this.emitter.emit(DEVICE.CONNECT, device);
171
171
  this.connectedPool.splice(i, 1);
172
172
  }
@@ -203,7 +203,7 @@ export class DevicePool extends EventEmitter {
203
203
  this._addConnectedDeviceToPool(d);
204
204
  return;
205
205
  }
206
- Log.debug('emit DEVICE.CONNECT: ', device.profile ?? device.features);
206
+ Log.debug('emit DEVICE.CONNECT: ', device.features);
207
207
  this.emitter.emit(DEVICE.CONNECT, device);
208
208
  });
209
209
 
@@ -215,7 +215,7 @@ export class DevicePool extends EventEmitter {
215
215
  return;
216
216
  }
217
217
 
218
- Log.debug('emit DEVICE.DISCONNECT: ', device.profile ?? device.features);
218
+ Log.debug('emit DEVICE.DISCONNECT: ', device.features);
219
219
  this.emitter.emit(DEVICE.DISCONNECT, device);
220
220
  });
221
221
  }
@@ -0,0 +1,78 @@
1
+ export class DeviceWalletSessionStore {
2
+ private readonly walletSessions = new Map<string, Map<string, string>>();
3
+
4
+ private readonly pendingSessions = new Map<string, string>();
5
+
6
+ get(deviceKey: string, passphraseState?: string) {
7
+ if (!deviceKey || !passphraseState) return undefined;
8
+ return this.walletSessions.get(deviceKey)?.get(passphraseState);
9
+ }
10
+
11
+ set(deviceKey: string, passphraseState?: string, sessionId?: string) {
12
+ if (!deviceKey || !passphraseState || !sessionId) return;
13
+ let deviceSessions = this.walletSessions.get(deviceKey);
14
+ if (!deviceSessions) {
15
+ deviceSessions = new Map<string, string>();
16
+ this.walletSessions.set(deviceKey, deviceSessions);
17
+ }
18
+ deviceSessions.set(passphraseState, sessionId);
19
+ }
20
+
21
+ setPending(deviceKey: string, sessionId?: string) {
22
+ if (!deviceKey || !sessionId) return;
23
+ this.pendingSessions.set(deviceKey, sessionId);
24
+ }
25
+
26
+ getPending(deviceKey: string) {
27
+ if (!deviceKey) return undefined;
28
+ return this.pendingSessions.get(deviceKey);
29
+ }
30
+
31
+ delete(deviceKey: string, passphraseState?: string) {
32
+ if (!deviceKey || !passphraseState) return;
33
+ const deviceSessions = this.walletSessions.get(deviceKey);
34
+ if (!deviceSessions) return;
35
+ deviceSessions.delete(passphraseState);
36
+ if (deviceSessions.size === 0) {
37
+ this.walletSessions.delete(deviceKey);
38
+ }
39
+ }
40
+
41
+ deletePending(deviceKey: string) {
42
+ if (!deviceKey) return;
43
+ this.pendingSessions.delete(deviceKey);
44
+ }
45
+
46
+ deleteDevice(deviceKey: string) {
47
+ if (!deviceKey) return;
48
+ this.walletSessions.delete(deviceKey);
49
+ this.pendingSessions.delete(deviceKey);
50
+ }
51
+
52
+ migrateDeviceKey(from: string, to: string) {
53
+ if (!from || !to || from === to) return;
54
+
55
+ const sourceSessions = this.walletSessions.get(from);
56
+ if (sourceSessions) {
57
+ const targetSessions = this.walletSessions.get(to) ?? new Map<string, string>();
58
+ this.walletSessions.set(to, targetSessions);
59
+ sourceSessions.forEach((sessionId, passphraseState) => {
60
+ targetSessions.set(passphraseState, sessionId);
61
+ });
62
+ this.walletSessions.delete(from);
63
+ }
64
+
65
+ const pendingSession = this.pendingSessions.get(from);
66
+ if (pendingSession) {
67
+ this.pendingSessions.set(to, pendingSession);
68
+ this.pendingSessions.delete(from);
69
+ }
70
+ }
71
+
72
+ clear() {
73
+ this.walletSessions.clear();
74
+ this.pendingSessions.clear();
75
+ }
76
+ }
77
+
78
+ export const deviceWalletSessionStore = new DeviceWalletSessionStore();
@@ -0,0 +1,365 @@
1
+ import { EDeviceType, EFirmwareType } from '@onekeyfe/hd-shared';
2
+
3
+ import type { Features } from '../types';
4
+ import type { PROTO } from '../constants';
5
+ import type { DeviceFirmwareImageInfo, ProtocolV2DeviceInfo } from '@onekeyfe/hd-transport';
6
+ import { isProtocolV2BootloaderDeviceInfo } from '../protocols/protocol-v2/features';
7
+
8
+ type ProtocolV1FeaturesCompat = PROTO.Features &
9
+ Partial<PROTO.OnekeyFeatures> & {
10
+ protocol_version?: number | null;
11
+ onekey_version?: string;
12
+ onekey_serial?: string;
13
+ };
14
+
15
+ const getImageVersion = (image?: DeviceFirmwareImageInfo | null) => image?.version ?? null;
16
+
17
+ const bytesToHex = (value: unknown): string | undefined => {
18
+ if (!value) return undefined;
19
+ if (typeof value === 'string') return value;
20
+ if (value instanceof Uint8Array) {
21
+ return Array.from(value)
22
+ .map(byte => byte.toString(16).padStart(2, '0'))
23
+ .join('');
24
+ }
25
+ if (Array.isArray(value)) {
26
+ return value.map(byte => Number(byte).toString(16).padStart(2, '0')).join('');
27
+ }
28
+ return undefined;
29
+ };
30
+
31
+ const getImageBuildId = (image?: DeviceFirmwareImageInfo | null) => image?.build_id ?? undefined;
32
+
33
+ const getImageHash = (image?: DeviceFirmwareImageInfo | null) => bytesToHex(image?.hash);
34
+
35
+ const firstValue = <T>(...values: Array<T | null | undefined>) =>
36
+ values.find(value => value !== undefined && value !== null);
37
+
38
+ const firstMeaningfulVersion = (...versions: Array<string | null | undefined>) =>
39
+ versions.find(version => Boolean(version && version !== '0.0.0')) ?? null;
40
+
41
+ const versionFromParts = (major?: number | null, minor?: number | null, patch?: number | null) =>
42
+ [major, minor, patch].map(part => Number(part) || 0).join('.');
43
+
44
+ const getProtocolV1Mode = (features: ProtocolV1FeaturesCompat): Features['mode'] => {
45
+ if (features.bootloader_mode === true) return 'bootloader';
46
+ if (features.initialized === false) return 'notInitialized';
47
+ if (features.initialized === true) return 'normal';
48
+ return 'unknown';
49
+ };
50
+
51
+ const getProtocolV1DeviceType = (features: ProtocolV1FeaturesCompat): Features['deviceType'] => {
52
+ const onekeyDeviceType = features.onekey_device_type as string | null | undefined;
53
+ switch (onekeyDeviceType) {
54
+ case 'CLASSIC':
55
+ return EDeviceType.Classic;
56
+ case 'CLASSIC1S':
57
+ return EDeviceType.Classic1s;
58
+ case 'MINI':
59
+ return EDeviceType.Mini;
60
+ case 'TOUCH':
61
+ return EDeviceType.Touch;
62
+ case 'PRO':
63
+ return EDeviceType.Pro;
64
+ case 'PRO2':
65
+ case 'pro2':
66
+ return EDeviceType.Pro2;
67
+ case 'PURE':
68
+ return EDeviceType.ClassicPure;
69
+ default:
70
+ break;
71
+ }
72
+
73
+ const serialNo = features.onekey_serial_no || features.onekey_serial || features.serial_no || '';
74
+ const prefix = serialNo.slice(0, 2).toLowerCase();
75
+ if (prefix === 'bi' || prefix === 'cl') return EDeviceType.Classic;
76
+ if (prefix === 'cp') return EDeviceType.ClassicPure;
77
+ if (prefix === 'mi') return EDeviceType.Mini;
78
+ if (prefix === 'tc') return EDeviceType.Touch;
79
+ if (prefix === 'pr') return EDeviceType.Pro;
80
+ if (prefix === 'p2') return EDeviceType.Pro2;
81
+ if (!serialNo && features.bootloader_mode === true && features.model === '1') {
82
+ return EDeviceType.Classic;
83
+ }
84
+ return EDeviceType.Unknown;
85
+ };
86
+
87
+ const getProtocolV1FirmwareType = (
88
+ features: ProtocolV1FeaturesCompat
89
+ ): Features['firmwareType'] => {
90
+ if (features.fw_vendor === 'OneKey Bitcoin-only') return EFirmwareType.BitcoinOnly;
91
+ return EFirmwareType.Universal;
92
+ };
93
+
94
+ const getProtocolV1Label = (
95
+ features: ProtocolV1FeaturesCompat,
96
+ deviceType: Features['deviceType'],
97
+ bleName: string | null
98
+ ) => {
99
+ if (features.label) return features.label;
100
+ if (bleName) return bleName;
101
+ if (deviceType === EDeviceType.Unknown) return null;
102
+ if (deviceType === EDeviceType.ClassicPure) return 'OneKey Classic 1S';
103
+ return `OneKey ${deviceType.charAt(0).toUpperCase()}${deviceType.slice(1)}`;
104
+ };
105
+
106
+ export const buildProtocolV1FeaturesPayload = (
107
+ protocolV1Features: PROTO.Features,
108
+ previous?: Features
109
+ ): Features => {
110
+ const features = protocolV1Features as ProtocolV1FeaturesCompat;
111
+ const firmwareVersion = firstMeaningfulVersion(
112
+ features.onekey_firmware_version,
113
+ features.onekey_version,
114
+ versionFromParts(features.major_version, features.minor_version, features.patch_version)
115
+ );
116
+ const bootloaderVersion = firstMeaningfulVersion(
117
+ features.onekey_boot_version,
118
+ features.bootloader_version,
119
+ features.bootloader_mode
120
+ ? versionFromParts(features.major_version, features.minor_version, features.patch_version)
121
+ : null
122
+ );
123
+ const boardVersion = firstMeaningfulVersion(
124
+ features.onekey_board_version,
125
+ features.boardloader_version
126
+ );
127
+ const bleVersion = firstMeaningfulVersion(features.onekey_ble_version, features.ble_ver);
128
+ const serialNo = features.onekey_serial_no || features.onekey_serial || features.serial_no || '';
129
+ const bleName = features.onekey_ble_name || features.ble_name || null;
130
+ const deviceType = getProtocolV1DeviceType(features);
131
+ const sessionId = features.session_id ?? previous?.sessionId ?? null;
132
+
133
+ return {
134
+ protocol: 'V1',
135
+ protocolVersion: features.protocol_version ?? previous?.protocolVersion ?? 1,
136
+ deviceType,
137
+ firmwareType: getProtocolV1FirmwareType(features),
138
+ model: features.model ?? null,
139
+ vendor: features.vendor ?? null,
140
+ deviceId: features.device_id ?? null,
141
+ serialNo,
142
+ label: getProtocolV1Label(features, deviceType, bleName),
143
+ bleName,
144
+ capabilities: features.capabilities ?? [],
145
+ mode: getProtocolV1Mode(features),
146
+ initialized: features.initialized ?? null,
147
+ bootloaderMode: features.bootloader_mode ?? null,
148
+ unlocked: features.unlocked ?? true,
149
+ firmwarePresent: features.firmware_present ?? null,
150
+ passphraseProtection: features.passphrase_protection ?? null,
151
+ pinProtection: features.pin_protection ?? null,
152
+ backupRequired: features.needs_backup ?? null,
153
+ noBackup: features.no_backup ?? null,
154
+ unfinishedBackup: features.unfinished_backup ?? null,
155
+ recoveryMode: features.recovery_mode ?? null,
156
+ language: features.language ?? null,
157
+ bleEnabled: features.ble_enable ?? null,
158
+ sdCardPresent: features.sd_card_present ?? null,
159
+ sdProtection: features.sd_protection ?? null,
160
+ wipeCodeProtection: features.wipe_code_protection ?? null,
161
+ passphraseAlwaysOnDevice: features.passphrase_always_on_device ?? null,
162
+ safetyChecks: features.safety_checks ?? null,
163
+ autoLockDelayMs: features.auto_lock_delay_ms ?? null,
164
+ displayRotation: features.display_rotation ?? null,
165
+ experimentalFeatures: features.experimental_features ?? null,
166
+ firmwareVersion,
167
+ bootloaderVersion,
168
+ boardVersion,
169
+ bleVersion,
170
+ se01Version: firstMeaningfulVersion(features.onekey_se01_version),
171
+ se02Version: firstMeaningfulVersion(features.onekey_se02_version),
172
+ se03Version: firstMeaningfulVersion(features.onekey_se03_version),
173
+ se04Version: firstMeaningfulVersion(features.onekey_se04_version),
174
+ se01BootVersion: firstMeaningfulVersion(features.onekey_se01_boot_version),
175
+ se02BootVersion: firstMeaningfulVersion(features.onekey_se02_boot_version),
176
+ se03BootVersion: firstMeaningfulVersion(features.onekey_se03_boot_version),
177
+ se04BootVersion: firstMeaningfulVersion(features.onekey_se04_boot_version),
178
+ seVersion: features.se_ver ?? null,
179
+ verify: {
180
+ firmwareBuildId: features.onekey_firmware_build_id,
181
+ firmwareHash: features.onekey_firmware_hash,
182
+ bootloaderBuildId: features.onekey_boot_build_id,
183
+ bootloaderHash: features.onekey_boot_hash,
184
+ boardBuildId: features.onekey_board_build_id,
185
+ boardHash: features.onekey_board_hash,
186
+ bleBuildId: features.onekey_ble_build_id,
187
+ bleHash: features.onekey_ble_hash,
188
+ se01BuildId: features.onekey_se01_build_id,
189
+ se01Hash: features.onekey_se01_hash,
190
+ se02BuildId: features.onekey_se02_build_id,
191
+ se02Hash: features.onekey_se02_hash,
192
+ se03BuildId: features.onekey_se03_build_id,
193
+ se03Hash: features.onekey_se03_hash,
194
+ se04BuildId: features.onekey_se04_build_id,
195
+ se04Hash: features.onekey_se04_hash,
196
+ se01BootBuildId: features.onekey_se01_boot_build_id,
197
+ se01BootHash: features.onekey_se01_boot_hash,
198
+ se02BootBuildId: features.onekey_se02_boot_build_id,
199
+ se02BootHash: features.onekey_se02_boot_hash,
200
+ se03BootBuildId: features.onekey_se03_boot_build_id,
201
+ se03BootHash: features.onekey_se03_boot_hash,
202
+ se04BootBuildId: features.onekey_se04_boot_build_id,
203
+ se04BootHash: features.onekey_se04_boot_hash,
204
+ },
205
+ sessionId,
206
+ raw: {
207
+ protocolV1Features: protocolV1Features,
208
+ },
209
+ };
210
+ };
211
+
212
+ /**
213
+ * Protocol V2 的结构化 `Features` 构建器。
214
+ *
215
+ * 这是 Device 内部唯一缓存状态。字段只来自 DeviceInfoGet 或前一次 features
216
+ * 缓存的同名字段级合并;不存在协议等价语义的字段保持 null/空值,不再通过
217
+ * DeviceProfile 或 transport path 做身份兜底。
218
+ */
219
+ export const buildProtocolV2FeaturesPayload = (
220
+ deviceInfo?: ProtocolV2DeviceInfo,
221
+ previous?: Features
222
+ ): Features => {
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;
229
+
230
+ const firmwareVersion = firstMeaningfulVersion(
231
+ getImageVersion(fwApplication),
232
+ previous?.firmwareVersion
233
+ );
234
+ const bootloaderVersion = firstMeaningfulVersion(
235
+ getImageVersion(fwBootloader),
236
+ previous?.bootloaderVersion
237
+ );
238
+ const boardVersion = firstMeaningfulVersion(getImageVersion(fwBoard), previous?.boardVersion);
239
+ const bleVersion = firstMeaningfulVersion(getImageVersion(bleApplication), previous?.bleVersion);
240
+ const deviceId = status?.device_id ?? null;
241
+ const serialNo = firstValue(info?.hw?.serial_no, previous?.serialNo) ?? '';
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';
260
+
261
+ return {
262
+ protocol: 'V2',
263
+ protocolVersion: deviceInfo?.protocol_version ?? previous?.protocolVersion ?? null,
264
+ deviceType: EDeviceType.Pro2,
265
+ firmwareType: previous?.firmwareType ?? EFirmwareType.Universal,
266
+ model: 'pro2',
267
+ vendor: 'onekey.so',
268
+ deviceId,
269
+ serialNo,
270
+ label,
271
+ bleName: bleName ?? null,
272
+ capabilities: [],
273
+ mode,
274
+ initialized,
275
+ bootloaderMode,
276
+ unlocked,
277
+ firmwarePresent: previous?.firmwarePresent ?? null,
278
+ passphraseProtection,
279
+ pinProtection: null,
280
+ backupRequired,
281
+ noBackup: null,
282
+ unfinishedBackup: null,
283
+ recoveryMode: null,
284
+ language,
285
+ bleEnabled: bleEnabled ?? null,
286
+ sdCardPresent: null,
287
+ sdProtection: null,
288
+ wipeCodeProtection: null,
289
+ passphraseAlwaysOnDevice: null,
290
+ attachToPinEnabled,
291
+ safetyChecks: null,
292
+ autoLockDelayMs: null,
293
+ displayRotation: null,
294
+ experimentalFeatures: null,
295
+ firmwareVersion,
296
+ bootloaderVersion,
297
+ boardVersion,
298
+ bleVersion,
299
+ se01Version: firstMeaningfulVersion(
300
+ getImageVersion(info?.se1?.application),
301
+ previous?.se01Version
302
+ ),
303
+ se02Version: firstMeaningfulVersion(
304
+ getImageVersion(info?.se2?.application),
305
+ previous?.se02Version
306
+ ),
307
+ se03Version: firstMeaningfulVersion(
308
+ getImageVersion(info?.se3?.application),
309
+ previous?.se03Version
310
+ ),
311
+ se04Version: firstMeaningfulVersion(
312
+ getImageVersion(info?.se4?.application),
313
+ previous?.se04Version
314
+ ),
315
+ se01BootVersion: firstMeaningfulVersion(
316
+ getImageVersion(info?.se1?.bootloader),
317
+ previous?.se01BootVersion
318
+ ),
319
+ se02BootVersion: firstMeaningfulVersion(
320
+ getImageVersion(info?.se2?.bootloader),
321
+ previous?.se02BootVersion
322
+ ),
323
+ se03BootVersion: firstMeaningfulVersion(
324
+ getImageVersion(info?.se3?.bootloader),
325
+ previous?.se03BootVersion
326
+ ),
327
+ se04BootVersion: firstMeaningfulVersion(
328
+ getImageVersion(info?.se4?.bootloader),
329
+ previous?.se04BootVersion
330
+ ),
331
+ seVersion: previous?.seVersion ?? null,
332
+ verify: {
333
+ firmwareBuildId: getImageBuildId(fwApplication) ?? previous?.verify?.firmwareBuildId,
334
+ firmwareHash: getImageHash(fwApplication) ?? previous?.verify?.firmwareHash,
335
+ bootloaderBuildId: getImageBuildId(fwBootloader) ?? previous?.verify?.bootloaderBuildId,
336
+ bootloaderHash: getImageHash(fwBootloader) ?? previous?.verify?.bootloaderHash,
337
+ boardBuildId: getImageBuildId(fwBoard) ?? previous?.verify?.boardBuildId,
338
+ boardHash: getImageHash(fwBoard) ?? previous?.verify?.boardHash,
339
+ bleBuildId: getImageBuildId(bleApplication) ?? previous?.verify?.bleBuildId,
340
+ bleHash: getImageHash(bleApplication) ?? previous?.verify?.bleHash,
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,
357
+ },
358
+ sessionId: previous?.sessionId ?? null,
359
+ passphraseState: previous?.passphraseState,
360
+ unlockedAttachPin,
361
+ raw: {
362
+ protocolV2DeviceInfo: deviceInfo,
363
+ },
364
+ };
365
+ };