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

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 (406) hide show
  1. package/__tests__/AllNetworkGetAddressBase.tracing.test.ts +75 -0
  2. package/__tests__/DeviceCommands.test.ts +285 -0
  3. package/__tests__/DeviceEventRegistration.test.ts +43 -0
  4. package/__tests__/connectSettings.test.ts +19 -0
  5. package/__tests__/core-dispose.test.ts +34 -0
  6. package/__tests__/core-error-output.test.ts +39 -0
  7. package/__tests__/device-features-state.test.ts +78 -0
  8. package/__tests__/device-identity.test.ts +30 -0
  9. package/__tests__/device-lifecycle-events.test.ts +117 -0
  10. package/__tests__/device-pool-state.test.ts +132 -0
  11. package/__tests__/device-settings.test.ts +391 -0
  12. package/__tests__/device-state-contract.test.ts +27 -0
  13. package/__tests__/device-state-events.test.ts +162 -0
  14. package/__tests__/device-state-mapper.test.ts +241 -0
  15. package/__tests__/device-state-projector.test.ts +94 -0
  16. package/__tests__/device-state-store.test.ts +82 -0
  17. package/__tests__/device-utils.test.ts +106 -0
  18. package/__tests__/device-wallet-session-store.test.ts +213 -0
  19. package/__tests__/deviceFeaturesUtils.test.ts +39 -0
  20. package/__tests__/deviceSettings.test.ts +103 -0
  21. package/__tests__/evmLedgerLegacySafety.test.ts +10 -6
  22. package/__tests__/evmSignTypedData.test.ts +80 -0
  23. package/__tests__/filesystemValidation.test.ts +53 -0
  24. package/__tests__/firmware-update/firmware-update-v2-download-before-boot.test.ts +402 -0
  25. package/__tests__/get-device-state.test.ts +410 -0
  26. package/__tests__/homescreen.test.ts +24 -0
  27. package/__tests__/kaspaSignTransaction.test.ts +591 -0
  28. package/__tests__/logBlockEvent.test.ts +26 -0
  29. package/__tests__/networkUtils.test.ts +386 -0
  30. package/__tests__/open-wallet-session-error-response.test.ts +43 -0
  31. package/__tests__/open-wallet-session.test.ts +559 -0
  32. package/__tests__/preInitialize.test.ts +33 -0
  33. package/__tests__/pro2Wallpaper.test.ts +50 -0
  34. package/__tests__/protocol-v2-bootloader-mode.test.ts +37 -0
  35. package/__tests__/protocol-v2-firmware-targets.test.ts +19 -0
  36. package/__tests__/protocol-v2.test.ts +3954 -1191
  37. package/__tests__/protocolV2FileWrite.test.ts +92 -0
  38. package/__tests__/protocolV2UiInteraction.test.ts +266 -0
  39. package/__tests__/public-device-state-api.test.ts +257 -0
  40. package/__tests__/public-pro2-api-boundary.test.ts +110 -0
  41. package/__tests__/refresh-device-state.test.ts +101 -0
  42. package/__tests__/request-context-logging.test.ts +16 -0
  43. package/__tests__/search-devices.test.ts +136 -0
  44. package/dist/api/BaseMethod.d.ts +8 -0
  45. package/dist/api/BaseMethod.d.ts.map +1 -1
  46. package/dist/api/CheckBootloaderRelease.d.ts.map +1 -1
  47. package/dist/api/CheckFirmwareRelease.d.ts.map +1 -1
  48. package/dist/api/ClearSessionCache.d.ts +9 -0
  49. package/dist/api/ClearSessionCache.d.ts.map +1 -0
  50. package/dist/api/DirList.d.ts.map +1 -1
  51. package/dist/api/FileRead.d.ts.map +1 -1
  52. package/dist/api/FileWrite.d.ts +1 -0
  53. package/dist/api/FileWrite.d.ts.map +1 -1
  54. package/dist/api/FirmwareUpdateV2.d.ts +2 -2
  55. package/dist/api/FirmwareUpdateV2.d.ts.map +1 -1
  56. package/dist/api/FirmwareUpdateV3.d.ts.map +1 -1
  57. package/dist/api/FirmwareUpdateV4.d.ts +25 -5
  58. package/dist/api/FirmwareUpdateV4.d.ts.map +1 -1
  59. package/dist/api/GetDeviceState.d.ts +7 -0
  60. package/dist/api/GetDeviceState.d.ts.map +1 -0
  61. package/dist/api/GetFeatures.d.ts +1 -1
  62. package/dist/api/GetFeatures.d.ts.map +1 -1
  63. package/dist/api/GetOnekeyFeatures.d.ts.map +1 -1
  64. package/dist/api/GetPassphraseState.d.ts +1 -6
  65. package/dist/api/GetPassphraseState.d.ts.map +1 -1
  66. package/dist/api/OpenWalletSession.d.ts +14 -0
  67. package/dist/api/OpenWalletSession.d.ts.map +1 -0
  68. package/dist/api/PathInfo.d.ts.map +1 -1
  69. package/dist/api/PromptWebDeviceAccess.d.ts.map +1 -1
  70. package/dist/api/SearchDevices.d.ts +3 -0
  71. package/dist/api/SearchDevices.d.ts.map +1 -1
  72. package/dist/api/UploadPortfolio.d.ts +17 -0
  73. package/dist/api/UploadPortfolio.d.ts.map +1 -0
  74. package/dist/api/allnetwork/AllNetworkGetAddressBase.d.ts.map +1 -1
  75. package/dist/api/device/DeviceCancel.d.ts.map +1 -1
  76. package/dist/api/device/DeviceChangePin.d.ts.map +1 -1
  77. package/dist/api/device/DeviceFullyUploadResource.d.ts +1 -2
  78. package/dist/api/device/DeviceFullyUploadResource.d.ts.map +1 -1
  79. package/dist/api/device/DeviceLock.d.ts.map +1 -1
  80. package/dist/api/device/DeviceRebootToBoardloader.d.ts.map +1 -1
  81. package/dist/api/device/DeviceRebootToBootloader.d.ts.map +1 -1
  82. package/dist/api/device/DeviceSettings.d.ts.map +1 -1
  83. package/dist/api/device/DeviceUnlock.d.ts +1 -1
  84. package/dist/api/device/DeviceUnlock.d.ts.map +1 -1
  85. package/dist/api/device/DeviceUpdateBootloader.d.ts.map +1 -1
  86. package/dist/api/device/DeviceWipe.d.ts.map +1 -1
  87. package/dist/api/evm/EVMSignTypedData.d.ts.map +1 -1
  88. package/dist/api/firmware/FirmwareUpdateBaseMethod.d.ts +1 -0
  89. package/dist/api/firmware/FirmwareUpdateBaseMethod.d.ts.map +1 -1
  90. package/dist/api/firmware/getBinary.d.ts +11 -3
  91. package/dist/api/firmware/getBinary.d.ts.map +1 -1
  92. package/dist/api/firmware/progressThrottle.d.ts +3 -0
  93. package/dist/api/firmware/progressThrottle.d.ts.map +1 -0
  94. package/dist/api/helpers/filesystemValidation.d.ts +3 -0
  95. package/dist/api/helpers/filesystemValidation.d.ts.map +1 -1
  96. package/dist/api/helpers/paramsValidator.d.ts +1 -0
  97. package/dist/api/helpers/paramsValidator.d.ts.map +1 -1
  98. package/dist/api/helpers/protocolV2FileWrite.d.ts +33 -0
  99. package/dist/api/helpers/protocolV2FileWrite.d.ts.map +1 -0
  100. package/dist/api/index.d.ts +12 -19
  101. package/dist/api/index.d.ts.map +1 -1
  102. package/dist/api/kaspa/KaspaSignTransaction.d.ts +5 -1
  103. package/dist/api/kaspa/KaspaSignTransaction.d.ts.map +1 -1
  104. package/dist/api/kaspa/helpers/TransferSerialize.d.ts.map +1 -1
  105. package/dist/api/protocol-v2/DeviceFactoryInfoGet.d.ts +6 -0
  106. package/dist/api/protocol-v2/DeviceFactoryInfoGet.d.ts.map +1 -0
  107. package/dist/api/protocol-v2/DeviceFactoryInfoSet.d.ts +7 -0
  108. package/dist/api/protocol-v2/DeviceFactoryInfoSet.d.ts.map +1 -0
  109. package/dist/api/protocol-v2/DeviceFirmwareUpdate.d.ts +1 -1
  110. package/dist/api/protocol-v2/DeviceFirmwareUpdate.d.ts.map +1 -1
  111. package/dist/api/protocol-v2/DeviceGetFirmwareUpdateStatus.d.ts +3 -2
  112. package/dist/api/protocol-v2/DeviceGetFirmwareUpdateStatus.d.ts.map +1 -1
  113. package/dist/api/protocol-v2/DeviceGetOnboardingStatus.d.ts +1 -1
  114. package/dist/api/protocol-v2/DeviceGetOnboardingStatus.d.ts.map +1 -1
  115. package/dist/api/protocol-v2/DeviceInfoGet.d.ts +28 -0
  116. package/dist/api/protocol-v2/DeviceInfoGet.d.ts.map +1 -0
  117. package/dist/api/protocol-v2/DeviceReboot.d.ts.map +1 -1
  118. package/dist/api/protocol-v2/DeviceStatusGet.d.ts +6 -0
  119. package/dist/api/protocol-v2/DeviceStatusGet.d.ts.map +1 -0
  120. package/dist/api/protocol-v2/DeviceUploadWallpaper.d.ts +26 -0
  121. package/dist/api/protocol-v2/DeviceUploadWallpaper.d.ts.map +1 -0
  122. package/dist/api/protocol-v2/FilesystemFormat.d.ts.map +1 -1
  123. package/dist/api/protocol-v2/{FilesystemFixPermission.d.ts → FilesystemPermissionFix.d.ts} +2 -2
  124. package/dist/api/protocol-v2/FilesystemPermissionFix.d.ts.map +1 -0
  125. package/dist/api/protocol-v2/ProtocolInfoRequest.d.ts +6 -0
  126. package/dist/api/protocol-v2/ProtocolInfoRequest.d.ts.map +1 -0
  127. package/dist/api/protocol-v2/helpers.d.ts +27 -19
  128. package/dist/api/protocol-v2/helpers.d.ts.map +1 -1
  129. package/dist/api/ton/TonSignData.d.ts +1 -5
  130. package/dist/api/ton/TonSignData.d.ts.map +1 -1
  131. package/dist/api/utils.d.ts +2 -1
  132. package/dist/api/utils.d.ts.map +1 -1
  133. package/dist/constants/index.d.ts +2 -1
  134. package/dist/constants/index.d.ts.map +1 -1
  135. package/dist/core/RequestQueue.d.ts.map +1 -1
  136. package/dist/core/deviceEventRegistration.d.ts +11 -0
  137. package/dist/core/deviceEventRegistration.d.ts.map +1 -0
  138. package/dist/core/index.d.ts +3 -1
  139. package/dist/core/index.d.ts.map +1 -1
  140. package/dist/data-manager/DataManager.d.ts +1 -1
  141. package/dist/data-manager/DataManager.d.ts.map +1 -1
  142. package/dist/data-manager/connectSettings.d.ts.map +1 -1
  143. package/dist/device/Device.d.ts +35 -11
  144. package/dist/device/Device.d.ts.map +1 -1
  145. package/dist/device/DeviceCommands.d.ts +8 -6
  146. package/dist/device/DeviceCommands.d.ts.map +1 -1
  147. package/dist/device/DeviceFeaturesState.d.ts +3 -0
  148. package/dist/device/DeviceFeaturesState.d.ts.map +1 -0
  149. package/dist/device/DevicePool.d.ts +4 -2
  150. package/dist/device/DevicePool.d.ts.map +1 -1
  151. package/dist/device/DeviceStateMapper.d.ts +13 -0
  152. package/dist/device/DeviceStateMapper.d.ts.map +1 -0
  153. package/dist/device/DeviceStateProjector.d.ts +7 -0
  154. package/dist/device/DeviceStateProjector.d.ts.map +1 -0
  155. package/dist/device/DeviceStateStore.d.ts +21 -0
  156. package/dist/device/DeviceStateStore.d.ts.map +1 -0
  157. package/dist/device/DeviceWalletSessionStore.d.ts +20 -0
  158. package/dist/device/DeviceWalletSessionStore.d.ts.map +1 -0
  159. package/dist/device/cloneDeviceState.d.ts +2 -0
  160. package/dist/device/cloneDeviceState.d.ts.map +1 -0
  161. package/dist/device/deviceIdentity.d.ts +5 -0
  162. package/dist/device/deviceIdentity.d.ts.map +1 -0
  163. package/dist/deviceProfile/buildDeviceFeatures.d.ts +9 -3
  164. package/dist/deviceProfile/buildDeviceFeatures.d.ts.map +1 -1
  165. package/dist/deviceProfile/index.d.ts +0 -1
  166. package/dist/deviceProfile/index.d.ts.map +1 -1
  167. package/dist/events/device.d.ts +11 -2
  168. package/dist/events/device.d.ts.map +1 -1
  169. package/dist/events/logBlockEvent.d.ts.map +1 -1
  170. package/dist/events/ui-request.d.ts +18 -2
  171. package/dist/events/ui-request.d.ts.map +1 -1
  172. package/dist/index.d.ts +1361 -609
  173. package/dist/index.js +5898 -2860
  174. package/dist/inject.d.ts.map +1 -1
  175. package/dist/protocols/protocol-v2/deviceSession.d.ts +7 -0
  176. package/dist/protocols/protocol-v2/deviceSession.d.ts.map +1 -0
  177. package/dist/protocols/protocol-v2/features.d.ts +23 -28
  178. package/dist/protocols/protocol-v2/features.d.ts.map +1 -1
  179. package/dist/protocols/protocol-v2/firmware.d.ts +11 -9
  180. package/dist/protocols/protocol-v2/firmware.d.ts.map +1 -1
  181. package/dist/protocols/protocol-v2/index.d.ts +3 -2
  182. package/dist/protocols/protocol-v2/index.d.ts.map +1 -1
  183. package/dist/protocols/protocol-v2/lockedError.d.ts +2 -0
  184. package/dist/protocols/protocol-v2/lockedError.d.ts.map +1 -0
  185. package/dist/protocols/protocol-v2/settingsUnlockPolicy.d.ts +16 -0
  186. package/dist/protocols/protocol-v2/settingsUnlockPolicy.d.ts.map +1 -0
  187. package/dist/protocols/protocol-v2/uiInteraction.d.ts +39 -0
  188. package/dist/protocols/protocol-v2/uiInteraction.d.ts.map +1 -0
  189. package/dist/protocols/protocol-v2/unlockRetry.d.ts +11 -0
  190. package/dist/protocols/protocol-v2/unlockRetry.d.ts.map +1 -0
  191. package/dist/protocols/protocol-v2/walletSession.d.ts +19 -0
  192. package/dist/protocols/protocol-v2/walletSession.d.ts.map +1 -0
  193. package/dist/types/api/checkAllFirmwareRelease.d.ts +1 -2
  194. package/dist/types/api/checkAllFirmwareRelease.d.ts.map +1 -1
  195. package/dist/types/api/deviceSettings.d.ts +11 -2
  196. package/dist/types/api/deviceSettings.d.ts.map +1 -1
  197. package/dist/types/api/deviceUnlock.d.ts +2 -2
  198. package/dist/types/api/deviceUnlock.d.ts.map +1 -1
  199. package/dist/types/api/firmwareUpdate.d.ts +6 -6
  200. package/dist/types/api/firmwareUpdate.d.ts.map +1 -1
  201. package/dist/types/api/getDeviceState.d.ts +12 -0
  202. package/dist/types/api/getDeviceState.d.ts.map +1 -0
  203. package/dist/types/api/getFeatures.d.ts.map +1 -1
  204. package/dist/types/api/getOnekeyFeatures.d.ts.map +1 -1
  205. package/dist/types/api/getPassphraseState.d.ts +2 -10
  206. package/dist/types/api/getPassphraseState.d.ts.map +1 -1
  207. package/dist/types/api/index.d.ts +22 -25
  208. package/dist/types/api/index.d.ts.map +1 -1
  209. package/dist/types/api/kaspaSignTransaction.d.ts +27 -2
  210. package/dist/types/api/kaspaSignTransaction.d.ts.map +1 -1
  211. package/dist/types/api/openWalletSession.d.ts +41 -0
  212. package/dist/types/api/openWalletSession.d.ts.map +1 -0
  213. package/dist/types/api/protocolV2.d.ts +23 -28
  214. package/dist/types/api/protocolV2.d.ts.map +1 -1
  215. package/dist/types/api/sessionCache.d.ts +10 -0
  216. package/dist/types/api/sessionCache.d.ts.map +1 -0
  217. package/dist/types/device.d.ts +121 -5
  218. package/dist/types/device.d.ts.map +1 -1
  219. package/dist/types/params.d.ts +1 -0
  220. package/dist/types/params.d.ts.map +1 -1
  221. package/dist/types/settings.d.ts +21 -1
  222. package/dist/types/settings.d.ts.map +1 -1
  223. package/dist/utils/assets.d.ts +2 -1
  224. package/dist/utils/assets.d.ts.map +1 -1
  225. package/dist/utils/deviceFeaturesCompat.d.ts +13 -0
  226. package/dist/utils/deviceFeaturesCompat.d.ts.map +1 -0
  227. package/dist/utils/deviceFeaturesUtils.d.ts +13 -3
  228. package/dist/utils/deviceFeaturesUtils.d.ts.map +1 -1
  229. package/dist/utils/deviceInfoUtils.d.ts +9 -8
  230. package/dist/utils/deviceInfoUtils.d.ts.map +1 -1
  231. package/dist/utils/deviceSettings.d.ts +38 -7
  232. package/dist/utils/deviceSettings.d.ts.map +1 -1
  233. package/dist/utils/deviceVersionUtils.d.ts +6 -5
  234. package/dist/utils/deviceVersionUtils.d.ts.map +1 -1
  235. package/dist/utils/homescreen.d.ts.map +1 -1
  236. package/dist/utils/index.d.ts +5 -2
  237. package/dist/utils/index.d.ts.map +1 -1
  238. package/dist/utils/networkUtils.d.ts +9 -1
  239. package/dist/utils/networkUtils.d.ts.map +1 -1
  240. package/dist/utils/patch.d.ts +1 -1
  241. package/dist/utils/patch.d.ts.map +1 -1
  242. package/dist/utils/pro2Wallpaper.d.ts +12 -0
  243. package/dist/utils/pro2Wallpaper.d.ts.map +1 -0
  244. package/dist/utils/tracing.d.ts.map +1 -1
  245. package/package.json +4 -4
  246. package/src/api/BaseMethod.ts +36 -9
  247. package/src/api/CheckBootloaderRelease.ts +1 -2
  248. package/src/api/CheckFirmwareRelease.ts +1 -2
  249. package/src/api/ClearSessionCache.ts +28 -0
  250. package/src/api/DirList.ts +5 -3
  251. package/src/api/DirMake.ts +3 -3
  252. package/src/api/DirRemove.ts +3 -3
  253. package/src/api/FileDelete.ts +3 -3
  254. package/src/api/FileRead.ts +23 -7
  255. package/src/api/FileWrite.ts +23 -168
  256. package/src/api/FirmwareUpdate.ts +4 -4
  257. package/src/api/FirmwareUpdateV2.ts +133 -45
  258. package/src/api/FirmwareUpdateV3.ts +3 -5
  259. package/src/api/FirmwareUpdateV4.ts +1138 -357
  260. package/src/api/GetDeviceState.ts +55 -0
  261. package/src/api/GetFeatures.ts +8 -3
  262. package/src/api/GetOnekeyFeatures.ts +3 -72
  263. package/src/api/GetPassphraseState.ts +11 -18
  264. package/src/api/OpenWalletSession.ts +221 -0
  265. package/src/api/PathInfo.ts +5 -3
  266. package/src/api/PromptWebDeviceAccess.ts +2 -3
  267. package/src/api/SearchDevices.ts +29 -4
  268. package/src/api/UploadPortfolio.ts +40 -0
  269. package/src/api/alephium/AlephiumSignTransaction.ts +2 -2
  270. package/src/api/allnetwork/AllNetworkGetAddressBase.ts +4 -8
  271. package/src/api/benfen/BenfenGetAddress.ts +1 -1
  272. package/src/api/btc/BTCGetPublicKey.ts +1 -1
  273. package/src/api/cardano/CardanoSignMessage.ts +1 -1
  274. package/src/api/cardano/CardanoSignTransaction.ts +1 -1
  275. package/src/api/device/DeviceCancel.ts +1 -0
  276. package/src/api/device/DeviceChangePin.ts +24 -0
  277. package/src/api/device/DeviceFullyUploadResource.ts +4 -5
  278. package/src/api/device/DeviceLock.ts +1 -0
  279. package/src/api/device/DeviceRebootToBoardloader.ts +5 -4
  280. package/src/api/device/DeviceRebootToBootloader.ts +5 -4
  281. package/src/api/device/DeviceSettings.ts +183 -1
  282. package/src/api/device/DeviceUnlock.ts +11 -1
  283. package/src/api/device/DeviceUpdateBootloader.ts +1 -2
  284. package/src/api/device/DeviceWipe.ts +19 -0
  285. package/src/api/evm/EVMSignTypedData.ts +3 -5
  286. package/src/api/evm/legacyV1/getAddress.ts +2 -2
  287. package/src/api/evm/legacyV1/getPublicKey.ts +2 -2
  288. package/src/api/evm/legacyV1/signMessage.ts +2 -2
  289. package/src/api/evm/legacyV1/signTypedData.ts +2 -2
  290. package/src/api/evm/legacyV1/signTypedHash.ts +2 -2
  291. package/src/api/evm/legacyV1/verifyMessage.ts +2 -2
  292. package/src/api/firmware/FirmwareUpdateBaseMethod.ts +21 -7
  293. package/src/api/firmware/getBinary.ts +8 -3
  294. package/src/api/firmware/progressThrottle.ts +44 -0
  295. package/src/api/helpers/batchGetPublickeys.ts +2 -2
  296. package/src/api/helpers/filesystemValidation.ts +61 -0
  297. package/src/api/helpers/paramsValidator.ts +1 -1
  298. package/src/api/helpers/protocolV2FileWrite.ts +193 -0
  299. package/src/api/index.ts +14 -20
  300. package/src/api/kaspa/KaspaSignTransaction.ts +341 -22
  301. package/src/api/kaspa/helpers/TransferSerialize.ts +14 -0
  302. package/src/api/nervos/NervosSignTransaction.ts +2 -2
  303. package/src/api/nexa/NexaSignTransaction.ts +1 -1
  304. package/src/api/protocol-v2/{FactoryGetDeviceInfo.ts → DeviceFactoryInfoGet.ts} +4 -4
  305. package/src/api/protocol-v2/DeviceFactoryInfoSet.ts +32 -0
  306. package/src/api/protocol-v2/DeviceFirmwareUpdate.ts +7 -9
  307. package/src/api/protocol-v2/DeviceGetFirmwareUpdateStatus.ts +41 -6
  308. package/src/api/protocol-v2/DeviceGetOnboardingStatus.ts +6 -4
  309. package/src/api/protocol-v2/DeviceInfoGet.ts +145 -0
  310. package/src/api/protocol-v2/DeviceReboot.ts +5 -3
  311. package/src/api/protocol-v2/DeviceStatusGet.ts +16 -0
  312. package/src/api/protocol-v2/DeviceUploadWallpaper.ts +131 -0
  313. package/src/api/protocol-v2/FilesystemFormat.ts +5 -2
  314. package/src/api/protocol-v2/{FilesystemFixPermission.ts → FilesystemPermissionFix.ts} +3 -3
  315. package/src/api/protocol-v2/Ping.ts +1 -1
  316. package/src/api/protocol-v2/{GetProtoVersion.ts → ProtocolInfoRequest.ts} +3 -3
  317. package/src/api/protocol-v2/helpers.ts +58 -62
  318. package/src/api/ton/TonSignData.ts +1 -5
  319. package/src/api/utils.ts +7 -3
  320. package/src/constants/index.ts +7 -1
  321. package/src/core/RequestQueue.ts +1 -0
  322. package/src/core/deviceEventRegistration.ts +23 -0
  323. package/src/core/index.ts +140 -35
  324. package/src/data/messages/messages-protocol-v2.json +825 -709
  325. package/src/data/messages/messages.json +286 -1
  326. package/src/data-manager/DataManager.ts +13 -6
  327. package/src/data-manager/connectSettings.ts +4 -0
  328. package/src/device/Device.ts +480 -192
  329. package/src/device/DeviceCommands.ts +81 -25
  330. package/src/device/DeviceFeaturesState.ts +25 -0
  331. package/src/device/DevicePool.ts +67 -19
  332. package/src/device/DeviceStateMapper.ts +349 -0
  333. package/src/device/DeviceStateProjector.ts +95 -0
  334. package/src/device/DeviceStateStore.ts +201 -0
  335. package/src/device/DeviceWalletSessionStore.ts +105 -0
  336. package/src/device/cloneDeviceState.ts +39 -0
  337. package/src/device/deviceIdentity.ts +18 -0
  338. package/src/deviceProfile/buildDeviceFeatures.ts +235 -210
  339. package/src/deviceProfile/index.ts +0 -1
  340. package/src/events/device.ts +17 -1
  341. package/src/events/logBlockEvent.ts +8 -1
  342. package/src/events/ui-request.ts +24 -2
  343. package/src/inject.ts +23 -34
  344. package/src/protocols/protocol-v2/deviceSession.ts +24 -0
  345. package/src/protocols/protocol-v2/features.ts +68 -82
  346. package/src/protocols/protocol-v2/firmware.ts +12 -36
  347. package/src/protocols/protocol-v2/index.ts +3 -1
  348. package/src/protocols/protocol-v2/lockedError.ts +10 -0
  349. package/src/protocols/protocol-v2/settingsUnlockPolicy.ts +61 -0
  350. package/src/protocols/protocol-v2/uiInteraction.ts +210 -0
  351. package/src/protocols/protocol-v2/unlockRetry.ts +76 -0
  352. package/src/protocols/protocol-v2/walletSession.ts +107 -0
  353. package/src/types/api/checkAllFirmwareRelease.ts +1 -2
  354. package/src/types/api/deviceSettings.ts +26 -2
  355. package/src/types/api/deviceUnlock.ts +5 -2
  356. package/src/types/api/firmwareUpdate.ts +28 -20
  357. package/src/types/api/getDeviceState.ts +19 -0
  358. package/src/types/api/getFeatures.ts +3 -0
  359. package/src/types/api/getOnekeyFeatures.ts +3 -0
  360. package/src/types/api/getPassphraseState.ts +8 -11
  361. package/src/types/api/index.ts +30 -53
  362. package/src/types/api/kaspaSignTransaction.ts +40 -2
  363. package/src/types/api/openWalletSession.ts +64 -0
  364. package/src/types/api/protocolV2.ts +58 -55
  365. package/src/types/api/sessionCache.ts +14 -0
  366. package/src/types/device.ts +170 -4
  367. package/src/types/params.ts +4 -0
  368. package/src/types/settings.ts +42 -30
  369. package/src/utils/assets.ts +4 -1
  370. package/src/utils/deviceFeaturesCompat.ts +173 -0
  371. package/src/utils/deviceFeaturesUtils.ts +68 -24
  372. package/src/utils/deviceInfoUtils.ts +26 -64
  373. package/src/utils/deviceSettings.ts +161 -39
  374. package/src/utils/deviceVersionUtils.ts +25 -44
  375. package/src/utils/findDefectiveBatchDevice.ts +3 -3
  376. package/src/utils/homescreen.ts +10 -0
  377. package/src/utils/index.ts +21 -1
  378. package/src/utils/networkUtils.ts +270 -14
  379. package/src/utils/pro2Wallpaper.ts +109 -0
  380. package/src/utils/tracing.ts +3 -1
  381. package/dist/api/GetDeviceInfo.d.ts +0 -9
  382. package/dist/api/GetDeviceInfo.d.ts.map +0 -1
  383. package/dist/api/protocol-v2/DevReboot.d.ts +0 -7
  384. package/dist/api/protocol-v2/DevReboot.d.ts.map +0 -1
  385. package/dist/api/protocol-v2/DeviceGetDeviceInfo.d.ts +0 -29
  386. package/dist/api/protocol-v2/DeviceGetDeviceInfo.d.ts.map +0 -1
  387. package/dist/api/protocol-v2/FactoryDeviceInfoSettings.d.ts +0 -7
  388. package/dist/api/protocol-v2/FactoryDeviceInfoSettings.d.ts.map +0 -1
  389. package/dist/api/protocol-v2/FactoryGetDeviceInfo.d.ts +0 -6
  390. package/dist/api/protocol-v2/FactoryGetDeviceInfo.d.ts.map +0 -1
  391. package/dist/api/protocol-v2/FilesystemDiskControl.d.ts +0 -13
  392. package/dist/api/protocol-v2/FilesystemDiskControl.d.ts.map +0 -1
  393. package/dist/api/protocol-v2/FilesystemFixPermission.d.ts.map +0 -1
  394. package/dist/api/protocol-v2/GetProtoVersion.d.ts +0 -6
  395. package/dist/api/protocol-v2/GetProtoVersion.d.ts.map +0 -1
  396. package/dist/deviceProfile/buildDeviceProfile.d.ts +0 -21
  397. package/dist/deviceProfile/buildDeviceProfile.d.ts.map +0 -1
  398. package/dist/types/api/getDeviceInfo.d.ts +0 -85
  399. package/dist/types/api/getDeviceInfo.d.ts.map +0 -1
  400. package/src/api/GetDeviceInfo.ts +0 -145
  401. package/src/api/protocol-v2/DevReboot.ts +0 -24
  402. package/src/api/protocol-v2/DeviceGetDeviceInfo.ts +0 -118
  403. package/src/api/protocol-v2/FactoryDeviceInfoSettings.ts +0 -29
  404. package/src/api/protocol-v2/FilesystemDiskControl.ts +0 -50
  405. package/src/deviceProfile/buildDeviceProfile.ts +0 -334
  406. package/src/types/api/getDeviceInfo.ts +0 -99
@@ -0,0 +1,117 @@
1
+ import { initConnector, initCore } from '../src/core';
2
+ import { DataManager } from '../src/data-manager';
3
+ import TransportManager from '../src/data-manager/TransportManager';
4
+ import { Device } from '../src/device/Device';
5
+ import { DevicePool } from '../src/device/DevicePool';
6
+ import { CORE_EVENT, DEVICE, IFRAME } from '../src/events';
7
+
8
+ import type Core from '../src/core';
9
+ import type { CoreMessage } from '../src/events';
10
+ import type { KnownDevice } from '../src/types';
11
+
12
+ jest.mock('../src/data/config', () => ({
13
+ getSDKVersion: jest.fn(() => '1.0.0-test'),
14
+ DEFAULT_DOMAIN: 'https://jssdk.onekey.so/1.0.0-test/',
15
+ }));
16
+
17
+ const createInitializedDevice = (protocol: 'V1' | 'V2') => {
18
+ const device = Device.fromDescriptor({
19
+ id: 'ble-discovery-id',
20
+ path: 'ble-discovery-id',
21
+ commType: 'ble',
22
+ protocolType: protocol,
23
+ } as never);
24
+ device.mainId = 'ble-connect-id';
25
+ device.features = {
26
+ protocol,
27
+ deviceType: protocol === 'V2' ? 'pro2' : 'classic',
28
+ firmwareType: 'universal',
29
+ deviceId: 'wallet-device-id',
30
+ serialNo: 'SERIAL-001',
31
+ label: 'OneKey Test',
32
+ bleName: 'OneKey Test BLE',
33
+ capabilities: [],
34
+ mode: 'normal',
35
+ initialized: true,
36
+ bootloaderMode: false,
37
+ firmwareVersion: '1.2.3',
38
+ bootloaderVersion: '1.0.0',
39
+ boardVersion: '1.0.0',
40
+ bleVersion: '2.3.4',
41
+ } as never;
42
+ return device;
43
+ };
44
+
45
+ describe('public device lifecycle events', () => {
46
+ let core: Core | undefined;
47
+
48
+ beforeEach(() => {
49
+ DevicePool.resetState();
50
+ jest.spyOn(TransportManager, 'load').mockImplementation();
51
+ TransportManager.transport = {
52
+ stop: jest.fn().mockResolvedValue(undefined),
53
+ } as never;
54
+ });
55
+
56
+ afterEach(async () => {
57
+ await core?.dispose();
58
+ core = undefined;
59
+ jest.restoreAllMocks();
60
+ });
61
+
62
+ test.each([
63
+ ['react-native', 'V1'],
64
+ ['react-native', 'V2'],
65
+ ['lowlevel', 'V1'],
66
+ ['lowlevel', 'V2'],
67
+ ] as const)(
68
+ 'emits KnownDevice snapshots for %s Protocol %s connect and disconnect events',
69
+ async (env, protocol) => {
70
+ jest.spyOn(DataManager, 'getSettings').mockReturnValue(env as never);
71
+ core = initCore();
72
+ initConnector();
73
+
74
+ await core.handleMessage({
75
+ id: 'register-device-connect-listener',
76
+ event: IFRAME.CALL,
77
+ type: IFRAME.CALL,
78
+ payload: { method: 'clearSessionCache' },
79
+ } as CoreMessage);
80
+
81
+ const messages: CoreMessage[] = [];
82
+ core.on(CORE_EVENT, message => messages.push(message));
83
+ const internalDevice = createInitializedDevice(protocol);
84
+
85
+ DevicePool.emitter.emit(DEVICE.CONNECT, internalDevice);
86
+ internalDevice.updateState({ identity: { label: 'Updated label' } }, 'settings-write');
87
+ DevicePool.emitter.emit(DEVICE.DISCONNECT, internalDevice);
88
+
89
+ const connectMessage = messages.find(message => message.type === DEVICE.CONNECT);
90
+ const disconnectMessage = messages.find(message => message.type === DEVICE.DISCONNECT);
91
+ const connectedDevice = connectMessage?.payload.device as KnownDevice;
92
+ const disconnectedDevice = disconnectMessage?.payload.device as KnownDevice;
93
+
94
+ expect(connectedDevice).toMatchObject({
95
+ connectId: 'ble-connect-id',
96
+ serialNo: 'SERIAL-001',
97
+ uuid: 'SERIAL-001',
98
+ label: 'OneKey Test',
99
+ state: { protocol },
100
+ });
101
+ expect(disconnectedDevice).toMatchObject({
102
+ connectId: 'ble-connect-id',
103
+ serialNo: 'SERIAL-001',
104
+ uuid: 'SERIAL-001',
105
+ label: 'Updated label',
106
+ state: { protocol },
107
+ });
108
+ expect(connectedDevice).not.toBe(internalDevice);
109
+ expect(connectedDevice).not.toBe(disconnectedDevice);
110
+ expect(connectedDevice).not.toHaveProperty('run');
111
+ expect(connectedDevice).not.toHaveProperty('acquire');
112
+ expect(connectedDevice).not.toHaveProperty('commands');
113
+ expect(() => JSON.stringify(connectedDevice)).not.toThrow();
114
+ expect(connectedDevice.label).toBe('OneKey Test');
115
+ }
116
+ );
117
+ });
@@ -0,0 +1,132 @@
1
+ import { DevicePool } from '../src/device/DevicePool';
2
+ import { Device } from '../src/device/Device';
3
+ import { DEVICE } from '../src/events';
4
+
5
+ jest.mock('../src/data/config', () => ({
6
+ getSDKVersion: jest.fn(() => '1.0.0'),
7
+ DEFAULT_DOMAIN: 'https://jssdk.onekey.so/1.0.0/',
8
+ }));
9
+
10
+ describe('DevicePool state lifecycle', () => {
11
+ beforeEach(() => {
12
+ DevicePool.resetState();
13
+ });
14
+
15
+ afterEach(() => {
16
+ DevicePool.resetState();
17
+ });
18
+
19
+ test('refreshes runtime state for a cached Protocol V2 discovery result', async () => {
20
+ const descriptor = { path: 'pro2-path', protocolType: 'V2' } as any;
21
+ const getDeviceState = jest.fn().mockResolvedValue({ status: { mode: 'normal' } });
22
+ const device = {
23
+ originalDescriptor: descriptor,
24
+ updateDescriptor: jest.fn(),
25
+ isProtocolV2: () => true,
26
+ getDeviceState,
27
+ run: jest.fn(async (callback: () => Promise<void>) => callback()),
28
+ } as any;
29
+ DevicePool.devicesCache = { 'pro2-id': device };
30
+
31
+ await DevicePool.getDevices([descriptor], 'pro2-id', {
32
+ connectProtocol: 'V2',
33
+ refreshRuntimeState: true,
34
+ });
35
+
36
+ expect(device.run).toHaveBeenCalledTimes(1);
37
+ expect(getDeviceState).toHaveBeenNthCalledWith(1, { refreshSections: ['status'] });
38
+ expect(getDeviceState).toHaveBeenNthCalledWith(2, { refreshSections: ['settings'] });
39
+ });
40
+
41
+ test('keeps a discovered device when its Protocol V2 label cannot be read', async () => {
42
+ const labelError = new Error('settings unavailable');
43
+ const getDeviceState = jest
44
+ .fn()
45
+ .mockResolvedValueOnce({ status: { mode: 'normal' } })
46
+ .mockRejectedValueOnce(labelError);
47
+ const device = {
48
+ isProtocolV2: () => true,
49
+ getDeviceState,
50
+ run: jest.fn(async (callback: () => Promise<void>) => callback()),
51
+ } as any;
52
+
53
+ await expect(
54
+ (DevicePool as any)._refreshRuntimeState(device, { refreshRuntimeState: true })
55
+ ).resolves.toBeUndefined();
56
+ expect(getDeviceState).toHaveBeenCalledTimes(2);
57
+ });
58
+
59
+ test('uses the disconnected descriptor and invalidates its cached state', () => {
60
+ const descriptor = { path: 'pro2-path', protocolType: 'V2' } as any;
61
+ const device = {
62
+ originalDescriptor: descriptor,
63
+ markTransportDisconnected: jest.fn(),
64
+ } as any;
65
+ DevicePool.devicesCache = { 'pro2-id': device };
66
+ DevicePool.disconnectPool = [descriptor];
67
+ const onDisconnect = jest.fn();
68
+ DevicePool.emitter.on(DEVICE.DISCONNECT, onDisconnect);
69
+
70
+ (DevicePool as any)._sendDisconnectMessage();
71
+
72
+ expect(device.markTransportDisconnected).toHaveBeenCalledTimes(1);
73
+ expect(onDisconnect).toHaveBeenCalledWith(device);
74
+ expect(DevicePool.disconnectPool).toEqual([]);
75
+ });
76
+
77
+ test('releases a newly created device when initialization fails', async () => {
78
+ const descriptor = { path: 'pro2-path', protocolType: 'V2' } as any;
79
+ const release = jest.fn().mockResolvedValue(undefined);
80
+ const device = {
81
+ connect: jest.fn().mockResolvedValue(true),
82
+ initialize: jest.fn().mockRejectedValue(new Error('initialize failed')),
83
+ release,
84
+ } as any;
85
+ const fromDescriptor = jest.spyOn(Device, 'fromDescriptor').mockReturnValue(device);
86
+
87
+ try {
88
+ await expect((DevicePool as any)._createDevice(descriptor)).rejects.toThrow(
89
+ 'initialize failed'
90
+ );
91
+ } finally {
92
+ fromDescriptor.mockRestore();
93
+ }
94
+
95
+ expect(release).toHaveBeenCalledTimes(1);
96
+ });
97
+
98
+ test('releases the cached device before surfacing a runtime refresh error', async () => {
99
+ const refreshError = new Error('status failed');
100
+ let callbackRejected = false;
101
+ const device = {
102
+ isProtocolV2: () => true,
103
+ getDeviceState: jest.fn().mockRejectedValue(refreshError),
104
+ run: jest.fn(async (callback: () => Promise<void>) => {
105
+ try {
106
+ await callback();
107
+ } catch {
108
+ callbackRejected = true;
109
+ }
110
+ }),
111
+ } as any;
112
+
113
+ await expect(
114
+ (DevicePool as any)._refreshRuntimeState(device, { refreshRuntimeState: true })
115
+ ).rejects.toBe(refreshError);
116
+ expect(callbackRejected).toBe(false);
117
+ });
118
+
119
+ test('releases an acquired device when reinitialization fails', async () => {
120
+ const device = Device.fromDescriptor({ path: 'pro2-path', protocolType: 'V2' } as any);
121
+ (device as any).commands = { disposed: true };
122
+ jest.spyOn(device, 'acquire').mockResolvedValue(true);
123
+ jest.spyOn(device, 'initialize').mockRejectedValue(new Error('reinitialize failed'));
124
+ const release = jest.spyOn(device, 'release').mockResolvedValue(undefined);
125
+
126
+ await expect(device.run(jest.fn().mockResolvedValue(undefined))).rejects.toThrow(
127
+ 'reinitialize failed'
128
+ );
129
+
130
+ expect(release).toHaveBeenCalledTimes(1);
131
+ });
132
+ });
@@ -0,0 +1,391 @@
1
+ import { EDeviceType, HardwareErrorCode } from '@onekeyfe/hd-shared';
2
+ import { DeviceSettingsPage } from '@onekeyfe/hd-transport';
3
+
4
+ import DeviceSettings from '../src/api/device/DeviceSettings';
5
+
6
+ import type { Features } from '../src/types';
7
+
8
+ jest.mock('../src/data/config', () => ({
9
+ DEFAULT_DOMAIN: 'https://example.com/',
10
+ getSDKVersion: () => '0.0.0-test',
11
+ }));
12
+
13
+ const features = {
14
+ protocol: 'V2',
15
+ label: 'Old Label',
16
+ language: 'en-US',
17
+ } as Features;
18
+
19
+ function createDevice({ protocol }: { protocol: 'V1' | 'V2' }) {
20
+ const typedCall = jest.fn().mockResolvedValue({ message: { message: 'Success' } });
21
+ const updateState = jest.fn();
22
+ const getDeviceState = jest.fn();
23
+ return {
24
+ device: {
25
+ features,
26
+ isProtocolV2: () => protocol === 'V2',
27
+ getCurrentDeviceType: () => (protocol === 'V2' ? EDeviceType.Pro2 : EDeviceType.Pro),
28
+ commands: { typedCall },
29
+ updateState,
30
+ getDeviceState,
31
+ },
32
+ typedCall,
33
+ updateState,
34
+ getDeviceState,
35
+ };
36
+ }
37
+
38
+ describe('DeviceSettings protocol routing', () => {
39
+ it.each([
40
+ ['label', { label: 'Shared Label' }],
41
+ ['language', { language: 'ja-JP' }],
42
+ ['brightness', { brightness: 80 }],
43
+ ['haptic feedback', { hapticFeedback: true }],
44
+ ])('does not unlock Protocol V2 before changing %s', (_name, settings) => {
45
+ const method = new DeviceSettings({
46
+ id: 1,
47
+ payload: {
48
+ method: 'deviceSettings',
49
+ ...settings,
50
+ },
51
+ });
52
+
53
+ method.init();
54
+
55
+ expect(method.unlockPolicy).toBe('none');
56
+ });
57
+
58
+ it.each([
59
+ ['auto lock', { autoLockDelayMs: 60_000 }],
60
+ ['auto shutdown', { autoShutdownDelayMs: 120_000 }],
61
+ ['mixed settings', { brightness: 80, autoLockDelayMs: 60_000 }],
62
+ ])('unlocks Protocol V2 before changing %s', (_name, settings) => {
63
+ const method = new DeviceSettings({
64
+ id: 1,
65
+ payload: {
66
+ method: 'deviceSettings',
67
+ ...settings,
68
+ },
69
+ });
70
+
71
+ method.init();
72
+
73
+ expect(method.unlockPolicy).toBe('retry-on-locked');
74
+ });
75
+
76
+ it('uses ApplySettings and commits the confirmed patch for Protocol V1', async () => {
77
+ const { device, typedCall, updateState } = createDevice({ protocol: 'V1' });
78
+ const method = new DeviceSettings({
79
+ id: 1,
80
+ payload: {
81
+ method: 'deviceSettings',
82
+ label: 'Shared Label',
83
+ language: 'ja',
84
+ bluetoothEnabled: true,
85
+ },
86
+ });
87
+ method.init();
88
+ (method as any).device = device;
89
+
90
+ await expect(method.run()).resolves.toEqual({ message: 'Success' });
91
+ expect(typedCall).toHaveBeenCalledWith('ApplySettings', 'Success', {
92
+ label: 'Shared Label',
93
+ language: 'ja',
94
+ use_passphrase: undefined,
95
+ homescreen: undefined,
96
+ _passphrase_source: undefined,
97
+ auto_lock_delay_ms: undefined,
98
+ display_rotation: undefined,
99
+ passphrase_always_on_device: undefined,
100
+ safety_checks: undefined,
101
+ experimental_features: undefined,
102
+ auto_shutdown_delay_ms: undefined,
103
+ use_ble: true,
104
+ haptic_feedback: undefined,
105
+ });
106
+ expect(updateState).toHaveBeenCalledWith(
107
+ {
108
+ identity: { label: 'Shared Label' },
109
+ settings: { language: 'ja', bleEnabled: true },
110
+ },
111
+ 'settings-write'
112
+ );
113
+ });
114
+
115
+ it('uses DeviceSettingsSet and commits the confirmed patch for Protocol V2', async () => {
116
+ const { device, typedCall, updateState } = createDevice({ protocol: 'V2' });
117
+ const method = new DeviceSettings({
118
+ id: 2,
119
+ payload: {
120
+ method: 'deviceSettings',
121
+ label: 'Shared Label',
122
+ language: 'ja',
123
+ autoLockDelayMs: 60_000,
124
+ hapticFeedback: true,
125
+ bluetoothEnabled: true,
126
+ },
127
+ });
128
+ method.init();
129
+ (method as any).device = device;
130
+
131
+ await expect(method.run()).resolves.toEqual({ message: 'Success' });
132
+ expect(typedCall).toHaveBeenCalledWith('DeviceSettingsSet', 'Success', {
133
+ settings: {
134
+ label: 'Shared Label',
135
+ language: 'ja-Jpan-JP',
136
+ bt_enable: true,
137
+ autolock_delay_ms: 60_000,
138
+ haptic_feedback: true,
139
+ },
140
+ });
141
+ expect(updateState).toHaveBeenCalledWith(
142
+ {
143
+ identity: { label: 'Shared Label' },
144
+ settings: {
145
+ language: 'ja',
146
+ bleEnabled: true,
147
+ autoLockDelayMs: 60_000,
148
+ hapticFeedback: true,
149
+ },
150
+ },
151
+ 'settings-write'
152
+ );
153
+ expect(typedCall.mock.calls.map(call => call[0])).not.toEqual(
154
+ expect.arrayContaining(['DeviceInfoGet', 'DeviceStatusGet', 'DeviceSettingsGet'])
155
+ );
156
+ });
157
+
158
+ it('uses the Pro2 passphrase page as a device-side toggle and verifies the target state', async () => {
159
+ const { device, typedCall, getDeviceState } = createDevice({ protocol: 'V2' });
160
+ getDeviceState
161
+ .mockResolvedValueOnce({
162
+ status: { passphraseProtection: false },
163
+ })
164
+ .mockResolvedValueOnce({
165
+ status: { passphraseProtection: true },
166
+ });
167
+ const method = new DeviceSettings({
168
+ id: 3,
169
+ payload: {
170
+ method: 'deviceSettings',
171
+ usePassphrase: true,
172
+ },
173
+ });
174
+ method.init();
175
+ (method as any).device = device;
176
+
177
+ await expect(method.run()).resolves.toEqual({ message: 'Success' });
178
+ expect(typedCall).toHaveBeenCalledWith('DeviceSettingsPageShow', 'Success', {
179
+ page: DeviceSettingsPage.DevicePassphrase,
180
+ });
181
+ expect(typedCall).not.toHaveBeenCalledWith('DeviceSettingsSet', 'Success', expect.anything());
182
+ expect(getDeviceState).toHaveBeenNthCalledWith(1, { refreshSections: ['status'] });
183
+ expect(getDeviceState).toHaveBeenNthCalledWith(2, { refreshSections: ['status'] });
184
+ });
185
+
186
+ it('does not open a Pro2 settings page when the hardware already matches the target', async () => {
187
+ const { device, typedCall, getDeviceState } = createDevice({ protocol: 'V2' });
188
+ getDeviceState.mockResolvedValue({
189
+ settings: { airgapMode: false },
190
+ });
191
+ const method = new DeviceSettings({
192
+ id: 4,
193
+ payload: {
194
+ method: 'deviceSettings',
195
+ airgapMode: false,
196
+ },
197
+ });
198
+ method.init();
199
+ (method as any).device = device;
200
+
201
+ await expect(method.run()).resolves.toEqual({
202
+ message: 'Settings already match requested value.',
203
+ });
204
+ expect(typedCall).not.toHaveBeenCalled();
205
+ expect(getDeviceState).toHaveBeenCalledWith({ refreshSections: ['settings'] });
206
+ });
207
+
208
+ it('rejects a successful Pro2 page response when the hardware did not reach the target', async () => {
209
+ const { device, getDeviceState } = createDevice({ protocol: 'V2' });
210
+ getDeviceState.mockResolvedValue({
211
+ status: { passphraseProtection: false },
212
+ });
213
+ const method = new DeviceSettings({
214
+ id: 5,
215
+ payload: {
216
+ method: 'deviceSettings',
217
+ usePassphrase: true,
218
+ },
219
+ });
220
+ method.init();
221
+ (method as any).device = device;
222
+
223
+ await expect(method.run()).rejects.toMatchObject({
224
+ errorCode: HardwareErrorCode.RuntimeError,
225
+ message: 'Protocol V2 passphrase setting did not reach the requested value.',
226
+ });
227
+ });
228
+
229
+ it('keeps Protocol V1 passphrase settings on ApplySettings', async () => {
230
+ const { device, typedCall, getDeviceState } = createDevice({ protocol: 'V1' });
231
+ const method = new DeviceSettings({
232
+ id: 6,
233
+ payload: {
234
+ method: 'deviceSettings',
235
+ usePassphrase: true,
236
+ },
237
+ });
238
+ method.init();
239
+ (method as any).device = device;
240
+
241
+ await method.run();
242
+
243
+ expect(typedCall).toHaveBeenCalledWith(
244
+ 'ApplySettings',
245
+ 'Success',
246
+ expect.objectContaining({ use_passphrase: true })
247
+ );
248
+ expect(getDeviceState).not.toHaveBeenCalled();
249
+ });
250
+
251
+ it('rejects combining a Pro2 device-side toggle with direct settings', async () => {
252
+ const { device, typedCall } = createDevice({ protocol: 'V2' });
253
+ const method = new DeviceSettings({
254
+ id: 7,
255
+ payload: {
256
+ method: 'deviceSettings',
257
+ usePassphrase: true,
258
+ label: 'New Label',
259
+ },
260
+ });
261
+ method.init();
262
+ (method as any).device = device;
263
+
264
+ expect(method.unlockPolicy).toBe('none');
265
+ expect(method.protocolV2UiInteraction).toBeUndefined();
266
+ await expect(method.run()).rejects.toMatchObject({
267
+ errorCode: HardwareErrorCode.CallMethodInvalidParameter,
268
+ });
269
+ expect(typedCall).not.toHaveBeenCalled();
270
+ });
271
+
272
+ it('rejects two Pro2 device-side toggles without starting an interaction', async () => {
273
+ const { device, typedCall } = createDevice({ protocol: 'V2' });
274
+ const method = new DeviceSettings({
275
+ id: 8,
276
+ payload: {
277
+ method: 'deviceSettings',
278
+ usePassphrase: true,
279
+ airgapMode: true,
280
+ },
281
+ });
282
+ method.init();
283
+ (method as any).device = device;
284
+
285
+ expect(method.unlockPolicy).toBe('none');
286
+ expect(method.protocolV2UiInteraction).toBeUndefined();
287
+ await expect(method.run()).rejects.toMatchObject({
288
+ errorCode: HardwareErrorCode.CallMethodInvalidParameter,
289
+ });
290
+ expect(typedCall).not.toHaveBeenCalled();
291
+ });
292
+
293
+ it('rejects Protocol V1-only settings on Protocol V2 without partially applying the request', async () => {
294
+ const { device, typedCall } = createDevice({ protocol: 'V2' });
295
+ const method = new DeviceSettings({
296
+ id: 9,
297
+ payload: {
298
+ method: 'deviceSettings',
299
+ label: 'Must not be partially applied',
300
+ safetyChecks: 0,
301
+ },
302
+ });
303
+ method.init();
304
+ (method as any).device = device;
305
+
306
+ await expect(method.run()).rejects.toMatchObject({
307
+ errorCode: HardwareErrorCode.CallMethodInvalidParameter,
308
+ message: 'Protocol V2 does not support settings: safetyChecks.',
309
+ });
310
+ expect(typedCall).not.toHaveBeenCalled();
311
+ });
312
+
313
+ it('rejects Protocol V2-only settings on Protocol V1 without partially applying the request', async () => {
314
+ const { device, typedCall } = createDevice({ protocol: 'V1' });
315
+ const method = new DeviceSettings({
316
+ id: 10,
317
+ payload: {
318
+ method: 'deviceSettings',
319
+ label: 'Must not be partially applied',
320
+ brightness: 80,
321
+ },
322
+ });
323
+ method.init();
324
+ (method as any).device = device;
325
+
326
+ await expect(method.run()).rejects.toMatchObject({
327
+ errorCode: HardwareErrorCode.CallMethodInvalidParameter,
328
+ message: 'Protocol V1 does not support settings: brightness.',
329
+ });
330
+ expect(typedCall).not.toHaveBeenCalled();
331
+ });
332
+
333
+ it('accepts the Protocol V2 never timeout wire value', async () => {
334
+ const { device, typedCall } = createDevice({ protocol: 'V2' });
335
+ const method = new DeviceSettings({
336
+ id: 11,
337
+ payload: {
338
+ method: 'deviceSettings',
339
+ autoLockDelayMs: 0x10000000,
340
+ autoShutdownDelayMs: 0x10000000,
341
+ },
342
+ });
343
+ method.init();
344
+ (method as any).device = device;
345
+
346
+ await method.run();
347
+
348
+ expect(typedCall).toHaveBeenCalledWith('DeviceSettingsSet', 'Success', {
349
+ settings: {
350
+ autolock_delay_ms: 0x10000000,
351
+ autoshutdown_delay_ms: 0x10000000,
352
+ },
353
+ });
354
+ });
355
+
356
+ it('rejects unsupported Protocol V2 timeout values before sending a command', async () => {
357
+ const { device, typedCall } = createDevice({ protocol: 'V2' });
358
+ const method = new DeviceSettings({
359
+ id: 12,
360
+ payload: {
361
+ method: 'deviceSettings',
362
+ autoLockDelayMs: 0,
363
+ },
364
+ });
365
+ method.init();
366
+ (method as any).device = device;
367
+
368
+ await expect(method.run()).rejects.toMatchObject({
369
+ errorCode: HardwareErrorCode.CallMethodInvalidParameter,
370
+ });
371
+ expect(typedCall).not.toHaveBeenCalled();
372
+ });
373
+
374
+ it('rejects unknown Protocol V1 safety check levels before sending a command', async () => {
375
+ const { device, typedCall } = createDevice({ protocol: 'V1' });
376
+ const method = new DeviceSettings({
377
+ id: 13,
378
+ payload: {
379
+ method: 'deviceSettings',
380
+ safetyChecks: 3,
381
+ },
382
+ } as never);
383
+ method.init();
384
+ (method as any).device = device;
385
+
386
+ await expect(method.run()).rejects.toMatchObject({
387
+ errorCode: HardwareErrorCode.CallMethodInvalidParameter,
388
+ });
389
+ expect(typedCall).not.toHaveBeenCalled();
390
+ });
391
+ });
@@ -0,0 +1,27 @@
1
+ import { DEVICE } from '../src/events';
2
+ import type { DeviceState, DeviceStateEvent } from '../src/types';
3
+
4
+ describe('DeviceState contract', () => {
5
+ test('exports the unified device state event contract', () => {
6
+ expect(DEVICE.STATE).toBe('state');
7
+
8
+ const state = {} as DeviceState;
9
+ const event: DeviceStateEvent = {
10
+ connectId: 'usb-1',
11
+ state,
12
+ revision: 1,
13
+ source: 'initialize',
14
+ changedKeys: ['identity.label'],
15
+ };
16
+
17
+ expect(event.state).toBe(state);
18
+ });
19
+ });
20
+
21
+ // raw 仅供 SDK 内部兼容投影使用,不属于公共 DeviceState。
22
+ // @ts-expect-error raw 不应成为外部接入者需要理解的字段
23
+ type RemovedPublicRaw = DeviceState['raw'];
24
+
25
+ // session 属于 SDK 运行时内部缓存,不应通过公共状态或事件暴露。
26
+ // @ts-expect-error session 不属于公共 DeviceState
27
+ type RemovedPublicSession = DeviceState['session'];