@onekeyfe/hd-core 1.2.0-alpha.16 → 1.2.0-alpha.161

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