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

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