@onekeyfe/hd-core 1.2.0-alpha.66 → 1.2.0-alpha.67

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 (315) hide show
  1. package/__tests__/AllNetworkGetAddressBase.tracing.test.ts +0 -313
  2. package/__tests__/DeviceCommands.test.ts +13 -59
  3. package/__tests__/DeviceEventRegistration.test.ts +0 -6
  4. package/__tests__/check-all-firmware-release-protocol-v2.test.ts +3 -198
  5. package/__tests__/connectSettings.test.ts +47 -5
  6. package/__tests__/device-initialize-timeout.test.ts +56 -0
  7. package/__tests__/device-lifecycle-events.test.ts +3 -105
  8. package/__tests__/device-pool-state.test.ts +0 -22
  9. package/__tests__/device-settings.test.ts +18 -39
  10. package/__tests__/device-state-contract.test.ts +0 -1
  11. package/__tests__/device-state-mapper.test.ts +1 -13
  12. package/__tests__/device-utils.test.ts +1 -48
  13. package/__tests__/deviceSettings.test.ts +1 -11
  14. package/__tests__/firmware-update/check-all-firmware-release.test.ts +175 -0
  15. package/__tests__/firmware-update/device-update-bootloader.test.ts +87 -0
  16. package/__tests__/firmware-update/firmware-artifact-source.test.ts +119 -0
  17. package/__tests__/firmware-update/firmware-host-binding.test.ts +70 -0
  18. package/__tests__/firmware-update/firmware-preparation-error.test.ts +27 -0
  19. package/__tests__/firmware-update/firmware-update-bootloader-poll.test.ts +200 -0
  20. package/__tests__/firmware-update/firmware-update-capabilities.test.ts +13 -0
  21. package/__tests__/firmware-update/firmware-update-plan-bootloader-identity.test.ts +394 -0
  22. package/__tests__/firmware-update/firmware-update-plan.test.ts +593 -0
  23. package/__tests__/firmware-update/firmware-update-prepared-plan.test.ts +231 -0
  24. package/__tests__/firmware-update/firmware-update-v2-download-before-boot.test.ts +59 -31
  25. package/__tests__/firmware-update/firmware-update-v3-reconnect.test.ts +58 -0
  26. package/__tests__/firmware-update/firmware-upload-source.test.ts +70 -0
  27. package/__tests__/get-device-state.test.ts +12 -132
  28. package/__tests__/homescreen.test.ts +1 -41
  29. package/__tests__/kaspa-use-tweak-pro2.test.ts +2 -2
  30. package/__tests__/kaspaSignTransaction.test.ts +26 -3
  31. package/__tests__/logBlockEvent.test.ts +1 -1
  32. package/__tests__/method-protocol-support.test.ts +0 -19
  33. package/__tests__/open-wallet-session.test.ts +37 -568
  34. package/__tests__/protocol-v2-unlock-policy.test.ts +37 -300
  35. package/__tests__/protocol-v2.test.ts +1153 -1458
  36. package/__tests__/protocolV2FileWrite.test.ts +0 -152
  37. package/__tests__/protocolV2UiInteraction.test.ts +0 -63
  38. package/__tests__/public-pro2-api-boundary.test.ts +0 -1
  39. package/__tests__/search-devices.test.ts +3 -12
  40. package/__tests__/tron-sign-message-init.test.ts +2 -2
  41. package/dist/api/BaseMethod.d.ts +1 -3
  42. package/dist/api/BaseMethod.d.ts.map +1 -1
  43. package/dist/api/CheckAllFirmwareRelease.d.ts +1 -2
  44. package/dist/api/CheckAllFirmwareRelease.d.ts.map +1 -1
  45. package/dist/api/FirmwareUpdate.d.ts.map +1 -1
  46. package/dist/api/FirmwareUpdateV2.d.ts +10 -0
  47. package/dist/api/FirmwareUpdateV2.d.ts.map +1 -1
  48. package/dist/api/FirmwareUpdateV3.d.ts +7 -3
  49. package/dist/api/FirmwareUpdateV3.d.ts.map +1 -1
  50. package/dist/api/FirmwareUpdateV4.d.ts +27 -13
  51. package/dist/api/FirmwareUpdateV4.d.ts.map +1 -1
  52. package/dist/api/GetPassphraseState.d.ts.map +1 -1
  53. package/dist/api/OpenWalletSession.d.ts.map +1 -1
  54. package/dist/api/SearchDevices.d.ts.map +1 -1
  55. package/dist/api/allnetwork/AllNetworkGetAddressBase.d.ts.map +1 -1
  56. package/dist/api/device/DeviceSettings.d.ts.map +1 -1
  57. package/dist/api/device/DeviceUnlock.d.ts +2 -2
  58. package/dist/api/device/DeviceUnlock.d.ts.map +1 -1
  59. package/dist/api/device/DeviceUpdateBootloader.d.ts +5 -1
  60. package/dist/api/device/DeviceUpdateBootloader.d.ts.map +1 -1
  61. package/dist/api/firmware/FirmwareArtifactSource.d.ts +25 -0
  62. package/dist/api/firmware/FirmwareArtifactSource.d.ts.map +1 -0
  63. package/dist/api/firmware/FirmwareHostBinding.d.ts +6 -0
  64. package/dist/api/firmware/FirmwareHostBinding.d.ts.map +1 -0
  65. package/dist/api/firmware/FirmwarePreparationError.d.ts +3 -0
  66. package/dist/api/firmware/FirmwarePreparationError.d.ts.map +1 -0
  67. package/dist/api/firmware/FirmwareUpdateBaseMethod.d.ts +11 -4
  68. package/dist/api/firmware/FirmwareUpdateBaseMethod.d.ts.map +1 -1
  69. package/dist/api/firmware/FirmwareUpdateCapabilities.d.ts +3 -0
  70. package/dist/api/firmware/FirmwareUpdateCapabilities.d.ts.map +1 -0
  71. package/dist/api/firmware/FirmwareUpdatePlan.d.ts +25 -0
  72. package/dist/api/firmware/FirmwareUpdatePlan.d.ts.map +1 -0
  73. package/dist/api/firmware/FirmwareUpdatePreparedPlan.d.ts +32 -0
  74. package/dist/api/firmware/FirmwareUpdatePreparedPlan.d.ts.map +1 -0
  75. package/dist/api/firmware/getBinary.d.ts +7 -0
  76. package/dist/api/firmware/getBinary.d.ts.map +1 -1
  77. package/dist/api/firmware/progressThrottle.d.ts +3 -0
  78. package/dist/api/firmware/progressThrottle.d.ts.map +1 -0
  79. package/dist/api/firmware/updateBootloader.d.ts +2 -0
  80. package/dist/api/firmware/updateBootloader.d.ts.map +1 -1
  81. package/dist/api/firmware/uploadFirmware.d.ts +9 -1
  82. package/dist/api/firmware/uploadFirmware.d.ts.map +1 -1
  83. package/dist/api/helpers/protocolV2FileWrite.d.ts +0 -9
  84. package/dist/api/helpers/protocolV2FileWrite.d.ts.map +1 -1
  85. package/dist/api/index.d.ts +0 -2
  86. package/dist/api/index.d.ts.map +1 -1
  87. package/dist/api/kaspa/KaspaGetAddress.d.ts +1 -1
  88. package/dist/api/kaspa/KaspaSignTransaction.d.ts +1 -1
  89. package/dist/api/kaspa/KaspaSignTransaction.d.ts.map +1 -1
  90. package/dist/api/polkadot/PolkadotGetAddress.d.ts +1 -1
  91. package/dist/api/polkadot/networks.d.ts +1 -1
  92. package/dist/api/protocol-v2/ProtocolInfoRequest.d.ts.map +1 -1
  93. package/dist/api/protocol-v2/helpers.d.ts.map +1 -1
  94. package/dist/api/solana/SolSignMessage.d.ts +1 -1
  95. package/dist/api/solana/SolSignOffchainMessage.d.ts +1 -1
  96. package/dist/api/solana/SolSignTransaction.d.ts +2 -2
  97. package/dist/api/stellar/StellarSignTransaction.d.ts +1 -1
  98. package/dist/api/sui/SuiGetAddress.d.ts +1 -1
  99. package/dist/api/sui/SuiGetPublicKey.d.ts +1 -1
  100. package/dist/api/sui/SuiSignMessage.d.ts +1 -1
  101. package/dist/api/sui/SuiSignTransaction.d.ts +1 -1
  102. package/dist/api/ton/TonGetAddress.d.ts +1 -1
  103. package/dist/api/ton/TonSignMessage.d.ts +1 -1
  104. package/dist/api/ton/TonSignProof.d.ts +1 -1
  105. package/dist/api/tron/TronSignMessage.d.ts +2 -2
  106. package/dist/api/tron/TronSignTransaction.d.ts +1 -1
  107. package/dist/core/deviceEventRegistration.d.ts +0 -2
  108. package/dist/core/deviceEventRegistration.d.ts.map +1 -1
  109. package/dist/core/index.d.ts.map +1 -1
  110. package/dist/data-manager/DataManager.d.ts +4 -9
  111. package/dist/data-manager/DataManager.d.ts.map +1 -1
  112. package/dist/data-manager/TransportManager.d.ts.map +1 -1
  113. package/dist/data-manager/connectSettings.d.ts.map +1 -1
  114. package/dist/device/Device.d.ts +6 -29
  115. package/dist/device/Device.d.ts.map +1 -1
  116. package/dist/device/DeviceCommands.d.ts +4 -4
  117. package/dist/device/DeviceCommands.d.ts.map +1 -1
  118. package/dist/device/DeviceConnector.d.ts +1 -2
  119. package/dist/device/DeviceConnector.d.ts.map +1 -1
  120. package/dist/device/DevicePool.d.ts.map +1 -1
  121. package/dist/deviceProfile/protocolV2DeviceIdentity.d.ts.map +1 -1
  122. package/dist/events/device.d.ts +0 -4
  123. package/dist/events/device.d.ts.map +1 -1
  124. package/dist/events/logBlockEvent.d.ts.map +1 -1
  125. package/dist/events/ui-promise.d.ts +2 -4
  126. package/dist/events/ui-promise.d.ts.map +1 -1
  127. package/dist/events/ui-request.d.ts +2 -31
  128. package/dist/events/ui-request.d.ts.map +1 -1
  129. package/dist/events/ui-response.d.ts +2 -10
  130. package/dist/events/ui-response.d.ts.map +1 -1
  131. package/dist/index.d.ts +247 -243
  132. package/dist/index.d.ts.map +1 -1
  133. package/dist/index.js +3773 -3054
  134. package/dist/inject.d.ts +1 -6
  135. package/dist/inject.d.ts.map +1 -1
  136. package/dist/lowLevelInject.d.ts.map +1 -1
  137. package/dist/protocols/protocol-v2/features.d.ts +4 -0
  138. package/dist/protocols/protocol-v2/features.d.ts.map +1 -1
  139. package/dist/protocols/protocol-v2/firmware.d.ts.map +1 -1
  140. package/dist/protocols/protocol-v2/lockedError.d.ts +2 -0
  141. package/dist/protocols/protocol-v2/lockedError.d.ts.map +1 -0
  142. package/dist/protocols/protocol-v2/uiInteraction.d.ts +4 -7
  143. package/dist/protocols/protocol-v2/uiInteraction.d.ts.map +1 -1
  144. package/dist/protocols/protocol-v2/unlockPolicy.d.ts +3 -1
  145. package/dist/protocols/protocol-v2/unlockPolicy.d.ts.map +1 -1
  146. package/dist/protocols/protocol-v2/unlockRetry.d.ts +10 -0
  147. package/dist/protocols/protocol-v2/unlockRetry.d.ts.map +1 -0
  148. package/dist/protocols/protocol-v2/walletSession.d.ts +1 -6
  149. package/dist/protocols/protocol-v2/walletSession.d.ts.map +1 -1
  150. package/dist/topLevelInject.d.ts.map +1 -1
  151. package/dist/types/api/checkAllFirmwareRelease.d.ts +5 -3
  152. package/dist/types/api/checkAllFirmwareRelease.d.ts.map +1 -1
  153. package/dist/types/api/deviceUnlock.d.ts +1 -5
  154. package/dist/types/api/deviceUnlock.d.ts.map +1 -1
  155. package/dist/types/api/deviceUpdateBootloader.d.ts +6 -0
  156. package/dist/types/api/deviceUpdateBootloader.d.ts.map +1 -1
  157. package/dist/types/api/export.d.ts +4 -2
  158. package/dist/types/api/export.d.ts.map +1 -1
  159. package/dist/types/api/firmwareUpdate.d.ts +70 -4
  160. package/dist/types/api/firmwareUpdate.d.ts.map +1 -1
  161. package/dist/types/api/firmwareUpdateCapabilities.d.ts +9 -0
  162. package/dist/types/api/firmwareUpdateCapabilities.d.ts.map +1 -0
  163. package/dist/types/api/firmwareUpdatePlan.d.ts +28 -0
  164. package/dist/types/api/firmwareUpdatePlan.d.ts.map +1 -0
  165. package/dist/types/api/firmwareUpdatePreparedPlan.d.ts +42 -0
  166. package/dist/types/api/firmwareUpdatePreparedPlan.d.ts.map +1 -0
  167. package/dist/types/api/index.d.ts +10 -7
  168. package/dist/types/api/index.d.ts.map +1 -1
  169. package/dist/types/api/protocolV2.d.ts +0 -3
  170. package/dist/types/api/protocolV2.d.ts.map +1 -1
  171. package/dist/types/device.d.ts +2 -2
  172. package/dist/types/device.d.ts.map +1 -1
  173. package/dist/types/params.d.ts +0 -1
  174. package/dist/types/params.d.ts.map +1 -1
  175. package/dist/types/settings.d.ts +21 -38
  176. package/dist/types/settings.d.ts.map +1 -1
  177. package/dist/utils/deviceFeaturesCompat.d.ts +1 -0
  178. package/dist/utils/deviceFeaturesCompat.d.ts.map +1 -1
  179. package/dist/utils/deviceFeaturesUtils.d.ts +0 -4
  180. package/dist/utils/deviceFeaturesUtils.d.ts.map +1 -1
  181. package/dist/utils/deviceInfoUtils.d.ts.map +1 -1
  182. package/dist/utils/deviceSettings.d.ts.map +1 -1
  183. package/dist/utils/homescreen.d.ts +0 -4
  184. package/dist/utils/homescreen.d.ts.map +1 -1
  185. package/dist/utils/index.d.ts +1 -1
  186. package/dist/utils/index.d.ts.map +1 -1
  187. package/dist/utils/patch.d.ts +1 -1
  188. package/dist/utils/patch.d.ts.map +1 -1
  189. package/dist/utils/pro2Wallpaper.d.ts +0 -10
  190. package/dist/utils/pro2Wallpaper.d.ts.map +1 -1
  191. package/package.json +4 -4
  192. package/src/api/BaseMethod.ts +10 -8
  193. package/src/api/CheckAllFirmwareRelease.ts +60 -59
  194. package/src/api/FirmwareUpdate.ts +15 -7
  195. package/src/api/FirmwareUpdateV2.ts +298 -126
  196. package/src/api/FirmwareUpdateV3.ts +265 -63
  197. package/src/api/FirmwareUpdateV4.ts +1017 -602
  198. package/src/api/GetPassphraseState.ts +1 -7
  199. package/src/api/OpenWalletSession.ts +17 -71
  200. package/src/api/SearchDevices.ts +1 -3
  201. package/src/api/allnetwork/AllNetworkGetAddress.ts +21 -21
  202. package/src/api/allnetwork/AllNetworkGetAddressBase.ts +11 -36
  203. package/src/api/device/DeviceSettings.ts +4 -5
  204. package/src/api/device/DeviceUnlock.ts +3 -8
  205. package/src/api/device/DeviceUpdateBootloader.ts +125 -6
  206. package/src/api/firmware/FirmwareArtifactSource.ts +278 -0
  207. package/src/api/firmware/FirmwareHostBinding.ts +100 -0
  208. package/src/api/firmware/FirmwarePreparationError.ts +12 -0
  209. package/src/api/firmware/FirmwareUpdateBaseMethod.ts +83 -27
  210. package/src/api/firmware/FirmwareUpdateCapabilities.ts +9 -0
  211. package/src/api/firmware/FirmwareUpdatePlan.ts +772 -0
  212. package/src/api/firmware/FirmwareUpdatePreparedPlan.ts +449 -0
  213. package/src/api/firmware/progressThrottle.ts +44 -0
  214. package/src/api/firmware/updateBootloader.ts +19 -4
  215. package/src/api/firmware/uploadFirmware.ts +144 -39
  216. package/src/api/helpers/protocolV2FileWrite.ts +63 -202
  217. package/src/api/index.ts +0 -2
  218. package/src/api/kaspa/KaspaGetAddress.ts +1 -1
  219. package/src/api/kaspa/KaspaSignTransaction.ts +13 -2
  220. package/src/api/polkadot/networks.ts +3 -3
  221. package/src/api/protocol-v2/ProtocolInfoRequest.ts +1 -3
  222. package/src/api/protocol-v2/helpers.ts +1 -1
  223. package/src/api/solana/SolSignMessage.ts +1 -1
  224. package/src/api/solana/SolSignOffchainMessage.ts +1 -1
  225. package/src/api/solana/SolSignTransaction.ts +2 -2
  226. package/src/api/sui/SuiGetAddress.ts +1 -1
  227. package/src/api/sui/SuiGetPublicKey.ts +1 -1
  228. package/src/api/sui/SuiSignMessage.ts +1 -1
  229. package/src/api/sui/SuiSignTransaction.ts +1 -1
  230. package/src/api/ton/TonGetAddress.ts +1 -1
  231. package/src/api/ton/TonSignMessage.ts +1 -1
  232. package/src/api/ton/TonSignProof.ts +1 -1
  233. package/src/api/tron/TronSignMessage.ts +2 -2
  234. package/src/api/tron/TronSignTransaction.ts +1 -1
  235. package/src/core/deviceEventRegistration.ts +0 -4
  236. package/src/core/index.ts +111 -213
  237. package/src/data/messages/messages-protocol-v2.json +0 -25
  238. package/src/data-manager/DataManager.ts +41 -113
  239. package/src/data-manager/TransportManager.ts +0 -6
  240. package/src/data-manager/connectSettings.ts +11 -0
  241. package/src/device/Device.ts +49 -274
  242. package/src/device/DeviceCommands.ts +4 -31
  243. package/src/device/DeviceConnector.ts +13 -33
  244. package/src/device/DevicePool.ts +7 -21
  245. package/src/deviceProfile/buildDeviceFeatures.ts +2 -2
  246. package/src/deviceProfile/protocolV2DeviceIdentity.ts +0 -3
  247. package/src/events/device.ts +0 -4
  248. package/src/events/logBlockEvent.ts +0 -1
  249. package/src/events/ui-promise.ts +2 -4
  250. package/src/events/ui-request.ts +2 -36
  251. package/src/events/ui-response.ts +2 -12
  252. package/src/index.ts +5 -0
  253. package/src/inject.ts +24 -60
  254. package/src/lowLevelInject.ts +8 -7
  255. package/src/protocols/protocol-v2/features.ts +7 -10
  256. package/src/protocols/protocol-v2/firmware.ts +0 -2
  257. package/src/protocols/protocol-v2/lockedError.ts +10 -0
  258. package/src/protocols/protocol-v2/uiInteraction.ts +6 -46
  259. package/src/protocols/protocol-v2/unlockPolicy.ts +105 -1
  260. package/src/protocols/protocol-v2/unlockRetry.ts +109 -0
  261. package/src/protocols/protocol-v2/walletSession.ts +36 -214
  262. package/src/topLevelInject.ts +8 -7
  263. package/src/types/api/checkAllFirmwareRelease.ts +5 -3
  264. package/src/types/api/deviceUnlock.ts +1 -12
  265. package/src/types/api/deviceUpdateBootloader.ts +6 -0
  266. package/src/types/api/export.ts +18 -1
  267. package/src/types/api/firmwareUpdate.ts +78 -6
  268. package/src/types/api/firmwareUpdateCapabilities.ts +9 -0
  269. package/src/types/api/firmwareUpdatePlan.ts +38 -0
  270. package/src/types/api/firmwareUpdatePreparedPlan.ts +53 -0
  271. package/src/types/api/index.ts +14 -13
  272. package/src/types/api/protocolV2.ts +0 -13
  273. package/src/types/device.ts +3 -15
  274. package/src/types/params.ts +1 -7
  275. package/src/types/settings.ts +22 -60
  276. package/src/utils/deviceFeaturesCompat.ts +6 -5
  277. package/src/utils/deviceFeaturesUtils.ts +3 -14
  278. package/src/utils/deviceInfoUtils.ts +0 -2
  279. package/src/utils/deviceSettings.ts +0 -3
  280. package/src/utils/homescreen.ts +6 -32
  281. package/src/utils/index.ts +1 -6
  282. package/src/utils/pro2Wallpaper.ts +8 -35
  283. package/__tests__/core-initialization.test.ts +0 -23
  284. package/__tests__/device-connector-protocol.test.ts +0 -81
  285. package/__tests__/deviceUploadNft.test.ts +0 -316
  286. package/__tests__/pro2Nft.test.ts +0 -108
  287. package/__tests__/protocol-binding.test.ts +0 -89
  288. package/__tests__/protocol-v2-resources.test.ts +0 -340
  289. package/__tests__/protocol-v2-ui-lifecycle.test.ts +0 -91
  290. package/__tests__/uiProgressThrottle.test.ts +0 -74
  291. package/__tests__/uiPromiseRegistry.test.ts +0 -115
  292. package/dist/api/DetectDeviceConnectProtocol.d.ts +0 -7
  293. package/dist/api/DetectDeviceConnectProtocol.d.ts.map +0 -1
  294. package/dist/api/protocol-v2/DeviceUploadNft.d.ts +0 -31
  295. package/dist/api/protocol-v2/DeviceUploadNft.d.ts.map +0 -1
  296. package/dist/core/uiPromiseRegistry.d.ts +0 -6
  297. package/dist/core/uiPromiseRegistry.d.ts.map +0 -1
  298. package/dist/protocols/protocol-v2/resources.d.ts +0 -30
  299. package/dist/protocols/protocol-v2/resources.d.ts.map +0 -1
  300. package/dist/protocols/protocol-v2/unlockPolicyRunner.d.ts +0 -22
  301. package/dist/protocols/protocol-v2/unlockPolicyRunner.d.ts.map +0 -1
  302. package/dist/types/api/detectDeviceConnectProtocol.d.ts +0 -4
  303. package/dist/types/api/detectDeviceConnectProtocol.d.ts.map +0 -1
  304. package/dist/utils/pro2Nft.d.ts +0 -31
  305. package/dist/utils/pro2Nft.d.ts.map +0 -1
  306. package/dist/utils/uiProgressThrottle.d.ts +0 -3
  307. package/dist/utils/uiProgressThrottle.d.ts.map +0 -1
  308. package/src/api/DetectDeviceConnectProtocol.ts +0 -18
  309. package/src/api/protocol-v2/DeviceUploadNft.ts +0 -197
  310. package/src/core/uiPromiseRegistry.ts +0 -63
  311. package/src/protocols/protocol-v2/resources.ts +0 -390
  312. package/src/protocols/protocol-v2/unlockPolicyRunner.ts +0 -131
  313. package/src/types/api/detectDeviceConnectProtocol.ts +0 -6
  314. package/src/utils/pro2Nft.ts +0 -142
  315. package/src/utils/uiProgressThrottle.ts +0 -63
@@ -5,7 +5,6 @@ import CheckAllFirmwareRelease, {
5
5
  } from '../src/api/CheckAllFirmwareRelease';
6
6
  import { DataManager } from '../src/data-manager';
7
7
  import { createCoreApi } from '../src/inject';
8
- import { PROTOCOL_V2_RESOURCE_DEVICE_PATHS } from '../src/protocols/protocol-v2/resources';
9
8
 
10
9
  import type { CoreApi } from '../src/types/api';
11
10
  import type { DeviceStateVersions, IFirmwareReleaseInfo } from '../src/types';
@@ -73,74 +72,7 @@ const release: IFirmwareReleaseInfo = {
73
72
  ],
74
73
  };
75
74
 
76
- const stableResources = ['images', 'animation', 'wallpaper', 'translations', 'roobert', 'noto'].map(
77
- (type, index) => ({
78
- type,
79
- url: `https://example.com/${type}.okpkg`,
80
- size: 0x52a0 + index + 1,
81
- fileHash: 'a'.repeat(64),
82
- headerHash: index.toString(16).padStart(128, '0'),
83
- })
84
- );
85
-
86
- const createFilesystemTypedCall = (missingAll = false) => {
87
- const resourceByPath = new Map(
88
- stableResources.map(resource => [
89
- PROTOCOL_V2_RESOURCE_DEVICE_PATHS[
90
- resource.type as keyof typeof PROTOCOL_V2_RESOURCE_DEVICE_PATHS
91
- ],
92
- resource,
93
- ])
94
- );
95
- return jest.fn((requestType: string, _responseType: string, payload: Record<string, any>) => {
96
- if (requestType === 'ResourceInventoryGet') {
97
- throw new Error('ResourceInventoryGet is unavailable on released firmware');
98
- }
99
- if (requestType === 'FilesystemPathInfoQuery') {
100
- const resource = resourceByPath.get(payload.path);
101
- return {
102
- message: {
103
- exist: Boolean(resource) && !missingAll,
104
- directory: false,
105
- size: missingAll ? 0 : resource?.size,
106
- },
107
- };
108
- }
109
- if (requestType === 'FilesystemFileRead') {
110
- const resource = resourceByPath.get(payload.file.path);
111
- if (!resource || missingAll) throw new Error('missing resource');
112
- const header = new Uint8Array(0x52a0);
113
- const view = new DataView(header.buffer);
114
- 'OKPP'.split('').forEach((char, index) => {
115
- header[index] = char.charCodeAt(0);
116
- });
117
- 'RESC'.split('').forEach((char, index) => {
118
- header[0x08 + index] = char.charCodeAt(0);
119
- });
120
- view.setUint32(0x0c, header.byteLength, true);
121
- for (let index = 0; index < resource.headerHash.length / 2; index++) {
122
- header[0x240 + index] = Number.parseInt(
123
- resource.headerHash.slice(index * 2, index * 2 + 2),
124
- 16
125
- );
126
- }
127
- const offset = Number(payload.file.offset);
128
- const chunkLength = Number(payload.chunk_len);
129
- return {
130
- message: {
131
- data: header.slice(offset, offset + chunkLength),
132
- },
133
- };
134
- }
135
- throw new Error(`Unexpected request: ${requestType}`);
136
- });
137
- };
138
-
139
75
  describe('checkAllFirmwareRelease Protocol V2 support', () => {
140
- afterEach(() => {
141
- jest.restoreAllMocks();
142
- });
143
-
144
76
  test('builds ordered firmwareUpdateV4 targets from recommended component versions', () => {
145
77
  const result = buildProtocolV2FirmwareRelease({
146
78
  currentVersions,
@@ -152,7 +84,7 @@ describe('checkAllFirmwareRelease Protocol V2 support', () => {
152
84
  status: 'required',
153
85
  hasUpgrade: true,
154
86
  required: true,
155
- targetsToUpdate: ['boot', 'app_v1'],
87
+ targetsToUpdate: ['boot', 'app_v1', 'resource'],
156
88
  components: [
157
89
  { configKey: 'bootloader', status: 'outdated', updateTarget: 'boot' },
158
90
  { configKey: 'applicationP1', status: 'outdated', updateTarget: 'app_v1' },
@@ -210,7 +142,6 @@ describe('checkAllFirmwareRelease Protocol V2 support', () => {
210
142
  applicationP1Hash: 'aa'.repeat(32),
211
143
  applicationP2Hash: 'bb'.repeat(32),
212
144
  },
213
- checkFirmwareHash: true,
214
145
  remotePayloadHashes: {
215
146
  applicationP1: 'aa'.repeat(64),
216
147
  applicationP2: 'cc'.repeat(64),
@@ -229,37 +160,6 @@ describe('checkAllFirmwareRelease Protocol V2 support', () => {
229
160
  });
230
161
  });
231
162
 
232
- test('uses version-only comparison for same-version packages by default', () => {
233
- const packageSet: IFirmwareReleaseInfo = {
234
- ...release,
235
- required: false,
236
- resourceBundles: undefined,
237
- installOrder: ['applicationP1'],
238
- components: {
239
- applicationP1: {
240
- target: 'APPLICATION_P1',
241
- version: [1, 0, 0],
242
- url: 'https://example.com/application-p1.okpkg',
243
- payloadHash: 'cc'.repeat(64),
244
- },
245
- },
246
- };
247
-
248
- expect(
249
- buildProtocolV2FirmwareRelease({
250
- currentVersions: { ...currentVersions, applicationP1: '1.0.0' },
251
- currentVerification: { applicationP1Hash: 'aa'.repeat(32) },
252
- firmwareType: EFirmwareType.Universal,
253
- release: packageSet,
254
- })
255
- ).toMatchObject({
256
- status: 'valid',
257
- hasUpgrade: false,
258
- targetsToUpdate: [],
259
- components: [{ configKey: 'applicationP1', status: 'valid' }],
260
- });
261
- });
262
-
263
163
  test('keeps same-version hash-aware components unknown without metadata payloadHash', () => {
264
164
  const packageSet: IFirmwareReleaseInfo = {
265
165
  ...release,
@@ -280,7 +180,6 @@ describe('checkAllFirmwareRelease Protocol V2 support', () => {
280
180
  buildProtocolV2FirmwareRelease({
281
181
  currentVersions: { ...currentVersions, applicationP1: '1.0.0' },
282
182
  currentVerification: { applicationP1Hash: 'aa'.repeat(32) },
283
- checkFirmwareHash: true,
284
183
  firmwareType: EFirmwareType.Universal,
285
184
  release: packageSet,
286
185
  })
@@ -316,7 +215,6 @@ describe('checkAllFirmwareRelease Protocol V2 support', () => {
316
215
  const result = buildProtocolV2FirmwareRelease({
317
216
  currentVersions,
318
217
  currentVerification: { applicationP1Hash: 'aa'.repeat(32) },
319
- checkFirmwareHash: true,
320
218
  remotePayloadHashes: { applicationP1: 'cc'.repeat(64) },
321
219
  firmwareType: EFirmwareType.Universal,
322
220
  release: packageSet,
@@ -325,7 +223,7 @@ describe('checkAllFirmwareRelease Protocol V2 support', () => {
325
223
  expect(result.targetsToUpdate).toEqual(['app_v1', 'app_v2']);
326
224
  });
327
225
 
328
- test('does not read vol0 resource inventory while Protocol V2 is in Application mode', async () => {
226
+ test('uses the existing method on Protocol V2 and keeps its public API name', async () => {
329
227
  const method = new CheckAllFirmwareRelease({
330
228
  id: 1,
331
229
  payload: {
@@ -342,7 +240,6 @@ describe('checkAllFirmwareRelease Protocol V2 support', () => {
342
240
  status: { mode: 'normal' },
343
241
  versions: currentVersions,
344
242
  });
345
- const typedCall = createFilesystemTypedCall(true);
346
243
  method.device = {
347
244
  isProtocolV2: () => true,
348
245
  features: {
@@ -350,124 +247,32 @@ describe('checkAllFirmwareRelease Protocol V2 support', () => {
350
247
  firmwareVersion: '1.0.0',
351
248
  },
352
249
  getDeviceState,
353
- getCommands: () => ({ typedCall }),
354
250
  } as unknown as CheckAllFirmwareRelease['device'];
355
251
  jest.spyOn(DataManager, 'getFirmwareLatestRelease').mockReturnValue(release);
356
- jest.spyOn(DataManager, 'getProtocolV2Resources').mockReturnValue(stableResources as any);
357
252
 
358
253
  await expect(method.run()).resolves.toMatchObject({
359
254
  protocol: 'V2',
360
255
  deviceType: 'pro2',
361
256
  status: 'required',
362
- resourceStatus: 'unknown',
363
- targetsToUpdate: ['boot', 'app_v1'],
257
+ targetsToUpdate: ['boot', 'app_v1', 'resource'],
364
258
  firmware: {
365
259
  status: 'required',
366
260
  },
367
261
  });
368
- expect(typedCall).not.toHaveBeenCalled();
369
- expect(getDeviceState).toHaveBeenCalledWith({
370
- refreshSections: ['identity', 'versions'],
371
- });
372
262
  expect(method.getSupportedProtocols()).toEqual(['V1', 'V2']);
373
263
  });
374
264
 
375
- test('requests and compares firmware hashes only when explicitly enabled', async () => {
376
- const packageSet: IFirmwareReleaseInfo = {
377
- ...release,
378
- required: false,
379
- resourceBundles: undefined,
380
- installOrder: ['applicationP1'],
381
- components: {
382
- applicationP1: {
383
- target: 'APPLICATION_P1',
384
- version: [1, 0, 0],
385
- url: 'https://example.com/application-p1.okpkg',
386
- payloadHash: 'cc'.repeat(64),
387
- },
388
- },
389
- };
390
- const method = new CheckAllFirmwareRelease({
391
- id: 1,
392
- payload: {
393
- method: 'checkAllFirmwareRelease',
394
- firmwareType: EFirmwareType.Universal,
395
- checkFirmwareHash: true,
396
- },
397
- });
398
- method.init();
399
- const getDeviceState = jest.fn().mockResolvedValue({
400
- identity: { deviceType: 'pro2', firmwareType: EFirmwareType.Universal },
401
- status: { mode: 'normal' },
402
- versions: { ...currentVersions, applicationP1: '1.0.0' },
403
- verification: { applicationP1Hash: 'aa'.repeat(32) },
404
- });
405
- method.device = {
406
- isProtocolV2: () => true,
407
- features: { deviceType: 'pro2', firmwareVersion: '1.0.0' },
408
- getDeviceState,
409
- getCommands: () => ({ typedCall: jest.fn() }),
410
- } as unknown as CheckAllFirmwareRelease['device'];
411
- jest.spyOn(DataManager, 'getFirmwareLatestRelease').mockReturnValue(packageSet);
412
- jest.spyOn(DataManager, 'getProtocolV2Resources').mockReturnValue(undefined);
413
-
414
- await expect(method.run()).resolves.toMatchObject({
415
- status: 'outdated',
416
- targetsToUpdate: ['app_v1'],
417
- });
418
- expect(getDeviceState).toHaveBeenCalledWith({
419
- refreshSections: ['identity', 'versions', 'verification'],
420
- });
421
- });
422
-
423
- test.each(['bootloader', 'romloader'] as const)(
424
- 'uses filesystem inventory in %s mode instead of forcing all resources',
425
- async mode => {
426
- const method = new CheckAllFirmwareRelease({
427
- id: 1,
428
- payload: {
429
- method: 'checkAllFirmwareRelease',
430
- firmwareType: EFirmwareType.Universal,
431
- },
432
- });
433
- method.init();
434
- const typedCall = createFilesystemTypedCall();
435
- method.device = {
436
- isProtocolV2: () => true,
437
- features: { deviceType: 'pro2', firmwareVersion: '1.0.0' },
438
- getDeviceState: jest.fn().mockResolvedValue({
439
- identity: { deviceType: 'pro2', firmwareType: EFirmwareType.Universal },
440
- status: { mode },
441
- versions: currentVersions,
442
- }),
443
- getCommands: () => ({ typedCall }),
444
- } as unknown as CheckAllFirmwareRelease['device'];
445
- jest.spyOn(DataManager, 'getFirmwareLatestRelease').mockReturnValue(release);
446
- jest.spyOn(DataManager, 'getProtocolV2Resources').mockReturnValue(stableResources as any);
447
-
448
- await expect(method.run()).resolves.toMatchObject({
449
- protocol: 'V2',
450
- resourceStatus: 'valid',
451
- targetsToUpdate: ['boot', 'app_v1'],
452
- });
453
- expect(typedCall.mock.calls.some(call => call[0] === 'ResourceInventoryGet')).toBe(false);
454
- expect(typedCall.mock.calls.some(call => call[0] === 'FilesystemFileRead')).toBe(true);
455
- }
456
- );
457
-
458
265
  test('continues forwarding the existing public method', async () => {
459
266
  const call = jest.fn().mockResolvedValue({ success: true, payload: {} });
460
267
  const api = createCoreApi(call as CoreApi['call']) as CoreApi;
461
268
 
462
269
  await api.checkAllFirmwareRelease('pro2-connect-id', {
463
- checkFirmwareHash: true,
464
270
  firmwareType: EFirmwareType.Universal,
465
271
  retryCount: 0,
466
272
  });
467
273
 
468
274
  expect(call).toHaveBeenCalledWith({
469
275
  connectId: 'pro2-connect-id',
470
- checkFirmwareHash: true,
471
276
  firmwareType: EFirmwareType.Universal,
472
277
  retryCount: 0,
473
278
  method: 'checkAllFirmwareRelease',
@@ -1,19 +1,61 @@
1
+ import DataManager from '../src/data-manager/DataManager';
1
2
  import { parseConnectSettings } from '../src/data-manager/connectSettings';
2
3
 
4
+ import type { RemoteConfigResponse } from '../src/types';
5
+
6
+ jest.mock('axios', () => ({
7
+ get: jest.fn(),
8
+ }));
9
+
3
10
  jest.mock('../src/data/config', () => ({
4
11
  getSDKVersion: jest.fn(() => '1.0.0'),
5
12
  DEFAULT_DOMAIN: 'https://jssdk.onekey.so/1.0.0/',
6
13
  }));
7
14
 
15
+ const mockAxiosGet: jest.Mock = jest.requireMock('axios').get;
16
+
8
17
  describe('parseConnectSettings', () => {
9
- it('keeps custom configFetcher in parsed settings', () => {
10
- const configFetcher = jest.fn();
18
+ const preloadedConfig = {
19
+ bridge: {},
20
+ classic: { firmware: [], ble: [] },
21
+ classic1s: { firmware: [], ble: [] },
22
+ classicpure: { firmware: [], ble: [] },
23
+ mini: { firmware: [], ble: [] },
24
+ touch: { firmware: [], ble: [] },
25
+ pro: { firmware: [], ble: [] },
26
+ pro2: { firmware: [], ble: [] },
27
+ } as unknown as RemoteConfigResponse;
28
+
29
+ it('keeps a serializable preloaded config in parsed settings', () => {
30
+ const settings = parseConnectSettings({
31
+ firmwareManifestMode: 'sdk-managed',
32
+ preloadedConfig,
33
+ });
34
+
35
+ expect(settings.firmwareManifestMode).toBe('sdk-managed');
36
+ expect(settings.preloadedConfig).toBe(preloadedConfig);
37
+ });
38
+
39
+ it('uses the preloaded config before the SDK network client', async () => {
40
+ const settings = parseConnectSettings({
41
+ firmwareManifestMode: 'sdk-managed',
42
+ preloadedConfig,
43
+ });
44
+
45
+ await DataManager.load(settings);
46
+
47
+ expect(mockAxiosGet).not.toHaveBeenCalled();
48
+ expect(DataManager.deviceMap.classic).toEqual({ firmware: [], ble: [] });
49
+ });
11
50
 
51
+ it('fails closed without a preloaded config in external-only mode', async () => {
12
52
  const settings = parseConnectSettings({
13
- fetchConfig: true,
14
- configFetcher,
53
+ firmwareManifestMode: 'external-only',
15
54
  });
16
55
 
17
- expect(settings.configFetcher).toBe(configFetcher);
56
+ await expect(DataManager.load(settings)).rejects.toThrow(
57
+ 'External firmware config snapshot is required'
58
+ );
59
+ expect(mockAxiosGet).not.toHaveBeenCalled();
18
60
  });
19
61
  });
@@ -0,0 +1,56 @@
1
+ import { Device } from '../src/device/Device';
2
+ import TransportManager from '../src/data-manager/TransportManager';
3
+
4
+ jest.mock('../src/data/config', () => ({
5
+ getSDKVersion: jest.fn(() => '1.0.0'),
6
+ DEFAULT_DOMAIN: 'https://jssdk.onekey.so/1.0.0/',
7
+ }));
8
+
9
+ function buildV1Device() {
10
+ const device = Object.create(Device.prototype) as Device;
11
+ const typedCall = jest.fn(() => Promise.resolve({ message: { device_id: 'device' } }));
12
+ Object.assign(device, {
13
+ commands: { typedCall },
14
+ stateStore: { getState: () => undefined },
15
+ isProtocolV2: () => false,
16
+ _updateFeatures: jest.fn(),
17
+ getInternalState: jest.fn(() => undefined),
18
+ });
19
+ return { device, typedCall };
20
+ }
21
+
22
+ describe('Device.initialize Protocol V1 timeout', () => {
23
+ beforeEach(() => {
24
+ jest.spyOn(TransportManager, 'reconfigure').mockResolvedValue(undefined);
25
+ });
26
+
27
+ afterEach(() => {
28
+ jest.restoreAllMocks();
29
+ });
30
+
31
+ test('passes a custom Initialize timeout through to typedCall', async () => {
32
+ const { device, typedCall } = buildV1Device();
33
+
34
+ await device.initialize({ timeoutMs: 2500 });
35
+
36
+ expect(typedCall).toHaveBeenCalledWith(
37
+ 'Initialize',
38
+ 'Features',
39
+ expect.objectContaining({ is_contains_attach: true }),
40
+ { timeoutMs: 2500 }
41
+ );
42
+ });
43
+
44
+ test('keeps the 25s Initialize timeout by default', async () => {
45
+ const { device, typedCall } = buildV1Device();
46
+
47
+ await device.initialize();
48
+
49
+ expect(typedCall).toHaveBeenCalledWith(
50
+ 'Initialize',
51
+ 'Features',
52
+ expect.objectContaining({ is_contains_attach: true }),
53
+ { timeoutMs: 25 * 1000 }
54
+ );
55
+ });
56
+ });
@@ -1,4 +1,3 @@
1
- import { HardwareErrorCode } from '@onekeyfe/hd-shared';
2
1
  import { TRANSPORT_EVENT } from '@onekeyfe/hd-transport';
3
2
 
4
3
  import { initConnector, initCore } from '../src/core';
@@ -96,25 +95,7 @@ describe('public device lifecycle events', () => {
96
95
  expect(messages.filter(message => message.type === DEVICE.DISCONNECT)).toHaveLength(1);
97
96
  });
98
97
 
99
- test('uses a verified cached protocol as a strict expected protocol', async () => {
100
- jest.spyOn(DataManager, 'getSettings').mockReturnValue('react-native' as never);
101
- const device = Device.fromDescriptor({
102
- id: 'ble-id',
103
- path: 'ble-id',
104
- commType: 'ble',
105
- protocolType: 'V1',
106
- } as never);
107
- const acquire = jest.fn().mockResolvedValue({ uuid: 'ble-id', protocolType: 'V1' });
108
- device.deviceConnector = { acquire } as never;
109
-
110
- await device.acquire();
111
-
112
- expect(acquire).toHaveBeenCalledWith('ble-id', undefined, true, 'V1', undefined);
113
- expect(device.getProtocol()).toBe('V1');
114
- expect(device.originalDescriptor.protocolType).toBe('V1');
115
- });
116
-
117
- test('bypasses a cached protocol only for explicit active detection', async () => {
98
+ test('uses a cached protocol as a fallback-capable acquire hint', async () => {
118
99
  jest.spyOn(DataManager, 'getSettings').mockReturnValue('react-native' as never);
119
100
  const device = Device.fromDescriptor({
120
101
  id: 'ble-id',
@@ -125,96 +106,13 @@ describe('public device lifecycle events', () => {
125
106
  const acquire = jest.fn().mockResolvedValue({ uuid: 'ble-id', protocolType: 'V2' });
126
107
  device.deviceConnector = { acquire } as never;
127
108
 
128
- await device.acquire(undefined, { forceProtocolDetection: true });
109
+ await device.acquire();
129
110
 
130
- expect(acquire).toHaveBeenCalledWith('ble-id', undefined, true, undefined, undefined);
111
+ expect(acquire).toHaveBeenCalledWith('ble-id', undefined, true, undefined, 'V1');
131
112
  expect(device.getProtocol()).toBe('V2');
132
113
  expect(device.originalDescriptor.protocolType).toBe('V2');
133
114
  });
134
115
 
135
- test('does not reuse a stale protocol when active detection returns no protocol', async () => {
136
- jest.spyOn(DataManager, 'getSettings').mockReturnValue('react-native' as never);
137
- const device = Device.fromDescriptor({
138
- id: 'ble-id',
139
- path: 'ble-id',
140
- commType: 'ble',
141
- protocolType: 'V1',
142
- } as never);
143
- const acquire = jest.fn().mockResolvedValue({ uuid: 'ble-id' });
144
- const release = jest.fn().mockResolvedValue(undefined);
145
- device.deviceConnector = { acquire, release } as never;
146
- await expect(
147
- device.acquire(undefined, {
148
- forceProtocolDetection: true,
149
- throwOnRunPromiseError: true,
150
- })
151
- ).rejects.toMatchObject({ errorCode: HardwareErrorCode.RuntimeError });
152
- expect(device.originalDescriptor.protocolType).toBe('V1');
153
- expect(device.hasDeviceAcquire()).toBe(false);
154
- expect(release).toHaveBeenCalledWith('ble-id', false);
155
- });
156
-
157
- test('actively reacquires an already connected device without initializing it', async () => {
158
- jest.spyOn(DataManager, 'getSettings').mockReturnValue('webusb' as never);
159
- const device = Device.fromDescriptor({
160
- id: 'usb-device',
161
- path: 'usb-device',
162
- session: 'old-session',
163
- protocolType: 'V1',
164
- } as never);
165
- device.mainId = 'old-session';
166
- device.commands = { disposed: false } as never;
167
- const release = jest.spyOn(device, 'release').mockImplementation(() => {
168
- device.mainId = null;
169
- device.originalDescriptor.session = null;
170
- device.commands.disposed = true;
171
- return Promise.resolve();
172
- });
173
- const acquire = jest.spyOn(device, 'acquire').mockImplementation(() => {
174
- device.mainId = 'new-session';
175
- device.originalDescriptor.session = 'new-session';
176
- device.originalDescriptor.protocolType = 'V2';
177
- device.commands.disposed = false;
178
- return Promise.resolve();
179
- });
180
- const initialize = jest.spyOn(device, 'initialize').mockResolvedValue(undefined);
181
-
182
- await device.run(() => Promise.resolve(undefined), {
183
- forceProtocolDetection: true,
184
- skipInitialize: true,
185
- });
186
-
187
- expect(release).toHaveBeenCalled();
188
- expect(acquire).toHaveBeenCalledWith(undefined, {
189
- forceProtocolDetection: true,
190
- });
191
- expect(initialize).not.toHaveBeenCalled();
192
- expect(device.getProtocol()).toBe('V2');
193
- });
194
-
195
- test('keeps the freshly probed React Native BLE session until the call completes', async () => {
196
- jest.spyOn(DataManager, 'getSettings').mockReturnValue('react-native' as never);
197
- const device = Device.fromDescriptor({
198
- id: 'ble-device',
199
- path: 'ble-device',
200
- commType: 'ble',
201
- protocolType: 'V1',
202
- } as never);
203
- device.mainId = 'ble-device';
204
- device.commands = { disposed: false } as never;
205
- (device as unknown as { deviceAcquired: boolean }).deviceAcquired = true;
206
- const release = jest.spyOn(device, 'release').mockResolvedValue(undefined);
207
- const run = jest.fn().mockResolvedValue(undefined);
208
-
209
- await device.run(run, {
210
- forceProtocolDetection: true,
211
- skipInitialize: true,
212
- });
213
-
214
- expect(run).toHaveBeenCalledTimes(1);
215
- expect(release).toHaveBeenCalledTimes(1);
216
- });
217
-
218
116
  test('keeps an explicit connectProtocol as a strict expected protocol', async () => {
219
117
  jest.spyOn(DataManager, 'getSettings').mockReturnValue('react-native' as never);
220
118
  const device = Device.fromDescriptor({
@@ -38,28 +38,6 @@ describe('DevicePool state lifecycle', () => {
38
38
  expect(getDeviceState).toHaveBeenNthCalledWith(2, { refreshSections: ['settings'] });
39
39
  });
40
40
 
41
- test('actively re-detects a cached device when protocol detection is forced', async () => {
42
- const descriptor = { path: 'cached-path', protocolType: 'V1' } as any;
43
- const device = Device.fromDescriptor(descriptor);
44
- const acquire = jest.spyOn(device, 'acquire').mockImplementation(() => {
45
- device.originalDescriptor.protocolType = 'V2';
46
- return Promise.resolve(true);
47
- });
48
- const initialize = jest.spyOn(device, 'initialize').mockResolvedValue(undefined);
49
- const release = jest.spyOn(device, 'release').mockResolvedValue(undefined);
50
- DevicePool.devicesCache = { 'cached-id': device };
51
-
52
- const result = await DevicePool.getDevices([descriptor], 'cached-id', {
53
- forceProtocolDetection: true,
54
- });
55
-
56
- expect(acquire).toHaveBeenCalledWith(undefined, { forceProtocolDetection: true });
57
- expect(initialize).toHaveBeenCalledWith({ forceProtocolDetection: true });
58
- expect(release).toHaveBeenCalledTimes(1);
59
- expect(device.originalDescriptor.protocolType).toBe('V2');
60
- expect(result.deviceList).toEqual([device]);
61
- });
62
-
63
41
  test('keeps a discovered device when its Protocol V2 label cannot be read', async () => {
64
42
  const labelError = new Error('settings unavailable');
65
43
  const getDeviceState = jest
@@ -115,8 +115,8 @@ describe('DeviceSettings protocol routing', () => {
115
115
  );
116
116
  });
117
117
 
118
- it('uses DeviceSettingsSet and reloads Protocol V2 status and settings from the device', async () => {
119
- const { device, typedCall, updateState, getDeviceState } = createDevice({ protocol: 'V2' });
118
+ it('uses DeviceSettingsSet and commits the confirmed patch for Protocol V2', async () => {
119
+ const { device, typedCall, updateState } = createDevice({ protocol: 'V2' });
120
120
  const method = new DeviceSettings({
121
121
  id: 2,
122
122
  payload: {
@@ -141,10 +141,21 @@ describe('DeviceSettings protocol routing', () => {
141
141
  haptic_feedback: true,
142
142
  },
143
143
  });
144
- expect(getDeviceState).toHaveBeenCalledWith({
145
- refreshSections: ['status', 'settings'],
146
- });
147
- expect(updateState).not.toHaveBeenCalled();
144
+ expect(updateState).toHaveBeenCalledWith(
145
+ {
146
+ identity: { label: 'Shared Label' },
147
+ settings: {
148
+ language: 'ja',
149
+ bleEnabled: true,
150
+ autoLockDelayMs: 60_000,
151
+ hapticFeedback: true,
152
+ },
153
+ },
154
+ 'settings-write'
155
+ );
156
+ expect(typedCall.mock.calls.map(call => call[0])).not.toEqual(
157
+ expect.arrayContaining(['DeviceInfoGet', 'DeviceStatusGet', 'DeviceSettingsGet'])
158
+ );
148
159
  });
149
160
 
150
161
  it('uses the Pro2 passphrase page as a device-side toggle and verifies the target state', async () => {
@@ -172,39 +183,7 @@ describe('DeviceSettings protocol routing', () => {
172
183
  });
173
184
  expect(typedCall).not.toHaveBeenCalledWith('DeviceSettingsSet', 'Success', expect.anything());
174
185
  expect(getDeviceState).toHaveBeenNthCalledWith(1, { refreshSections: ['status'] });
175
- expect(getDeviceState).toHaveBeenNthCalledWith(2, {
176
- refreshSections: ['status', 'settings'],
177
- });
178
- });
179
-
180
- it('reloads Protocol V2 status and settings after changing air-gap mode', async () => {
181
- const { device, typedCall, getDeviceState } = createDevice({ protocol: 'V2' });
182
- getDeviceState
183
- .mockResolvedValueOnce({
184
- settings: { airgapMode: false },
185
- })
186
- .mockResolvedValueOnce({
187
- status: { unlocked: true },
188
- settings: { airgapMode: true },
189
- });
190
- const method = new DeviceSettings({
191
- id: 4,
192
- payload: {
193
- method: 'deviceSettings',
194
- airgapMode: true,
195
- },
196
- });
197
- method.init();
198
- (method as any).device = device;
199
-
200
- await expect(method.run()).resolves.toEqual({ message: 'Success' });
201
- expect(typedCall).toHaveBeenCalledWith('DeviceSettingsPageShow', 'Success', {
202
- page: DeviceSettingsPage.DeviceAirgap,
203
- });
204
- expect(getDeviceState).toHaveBeenNthCalledWith(1, { refreshSections: ['settings'] });
205
- expect(getDeviceState).toHaveBeenNthCalledWith(2, {
206
- refreshSections: ['status', 'settings'],
207
- });
186
+ expect(getDeviceState).toHaveBeenNthCalledWith(2, { refreshSections: ['status'] });
208
187
  });
209
188
 
210
189
  it('does not open a Pro2 settings page when the hardware already matches the target', async () => {
@@ -1,5 +1,4 @@
1
1
  import { DEVICE } from '../src/events';
2
-
3
2
  import type { DeviceState, DeviceStateEvent } from '../src/types';
4
3
 
5
4
  describe('DeviceState contract', () => {