@onekeyfe/hd-core 1.2.0-alpha.19 → 1.2.0-alpha.20

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (256) hide show
  1. package/__tests__/AllNetworkGetAddressBase.tracing.test.ts +75 -0
  2. package/__tests__/DeviceCommands.test.ts +143 -7
  3. package/__tests__/RequestQueue.test.ts +106 -0
  4. package/__tests__/UploadPortfolio.test.ts +46 -0
  5. package/__tests__/core-dispose.test.ts +34 -0
  6. package/__tests__/core-error-output.test.ts +39 -0
  7. package/__tests__/device-lifecycle-events.test.ts +117 -0
  8. package/__tests__/device-pool-state.test.ts +20 -1
  9. package/__tests__/device-settings.test.ts +184 -6
  10. package/__tests__/device-state-events.test.ts +1 -2
  11. package/__tests__/device-state-mapper.test.ts +33 -26
  12. package/__tests__/device-state-store.test.ts +1 -34
  13. package/__tests__/device-utils.test.ts +106 -0
  14. package/__tests__/device-wallet-session-store.test.ts +65 -29
  15. package/__tests__/deviceSettings.test.ts +21 -12
  16. package/__tests__/evmLedgerLegacySafety.test.ts +2 -2
  17. package/__tests__/evmSignTypedData.test.ts +80 -0
  18. package/__tests__/filesystemValidation.test.ts +53 -0
  19. package/__tests__/firmware-update/firmware-update-v2-download-before-boot.test.ts +402 -0
  20. package/__tests__/get-device-state.test.ts +77 -41
  21. package/__tests__/logBlockEvent.test.ts +24 -11
  22. package/__tests__/networkUtils.test.ts +386 -0
  23. package/__tests__/open-wallet-session-error-response.test.ts +43 -0
  24. package/__tests__/open-wallet-session.test.ts +559 -0
  25. package/__tests__/protocol-v2.test.ts +756 -452
  26. package/__tests__/public-device-state-api.test.ts +113 -13
  27. package/__tests__/public-pro2-api-boundary.test.ts +91 -0
  28. package/__tests__/search-devices.test.ts +43 -0
  29. package/dist/api/BaseMethod.d.ts +3 -0
  30. package/dist/api/BaseMethod.d.ts.map +1 -1
  31. package/dist/api/CheckBootloaderRelease.d.ts.map +1 -1
  32. package/dist/api/CheckFirmwareRelease.d.ts.map +1 -1
  33. package/dist/api/ClearSessionCache.d.ts.map +1 -1
  34. package/dist/api/DirList.d.ts.map +1 -1
  35. package/dist/api/FileRead.d.ts.map +1 -1
  36. package/dist/api/FirmwareUpdateV2.d.ts +2 -2
  37. package/dist/api/FirmwareUpdateV2.d.ts.map +1 -1
  38. package/dist/api/FirmwareUpdateV3.d.ts.map +1 -1
  39. package/dist/api/FirmwareUpdateV4.d.ts +3 -2
  40. package/dist/api/FirmwareUpdateV4.d.ts.map +1 -1
  41. package/dist/api/GetPassphraseState.d.ts.map +1 -1
  42. package/dist/api/OpenWalletSession.d.ts +14 -0
  43. package/dist/api/OpenWalletSession.d.ts.map +1 -0
  44. package/dist/api/PathInfo.d.ts.map +1 -1
  45. package/dist/api/PromptWebDeviceAccess.d.ts.map +1 -1
  46. package/dist/api/SearchDevices.d.ts +3 -0
  47. package/dist/api/SearchDevices.d.ts.map +1 -1
  48. package/dist/api/UploadPortfolio.d.ts.map +1 -1
  49. package/dist/api/allnetwork/AllNetworkGetAddressBase.d.ts.map +1 -1
  50. package/dist/api/device/DeviceChangePin.d.ts.map +1 -1
  51. package/dist/api/device/DeviceFullyUploadResource.d.ts +1 -2
  52. package/dist/api/device/DeviceFullyUploadResource.d.ts.map +1 -1
  53. package/dist/api/device/DeviceSettings.d.ts.map +1 -1
  54. package/dist/api/device/DeviceUpdateBootloader.d.ts.map +1 -1
  55. package/dist/api/device/DeviceWipe.d.ts.map +1 -1
  56. package/dist/api/evm/EVMSignTypedData.d.ts.map +1 -1
  57. package/dist/api/firmware/getBinary.d.ts +7 -3
  58. package/dist/api/firmware/getBinary.d.ts.map +1 -1
  59. package/dist/api/helpers/filesystemValidation.d.ts +3 -0
  60. package/dist/api/helpers/filesystemValidation.d.ts.map +1 -1
  61. package/dist/api/helpers/paramsValidator.d.ts +1 -0
  62. package/dist/api/helpers/paramsValidator.d.ts.map +1 -1
  63. package/dist/api/helpers/protocolV2FileWrite.d.ts.map +1 -1
  64. package/dist/api/index.d.ts +7 -11
  65. package/dist/api/index.d.ts.map +1 -1
  66. package/dist/api/protocol-v2/DeviceGetFirmwareUpdateStatus.d.ts.map +1 -1
  67. package/dist/api/protocol-v2/DeviceSettingsPageShow.d.ts.map +1 -1
  68. package/dist/api/protocol-v2/DeviceSettingsSet.d.ts.map +1 -1
  69. package/dist/api/utils.d.ts.map +1 -1
  70. package/dist/core/RequestQueue.d.ts +17 -1
  71. package/dist/core/RequestQueue.d.ts.map +1 -1
  72. package/dist/core/index.d.ts +3 -1
  73. package/dist/core/index.d.ts.map +1 -1
  74. package/dist/device/Device.d.ts +6 -5
  75. package/dist/device/Device.d.ts.map +1 -1
  76. package/dist/device/DeviceCommands.d.ts +5 -5
  77. package/dist/device/DeviceCommands.d.ts.map +1 -1
  78. package/dist/device/DevicePool.d.ts +1 -0
  79. package/dist/device/DevicePool.d.ts.map +1 -1
  80. package/dist/device/DeviceStateMapper.d.ts +2 -2
  81. package/dist/device/DeviceStateMapper.d.ts.map +1 -1
  82. package/dist/device/DeviceStateProjector.d.ts +1 -2
  83. package/dist/device/DeviceStateProjector.d.ts.map +1 -1
  84. package/dist/device/DeviceStateStore.d.ts +1 -3
  85. package/dist/device/DeviceStateStore.d.ts.map +1 -1
  86. package/dist/device/DeviceWalletSessionStore.d.ts +6 -1
  87. package/dist/device/DeviceWalletSessionStore.d.ts.map +1 -1
  88. package/dist/device/cloneDeviceState.d.ts +2 -0
  89. package/dist/device/cloneDeviceState.d.ts.map +1 -0
  90. package/dist/deviceProfile/buildDeviceFeatures.d.ts +3 -1
  91. package/dist/deviceProfile/buildDeviceFeatures.d.ts.map +1 -1
  92. package/dist/events/logBlockEvent.d.ts.map +1 -1
  93. package/dist/index.d.ts +608 -75
  94. package/dist/index.js +2287 -1706
  95. package/dist/inject.d.ts.map +1 -1
  96. package/dist/protocols/protocol-v2/deviceSession.d.ts +7 -0
  97. package/dist/protocols/protocol-v2/deviceSession.d.ts.map +1 -0
  98. package/dist/protocols/protocol-v2/features.d.ts +11 -4
  99. package/dist/protocols/protocol-v2/features.d.ts.map +1 -1
  100. package/dist/protocols/protocol-v2/index.d.ts +2 -2
  101. package/dist/protocols/protocol-v2/index.d.ts.map +1 -1
  102. package/dist/protocols/protocol-v2/settingsUnlockPolicy.d.ts +16 -0
  103. package/dist/protocols/protocol-v2/settingsUnlockPolicy.d.ts.map +1 -0
  104. package/dist/protocols/protocol-v2/uiInteraction.d.ts.map +1 -1
  105. package/dist/protocols/protocol-v2/walletSession.d.ts +8 -3
  106. package/dist/protocols/protocol-v2/walletSession.d.ts.map +1 -1
  107. package/dist/types/api/checkAllFirmwareRelease.d.ts +1 -2
  108. package/dist/types/api/checkAllFirmwareRelease.d.ts.map +1 -1
  109. package/dist/types/api/deviceSettings.d.ts +1 -0
  110. package/dist/types/api/deviceSettings.d.ts.map +1 -1
  111. package/dist/types/api/deviceUnlock.d.ts +1 -1
  112. package/dist/types/api/deviceUnlock.d.ts.map +1 -1
  113. package/dist/types/api/getFeatures.d.ts.map +1 -1
  114. package/dist/types/api/getOnekeyFeatures.d.ts.map +1 -1
  115. package/dist/types/api/getPassphraseState.d.ts.map +1 -1
  116. package/dist/types/api/index.d.ts +13 -15
  117. package/dist/types/api/index.d.ts.map +1 -1
  118. package/dist/types/api/openWalletSession.d.ts +41 -0
  119. package/dist/types/api/openWalletSession.d.ts.map +1 -0
  120. package/dist/types/api/protocolV2.d.ts +6 -11
  121. package/dist/types/api/protocolV2.d.ts.map +1 -1
  122. package/dist/types/device.d.ts +2 -9
  123. package/dist/types/device.d.ts.map +1 -1
  124. package/dist/utils/assets.d.ts +2 -1
  125. package/dist/utils/assets.d.ts.map +1 -1
  126. package/dist/utils/deviceFeaturesCompat.d.ts +13 -0
  127. package/dist/utils/deviceFeaturesCompat.d.ts.map +1 -0
  128. package/dist/utils/deviceFeaturesUtils.d.ts +11 -1
  129. package/dist/utils/deviceFeaturesUtils.d.ts.map +1 -1
  130. package/dist/utils/deviceInfoUtils.d.ts +9 -8
  131. package/dist/utils/deviceInfoUtils.d.ts.map +1 -1
  132. package/dist/utils/deviceSettings.d.ts +2 -0
  133. package/dist/utils/deviceSettings.d.ts.map +1 -1
  134. package/dist/utils/deviceVersionUtils.d.ts +6 -5
  135. package/dist/utils/deviceVersionUtils.d.ts.map +1 -1
  136. package/dist/utils/index.d.ts +2 -2
  137. package/dist/utils/index.d.ts.map +1 -1
  138. package/dist/utils/networkUtils.d.ts +9 -1
  139. package/dist/utils/networkUtils.d.ts.map +1 -1
  140. package/dist/utils/patch.d.ts +1 -1
  141. package/dist/utils/patch.d.ts.map +1 -1
  142. package/dist/utils/pro2Wallpaper.d.ts.map +1 -1
  143. package/package.json +4 -4
  144. package/src/api/BaseMethod.ts +17 -10
  145. package/src/api/CheckBootloaderRelease.ts +1 -2
  146. package/src/api/CheckFirmwareRelease.ts +1 -2
  147. package/src/api/ClearSessionCache.ts +0 -4
  148. package/src/api/DirList.ts +5 -3
  149. package/src/api/DirMake.ts +3 -3
  150. package/src/api/DirRemove.ts +3 -3
  151. package/src/api/FileDelete.ts +3 -3
  152. package/src/api/FileRead.ts +9 -6
  153. package/src/api/FileWrite.ts +3 -3
  154. package/src/api/FirmwareUpdate.ts +4 -4
  155. package/src/api/FirmwareUpdateV2.ts +133 -45
  156. package/src/api/FirmwareUpdateV3.ts +3 -5
  157. package/src/api/FirmwareUpdateV4.ts +192 -154
  158. package/src/api/GetPassphraseState.ts +10 -16
  159. package/src/api/OpenWalletSession.ts +221 -0
  160. package/src/api/PathInfo.ts +5 -3
  161. package/src/api/PromptWebDeviceAccess.ts +2 -3
  162. package/src/api/SearchDevices.ts +6 -2
  163. package/src/api/UploadPortfolio.ts +12 -3
  164. package/src/api/alephium/AlephiumSignTransaction.ts +2 -2
  165. package/src/api/allnetwork/AllNetworkGetAddressBase.ts +4 -8
  166. package/src/api/benfen/BenfenGetAddress.ts +1 -1
  167. package/src/api/btc/BTCGetPublicKey.ts +1 -1
  168. package/src/api/device/DeviceChangePin.ts +1 -0
  169. package/src/api/device/DeviceFullyUploadResource.ts +4 -5
  170. package/src/api/device/DeviceSettings.ts +93 -0
  171. package/src/api/device/DeviceUpdateBootloader.ts +1 -2
  172. package/src/api/device/DeviceWipe.ts +1 -0
  173. package/src/api/evm/EVMSignTypedData.ts +3 -5
  174. package/src/api/evm/legacyV1/getAddress.ts +2 -2
  175. package/src/api/evm/legacyV1/getPublicKey.ts +2 -2
  176. package/src/api/evm/legacyV1/signMessage.ts +2 -2
  177. package/src/api/evm/legacyV1/signTypedData.ts +2 -2
  178. package/src/api/evm/legacyV1/signTypedHash.ts +2 -2
  179. package/src/api/evm/legacyV1/verifyMessage.ts +2 -2
  180. package/src/api/firmware/FirmwareUpdateBaseMethod.ts +3 -3
  181. package/src/api/firmware/getBinary.ts +8 -3
  182. package/src/api/helpers/batchGetPublickeys.ts +2 -2
  183. package/src/api/helpers/filesystemValidation.ts +61 -0
  184. package/src/api/helpers/paramsValidator.ts +1 -1
  185. package/src/api/helpers/protocolV2FileWrite.ts +3 -2
  186. package/src/api/index.ts +9 -12
  187. package/src/api/nervos/NervosSignTransaction.ts +2 -2
  188. package/src/api/nexa/NexaSignTransaction.ts +1 -1
  189. package/src/api/protocol-v2/DeviceFactoryInfoGet.ts +1 -1
  190. package/src/api/protocol-v2/DeviceFactoryInfoSet.ts +1 -1
  191. package/src/api/protocol-v2/DeviceFirmwareUpdate.ts +4 -4
  192. package/src/api/protocol-v2/DeviceGetFirmwareUpdateStatus.ts +6 -5
  193. package/src/api/protocol-v2/DeviceInfoGet.ts +4 -4
  194. package/src/api/protocol-v2/DeviceReboot.ts +1 -1
  195. package/src/api/protocol-v2/DeviceSettingsPageShow.ts +11 -8
  196. package/src/api/protocol-v2/DeviceSettingsSet.ts +4 -11
  197. package/src/api/protocol-v2/FilesystemFormat.ts +1 -1
  198. package/src/api/protocol-v2/FilesystemPermissionFix.ts +1 -1
  199. package/src/api/protocol-v2/Ping.ts +1 -1
  200. package/src/api/protocol-v2/ProtocolInfoRequest.ts +1 -1
  201. package/src/api/utils.ts +1 -3
  202. package/src/core/RequestQueue.ts +107 -6
  203. package/src/core/index.ts +91 -46
  204. package/src/data/messages/messages-protocol-v2.json +25 -79
  205. package/src/data-manager/DataManager.ts +6 -6
  206. package/src/device/Device.ts +186 -102
  207. package/src/device/DeviceCommands.ts +51 -21
  208. package/src/device/DeviceFeaturesState.ts +4 -4
  209. package/src/device/DevicePool.ts +17 -3
  210. package/src/device/DeviceStateMapper.ts +13 -29
  211. package/src/device/DeviceStateProjector.ts +11 -8
  212. package/src/device/DeviceStateStore.ts +11 -52
  213. package/src/device/DeviceWalletSessionStore.ts +31 -4
  214. package/src/device/cloneDeviceState.ts +39 -0
  215. package/src/device/deviceIdentity.ts +2 -2
  216. package/src/deviceProfile/buildDeviceFeatures.ts +29 -88
  217. package/src/events/logBlockEvent.ts +8 -1
  218. package/src/inject.ts +14 -24
  219. package/src/protocols/protocol-v2/deviceSession.ts +24 -0
  220. package/src/protocols/protocol-v2/features.ts +37 -49
  221. package/src/protocols/protocol-v2/firmware.ts +1 -1
  222. package/src/protocols/protocol-v2/index.ts +2 -3
  223. package/src/protocols/protocol-v2/settingsUnlockPolicy.ts +61 -0
  224. package/src/protocols/protocol-v2/uiInteraction.ts +4 -3
  225. package/src/protocols/protocol-v2/walletSession.ts +57 -146
  226. package/src/types/api/checkAllFirmwareRelease.ts +1 -2
  227. package/src/types/api/deviceSettings.ts +1 -0
  228. package/src/types/api/deviceUnlock.ts +1 -1
  229. package/src/types/api/firmwareUpdate.ts +5 -5
  230. package/src/types/api/getDeviceState.ts +1 -1
  231. package/src/types/api/getFeatures.ts +3 -0
  232. package/src/types/api/getOnekeyFeatures.ts +3 -0
  233. package/src/types/api/getPassphraseState.ts +6 -0
  234. package/src/types/api/index.ts +16 -23
  235. package/src/types/api/openWalletSession.ts +64 -0
  236. package/src/types/api/protocolV2.ts +36 -18
  237. package/src/types/device.ts +20 -14
  238. package/src/types/params.ts +1 -1
  239. package/src/types/settings.ts +8 -8
  240. package/src/utils/assets.ts +4 -1
  241. package/src/utils/deviceFeaturesCompat.ts +173 -0
  242. package/src/utils/deviceFeaturesUtils.ts +9 -8
  243. package/src/utils/deviceInfoUtils.ts +26 -64
  244. package/src/utils/deviceSettings.ts +18 -11
  245. package/src/utils/deviceVersionUtils.ts +25 -44
  246. package/src/utils/findDefectiveBatchDevice.ts +3 -3
  247. package/src/utils/index.ts +2 -5
  248. package/src/utils/networkUtils.ts +270 -14
  249. package/src/utils/pro2Wallpaper.ts +11 -13
  250. package/src/utils/tracing.ts +2 -2
  251. package/dist/api/internal.d.ts +0 -4
  252. package/dist/api/internal.d.ts.map +0 -1
  253. package/dist/api/protocol-v2/DeviceSessionOpen.d.ts +0 -28
  254. package/dist/api/protocol-v2/DeviceSessionOpen.d.ts.map +0 -1
  255. package/src/api/internal.ts +0 -9
  256. package/src/api/protocol-v2/DeviceSessionOpen.ts +0 -100
@@ -16,8 +16,8 @@ export const signTypedData = async ({
16
16
  }) => {
17
17
  const { primaryType }: EthereumSignTypedDataMessage<EthereumSignTypedDataTypes> = data;
18
18
 
19
- // legacy EthereumSignTypedData 的生成类型没有 chain_id 字段,但旧固件按 OneKey 扩展
20
- // 接受该字段;通过预先声明的对象(非 fresh literal)携带额外字段,保持原有运行时行为。
19
+ // The generated legacy type omits chain_id, but old firmware accepts the OneKey
20
+ // extension. A non-fresh object preserves that runtime field without a type cast.
21
21
  const message = {
22
22
  address_n: addressN,
23
23
  primary_type: primaryType as string,
@@ -38,8 +38,8 @@ export const signTypedHash = async ({
38
38
  }
39
39
  }
40
40
 
41
- // legacy EthereumSignTypedHash 的生成类型没有 chain_id 字段,但旧固件按 OneKey 扩展
42
- // 接受该字段;通过预先声明的对象(非 fresh literal)携带额外字段,保持原有运行时行为。
41
+ // The generated legacy type omits chain_id, but old firmware accepts the OneKey
42
+ // extension. A non-fresh object preserves that runtime field without a type cast.
43
43
  const message = {
44
44
  address_n: addressN,
45
45
  domain_separator_hash: domainHash ?? '',
@@ -7,8 +7,8 @@ export default async function ({
7
7
  typedCall: TypedCall;
8
8
  params: EthereumVerifyMessageOneKey;
9
9
  }): Promise<Success> {
10
- // legacy EthereumVerifyMessage 的生成类型没有 chain_id 字段,但旧固件按 OneKey 扩展
11
- // 接受该字段;通过预先声明的对象(非 fresh literal)携带额外字段,保持原有运行时行为。
10
+ // The generated legacy type omits chain_id, but old firmware accepts the OneKey
11
+ // extension. A non-fresh object preserves that runtime field without a type cast.
12
12
  const message = {
13
13
  signature: params.signature,
14
14
  message: params.message,
@@ -8,7 +8,7 @@ import {
8
8
 
9
9
  import { FirmwareUpdateTipMessage, UI_REQUEST, createUiMessage } from '../../events/ui-request';
10
10
  import { DevicePool } from '../../device/DevicePool';
11
- import { LoggerNames, getDeviceUUID, getLogger, wait } from '../../utils';
11
+ import { LoggerNames, getLogger, wait } from '../../utils';
12
12
  import { DeviceModelToTypes } from '../../types';
13
13
  import { DataManager } from '../../data-manager';
14
14
  import { BaseMethod } from '../BaseMethod';
@@ -251,7 +251,7 @@ export class FirmwareUpdateBaseMethod<Params> extends BaseMethod<Params> {
251
251
  async enterBootloaderMode() {
252
252
  const typedCall = this.device.getCommands().typedCall.bind(this.device.getCommands());
253
253
  if (this.device.features && !this.device.isBootloader()) {
254
- const uuid = getDeviceUUID(this.device.features);
254
+ const serialNo = this.device.getCurrentSerialNo();
255
255
  const deviceType = this.device.getCurrentDeviceType();
256
256
  // auto go to bootloader mode
257
257
  try {
@@ -266,7 +266,7 @@ export class FirmwareUpdateBaseMethod<Params> extends BaseMethod<Params> {
266
266
 
267
267
  // force clean classic device cache so that the device can initialize again
268
268
  if (DeviceModelToTypes.model_classic.includes(deviceType)) {
269
- DevicePool.clearDeviceCache(uuid);
269
+ DevicePool.clearDeviceCache(serialNo);
270
270
  }
271
271
  delete DevicePool.devicesCache[''];
272
272
  await this.checkPromise?.promise;
@@ -7,9 +7,12 @@ import { findLatestRelease } from '../../utils/release';
7
7
  import { getFirmwareUpdateField } from '../../utils/deviceFeaturesUtils';
8
8
 
9
9
  import type { Features } from '../../types';
10
+ import type { HttpRequestOptions } from '../../utils/networkUtils';
10
11
  import type { EFirmwareType } from '@onekeyfe/hd-shared';
11
12
  import type { IFirmwareField } from '../../data-manager/DataManager';
12
13
 
14
+ export type FirmwareBinary = ArrayBuffer | Buffer;
15
+
13
16
  export interface GetInfoProps {
14
17
  features: Features;
15
18
  updateType: 'firmware' | 'ble';
@@ -20,6 +23,7 @@ export interface GetInfoProps {
20
23
 
21
24
  interface GetBinaryProps extends GetInfoProps {
22
25
  version?: number[];
26
+ requestOptions?: HttpRequestOptions;
23
27
  }
24
28
 
25
29
  export const getBinary = async ({
@@ -28,6 +32,7 @@ export const getBinary = async ({
28
32
  version,
29
33
  isUpdateBootloader,
30
34
  firmwareType,
35
+ requestOptions,
31
36
  }: GetBinaryProps) => {
32
37
  const releaseInfo = getInfo({
33
38
  features,
@@ -55,9 +60,9 @@ export const getBinary = async ({
55
60
  : isUpdateBootloader
56
61
  ? releaseInfo.bootloaderResource
57
62
  : releaseInfo.url;
58
- let fw;
63
+ let fw: FirmwareBinary;
59
64
  try {
60
- fw = await httpRequest(url, 'binary');
65
+ fw = await httpRequest(url, 'binary', requestOptions);
61
66
  } catch {
62
67
  throw ERRORS.TypedError(HardwareErrorCode.RuntimeError, 'Method_FirmwareUpdate_DownloadFailed');
63
68
  }
@@ -69,7 +74,7 @@ export const getBinary = async ({
69
74
  };
70
75
 
71
76
  export const getSysResourceBinary = async (url: string) => {
72
- let fw;
77
+ let fw: FirmwareBinary;
73
78
  try {
74
79
  fw = await httpRequest(url, 'binary');
75
80
  } catch {
@@ -27,8 +27,8 @@ export function supportBatchPublicKeyByDevice(
27
27
  const currentVersion = device.getCurrentFirmwareVersionString() ?? '0.0.0';
28
28
  const deviceType = device.getCurrentDeviceType();
29
29
 
30
- // Pro2 (Protocol V2) 版本线独立于 Pro 系列,固件从首个版本即支持 batch / include_node,
31
- // 不能套用下面 Pro 系列的 4.x 门槛。
30
+ // Pro2 has an independent version line and supports batch/include_node from its first
31
+ // firmware version, so the Protocol V1 Pro 4.x threshold does not apply.
32
32
  if (device.isProtocolV2() || deviceType === EDeviceType.Pro2) {
33
33
  return true;
34
34
  }
@@ -10,6 +10,67 @@ export function validateNonEmptyString(value: unknown, name: string): string {
10
10
  return value;
11
11
  }
12
12
 
13
+ const PROTOCOL_V2_FILESYSTEM_VOLUMES = new Set(['vol0', 'vol1']);
14
+ // Bootloader and romloader reserve 128 bytes including the terminating NUL.
15
+ const MAX_PROTOCOL_V2_FILESYSTEM_PATH_BYTES = 127;
16
+
17
+ function getUtf8ByteLength(value: string) {
18
+ return Array.from(value).reduce((length, character) => {
19
+ const codePoint = character.codePointAt(0) ?? 0;
20
+ if (codePoint <= 0x7f) return length + 1;
21
+ if (codePoint <= 0x7ff) return length + 2;
22
+ if (codePoint <= 0xffff) return length + 3;
23
+ return length + 4;
24
+ }, 0);
25
+ }
26
+
27
+ export function validateProtocolV2FilesystemPath(
28
+ value: unknown,
29
+ name: string,
30
+ options: { allowVolumeRoot?: boolean } = {}
31
+ ): string {
32
+ const rawPath = validateNonEmptyString(value, name).trim();
33
+ const containsUnsupportedCharacter = Array.from(rawPath).some(character => {
34
+ const codePoint = character.charCodeAt(0);
35
+ return codePoint <= 0x1f || codePoint === 0x7f || character === '\\';
36
+ });
37
+
38
+ if (containsUnsupportedCharacter) {
39
+ throw invalidParameter(`Parameter [${name}] contains unsupported path characters.`);
40
+ }
41
+
42
+ const match = /^([a-zA-Z0-9]+):(.*)$/.exec(rawPath);
43
+ if (!match) {
44
+ throw invalidParameter(
45
+ `Parameter [${name}] must use a supported Protocol V2 filesystem volume.`
46
+ );
47
+ }
48
+
49
+ const volume = match[1].toLowerCase();
50
+ if (!PROTOCOL_V2_FILESYSTEM_VOLUMES.has(volume)) {
51
+ throw invalidParameter(`Parameter [${name}] uses an unsupported filesystem volume.`);
52
+ }
53
+
54
+ const rawSuffix = match[2];
55
+ if (rawSuffix.length === 0) {
56
+ if (options.allowVolumeRoot) return `${volume}:`;
57
+ throw invalidParameter(`Parameter [${name}] must identify a filesystem entry.`);
58
+ }
59
+
60
+ const suffix = rawSuffix.startsWith('/') ? rawSuffix : `/${rawSuffix}`;
61
+ const segments = suffix.slice(1).split('/');
62
+ if (segments.some(segment => segment.length === 0 || segment === '.' || segment === '..')) {
63
+ throw invalidParameter(`Parameter [${name}] contains an invalid path segment.`);
64
+ }
65
+
66
+ const canonicalPath = `${volume}:${rawSuffix.startsWith('/') ? '/' : ''}${segments.join('/')}`;
67
+ if (getUtf8ByteLength(canonicalPath) > MAX_PROTOCOL_V2_FILESYSTEM_PATH_BYTES) {
68
+ throw invalidParameter(`Parameter [${name}] exceeds the maximum filesystem path length.`);
69
+ }
70
+
71
+ return canonicalPath;
72
+ }
73
+
13
74
  export function validateNonNegativeInteger(
14
75
  value: unknown,
15
76
  name: string,
@@ -20,7 +20,7 @@ export type SchemaParam = {
20
20
  allowNegative?: boolean;
21
21
  };
22
22
 
23
- const invalidParameter = (message: string) =>
23
+ export const invalidParameter = (message: string) =>
24
24
  ERRORS.TypedError(HardwareErrorCode.CallMethodInvalidParameter, message);
25
25
 
26
26
  const invalidResponse = (message: string) =>
@@ -136,7 +136,8 @@ export async function writeProtocolV2File(options: ProtocolV2FileWriteOptions) {
136
136
  const maxChunkRetries = Math.max(Math.floor(options.maxChunkRetries ?? 0), 0);
137
137
  let retryCount = 0;
138
138
  let response;
139
- while (true) {
139
+ let isWritePending = true;
140
+ while (isWritePending) {
140
141
  try {
141
142
  response = await options.commands.typedCall(
142
143
  'FilesystemFileWrite',
@@ -144,7 +145,7 @@ export async function writeProtocolV2File(options: ProtocolV2FileWriteOptions) {
144
145
  request,
145
146
  { timeoutMs: options.timeoutMs }
146
147
  );
147
- break;
148
+ isWritePending = false;
148
149
  } catch (error) {
149
150
  if (retryCount >= maxChunkRetries || !isRetryableFileWriteTimeout(error)) throw error;
150
151
  retryCount += 1;
package/src/api/index.ts CHANGED
@@ -6,6 +6,7 @@ export { default as getFeatures } from './GetFeatures';
6
6
  export { default as getDeviceState } from './GetDeviceState';
7
7
  export { default as getOnekeyFeatures } from './GetOnekeyFeatures';
8
8
  export { default as getPassphraseState } from './GetPassphraseState';
9
+ export { default as openWalletSession } from './OpenWalletSession';
9
10
  export { default as getLogs } from './GetLogs';
10
11
  export { default as clearSessionCache } from './ClearSessionCache';
11
12
  export { default as checkFirmwareRelease } from './CheckFirmwareRelease';
@@ -43,19 +44,22 @@ export { default as firmwareUpdateV3 } from './FirmwareUpdateV3';
43
44
  export { default as firmwareUpdateV4 } from './FirmwareUpdateV4';
44
45
  export { default as promptWebDeviceAccess } from './PromptWebDeviceAccess';
45
46
 
46
- // File system & device control API (Protocol V2 only)
47
- export { default as protocolInfoRequest } from './protocol-v2/ProtocolInfoRequest';
48
- export { default as ping } from './protocol-v2/Ping';
47
+ // Pro2 business API
49
48
  export { default as deviceReboot } from './protocol-v2/DeviceReboot';
50
49
  export { default as deviceGetOnboardingStatus } from './protocol-v2/DeviceGetOnboardingStatus';
51
- export { default as deviceSessionOpen } from './protocol-v2/DeviceSessionOpen';
50
+ export { default as deviceUploadWallpaper } from './protocol-v2/DeviceUploadWallpaper';
51
+ // Protocol V2 development APIs. These remain public while Pro2 integration is in development.
52
+ export { default as deviceInfoGet } from './protocol-v2/DeviceInfoGet';
53
+ export { default as deviceStatusGet } from './protocol-v2/DeviceStatusGet';
54
+ export { default as deviceSettingsGet } from './protocol-v2/DeviceSettingsGet';
55
+ export { default as protocolInfoRequest } from './protocol-v2/ProtocolInfoRequest';
56
+ export { default as ping } from './protocol-v2/Ping';
52
57
  export { default as deviceFirmwareUpdate } from './protocol-v2/DeviceFirmwareUpdate';
53
58
  export { default as deviceGetFirmwareUpdateStatus } from './protocol-v2/DeviceGetFirmwareUpdateStatus';
54
59
  export { default as deviceFactoryInfoSet } from './protocol-v2/DeviceFactoryInfoSet';
55
60
  export { default as deviceFactoryInfoGet } from './protocol-v2/DeviceFactoryInfoGet';
56
61
  export { default as deviceSettingsSet } from './protocol-v2/DeviceSettingsSet';
57
62
  export { default as deviceSettingsPageShow } from './protocol-v2/DeviceSettingsPageShow';
58
- export { default as deviceUploadWallpaper } from './protocol-v2/DeviceUploadWallpaper';
59
63
  export { default as filesystemPermissionFix } from './protocol-v2/FilesystemPermissionFix';
60
64
  export { default as filesystemFormat } from './protocol-v2/FilesystemFormat';
61
65
  export { default as fileRead } from './FileRead';
@@ -65,14 +69,7 @@ export { default as dirList } from './DirList';
65
69
  export { default as dirMake } from './DirMake';
66
70
  export { default as dirRemove } from './DirRemove';
67
71
  export { default as pathInfo } from './PathInfo';
68
- export { default as filesystemFileRead } from './FileRead';
69
- export { default as filesystemFileWrite } from './FileWrite';
70
72
  export { default as uploadPortfolio } from './UploadPortfolio';
71
- export { default as filesystemFileDelete } from './FileDelete';
72
- export { default as filesystemDirList } from './DirList';
73
- export { default as filesystemDirMake } from './DirMake';
74
- export { default as filesystemDirRemove } from './DirRemove';
75
- export { default as filesystemPathInfoQuery } from './PathInfo';
76
73
 
77
74
  export { default as cipherKeyValue } from './CipherKeyValue';
78
75
 
@@ -67,8 +67,8 @@ export default class NervosSignTransaction extends BaseMethod<NervosSignTx> {
67
67
  res: TypedResponseMessage<'NervosSignedTx'> | TypedResponseMessage<'NervosTxRequest'>,
68
68
  data: Buffer,
69
69
  offset = 0
70
- // 设备可能在最后一个 NervosTxRequest(无 data_length)里返回签名,
71
- // 该消息没有 address 字段,返回类型如实声明为联合类型
70
+ // The final NervosTxRequest may return a signature without data_length or address,
71
+ // so the result accurately uses a union type.
72
72
  ): Promise<NervosSignedTx | (NervosTxRequest & { path: string })> => {
73
73
  if (res.type === 'NervosSignedTx') {
74
74
  if (!res?.message?.signature) {
@@ -73,7 +73,7 @@ export default class NexaSignTransaction extends BaseMethod<NexaSignTransactionP
73
73
  const nextIndex = res.message.request_index;
74
74
  const input = this.params.inputs[nextIndex];
75
75
  const response = await typedCall('NexaTxInputAck', ['NexaTxInputRequest', 'NexaSignedTx'], {
76
- // path 为字符串形式,归一为 address_n 数组(与 run() 中首个 input 的处理一致)
76
+ // Normalize a string path to address_n, matching the first input handled by run().
77
77
  address_n: validatePath(input.path, 3),
78
78
  raw_message: input.message,
79
79
  });
@@ -2,7 +2,7 @@ import { BaseMethod } from '../BaseMethod';
2
2
 
3
3
  export default class DeviceFactoryInfoGet extends BaseMethod {
4
4
  init() {
5
- // Protocol V2 (Pro2) 专属方法,core 调度层统一做非 V2 设备守卫
5
+ // Protocol V2 (Pro2) only; Core rejects non-V2 devices.
6
6
  this.requireProtocolV2 = true;
7
7
  this.skipForceUpdateCheck = true;
8
8
  this.useDevicePassphraseState = false;
@@ -4,7 +4,7 @@ import type { DeviceFactoryInfoSetParams } from './helpers';
4
4
 
5
5
  export default class DeviceFactoryInfoSet extends BaseMethod<DeviceFactoryInfoSetParams> {
6
6
  init() {
7
- // Protocol V2 (Pro2) 专属方法,core 调度层统一做非 V2 设备守卫
7
+ // Protocol V2 (Pro2) only; Core rejects non-V2 devices.
8
8
  this.requireProtocolV2 = true;
9
9
  this.skipForceUpdateCheck = true;
10
10
  this.useDevicePassphraseState = false;
@@ -13,7 +13,7 @@ import type { DeviceFirmwareUpdateParams } from './helpers';
13
13
 
14
14
  export default class DeviceFirmwareUpdate extends BaseMethod<DeviceFirmwareUpdateParams> {
15
15
  init() {
16
- // Protocol V2 (Pro2) 专属方法,core 调度层统一做非 V2 设备守卫
16
+ // Protocol V2 (Pro2) only; Core rejects non-V2 devices.
17
17
  this.requireProtocolV2 = true;
18
18
  this.skipForceUpdateCheck = true;
19
19
  this.useDevicePassphraseState = false;
@@ -48,12 +48,12 @@ export default class DeviceFirmwareUpdate extends BaseMethod<DeviceFirmwareUpdat
48
48
  },
49
49
  }
50
50
  );
51
- return Promise.resolve(res.message);
51
+ return res.message;
52
52
  } catch (error) {
53
53
  if (isProtocolV2DeviceDisconnectedError(error)) {
54
- return Promise.resolve({
54
+ return {
55
55
  message: 'Device firmware update started',
56
- });
56
+ };
57
57
  }
58
58
  throw error;
59
59
  }
@@ -24,18 +24,19 @@ function normalizeStatusFields(
24
24
  const normalized: DeviceFirmwareUpdateRecordFields = {};
25
25
  for (const field of DEVICE_FIRMWARE_UPDATE_STATUS_FIELDS) {
26
26
  const value = fields[field];
27
- if (value === undefined) continue;
28
- if (typeof value !== 'boolean') {
29
- throw invalidParameter(`Parameter [fields.${field}] must be a boolean.`);
27
+ if (value !== undefined) {
28
+ if (typeof value !== 'boolean') {
29
+ throw invalidParameter(`Parameter [fields.${field}] must be a boolean.`);
30
+ }
31
+ normalized[field] = value;
30
32
  }
31
- normalized[field] = value;
32
33
  }
33
34
  return normalized;
34
35
  }
35
36
 
36
37
  export default class DeviceGetFirmwareUpdateStatus extends BaseMethod<DeviceFirmwareUpdateStatusGetParams> {
37
38
  init() {
38
- // Protocol V2 (Pro2) 专属方法,core 调度层统一做非 V2 设备守卫
39
+ // Protocol V2 (Pro2) only; Core rejects non-V2 devices.
39
40
  this.requireProtocolV2 = true;
40
41
  this.skipForceUpdateCheck = true;
41
42
  this.useDevicePassphraseState = false;
@@ -100,17 +100,17 @@ function normalizeTypes(value: unknown): DeviceInfoGetTypes | undefined {
100
100
  }
101
101
 
102
102
  /**
103
- * 原生 DeviceInfoGetProtocol V2 only)。
103
+ * Raw DeviceInfoGet command for Protocol V2 only.
104
104
  *
105
- * SDK 内部按需构造 targets/types,并返回未加工的 DeviceInfo 消息。
106
- * command 不属于公共 CoreApi;业务接入统一使用 getDeviceState
105
+ * The SDK builds targets/types on demand and returns the raw DeviceInfo message.
106
+ * This command is internal; integrations should use getDeviceState.
107
107
  */
108
108
  export default class DeviceInfoGet extends BaseMethod<{
109
109
  targets: DeviceInfoGetTargets;
110
110
  types: DeviceInfoGetTypes;
111
111
  }> {
112
112
  init() {
113
- // Protocol V2 (Pro2) 专属方法,core 调度层统一做非 V2 设备守卫
113
+ // Protocol V2 (Pro2) only; Core rejects non-V2 devices.
114
114
  this.requireProtocolV2 = true;
115
115
  this.unlockPolicy = 'none';
116
116
  this.allowDeviceMode = [
@@ -5,7 +5,7 @@ import type { DeviceRebootParams } from './helpers';
5
5
 
6
6
  export default class DeviceReboot extends BaseMethod<DeviceRebootParams> {
7
7
  init() {
8
- // Protocol V2 (Pro2) 专属方法,core 调度层统一做非 V2 设备守卫
8
+ // Protocol V2 (Pro2) only; Core rejects non-V2 devices.
9
9
  this.requireProtocolV2 = true;
10
10
  this.skipForceUpdateCheck = true;
11
11
  this.useDevicePassphraseState = false;
@@ -2,6 +2,7 @@ import { DeviceSettingsPage } from '@onekeyfe/hd-transport';
2
2
 
3
3
  import { BaseMethod } from '../BaseMethod';
4
4
  import { invalidParameter } from '../helpers/filesystemValidation';
5
+ import { getProtocolV2SettingsBehavior } from '../../protocols/protocol-v2/settingsUnlockPolicy';
5
6
 
6
7
  export type SupportedDeviceSettingsPage = DeviceSettingsPage;
7
8
 
@@ -39,21 +40,18 @@ export default class DeviceSettingsPageShow extends BaseMethod<{
39
40
  }> {
40
41
  init() {
41
42
  this.requireProtocolV2 = true;
42
- this.unlockPolicy = 'retry-on-locked';
43
43
  this.skipForceUpdateCheck = true;
44
44
  this.useDevicePassphraseState = false;
45
45
  this.params = {
46
46
  page: normalizePage(this.payload.page),
47
47
  field_name: this.payload.field_name ?? this.payload.fieldName,
48
48
  };
49
- this.protocolV2UiInteraction = {
50
- request: 'button',
51
- source: 'method-lifecycle',
52
- reason: 'settings-page',
53
- completion: 'operation-completed',
54
- deviceOnly: true,
49
+ const behavior = getProtocolV2SettingsBehavior({
50
+ kind: 'page',
55
51
  page: this.params.page,
56
- };
52
+ });
53
+ this.unlockPolicy = behavior.unlockPolicy;
54
+ this.protocolV2UiInteraction = behavior.uiInteraction;
57
55
  }
58
56
 
59
57
  async run() {
@@ -62,6 +60,11 @@ export default class DeviceSettingsPageShow extends BaseMethod<{
62
60
  'Success',
63
61
  this.params
64
62
  );
63
+ if (this.params.page === DeviceSettingsPage.DevicePassphrase) {
64
+ await this.device.getDeviceState({ refreshSections: ['status'] });
65
+ } else if (this.params.page === DeviceSettingsPage.DeviceAirgap) {
66
+ await this.device.getDeviceState({ refreshSections: ['settings'] });
67
+ }
65
68
  return Promise.resolve(res.message);
66
69
  }
67
70
  }
@@ -1,5 +1,6 @@
1
1
  import { BaseMethod } from '../BaseMethod';
2
2
  import { mapDeviceSettingsToState } from '../../device/DeviceStateMapper';
3
+ import { getProtocolV2SettingsBehavior } from '../../protocols/protocol-v2/settingsUnlockPolicy';
3
4
  import { invalidParameter } from '../helpers/filesystemValidation';
4
5
 
5
6
  import type { DeviceSettings } from '@onekeyfe/hd-transport';
@@ -27,20 +28,12 @@ export default class DeviceSettingsSet extends BaseMethod<{
27
28
  }
28
29
 
29
30
  this.requireProtocolV2 = true;
30
- this.unlockPolicy = 'retry-on-locked';
31
+ const behavior = getProtocolV2SettingsBehavior({ kind: 'direct', settings: supported });
32
+ this.unlockPolicy = behavior.unlockPolicy;
31
33
  this.skipForceUpdateCheck = true;
32
34
  this.useDevicePassphraseState = false;
33
35
  this.params = { settings: supported };
34
- if (typeof supported.label === 'string') {
35
- this.protocolV2UiInteraction = {
36
- request: 'button',
37
- source: 'method-lifecycle',
38
- reason: 'device-management',
39
- completion: 'operation-completed',
40
- deviceOnly: true,
41
- operation: 'change-label',
42
- };
43
- }
36
+ this.protocolV2UiInteraction = behavior.uiInteraction;
44
37
  }
45
38
 
46
39
  async run() {
@@ -2,7 +2,7 @@ import { BaseMethod } from '../BaseMethod';
2
2
 
3
3
  export default class FilesystemFormat extends BaseMethod {
4
4
  init() {
5
- // Protocol V2 (Pro2) 专属方法,core 调度层统一做非 V2 设备守卫
5
+ // Protocol V2 (Pro2) only; Core rejects non-V2 devices.
6
6
  this.requireProtocolV2 = true;
7
7
  this.skipForceUpdateCheck = true;
8
8
  this.useDevicePassphraseState = false;
@@ -2,7 +2,7 @@ import { BaseMethod } from '../BaseMethod';
2
2
 
3
3
  export default class FilesystemPermissionFix extends BaseMethod {
4
4
  init() {
5
- // Protocol V2 (Pro2) 专属方法,core 调度层统一做非 V2 设备守卫
5
+ // Protocol V2 (Pro2) only; Core rejects non-V2 devices.
6
6
  this.requireProtocolV2 = true;
7
7
  this.skipForceUpdateCheck = true;
8
8
  this.useDevicePassphraseState = false;
@@ -2,7 +2,7 @@ import { BaseMethod } from '../BaseMethod';
2
2
 
3
3
  export default class Ping extends BaseMethod<{ message?: string }> {
4
4
  init() {
5
- // Protocol V2 (Pro2) 专属方法,core 调度层统一做非 V2 设备守卫
5
+ // Protocol V2 (Pro2) only; Core rejects non-V2 devices.
6
6
  this.requireProtocolV2 = true;
7
7
  this.skipForceUpdateCheck = true;
8
8
  this.useDevicePassphraseState = false;
@@ -2,7 +2,7 @@ import { BaseMethod } from '../BaseMethod';
2
2
 
3
3
  export default class ProtocolInfoRequest extends BaseMethod {
4
4
  init() {
5
- // Protocol V2 (Pro2) 专属方法,core 调度层统一做非 V2 设备守卫
5
+ // Protocol V2 (Pro2) only; Core rejects non-V2 devices.
6
6
  this.requireProtocolV2 = true;
7
7
  this.skipForceUpdateCheck = true;
8
8
  this.useDevicePassphraseState = false;
package/src/api/utils.ts CHANGED
@@ -1,7 +1,6 @@
1
1
  import { ERRORS, HardwareErrorCode } from '@onekeyfe/hd-shared';
2
2
 
3
3
  import * as ApiMethods from './index';
4
- import * as InternalApiMethods from './internal';
5
4
 
6
5
  import type { BaseMethod } from './BaseMethod';
7
6
  import type { IFrameCallMessage } from '../events';
@@ -9,7 +8,6 @@ import type { IFrameCallMessage } from '../events';
9
8
  type MethodConstructor = new (message: IFrameCallMessage & { id?: number }) => BaseMethod<any>;
10
9
 
11
10
  const publicMethodRegistry = ApiMethods as unknown as Record<string, MethodConstructor>;
12
- const internalMethodRegistry = InternalApiMethods as unknown as Record<string, MethodConstructor>;
13
11
 
14
12
  export function findMethod(message: IFrameCallMessage & { id?: number }): BaseMethod<any> {
15
13
  const { method } = message.payload;
@@ -17,7 +15,7 @@ export function findMethod(message: IFrameCallMessage & { id?: number }): BaseMe
17
15
  throw ERRORS.TypedError(HardwareErrorCode.CallMethodInvalidParameter, 'Method is not set');
18
16
  }
19
17
 
20
- const MethodConstructor = publicMethodRegistry[method] ?? internalMethodRegistry[method];
18
+ const MethodConstructor = publicMethodRegistry[method];
21
19
  if (MethodConstructor) {
22
20
  return new MethodConstructor(message);
23
21
  }