@onekeyfe/hd-core 1.2.0-alpha.18 → 1.2.0-alpha.180

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 (846) hide show
  1. package/__tests__/AllNetworkGetAddressBase.tracing.test.ts +390 -0
  2. package/__tests__/DeviceCommands.test.ts +586 -9
  3. package/__tests__/DeviceEventRegistration.test.ts +6 -0
  4. package/__tests__/base64Data.test.ts +69 -0
  5. package/__tests__/chain-params-onekey-compatibility.test.ts +229 -0
  6. package/__tests__/check-all-firmware-release-protocol-v2.test.ts +878 -0
  7. package/__tests__/check-firmware-release-protocol-v2.test.ts +270 -0
  8. package/__tests__/connectSettings.test.ts +45 -5
  9. package/__tests__/core-dispose.test.ts +34 -0
  10. package/__tests__/core-error-output.test.ts +39 -0
  11. package/__tests__/core-initialization.test.ts +23 -0
  12. package/__tests__/device-connector-protocol.test.ts +102 -0
  13. package/__tests__/device-features-state.test.ts +78 -0
  14. package/__tests__/device-identity.test.ts +52 -0
  15. package/__tests__/device-initialize-timeout.test.ts +56 -0
  16. package/__tests__/device-lifecycle-events.test.ts +752 -0
  17. package/__tests__/device-pool-state.test.ts +191 -0
  18. package/__tests__/device-settings.test.ts +665 -0
  19. package/__tests__/device-state-contract.test.ts +28 -0
  20. package/__tests__/device-state-events.test.ts +286 -0
  21. package/__tests__/device-state-mapper.test.ts +344 -0
  22. package/__tests__/device-state-projector.test.ts +114 -0
  23. package/__tests__/device-state-store.test.ts +109 -0
  24. package/__tests__/device-utils.test.ts +168 -0
  25. package/__tests__/device-wallet-session-store.test.ts +474 -1
  26. package/__tests__/deviceFeaturesUtils.test.ts +13 -1
  27. package/__tests__/devicePoolBootloaderPath.test.ts +64 -0
  28. package/__tests__/deviceSettings.test.ts +117 -0
  29. package/__tests__/deviceUploadNft.test.ts +348 -0
  30. package/__tests__/evmLedgerLegacySafety.test.ts +10 -7
  31. package/__tests__/evmSignTransaction.test.ts +69 -0
  32. package/__tests__/evmSignTypedData.test.ts +80 -0
  33. package/__tests__/filesystemValidation.test.ts +53 -0
  34. package/__tests__/firmware-update/check-all-firmware-release.test.ts +175 -0
  35. package/__tests__/firmware-update/device-update-bootloader.test.ts +109 -0
  36. package/__tests__/firmware-update/firmware-artifact-source.test.ts +171 -0
  37. package/__tests__/firmware-update/firmware-host-binding.test.ts +79 -0
  38. package/__tests__/firmware-update/firmware-preparation-error.test.ts +27 -0
  39. package/__tests__/firmware-update/firmware-prepared-host-digest.test.ts +583 -0
  40. package/__tests__/firmware-update/firmware-prepared-resource-archive.test.ts +171 -0
  41. package/__tests__/firmware-update/firmware-update-bootloader-poll.test.ts +438 -0
  42. package/__tests__/firmware-update/firmware-update-capabilities.test.ts +13 -0
  43. package/__tests__/firmware-update/firmware-update-plan-bootloader-identity.test.ts +474 -0
  44. package/__tests__/firmware-update/firmware-update-plan.test.ts +819 -0
  45. package/__tests__/firmware-update/firmware-update-prepared-plan.test.ts +297 -0
  46. package/__tests__/firmware-update/firmware-update-prepared-resource-executors.test.ts +326 -0
  47. package/__tests__/firmware-update/firmware-update-v2-download-before-boot.test.ts +457 -0
  48. package/__tests__/firmware-update/firmware-update-v3-reconnect.test.ts +237 -0
  49. package/__tests__/firmware-update/firmware-update-v4-install-poll.test.ts +525 -0
  50. package/__tests__/firmware-update/firmware-update-v4-parameters.test.ts +85 -0
  51. package/__tests__/firmware-update/firmware-upload-source.test.ts +70 -0
  52. package/__tests__/get-device-state.test.ts +617 -0
  53. package/__tests__/homescreen.test.ts +58 -1
  54. package/__tests__/kaspa-public-types.type-test.ts +16 -0
  55. package/__tests__/kaspa-use-tweak-pro2.test.ts +20 -0
  56. package/__tests__/kaspaSignTransaction.test.ts +16 -29
  57. package/__tests__/known-device-public-types.type-test.ts +3 -0
  58. package/__tests__/logBlockEvent.test.ts +140 -1
  59. package/__tests__/method-protocol-support.test.ts +144 -0
  60. package/__tests__/networkUtils.test.ts +406 -0
  61. package/__tests__/open-wallet-session-error-response.test.ts +43 -0
  62. package/__tests__/open-wallet-session.test.ts +1899 -0
  63. package/__tests__/pro2Nft.test.ts +108 -0
  64. package/__tests__/pro2Wallpaper.test.ts +8 -19
  65. package/__tests__/protocol-binding.test.ts +89 -0
  66. package/__tests__/protocol-v2-firmware-targets.test.ts +105 -0
  67. package/__tests__/protocol-v2-ping.test.ts +28 -0
  68. package/__tests__/protocol-v2-resources.test.ts +371 -0
  69. package/__tests__/protocol-v2-ui-lifecycle.test.ts +91 -0
  70. package/__tests__/protocol-v2-unlock-policy.test.ts +507 -0
  71. package/__tests__/protocol-v2.test.ts +7577 -2183
  72. package/__tests__/protocolV2FileWrite.test.ts +193 -0
  73. package/__tests__/protocolV2UiInteraction.test.ts +63 -0
  74. package/__tests__/public-device-state-api.test.ts +275 -0
  75. package/__tests__/public-pro2-api-boundary.test.ts +107 -0
  76. package/__tests__/refresh-device-state.test.ts +103 -0
  77. package/__tests__/request-context-logging.test.ts +16 -0
  78. package/__tests__/resourceBase64Boundary.test.ts +48 -0
  79. package/__tests__/search-devices.test.ts +192 -0
  80. package/__tests__/ton-sign-message.test.ts +84 -0
  81. package/__tests__/tron-sign-message-init.test.ts +74 -0
  82. package/__tests__/uiProgressThrottle.test.ts +74 -0
  83. package/__tests__/uiPromiseRegistry.test.ts +115 -0
  84. package/dist/api/BaseMethod.d.ts +10 -2
  85. package/dist/api/BaseMethod.d.ts.map +1 -1
  86. package/dist/api/CheckAllFirmwareRelease.d.ts +25 -1
  87. package/dist/api/CheckAllFirmwareRelease.d.ts.map +1 -1
  88. package/dist/api/CheckBLEFirmwareRelease.d.ts +3 -2
  89. package/dist/api/CheckBLEFirmwareRelease.d.ts.map +1 -1
  90. package/dist/api/CheckBootloaderRelease.d.ts +2 -1
  91. package/dist/api/CheckBootloaderRelease.d.ts.map +1 -1
  92. package/dist/api/CheckFirmwareRelease.d.ts +3 -2
  93. package/dist/api/CheckFirmwareRelease.d.ts.map +1 -1
  94. package/dist/api/CipherKeyValue.d.ts +1 -0
  95. package/dist/api/CipherKeyValue.d.ts.map +1 -1
  96. package/dist/api/ClearSessionCache.d.ts.map +1 -1
  97. package/dist/api/DetectDeviceConnectProtocol.d.ts +7 -0
  98. package/dist/api/DetectDeviceConnectProtocol.d.ts.map +1 -0
  99. package/dist/api/DirList.d.ts +1 -0
  100. package/dist/api/DirList.d.ts.map +1 -1
  101. package/dist/api/DirMake.d.ts +1 -0
  102. package/dist/api/DirMake.d.ts.map +1 -1
  103. package/dist/api/DirRemove.d.ts +1 -0
  104. package/dist/api/DirRemove.d.ts.map +1 -1
  105. package/dist/api/FileDelete.d.ts +1 -0
  106. package/dist/api/FileDelete.d.ts.map +1 -1
  107. package/dist/api/FileRead.d.ts +1 -0
  108. package/dist/api/FileRead.d.ts.map +1 -1
  109. package/dist/api/FileWrite.d.ts +1 -0
  110. package/dist/api/FileWrite.d.ts.map +1 -1
  111. package/dist/api/FirmwareUpdate.d.ts.map +1 -1
  112. package/dist/api/FirmwareUpdateV2.d.ts +13 -2
  113. package/dist/api/FirmwareUpdateV2.d.ts.map +1 -1
  114. package/dist/api/FirmwareUpdateV3.d.ts +7 -3
  115. package/dist/api/FirmwareUpdateV3.d.ts.map +1 -1
  116. package/dist/api/FirmwareUpdateV4.d.ts +65 -14
  117. package/dist/api/FirmwareUpdateV4.d.ts.map +1 -1
  118. package/dist/api/GetDeviceState.d.ts +8 -0
  119. package/dist/api/GetDeviceState.d.ts.map +1 -0
  120. package/dist/api/GetFeatures.d.ts +1 -1
  121. package/dist/api/GetFeatures.d.ts.map +1 -1
  122. package/dist/api/GetOnekeyFeatures.d.ts.map +1 -1
  123. package/dist/api/GetPassphraseState.d.ts +1 -0
  124. package/dist/api/GetPassphraseState.d.ts.map +1 -1
  125. package/dist/api/OpenWalletSession.d.ts +8 -0
  126. package/dist/api/OpenWalletSession.d.ts.map +1 -0
  127. package/dist/api/PathInfo.d.ts +1 -0
  128. package/dist/api/PathInfo.d.ts.map +1 -1
  129. package/dist/api/PromptWebDeviceAccess.d.ts.map +1 -1
  130. package/dist/api/SearchDevices.d.ts +3 -0
  131. package/dist/api/SearchDevices.d.ts.map +1 -1
  132. package/dist/api/UploadPortfolio.d.ts +1 -2
  133. package/dist/api/UploadPortfolio.d.ts.map +1 -1
  134. package/dist/api/alephium/AlephiumGetAddress.d.ts.map +1 -1
  135. package/dist/api/alephium/AlephiumSignMessage.d.ts.map +1 -1
  136. package/dist/api/alephium/AlephiumSignTransaction.d.ts.map +1 -1
  137. package/dist/api/algo/AlgoGetAddress.d.ts +1 -0
  138. package/dist/api/algo/AlgoGetAddress.d.ts.map +1 -1
  139. package/dist/api/algo/AlgoSignTransaction.d.ts +1 -0
  140. package/dist/api/algo/AlgoSignTransaction.d.ts.map +1 -1
  141. package/dist/api/allnetwork/AllNetworkGetAddressBase.d.ts +1 -0
  142. package/dist/api/allnetwork/AllNetworkGetAddressBase.d.ts.map +1 -1
  143. package/dist/api/aptos/AptosGetAddress.d.ts +1 -0
  144. package/dist/api/aptos/AptosGetAddress.d.ts.map +1 -1
  145. package/dist/api/aptos/AptosGetPublicKey.d.ts +1 -0
  146. package/dist/api/aptos/AptosGetPublicKey.d.ts.map +1 -1
  147. package/dist/api/aptos/AptosSignInMessage.d.ts +1 -0
  148. package/dist/api/aptos/AptosSignInMessage.d.ts.map +1 -1
  149. package/dist/api/aptos/AptosSignMessage.d.ts +1 -0
  150. package/dist/api/aptos/AptosSignMessage.d.ts.map +1 -1
  151. package/dist/api/aptos/AptosSignTransaction.d.ts +1 -0
  152. package/dist/api/aptos/AptosSignTransaction.d.ts.map +1 -1
  153. package/dist/api/benfen/BenfenGetAddress.d.ts.map +1 -1
  154. package/dist/api/benfen/BenfenGetPublicKey.d.ts.map +1 -1
  155. package/dist/api/benfen/BenfenSignMessage.d.ts.map +1 -1
  156. package/dist/api/benfen/BenfenSignTransaction.d.ts.map +1 -1
  157. package/dist/api/btc/BTCGetAddress.d.ts +1 -0
  158. package/dist/api/btc/BTCGetAddress.d.ts.map +1 -1
  159. package/dist/api/btc/BTCGetPublicKey.d.ts +1 -0
  160. package/dist/api/btc/BTCGetPublicKey.d.ts.map +1 -1
  161. package/dist/api/btc/BTCSignMessage.d.ts +1 -0
  162. package/dist/api/btc/BTCSignMessage.d.ts.map +1 -1
  163. package/dist/api/btc/BTCSignPsbt.d.ts +1 -0
  164. package/dist/api/btc/BTCSignPsbt.d.ts.map +1 -1
  165. package/dist/api/btc/BTCSignTransaction.d.ts +1 -0
  166. package/dist/api/btc/BTCSignTransaction.d.ts.map +1 -1
  167. package/dist/api/btc/BTCVerifyMessage.d.ts +1 -0
  168. package/dist/api/btc/BTCVerifyMessage.d.ts.map +1 -1
  169. package/dist/api/btc/helpers/versionLimit.d.ts +2 -0
  170. package/dist/api/btc/helpers/versionLimit.d.ts.map +1 -1
  171. package/dist/api/cardano/CardanoGetAddress.d.ts +1 -0
  172. package/dist/api/cardano/CardanoGetAddress.d.ts.map +1 -1
  173. package/dist/api/cardano/CardanoGetPublicKey.d.ts +1 -0
  174. package/dist/api/cardano/CardanoGetPublicKey.d.ts.map +1 -1
  175. package/dist/api/cardano/CardanoSignMessage.d.ts +1 -0
  176. package/dist/api/cardano/CardanoSignMessage.d.ts.map +1 -1
  177. package/dist/api/cardano/CardanoSignTransaction.d.ts +1 -0
  178. package/dist/api/cardano/CardanoSignTransaction.d.ts.map +1 -1
  179. package/dist/api/conflux/ConfluxGetAddress.d.ts +2 -0
  180. package/dist/api/conflux/ConfluxGetAddress.d.ts.map +1 -1
  181. package/dist/api/conflux/ConfluxSignMessage.d.ts +2 -0
  182. package/dist/api/conflux/ConfluxSignMessage.d.ts.map +1 -1
  183. package/dist/api/conflux/ConfluxSignMessageCIP23.d.ts +2 -0
  184. package/dist/api/conflux/ConfluxSignMessageCIP23.d.ts.map +1 -1
  185. package/dist/api/conflux/ConfluxSignTransaction.d.ts +2 -0
  186. package/dist/api/conflux/ConfluxSignTransaction.d.ts.map +1 -1
  187. package/dist/api/cosmos/CosmosGetAddress.d.ts +1 -0
  188. package/dist/api/cosmos/CosmosGetAddress.d.ts.map +1 -1
  189. package/dist/api/cosmos/CosmosGetPublicKey.d.ts +1 -0
  190. package/dist/api/cosmos/CosmosGetPublicKey.d.ts.map +1 -1
  191. package/dist/api/cosmos/CosmosSignTransaction.d.ts +1 -0
  192. package/dist/api/cosmos/CosmosSignTransaction.d.ts.map +1 -1
  193. package/dist/api/device/DeviceCancel.d.ts +1 -0
  194. package/dist/api/device/DeviceCancel.d.ts.map +1 -1
  195. package/dist/api/device/DeviceChangePin.d.ts +1 -0
  196. package/dist/api/device/DeviceChangePin.d.ts.map +1 -1
  197. package/dist/api/device/DeviceFullyUploadResource.d.ts +1 -2
  198. package/dist/api/device/DeviceFullyUploadResource.d.ts.map +1 -1
  199. package/dist/api/device/DeviceLock.d.ts +1 -0
  200. package/dist/api/device/DeviceLock.d.ts.map +1 -1
  201. package/dist/api/device/DeviceRebootToBoardloader.d.ts +1 -0
  202. package/dist/api/device/DeviceRebootToBoardloader.d.ts.map +1 -1
  203. package/dist/api/device/DeviceRebootToBootloader.d.ts +1 -0
  204. package/dist/api/device/DeviceRebootToBootloader.d.ts.map +1 -1
  205. package/dist/api/device/DeviceSettings.d.ts +1 -0
  206. package/dist/api/device/DeviceSettings.d.ts.map +1 -1
  207. package/dist/api/device/DeviceSupportFeatures.d.ts +1 -0
  208. package/dist/api/device/DeviceSupportFeatures.d.ts.map +1 -1
  209. package/dist/api/device/DeviceUnlock.d.ts +3 -2
  210. package/dist/api/device/DeviceUnlock.d.ts.map +1 -1
  211. package/dist/api/device/DeviceUpdateBootloader.d.ts +5 -1
  212. package/dist/api/device/DeviceUpdateBootloader.d.ts.map +1 -1
  213. package/dist/api/device/DeviceVerify.d.ts +1 -0
  214. package/dist/api/device/DeviceVerify.d.ts.map +1 -1
  215. package/dist/api/device/DeviceWipe.d.ts +1 -0
  216. package/dist/api/device/DeviceWipe.d.ts.map +1 -1
  217. package/dist/api/device/PreInitialize.d.ts +1 -0
  218. package/dist/api/device/PreInitialize.d.ts.map +1 -1
  219. package/dist/api/dynex/DnxGetAddress.d.ts.map +1 -1
  220. package/dist/api/dynex/DnxSignTransaction.d.ts.map +1 -1
  221. package/dist/api/evm/EVMGetAddress.d.ts +1 -0
  222. package/dist/api/evm/EVMGetAddress.d.ts.map +1 -1
  223. package/dist/api/evm/EVMGetPublicKey.d.ts +1 -0
  224. package/dist/api/evm/EVMGetPublicKey.d.ts.map +1 -1
  225. package/dist/api/evm/EVMSignMessage.d.ts +1 -0
  226. package/dist/api/evm/EVMSignMessage.d.ts.map +1 -1
  227. package/dist/api/evm/EVMSignMessageEIP712.d.ts.map +1 -1
  228. package/dist/api/evm/EVMSignTransaction.d.ts +1 -0
  229. package/dist/api/evm/EVMSignTransaction.d.ts.map +1 -1
  230. package/dist/api/evm/EVMSignTypedData.d.ts +1 -0
  231. package/dist/api/evm/EVMSignTypedData.d.ts.map +1 -1
  232. package/dist/api/evm/EVMVerifyMessage.d.ts +1 -0
  233. package/dist/api/evm/EVMVerifyMessage.d.ts.map +1 -1
  234. package/dist/api/evm/protocol.d.ts +3 -0
  235. package/dist/api/evm/protocol.d.ts.map +1 -0
  236. package/dist/api/filecoin/FilecoinGetAddress.d.ts +1 -0
  237. package/dist/api/filecoin/FilecoinGetAddress.d.ts.map +1 -1
  238. package/dist/api/filecoin/FilecoinSignTransaction.d.ts +1 -0
  239. package/dist/api/filecoin/FilecoinSignTransaction.d.ts.map +1 -1
  240. package/dist/api/firmware/FirmwareArtifactSource.d.ts +29 -0
  241. package/dist/api/firmware/FirmwareArtifactSource.d.ts.map +1 -0
  242. package/dist/api/firmware/FirmwareHostBinding.d.ts +6 -0
  243. package/dist/api/firmware/FirmwareHostBinding.d.ts.map +1 -0
  244. package/dist/api/firmware/FirmwarePreparationError.d.ts +3 -0
  245. package/dist/api/firmware/FirmwarePreparationError.d.ts.map +1 -0
  246. package/dist/api/firmware/FirmwarePreparedResourceArchive.d.ts +11 -0
  247. package/dist/api/firmware/FirmwarePreparedResourceArchive.d.ts.map +1 -0
  248. package/dist/api/firmware/FirmwareUpdateBaseMethod.d.ts +12 -3
  249. package/dist/api/firmware/FirmwareUpdateBaseMethod.d.ts.map +1 -1
  250. package/dist/api/firmware/FirmwareUpdateCapabilities.d.ts +3 -0
  251. package/dist/api/firmware/FirmwareUpdateCapabilities.d.ts.map +1 -0
  252. package/dist/api/firmware/FirmwareUpdatePlan.d.ts +57 -0
  253. package/dist/api/firmware/FirmwareUpdatePlan.d.ts.map +1 -0
  254. package/dist/api/firmware/FirmwareUpdatePreparedPlan.d.ts +38 -0
  255. package/dist/api/firmware/FirmwareUpdatePreparedPlan.d.ts.map +1 -0
  256. package/dist/api/firmware/getBinary.d.ts +15 -4
  257. package/dist/api/firmware/getBinary.d.ts.map +1 -1
  258. package/dist/api/firmware/protocolV2Release.d.ts +33 -0
  259. package/dist/api/firmware/protocolV2Release.d.ts.map +1 -0
  260. package/dist/api/firmware/updateBootloader.d.ts +2 -0
  261. package/dist/api/firmware/updateBootloader.d.ts.map +1 -1
  262. package/dist/api/firmware/uploadFirmware.d.ts +9 -1
  263. package/dist/api/firmware/uploadFirmware.d.ts.map +1 -1
  264. package/dist/api/helpers/base64Data.d.ts +16 -0
  265. package/dist/api/helpers/base64Data.d.ts.map +1 -0
  266. package/dist/api/helpers/filesystemValidation.d.ts +3 -0
  267. package/dist/api/helpers/filesystemValidation.d.ts.map +1 -1
  268. package/dist/api/helpers/paramsValidator.d.ts +1 -0
  269. package/dist/api/helpers/paramsValidator.d.ts.map +1 -1
  270. package/dist/api/helpers/protocolV2FileWrite.d.ts +10 -0
  271. package/dist/api/helpers/protocolV2FileWrite.d.ts.map +1 -1
  272. package/dist/api/index.d.ts +5 -29
  273. package/dist/api/index.d.ts.map +1 -1
  274. package/dist/api/kaspa/KaspaGetAddress.d.ts +4 -0
  275. package/dist/api/kaspa/KaspaGetAddress.d.ts.map +1 -1
  276. package/dist/api/kaspa/KaspaSignTransaction.d.ts +4 -0
  277. package/dist/api/kaspa/KaspaSignTransaction.d.ts.map +1 -1
  278. package/dist/api/kaspa/helpers/TransferSerialize.d.ts.map +1 -1
  279. package/dist/api/lightning/LnurlAuth.d.ts +0 -4
  280. package/dist/api/lightning/LnurlAuth.d.ts.map +1 -1
  281. package/dist/api/near/NearGetAddress.d.ts +1 -0
  282. package/dist/api/near/NearGetAddress.d.ts.map +1 -1
  283. package/dist/api/near/NearSignTransaction.d.ts +1 -0
  284. package/dist/api/near/NearSignTransaction.d.ts.map +1 -1
  285. package/dist/api/nem/NEMGetAddress.d.ts +1 -0
  286. package/dist/api/nem/NEMGetAddress.d.ts.map +1 -1
  287. package/dist/api/nem/NEMSignTransaction.d.ts +1 -0
  288. package/dist/api/nem/NEMSignTransaction.d.ts.map +1 -1
  289. package/dist/api/neo/NeoGetAddress.d.ts.map +1 -1
  290. package/dist/api/neo/NeoSignTransaction.d.ts.map +1 -1
  291. package/dist/api/nervos/NervosGetAddress.d.ts.map +1 -1
  292. package/dist/api/nervos/NervosSignTransaction.d.ts.map +1 -1
  293. package/dist/api/nexa/NexaGetAddress.d.ts.map +1 -1
  294. package/dist/api/nexa/NexaSignTransaction.d.ts +1 -0
  295. package/dist/api/nexa/NexaSignTransaction.d.ts.map +1 -1
  296. package/dist/api/nostr/NostrDecryptMessage.d.ts +1 -0
  297. package/dist/api/nostr/NostrDecryptMessage.d.ts.map +1 -1
  298. package/dist/api/nostr/NostrEncryptMessage.d.ts +1 -0
  299. package/dist/api/nostr/NostrEncryptMessage.d.ts.map +1 -1
  300. package/dist/api/nostr/NostrGetPublicKey.d.ts +1 -0
  301. package/dist/api/nostr/NostrGetPublicKey.d.ts.map +1 -1
  302. package/dist/api/nostr/NostrSignEvent.d.ts +1 -0
  303. package/dist/api/nostr/NostrSignEvent.d.ts.map +1 -1
  304. package/dist/api/nostr/NostrSignSchnorr.d.ts +1 -0
  305. package/dist/api/nostr/NostrSignSchnorr.d.ts.map +1 -1
  306. package/dist/api/polkadot/PolkadotGetAddress.d.ts +2 -1
  307. package/dist/api/polkadot/PolkadotGetAddress.d.ts.map +1 -1
  308. package/dist/api/polkadot/PolkadotSignTransaction.d.ts +1 -0
  309. package/dist/api/polkadot/PolkadotSignTransaction.d.ts.map +1 -1
  310. package/dist/api/polkadot/networks.d.ts +1 -1
  311. package/dist/api/protocol-v2/DeviceFactoryInfoGet.d.ts +1 -0
  312. package/dist/api/protocol-v2/DeviceFactoryInfoGet.d.ts.map +1 -1
  313. package/dist/api/protocol-v2/DeviceFactoryInfoSet.d.ts +1 -0
  314. package/dist/api/protocol-v2/DeviceFactoryInfoSet.d.ts.map +1 -1
  315. package/dist/api/protocol-v2/DeviceFirmwareUpdate.d.ts +4 -1
  316. package/dist/api/protocol-v2/DeviceFirmwareUpdate.d.ts.map +1 -1
  317. package/dist/api/protocol-v2/DeviceGetFirmwareUpdateStatus.d.ts +1 -0
  318. package/dist/api/protocol-v2/DeviceGetFirmwareUpdateStatus.d.ts.map +1 -1
  319. package/dist/api/protocol-v2/DeviceGetOnboardingStatus.d.ts +2 -1
  320. package/dist/api/protocol-v2/DeviceGetOnboardingStatus.d.ts.map +1 -1
  321. package/dist/api/protocol-v2/DeviceInfoGet.d.ts +2 -2
  322. package/dist/api/protocol-v2/DeviceInfoGet.d.ts.map +1 -1
  323. package/dist/api/protocol-v2/DeviceReboot.d.ts +2 -1
  324. package/dist/api/protocol-v2/DeviceReboot.d.ts.map +1 -1
  325. package/dist/api/protocol-v2/DeviceStatusGet.d.ts +1 -0
  326. package/dist/api/protocol-v2/DeviceStatusGet.d.ts.map +1 -1
  327. package/dist/api/protocol-v2/DeviceUploadNft.d.ts +30 -0
  328. package/dist/api/protocol-v2/DeviceUploadNft.d.ts.map +1 -0
  329. package/dist/api/protocol-v2/DeviceUploadWallpaper.d.ts +3 -3
  330. package/dist/api/protocol-v2/DeviceUploadWallpaper.d.ts.map +1 -1
  331. package/dist/api/protocol-v2/FilesystemFormat.d.ts +1 -0
  332. package/dist/api/protocol-v2/FilesystemFormat.d.ts.map +1 -1
  333. package/dist/api/protocol-v2/FilesystemPermissionFix.d.ts +1 -0
  334. package/dist/api/protocol-v2/FilesystemPermissionFix.d.ts.map +1 -1
  335. package/dist/api/protocol-v2/Ping.d.ts +3 -0
  336. package/dist/api/protocol-v2/Ping.d.ts.map +1 -1
  337. package/dist/api/protocol-v2/ProtocolInfoRequest.d.ts +1 -0
  338. package/dist/api/protocol-v2/ProtocolInfoRequest.d.ts.map +1 -1
  339. package/dist/api/protocol-v2/helpers.d.ts.map +1 -1
  340. package/dist/api/scdo/ScdoGetAddress.d.ts.map +1 -1
  341. package/dist/api/scdo/ScdoSignMessage.d.ts.map +1 -1
  342. package/dist/api/scdo/ScdoSignTransaction.d.ts.map +1 -1
  343. package/dist/api/solana/SolGetAddress.d.ts +1 -0
  344. package/dist/api/solana/SolGetAddress.d.ts.map +1 -1
  345. package/dist/api/solana/SolSignMessage.d.ts +2 -1
  346. package/dist/api/solana/SolSignMessage.d.ts.map +1 -1
  347. package/dist/api/solana/SolSignOffchainMessage.d.ts +2 -1
  348. package/dist/api/solana/SolSignOffchainMessage.d.ts.map +1 -1
  349. package/dist/api/solana/SolSignTransaction.d.ts +3 -2
  350. package/dist/api/solana/SolSignTransaction.d.ts.map +1 -1
  351. package/dist/api/starcoin/StarcoinGetAddress.d.ts +1 -0
  352. package/dist/api/starcoin/StarcoinGetAddress.d.ts.map +1 -1
  353. package/dist/api/starcoin/StarcoinGetPublicKey.d.ts +1 -0
  354. package/dist/api/starcoin/StarcoinGetPublicKey.d.ts.map +1 -1
  355. package/dist/api/starcoin/StarcoinSignMessage.d.ts +1 -0
  356. package/dist/api/starcoin/StarcoinSignMessage.d.ts.map +1 -1
  357. package/dist/api/starcoin/StarcoinSignTransaction.d.ts +1 -0
  358. package/dist/api/starcoin/StarcoinSignTransaction.d.ts.map +1 -1
  359. package/dist/api/starcoin/StarcoinVerifyMessage.d.ts +1 -0
  360. package/dist/api/starcoin/StarcoinVerifyMessage.d.ts.map +1 -1
  361. package/dist/api/stellar/StellarGetAddress.d.ts +1 -2
  362. package/dist/api/stellar/StellarGetAddress.d.ts.map +1 -1
  363. package/dist/api/stellar/StellarSignTransaction.d.ts +2 -3
  364. package/dist/api/stellar/StellarSignTransaction.d.ts.map +1 -1
  365. package/dist/api/sui/SuiGetAddress.d.ts +2 -1
  366. package/dist/api/sui/SuiGetAddress.d.ts.map +1 -1
  367. package/dist/api/sui/SuiGetPublicKey.d.ts +2 -1
  368. package/dist/api/sui/SuiGetPublicKey.d.ts.map +1 -1
  369. package/dist/api/sui/SuiSignMessage.d.ts +2 -1
  370. package/dist/api/sui/SuiSignMessage.d.ts.map +1 -1
  371. package/dist/api/sui/SuiSignTransaction.d.ts +2 -1
  372. package/dist/api/sui/SuiSignTransaction.d.ts.map +1 -1
  373. package/dist/api/ton/TonGetAddress.d.ts +2 -1
  374. package/dist/api/ton/TonGetAddress.d.ts.map +1 -1
  375. package/dist/api/ton/TonSignData.d.ts +1 -0
  376. package/dist/api/ton/TonSignData.d.ts.map +1 -1
  377. package/dist/api/ton/TonSignMessage.d.ts +2 -1
  378. package/dist/api/ton/TonSignMessage.d.ts.map +1 -1
  379. package/dist/api/ton/TonSignProof.d.ts +2 -1
  380. package/dist/api/ton/TonSignProof.d.ts.map +1 -1
  381. package/dist/api/tron/TronGetAddress.d.ts +1 -0
  382. package/dist/api/tron/TronGetAddress.d.ts.map +1 -1
  383. package/dist/api/tron/TronSignMessage.d.ts +6 -1
  384. package/dist/api/tron/TronSignMessage.d.ts.map +1 -1
  385. package/dist/api/tron/TronSignTransaction.d.ts +2 -1
  386. package/dist/api/tron/TronSignTransaction.d.ts.map +1 -1
  387. package/dist/api/utils.d.ts +4 -1
  388. package/dist/api/utils.d.ts.map +1 -1
  389. package/dist/api/xrp/XrpGetAddress.d.ts +1 -0
  390. package/dist/api/xrp/XrpGetAddress.d.ts.map +1 -1
  391. package/dist/api/xrp/XrpSignTransaction.d.ts +1 -0
  392. package/dist/api/xrp/XrpSignTransaction.d.ts.map +1 -1
  393. package/dist/constants/index.d.ts +1 -1
  394. package/dist/constants/index.d.ts.map +1 -1
  395. package/dist/core/RequestQueue.d.ts +0 -2
  396. package/dist/core/RequestQueue.d.ts.map +1 -1
  397. package/dist/core/deviceEventRegistration.d.ts +2 -0
  398. package/dist/core/deviceEventRegistration.d.ts.map +1 -1
  399. package/dist/core/index.d.ts +8 -3
  400. package/dist/core/index.d.ts.map +1 -1
  401. package/dist/core/uiPromiseRegistry.d.ts +6 -0
  402. package/dist/core/uiPromiseRegistry.d.ts.map +1 -0
  403. package/dist/data-manager/DataManager.d.ts +14 -5
  404. package/dist/data-manager/DataManager.d.ts.map +1 -1
  405. package/dist/data-manager/TransportManager.d.ts.map +1 -1
  406. package/dist/data-manager/connectSettings.d.ts.map +1 -1
  407. package/dist/device/Device.d.ts +82 -14
  408. package/dist/device/Device.d.ts.map +1 -1
  409. package/dist/device/DeviceCommands.d.ts +5 -5
  410. package/dist/device/DeviceCommands.d.ts.map +1 -1
  411. package/dist/device/DeviceConnector.d.ts +4 -3
  412. package/dist/device/DeviceConnector.d.ts.map +1 -1
  413. package/dist/device/DeviceFeaturesState.d.ts +3 -0
  414. package/dist/device/DeviceFeaturesState.d.ts.map +1 -0
  415. package/dist/device/DevicePool.d.ts +4 -0
  416. package/dist/device/DevicePool.d.ts.map +1 -1
  417. package/dist/device/DeviceStateMapper.d.ts +13 -0
  418. package/dist/device/DeviceStateMapper.d.ts.map +1 -0
  419. package/dist/device/DeviceStateProjector.d.ts +7 -0
  420. package/dist/device/DeviceStateProjector.d.ts.map +1 -0
  421. package/dist/device/DeviceStateStore.d.ts +21 -0
  422. package/dist/device/DeviceStateStore.d.ts.map +1 -0
  423. package/dist/device/DeviceWalletSessionStore.d.ts +13 -1
  424. package/dist/device/DeviceWalletSessionStore.d.ts.map +1 -1
  425. package/dist/device/cloneDeviceState.d.ts +2 -0
  426. package/dist/device/cloneDeviceState.d.ts.map +1 -0
  427. package/dist/device/deviceIdentity.d.ts +5 -0
  428. package/dist/device/deviceIdentity.d.ts.map +1 -0
  429. package/dist/deviceProfile/buildDeviceFeatures.d.ts +3 -1
  430. package/dist/deviceProfile/buildDeviceFeatures.d.ts.map +1 -1
  431. package/dist/deviceProfile/index.d.ts +0 -1
  432. package/dist/deviceProfile/index.d.ts.map +1 -1
  433. package/dist/deviceProfile/protocolV2DeviceIdentity.d.ts +7 -0
  434. package/dist/deviceProfile/protocolV2DeviceIdentity.d.ts.map +1 -0
  435. package/dist/events/call.d.ts +0 -7
  436. package/dist/events/call.d.ts.map +1 -1
  437. package/dist/events/core.d.ts +2 -2
  438. package/dist/events/core.d.ts.map +1 -1
  439. package/dist/events/device.d.ts +12 -2
  440. package/dist/events/device.d.ts.map +1 -1
  441. package/dist/events/iframe.d.ts +0 -1
  442. package/dist/events/iframe.d.ts.map +1 -1
  443. package/dist/events/logBlockEvent.d.ts +2 -0
  444. package/dist/events/logBlockEvent.d.ts.map +1 -1
  445. package/dist/events/ui-promise.d.ts +4 -2
  446. package/dist/events/ui-promise.d.ts.map +1 -1
  447. package/dist/events/ui-request.d.ts +32 -2
  448. package/dist/events/ui-request.d.ts.map +1 -1
  449. package/dist/events/ui-response.d.ts +10 -2
  450. package/dist/events/ui-response.d.ts.map +1 -1
  451. package/dist/index.d.ts +1690 -847
  452. package/dist/index.d.ts.map +1 -1
  453. package/dist/index.js +10856 -4825
  454. package/dist/inject.d.ts +7 -3
  455. package/dist/inject.d.ts.map +1 -1
  456. package/dist/lowLevelInject.d.ts +1 -2
  457. package/dist/lowLevelInject.d.ts.map +1 -1
  458. package/dist/protocols/protocol-v2/deviceSession.d.ts +7 -0
  459. package/dist/protocols/protocol-v2/deviceSession.d.ts.map +1 -0
  460. package/dist/protocols/protocol-v2/features.d.ts +31 -8
  461. package/dist/protocols/protocol-v2/features.d.ts.map +1 -1
  462. package/dist/protocols/protocol-v2/firmware.d.ts.map +1 -1
  463. package/dist/protocols/protocol-v2/index.d.ts +2 -2
  464. package/dist/protocols/protocol-v2/index.d.ts.map +1 -1
  465. package/dist/protocols/protocol-v2/resources.d.ts +17 -0
  466. package/dist/protocols/protocol-v2/resources.d.ts.map +1 -0
  467. package/dist/protocols/protocol-v2/settingsUnlockPolicy.d.ts +17 -0
  468. package/dist/protocols/protocol-v2/settingsUnlockPolicy.d.ts.map +1 -0
  469. package/dist/protocols/protocol-v2/uiInteraction.d.ts +7 -4
  470. package/dist/protocols/protocol-v2/uiInteraction.d.ts.map +1 -1
  471. package/dist/protocols/protocol-v2/unlockPolicy.d.ts +2 -0
  472. package/dist/protocols/protocol-v2/unlockPolicy.d.ts.map +1 -0
  473. package/dist/protocols/protocol-v2/unlockPolicyRunner.d.ts +22 -0
  474. package/dist/protocols/protocol-v2/unlockPolicyRunner.d.ts.map +1 -0
  475. package/dist/protocols/protocol-v2/walletSession.d.ts +16 -3
  476. package/dist/protocols/protocol-v2/walletSession.d.ts.map +1 -1
  477. package/dist/topLevelInject.d.ts.map +1 -1
  478. package/dist/types/api/checkAllFirmwareRelease.d.ts +48 -9
  479. package/dist/types/api/checkAllFirmwareRelease.d.ts.map +1 -1
  480. package/dist/types/api/checkBLEFirmwareRelease.d.ts +2 -13
  481. package/dist/types/api/checkBLEFirmwareRelease.d.ts.map +1 -1
  482. package/dist/types/api/checkBootloaderRelease.d.ts +2 -6
  483. package/dist/types/api/checkBootloaderRelease.d.ts.map +1 -1
  484. package/dist/types/api/checkFirmwareRelease.d.ts +2 -13
  485. package/dist/types/api/checkFirmwareRelease.d.ts.map +1 -1
  486. package/dist/types/api/checkFirmwareTypeAvailable.d.ts +2 -2
  487. package/dist/types/api/checkFirmwareTypeAvailable.d.ts.map +1 -1
  488. package/dist/types/api/detectDeviceConnectProtocol.d.ts +4 -0
  489. package/dist/types/api/detectDeviceConnectProtocol.d.ts.map +1 -0
  490. package/dist/types/api/deviceSettings.d.ts +11 -2
  491. package/dist/types/api/deviceSettings.d.ts.map +1 -1
  492. package/dist/types/api/deviceUnlock.d.ts +6 -2
  493. package/dist/types/api/deviceUnlock.d.ts.map +1 -1
  494. package/dist/types/api/deviceUpdateBootloader.d.ts +6 -0
  495. package/dist/types/api/deviceUpdateBootloader.d.ts.map +1 -1
  496. package/dist/types/api/export.d.ts +8 -3
  497. package/dist/types/api/export.d.ts.map +1 -1
  498. package/dist/types/api/firmwareUpdate.d.ts +67 -5
  499. package/dist/types/api/firmwareUpdate.d.ts.map +1 -1
  500. package/dist/types/api/firmwareUpdateCapabilities.d.ts +9 -0
  501. package/dist/types/api/firmwareUpdateCapabilities.d.ts.map +1 -0
  502. package/dist/types/api/firmwareUpdatePlan.d.ts +28 -0
  503. package/dist/types/api/firmwareUpdatePlan.d.ts.map +1 -0
  504. package/dist/types/api/firmwareUpdatePreparedPlan.d.ts +42 -0
  505. package/dist/types/api/firmwareUpdatePreparedPlan.d.ts.map +1 -0
  506. package/dist/types/api/getDeviceState.d.ts +12 -0
  507. package/dist/types/api/getDeviceState.d.ts.map +1 -0
  508. package/dist/types/api/getFeatures.d.ts.map +1 -1
  509. package/dist/types/api/getOnekeyFeatures.d.ts.map +1 -1
  510. package/dist/types/api/getPassphraseState.d.ts.map +1 -1
  511. package/dist/types/api/index.d.ts +25 -35
  512. package/dist/types/api/index.d.ts.map +1 -1
  513. package/dist/types/api/kaspaSignTransaction.d.ts +15 -2
  514. package/dist/types/api/kaspaSignTransaction.d.ts.map +1 -1
  515. package/dist/types/api/openWalletSession.d.ts +35 -0
  516. package/dist/types/api/openWalletSession.d.ts.map +1 -0
  517. package/dist/types/api/protocolV2.d.ts +11 -95
  518. package/dist/types/api/protocolV2.d.ts.map +1 -1
  519. package/dist/types/api/sessionCache.d.ts +4 -1
  520. package/dist/types/api/sessionCache.d.ts.map +1 -1
  521. package/dist/types/device.d.ts +138 -8
  522. package/dist/types/device.d.ts.map +1 -1
  523. package/dist/types/params.d.ts +1 -0
  524. package/dist/types/params.d.ts.map +1 -1
  525. package/dist/types/settings.d.ts +31 -16
  526. package/dist/types/settings.d.ts.map +1 -1
  527. package/dist/utils/assets.d.ts +2 -1
  528. package/dist/utils/assets.d.ts.map +1 -1
  529. package/dist/utils/deviceFeaturesCompat.d.ts +14 -0
  530. package/dist/utils/deviceFeaturesCompat.d.ts.map +1 -0
  531. package/dist/utils/deviceFeaturesUtils.d.ts +10 -1
  532. package/dist/utils/deviceFeaturesUtils.d.ts.map +1 -1
  533. package/dist/utils/deviceInfoUtils.d.ts +9 -9
  534. package/dist/utils/deviceInfoUtils.d.ts.map +1 -1
  535. package/dist/utils/deviceSettings.d.ts +39 -7
  536. package/dist/utils/deviceSettings.d.ts.map +1 -1
  537. package/dist/utils/deviceVersionUtils.d.ts +7 -5
  538. package/dist/utils/deviceVersionUtils.d.ts.map +1 -1
  539. package/dist/utils/homescreen.d.ts +4 -0
  540. package/dist/utils/homescreen.d.ts.map +1 -1
  541. package/dist/utils/index.d.ts +5 -4
  542. package/dist/utils/index.d.ts.map +1 -1
  543. package/dist/utils/networkUtils.d.ts +10 -1
  544. package/dist/utils/networkUtils.d.ts.map +1 -1
  545. package/dist/utils/patch.d.ts +1 -1
  546. package/dist/utils/patch.d.ts.map +1 -1
  547. package/dist/utils/pro2Nft.d.ts +38 -0
  548. package/dist/utils/pro2Nft.d.ts.map +1 -0
  549. package/dist/utils/pro2Wallpaper.d.ts +10 -0
  550. package/dist/utils/pro2Wallpaper.d.ts.map +1 -1
  551. package/dist/utils/tracing.d.ts.map +1 -1
  552. package/dist/utils/uiProgressThrottle.d.ts +3 -0
  553. package/dist/utils/uiProgressThrottle.d.ts.map +1 -0
  554. package/package.json +6 -4
  555. package/src/api/BaseMethod.ts +39 -25
  556. package/src/api/CheckAllFirmwareRelease.ts +440 -4
  557. package/src/api/CheckBLEFirmwareRelease.ts +37 -5
  558. package/src/api/CheckBootloaderRelease.ts +37 -5
  559. package/src/api/CheckFirmwareRelease.ts +36 -9
  560. package/src/api/CipherKeyValue.ts +4 -0
  561. package/src/api/ClearSessionCache.ts +4 -0
  562. package/src/api/DetectDeviceConnectProtocol.ts +18 -0
  563. package/src/api/DirList.ts +9 -4
  564. package/src/api/DirMake.ts +7 -4
  565. package/src/api/DirRemove.ts +7 -4
  566. package/src/api/FileDelete.ts +7 -4
  567. package/src/api/FileRead.ts +13 -7
  568. package/src/api/FileWrite.ts +7 -4
  569. package/src/api/FirmwareUpdate.ts +30 -15
  570. package/src/api/FirmwareUpdateV2.ts +535 -169
  571. package/src/api/FirmwareUpdateV3.ts +349 -91
  572. package/src/api/FirmwareUpdateV4.ts +2195 -696
  573. package/src/api/GetDeviceState.ts +59 -0
  574. package/src/api/GetFeatures.ts +6 -4
  575. package/src/api/GetOnekeyFeatures.ts +1 -75
  576. package/src/api/GetPassphraseState.ts +34 -13
  577. package/src/api/OpenWalletSession.ts +268 -0
  578. package/src/api/PathInfo.ts +9 -4
  579. package/src/api/PromptWebDeviceAccess.ts +3 -8
  580. package/src/api/SearchDevices.ts +35 -5
  581. package/src/api/UploadPortfolio.ts +29 -5
  582. package/src/api/alephium/AlephiumGetAddress.ts +0 -4
  583. package/src/api/alephium/AlephiumSignMessage.ts +0 -4
  584. package/src/api/alephium/AlephiumSignTransaction.ts +2 -6
  585. package/src/api/algo/AlgoGetAddress.ts +4 -0
  586. package/src/api/algo/AlgoSignTransaction.ts +4 -0
  587. package/src/api/allnetwork/AllNetworkGetAddress.ts +21 -21
  588. package/src/api/allnetwork/AllNetworkGetAddressBase.ts +45 -32
  589. package/src/api/aptos/AptosGetAddress.ts +4 -0
  590. package/src/api/aptos/AptosGetPublicKey.ts +4 -0
  591. package/src/api/aptos/AptosSignInMessage.ts +4 -0
  592. package/src/api/aptos/AptosSignMessage.ts +4 -0
  593. package/src/api/aptos/AptosSignTransaction.ts +4 -0
  594. package/src/api/benfen/BenfenGetAddress.ts +11 -7
  595. package/src/api/benfen/BenfenGetPublicKey.ts +0 -4
  596. package/src/api/benfen/BenfenSignMessage.ts +0 -4
  597. package/src/api/benfen/BenfenSignTransaction.ts +0 -4
  598. package/src/api/btc/BTCGetAddress.ts +8 -1
  599. package/src/api/btc/BTCGetPublicKey.ts +9 -2
  600. package/src/api/btc/BTCSignMessage.ts +8 -1
  601. package/src/api/btc/BTCSignPsbt.ts +4 -0
  602. package/src/api/btc/BTCSignTransaction.ts +8 -1
  603. package/src/api/btc/BTCVerifyMessage.ts +8 -1
  604. package/src/api/btc/helpers/versionLimit.ts +7 -4
  605. package/src/api/cardano/CardanoGetAddress.ts +4 -0
  606. package/src/api/cardano/CardanoGetPublicKey.ts +4 -0
  607. package/src/api/cardano/CardanoSignMessage.ts +4 -0
  608. package/src/api/cardano/CardanoSignTransaction.ts +4 -0
  609. package/src/api/conflux/ConfluxGetAddress.ts +6 -0
  610. package/src/api/conflux/ConfluxSignMessage.ts +6 -0
  611. package/src/api/conflux/ConfluxSignMessageCIP23.ts +6 -0
  612. package/src/api/conflux/ConfluxSignTransaction.ts +8 -5
  613. package/src/api/cosmos/CosmosGetAddress.ts +4 -0
  614. package/src/api/cosmos/CosmosGetPublicKey.ts +4 -0
  615. package/src/api/cosmos/CosmosSignTransaction.ts +4 -0
  616. package/src/api/device/DeviceCancel.ts +4 -0
  617. package/src/api/device/DeviceChangePin.ts +9 -1
  618. package/src/api/device/DeviceFullyUploadResource.ts +4 -5
  619. package/src/api/device/DeviceLock.ts +4 -0
  620. package/src/api/device/DeviceRebootToBoardloader.ts +8 -1
  621. package/src/api/device/DeviceRebootToBootloader.ts +8 -1
  622. package/src/api/device/DeviceSettings.ts +211 -3
  623. package/src/api/device/DeviceSupportFeatures.ts +4 -0
  624. package/src/api/device/DeviceUnlock.ts +12 -3
  625. package/src/api/device/DeviceUpdateBootloader.ts +152 -8
  626. package/src/api/device/DeviceVerify.ts +25 -0
  627. package/src/api/device/DeviceWipe.ts +11 -1
  628. package/src/api/device/PreInitialize.ts +4 -0
  629. package/src/api/dynex/DnxGetAddress.ts +0 -6
  630. package/src/api/dynex/DnxSignTransaction.ts +0 -6
  631. package/src/api/evm/EVMGetAddress.ts +6 -2
  632. package/src/api/evm/EVMGetPublicKey.ts +6 -2
  633. package/src/api/evm/EVMSignMessage.ts +6 -2
  634. package/src/api/evm/EVMSignMessageEIP712.ts +1 -11
  635. package/src/api/evm/EVMSignTransaction.ts +6 -2
  636. package/src/api/evm/EVMSignTypedData.ts +42 -50
  637. package/src/api/evm/EVMVerifyMessage.ts +6 -2
  638. package/src/api/evm/legacyV1/getAddress.ts +2 -2
  639. package/src/api/evm/legacyV1/getPublicKey.ts +2 -2
  640. package/src/api/evm/legacyV1/signMessage.ts +2 -2
  641. package/src/api/evm/legacyV1/signTypedData.ts +2 -2
  642. package/src/api/evm/legacyV1/signTypedHash.ts +2 -2
  643. package/src/api/evm/legacyV1/verifyMessage.ts +2 -2
  644. package/src/api/evm/protocol.ts +6 -0
  645. package/src/api/filecoin/FilecoinGetAddress.ts +4 -0
  646. package/src/api/filecoin/FilecoinSignTransaction.ts +4 -0
  647. package/src/api/firmware/FirmwareArtifactSource.ts +305 -0
  648. package/src/api/firmware/FirmwareHostBinding.ts +123 -0
  649. package/src/api/firmware/FirmwarePreparationError.ts +12 -0
  650. package/src/api/firmware/FirmwarePreparedResourceArchive.ts +196 -0
  651. package/src/api/firmware/FirmwareUpdateBaseMethod.ts +214 -77
  652. package/src/api/firmware/FirmwareUpdateCapabilities.ts +9 -0
  653. package/src/api/firmware/FirmwareUpdatePlan.ts +905 -0
  654. package/src/api/firmware/FirmwareUpdatePreparedPlan.ts +490 -0
  655. package/src/api/firmware/getBinary.ts +8 -3
  656. package/src/api/firmware/protocolV2Release.ts +173 -0
  657. package/src/api/firmware/updateBootloader.ts +19 -4
  658. package/src/api/firmware/uploadFirmware.ts +157 -26
  659. package/src/api/helpers/base64Data.ts +85 -0
  660. package/src/api/helpers/batchGetPublickeys.ts +2 -2
  661. package/src/api/helpers/filesystemValidation.ts +61 -0
  662. package/src/api/helpers/paramsValidator.ts +1 -1
  663. package/src/api/helpers/protocolV2FileWrite.ts +260 -60
  664. package/src/api/index.ts +6 -30
  665. package/src/api/kaspa/KaspaGetAddress.ts +7 -0
  666. package/src/api/kaspa/KaspaSignTransaction.ts +48 -27
  667. package/src/api/kaspa/helpers/TransferSerialize.ts +3 -7
  668. package/src/api/lightning/LnurlAuth.ts +0 -4
  669. package/src/api/near/NearGetAddress.ts +4 -0
  670. package/src/api/near/NearSignTransaction.ts +4 -0
  671. package/src/api/nem/NEMGetAddress.ts +4 -0
  672. package/src/api/nem/NEMSignTransaction.ts +4 -0
  673. package/src/api/neo/NeoGetAddress.ts +0 -4
  674. package/src/api/neo/NeoSignTransaction.ts +0 -4
  675. package/src/api/nervos/NervosGetAddress.ts +0 -4
  676. package/src/api/nervos/NervosSignTransaction.ts +2 -6
  677. package/src/api/nexa/NexaGetAddress.ts +0 -4
  678. package/src/api/nexa/NexaSignTransaction.ts +3 -5
  679. package/src/api/nostr/NostrDecryptMessage.ts +4 -0
  680. package/src/api/nostr/NostrEncryptMessage.ts +4 -0
  681. package/src/api/nostr/NostrGetPublicKey.ts +4 -0
  682. package/src/api/nostr/NostrSignEvent.ts +4 -0
  683. package/src/api/nostr/NostrSignSchnorr.ts +4 -0
  684. package/src/api/polkadot/PolkadotGetAddress.ts +4 -0
  685. package/src/api/polkadot/PolkadotSignTransaction.ts +4 -0
  686. package/src/api/polkadot/networks.ts +3 -3
  687. package/src/api/protocol-v2/DeviceFactoryInfoGet.ts +5 -2
  688. package/src/api/protocol-v2/DeviceFactoryInfoSet.ts +6 -3
  689. package/src/api/protocol-v2/DeviceFirmwareUpdate.ts +13 -32
  690. package/src/api/protocol-v2/DeviceGetFirmwareUpdateStatus.ts +10 -6
  691. package/src/api/protocol-v2/DeviceGetOnboardingStatus.ts +6 -3
  692. package/src/api/protocol-v2/DeviceInfoGet.ts +11 -17
  693. package/src/api/protocol-v2/DeviceReboot.ts +12 -3
  694. package/src/api/protocol-v2/DeviceStatusGet.ts +5 -1
  695. package/src/api/protocol-v2/DeviceUploadNft.ts +249 -0
  696. package/src/api/protocol-v2/DeviceUploadWallpaper.ts +57 -20
  697. package/src/api/protocol-v2/FilesystemFormat.ts +5 -2
  698. package/src/api/protocol-v2/FilesystemPermissionFix.ts +5 -2
  699. package/src/api/protocol-v2/Ping.ts +37 -3
  700. package/src/api/protocol-v2/ProtocolInfoRequest.ts +8 -3
  701. package/src/api/protocol-v2/helpers.ts +1 -1
  702. package/src/api/scdo/ScdoGetAddress.ts +0 -4
  703. package/src/api/scdo/ScdoSignMessage.ts +0 -4
  704. package/src/api/scdo/ScdoSignTransaction.ts +0 -4
  705. package/src/api/solana/SolGetAddress.ts +4 -0
  706. package/src/api/solana/SolSignMessage.ts +5 -1
  707. package/src/api/solana/SolSignOffchainMessage.ts +5 -1
  708. package/src/api/solana/SolSignTransaction.ts +6 -2
  709. package/src/api/starcoin/StarcoinGetAddress.ts +4 -0
  710. package/src/api/starcoin/StarcoinGetPublicKey.ts +4 -0
  711. package/src/api/starcoin/StarcoinSignMessage.ts +4 -0
  712. package/src/api/starcoin/StarcoinSignTransaction.ts +4 -0
  713. package/src/api/starcoin/StarcoinVerifyMessage.ts +4 -0
  714. package/src/api/stellar/StellarGetAddress.ts +1 -10
  715. package/src/api/stellar/StellarSignTransaction.ts +1 -14
  716. package/src/api/sui/SuiGetAddress.ts +5 -1
  717. package/src/api/sui/SuiGetPublicKey.ts +5 -1
  718. package/src/api/sui/SuiSignMessage.ts +5 -1
  719. package/src/api/sui/SuiSignTransaction.ts +5 -1
  720. package/src/api/ton/TonGetAddress.ts +5 -1
  721. package/src/api/ton/TonSignData.ts +5 -1
  722. package/src/api/ton/TonSignMessage.ts +10 -4
  723. package/src/api/ton/TonSignProof.ts +5 -1
  724. package/src/api/tron/TronGetAddress.ts +4 -0
  725. package/src/api/tron/TronSignMessage.ts +19 -8
  726. package/src/api/tron/TronSignTransaction.ts +5 -1
  727. package/src/api/utils.ts +32 -3
  728. package/src/api/xrp/XrpGetAddress.ts +4 -0
  729. package/src/api/xrp/XrpSignTransaction.ts +5 -1
  730. package/src/constants/index.ts +1 -4
  731. package/src/core/RequestQueue.ts +0 -18
  732. package/src/core/deviceEventRegistration.ts +4 -0
  733. package/src/core/index.ts +583 -203
  734. package/src/core/uiPromiseRegistry.ts +63 -0
  735. package/src/data/messages/messages-protocol-v2.json +515 -540
  736. package/src/data-manager/DataManager.ts +162 -44
  737. package/src/data-manager/TransportManager.ts +10 -2
  738. package/src/data-manager/connectSettings.ts +11 -0
  739. package/src/device/Device.ts +1016 -254
  740. package/src/device/DeviceCommands.ts +175 -157
  741. package/src/device/DeviceConnector.ts +59 -22
  742. package/src/device/DeviceFeaturesState.ts +25 -0
  743. package/src/device/DevicePool.ts +96 -19
  744. package/src/device/DeviceStateMapper.ts +422 -0
  745. package/src/device/DeviceStateProjector.ts +152 -0
  746. package/src/device/DeviceStateStore.ts +232 -0
  747. package/src/device/DeviceWalletSessionStore.ts +72 -6
  748. package/src/device/cloneDeviceState.ts +39 -0
  749. package/src/device/deviceIdentity.ts +18 -0
  750. package/src/deviceProfile/buildDeviceFeatures.ts +199 -188
  751. package/src/deviceProfile/index.ts +0 -1
  752. package/src/deviceProfile/protocolV2DeviceIdentity.ts +35 -0
  753. package/src/events/call.ts +0 -6
  754. package/src/events/core.ts +0 -2
  755. package/src/events/device.ts +18 -1
  756. package/src/events/iframe.ts +0 -1
  757. package/src/events/logBlockEvent.ts +93 -2
  758. package/src/events/ui-promise.ts +4 -2
  759. package/src/events/ui-request.ts +37 -2
  760. package/src/events/ui-response.ts +12 -2
  761. package/src/index.ts +7 -4
  762. package/src/inject.ts +89 -55
  763. package/src/lowLevelInject.ts +11 -7
  764. package/src/protocols/protocol-v2/deviceSession.ts +24 -0
  765. package/src/protocols/protocol-v2/features.ts +104 -45
  766. package/src/protocols/protocol-v2/firmware.ts +3 -1
  767. package/src/protocols/protocol-v2/index.ts +9 -2
  768. package/src/protocols/protocol-v2/resources.ts +173 -0
  769. package/src/protocols/protocol-v2/settingsUnlockPolicy.ts +65 -0
  770. package/src/protocols/protocol-v2/uiInteraction.ts +50 -9
  771. package/src/protocols/protocol-v2/unlockPolicy.ts +1 -0
  772. package/src/protocols/protocol-v2/unlockPolicyRunner.ts +136 -0
  773. package/src/protocols/protocol-v2/walletSession.ts +395 -130
  774. package/src/topLevelInject.ts +11 -6
  775. package/src/types/api/checkAllFirmwareRelease.ts +72 -9
  776. package/src/types/api/checkBLEFirmwareRelease.ts +4 -13
  777. package/src/types/api/checkBootloaderRelease.ts +2 -6
  778. package/src/types/api/checkFirmwareRelease.ts +2 -13
  779. package/src/types/api/checkFirmwareTypeAvailable.ts +2 -2
  780. package/src/types/api/detectDeviceConnectProtocol.ts +6 -0
  781. package/src/types/api/deviceSettings.ts +26 -2
  782. package/src/types/api/deviceUnlock.ts +13 -2
  783. package/src/types/api/deviceUpdateBootloader.ts +7 -0
  784. package/src/types/api/export.ts +33 -1
  785. package/src/types/api/firmwareUpdate.ts +85 -11
  786. package/src/types/api/firmwareUpdateCapabilities.ts +9 -0
  787. package/src/types/api/firmwareUpdatePlan.ts +38 -0
  788. package/src/types/api/firmwareUpdatePreparedPlan.ts +53 -0
  789. package/src/types/api/getDeviceState.ts +19 -0
  790. package/src/types/api/getFeatures.ts +3 -0
  791. package/src/types/api/getOnekeyFeatures.ts +3 -0
  792. package/src/types/api/getPassphraseState.ts +7 -0
  793. package/src/types/api/index.ts +43 -73
  794. package/src/types/api/kaspaSignTransaction.ts +20 -2
  795. package/src/types/api/openWalletSession.ts +54 -0
  796. package/src/types/api/protocolV2.ts +23 -190
  797. package/src/types/api/sessionCache.ts +9 -4
  798. package/src/types/device.ts +206 -9
  799. package/src/types/params.ts +9 -2
  800. package/src/types/settings.ts +37 -25
  801. package/src/utils/assets.ts +4 -1
  802. package/src/utils/deviceFeaturesCompat.ts +196 -0
  803. package/src/utils/deviceFeaturesUtils.ts +34 -14
  804. package/src/utils/deviceInfoUtils.ts +37 -70
  805. package/src/utils/deviceSettings.ts +181 -39
  806. package/src/utils/deviceVersionUtils.ts +25 -44
  807. package/src/utils/findDefectiveBatchDevice.ts +3 -3
  808. package/src/utils/homescreen.ts +37 -7
  809. package/src/utils/index.ts +26 -7
  810. package/src/utils/networkUtils.ts +274 -16
  811. package/src/utils/pro2Nft.ts +165 -0
  812. package/src/utils/pro2Wallpaper.ts +44 -25
  813. package/src/utils/tracing.ts +3 -1
  814. package/src/utils/uiProgressThrottle.ts +63 -0
  815. package/tsconfig.type-tests.json +12 -0
  816. package/__tests__/RequestQueue.test.ts +0 -34
  817. package/dist/api/GetDeviceInfo.d.ts +0 -9
  818. package/dist/api/GetDeviceInfo.d.ts.map +0 -1
  819. package/dist/api/firmware/progressThrottle.d.ts +0 -3
  820. package/dist/api/firmware/progressThrottle.d.ts.map +0 -1
  821. package/dist/api/protocol-v2/DeviceSessionOpen.d.ts +0 -28
  822. package/dist/api/protocol-v2/DeviceSessionOpen.d.ts.map +0 -1
  823. package/dist/api/protocol-v2/DeviceSettingsGet.d.ts +0 -6
  824. package/dist/api/protocol-v2/DeviceSettingsGet.d.ts.map +0 -1
  825. package/dist/api/protocol-v2/DeviceSettingsPageShow.d.ts +0 -16
  826. package/dist/api/protocol-v2/DeviceSettingsPageShow.d.ts.map +0 -1
  827. package/dist/api/protocol-v2/DeviceSettingsSet.d.ts +0 -12
  828. package/dist/api/protocol-v2/DeviceSettingsSet.d.ts.map +0 -1
  829. package/dist/deviceProfile/buildDeviceProfile.d.ts +0 -22
  830. package/dist/deviceProfile/buildDeviceProfile.d.ts.map +0 -1
  831. package/dist/protocols/protocol-v2/lockedError.d.ts +0 -2
  832. package/dist/protocols/protocol-v2/lockedError.d.ts.map +0 -1
  833. package/dist/protocols/protocol-v2/unlockRetry.d.ts +0 -11
  834. package/dist/protocols/protocol-v2/unlockRetry.d.ts.map +0 -1
  835. package/dist/types/api/getDeviceInfo.d.ts +0 -88
  836. package/dist/types/api/getDeviceInfo.d.ts.map +0 -1
  837. package/src/api/GetDeviceInfo.ts +0 -152
  838. package/src/api/firmware/progressThrottle.ts +0 -44
  839. package/src/api/protocol-v2/DeviceSessionOpen.ts +0 -100
  840. package/src/api/protocol-v2/DeviceSettingsGet.ts +0 -16
  841. package/src/api/protocol-v2/DeviceSettingsPageShow.ts +0 -67
  842. package/src/api/protocol-v2/DeviceSettingsSet.ts +0 -49
  843. package/src/deviceProfile/buildDeviceProfile.ts +0 -370
  844. package/src/protocols/protocol-v2/lockedError.ts +0 -10
  845. package/src/protocols/protocol-v2/unlockRetry.ts +0 -76
  846. package/src/types/api/getDeviceInfo.ts +0 -106
@@ -1,41 +1,46 @@
1
1
  import EventEmitter from 'events';
2
2
  import semver from 'semver';
3
- import { Enum_Capability } from '@onekeyfe/hd-transport';
3
+ import { DeviceRebootType, DeviceSessionPinType, Enum_Capability } from '@onekeyfe/hd-transport';
4
4
  import {
5
5
  EDeviceType,
6
+ EFirmwareType,
6
7
  ERRORS,
7
8
  ERROR_CODES_REQUIRE_DISCONNECT,
8
9
  ERROR_CODES_REQUIRE_RELEASE,
9
10
  HardwareError,
10
11
  HardwareErrorCode,
12
+ canonicalizePro2BleAdvertisementName,
11
13
  createDeferred,
12
14
  createDeviceNotSupportMethodError,
13
15
  } from '@onekeyfe/hd-shared';
14
16
 
15
- import {
16
- LoggerNames,
17
- getDeviceBLEFirmwareVersion,
18
- getDeviceBleName,
19
- getDeviceFirmwareVersion,
20
- getDeviceLabel,
21
- getDeviceType,
22
- getDeviceUUID,
23
- getFirmwareType,
24
- getLogger,
25
- } from '../utils';
17
+ import { LoggerNames, getLogger } from '../utils';
26
18
  import {
27
19
  fixFeaturesFirmwareVersion,
28
20
  getPassphraseStateWithRefreshDeviceInfo,
29
- supportInputPinOnSoftware,
30
- supportModifyHomescreen,
31
21
  } from '../utils/deviceFeaturesUtils';
22
+ import { parseDeviceVersion } from '../utils/deviceVersionUtils';
32
23
  import { generateInstanceId } from '../utils/tracing';
33
24
  // eslint-disable-next-line import/no-cycle
34
25
  import { DeviceCommands } from './DeviceCommands';
26
+ import { mergeDeviceFeaturesPatch } from './DeviceFeaturesState';
27
+ import {
28
+ mapDeviceSettingsToState,
29
+ mapFeaturesToState,
30
+ mapProtocolV1OnekeyFeaturesToState,
31
+ mapProtocolV2DeviceInfoToState,
32
+ mapProtocolV2DeviceStatusToState,
33
+ } from './DeviceStateMapper';
34
+ import { projectFeatures } from './DeviceStateProjector';
35
+ import { DeviceStateStore, createPublicDeviceState } from './DeviceStateStore';
36
+ import { cloneDeviceState } from './cloneDeviceState';
35
37
  import { deviceWalletSessionStore } from './DeviceWalletSessionStore';
36
38
  import {
37
39
  type DeviceFirmwareRange,
38
40
  DeviceModelToTypes,
41
+ type DeviceStateEvent,
42
+ type DeviceStatePatch,
43
+ type DeviceStateUpdateSource,
39
44
  DeviceTypeToModels,
40
45
  type Device as DeviceTyped,
41
46
  EOneKeyDeviceMode,
@@ -50,24 +55,37 @@ import { DEVICE, UI_REQUEST } from '../events';
50
55
  import { DataManager } from '../data-manager';
51
56
  import TransportManager from '../data-manager/TransportManager';
52
57
  import { toHardened } from '../api/helpers/pathUtils';
53
- import { existCapability } from '../utils/capabilitieUtils';
54
58
  import {
59
+ PROTOCOL_V2_DEVICE_STATUS_GET_MESSAGE_TYPE,
60
+ PROTOCOL_V2_FEATURES_DEVICE_INFO_REQUEST,
61
+ PROTOCOL_V2_FULL_DEVICE_INFO_REQUEST,
62
+ PROTOCOL_V2_VERSIONS_DEVICE_INFO_REQUEST,
63
+ type ProtocolV2RuntimeMode,
64
+ getProtocolV2RuntimeMode,
65
+ isLegacyProtocolV2ProtocolInfo,
55
66
  requestProtocolV2DeviceInfo,
56
67
  requestProtocolV2DeviceStatus,
68
+ requestProtocolV2ProtocolInfo,
69
+ supportsProtocolV2Message,
57
70
  } from '../protocols/protocol-v2/features';
58
- import { buildProtocolV1FeaturesPayload, buildProtocolV2FeaturesPayload } from '../deviceProfile';
71
+ import { buildProtocolV1FeaturesPayload } from '../deviceProfile';
72
+ import { resolveProtocolV2DeviceIdentity } from '../deviceProfile/protocolV2DeviceIdentity';
59
73
 
60
74
  import type { PROTO } from '../constants';
75
+ import type { DeviceStateReadOptions } from '../types/api/getDeviceState';
61
76
  import type {
62
77
  DeviceButtonRequestPayload,
63
78
  DeviceFeaturesPayload,
79
+ HardwareUiInteractionMeta,
64
80
  PassphraseRequestPayload,
81
+ ProtocolV2UiEventMetadata,
65
82
  } from '../events';
66
83
  import type { PassphrasePromptResponse } from './DeviceCommands';
67
84
  import type { Deferred, HardwareConnectProtocol } from '@onekeyfe/hd-shared';
68
85
  import type {
69
86
  OneKeyDeviceInfo as DeviceDescriptor,
70
87
  DeviceStatus,
88
+ ProtocolInfo,
71
89
  ProtocolV2DeviceInfo,
72
90
  Success,
73
91
  } from '@onekeyfe/hd-transport';
@@ -79,7 +97,15 @@ export type InitOptions = {
79
97
  passphraseState?: string;
80
98
  deriveCardano?: boolean;
81
99
  connectProtocol?: HardwareConnectProtocol;
100
+ forceProtocolDetection?: boolean;
82
101
  protocolV2DeviceInfoTimeoutMs?: number;
102
+ /** Refresh Protocol V2 runtime state before returning discovery results. */
103
+ refreshRuntimeState?: boolean;
104
+ /**
105
+ * Protocol V1 Initialize response timeout override. Reboot-wait polling passes a
106
+ * short value so an unanswered probe settles before the next poll tick.
107
+ */
108
+ timeoutMs?: number;
83
109
  };
84
110
 
85
111
  export type RunOptions = {
@@ -94,12 +120,35 @@ const parseRunOptions = (options?: RunOptions): RunOptions => {
94
120
 
95
121
  const Log = getLogger(LoggerNames.Device);
96
122
 
123
+ const isProtocolV2DeviceStatusUnsupportedError = (error: unknown) => {
124
+ if (error instanceof HardwareError) {
125
+ if (error.errorCode === HardwareErrorCode.DeviceNotSupportMethod) {
126
+ return true;
127
+ }
128
+ if (error.params?.failureCode === 'Failure_UnexpectedMessage') {
129
+ return true;
130
+ }
131
+ }
132
+
133
+ const message =
134
+ error instanceof Error
135
+ ? error.message
136
+ : String((error as { message?: unknown } | null)?.message ?? error ?? '');
137
+ return (
138
+ /^Failure_UnexpectedMessage(?:,|\b)/i.test(message) ||
139
+ /\b(?:unsupported message|handler not registered|message handler not found)\b/i.test(message)
140
+ );
141
+ };
142
+
97
143
  export interface DeviceEvents {
98
144
  [DEVICE.PIN]: [Device, PROTO.PinMatrixRequestType | undefined, (err: any, pin: string) => void];
145
+ [DEVICE.PIN_ON_DEVICE]: [Device, DeviceSessionPinType, ProtocolV2UiEventMetadata?];
146
+ [DEVICE.PIN_ON_DEVICE_COMPLETE]: [Device, HardwareUiInteractionMeta];
99
147
  [DEVICE.PASSPHRASE_ON_DEVICE]: [Device, PassphraseRequestPayload?];
100
148
  [DEVICE.ATTACH_PIN_ON_DEVICE]: [Device, PassphraseRequestPayload?];
101
149
  [DEVICE.BUTTON]: [Device, DeviceButtonRequestPayload];
102
150
  [DEVICE.FEATURES]: [Device, DeviceFeaturesPayload];
151
+ [DEVICE.STATE]: [Device, DeviceStateEvent];
103
152
  [DEVICE.PASSPHRASE]: [
104
153
  Device,
105
154
  PassphraseRequestPayload,
@@ -129,7 +178,8 @@ export interface Device {
129
178
  * This allows short-lived processes (e.g. CLI) to restore a previously
130
179
  * obtained session, avoiding the need to re-enter passphrase on every
131
180
  * invocation. The session must have been obtained from a prior
132
- * getPassphraseState() call on the same device.
181
+ * wallet-session call on the same device. This compatibility hook is intended
182
+ * for a trusted CLI process restoring its own OS-keychain entry.
133
183
  *
134
184
  * @param deviceId - The device's device_id (from features)
135
185
  * @param passphraseState - The passphrase state token
@@ -187,24 +237,66 @@ export class Device extends EventEmitter {
187
237
  private deviceAcquired = false;
188
238
 
189
239
  /**
190
- * 唯一设备状态缓存。
191
- *
192
- * V1 直接保存原生 Features;V2 保存由 DeviceInfoGet 映射出的
193
- * Features 视图。Device 不再保存 profile,结构化 DeviceProfile 只作为
194
- * getDeviceInfo() 的 API 返回值存在。
240
+ * Connection-attempt generation. interruptionFromUser() pins the current
241
+ * attempt so a late acquire cannot finish, while the next public connect
242
+ * increments this and is allowed to proceed.
195
243
  */
196
- features: Features | undefined = undefined;
244
+ private connectionAttempt = 0;
197
245
 
198
- /**
199
- * 是否需要更新设备信息。
200
- *
201
- * 历史名称保留用于兼容现有调用语义;对 V2 表示 features 需要由
202
- * DeviceInfoGet 刷新。
203
- */
204
- featuresNeedsReload = false;
246
+ private interruptedAttempt: number | null = null;
247
+
248
+ /** Canonical device-state cache; legacy Features is a compatibility projection. */
249
+ private stateStore = new DeviceStateStore();
250
+
251
+ /** Force the next initialization to reload DeviceInfo after reconnect or reboot. */
252
+ private protocolV2StateNeedsReload = false;
253
+
254
+ /** Runtime context negotiated once per active Protocol V2 link. */
255
+ private protocolV2RuntimeContext?: ProtocolInfo;
256
+
257
+ /** Coalesces concurrent first-use runtime negotiation on the same active link. */
258
+ private protocolV2RuntimeContextPromise?: Promise<ProtocolInfo>;
259
+
260
+ /** Invalidates an in-flight runtime-context response without adding a transport epoch. */
261
+ private protocolV2RuntimeContextRequestToken?: object;
262
+
263
+ private protocolV2UiInteraction?: {
264
+ interactionId: string;
265
+ phaseCounter: number;
266
+ sequence: number;
267
+ opened: boolean;
268
+ };
269
+
270
+ private protocolV2UiInteractionCounter = 0;
271
+
272
+ get state() {
273
+ return this.stateStore.getState();
274
+ }
275
+
276
+ get features(): Features | undefined {
277
+ if (!this.state) return undefined;
278
+ return projectFeatures(this.state);
279
+ }
280
+
281
+ set features(features: Features | undefined) {
282
+ this.stateStore = new DeviceStateStore();
283
+ if (features) {
284
+ this.stateStore.update(mapFeaturesToState(features), 'compatibility');
285
+ const { passphraseState } = features;
286
+ const sessionId = features.sessionId ?? features.session_id;
287
+ const deviceKey = this.getSessionCacheDeviceKey(features.deviceId ?? undefined);
288
+ if (passphraseState && sessionId && deviceKey) {
289
+ this.passphraseState = passphraseState;
290
+ deviceWalletSessionStore.set(deviceKey, passphraseState, sessionId);
291
+ }
292
+ }
293
+ }
205
294
 
206
295
  runPromise?: Deferred<void> | null;
207
296
 
297
+ /** Resolves only after the active run has completed its release path. */
298
+ private runCleanupPromise?: Promise<void>;
299
+
208
300
  externalState: string[] = [];
209
301
 
210
302
  unavailableCapabilities: UnavailableCapabilities = {};
@@ -255,38 +347,46 @@ export class Device extends EventEmitter {
255
347
 
256
348
  // simplified object to pass via postMessage
257
349
  toMessageObject(): DeviceTyped | null {
258
- if (this.isUnacquired()) return null;
350
+ if (this.isUnacquired() || !this.features) return null;
259
351
 
260
352
  const env = DataManager.getSettings('env');
261
353
  const deviceType = this.getCurrentDeviceType();
262
354
 
263
355
  const bleName = this.getCurrentBleName();
264
- const label = this.getCurrentLabel();
356
+ const displayName = this.getCurrentDisplayName();
265
357
  const serialNo = this.getCurrentSerialNo();
266
358
  const connectId = this.getConnectId();
267
359
  const deviceId = this.getCurrentDeviceId() || null;
268
360
 
269
361
  const { features } = this;
362
+ const state = this.state ? createPublicDeviceState(this.state) : undefined;
270
363
 
271
364
  return {
272
- /** Android uses Mac address, iOS uses uuid, USB uses uuid */
365
+ /** Android uses a MAC address, while iOS and USB use transport-specific identifiers. */
273
366
  connectId: DataManager.isBleConnect(env) ? this.mainId || null : connectId,
274
- /** Hardware ID, will not change at any time */
367
+ /** Persist this after the first active probe so later calls do not need to guess. */
368
+ connectProtocol: this.originalDescriptor.protocolType,
369
+ /** Stable physical-device identity. */
370
+ serialNo,
371
+ /** @deprecated Use serialNo instead. */
275
372
  uuid: serialNo,
276
373
  commType: this.originalDescriptor.commType,
277
374
  sdkInstanceId: this.sdkInstanceId,
278
375
  instanceId: this.instanceId,
279
376
  createdAt: this.createdAt,
280
377
  deviceType,
281
- /** ID for current seeds, will clear after replace a new seed at device */
378
+ /** Wallet-lifecycle ID; changes after the device is wiped or reinitialized. */
282
379
  deviceId,
283
380
  path: this.originalDescriptor?.path,
284
381
  bleName,
285
- name: bleName || label || `OneKey ${deviceType?.toUpperCase()}`,
286
- label: label || 'OneKey',
382
+ name: bleName || displayName || `OneKey ${deviceType?.toUpperCase()}`,
383
+ // Keep the legacy top-level field string-compatible while preserving
384
+ // the canonical nullable value at state.identity.label.
385
+ label: displayName ?? '',
386
+ status: this.getStatus(),
287
387
  mode: this.getMode(),
288
388
  features,
289
- sessionId: this.features?.sessionId ?? null,
389
+ state,
290
390
  firmwareVersion: this.getFirmwareVersion(),
291
391
  bleFirmwareVersion: this.getBLEFirmwareVersion(),
292
392
  unavailableCapabilities: this.unavailableCapabilities,
@@ -297,13 +397,20 @@ export class Device extends EventEmitter {
297
397
  * Device connect
298
398
  * @returns {Promise<boolean>}
299
399
  */
300
- connect(connectProtocol?: HardwareConnectProtocol) {
400
+ connect(
401
+ connectProtocol?: HardwareConnectProtocol,
402
+ options?: { forceProtocolDetection?: boolean }
403
+ ) {
301
404
  const env = DataManager.getSettings('env');
302
405
  // eslint-disable-next-line no-async-promise-executor
303
406
  return new Promise<boolean>(async (resolve, reject) => {
304
407
  if (DataManager.isBleConnect(env)) {
408
+ if (this.hasDeviceAcquire() && this.commands && !this.commands.disposed) {
409
+ resolve(true);
410
+ return;
411
+ }
305
412
  try {
306
- await this.acquire(connectProtocol);
413
+ await this.acquire(connectProtocol, options);
307
414
  resolve(true);
308
415
  } catch (error) {
309
416
  reject(error);
@@ -313,7 +420,7 @@ export class Device extends EventEmitter {
313
420
  // 不存在 Session ID 或存在 Session ID 但设备在别处使用,都需要 acquire 获取最新 sessionID
314
421
  if (!this.mainId || (!this.isUsedHere() && this.originalDescriptor)) {
315
422
  try {
316
- await this.acquire(connectProtocol);
423
+ await this.acquire(connectProtocol, options);
317
424
  resolve(true);
318
425
  } catch (error) {
319
426
  reject(error);
@@ -329,25 +436,33 @@ export class Device extends EventEmitter {
329
436
  }
330
437
 
331
438
  async acquire(
332
- connectProtocol?: HardwareConnectProtocol,
333
- options?: { throwOnRunPromiseError?: boolean }
439
+ expectedProtocol?: HardwareConnectProtocol,
440
+ options?: { throwOnRunPromiseError?: boolean; forceProtocolDetection?: boolean }
334
441
  ) {
442
+ const attempt = this.connectionAttempt;
443
+ this.throwIfInterruptedByUser();
335
444
  const env = DataManager.getSettings('env');
336
445
  const mainIdKey = DataManager.isBleConnect(env) ? 'id' : 'session';
337
- const expectedProtocol = connectProtocol ?? this.originalDescriptor.protocolType;
446
+ const previousProtocol = this.originalDescriptor.protocolType;
447
+ // A protocol stored after a successful probe is authoritative. Only the explicit
448
+ // first-connection/recovery path may bypass it and probe both protocols again.
449
+ const strictProtocol = options?.forceProtocolDetection
450
+ ? undefined
451
+ : expectedProtocol ?? this.originalDescriptor.protocolType;
338
452
  try {
339
453
  let acquireResult: unknown;
340
454
  if (DataManager.isBleConnect(env)) {
341
- // forceCleanRunPromise=true(自 e21b83c6 引入,修复 Pro2 BLE 重连):
342
- // acquire 意味着开启一个全新会话,transport 里残留的上一次 runPromise
343
- // 必然属于已死亡的会话(如固件升级重启、探测中断),不清理会让新会话的
344
- // 调用被旧 promise 卡死。无法在 Device 层面区分“重连恢复”与普通 acquire,
345
- // 因此对 BLE acquire 恒清理是有意为之。
455
+ // acquire starts a new BLE session. Any previous runPromise belongs to a dead
456
+ // session, such as an interrupted probe or firmware-update reboot, and would
457
+ // otherwise block the new session. Device cannot distinguish recovery from a
458
+ // regular acquire, so BLE always clears it intentionally.
346
459
  acquireResult = await this.deviceConnector?.acquire(
347
460
  this.originalDescriptor.id,
348
461
  undefined,
349
462
  true,
350
- expectedProtocol
463
+ strictProtocol,
464
+ undefined,
465
+ options?.forceProtocolDetection
351
466
  );
352
467
  this.mainId = (acquireResult as any)?.uuid ?? '';
353
468
  Log.debug('Expected uuid:', this.mainId);
@@ -356,30 +471,68 @@ export class Device extends EventEmitter {
356
471
  this.originalDescriptor.path,
357
472
  this.originalDescriptor.session,
358
473
  undefined,
359
- expectedProtocol
474
+ strictProtocol,
475
+ undefined,
476
+ options?.forceProtocolDetection
360
477
  );
361
478
  this.mainId = acquireResult as string | undefined;
362
479
  Log.debug('Expected session id:', this.mainId);
363
480
  }
364
- this.deviceAcquired = true;
365
- this.updateDescriptor({ [mainIdKey]: this.mainId } as unknown as DeviceDescriptor);
366
-
367
481
  // Propagate protocol version detected during acquire.
368
482
  const detectedProtocol =
369
483
  (acquireResult as { protocolType?: HardwareConnectProtocol } | undefined)?.protocolType ??
370
484
  TransportManager.transport?.getProtocolType?.(
371
485
  DataManager.isBleConnect(env) ? this.originalDescriptor.id : this.originalDescriptor.path
372
486
  );
487
+ if (options?.forceProtocolDetection && !detectedProtocol) {
488
+ throw ERRORS.TypedError(
489
+ HardwareErrorCode.RuntimeError,
490
+ `Active protocol detection returned no protocol for ${
491
+ this.originalDescriptor.path || this.originalDescriptor.id
492
+ }`
493
+ );
494
+ }
373
495
  if (detectedProtocol) {
374
496
  this.originalDescriptor.protocolType = detectedProtocol;
375
497
  }
498
+ if (this.interruptedAttempt === attempt || this.connectionAttempt !== attempt) {
499
+ const session = this.mainId;
500
+ if (session && this.deviceConnector?.disconnect) {
501
+ await this.deviceConnector.disconnect(session).catch(disconnectError => {
502
+ Log.debug('Ignored disconnect after user cancel during acquire', disconnectError);
503
+ });
504
+ }
505
+ throw ERRORS.TypedError(HardwareErrorCode.DeviceInterruptedFromUser);
506
+ }
507
+ this.deviceAcquired = true;
508
+ this.updateDescriptor({ [mainIdKey]: this.mainId } as unknown as DeviceDescriptor);
376
509
 
377
510
  if (this.commands) {
378
511
  await this.commands.dispose(false);
379
512
  }
380
513
 
381
514
  this.commands = new DeviceCommands(this, this.mainId ?? '');
515
+ // Protocol V2 runtime metadata belongs to one active transport link. A
516
+ // successful acquire creates a fresh link/session, so never carry cached
517
+ // ProtocolInfo or pre-initialize state across that boundary.
518
+ this.invalidateProtocolV2RuntimeState();
382
519
  } catch (error) {
520
+ if (options?.forceProtocolDetection) {
521
+ this.originalDescriptor.protocolType = previousProtocol;
522
+ const failedSession = this.mainId;
523
+ this.deviceAcquired = false;
524
+ if (failedSession) {
525
+ try {
526
+ await this.deviceConnector?.release?.(failedSession, false);
527
+ } catch (releaseError) {
528
+ Log.debug('Failed to release an unsuccessful protocol probe', releaseError);
529
+ }
530
+ }
531
+ if (!DataManager.isBleConnect(env)) {
532
+ this.mainId = null;
533
+ this.updateDescriptor({ session: null } as DeviceDescriptor);
534
+ }
535
+ }
383
536
  if (options?.throwOnRunPromiseError) {
384
537
  throw error;
385
538
  }
@@ -421,7 +574,8 @@ export class Device extends EventEmitter {
421
574
  }
422
575
  }
423
576
  try {
424
- await this.deviceConnector?.release(this.mainId, false);
577
+ // BLE releases even when keepSession is set, so forward the intent.
578
+ await this.deviceConnector?.release(this.mainId, false, this.keepSession);
425
579
  this.updateDescriptor({ session: null } as DeviceDescriptor);
426
580
  } catch (err) {
427
581
  Log.error('[Device] release error: ', err);
@@ -483,12 +637,11 @@ export class Device extends EventEmitter {
483
637
  }
484
638
 
485
639
  /**
486
- * 唯一协议判别器。
640
+ * Canonical protocol discriminator.
487
641
  *
488
- * descriptor.protocolType 是协议探测后的结果;V2 features DeviceInfoGet
489
- * 映射产生。
490
- * SDK 的协议分支都必须走这里,不要直接读 originalDescriptor.protocolType
491
- * 或从 features 反推。
642
+ * descriptor.protocolType is established by active probing; V2 features are mapped
643
+ * from DeviceInfoGet. All protocol branches must use this method instead of reading
644
+ * originalDescriptor.protocolType directly or inferring a protocol from features.
492
645
  */
493
646
  getProtocol(): 'V1' | 'V2' {
494
647
  return this.originalDescriptor.protocolType === 'V2' ? 'V2' : 'V1';
@@ -499,53 +652,76 @@ export class Device extends EventEmitter {
499
652
  }
500
653
 
501
654
  getCurrentDeviceType() {
502
- return getDeviceType(this.features);
655
+ return this.state?.identity.deviceType ?? EDeviceType.Unknown;
503
656
  }
504
657
 
505
658
  getCurrentDeviceId() {
506
- return this.features?.deviceId || undefined;
659
+ return this.state?.identity.deviceId || undefined;
507
660
  }
508
661
 
509
662
  getCurrentSerialNo() {
510
- return this.features ? getDeviceUUID(this.features) : '';
663
+ return this.state?.identity.serialNo ?? '';
511
664
  }
512
665
 
513
666
  getConnectId() {
514
667
  const serialNo = this.getCurrentSerialNo();
515
668
  if (serialNo) return serialNo;
516
669
 
517
- // connectId SDK 内部连接路由 key。这里兜底到 transport descriptor
518
- // 不改变 features.serialNo / deviceId 的业务语义。
670
+ // connectId is an internal routing key. Falling back to the transport descriptor
671
+ // does not change the business meaning of features.serialNo or deviceId.
519
672
  return this.originalDescriptor.path || this.originalDescriptor.id || '';
520
673
  }
521
674
 
522
675
  getCurrentBleName() {
523
- return getDeviceBleName(this.features);
676
+ const bleName = this.state?.identity.bleName ?? null;
677
+ return bleName ? canonicalizePro2BleAdvertisementName(bleName) : null;
524
678
  }
525
679
 
526
680
  getCurrentLabel() {
527
- return getDeviceLabel(this.features);
681
+ return this.state?.identity.label ?? null;
682
+ }
683
+
684
+ getCurrentDisplayName() {
685
+ if (!this.state) return null;
686
+
687
+ const label = this.getCurrentLabel();
688
+ if (label) return label;
689
+
690
+ const bleName = this.getCurrentBleName();
691
+ if (bleName) return bleName;
692
+
693
+ const deviceType = this.getCurrentDeviceType();
694
+ if (deviceType === EDeviceType.ClassicPure) {
695
+ return 'OneKey Classic 1S';
696
+ }
697
+
698
+ return `OneKey ${deviceType.charAt(0).toUpperCase() + deviceType.slice(1)}`;
528
699
  }
529
700
 
530
701
  getCurrentPassphraseProtection() {
531
- return this.features?.passphraseProtection;
702
+ return this.state?.status.passphraseProtection;
532
703
  }
533
704
 
534
705
  getCurrentFirmwareType() {
535
- return getFirmwareType(this.features);
706
+ return this.state?.identity.firmwareType ?? EFirmwareType.Universal;
536
707
  }
537
708
 
538
709
  getCurrentFirmwareVersionString() {
539
- return getDeviceFirmwareVersion(this.features)?.join('.');
710
+ return parseDeviceVersion(this.state?.versions.firmware).join('.');
540
711
  }
541
712
 
542
713
  getCurrentBLEFirmwareVersionString() {
543
- if (!this.features) return undefined;
544
- return getDeviceBLEFirmwareVersion(this.features).join('.');
714
+ if (!this.state) return undefined;
715
+ return parseDeviceVersion(this.state.versions.ble).join('.');
716
+ }
717
+
718
+ getCurrentBootloaderVersionString() {
719
+ if (!this.state) return undefined;
720
+ return parseDeviceVersion(this.state.versions.bootloader).join('.');
545
721
  }
546
722
 
547
723
  getCurrentSafetyChecks() {
548
- return this.features?.safetyChecks;
724
+ return this.state?.settings.safetyChecks;
549
725
  }
550
726
 
551
727
  getCurrentMethodVersionRange(
@@ -558,6 +734,7 @@ export class Device extends EventEmitter {
558
734
  // Most-specific model first; must match getMethodVersionRange in deviceInfoUtils,
559
735
  // otherwise e.g. Classic1s resolves the looser model_mini range before model_classic1s.
560
736
  const modelFallbacks: IDeviceModel[] = [
737
+ 'model_pro2',
561
738
  'model_classic1s',
562
739
  'model_classic',
563
740
  'model_mini',
@@ -577,7 +754,8 @@ export class Device extends EventEmitter {
577
754
  if (
578
755
  deviceType === EDeviceType.Touch ||
579
756
  deviceType === EDeviceType.Pro ||
580
- deviceType === EDeviceType.Pro2
757
+ deviceType === EDeviceType.Pro2 ||
758
+ deviceType === EDeviceType.Neo
581
759
  ) {
582
760
  return { support: true };
583
761
  }
@@ -590,13 +768,12 @@ export class Device extends EventEmitter {
590
768
  }
591
769
 
592
770
  supportInputPinOnSoftware(): SupportFeatureType {
593
- if (this.features) return supportInputPinOnSoftware(this.features);
594
-
595
771
  const deviceType = this.getCurrentDeviceType();
596
772
  if (
597
773
  deviceType === EDeviceType.Touch ||
598
774
  deviceType === EDeviceType.Pro ||
599
- deviceType === EDeviceType.Pro2
775
+ deviceType === EDeviceType.Pro2 ||
776
+ deviceType === EDeviceType.Neo
600
777
  ) {
601
778
  return { support: false };
602
779
  }
@@ -609,15 +786,12 @@ export class Device extends EventEmitter {
609
786
  }
610
787
 
611
788
  supportModifyHomescreen(): SupportFeatureType {
612
- // Pro2 走独立 1.x 版本线,不能套用 Touch/Pro 3.4.0 门槛(恒 false 且未来会误判)。
613
- // 依据:firmware-pro2 协议 schema(messages-protocol-v2.json)的 ApplySettings
614
- // 包含 homescreen 字段,V2 固件从首个版本即支持修改主屏。
789
+ // Pro2 has an independent 1.x version line and must not use the Touch/Pro 3.4.0
790
+ // threshold. ApplySettings includes homescreen from the first V2 firmware version.
615
791
  if (this.isProtocolV2()) {
616
792
  return { support: true };
617
793
  }
618
794
 
619
- if (this.features) return supportModifyHomescreen(this.features);
620
-
621
795
  const deviceType = this.getCurrentDeviceType();
622
796
  if (DeviceModelToTypes.model_mini.includes(deviceType)) {
623
797
  return { support: true };
@@ -633,17 +807,25 @@ export class Device extends EventEmitter {
633
807
  const deviceId = _deviceId || this.getCurrentDeviceId();
634
808
  if (deviceId) return deviceId;
635
809
  if (this.isProtocolV2()) {
636
- return this.originalDescriptor.path || this.originalDescriptor.id;
810
+ return this.originalDescriptor.path;
637
811
  }
638
812
  return undefined;
639
813
  }
640
814
 
815
+ private reconcileSessionCacheDeviceIdentity(previousDeviceId?: string) {
816
+ deviceWalletSessionStore.reconcileDeviceIdentity({
817
+ temporaryKey: this.isProtocolV2() ? this.originalDescriptor.path : undefined,
818
+ previousDeviceId,
819
+ nextDeviceId: this.getCurrentDeviceId(),
820
+ });
821
+ }
822
+
641
823
  getInternalState(_deviceId?: string) {
642
824
  Log.debug(
643
825
  'getInternalState session param: ',
644
826
  `device_id: ${_deviceId}`,
645
- `features.deviceId: ${this.features?.deviceId}`,
646
- `passphraseState: ${this.passphraseState}`
827
+ `currentDeviceId: ${this.getCurrentDeviceId()}`,
828
+ `hasPassphraseState: ${Boolean(this.passphraseState)}`
647
829
  );
648
830
 
649
831
  const deviceId = this.getSessionCacheDeviceKey(_deviceId);
@@ -659,19 +841,26 @@ export class Device extends EventEmitter {
659
841
  return deviceWalletSessionStore.get(deviceId, this.passphraseState);
660
842
  }
661
843
 
844
+ getStandardInternalState(_deviceId?: string) {
845
+ const deviceId = this.getSessionCacheDeviceKey(_deviceId);
846
+ if (!deviceId) return undefined;
847
+ return deviceWalletSessionStore.getStandard(deviceId);
848
+ }
849
+
662
850
  // attach to pin to fix internal state
663
851
  updateInternalState(
664
852
  enablePassphrase: boolean,
665
853
  passphraseState: string | undefined,
666
854
  deviceId: string | undefined,
667
855
  sessionId: string | null = null,
668
- featuresSessionId: string | null = null
856
+ featuresSessionId: string | null = null,
857
+ walletType: 'standard' | 'hidden' = 'hidden'
669
858
  ) {
670
859
  Log.debug(
671
860
  'updateInternalState session param: ',
672
861
  `device_id: ${deviceId}`,
673
862
  `enablePassphrase: ${enablePassphrase}`,
674
- `passphraseState: ${passphraseState}`,
863
+ `hasPassphraseState: ${Boolean(passphraseState)}`,
675
864
  `hasSessionId: ${Boolean(sessionId)}`,
676
865
  `hasFeaturesSessionId: ${Boolean(featuresSessionId)}`
677
866
  );
@@ -682,7 +871,15 @@ export class Device extends EventEmitter {
682
871
  if (enablePassphrase) {
683
872
  const walletSessionId =
684
873
  sessionId || featuresSessionId || deviceWalletSessionStore.getPending(cacheDeviceKey);
685
- deviceWalletSessionStore.set(cacheDeviceKey, passphraseState, walletSessionId ?? undefined);
874
+ if (walletType === 'standard') {
875
+ deviceWalletSessionStore.setStandard(
876
+ cacheDeviceKey,
877
+ passphraseState,
878
+ walletSessionId ?? undefined
879
+ );
880
+ } else {
881
+ deviceWalletSessionStore.set(cacheDeviceKey, passphraseState, walletSessionId ?? undefined);
882
+ }
686
883
  }
687
884
 
688
885
  deviceWalletSessionStore.deletePending(cacheDeviceKey);
@@ -693,8 +890,8 @@ export class Device extends EventEmitter {
693
890
  'setInternalState session param: ',
694
891
  `hasState: ${Boolean(state)}`,
695
892
  `initSession: ${initSession}`,
696
- `deviceId: ${this.features?.deviceId}`,
697
- `passphraseState: ${this.passphraseState}`
893
+ `deviceId: ${this.getCurrentDeviceId()}`,
894
+ `hasPassphraseState: ${Boolean(this.passphraseState)}`
698
895
  );
699
896
 
700
897
  if (!this.passphraseState && !initSession) return;
@@ -721,59 +918,118 @@ export class Device extends EventEmitter {
721
918
  }
722
919
  }
723
920
 
921
+ clearStandardInternalState(_deviceId?: string) {
922
+ const deviceId = this.getSessionCacheDeviceKey(_deviceId);
923
+ if (!deviceId) return;
924
+ deviceWalletSessionStore.deleteStandard(deviceId);
925
+ }
926
+
724
927
  async initialize(options?: InitOptions) {
725
- // Protocol V2 不支持传统 Initialize,直接使用协议专用初始化流程。
928
+ this.throwIfInterruptedByUser();
929
+ // Protocol V2 does not support legacy Initialize; use its dedicated flow.
726
930
  if (this.isProtocolV2()) {
727
931
  this.passphraseState = options?.passphraseState;
728
- if (this.features && !this.featuresNeedsReload && !options?.initSession) {
729
- if (this.features.bootloaderMode) {
932
+ if (this.state && !options?.initSession && !this.protocolV2StateNeedsReload) {
933
+ if (this.state.status.mode === 'bootloader' || this.state.status.mode === 'romloader') {
730
934
  return;
731
935
  }
732
- // 普通业务调用复用缓存。动态状态由显式 getFeatures/deviceStatusGet、
733
- // 解锁流程和设备事件刷新,避免每个 SDK 方法都额外轮询 DeviceStatus。
936
+ // Normal calls reuse the cache. Explicit getDeviceState refreshes, unlock flow,
937
+ // and device events update dynamic state without polling on every SDK call.
734
938
  return;
735
939
  }
736
940
  await this._initializeProtocolV2(options);
941
+ this.protocolV2StateNeedsReload = false;
737
942
  return;
738
943
  }
739
944
 
740
- // Log.debug('initialize param:', options);
945
+ try {
946
+ const callInitialize = async (payload: Record<string, unknown>, initSession?: boolean) => {
947
+ const initStartAt = Date.now();
948
+ const { message } = await this.commands.typedCall('Initialize', 'Features', payload, {
949
+ // iOS BLE bound devices can need close to 20 seconds.
950
+ timeoutMs: options?.timeoutMs ?? 25 * 1000,
951
+ });
952
+ this.setLastInitializeDuration(Date.now() - initStartAt);
953
+ this._updateFeatures(message, initSession);
954
+ await TransportManager.reconfigure(this.features);
955
+ };
741
956
 
742
- this.passphraseState = options?.passphraseState;
957
+ const expectedDeviceId = options?.deviceId;
958
+
959
+ if (expectedDeviceId && !(this.features && this.checkDeviceId(expectedDeviceId))) {
960
+ // No locally-cached evidence that the device at this path is the
961
+ // expected one (first contact, or the cached features already disagree
962
+ // with the caller). Establish identity with a context-free Initialize
963
+ // BEFORE any wallet context (session_id / passphrase_state) goes on
964
+ // the wire. In normal flows features are always fresh — enumerate /
965
+ // getFeatures run first and every call response refreshes them — so
966
+ // this extra round trip is confined to the ambiguous cases where the
967
+ // disclosure risk actually lives.
968
+ this.passphraseState = undefined;
969
+ await callInitialize({ is_contains_attach: true });
970
+ if (!this.checkDeviceId(expectedDeviceId)) {
971
+ throw ERRORS.TypedError(HardwareErrorCode.DeviceCheckDeviceIdError);
972
+ }
973
+ }
743
974
 
744
- if (options?.initSession) {
745
- this.clearInternalState(options?.deviceId);
746
- }
975
+ this.passphraseState = options?.passphraseState;
747
976
 
748
- const internalState = this.getInternalState(options?.deviceId);
749
- const payload: any = {};
750
- if (internalState) {
751
- payload.session_id = internalState;
752
- }
977
+ if (options?.initSession) {
978
+ this.clearInternalState(options?.deviceId);
979
+ }
753
980
 
754
- if (options?.deriveCardano) {
755
- payload.derive_cardano = true;
756
- }
757
- payload.passphrase_state = options?.passphraseState;
758
- payload.is_contains_attach = true;
981
+ const internalState = this.getInternalState(options?.deviceId);
982
+ const payload: Record<string, unknown> = {
983
+ passphrase_state: options?.passphraseState,
984
+ is_contains_attach: true,
985
+ };
986
+ if (internalState) {
987
+ payload.session_id = internalState;
988
+ }
989
+ if (options?.deriveCardano) {
990
+ payload.derive_cardano = true;
991
+ }
759
992
 
760
- const initStartAt = Date.now();
761
- try {
762
- // @ts-expect-error
763
- const { message } = await Promise.race([
764
- this.commands.typedCall('Initialize', 'Features', payload),
765
- new Promise((_, reject) => {
766
- setTimeout(() => {
767
- reject(ERRORS.TypedError(HardwareErrorCode.DeviceInitializeFailed));
768
- // iOS ble bound device timeout 20s
769
- }, 25 * 1000);
770
- }),
771
- ]);
772
-
773
- const initCostMs = Date.now() - initStartAt;
774
- this.setLastInitializeDuration(initCostMs);
775
- this._updateFeatures(message, options?.initSession);
776
- await TransportManager.reconfigure(this.features);
993
+ if (this.features) {
994
+ // Re-sync the V1 message schema for THIS device before encoding
995
+ // Initialize: the process-global schema may still reflect another
996
+ // device (e.g. legacy-firmware Touch/Mini) on multi-device setups, and
997
+ // a stale legacy schema would silently strip passphrase_state /
998
+ // is_contains_attach from the wire message. Local operation, no wire
999
+ // I/O; a no-op when the schema is unchanged.
1000
+ await TransportManager.reconfigure(this.features);
1001
+ }
1002
+
1003
+ // Initialize's own Features response carries device_id, so the physical
1004
+ // device identity is validated on the same round trip instead of via a
1005
+ // separate read-only GetFeatures preflight (which doubled the wire cost
1006
+ // of every deviceId-carrying call). The method fn has not run yet, so a
1007
+ // mismatch still fails before any wallet data can be derived, with the
1008
+ // same DeviceCheckDeviceIdError. Wallet-context selection is unchanged:
1009
+ // it is decided by the Initialize payload above either way.
1010
+ const assertExpectedDeviceIdentity = () => {
1011
+ if (expectedDeviceId && !this.checkDeviceId(expectedDeviceId)) {
1012
+ // The mismatched Initialize may have cached a session under the wrong
1013
+ // device's identity; drop it so no wallet context survives from it.
1014
+ // (This also evicts any session the wrong device legitimately cached
1015
+ // under the same passphraseState — a deliberate conservative purge
1016
+ // after a physical-swap event, consistent with
1017
+ // reconcileDeviceIdentity purging the previous device's sessions.)
1018
+ this.clearInternalState();
1019
+ throw ERRORS.TypedError(HardwareErrorCode.DeviceCheckDeviceIdError);
1020
+ }
1021
+ };
1022
+
1023
+ try {
1024
+ await callInitialize(payload, options?.initSession);
1025
+ } catch (error) {
1026
+ // callInitialize can fail AFTER the wire call cached the session (e.g.
1027
+ // TransportManager.reconfigure rejecting); the identity check must
1028
+ // still run so a wrong-device session never survives the error path.
1029
+ assertExpectedDeviceIdentity();
1030
+ throw error;
1031
+ }
1032
+ assertExpectedDeviceIdentity();
777
1033
  } catch (error) {
778
1034
  Log.error('Initialization failed:', error);
779
1035
  throw error;
@@ -783,31 +1039,22 @@ export class Device extends EventEmitter {
783
1039
  /**
784
1040
  * Device initialization over Protocol V2.
785
1041
  *
786
- * Protocol V2 不走传统 Initialize/GetFeatures;直接用 DeviceInfoGet
787
- * 生成唯一的 features 状态。
1042
+ * Protocol V2 bypasses legacy Initialize/GetFeatures and builds its canonical
1043
+ * features state directly from DeviceInfoGet.
788
1044
  */
789
1045
  private async _initializeProtocolV2(options?: InitOptions) {
790
1046
  Log.debug('Initialize device via Protocol V2 features adapter');
791
1047
 
792
1048
  try {
793
- // 超时由 requestProtocolV2DeviceInfo 内部的 typedCall timeoutMs(默认 10s)负责,
794
- // 不再额外包一层 Promise.race:外层 race timer 不会清理,
795
- // 且 reject 后底层调用仍会残留。
1049
+ // typedCall applies the request timeout. An outer Promise.race would leak its
1050
+ // timer and leave the underlying call active after rejection.
796
1051
  const deviceInfo = await requestProtocolV2DeviceInfo({
797
1052
  commands: this.commands,
798
1053
  timeoutMs: options?.protocolV2DeviceInfoTimeoutMs,
799
1054
  });
800
- const deviceStatus = await requestProtocolV2DeviceStatus({
801
- commands: this.commands,
802
- }).catch(error => {
803
- Log.debug('Protocol V2 status unavailable during initialization:', error);
804
- return undefined;
805
- });
806
- // 默认请求不含 SE/hash 数据,scope 如实标注为 basic;
807
- // 完整数据由 getDeviceInfo(scope:'verify'|'full') 获取。
808
- const features = this.updateProtocolV2Features(deviceInfo, deviceStatus);
809
- Log.debug('Protocol V2 features:', features);
810
- this.featuresNeedsReload = false;
1055
+ // The default request excludes SE/hash data and therefore uses basic scope.
1056
+ // Full version and verification data require getDeviceState({ scope: 'firmware' }).
1057
+ await this.probeProtocolV2RuntimeState(deviceInfo, options?.protocolV2DeviceInfoTimeoutMs);
811
1058
  } catch (error) {
812
1059
  Log.error('Protocol V2 initialization failed:', error);
813
1060
  throw error;
@@ -819,10 +1066,7 @@ export class Device extends EventEmitter {
819
1066
  const deviceInfo = await requestProtocolV2DeviceInfo({
820
1067
  commands: this.commands,
821
1068
  });
822
- const deviceStatus = await requestProtocolV2DeviceStatus({
823
- commands: this.commands,
824
- }).catch(() => undefined);
825
- return this.updateProtocolV2Features(deviceInfo, deviceStatus);
1069
+ return this.probeProtocolV2RuntimeState(deviceInfo);
826
1070
  }
827
1071
 
828
1072
  const { message } = await this.commands.typedCall('GetFeatures', 'Features', {});
@@ -830,65 +1074,355 @@ export class Device extends EventEmitter {
830
1074
  return this.features;
831
1075
  }
832
1076
 
1077
+ async getDeviceState(params: DeviceStateReadOptions = {}) {
1078
+ const refresh = new Set(params.refreshSections ?? []);
1079
+ const getProtocolV2DeviceInfoRequest = () => {
1080
+ if (refresh.has('verification')) return PROTOCOL_V2_FULL_DEVICE_INFO_REQUEST;
1081
+ if (refresh.has('versions')) return PROTOCOL_V2_VERSIONS_DEVICE_INFO_REQUEST;
1082
+ return PROTOCOL_V2_FEATURES_DEVICE_INFO_REQUEST;
1083
+ };
1084
+ let initializedWithDeviceInfo = false;
1085
+ let refreshedDeviceInfo: ProtocolV2DeviceInfo | undefined;
1086
+
1087
+ if (!this.state) {
1088
+ if (this.isProtocolV2()) {
1089
+ const deviceInfo = await requestProtocolV2DeviceInfo({
1090
+ commands: this.commands,
1091
+ request: getProtocolV2DeviceInfoRequest(),
1092
+ });
1093
+ await this.probeProtocolV2RuntimeState(deviceInfo);
1094
+ refreshedDeviceInfo = deviceInfo;
1095
+ initializedWithDeviceInfo = true;
1096
+ } else {
1097
+ await this.getFeatures();
1098
+ }
1099
+ } else if (!this.isProtocolV2() && refresh.size > 0) {
1100
+ await this.getFeatures();
1101
+ }
1102
+
1103
+ const supportsProtocolV1OnekeyFeatures =
1104
+ this.getCurrentDeviceType() === EDeviceType.Touch ||
1105
+ this.getCurrentDeviceType() === EDeviceType.Pro;
1106
+ if (!this.isProtocolV2() && refresh.has('verification') && supportsProtocolV1OnekeyFeatures) {
1107
+ const { message } = await this.commands.typedCall('OnekeyGetFeatures', 'OnekeyFeatures');
1108
+ this.updateState(mapProtocolV1OnekeyFeaturesToState(message), 'device-info');
1109
+ }
1110
+
1111
+ if (this.isProtocolV2()) {
1112
+ const refreshDeviceInfo =
1113
+ refresh.has('identity') || refresh.has('versions') || refresh.has('verification');
1114
+ if (refreshDeviceInfo && !initializedWithDeviceInfo) {
1115
+ const deviceInfo = await requestProtocolV2DeviceInfo({
1116
+ commands: this.commands,
1117
+ request: getProtocolV2DeviceInfoRequest(),
1118
+ });
1119
+ refreshedDeviceInfo = deviceInfo;
1120
+ if (!refresh.has('status')) {
1121
+ this.updateState(
1122
+ mapProtocolV2DeviceInfoToState(deviceInfo, this.state?.status.mode),
1123
+ 'device-info'
1124
+ );
1125
+ }
1126
+ }
1127
+
1128
+ if (refresh.has('status') && !initializedWithDeviceInfo) {
1129
+ const cachedMode = this.state?.status.mode;
1130
+ await this.probeProtocolV2RuntimeState(refreshedDeviceInfo, undefined, {
1131
+ // Loader firmware does not support DeviceStatusGet. Renegotiate ProtocolInfo
1132
+ // during an explicit refresh so a device rebooted into application firmware
1133
+ // can leave the cached loader state.
1134
+ forceRuntimeContextRefresh: cachedMode === 'bootloader' || cachedMode === 'romloader',
1135
+ });
1136
+ }
1137
+
1138
+ if (refresh.has('settings') && this.state?.status.mode === 'normal') {
1139
+ const { message } = await this.commands.typedCall(
1140
+ 'DeviceSettingsGet',
1141
+ 'DeviceSettings',
1142
+ {}
1143
+ );
1144
+ this.updateState(mapDeviceSettingsToState(message), 'settings-read');
1145
+ }
1146
+ }
1147
+
1148
+ if (!this.state) {
1149
+ throw ERRORS.TypedError(HardwareErrorCode.DeviceInitializeFailed);
1150
+ }
1151
+ return params.includeRaw ? cloneDeviceState(this.state) : createPublicDeviceState(this.state);
1152
+ }
1153
+
1154
+ async refreshProtocolV2SettingsAfterMutation() {
1155
+ return this.getDeviceState({ refreshSections: ['status', 'settings'] });
1156
+ }
1157
+
833
1158
  _updateFeatures(protoFeatures: PROTO.Features | Features, initSession?: boolean) {
834
- const previousCacheDeviceKey = this.getSessionCacheDeviceKey();
1159
+ const previousDeviceId = this.getCurrentDeviceId();
835
1160
  let feat =
836
1161
  'protocol' in protoFeatures
837
1162
  ? protoFeatures
838
1163
  : buildProtocolV1FeaturesPayload(protoFeatures, this.features);
839
1164
 
840
- // GetFeatures doesn't return 'session_id'
841
- if (this.features?.sessionId && !feat.sessionId) {
842
- feat.sessionId = this.features.sessionId;
843
- }
844
1165
  feat.unlocked = feat.unlocked ?? true;
845
1166
 
846
1167
  feat = fixFeaturesFirmwareVersion(feat);
847
1168
 
848
- this.features = feat;
849
- const nextCacheDeviceKey = this.getSessionCacheDeviceKey();
850
- if (previousCacheDeviceKey && nextCacheDeviceKey) {
851
- deviceWalletSessionStore.migrateDeviceKey(previousCacheDeviceKey, nextCacheDeviceKey);
852
- }
1169
+ this.updateState(mapFeaturesToState(feat), 'initialize');
1170
+ this.reconcileSessionCacheDeviceIdentity(previousDeviceId);
853
1171
  if (feat.deviceId && feat.sessionId) {
854
1172
  this.setInternalState(feat.sessionId, initSession);
855
1173
  }
856
- this.featuresNeedsReload = false;
857
- this.emit(DEVICE.FEATURES, this, feat);
858
- }
859
-
860
- updateProtocolV2Features(deviceInfo?: ProtocolV2DeviceInfo, deviceStatus?: DeviceStatus | null) {
861
- const previousCacheDeviceKey = this.getSessionCacheDeviceKey();
862
- const resolvedDeviceStatus =
863
- deviceStatus === undefined
864
- ? this.features?.raw?.protocolV2DeviceStatus
865
- : deviceStatus ?? undefined;
866
- const features = fixFeaturesFirmwareVersion(
867
- buildProtocolV2FeaturesPayload({
868
- deviceInfo,
869
- deviceStatus: resolvedDeviceStatus,
870
- previous: this.features,
871
- })
872
- );
873
- this.features = features;
874
- const nextCacheDeviceKey = this.getSessionCacheDeviceKey();
875
- if (previousCacheDeviceKey && nextCacheDeviceKey) {
876
- deviceWalletSessionStore.migrateDeviceKey(previousCacheDeviceKey, nextCacheDeviceKey);
1174
+ }
1175
+
1176
+ updateState(patch: DeviceStatePatch, source: DeviceStateUpdateSource) {
1177
+ const result = this.stateStore.update(patch, source);
1178
+ if (result.changedKeys.length === 0) return result.state;
1179
+
1180
+ const event: DeviceStateEvent = {
1181
+ connectId: this.getConnectId() ?? null,
1182
+ state: createPublicDeviceState(result.state),
1183
+ revision: result.revision,
1184
+ source,
1185
+ changedKeys: result.changedKeys,
1186
+ };
1187
+ Log.debug('Device state updated', {
1188
+ source,
1189
+ revision: result.revision,
1190
+ changedKeyCount: result.changedKeys.length,
1191
+ });
1192
+ this.emit(DEVICE.STATE, this, event);
1193
+ if (result.state.protocol === 'V1') {
1194
+ this.emit(DEVICE.FEATURES, this, projectFeatures(result.state));
1195
+ }
1196
+ return result.state;
1197
+ }
1198
+
1199
+ updateFeaturesPatch(patch: Partial<Features>, source: DeviceStateUpdateSource) {
1200
+ const currentFeatures = this.features;
1201
+ if (!currentFeatures) return undefined;
1202
+
1203
+ const features = mergeDeviceFeaturesPatch(currentFeatures, patch);
1204
+ if (features === currentFeatures) return currentFeatures;
1205
+
1206
+ const normalized = fixFeaturesFirmwareVersion(features);
1207
+ this.updateState(mapFeaturesToState(normalized), source);
1208
+ return this.features;
1209
+ }
1210
+
1211
+ async ensureProtocolV2RuntimeContext(
1212
+ timeoutMs?: number,
1213
+ options?: { forceRefresh?: boolean }
1214
+ ): Promise<ProtocolInfo> {
1215
+ const cachedProtocolInfo =
1216
+ options?.forceRefresh === true
1217
+ ? undefined
1218
+ : this.protocolV2RuntimeContext ??
1219
+ (!this.protocolV2StateNeedsReload
1220
+ ? this.state?.raw?.protocolV2ProtocolInfo ?? undefined
1221
+ : undefined);
1222
+ if (cachedProtocolInfo) {
1223
+ this.protocolV2RuntimeContext = cachedProtocolInfo;
1224
+ return cachedProtocolInfo;
1225
+ }
1226
+
1227
+ if (this.protocolV2RuntimeContextPromise) {
1228
+ return this.protocolV2RuntimeContextPromise;
1229
+ }
1230
+
1231
+ const requestToken = {};
1232
+ const pendingRequest = (async () => {
1233
+ const protocolInfo = await requestProtocolV2ProtocolInfo({
1234
+ commands: this.commands,
1235
+ timeoutMs,
1236
+ });
1237
+ if (this.protocolV2RuntimeContextRequestToken !== requestToken) {
1238
+ throw ERRORS.TypedError(
1239
+ HardwareErrorCode.DeviceInitializeFailed,
1240
+ 'Protocol V2 runtime context was invalidated while loading.'
1241
+ );
1242
+ }
1243
+ this.protocolV2RuntimeContext = protocolInfo;
1244
+ return protocolInfo;
1245
+ })();
1246
+ this.protocolV2RuntimeContextRequestToken = requestToken;
1247
+ this.protocolV2RuntimeContextPromise = pendingRequest;
1248
+
1249
+ try {
1250
+ return await pendingRequest;
1251
+ } finally {
1252
+ if (this.protocolV2RuntimeContextPromise === pendingRequest) {
1253
+ this.protocolV2RuntimeContextPromise = undefined;
1254
+ }
1255
+ if (this.protocolV2RuntimeContextRequestToken === requestToken) {
1256
+ this.protocolV2RuntimeContextRequestToken = undefined;
1257
+ }
1258
+ }
1259
+ }
1260
+
1261
+ async probeProtocolV2RuntimeState(
1262
+ deviceInfo?: ProtocolV2DeviceInfo,
1263
+ timeoutMs?: number,
1264
+ options?: {
1265
+ forceRuntimeContextRefresh?: boolean;
1266
+ }
1267
+ ) {
1268
+ const protocolInfo = await this.ensureProtocolV2RuntimeContext(timeoutMs, {
1269
+ forceRefresh: options?.forceRuntimeContextRefresh,
1270
+ });
1271
+ const runtimeDeviceInfo = deviceInfo ?? this.state?.raw?.protocolV2DeviceInfo;
1272
+ const runtimeMode = getProtocolV2RuntimeMode(protocolInfo, runtimeDeviceInfo);
1273
+ const legacyProtocolInfo = isLegacyProtocolV2ProtocolInfo(protocolInfo);
1274
+ const protocolV2DeviceType = runtimeDeviceInfo
1275
+ ? resolveProtocolV2DeviceIdentity(runtimeDeviceInfo.hw?.Device_type).deviceType
1276
+ : this.getCurrentDeviceType();
1277
+ if (
1278
+ runtimeMode === 'romloader' &&
1279
+ protocolV2DeviceType !== EDeviceType.Pro2 &&
1280
+ protocolV2DeviceType !== EDeviceType.Neo
1281
+ ) {
1282
+ throw ERRORS.TypedError(
1283
+ HardwareErrorCode.DeviceInitializeFailed,
1284
+ 'Protocol V2 romloader mode is only supported for Pro2 and Neo.'
1285
+ );
1286
+ }
1287
+ const deviceStatusSupported =
1288
+ legacyProtocolInfo ||
1289
+ supportsProtocolV2Message(protocolInfo, PROTOCOL_V2_DEVICE_STATUS_GET_MESSAGE_TYPE);
1290
+
1291
+ if (runtimeMode === 'bootloader' || runtimeMode === 'romloader') {
1292
+ return this.updateProtocolV2Features(deviceInfo, null, runtimeMode, protocolInfo);
1293
+ }
1294
+
1295
+ if (!deviceStatusSupported) {
1296
+ if (runtimeMode === 'normal') {
1297
+ return this.updateProtocolV2Features(deviceInfo, null, runtimeMode, protocolInfo);
1298
+ }
1299
+ throw ERRORS.TypedError(
1300
+ HardwareErrorCode.DeviceInitializeFailed,
1301
+ `Unknown Protocol V2 build fingerprint without DeviceStatusGet capability: ${protocolInfo.build_fingerprint}`
1302
+ );
1303
+ }
1304
+
1305
+ let deviceStatus: DeviceStatus;
1306
+ try {
1307
+ deviceStatus = await requestProtocolV2DeviceStatus({
1308
+ commands: this.commands,
1309
+ timeoutMs,
1310
+ });
1311
+ } catch (error) {
1312
+ if (runtimeMode === undefined && isProtocolV2DeviceStatusUnsupportedError(error)) {
1313
+ return this.updateProtocolV2Features(deviceInfo, null, 'bootloader', protocolInfo);
1314
+ }
1315
+ throw error;
877
1316
  }
878
- this.featuresNeedsReload = false;
879
- this.emit(DEVICE.FEATURES, this, features);
880
- return features;
1317
+ return this.updateProtocolV2Features(deviceInfo, deviceStatus, 'normal', protocolInfo);
1318
+ }
1319
+
1320
+ updateProtocolV2Features(
1321
+ deviceInfo?: ProtocolV2DeviceInfo,
1322
+ deviceStatus?: DeviceStatus | null,
1323
+ runtimeMode?: ProtocolV2RuntimeMode,
1324
+ protocolInfo?: ProtocolInfo
1325
+ ) {
1326
+ const previousDeviceId = this.getCurrentDeviceId();
1327
+ const resolvedMode = runtimeMode ?? (deviceStatus ? 'normal' : this.state?.status.mode);
1328
+ if (deviceInfo) {
1329
+ this.updateState(mapProtocolV2DeviceInfoToState(deviceInfo, resolvedMode), 'device-info');
1330
+ }
1331
+ if (protocolInfo) {
1332
+ this.updateState({ raw: { protocolV2ProtocolInfo: protocolInfo } }, 'device-info');
1333
+ }
1334
+ if (deviceStatus) {
1335
+ this.updateState(mapProtocolV2DeviceStatusToState(deviceStatus), 'device-status');
1336
+ }
1337
+ this.reconcileSessionCacheDeviceIdentity(previousDeviceId);
1338
+ return this.features as Features;
881
1339
  }
882
1340
 
883
1341
  updateProtocolV2Status(status: DeviceStatus) {
884
- const previousDeviceInfo = this.features?.raw?.protocolV2DeviceInfo;
885
- const previousStatus = this.features?.raw?.protocolV2DeviceStatus;
1342
+ const previousDeviceInfo = this.state?.raw?.protocolV2DeviceInfo;
1343
+ const previousStatus = this.state?.raw?.protocolV2DeviceStatus;
886
1344
  return this.updateProtocolV2Features(previousDeviceInfo, {
887
1345
  ...previousStatus,
888
1346
  ...status,
889
1347
  });
890
1348
  }
891
1349
 
1350
+ private invalidateProtocolV2RuntimeState() {
1351
+ if (!this.isProtocolV2()) return;
1352
+ this.protocolV2StateNeedsReload = true;
1353
+ this.protocolV2RuntimeContext = undefined;
1354
+ this.protocolV2RuntimeContextPromise = undefined;
1355
+ this.protocolV2RuntimeContextRequestToken = undefined;
1356
+ this.clearPreInitialized();
1357
+ }
1358
+
1359
+ markTransportDisconnected() {
1360
+ this.deviceAcquired = false;
1361
+ this.invalidateProtocolV2RuntimeState();
1362
+ }
1363
+
1364
+ invalidateAfterWipe() {
1365
+ const deviceId = this.getCurrentDeviceId();
1366
+ if (deviceId) {
1367
+ deviceWalletSessionStore.deleteDevice(deviceId);
1368
+ }
1369
+ if (this.isProtocolV2()) {
1370
+ if (this.originalDescriptor.path !== deviceId) {
1371
+ deviceWalletSessionStore.deleteDevice(this.originalDescriptor.path);
1372
+ }
1373
+ this.invalidateProtocolV2RuntimeState();
1374
+ }
1375
+
1376
+ this.passphraseState = undefined;
1377
+ this.stateStore = new DeviceStateStore();
1378
+ this.clearPreInitialized();
1379
+ this.needReloadDevice = true;
1380
+ }
1381
+
1382
+ markProtocolV2Reboot(rebootType: DeviceRebootType) {
1383
+ if (!this.isProtocolV2()) return;
1384
+
1385
+ this.invalidateProtocolV2RuntimeState();
1386
+ let loaderMode: 'bootloader' | 'romloader' | undefined;
1387
+ if (rebootType === DeviceRebootType.Bootloader) {
1388
+ loaderMode = 'bootloader';
1389
+ } else if (rebootType === DeviceRebootType.Romloader) {
1390
+ loaderMode = 'romloader';
1391
+ }
1392
+ if (loaderMode) {
1393
+ this.updateState(
1394
+ {
1395
+ identity: { deviceId: null },
1396
+ status: {
1397
+ mode: loaderMode,
1398
+ initialized: null,
1399
+ unlocked: null,
1400
+ firmwarePresent: null,
1401
+ backupRequired: null,
1402
+ noBackup: null,
1403
+ unfinishedBackup: null,
1404
+ recoveryMode: null,
1405
+ passphraseProtection: null,
1406
+ pinProtection: null,
1407
+ attachToPinEnabled: null,
1408
+ unlockedAttachPin: null,
1409
+ },
1410
+ raw: { protocolV2ProtocolInfo: null, protocolV2DeviceStatus: null },
1411
+ },
1412
+ 'transport-reconnect'
1413
+ );
1414
+ return;
1415
+ }
1416
+
1417
+ this.updateState(
1418
+ {
1419
+ status: { mode: 'normal', unlocked: null },
1420
+ raw: { protocolV2ProtocolInfo: null, protocolV2DeviceStatus: null },
1421
+ },
1422
+ 'transport-reconnect'
1423
+ );
1424
+ }
1425
+
892
1426
  /**
893
1427
  * 暂时只在 acquire 后更新 Session ID
894
1428
  * 后续看是否有需要依据 listen 返回结果更新
@@ -907,8 +1441,7 @@ export class Device extends EventEmitter {
907
1441
  }
908
1442
 
909
1443
  if (forceUpdate) {
910
- // 枚举得到的 descriptor 可能不带 protocolType(如 WebUSB enumerate),
911
- // 不能让覆盖丢掉已探测的协议结果。
1444
+ // Enumerated descriptors may omit protocolType, so preserve an actively probed value.
912
1445
  this.originalDescriptor = {
913
1446
  ...descriptor,
914
1447
  protocolType: descriptor.protocolType ?? this.originalDescriptor.protocolType,
@@ -923,6 +1456,10 @@ export class Device extends EventEmitter {
923
1456
  if (device.features) {
924
1457
  this._updateFeatures(device.features);
925
1458
  }
1459
+ // Adopting another Device instance's command channel also crosses an active
1460
+ // link boundary. Renegotiate runtime metadata on that channel instead of
1461
+ // retaining ProtocolInfo from the previous instance/session.
1462
+ this.invalidateProtocolV2RuntimeState();
926
1463
  }
927
1464
 
928
1465
  async run(fn?: () => Promise<void>, options?: RunOptions) {
@@ -931,21 +1468,54 @@ export class Device extends EventEmitter {
931
1468
  Log.debug('[Device] run error:', 'Device is running, but will cancel previous operate');
932
1469
  }
933
1470
 
1471
+ this.beginConnectionAttempt();
934
1472
  options = parseRunOptions(options);
935
1473
 
936
- this.runPromise = createDeferred(this._runInner.bind(this, fn, options));
937
- return this.runPromise.promise;
1474
+ const runPromise = createDeferred<void>();
1475
+ this.runPromise = runPromise;
1476
+ const cleanupPromise = this._runInner(fn, options, runPromise).catch(error => {
1477
+ if (this.runPromise === runPromise) {
1478
+ this.runPromise = null;
1479
+ }
1480
+ runPromise.reject(error);
1481
+ });
1482
+ this.runCleanupPromise = cleanupPromise;
1483
+ cleanupPromise
1484
+ .finally(() => {
1485
+ if (this.runCleanupPromise === cleanupPromise) {
1486
+ this.runCleanupPromise = undefined;
1487
+ }
1488
+ })
1489
+ .catch(() => undefined);
1490
+ return runPromise.promise;
938
1491
  }
939
1492
 
940
- async _runInner<T>(fn: (() => Promise<T>) | undefined, options: RunOptions) {
941
- if (!this.isUsedHere() || this.commands.disposed) {
942
- const env = DataManager.getSettings('env');
1493
+ async _runInner<T>(
1494
+ fn: (() => Promise<T>) | undefined,
1495
+ options: RunOptions,
1496
+ runPromise: Deferred<void>
1497
+ ) {
1498
+ const clearRunPromise = () => {
1499
+ if (this.runPromise === runPromise) {
1500
+ this.runPromise = null;
1501
+ }
1502
+ };
1503
+
1504
+ const env = DataManager.getSettings('env');
1505
+ if (options.forceProtocolDetection && env !== 'react-native' && this.isUsedHere()) {
1506
+ await this.release();
1507
+ }
1508
+
1509
+ if (options.forceProtocolDetection || !this.isUsedHere() || this.commands.disposed) {
943
1510
  if (env !== 'react-native') {
944
1511
  try {
945
- await this.acquire(options.connectProtocol);
1512
+ await this.acquire(options.connectProtocol, {
1513
+ forceProtocolDetection: options.forceProtocolDetection,
1514
+ });
946
1515
  } catch (error) {
947
- this.runPromise = null;
948
- return Promise.reject(error);
1516
+ clearRunPromise();
1517
+ runPromise.reject(error);
1518
+ return;
949
1519
  }
950
1520
 
951
1521
  try {
@@ -955,16 +1525,19 @@ export class Device extends EventEmitter {
955
1525
  }
956
1526
  }
957
1527
  } catch (error) {
958
- this.runPromise = null;
1528
+ await this.release();
1529
+ clearRunPromise();
959
1530
  if (error instanceof HardwareError) {
960
- return Promise.reject(error);
1531
+ runPromise.reject(error);
1532
+ return;
961
1533
  }
962
- return Promise.reject(
1534
+ runPromise.reject(
963
1535
  ERRORS.TypedError(
964
1536
  HardwareErrorCode.DeviceInitializeFailed,
965
1537
  `Initialize failed: ${error.message as string}, code: ${error.code as string}`
966
1538
  )
967
1539
  );
1540
+ return;
968
1541
  }
969
1542
  } else if (env === 'react-native') {
970
1543
  // TODO: implement react-native acquire
@@ -983,9 +1556,7 @@ export class Device extends EventEmitter {
983
1556
  try {
984
1557
  await fn();
985
1558
  } catch (e) {
986
- if (this.runPromise) {
987
- this.runPromise.reject(e);
988
- }
1559
+ runPromise.reject(e);
989
1560
 
990
1561
  if (
991
1562
  e instanceof HardwareError &&
@@ -998,7 +1569,7 @@ export class Device extends EventEmitter {
998
1569
  Log.debug(`error code ${e.errorCode} release device, mainId: ${this.mainId}`);
999
1570
  }
1000
1571
 
1001
- this.runPromise = null;
1572
+ clearRunPromise();
1002
1573
  return;
1003
1574
  }
1004
1575
  }
@@ -1012,11 +1583,8 @@ export class Device extends EventEmitter {
1012
1583
  Log.debug('release device, mainId: ', this.mainId);
1013
1584
  }
1014
1585
 
1015
- if (this.runPromise) {
1016
- this.runPromise.resolve();
1017
- }
1018
-
1019
- this.runPromise = null;
1586
+ runPromise.resolve();
1587
+ clearRunPromise();
1020
1588
  }
1021
1589
 
1022
1590
  async interruptionFromOutside() {
@@ -1030,13 +1598,32 @@ export class Device extends EventEmitter {
1030
1598
 
1031
1599
  async interruptionFromUser() {
1032
1600
  const error = ERRORS.TypedError(HardwareErrorCode.DeviceInterruptedFromUser);
1033
- await this.cancelableAction?.(error);
1601
+ this.interruptedAttempt = this.connectionAttempt;
1602
+ const cleanupPromise = this.runCleanupPromise;
1603
+ const { cancelableAction } = this;
1604
+ if (cancelableAction) {
1605
+ await cancelableAction(error);
1606
+ } else if (this.shouldSendFallbackProtocolCancel()) {
1607
+ await this.commands?.cancelDevice?.().catch(cancelError => {
1608
+ Log.debug('Protocol V2 fallback cancel error', cancelError);
1609
+ });
1610
+ } else if (!this.hasDeviceAcquire()) {
1611
+ // Pairing / connect-native / probe: drop the physical link only.
1612
+ // Never acquire or send protocol Cancel just to abort setup.
1613
+ if (this.mainId && this.deviceConnector?.disconnect) {
1614
+ await this.deviceConnector.disconnect(this.mainId).catch(disconnectError => {
1615
+ Log.debug('Ignored disconnect during user cancel without acquire', disconnectError);
1616
+ });
1617
+ }
1618
+ this.markTransportDisconnected();
1619
+ }
1034
1620
  await this.commands?.cancel();
1035
1621
 
1036
1622
  if (this.runPromise) {
1037
1623
  this.runPromise.reject(error);
1038
1624
  this.runPromise = null;
1039
1625
  }
1626
+ await cleanupPromise?.catch(() => undefined);
1040
1627
  }
1041
1628
 
1042
1629
  setCancelableAction(callback: (err?: Error) => Promise<unknown>) {
@@ -1055,39 +1642,81 @@ export class Device extends EventEmitter {
1055
1642
  }
1056
1643
 
1057
1644
  getMode() {
1058
- if (this.features?.bootloaderMode) {
1059
- // bootloader mode
1060
- return EOneKeyDeviceMode.bootloader;
1061
- }
1062
-
1063
- if (!this.features?.initialized) {
1064
- // not initialized
1065
- return EOneKeyDeviceMode.notInitialized;
1066
- }
1067
-
1068
- if (this.features?.noBackup) {
1069
- // backup mode
1070
- return EOneKeyDeviceMode.backupMode;
1645
+ switch (this.state?.status.mode) {
1646
+ case 'bootloader':
1647
+ case 'romloader':
1648
+ return EOneKeyDeviceMode.bootloader;
1649
+ case 'notInitialized':
1650
+ return EOneKeyDeviceMode.notInitialized;
1651
+ case 'backupMode':
1652
+ return EOneKeyDeviceMode.backupMode;
1653
+ case 'normal':
1654
+ return EOneKeyDeviceMode.normal;
1655
+ default:
1656
+ break;
1071
1657
  }
1072
1658
 
1073
- // normal mode
1074
1659
  return EOneKeyDeviceMode.normal;
1075
1660
  }
1076
1661
 
1662
+ getStatus() {
1663
+ if (this.isUsedElsewhere()) return 'occupied' as const;
1664
+ if (this.isUsedHere()) return 'used' as const;
1665
+ return 'available' as const;
1666
+ }
1667
+
1077
1668
  getFirmwareVersion() {
1078
- if (!this.features) return null;
1079
- return getDeviceFirmwareVersion(this.features);
1669
+ if (!this.state) return null;
1670
+ return parseDeviceVersion(this.state.versions.firmware);
1080
1671
  }
1081
1672
 
1082
1673
  getBLEFirmwareVersion() {
1083
- if (!this.features) return null;
1084
- return getDeviceBLEFirmwareVersion(this.features);
1674
+ if (!this.state) return null;
1675
+ return parseDeviceVersion(this.state.versions.ble);
1085
1676
  }
1086
1677
 
1087
1678
  isUsed() {
1088
1679
  return typeof this.originalDescriptor.session === 'string';
1089
1680
  }
1090
1681
 
1682
+ beginConnectionAttempt() {
1683
+ this.connectionAttempt += 1;
1684
+ return this.connectionAttempt;
1685
+ }
1686
+
1687
+ wasInterruptedByUser() {
1688
+ return (
1689
+ typeof this.interruptedAttempt === 'number' &&
1690
+ this.interruptedAttempt === this.connectionAttempt
1691
+ );
1692
+ }
1693
+
1694
+ private throwIfInterruptedByUser() {
1695
+ if (this.wasInterruptedByUser()) {
1696
+ throw ERRORS.TypedError(HardwareErrorCode.DeviceInterruptedFromUser);
1697
+ }
1698
+ }
1699
+
1700
+ /**
1701
+ * Protocol Cancel is only for an acquired session that is already in a
1702
+ * user-facing prompt. Connect, probe and initialize must not send Cancel
1703
+ * and must not re-acquire just to deliver one.
1704
+ */
1705
+ private shouldSendFallbackProtocolCancel() {
1706
+ if (!this.hasDeviceAcquire() || !this.isProtocolV2()) {
1707
+ return false;
1708
+ }
1709
+ if (!this.hasOpenProtocolV2UiInteraction()) {
1710
+ return false;
1711
+ }
1712
+ const env = DataManager.getSettings('env');
1713
+ return (
1714
+ DataManager.isBleConnect(env) ||
1715
+ DataManager.isBrowserWebUsb(env) ||
1716
+ DataManager.isDesktopWebUsb(env)
1717
+ );
1718
+ }
1719
+
1091
1720
  hasDeviceAcquire() {
1092
1721
  const env = DataManager.getSettings('env');
1093
1722
  if (DataManager.isBleConnect(env)) {
@@ -1099,7 +1728,7 @@ export class Device extends EventEmitter {
1099
1728
  isUsedHere() {
1100
1729
  const env = DataManager.getSettings('env');
1101
1730
  if (DataManager.isBleConnect(env)) {
1102
- return false;
1731
+ return this.deviceAcquired;
1103
1732
  }
1104
1733
  return this.isUsed() && this.originalDescriptor.session === this.mainId;
1105
1734
  }
@@ -1109,19 +1738,32 @@ export class Device extends EventEmitter {
1109
1738
  }
1110
1739
 
1111
1740
  isBootloader() {
1112
- return this.features && !!this.features.bootloaderMode;
1741
+ if (!this.state) return undefined;
1742
+ return this.state.status.mode === 'bootloader';
1743
+ }
1744
+
1745
+ isRomloader() {
1746
+ if (!this.state) return undefined;
1747
+ return (
1748
+ this.isProtocolV2() &&
1749
+ (this.getCurrentDeviceType() === EDeviceType.Pro2 ||
1750
+ this.getCurrentDeviceType() === EDeviceType.Neo) &&
1751
+ this.state.status.mode === 'romloader'
1752
+ );
1113
1753
  }
1114
1754
 
1115
1755
  isInitialized() {
1116
- return this.features && !!this.features.initialized;
1756
+ if (!this.state) return undefined;
1757
+ return this.state.status.initialized === true;
1117
1758
  }
1118
1759
 
1119
1760
  isSeedless() {
1120
- return this.features && !!this.features.noBackup;
1761
+ if (!this.state) return undefined;
1762
+ return this.state.status.noBackup === true;
1121
1763
  }
1122
1764
 
1123
1765
  isUnacquired(): boolean {
1124
- return this.features === undefined;
1766
+ return this.state === undefined;
1125
1767
  }
1126
1768
 
1127
1769
  hasUnexpectedMode(allow: string[], require: string[]) {
@@ -1151,8 +1793,9 @@ export class Device extends EventEmitter {
1151
1793
  const isModeT =
1152
1794
  deviceType === EDeviceType.Touch ||
1153
1795
  deviceType === EDeviceType.Pro ||
1154
- deviceType === EDeviceType.Pro2;
1155
- const unlocked = this.features?.unlocked;
1796
+ deviceType === EDeviceType.Pro2 ||
1797
+ deviceType === EDeviceType.Neo;
1798
+ const unlocked = this.state?.status.unlocked;
1156
1799
  const preCheckTouch = isModeT && unlocked === false;
1157
1800
  const passphraseProtection = this.getCurrentPassphraseProtection();
1158
1801
 
@@ -1165,11 +1808,91 @@ export class Device extends EventEmitter {
1165
1808
 
1166
1809
  async lockDevice(): Promise<Success> {
1167
1810
  const res = await this.commands.typedCall('LockDevice', 'Success', {});
1811
+ this.updateState({ status: { unlocked: false } }, 'lock');
1168
1812
  return res.message;
1169
1813
  }
1170
1814
 
1815
+ beginProtocolV2UiInteraction() {
1816
+ if (!this.isProtocolV2()) return;
1817
+ this.protocolV2UiInteraction = {
1818
+ interactionId: `${this.instanceId}:${Date.now()}:${++this.protocolV2UiInteractionCounter}`,
1819
+ phaseCounter: 0,
1820
+ sequence: 0,
1821
+ opened: false,
1822
+ };
1823
+ }
1824
+
1825
+ createProtocolV2UiPhaseMetadata(
1826
+ phase: HardwareUiInteractionMeta['phase'],
1827
+ transition: HardwareUiInteractionMeta['transition'],
1828
+ options?: {
1829
+ phaseId?: string;
1830
+ outcome?: HardwareUiInteractionMeta['outcome'];
1831
+ }
1832
+ ): HardwareUiInteractionMeta | undefined {
1833
+ if (!this.isProtocolV2()) return undefined;
1834
+ if (!this.protocolV2UiInteraction) this.beginProtocolV2UiInteraction();
1835
+
1836
+ const interaction = this.protocolV2UiInteraction;
1837
+ if (!interaction) return undefined;
1838
+ const phaseId =
1839
+ options?.phaseId ?? `${interaction.interactionId}:phase-${++interaction.phaseCounter}`;
1840
+ interaction.opened = true;
1841
+ interaction.sequence += 1;
1842
+
1843
+ return {
1844
+ interactionId: interaction.interactionId,
1845
+ phaseId,
1846
+ sequence: interaction.sequence,
1847
+ phase,
1848
+ transition,
1849
+ ...(options?.outcome ? { outcome: options.outcome } : {}),
1850
+ protocol: 'V2',
1851
+ };
1852
+ }
1853
+
1854
+ completeProtocolV2UiPhase(
1855
+ phase: HardwareUiInteractionMeta,
1856
+ outcome: HardwareUiInteractionMeta['outcome'] = 'succeeded'
1857
+ ) {
1858
+ return this.createProtocolV2UiPhaseMetadata(phase.phase, 'complete', {
1859
+ phaseId: phase.phaseId,
1860
+ outcome,
1861
+ });
1862
+ }
1863
+
1864
+ finishProtocolV2UiInteraction(
1865
+ outcome?: HardwareUiInteractionMeta['outcome'],
1866
+ options?: { ensureMetadata?: boolean }
1867
+ ) {
1868
+ const interaction = this.protocolV2UiInteraction;
1869
+ if (!interaction || (!interaction.opened && !options?.ensureMetadata)) {
1870
+ this.protocolV2UiInteraction = undefined;
1871
+ return undefined;
1872
+ }
1873
+
1874
+ const phaseId = `${interaction.interactionId}:phase-${Math.max(interaction.phaseCounter, 1)}`;
1875
+ interaction.opened = true;
1876
+ interaction.sequence += 1;
1877
+ const metadata: HardwareUiInteractionMeta = {
1878
+ interactionId: interaction.interactionId,
1879
+ phaseId,
1880
+ sequence: interaction.sequence,
1881
+ phase: 'processing',
1882
+ transition: 'finish',
1883
+ outcome: outcome ?? 'succeeded',
1884
+ protocol: 'V2',
1885
+ };
1886
+ this.protocolV2UiInteraction = undefined;
1887
+ return metadata;
1888
+ }
1889
+
1890
+ hasOpenProtocolV2UiInteraction() {
1891
+ return this.protocolV2UiInteraction?.opened === true;
1892
+ }
1893
+
1171
1894
  supportUnlockVersionRange(): DeviceFirmwareRange {
1172
- // 仅适用于 Protocol V1 Pro 系列;Pro2 走独立的 Protocol V2 解锁流程。
1895
+ // This range applies to Protocol V1 Pro devices; Pro2 has a dedicated unlock flow.
1173
1896
  return {
1174
1897
  pro: {
1175
1898
  min: '4.15.0',
@@ -1177,11 +1900,32 @@ export class Device extends EventEmitter {
1177
1900
  };
1178
1901
  }
1179
1902
 
1180
- async unlockDevice() {
1903
+ async unlockDevice(
1904
+ pinType?: DeviceSessionPinType,
1905
+ options?: ProtocolV2UiEventMetadata & { emitUiEvent?: boolean }
1906
+ ) {
1181
1907
  if (this.isProtocolV2()) {
1908
+ const requestedPinType = pinType ?? DeviceSessionPinType.Main;
1909
+ const interaction =
1910
+ options?.interaction ??
1911
+ (options?.emitUiEvent === false
1912
+ ? undefined
1913
+ : this.createProtocolV2UiPhaseMetadata('pin', 'start'));
1914
+ if (options?.emitUiEvent !== false) {
1915
+ this.emit(DEVICE.PIN_ON_DEVICE, this, requestedPinType, {
1916
+ source: options?.source ?? 'unlock-coordinator',
1917
+ reason: options?.reason ?? 'device-unlock',
1918
+ deviceOnly: options?.deviceOnly ?? true,
1919
+ completion: options?.completion,
1920
+ method: options?.method,
1921
+ page: options?.page,
1922
+ operation: options?.operation,
1923
+ interaction: options?.interaction ?? interaction,
1924
+ });
1925
+ }
1182
1926
  try {
1183
- await this.commands.typedCall('DeviceSessionAskPin', 'Success', undefined, {
1184
- timeoutMs: 120_000,
1927
+ await this.commands.typedCall('DeviceSessionAskPin', 'Success', {
1928
+ type: requestedPinType,
1185
1929
  });
1186
1930
  } catch (error) {
1187
1931
  const errorText =
@@ -1194,11 +1938,12 @@ export class Device extends EventEmitter {
1194
1938
  throw error;
1195
1939
  }
1196
1940
 
1197
- const { message: status } = await this.commands.typedCall(
1198
- 'DeviceStatusGet',
1199
- 'DeviceStatus',
1200
- {}
1201
- );
1941
+ const completion = interaction ? this.completeProtocolV2UiPhase(interaction) : undefined;
1942
+ if (completion) {
1943
+ this.emit(DEVICE.PIN_ON_DEVICE_COMPLETE, this, completion);
1944
+ }
1945
+
1946
+ const status = await requestProtocolV2DeviceStatus({ commands: this.commands });
1202
1947
  return this.updateProtocolV2Status(status);
1203
1948
  }
1204
1949
 
@@ -1207,8 +1952,7 @@ export class Device extends EventEmitter {
1207
1952
  type => this.supportUnlockVersionRange()[type]
1208
1953
  );
1209
1954
 
1210
- const supportAttachPinCapability = existCapability(
1211
- this.features,
1955
+ const supportAttachPinCapability = this.state?.capabilities.includes(
1212
1956
  Enum_Capability.Capability_AttachToPin
1213
1957
  );
1214
1958
  const supportUnlock =
@@ -1219,12 +1963,21 @@ export class Device extends EventEmitter {
1219
1963
 
1220
1964
  if (supportUnlock) {
1221
1965
  const res = await this.commands.typedCall('UnLockDevice', 'UnLockDeviceResponse');
1222
- if (this.features) {
1223
- this.features.unlocked = res.message.unlocked == null ? null : res.message.unlocked;
1224
- this.features.unlockedAttachPin =
1225
- res.message.unlocked_attach_pin == null ? undefined : res.message.unlocked_attach_pin;
1226
- this.features.passphraseProtection =
1227
- res.message.passphrase_protection == null ? null : res.message.passphrase_protection;
1966
+ if (this.state) {
1967
+ this.updateState(
1968
+ {
1969
+ status: {
1970
+ unlocked: res.message.unlocked == null ? null : res.message.unlocked,
1971
+ unlockedAttachPin:
1972
+ res.message.unlocked_attach_pin == null ? null : res.message.unlocked_attach_pin,
1973
+ passphraseProtection:
1974
+ res.message.passphrase_protection == null
1975
+ ? null
1976
+ : res.message.passphrase_protection,
1977
+ },
1978
+ },
1979
+ 'unlock'
1980
+ );
1228
1981
 
1229
1982
  return Promise.resolve(this.features);
1230
1983
  }
@@ -1251,25 +2004,34 @@ export class Device extends EventEmitter {
1251
2004
  async checkPassphraseStateSafety(
1252
2005
  passphraseState?: string,
1253
2006
  useEmptyPassphrase?: boolean,
1254
- skipPassphraseCheck?: boolean
2007
+ skipPassphraseCheck?: boolean,
2008
+ deriveCardano?: boolean
1255
2009
  ) {
1256
2010
  if (this.isUnacquired()) return false;
1257
2011
 
2012
+ const expectedPassphraseState = useEmptyPassphrase ? undefined : passphraseState;
1258
2013
  const { passphraseState: newPassphraseState, unlockedAttachPin } =
1259
2014
  await getPassphraseStateWithRefreshDeviceInfo(this, {
1260
- expectPassphraseState: passphraseState,
2015
+ expectPassphraseState: expectedPassphraseState,
1261
2016
  onlyMainPin: useEmptyPassphrase,
2017
+ deriveCardano,
2018
+ rejectAttachPinForMainWallet: useEmptyPassphrase === true,
1262
2019
  });
1263
2020
 
1264
2021
  // Main wallet and unlock Attach Pin, throw safe error
1265
2022
  const mainWalletUseAttachPin = unlockedAttachPin && useEmptyPassphrase;
1266
2023
  const useErrorAttachPin =
1267
- unlockedAttachPin && passphraseState && passphraseState !== newPassphraseState;
1268
- const passphraseStateMismatch = !!passphraseState && passphraseState !== newPassphraseState;
2024
+ unlockedAttachPin &&
2025
+ expectedPassphraseState &&
2026
+ expectedPassphraseState !== newPassphraseState;
2027
+ const passphraseStateMismatch =
2028
+ !!expectedPassphraseState && expectedPassphraseState !== newPassphraseState;
1269
2029
 
1270
2030
  Log.debug('Check passphrase state safety: ', {
1271
- passphraseState,
1272
- newPassphraseState,
2031
+ hasExpectedPassphraseState: Boolean(expectedPassphraseState),
2032
+ hasNewPassphraseState: Boolean(newPassphraseState),
2033
+ passphraseStateMatches:
2034
+ Boolean(expectedPassphraseState) && expectedPassphraseState === newPassphraseState,
1273
2035
  unlockedAttachPin,
1274
2036
  useEmptyPassphrase,
1275
2037
  });