@onekeyfe/hd-core 1.2.0-alpha.24 → 1.2.0-alpha.26

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 (493) hide show
  1. package/__tests__/AllNetworkGetAddressBase.tracing.test.ts +2 -0
  2. package/__tests__/chain-params-onekey-compatibility.test.ts +229 -0
  3. package/__tests__/connectSettings.test.ts +47 -5
  4. package/__tests__/device-state-events.test.ts +124 -0
  5. package/__tests__/evmLedgerLegacySafety.test.ts +3 -1
  6. package/__tests__/firmware-update/check-all-firmware-release.test.ts +127 -0
  7. package/__tests__/firmware-update/firmware-artifact-source.test.ts +119 -0
  8. package/__tests__/firmware-update/firmware-host-binding.test.ts +70 -0
  9. package/__tests__/firmware-update/firmware-update-capabilities.test.ts +13 -0
  10. package/__tests__/firmware-update/firmware-update-plan.test.ts +354 -0
  11. package/__tests__/firmware-update/firmware-update-prepared-plan.test.ts +213 -0
  12. package/__tests__/firmware-update/firmware-update-v2-download-before-boot.test.ts +39 -30
  13. package/__tests__/firmware-update/firmware-upload-source.test.ts +70 -0
  14. package/__tests__/kaspa-public-types.type-test.ts +16 -0
  15. package/__tests__/kaspaSignTransaction.test.ts +4 -3
  16. package/__tests__/method-protocol-support.test.ts +113 -0
  17. package/__tests__/protocol-v2.test.ts +400 -123
  18. package/__tests__/public-device-state-api.test.ts +10 -8
  19. package/__tests__/tron-sign-message-init.test.ts +74 -0
  20. package/dist/api/BaseMethod.d.ts +6 -2
  21. package/dist/api/BaseMethod.d.ts.map +1 -1
  22. package/dist/api/CheckAllFirmwareRelease.d.ts.map +1 -1
  23. package/dist/api/CipherKeyValue.d.ts +1 -0
  24. package/dist/api/CipherKeyValue.d.ts.map +1 -1
  25. package/dist/api/DirList.d.ts +1 -0
  26. package/dist/api/DirList.d.ts.map +1 -1
  27. package/dist/api/DirMake.d.ts +1 -0
  28. package/dist/api/DirMake.d.ts.map +1 -1
  29. package/dist/api/DirRemove.d.ts +1 -0
  30. package/dist/api/DirRemove.d.ts.map +1 -1
  31. package/dist/api/FileDelete.d.ts +1 -0
  32. package/dist/api/FileDelete.d.ts.map +1 -1
  33. package/dist/api/FileRead.d.ts +1 -0
  34. package/dist/api/FileRead.d.ts.map +1 -1
  35. package/dist/api/FileWrite.d.ts +1 -0
  36. package/dist/api/FileWrite.d.ts.map +1 -1
  37. package/dist/api/FirmwareUpdate.d.ts.map +1 -1
  38. package/dist/api/FirmwareUpdateV2.d.ts +11 -0
  39. package/dist/api/FirmwareUpdateV2.d.ts.map +1 -1
  40. package/dist/api/FirmwareUpdateV3.d.ts +7 -3
  41. package/dist/api/FirmwareUpdateV3.d.ts.map +1 -1
  42. package/dist/api/FirmwareUpdateV4.d.ts +23 -5
  43. package/dist/api/FirmwareUpdateV4.d.ts.map +1 -1
  44. package/dist/api/GetDeviceState.d.ts +1 -0
  45. package/dist/api/GetDeviceState.d.ts.map +1 -1
  46. package/dist/api/GetFeatures.d.ts.map +1 -1
  47. package/dist/api/GetOnekeyFeatures.d.ts.map +1 -1
  48. package/dist/api/GetPassphraseState.d.ts +1 -0
  49. package/dist/api/GetPassphraseState.d.ts.map +1 -1
  50. package/dist/api/OpenWalletSession.d.ts +1 -0
  51. package/dist/api/OpenWalletSession.d.ts.map +1 -1
  52. package/dist/api/PathInfo.d.ts +1 -0
  53. package/dist/api/PathInfo.d.ts.map +1 -1
  54. package/dist/api/alephium/AlephiumGetAddress.d.ts.map +1 -1
  55. package/dist/api/alephium/AlephiumSignMessage.d.ts.map +1 -1
  56. package/dist/api/alephium/AlephiumSignTransaction.d.ts.map +1 -1
  57. package/dist/api/algo/AlgoGetAddress.d.ts +1 -0
  58. package/dist/api/algo/AlgoGetAddress.d.ts.map +1 -1
  59. package/dist/api/algo/AlgoSignTransaction.d.ts +1 -0
  60. package/dist/api/algo/AlgoSignTransaction.d.ts.map +1 -1
  61. package/dist/api/allnetwork/AllNetworkGetAddressBase.d.ts +1 -0
  62. package/dist/api/allnetwork/AllNetworkGetAddressBase.d.ts.map +1 -1
  63. package/dist/api/aptos/AptosGetAddress.d.ts +1 -0
  64. package/dist/api/aptos/AptosGetAddress.d.ts.map +1 -1
  65. package/dist/api/aptos/AptosGetPublicKey.d.ts +1 -0
  66. package/dist/api/aptos/AptosGetPublicKey.d.ts.map +1 -1
  67. package/dist/api/aptos/AptosSignInMessage.d.ts +1 -0
  68. package/dist/api/aptos/AptosSignInMessage.d.ts.map +1 -1
  69. package/dist/api/aptos/AptosSignMessage.d.ts +1 -0
  70. package/dist/api/aptos/AptosSignMessage.d.ts.map +1 -1
  71. package/dist/api/aptos/AptosSignTransaction.d.ts +1 -0
  72. package/dist/api/aptos/AptosSignTransaction.d.ts.map +1 -1
  73. package/dist/api/benfen/BenfenGetAddress.d.ts.map +1 -1
  74. package/dist/api/benfen/BenfenGetPublicKey.d.ts.map +1 -1
  75. package/dist/api/benfen/BenfenSignMessage.d.ts.map +1 -1
  76. package/dist/api/benfen/BenfenSignTransaction.d.ts.map +1 -1
  77. package/dist/api/btc/BTCGetAddress.d.ts +1 -0
  78. package/dist/api/btc/BTCGetAddress.d.ts.map +1 -1
  79. package/dist/api/btc/BTCGetPublicKey.d.ts +1 -0
  80. package/dist/api/btc/BTCGetPublicKey.d.ts.map +1 -1
  81. package/dist/api/btc/BTCSignMessage.d.ts +1 -0
  82. package/dist/api/btc/BTCSignMessage.d.ts.map +1 -1
  83. package/dist/api/btc/BTCSignPsbt.d.ts +1 -0
  84. package/dist/api/btc/BTCSignPsbt.d.ts.map +1 -1
  85. package/dist/api/btc/BTCSignTransaction.d.ts +1 -0
  86. package/dist/api/btc/BTCSignTransaction.d.ts.map +1 -1
  87. package/dist/api/btc/BTCVerifyMessage.d.ts +1 -0
  88. package/dist/api/btc/BTCVerifyMessage.d.ts.map +1 -1
  89. package/dist/api/btc/helpers/versionLimit.d.ts +2 -0
  90. package/dist/api/btc/helpers/versionLimit.d.ts.map +1 -1
  91. package/dist/api/cardano/CardanoGetAddress.d.ts +1 -0
  92. package/dist/api/cardano/CardanoGetAddress.d.ts.map +1 -1
  93. package/dist/api/cardano/CardanoGetPublicKey.d.ts +1 -0
  94. package/dist/api/cardano/CardanoGetPublicKey.d.ts.map +1 -1
  95. package/dist/api/cardano/CardanoSignMessage.d.ts +1 -0
  96. package/dist/api/cardano/CardanoSignMessage.d.ts.map +1 -1
  97. package/dist/api/cardano/CardanoSignTransaction.d.ts +1 -0
  98. package/dist/api/cardano/CardanoSignTransaction.d.ts.map +1 -1
  99. package/dist/api/conflux/ConfluxGetAddress.d.ts +1 -0
  100. package/dist/api/conflux/ConfluxGetAddress.d.ts.map +1 -1
  101. package/dist/api/conflux/ConfluxSignMessage.d.ts +1 -0
  102. package/dist/api/conflux/ConfluxSignMessage.d.ts.map +1 -1
  103. package/dist/api/conflux/ConfluxSignMessageCIP23.d.ts +1 -0
  104. package/dist/api/conflux/ConfluxSignMessageCIP23.d.ts.map +1 -1
  105. package/dist/api/conflux/ConfluxSignTransaction.d.ts +1 -0
  106. package/dist/api/conflux/ConfluxSignTransaction.d.ts.map +1 -1
  107. package/dist/api/cosmos/CosmosGetAddress.d.ts +1 -0
  108. package/dist/api/cosmos/CosmosGetAddress.d.ts.map +1 -1
  109. package/dist/api/cosmos/CosmosGetPublicKey.d.ts +1 -0
  110. package/dist/api/cosmos/CosmosGetPublicKey.d.ts.map +1 -1
  111. package/dist/api/cosmos/CosmosSignTransaction.d.ts +1 -0
  112. package/dist/api/cosmos/CosmosSignTransaction.d.ts.map +1 -1
  113. package/dist/api/device/DeviceCancel.d.ts +1 -0
  114. package/dist/api/device/DeviceCancel.d.ts.map +1 -1
  115. package/dist/api/device/DeviceChangePin.d.ts +1 -0
  116. package/dist/api/device/DeviceChangePin.d.ts.map +1 -1
  117. package/dist/api/device/DeviceLock.d.ts +1 -0
  118. package/dist/api/device/DeviceLock.d.ts.map +1 -1
  119. package/dist/api/device/DeviceRebootToBoardloader.d.ts +1 -0
  120. package/dist/api/device/DeviceRebootToBoardloader.d.ts.map +1 -1
  121. package/dist/api/device/DeviceRebootToBootloader.d.ts +1 -0
  122. package/dist/api/device/DeviceRebootToBootloader.d.ts.map +1 -1
  123. package/dist/api/device/DeviceSettings.d.ts +1 -0
  124. package/dist/api/device/DeviceSettings.d.ts.map +1 -1
  125. package/dist/api/device/DeviceSupportFeatures.d.ts +1 -0
  126. package/dist/api/device/DeviceSupportFeatures.d.ts.map +1 -1
  127. package/dist/api/device/DeviceUnlock.d.ts +1 -0
  128. package/dist/api/device/DeviceUnlock.d.ts.map +1 -1
  129. package/dist/api/device/DeviceUpdateBootloader.d.ts +5 -1
  130. package/dist/api/device/DeviceUpdateBootloader.d.ts.map +1 -1
  131. package/dist/api/device/DeviceWipe.d.ts +1 -0
  132. package/dist/api/device/DeviceWipe.d.ts.map +1 -1
  133. package/dist/api/device/PreInitialize.d.ts +1 -0
  134. package/dist/api/device/PreInitialize.d.ts.map +1 -1
  135. package/dist/api/dynex/DnxGetAddress.d.ts.map +1 -1
  136. package/dist/api/dynex/DnxSignTransaction.d.ts.map +1 -1
  137. package/dist/api/evm/EVMGetAddress.d.ts +1 -0
  138. package/dist/api/evm/EVMGetAddress.d.ts.map +1 -1
  139. package/dist/api/evm/EVMGetPublicKey.d.ts +1 -0
  140. package/dist/api/evm/EVMGetPublicKey.d.ts.map +1 -1
  141. package/dist/api/evm/EVMSignMessage.d.ts +1 -0
  142. package/dist/api/evm/EVMSignMessage.d.ts.map +1 -1
  143. package/dist/api/evm/EVMSignMessageEIP712.d.ts.map +1 -1
  144. package/dist/api/evm/EVMSignTransaction.d.ts +1 -0
  145. package/dist/api/evm/EVMSignTransaction.d.ts.map +1 -1
  146. package/dist/api/evm/EVMSignTypedData.d.ts +1 -0
  147. package/dist/api/evm/EVMSignTypedData.d.ts.map +1 -1
  148. package/dist/api/evm/EVMVerifyMessage.d.ts +1 -0
  149. package/dist/api/evm/EVMVerifyMessage.d.ts.map +1 -1
  150. package/dist/api/filecoin/FilecoinGetAddress.d.ts +1 -0
  151. package/dist/api/filecoin/FilecoinGetAddress.d.ts.map +1 -1
  152. package/dist/api/filecoin/FilecoinSignTransaction.d.ts +1 -0
  153. package/dist/api/filecoin/FilecoinSignTransaction.d.ts.map +1 -1
  154. package/dist/api/firmware/FirmwareArtifactSource.d.ts +25 -0
  155. package/dist/api/firmware/FirmwareArtifactSource.d.ts.map +1 -0
  156. package/dist/api/firmware/FirmwareHostBinding.d.ts +6 -0
  157. package/dist/api/firmware/FirmwareHostBinding.d.ts.map +1 -0
  158. package/dist/api/firmware/FirmwareUpdateBaseMethod.d.ts +7 -0
  159. package/dist/api/firmware/FirmwareUpdateBaseMethod.d.ts.map +1 -1
  160. package/dist/api/firmware/FirmwareUpdateCapabilities.d.ts +3 -0
  161. package/dist/api/firmware/FirmwareUpdateCapabilities.d.ts.map +1 -0
  162. package/dist/api/firmware/FirmwareUpdatePlan.d.ts +23 -0
  163. package/dist/api/firmware/FirmwareUpdatePlan.d.ts.map +1 -0
  164. package/dist/api/firmware/FirmwareUpdatePreparedPlan.d.ts +30 -0
  165. package/dist/api/firmware/FirmwareUpdatePreparedPlan.d.ts.map +1 -0
  166. package/dist/api/firmware/getBinary.d.ts +7 -0
  167. package/dist/api/firmware/getBinary.d.ts.map +1 -1
  168. package/dist/api/firmware/updateBootloader.d.ts +2 -0
  169. package/dist/api/firmware/updateBootloader.d.ts.map +1 -1
  170. package/dist/api/firmware/uploadFirmware.d.ts +9 -1
  171. package/dist/api/firmware/uploadFirmware.d.ts.map +1 -1
  172. package/dist/api/kaspa/KaspaGetAddress.d.ts +1 -0
  173. package/dist/api/kaspa/KaspaGetAddress.d.ts.map +1 -1
  174. package/dist/api/kaspa/KaspaSignTransaction.d.ts +1 -0
  175. package/dist/api/kaspa/KaspaSignTransaction.d.ts.map +1 -1
  176. package/dist/api/kaspa/helpers/TransferSerialize.d.ts.map +1 -1
  177. package/dist/api/lightning/LnurlAuth.d.ts +0 -4
  178. package/dist/api/lightning/LnurlAuth.d.ts.map +1 -1
  179. package/dist/api/near/NearGetAddress.d.ts +1 -0
  180. package/dist/api/near/NearGetAddress.d.ts.map +1 -1
  181. package/dist/api/near/NearSignTransaction.d.ts +1 -0
  182. package/dist/api/near/NearSignTransaction.d.ts.map +1 -1
  183. package/dist/api/nem/NEMGetAddress.d.ts +1 -0
  184. package/dist/api/nem/NEMGetAddress.d.ts.map +1 -1
  185. package/dist/api/nem/NEMSignTransaction.d.ts +1 -0
  186. package/dist/api/nem/NEMSignTransaction.d.ts.map +1 -1
  187. package/dist/api/neo/NeoGetAddress.d.ts.map +1 -1
  188. package/dist/api/neo/NeoSignTransaction.d.ts.map +1 -1
  189. package/dist/api/nervos/NervosGetAddress.d.ts.map +1 -1
  190. package/dist/api/nervos/NervosSignTransaction.d.ts.map +1 -1
  191. package/dist/api/nexa/NexaGetAddress.d.ts.map +1 -1
  192. package/dist/api/nexa/NexaSignTransaction.d.ts.map +1 -1
  193. package/dist/api/nostr/NostrDecryptMessage.d.ts +1 -0
  194. package/dist/api/nostr/NostrDecryptMessage.d.ts.map +1 -1
  195. package/dist/api/nostr/NostrEncryptMessage.d.ts +1 -0
  196. package/dist/api/nostr/NostrEncryptMessage.d.ts.map +1 -1
  197. package/dist/api/nostr/NostrGetPublicKey.d.ts +1 -0
  198. package/dist/api/nostr/NostrGetPublicKey.d.ts.map +1 -1
  199. package/dist/api/nostr/NostrSignEvent.d.ts +1 -0
  200. package/dist/api/nostr/NostrSignEvent.d.ts.map +1 -1
  201. package/dist/api/nostr/NostrSignSchnorr.d.ts +1 -0
  202. package/dist/api/nostr/NostrSignSchnorr.d.ts.map +1 -1
  203. package/dist/api/polkadot/PolkadotGetAddress.d.ts +1 -0
  204. package/dist/api/polkadot/PolkadotGetAddress.d.ts.map +1 -1
  205. package/dist/api/polkadot/PolkadotSignTransaction.d.ts +1 -0
  206. package/dist/api/polkadot/PolkadotSignTransaction.d.ts.map +1 -1
  207. package/dist/api/protocol-v2/DeviceFactoryInfoGet.d.ts +1 -0
  208. package/dist/api/protocol-v2/DeviceFactoryInfoGet.d.ts.map +1 -1
  209. package/dist/api/protocol-v2/DeviceFactoryInfoSet.d.ts +1 -0
  210. package/dist/api/protocol-v2/DeviceFactoryInfoSet.d.ts.map +1 -1
  211. package/dist/api/protocol-v2/DeviceFirmwareUpdate.d.ts +1 -0
  212. package/dist/api/protocol-v2/DeviceFirmwareUpdate.d.ts.map +1 -1
  213. package/dist/api/protocol-v2/DeviceGetFirmwareUpdateStatus.d.ts +1 -0
  214. package/dist/api/protocol-v2/DeviceGetFirmwareUpdateStatus.d.ts.map +1 -1
  215. package/dist/api/protocol-v2/DeviceGetOnboardingStatus.d.ts +1 -0
  216. package/dist/api/protocol-v2/DeviceGetOnboardingStatus.d.ts.map +1 -1
  217. package/dist/api/protocol-v2/DeviceInfoGet.d.ts +1 -0
  218. package/dist/api/protocol-v2/DeviceInfoGet.d.ts.map +1 -1
  219. package/dist/api/protocol-v2/DeviceReboot.d.ts +1 -0
  220. package/dist/api/protocol-v2/DeviceReboot.d.ts.map +1 -1
  221. package/dist/api/protocol-v2/DeviceStatusGet.d.ts +1 -0
  222. package/dist/api/protocol-v2/DeviceStatusGet.d.ts.map +1 -1
  223. package/dist/api/protocol-v2/DeviceUploadWallpaper.d.ts +1 -0
  224. package/dist/api/protocol-v2/DeviceUploadWallpaper.d.ts.map +1 -1
  225. package/dist/api/protocol-v2/FilesystemFormat.d.ts +1 -0
  226. package/dist/api/protocol-v2/FilesystemFormat.d.ts.map +1 -1
  227. package/dist/api/protocol-v2/FilesystemPermissionFix.d.ts +1 -0
  228. package/dist/api/protocol-v2/FilesystemPermissionFix.d.ts.map +1 -1
  229. package/dist/api/protocol-v2/Ping.d.ts +1 -0
  230. package/dist/api/protocol-v2/Ping.d.ts.map +1 -1
  231. package/dist/api/protocol-v2/ProtocolInfoRequest.d.ts +1 -0
  232. package/dist/api/protocol-v2/ProtocolInfoRequest.d.ts.map +1 -1
  233. package/dist/api/scdo/ScdoGetAddress.d.ts.map +1 -1
  234. package/dist/api/scdo/ScdoSignMessage.d.ts.map +1 -1
  235. package/dist/api/scdo/ScdoSignTransaction.d.ts.map +1 -1
  236. package/dist/api/solana/SolGetAddress.d.ts +1 -0
  237. package/dist/api/solana/SolGetAddress.d.ts.map +1 -1
  238. package/dist/api/solana/SolSignMessage.d.ts +1 -0
  239. package/dist/api/solana/SolSignMessage.d.ts.map +1 -1
  240. package/dist/api/solana/SolSignOffchainMessage.d.ts +1 -0
  241. package/dist/api/solana/SolSignOffchainMessage.d.ts.map +1 -1
  242. package/dist/api/solana/SolSignTransaction.d.ts +1 -0
  243. package/dist/api/solana/SolSignTransaction.d.ts.map +1 -1
  244. package/dist/api/starcoin/StarcoinGetAddress.d.ts +1 -0
  245. package/dist/api/starcoin/StarcoinGetAddress.d.ts.map +1 -1
  246. package/dist/api/starcoin/StarcoinGetPublicKey.d.ts +1 -0
  247. package/dist/api/starcoin/StarcoinGetPublicKey.d.ts.map +1 -1
  248. package/dist/api/starcoin/StarcoinSignMessage.d.ts +1 -0
  249. package/dist/api/starcoin/StarcoinSignMessage.d.ts.map +1 -1
  250. package/dist/api/starcoin/StarcoinSignTransaction.d.ts +1 -0
  251. package/dist/api/starcoin/StarcoinSignTransaction.d.ts.map +1 -1
  252. package/dist/api/starcoin/StarcoinVerifyMessage.d.ts +1 -0
  253. package/dist/api/starcoin/StarcoinVerifyMessage.d.ts.map +1 -1
  254. package/dist/api/stellar/StellarGetAddress.d.ts +1 -2
  255. package/dist/api/stellar/StellarGetAddress.d.ts.map +1 -1
  256. package/dist/api/stellar/StellarSignTransaction.d.ts +2 -3
  257. package/dist/api/stellar/StellarSignTransaction.d.ts.map +1 -1
  258. package/dist/api/sui/SuiGetAddress.d.ts +1 -0
  259. package/dist/api/sui/SuiGetAddress.d.ts.map +1 -1
  260. package/dist/api/sui/SuiGetPublicKey.d.ts +1 -0
  261. package/dist/api/sui/SuiGetPublicKey.d.ts.map +1 -1
  262. package/dist/api/sui/SuiSignMessage.d.ts +1 -0
  263. package/dist/api/sui/SuiSignMessage.d.ts.map +1 -1
  264. package/dist/api/sui/SuiSignTransaction.d.ts +1 -0
  265. package/dist/api/sui/SuiSignTransaction.d.ts.map +1 -1
  266. package/dist/api/ton/TonGetAddress.d.ts +1 -0
  267. package/dist/api/ton/TonGetAddress.d.ts.map +1 -1
  268. package/dist/api/ton/TonSignData.d.ts +1 -0
  269. package/dist/api/ton/TonSignData.d.ts.map +1 -1
  270. package/dist/api/ton/TonSignMessage.d.ts +1 -0
  271. package/dist/api/ton/TonSignMessage.d.ts.map +1 -1
  272. package/dist/api/ton/TonSignProof.d.ts +1 -0
  273. package/dist/api/ton/TonSignProof.d.ts.map +1 -1
  274. package/dist/api/tron/TronGetAddress.d.ts +1 -0
  275. package/dist/api/tron/TronGetAddress.d.ts.map +1 -1
  276. package/dist/api/tron/TronSignMessage.d.ts +5 -0
  277. package/dist/api/tron/TronSignMessage.d.ts.map +1 -1
  278. package/dist/api/tron/TronSignTransaction.d.ts +1 -0
  279. package/dist/api/tron/TronSignTransaction.d.ts.map +1 -1
  280. package/dist/api/xrp/XrpGetAddress.d.ts +1 -0
  281. package/dist/api/xrp/XrpGetAddress.d.ts.map +1 -1
  282. package/dist/api/xrp/XrpSignTransaction.d.ts +1 -0
  283. package/dist/api/xrp/XrpSignTransaction.d.ts.map +1 -1
  284. package/dist/core/index.d.ts.map +1 -1
  285. package/dist/data-manager/DataManager.d.ts +1 -0
  286. package/dist/data-manager/DataManager.d.ts.map +1 -1
  287. package/dist/data-manager/connectSettings.d.ts.map +1 -1
  288. package/dist/device/Device.d.ts +3 -1
  289. package/dist/device/Device.d.ts.map +1 -1
  290. package/dist/index.d.ts +271 -87
  291. package/dist/index.d.ts.map +1 -1
  292. package/dist/index.js +2864 -893
  293. package/dist/inject.d.ts.map +1 -1
  294. package/dist/lowLevelInject.d.ts.map +1 -1
  295. package/dist/protocols/protocol-v2/unlockRetry.d.ts.map +1 -1
  296. package/dist/topLevelInject.d.ts.map +1 -1
  297. package/dist/types/api/checkAllFirmwareRelease.d.ts +3 -0
  298. package/dist/types/api/checkAllFirmwareRelease.d.ts.map +1 -1
  299. package/dist/types/api/deviceUpdateBootloader.d.ts +6 -0
  300. package/dist/types/api/deviceUpdateBootloader.d.ts.map +1 -1
  301. package/dist/types/api/export.d.ts +5 -2
  302. package/dist/types/api/export.d.ts.map +1 -1
  303. package/dist/types/api/firmwareUpdate.d.ts +69 -0
  304. package/dist/types/api/firmwareUpdate.d.ts.map +1 -1
  305. package/dist/types/api/firmwareUpdateCapabilities.d.ts +9 -0
  306. package/dist/types/api/firmwareUpdateCapabilities.d.ts.map +1 -0
  307. package/dist/types/api/firmwareUpdatePlan.d.ts +27 -0
  308. package/dist/types/api/firmwareUpdatePlan.d.ts.map +1 -0
  309. package/dist/types/api/firmwareUpdatePreparedPlan.d.ts +42 -0
  310. package/dist/types/api/firmwareUpdatePreparedPlan.d.ts.map +1 -0
  311. package/dist/types/api/index.d.ts +9 -1
  312. package/dist/types/api/index.d.ts.map +1 -1
  313. package/dist/types/api/kaspaSignTransaction.d.ts +15 -2
  314. package/dist/types/api/kaspaSignTransaction.d.ts.map +1 -1
  315. package/dist/types/device.d.ts +0 -1
  316. package/dist/types/device.d.ts.map +1 -1
  317. package/dist/types/settings.d.ts +13 -0
  318. package/dist/types/settings.d.ts.map +1 -1
  319. package/dist/utils/deviceInfoUtils.d.ts +0 -1
  320. package/dist/utils/deviceInfoUtils.d.ts.map +1 -1
  321. package/dist/utils/deviceVersionUtils.d.ts +1 -0
  322. package/dist/utils/deviceVersionUtils.d.ts.map +1 -1
  323. package/dist/utils/index.d.ts +1 -1
  324. package/dist/utils/index.d.ts.map +1 -1
  325. package/package.json +4 -4
  326. package/src/api/BaseMethod.ts +21 -18
  327. package/src/api/CheckAllFirmwareRelease.ts +44 -4
  328. package/src/api/CipherKeyValue.ts +4 -0
  329. package/src/api/DirList.ts +4 -1
  330. package/src/api/DirMake.ts +4 -1
  331. package/src/api/DirRemove.ts +4 -1
  332. package/src/api/FileDelete.ts +4 -1
  333. package/src/api/FileRead.ts +4 -1
  334. package/src/api/FileWrite.ts +4 -1
  335. package/src/api/FirmwareUpdate.ts +0 -8
  336. package/src/api/FirmwareUpdateV2.ts +292 -120
  337. package/src/api/FirmwareUpdateV3.ts +256 -61
  338. package/src/api/FirmwareUpdateV4.ts +767 -289
  339. package/src/api/GetDeviceState.ts +4 -0
  340. package/src/api/GetFeatures.ts +1 -4
  341. package/src/api/GetOnekeyFeatures.ts +0 -5
  342. package/src/api/GetPassphraseState.ts +4 -0
  343. package/src/api/OpenWalletSession.ts +4 -0
  344. package/src/api/PathInfo.ts +4 -1
  345. package/src/api/UploadPortfolio.ts +1 -1
  346. package/src/api/alephium/AlephiumGetAddress.ts +0 -4
  347. package/src/api/alephium/AlephiumSignMessage.ts +0 -4
  348. package/src/api/alephium/AlephiumSignTransaction.ts +0 -4
  349. package/src/api/algo/AlgoGetAddress.ts +4 -0
  350. package/src/api/algo/AlgoSignTransaction.ts +4 -0
  351. package/src/api/allnetwork/AllNetworkGetAddressBase.ts +5 -13
  352. package/src/api/aptos/AptosGetAddress.ts +4 -0
  353. package/src/api/aptos/AptosGetPublicKey.ts +4 -0
  354. package/src/api/aptos/AptosSignInMessage.ts +4 -0
  355. package/src/api/aptos/AptosSignMessage.ts +4 -0
  356. package/src/api/aptos/AptosSignTransaction.ts +4 -0
  357. package/src/api/benfen/BenfenGetAddress.ts +11 -7
  358. package/src/api/benfen/BenfenGetPublicKey.ts +0 -4
  359. package/src/api/benfen/BenfenSignMessage.ts +0 -4
  360. package/src/api/benfen/BenfenSignTransaction.ts +0 -4
  361. package/src/api/btc/BTCGetAddress.ts +8 -1
  362. package/src/api/btc/BTCGetPublicKey.ts +8 -1
  363. package/src/api/btc/BTCSignMessage.ts +8 -1
  364. package/src/api/btc/BTCSignPsbt.ts +4 -0
  365. package/src/api/btc/BTCSignTransaction.ts +8 -1
  366. package/src/api/btc/BTCVerifyMessage.ts +8 -1
  367. package/src/api/btc/helpers/versionLimit.ts +7 -4
  368. package/src/api/cardano/CardanoGetAddress.ts +4 -0
  369. package/src/api/cardano/CardanoGetPublicKey.ts +4 -0
  370. package/src/api/cardano/CardanoSignMessage.ts +4 -0
  371. package/src/api/cardano/CardanoSignTransaction.ts +4 -0
  372. package/src/api/conflux/ConfluxGetAddress.ts +4 -0
  373. package/src/api/conflux/ConfluxSignMessage.ts +4 -0
  374. package/src/api/conflux/ConfluxSignMessageCIP23.ts +4 -0
  375. package/src/api/conflux/ConfluxSignTransaction.ts +6 -5
  376. package/src/api/cosmos/CosmosGetAddress.ts +4 -0
  377. package/src/api/cosmos/CosmosGetPublicKey.ts +4 -0
  378. package/src/api/cosmos/CosmosSignTransaction.ts +4 -0
  379. package/src/api/device/DeviceCancel.ts +4 -0
  380. package/src/api/device/DeviceChangePin.ts +4 -0
  381. package/src/api/device/DeviceLock.ts +4 -0
  382. package/src/api/device/DeviceRebootToBoardloader.ts +4 -0
  383. package/src/api/device/DeviceRebootToBootloader.ts +4 -0
  384. package/src/api/device/DeviceSettings.ts +4 -0
  385. package/src/api/device/DeviceSupportFeatures.ts +4 -0
  386. package/src/api/device/DeviceUnlock.ts +4 -0
  387. package/src/api/device/DeviceUpdateBootloader.ts +122 -6
  388. package/src/api/device/DeviceWipe.ts +4 -0
  389. package/src/api/device/PreInitialize.ts +4 -0
  390. package/src/api/dynex/DnxGetAddress.ts +0 -6
  391. package/src/api/dynex/DnxSignTransaction.ts +0 -6
  392. package/src/api/evm/EVMGetAddress.ts +4 -0
  393. package/src/api/evm/EVMGetPublicKey.ts +4 -0
  394. package/src/api/evm/EVMSignMessage.ts +4 -0
  395. package/src/api/evm/EVMSignMessageEIP712.ts +1 -11
  396. package/src/api/evm/EVMSignTransaction.ts +4 -0
  397. package/src/api/evm/EVMSignTypedData.ts +4 -0
  398. package/src/api/evm/EVMVerifyMessage.ts +4 -0
  399. package/src/api/filecoin/FilecoinGetAddress.ts +4 -0
  400. package/src/api/filecoin/FilecoinSignTransaction.ts +4 -0
  401. package/src/api/firmware/FirmwareArtifactSource.ts +278 -0
  402. package/src/api/firmware/FirmwareHostBinding.ts +100 -0
  403. package/src/api/firmware/FirmwareUpdateBaseMethod.ts +50 -0
  404. package/src/api/firmware/FirmwareUpdateCapabilities.ts +9 -0
  405. package/src/api/firmware/FirmwareUpdatePlan.ts +628 -0
  406. package/src/api/firmware/FirmwareUpdatePreparedPlan.ts +392 -0
  407. package/src/api/firmware/updateBootloader.ts +19 -4
  408. package/src/api/firmware/uploadFirmware.ts +140 -22
  409. package/src/api/kaspa/KaspaGetAddress.ts +4 -0
  410. package/src/api/kaspa/KaspaSignTransaction.ts +37 -15
  411. package/src/api/kaspa/helpers/TransferSerialize.ts +3 -7
  412. package/src/api/lightning/LnurlAuth.ts +0 -4
  413. package/src/api/near/NearGetAddress.ts +4 -0
  414. package/src/api/near/NearSignTransaction.ts +4 -0
  415. package/src/api/nem/NEMGetAddress.ts +4 -0
  416. package/src/api/nem/NEMSignTransaction.ts +4 -0
  417. package/src/api/neo/NeoGetAddress.ts +0 -4
  418. package/src/api/neo/NeoSignTransaction.ts +0 -4
  419. package/src/api/nervos/NervosGetAddress.ts +0 -4
  420. package/src/api/nervos/NervosSignTransaction.ts +0 -4
  421. package/src/api/nexa/NexaGetAddress.ts +0 -4
  422. package/src/api/nexa/NexaSignTransaction.ts +0 -4
  423. package/src/api/nostr/NostrDecryptMessage.ts +4 -0
  424. package/src/api/nostr/NostrEncryptMessage.ts +4 -0
  425. package/src/api/nostr/NostrGetPublicKey.ts +4 -0
  426. package/src/api/nostr/NostrSignEvent.ts +4 -0
  427. package/src/api/nostr/NostrSignSchnorr.ts +4 -0
  428. package/src/api/polkadot/PolkadotGetAddress.ts +4 -0
  429. package/src/api/polkadot/PolkadotSignTransaction.ts +4 -0
  430. package/src/api/protocol-v2/DeviceFactoryInfoGet.ts +4 -1
  431. package/src/api/protocol-v2/DeviceFactoryInfoSet.ts +4 -1
  432. package/src/api/protocol-v2/DeviceFirmwareUpdate.ts +4 -1
  433. package/src/api/protocol-v2/DeviceGetFirmwareUpdateStatus.ts +4 -1
  434. package/src/api/protocol-v2/DeviceGetOnboardingStatus.ts +4 -1
  435. package/src/api/protocol-v2/DeviceInfoGet.ts +4 -8
  436. package/src/api/protocol-v2/DeviceReboot.ts +4 -2
  437. package/src/api/protocol-v2/DeviceStatusGet.ts +4 -1
  438. package/src/api/protocol-v2/DeviceUploadWallpaper.ts +4 -1
  439. package/src/api/protocol-v2/FilesystemFormat.ts +4 -1
  440. package/src/api/protocol-v2/FilesystemPermissionFix.ts +4 -1
  441. package/src/api/protocol-v2/Ping.ts +4 -1
  442. package/src/api/protocol-v2/ProtocolInfoRequest.ts +4 -1
  443. package/src/api/scdo/ScdoGetAddress.ts +0 -4
  444. package/src/api/scdo/ScdoSignMessage.ts +0 -4
  445. package/src/api/scdo/ScdoSignTransaction.ts +0 -4
  446. package/src/api/solana/SolGetAddress.ts +4 -0
  447. package/src/api/solana/SolSignMessage.ts +4 -0
  448. package/src/api/solana/SolSignOffchainMessage.ts +4 -0
  449. package/src/api/solana/SolSignTransaction.ts +4 -0
  450. package/src/api/starcoin/StarcoinGetAddress.ts +4 -0
  451. package/src/api/starcoin/StarcoinGetPublicKey.ts +4 -0
  452. package/src/api/starcoin/StarcoinSignMessage.ts +4 -0
  453. package/src/api/starcoin/StarcoinSignTransaction.ts +4 -0
  454. package/src/api/starcoin/StarcoinVerifyMessage.ts +4 -0
  455. package/src/api/stellar/StellarGetAddress.ts +1 -10
  456. package/src/api/stellar/StellarSignTransaction.ts +1 -14
  457. package/src/api/sui/SuiGetAddress.ts +4 -0
  458. package/src/api/sui/SuiGetPublicKey.ts +4 -0
  459. package/src/api/sui/SuiSignMessage.ts +4 -0
  460. package/src/api/sui/SuiSignTransaction.ts +4 -0
  461. package/src/api/ton/TonGetAddress.ts +4 -0
  462. package/src/api/ton/TonSignData.ts +5 -1
  463. package/src/api/ton/TonSignMessage.ts +4 -0
  464. package/src/api/ton/TonSignProof.ts +4 -0
  465. package/src/api/tron/TronGetAddress.ts +4 -0
  466. package/src/api/tron/TronSignMessage.ts +18 -7
  467. package/src/api/tron/TronSignTransaction.ts +4 -0
  468. package/src/api/xrp/XrpGetAddress.ts +4 -0
  469. package/src/api/xrp/XrpSignTransaction.ts +5 -1
  470. package/src/core/index.ts +4 -17
  471. package/src/data-manager/DataManager.ts +33 -33
  472. package/src/data-manager/connectSettings.ts +11 -0
  473. package/src/device/Device.ts +53 -53
  474. package/src/index.ts +5 -0
  475. package/src/inject.ts +22 -2
  476. package/src/lowLevelInject.ts +5 -1
  477. package/src/protocols/protocol-v2/unlockRetry.ts +18 -11
  478. package/src/topLevelInject.ts +5 -1
  479. package/src/types/api/checkAllFirmwareRelease.ts +3 -0
  480. package/src/types/api/deviceUpdateBootloader.ts +6 -0
  481. package/src/types/api/export.ts +20 -0
  482. package/src/types/api/firmwareUpdate.ts +76 -0
  483. package/src/types/api/firmwareUpdateCapabilities.ts +9 -0
  484. package/src/types/api/firmwareUpdatePlan.ts +36 -0
  485. package/src/types/api/firmwareUpdatePreparedPlan.ts +53 -0
  486. package/src/types/api/index.ts +14 -0
  487. package/src/types/api/kaspaSignTransaction.ts +20 -2
  488. package/src/types/device.ts +0 -1
  489. package/src/types/settings.ts +13 -0
  490. package/src/utils/deviceInfoUtils.ts +0 -3
  491. package/src/utils/deviceVersionUtils.ts +1 -1
  492. package/src/utils/index.ts +0 -1
  493. package/tsconfig.type-tests.json +8 -0
@@ -1,4 +1,4 @@
1
- import { HardwareErrorCode } from '@onekeyfe/hd-shared';
1
+ import { EFirmwareType, HardwareErrorCode } from '@onekeyfe/hd-shared';
2
2
  import { DeviceRebootType, DeviceSessionPinType, DeviceSettingsPage } from '@onekeyfe/hd-transport';
3
3
 
4
4
  import * as firmwareBinaryApi from '../src/api/firmware/getBinary';
@@ -50,7 +50,7 @@ import TonSignProof from '../src/api/ton/TonSignProof';
50
50
  import TronGetAddress from '../src/api/tron/TronGetAddress';
51
51
  import StellarGetAddress from '../src/api/stellar/StellarGetAddress';
52
52
  import BenfenSignMessage from '../src/api/benfen/BenfenSignMessage';
53
- import { getBitcoinForkVersionRange } from '../src/api/btc/helpers/versionLimit';
53
+ import { getBitcoinForkSupportedProtocols } from '../src/api/btc/helpers/versionLimit';
54
54
  import { DataManager } from '../src/data-manager';
55
55
  import { createCoreApi } from '../src/inject';
56
56
  import { Device, preloadSessionCache } from '../src/device/Device';
@@ -80,9 +80,9 @@ import {
80
80
  getFirmwareUpdateField,
81
81
  getFirmwareUpdateFieldArray,
82
82
  getMethodVersionRange,
83
- isMethodVersionRangeUnsupported,
84
83
  } from '../src/utils';
85
84
  import { getDeviceFirmwareVersion } from '../src/utils/deviceVersionUtils';
85
+ import { openFirmwareByteSource } from '../src/api/firmware/FirmwareArtifactSource';
86
86
  import {
87
87
  getPassphraseState,
88
88
  getPassphraseStateWithRefreshDeviceInfo,
@@ -129,7 +129,7 @@ describe('DeviceUploadWallpaper', () => {
129
129
  method.init();
130
130
  const result = await method.run();
131
131
 
132
- expect(method.requireProtocolV2).toBe(true);
132
+ expect(method.getSupportedProtocols()).toEqual(['V2']);
133
133
  expect(method.unlockPolicy).toBe('unlock-before-run');
134
134
  expect(typedCall).toHaveBeenNthCalledWith(1, 'FilesystemDirMake', 'Success', {
135
135
  path: 'vol1:/wallpapers',
@@ -200,6 +200,42 @@ describe('DeviceUploadWallpaper', () => {
200
200
  });
201
201
 
202
202
  describe('UploadPortfolio', () => {
203
+ test('writes and applies the portfolio while the device is locked without unlocking', async () => {
204
+ const packageBytes = new Uint8Array([1, 2, 3]);
205
+ const typedCall = jest
206
+ .fn()
207
+ .mockResolvedValueOnce({ message: { processed_byte: 3 } })
208
+ .mockResolvedValueOnce({ message: { message: 'Portfolio updated' } });
209
+ const unlockDevice = jest.fn().mockResolvedValue(undefined);
210
+ const device = stubDevice({
211
+ features: { unlocked: false },
212
+ commands: { typedCall },
213
+ isProtocolV2: () => true,
214
+ unlockDevice,
215
+ });
216
+ const method = new UploadPortfolio({
217
+ id: 1,
218
+ payload: {
219
+ method: 'uploadPortfolio',
220
+ packageBytes,
221
+ },
222
+ });
223
+ (method as any).device = device;
224
+
225
+ method.init();
226
+ await runMethodWithUnlockRetry(method, device as any);
227
+
228
+ expect(unlockDevice).not.toHaveBeenCalled();
229
+ expect(typedCall).toHaveBeenNthCalledWith(
230
+ 1,
231
+ 'FilesystemFileWrite',
232
+ 'FilesystemFile',
233
+ expect.any(Object),
234
+ { timeoutMs: undefined }
235
+ );
236
+ expect(typedCall).toHaveBeenNthCalledWith(2, 'PortfolioUpdate', 'Success', {});
237
+ });
238
+
203
239
  test('stages the complete package before applying PortfolioUpdate', async () => {
204
240
  const packageBytes = new Uint8Array([1, 2, 3]);
205
241
  const typedCall = jest
@@ -219,7 +255,7 @@ describe('UploadPortfolio', () => {
219
255
  method.init();
220
256
  const result = await method.run();
221
257
 
222
- expect(method.unlockPolicy).toBe('unlock-before-run');
258
+ expect(method.unlockPolicy).toBe('none');
223
259
  expect(method.protocolV2UiMode).toBe('none');
224
260
  expect(method.protocolV2UiInteraction).toBeUndefined();
225
261
  expect(method.payload.emitProgress).toBe(false);
@@ -971,7 +1007,7 @@ describe('Protocol V2 feature adapter', () => {
971
1007
  wallet_initialized: false,
972
1008
  });
973
1009
  expect(typedCall).toHaveBeenCalledWith('DevGetOnboardingStatus', 'DevOnboardingStatus', {});
974
- expect(method.requireProtocolV2).toBe(true);
1010
+ expect(method.getSupportedProtocols()).toEqual(['V2']);
975
1011
  });
976
1012
 
977
1013
  test('routes onboarding without exposing the raw session command through CoreApi', async () => {
@@ -1957,13 +1993,6 @@ describe('Protocol V2 feature adapter', () => {
1957
1993
  });
1958
1994
 
1959
1995
  test('marks known unsupported public-chain methods as unsupported on Protocol V2', () => {
1960
- const features = normalizeProtocolV2Features({ ...descriptor, protocolType: 'V2' } as any, {
1961
- fw: {
1962
- application: {
1963
- version: '9.9.9',
1964
- },
1965
- },
1966
- });
1967
1996
  const stellar = new StellarGetAddress({
1968
1997
  id: 1,
1969
1998
  payload: {
@@ -1992,21 +2021,10 @@ describe('Protocol V2 feature adapter', () => {
1992
2021
  benfen.init();
1993
2022
  lnurlAuth.init();
1994
2023
 
1995
- const stellarRange = getMethodVersionRange(features, type => stellar.getVersionRange()[type]);
1996
- const benfenRange = getMethodVersionRange(features, type => benfen.getVersionRange()[type]);
1997
- const lnurlAuthRange = getMethodVersionRange(
1998
- features,
1999
- type => lnurlAuth.getVersionRange()[type]
2000
- );
2001
- const neuraiRange = getMethodVersionRange(
2002
- features,
2003
- type => getBitcoinForkVersionRange(['Neurai'])[type]
2004
- );
2005
-
2006
- expect(isMethodVersionRangeUnsupported(stellarRange)).toBe(true);
2007
- expect(isMethodVersionRangeUnsupported(benfenRange)).toBe(true);
2008
- expect(isMethodVersionRangeUnsupported(lnurlAuthRange)).toBe(true);
2009
- expect(isMethodVersionRangeUnsupported(neuraiRange)).toBe(true);
2024
+ expect(stellar.supportsProtocol('V2')).toBe(false);
2025
+ expect(benfen.supportsProtocol('V2')).toBe(false);
2026
+ expect(lnurlAuth.supportsProtocol('V2')).toBe(false);
2027
+ expect(getBitcoinForkSupportedProtocols(['Neurai'])).toEqual(['V1']);
2010
2028
  });
2011
2029
 
2012
2030
  test('does not block batch public key support checks on Protocol V2', async () => {
@@ -2045,7 +2063,7 @@ describe('Protocol V2 feature adapter', () => {
2045
2063
  });
2046
2064
  });
2047
2065
 
2048
- test('rejects legacy getOnekeyFeatures for Protocol V2 devices', async () => {
2066
+ test('declares legacy getOnekeyFeatures unsupported on Protocol V2', () => {
2049
2067
  const method = new GetOnekeyFeatures({
2050
2068
  id: 1,
2051
2069
  payload: {
@@ -2059,9 +2077,9 @@ describe('Protocol V2 feature adapter', () => {
2059
2077
  commands: { typedCall },
2060
2078
  });
2061
2079
 
2062
- await expect(method.run()).rejects.toMatchObject({
2063
- errorCode: expect.any(Number),
2064
- });
2080
+ expect(() => method.assertProtocolSupported('V2', EFirmwareType.Universal)).toThrow(
2081
+ expect.objectContaining({ errorCode: HardwareErrorCode.DeviceNotSupportMethod })
2082
+ );
2065
2083
  expect(typedCall).not.toHaveBeenCalled();
2066
2084
  });
2067
2085
 
@@ -2594,16 +2612,8 @@ describe('API compatibility handling', () => {
2594
2612
 
2595
2613
  polkadotGetAddressMethod.init();
2596
2614
 
2597
- expect(
2598
- isMethodVersionRangeUnsupported(
2599
- getMethodVersionRange(features, type => tronMethod.getVersionRange()[type])
2600
- )
2601
- ).toBe(false);
2602
- expect(
2603
- isMethodVersionRangeUnsupported(
2604
- getMethodVersionRange(features, type => solMethod.getVersionRange()[type])
2605
- )
2606
- ).toBe(false);
2615
+ expect(tronMethod.supportsProtocol('V2')).toBe(true);
2616
+ expect(solMethod.supportsProtocol('V2')).toBe(true);
2607
2617
  expect(
2608
2618
  getMethodVersionRange(features, type => tonGetAddressMethod.getVersionRange()[type])
2609
2619
  ).toEqual({
@@ -2759,7 +2769,7 @@ describe('API compatibility handling', () => {
2759
2769
  expect(params.data_initial_chunk).toHaveLength(2048);
2760
2770
  });
2761
2771
 
2762
- test('returns a typed unsupported error for Dynex signing on Protocol V2', async () => {
2772
+ test('declares Dynex signing unsupported on Protocol V2', () => {
2763
2773
  const method = new DnxSignTransaction({
2764
2774
  id: 1,
2765
2775
  payload: {
@@ -2781,17 +2791,14 @@ describe('API compatibility handling', () => {
2781
2791
  });
2782
2792
 
2783
2793
  method.init();
2784
- (method as any).device = stubDevice({
2785
- originalDescriptor: { protocolType: 'V2' },
2786
- features: normalizeProtocolV2Features({ ...descriptor, protocolType: 'V2' } as any),
2787
- });
2788
-
2789
- await expect(method.run()).rejects.toMatchObject({
2790
- errorCode: HardwareErrorCode.DeviceNotSupportMethod,
2791
- });
2794
+ expect(() => method.assertProtocolSupported('V2', EFirmwareType.Universal)).toThrow(
2795
+ expect.objectContaining({
2796
+ errorCode: HardwareErrorCode.DeviceNotSupportMethod,
2797
+ })
2798
+ );
2792
2799
  });
2793
2800
 
2794
- test('returns a typed unsupported error for Dynex address on Protocol V2', async () => {
2801
+ test('declares Dynex address unsupported on Protocol V2', () => {
2795
2802
  const method = new DnxGetAddress({
2796
2803
  id: 1,
2797
2804
  payload: {
@@ -2802,14 +2809,11 @@ describe('API compatibility handling', () => {
2802
2809
  });
2803
2810
 
2804
2811
  method.init();
2805
- (method as any).device = stubDevice({
2806
- originalDescriptor: { protocolType: 'V2' },
2807
- features: normalizeProtocolV2Features({ ...descriptor, protocolType: 'V2' } as any),
2808
- });
2809
-
2810
- await expect(method.run()).rejects.toMatchObject({
2811
- errorCode: HardwareErrorCode.DeviceNotSupportMethod,
2812
- });
2812
+ expect(() => method.assertProtocolSupported('V2', EFirmwareType.Universal)).toThrow(
2813
+ expect.objectContaining({
2814
+ errorCode: HardwareErrorCode.DeviceNotSupportMethod,
2815
+ })
2816
+ );
2813
2817
  });
2814
2818
  });
2815
2819
 
@@ -2848,18 +2852,16 @@ describe('Protocol V2 firmware update targets', () => {
2848
2852
  return header;
2849
2853
  };
2850
2854
 
2851
- test('keeps Protocol V2 firmware updates off the firmwareUpdateV3 path', async () => {
2855
+ test('keeps Protocol V2 firmware updates off the firmwareUpdateV3 path', () => {
2852
2856
  const method = new FirmwareUpdateV3({
2853
2857
  id: 1,
2854
2858
  payload: {
2855
2859
  method: 'firmwareUpdateV3',
2856
2860
  },
2857
2861
  });
2858
- (method as any).device = stubDevice({
2859
- originalDescriptor: { protocolType: 'V2' },
2860
- });
2861
-
2862
- await expect(method.run()).rejects.toThrow('firmwareUpdateV4');
2862
+ expect(() => method.assertProtocolSupported('V2', EFirmwareType.Universal)).toThrow(
2863
+ expect.objectContaining({ errorCode: HardwareErrorCode.DeviceNotSupportMethod })
2864
+ );
2863
2865
  });
2864
2866
 
2865
2867
  test('uses Protocol V2 features after BLE final reconnect without V1 Initialize', async () => {
@@ -2946,7 +2948,7 @@ describe('Protocol V2 firmware update targets', () => {
2946
2948
  });
2947
2949
  });
2948
2950
 
2949
- test('enters Protocol V2 bootloader before upload', async () => {
2951
+ test('delegates Protocol V2 mode transition to the phase executor', async () => {
2950
2952
  const method = new FirmwareUpdateV4({
2951
2953
  id: 1,
2952
2954
  payload: {
@@ -2981,7 +2983,7 @@ describe('Protocol V2 firmware update targets', () => {
2981
2983
 
2982
2984
  await method.run();
2983
2985
 
2984
- expect((method as any).enterProtocolV2BootloaderMode).toHaveBeenCalledTimes(1);
2986
+ expect((method as any).enterProtocolV2BootloaderMode).not.toHaveBeenCalled();
2985
2987
  expect((method as any).executeProtocolV2Update).toHaveBeenCalledWith({
2986
2988
  fwBinaryMap: [
2987
2989
  {
@@ -3300,9 +3302,9 @@ describe('Protocol V2 firmware update targets', () => {
3300
3302
  const typedCall = jest
3301
3303
  .fn()
3302
3304
  .mockRejectedValue(
3303
- new DOMException(
3304
- "Failed to execute 'open' on 'USBDevice': The device was disconnected",
3305
- 'NotFoundError'
3305
+ Object.assign(
3306
+ new Error("Failed to execute 'open' on 'USBDevice': The device was disconnected"),
3307
+ { name: 'NotFoundError' }
3306
3308
  )
3307
3309
  );
3308
3310
 
@@ -3390,7 +3392,7 @@ describe('Protocol V2 firmware update targets', () => {
3390
3392
  expect(method.postProgressMessage).toHaveBeenCalledWith(100, 'installingFirmware');
3391
3393
  });
3392
3394
 
3393
- test('accepts a missing firmware status handler as an app reboot signal', async () => {
3395
+ test('does not treat a missing firmware status handler as install completion', async () => {
3394
3396
  const method = new FirmwareUpdateV4({
3395
3397
  id: 1,
3396
3398
  payload: {
@@ -3409,12 +3411,88 @@ describe('Protocol V2 firmware update targets', () => {
3409
3411
  (method as any).verifyProtocolV2ReconnectIdentity = jest.fn().mockResolvedValue(undefined);
3410
3412
  method.postProgressMessage = jest.fn();
3411
3413
 
3412
- await (method as any).waitForProtocolV2FirmwareUpdateComplete([
3413
- { target_id: 4, path: 'vol0:/application_p1.bin' },
3414
- ]);
3414
+ await expect(
3415
+ (method as any).waitForProtocolV2FirmwareUpdateComplete([
3416
+ { target_id: 4, path: 'vol0:/application_p1.bin' },
3417
+ ])
3418
+ ).rejects.toThrow('Protocol V2 firmware install status is unavailable');
3415
3419
 
3416
3420
  expect(reconnectProtocolV2Device).toHaveBeenCalledTimes(1);
3417
- expect(typedCall.mock.calls.map(call => call[0])).toEqual(['DeviceFirmwareUpdateStatusGet']);
3421
+ expect(typedCall.mock.calls.map(call => call[0])).toEqual([
3422
+ 'DeviceFirmwareUpdateStatusGet',
3423
+ 'DeviceInfoGet',
3424
+ ]);
3425
+ });
3426
+
3427
+ test('rejects a finished target whose payload version conflicts with the plan', () => {
3428
+ const method = new FirmwareUpdateV4({
3429
+ id: 1,
3430
+ payload: {
3431
+ method: 'firmwareUpdateV4',
3432
+ platform: 'desktop',
3433
+ expectedTargetVersions: {
3434
+ app_v1: '2.0.0',
3435
+ },
3436
+ },
3437
+ });
3438
+ method.init();
3439
+ method.postProgressMessage = jest.fn();
3440
+
3441
+ expect(() =>
3442
+ (method as any).assertProtocolV2TargetStatus(
3443
+ [{ target_id: 4, status: 2, payload_version: 0x010000 }],
3444
+ new Set([4])
3445
+ )
3446
+ ).toThrow('expected 131072');
3447
+ });
3448
+
3449
+ test('does not fail a completed multi-app install when final app versions are unobservable', () => {
3450
+ const method = new FirmwareUpdateV4({
3451
+ id: 1,
3452
+ payload: {
3453
+ method: 'firmwareUpdateV4',
3454
+ platform: 'desktop',
3455
+ targetsToUpdate: ['app_v1', 'app_v2'],
3456
+ expectedTargetVersions: {
3457
+ app_v1: '1.0.0',
3458
+ app_v2: '2.0.0',
3459
+ },
3460
+ },
3461
+ });
3462
+ method.init();
3463
+ (method as any).protocolV2LatestFinalFeatures = {
3464
+ major_version: 3,
3465
+ minor_version: 0,
3466
+ patch_version: 0,
3467
+ };
3468
+ (method as any).protocolV2FinalStatusVerified = true;
3469
+
3470
+ expect(() => (method as any).assertExpectedProtocolV2Versions()).not.toThrow();
3471
+ });
3472
+
3473
+ test('rejects unobservable final versions after the status endpoint fallback', () => {
3474
+ const method = new FirmwareUpdateV4({
3475
+ id: 1,
3476
+ payload: {
3477
+ method: 'firmwareUpdateV4',
3478
+ platform: 'desktop',
3479
+ targetsToUpdate: ['app_v1', 'app_v2'],
3480
+ expectedTargetVersions: {
3481
+ app_v1: '1.0.0',
3482
+ app_v2: '2.0.0',
3483
+ },
3484
+ },
3485
+ });
3486
+ method.init();
3487
+ (method as any).protocolV2LatestFinalFeatures = {
3488
+ major_version: 3,
3489
+ minor_version: 0,
3490
+ patch_version: 0,
3491
+ };
3492
+
3493
+ expect(() => (method as any).assertExpectedProtocolV2Versions()).toThrow(
3494
+ 'has no observable final version after status fallback'
3495
+ );
3418
3496
  });
3419
3497
 
3420
3498
  test('polls target status after update ACK and finishes when all targets complete', async () => {
@@ -3593,10 +3671,14 @@ describe('Protocol V2 firmware update targets', () => {
3593
3671
  const writtenPaths: string[] = [];
3594
3672
  method.postTipMessage = jest.fn();
3595
3673
  method.postProgressMessage = jest.fn();
3596
- (method as any).protocolV2CommonUpdateProcess = jest.fn().mockImplementation(params => {
3674
+ (method as any).protocolV2SourceUpdateProcess = jest.fn().mockImplementation(params => {
3597
3675
  writtenPaths.push(params.filePath);
3598
- return Number(params.processedSize ?? 0) + Number(params.payload.byteLength);
3676
+ return Number(params.processedSize ?? 0) + Number(params.source.size);
3599
3677
  });
3678
+ (method as any).enterProtocolV2BootloaderMode = jest.fn().mockResolvedValue(undefined);
3679
+ (method as any).exitProtocolV2BootloaderToNormal = jest.fn().mockResolvedValue(undefined);
3680
+ (method as any).waitForProtocolV2FinalFeatures = jest.fn().mockResolvedValue({});
3681
+ (method as any).completeProtocolV2FinalVerification = jest.fn().mockResolvedValue({});
3600
3682
  (method as any).verifyProtocolV2StagedFile = jest.fn().mockResolvedValue(undefined);
3601
3683
  (method as any).protocolV2StartFirmwareUpdate = jest.fn().mockResolvedValue(undefined);
3602
3684
  (method as any).waitForProtocolV2FirmwareUpdateComplete = jest
@@ -3636,10 +3718,12 @@ describe('Protocol V2 firmware update targets', () => {
3636
3718
  'vol0:/coprocessor.bin',
3637
3719
  1
3638
3720
  );
3639
- expect((method as any).protocolV2StartFirmwareUpdate).toHaveBeenCalledTimes(1);
3640
- expect((method as any).protocolV2StartFirmwareUpdate).toHaveBeenCalledWith({
3721
+ expect((method as any).protocolV2StartFirmwareUpdate).toHaveBeenCalledTimes(2);
3722
+ expect((method as any).protocolV2StartFirmwareUpdate).toHaveBeenNthCalledWith(1, {
3723
+ targets: [{ target_id: 3, path: 'vol0:/bootloader.bin' }],
3724
+ });
3725
+ expect((method as any).protocolV2StartFirmwareUpdate).toHaveBeenNthCalledWith(2, {
3641
3726
  targets: [
3642
- { target_id: 3, path: 'vol0:/bootloader.bin' },
3643
3727
  { target_id: 6, path: 'vol0:/coprocessor.bin' },
3644
3728
  { target_id: 7, path: 'vol0:/se01.bin' },
3645
3729
  { target_id: 4, path: 'vol0:/application_p1.bin' },
@@ -3649,7 +3733,7 @@ describe('Protocol V2 firmware update targets', () => {
3649
3733
  expect((method as any).waitForProtocolV2FirmwareUpdateComplete).toHaveBeenCalled();
3650
3734
  });
3651
3735
 
3652
- test('announces one transfer when syncing resource bundles and staging firmware', async () => {
3736
+ test('announces separate resource and component transfer phases', async () => {
3653
3737
  const method = new FirmwareUpdateV4({
3654
3738
  id: 1,
3655
3739
  payload: {
@@ -3659,11 +3743,14 @@ describe('Protocol V2 firmware update targets', () => {
3659
3743
 
3660
3744
  method.postTipMessage = jest.fn();
3661
3745
  method.postProgressMessage = jest.fn();
3662
- (method as any).protocolV2CommonUpdateProcess = jest
3746
+ (method as any).protocolV2SourceUpdateProcess = jest
3663
3747
  .fn()
3664
3748
  .mockImplementation(params =>
3665
- Promise.resolve(Number(params.processedSize ?? 0) + Number(params.payload.byteLength))
3749
+ Promise.resolve(Number(params.processedSize ?? 0) + Number(params.source.size))
3666
3750
  );
3751
+ (method as any).enterProtocolV2BootloaderMode = jest.fn().mockResolvedValue(undefined);
3752
+ (method as any).exitProtocolV2BootloaderToNormal = jest.fn().mockResolvedValue(undefined);
3753
+ (method as any).completeProtocolV2FinalVerification = jest.fn().mockResolvedValue({});
3667
3754
  (method as any).verifyProtocolV2StagedFile = jest.fn().mockResolvedValue(undefined);
3668
3755
  (method as any).protocolV2StartFirmwareUpdate = jest.fn().mockResolvedValue(undefined);
3669
3756
  (method as any).waitForProtocolV2FirmwareUpdateComplete = jest
@@ -3683,21 +3770,22 @@ describe('Protocol V2 firmware update targets', () => {
3683
3770
  {
3684
3771
  fileName: 'application_p1.bin',
3685
3772
  binary: new Uint8Array([3]).buffer,
3686
- targetId: 3,
3773
+ targetId: 4,
3687
3774
  },
3688
3775
  ],
3689
3776
  });
3690
3777
 
3691
- expect(method.postTipMessage).toHaveBeenCalledTimes(2);
3778
+ expect(method.postTipMessage).toHaveBeenCalledTimes(3);
3692
3779
  expect(method.postTipMessage).toHaveBeenNthCalledWith(1, 'StartTransferData');
3693
- expect(method.postTipMessage).toHaveBeenNthCalledWith(2, 'ConfirmOnDevice');
3694
- expect((method as any).protocolV2CommonUpdateProcess).toHaveBeenNthCalledWith(
3780
+ expect(method.postTipMessage).toHaveBeenNthCalledWith(2, 'StartTransferData');
3781
+ expect(method.postTipMessage).toHaveBeenNthCalledWith(3, 'ConfirmOnDevice');
3782
+ expect((method as any).protocolV2SourceUpdateProcess).toHaveBeenNthCalledWith(
3695
3783
  1,
3696
- expect.objectContaining({ processedSize: 0, totalSize: 3 })
3784
+ expect.objectContaining({ processedSize: 0, totalSize: 2 })
3697
3785
  );
3698
- expect((method as any).protocolV2CommonUpdateProcess).toHaveBeenNthCalledWith(
3786
+ expect((method as any).protocolV2SourceUpdateProcess).toHaveBeenNthCalledWith(
3699
3787
  2,
3700
- expect.objectContaining({ processedSize: 2, totalSize: 3 })
3788
+ expect.objectContaining({ processedSize: 0, totalSize: 1 })
3701
3789
  );
3702
3790
  });
3703
3791
 
@@ -3711,7 +3799,8 @@ describe('Protocol V2 firmware update targets', () => {
3711
3799
 
3712
3800
  method.postTipMessage = jest.fn();
3713
3801
  method.postProgressMessage = jest.fn();
3714
- (method as any).protocolV2CommonUpdateProcess = jest.fn().mockResolvedValue(3);
3802
+ (method as any).protocolV2SourceUpdateProcess = jest.fn().mockResolvedValue(3);
3803
+ (method as any).enterProtocolV2BootloaderMode = jest.fn().mockResolvedValue(undefined);
3715
3804
  (method as any).device = stubDevice({
3716
3805
  getCommands: () => ({
3717
3806
  typedCall: jest.fn().mockResolvedValue({
@@ -3757,11 +3846,14 @@ describe('Protocol V2 firmware update targets', () => {
3757
3846
 
3758
3847
  method.postTipMessage = jest.fn();
3759
3848
  method.postProgressMessage = jest.fn();
3760
- (method as any).protocolV2CommonUpdateProcess = jest
3849
+ (method as any).protocolV2SourceUpdateProcess = jest
3761
3850
  .fn()
3762
3851
  .mockImplementation(params =>
3763
- Promise.resolve(Number(params.processedSize ?? 0) + Number(params.payload.byteLength))
3852
+ Promise.resolve(Number(params.processedSize ?? 0) + Number(params.source.size))
3764
3853
  );
3854
+ (method as any).enterProtocolV2BootloaderMode = jest.fn().mockResolvedValue(undefined);
3855
+ (method as any).exitProtocolV2BootloaderToNormal = jest.fn().mockResolvedValue(undefined);
3856
+ (method as any).completeProtocolV2FinalVerification = jest.fn().mockResolvedValue({});
3765
3857
  (method as any).verifyProtocolV2StagedFile = jest.fn().mockResolvedValue(undefined);
3766
3858
  (method as any).protocolV2StartFirmwareUpdate = jest.fn().mockResolvedValue(undefined);
3767
3859
  (method as any).waitForProtocolV2FirmwareUpdateComplete = jest
@@ -4028,6 +4120,58 @@ describe('Protocol V2 firmware update targets', () => {
4028
4120
  getFirmwareLatestReleaseSpy.mockRestore();
4029
4121
  });
4030
4122
 
4123
+ test('rejects prepared RESC bundle paths before opening an artifact source', async () => {
4124
+ const method = new FirmwareUpdateV4({
4125
+ id: 1,
4126
+ payload: {
4127
+ method: 'firmwareUpdateV4',
4128
+ },
4129
+ });
4130
+ const openPreparedSource = jest.fn();
4131
+ (method as any).params = {
4132
+ targetsToUpdate: ['resource'],
4133
+ resourceBundleArtifacts: [
4134
+ {
4135
+ name: 'images',
4136
+ artifact: {
4137
+ artifactRef: `fw:${'a'.repeat(64)}`,
4138
+ size: 1,
4139
+ sha256: 'a'.repeat(64),
4140
+ },
4141
+ },
4142
+ ],
4143
+ };
4144
+ (method as any).openProtocolV2PreparedSource = openPreparedSource;
4145
+ const getFirmwareLatestReleaseSpy = jest
4146
+ .spyOn(DataManager, 'getFirmwareLatestRelease')
4147
+ .mockReturnValue({
4148
+ required: false,
4149
+ version: [1, 0, 0],
4150
+ url: '',
4151
+ resourceBundles: [
4152
+ {
4153
+ name: 'images',
4154
+ url: 'https://example.com/images.okpkg',
4155
+ devicePath: 'vol0:/resource/../images.okpkg',
4156
+ },
4157
+ ],
4158
+ fingerprint: '',
4159
+ changelog: {
4160
+ 'zh-CN': '',
4161
+ 'en-US': '',
4162
+ },
4163
+ });
4164
+
4165
+ await expect(
4166
+ (method as any).prepareProtocolV2ResourceSources('universal', {
4167
+ deviceType: 'pro2',
4168
+ })
4169
+ ).rejects.toThrow('resourceBundles[].devicePath');
4170
+ expect(openPreparedSource).not.toHaveBeenCalled();
4171
+
4172
+ getFirmwareLatestReleaseSpy.mockRestore();
4173
+ });
4174
+
4031
4175
  test('downloads and validates remote RESC bundles before entering bootloader', async () => {
4032
4176
  const method = new FirmwareUpdateV4({
4033
4177
  id: 1,
@@ -4080,7 +4224,9 @@ describe('Protocol V2 firmware update targets', () => {
4080
4224
  order.push('bootloader');
4081
4225
  return Promise.resolve(true);
4082
4226
  });
4083
- (method as any).executeProtocolV2Update = jest.fn().mockResolvedValue(undefined);
4227
+ const executeProtocolV2UpdateSpy = jest.spyOn(method as any, 'executeProtocolV2Update');
4228
+ (method as any).executeProtocolV2TransferPhase = jest.fn().mockResolvedValue(undefined);
4229
+ (method as any).completeProtocolV2FinalVerification = jest.fn().mockResolvedValue(undefined);
4084
4230
  (method as any).exitProtocolV2BootloaderToNormal = jest.fn().mockResolvedValue(undefined);
4085
4231
  (method as any).waitForProtocolV2FinalFeatures = jest.fn().mockResolvedValue({
4086
4232
  bootloaderVersion: '1.0.0',
@@ -4092,7 +4238,7 @@ describe('Protocol V2 firmware update targets', () => {
4092
4238
  await method.run();
4093
4239
 
4094
4240
  expect(order).toEqual(['download', 'bootloader']);
4095
- expect((method as any).executeProtocolV2Update).toHaveBeenCalledWith({
4241
+ expect(executeProtocolV2UpdateSpy).toHaveBeenCalledWith({
4096
4242
  bootloaderBinary: null,
4097
4243
  fwBinaryMap: [],
4098
4244
  resourceBundles: [
@@ -4105,6 +4251,7 @@ describe('Protocol V2 firmware update targets', () => {
4105
4251
  ],
4106
4252
  });
4107
4253
 
4254
+ executeProtocolV2UpdateSpy.mockRestore();
4108
4255
  getSysResourceBinarySpy.mockRestore();
4109
4256
  getFirmwareLatestReleaseSpy.mockRestore();
4110
4257
  });
@@ -4393,7 +4540,10 @@ describe('Protocol V2 firmware update targets', () => {
4393
4540
 
4394
4541
  method.postTipMessage = jest.fn();
4395
4542
  method.postProgressMessage = jest.fn();
4396
- (method as any).protocolV2CommonUpdateProcess = jest.fn().mockResolvedValue(3);
4543
+ (method as any).protocolV2SourceUpdateProcess = jest.fn().mockResolvedValue(3);
4544
+ (method as any).enterProtocolV2BootloaderMode = jest.fn().mockResolvedValue(undefined);
4545
+ (method as any).completeProtocolV2FinalVerification = jest.fn().mockResolvedValue({});
4546
+ (method as any).verifyProtocolV2StagedFile = jest.fn().mockResolvedValue(undefined);
4397
4547
  (method as any).protocolV2StartFirmwareUpdate = jest.fn();
4398
4548
  (method as any).waitForProtocolV2FirmwareUpdateComplete = jest.fn();
4399
4549
 
@@ -4409,7 +4559,7 @@ describe('Protocol V2 firmware update targets', () => {
4409
4559
  fwBinaryMap: [],
4410
4560
  });
4411
4561
 
4412
- expect((method as any).protocolV2CommonUpdateProcess).toHaveBeenCalledTimes(1);
4562
+ expect((method as any).protocolV2SourceUpdateProcess).toHaveBeenCalledTimes(1);
4413
4563
  expect((method as any).protocolV2StartFirmwareUpdate).not.toHaveBeenCalled();
4414
4564
  expect((method as any).waitForProtocolV2FirmwareUpdateComplete).not.toHaveBeenCalled();
4415
4565
  });
@@ -4440,12 +4590,19 @@ describe('Protocol V2 firmware update targets', () => {
4440
4590
  });
4441
4591
  method.postProgressMessage = jest.fn();
4442
4592
 
4443
- await (method as any).protocolV2CommonUpdateProcess({
4444
- payload: new Uint8Array(4097).buffer,
4445
- filePath: 'vol1:firmware.bin',
4446
- processedSize: 0,
4447
- totalSize: 4097,
4593
+ const source = await openFirmwareByteSource({
4594
+ binary: new Uint8Array(4097).buffer,
4448
4595
  });
4596
+ try {
4597
+ await (method as any).protocolV2SourceUpdateProcess({
4598
+ source,
4599
+ filePath: 'vol1:firmware.bin',
4600
+ processedSize: 0,
4601
+ totalSize: 4097,
4602
+ });
4603
+ } finally {
4604
+ await source?.close();
4605
+ }
4449
4606
 
4450
4607
  const writePayloads = typedCall.mock.calls.map(call => call[2]);
4451
4608
  expect(writePayloads.map(payload => payload.file.offset)).toEqual([0, 4000]);
@@ -4496,12 +4653,16 @@ describe('Protocol V2 firmware update targets', () => {
4496
4653
  method.postProgressMessage = jest.fn();
4497
4654
 
4498
4655
  try {
4499
- await (method as any).protocolV2CommonUpdateProcess({
4500
- payload: new Uint8Array(8001).buffer,
4656
+ const source = await openFirmwareByteSource({
4657
+ binary: new Uint8Array(8001).buffer,
4658
+ });
4659
+ await (method as any).protocolV2SourceUpdateProcess({
4660
+ source,
4501
4661
  filePath: 'vol0:/firmware.bin',
4502
4662
  processedSize: 0,
4503
4663
  totalSize: 8001,
4504
4664
  });
4665
+ await source?.close();
4505
4666
  } finally {
4506
4667
  setTimeoutSpy.mockRestore();
4507
4668
  }
@@ -4533,16 +4694,21 @@ describe('Protocol V2 firmware update targets', () => {
4533
4694
  });
4534
4695
  method.postProgressMessage = jest.fn();
4535
4696
  method.postTipMessage = jest.fn();
4697
+ (method as any).recoverProtocolV2FileTransfer = jest.fn().mockResolvedValue(undefined);
4536
4698
 
4699
+ const source = await openFirmwareByteSource({
4700
+ binary: new Uint8Array(4097).buffer,
4701
+ });
4537
4702
  await expect(
4538
- (method as any).protocolV2WriteWholeFile({
4539
- payload: new Uint8Array(4097).buffer,
4703
+ (method as any).protocolV2SourceUpdateProcess({
4704
+ source,
4540
4705
  filePath: 'vol0:/firmware.bin',
4541
4706
  processedSize: 0,
4542
4707
  totalSize: 4097,
4543
4708
  })
4544
4709
  ).rejects.toMatchObject({ errorCode: HardwareErrorCode.EmmcFileWriteFirmwareError });
4545
- expect(typedCall).toHaveBeenCalledTimes(2);
4710
+ await source?.close();
4711
+ expect(typedCall).toHaveBeenCalledTimes(6);
4546
4712
  });
4547
4713
 
4548
4714
  test('caps native BLE firmware upload chunks below the WebUSB limit', async () => {
@@ -4575,12 +4741,19 @@ describe('Protocol V2 firmware update targets', () => {
4575
4741
  });
4576
4742
  method.postProgressMessage = jest.fn();
4577
4743
 
4578
- await (method as any).protocolV2CommonUpdateProcess({
4579
- payload: new Uint8Array(1801).buffer,
4580
- filePath: 'vol1:ble-firmware.bin',
4581
- processedSize: 0,
4582
- totalSize: 1801,
4744
+ const source = await openFirmwareByteSource({
4745
+ binary: new Uint8Array(1801).buffer,
4583
4746
  });
4747
+ try {
4748
+ await (method as any).protocolV2SourceUpdateProcess({
4749
+ source,
4750
+ filePath: 'vol1:ble-firmware.bin',
4751
+ processedSize: 0,
4752
+ totalSize: 1801,
4753
+ });
4754
+ } finally {
4755
+ await source?.close();
4756
+ }
4584
4757
 
4585
4758
  const writePayloads = typedCall.mock.calls.map(call => call[2]);
4586
4759
  expect(writePayloads.map(payload => payload.file.offset)).toEqual([0, 1800]);
@@ -4697,9 +4870,9 @@ describe('Protocol V2 firmware update method', () => {
4697
4870
  const typedCall = jest
4698
4871
  .fn()
4699
4872
  .mockRejectedValue(
4700
- new DOMException(
4701
- "Failed to execute 'open' on 'USBDevice': The device was disconnected",
4702
- 'NotFoundError'
4873
+ Object.assign(
4874
+ new Error("Failed to execute 'open' on 'USBDevice': The device was disconnected"),
4875
+ { name: 'NotFoundError' }
4703
4876
  )
4704
4877
  );
4705
4878
 
@@ -4864,6 +5037,21 @@ describe('Protocol V2 firmware update method', () => {
4864
5037
  });
4865
5038
 
4866
5039
  describe('Protocol V2 firmware reconnect identity', () => {
5040
+ test('keeps the host plan identity as the V4 reconnect anchor', () => {
5041
+ const method = new FirmwareUpdateV4({
5042
+ id: 1,
5043
+ payload: {
5044
+ method: 'firmwareUpdateV4',
5045
+ platform: 'native',
5046
+ expectedDeviceId: 'persisted-device-id',
5047
+ },
5048
+ });
5049
+
5050
+ method.init();
5051
+
5052
+ expect((method as any).params.expectedDeviceId).toBe('persisted-device-id');
5053
+ });
5054
+
4867
5055
  test('rejects a different physical serial before firmware transfer resumes', () => {
4868
5056
  expect(() => assertProtocolV2ReconnectIdentity('expected-serial', 'other-serial')).toThrow(
4869
5057
  'identity mismatch'
@@ -5207,6 +5395,93 @@ describe('Protocol V2 protected method execution', () => {
5207
5395
  ]);
5208
5396
  });
5209
5397
 
5398
+ test('restores the expected hidden-wallet session after pre-unlock without selecting Attach PIN', async () => {
5399
+ const calls: string[] = [];
5400
+ const method = {
5401
+ name: 'evmSignMessage',
5402
+ payload: { passphraseState: 'hidden-state' },
5403
+ useDevicePassphraseState: true,
5404
+ unlockPolicy: 'retry-on-locked',
5405
+ run: jest.fn(() => {
5406
+ calls.push('run');
5407
+ return Promise.resolve({ message: 'ok' });
5408
+ }),
5409
+ };
5410
+ const typedCall = jest.fn((requestType: string, _responseType: string, request: any) => {
5411
+ if (requestType === 'ProtocolInfoRequest') {
5412
+ calls.push('negotiate-session');
5413
+ return Promise.resolve({ message: { version: 2 } });
5414
+ }
5415
+ if (requestType === 'DeviceSessionGet') {
5416
+ calls.push('resume-hidden-session');
5417
+ expect(request).toEqual({ session_id: 'hidden-session' });
5418
+ return Promise.resolve({
5419
+ message: {
5420
+ session_id: 'hidden-session',
5421
+ btc_test_address: 'hidden-state',
5422
+ },
5423
+ });
5424
+ }
5425
+ throw new Error(`Unexpected request: ${requestType}`);
5426
+ });
5427
+ const features = {
5428
+ unlocked: false,
5429
+ unlockedAttachPin: true,
5430
+ passphraseProtection: true,
5431
+ };
5432
+ const device = {
5433
+ features,
5434
+ passphraseState: 'hidden-state',
5435
+ commands: { typedCall },
5436
+ isProtocolV2: () => true,
5437
+ unlockDevice: jest.fn(() => {
5438
+ calls.push('unlock-main');
5439
+ features.unlocked = true;
5440
+ features.unlockedAttachPin = false;
5441
+ return Promise.resolve();
5442
+ }),
5443
+ getCurrentPassphraseProtection: () => true,
5444
+ getInternalState: () => 'hidden-session',
5445
+ clearInternalState: jest.fn(),
5446
+ getCurrentDeviceId: () => 'wallet-device-id',
5447
+ updateInternalState: jest.fn(() => calls.push('validate-hidden-session')),
5448
+ };
5449
+
5450
+ await expect(runMethodWithUnlockRetry(method as any, device as any)).resolves.toEqual({
5451
+ message: 'ok',
5452
+ });
5453
+ expect(device.unlockDevice).toHaveBeenCalledWith();
5454
+ expect(calls).toEqual([
5455
+ 'unlock-main',
5456
+ 'negotiate-session',
5457
+ 'resume-hidden-session',
5458
+ 'validate-hidden-session',
5459
+ 'run',
5460
+ ]);
5461
+ });
5462
+
5463
+ test('does not restore a hidden-wallet session for a standard-wallet pre-unlock', async () => {
5464
+ const method = {
5465
+ name: 'evmGetAddress',
5466
+ payload: { useEmptyPassphrase: true },
5467
+ useDevicePassphraseState: true,
5468
+ unlockPolicy: 'retry-on-locked',
5469
+ run: jest.fn().mockResolvedValue({ address: 'standard-wallet-address' }),
5470
+ };
5471
+ const device = {
5472
+ features: { unlocked: false },
5473
+ passphraseState: 'stale-hidden-state',
5474
+ isProtocolV2: () => true,
5475
+ unlockDevice: jest.fn().mockResolvedValue(undefined),
5476
+ };
5477
+
5478
+ await expect(runMethodWithUnlockRetry(method as any, device as any)).resolves.toEqual({
5479
+ address: 'standard-wallet-address',
5480
+ });
5481
+ expect(device.unlockDevice).toHaveBeenCalledTimes(1);
5482
+ expect(method.run).toHaveBeenCalledTimes(1);
5483
+ });
5484
+
5210
5485
  test('unlocks before showing the method interaction when cached status is locked', async () => {
5211
5486
  const calls: string[] = [];
5212
5487
  const method = {
@@ -5292,10 +5567,10 @@ describe('Protocol V2 protected method execution', () => {
5292
5567
  }
5293
5568
  });
5294
5569
 
5295
- test('keeps auto unlock but suppresses all synthesized UI for eventless methods', async () => {
5570
+ test('runs lock-free eventless methods without unlocking or synthesized UI', async () => {
5296
5571
  const method = {
5297
5572
  name: 'uploadPortfolio',
5298
- unlockPolicy: 'unlock-before-run',
5573
+ unlockPolicy: 'none',
5299
5574
  protocolV2UiMode: 'none',
5300
5575
  run: jest.fn().mockResolvedValue({ message: 'ok' }),
5301
5576
  };
@@ -5313,17 +5588,17 @@ describe('Protocol V2 protected method execution', () => {
5313
5588
  await expect(
5314
5589
  runMethodWithUnlockRetry(method as any, device as any, uiCoordinator as any)
5315
5590
  ).resolves.toEqual({ message: 'ok' });
5316
- expect(device.unlockDevice).toHaveBeenCalledTimes(1);
5591
+ expect(device.unlockDevice).not.toHaveBeenCalled();
5317
5592
  expect(uiCoordinator.enterMethodInteraction).not.toHaveBeenCalled();
5318
5593
  expect(uiCoordinator.enterUnlockInteraction).not.toHaveBeenCalled();
5319
5594
  expect(uiCoordinator.resumeMethodInteraction).not.toHaveBeenCalled();
5320
5595
  });
5321
5596
 
5322
- test('does not replay a state-changing method after a locked response', async () => {
5597
+ test('does not unlock or replay a lock-free state-changing method after a locked response', async () => {
5323
5598
  const error = deviceLockedError();
5324
5599
  const method = {
5325
5600
  name: 'uploadPortfolio',
5326
- unlockPolicy: 'unlock-before-run',
5601
+ unlockPolicy: 'none',
5327
5602
  run: jest.fn().mockRejectedValue(error),
5328
5603
  };
5329
5604
  const device = {
@@ -5779,7 +6054,7 @@ describe('Protocol V2 raw device info method', () => {
5779
6054
  );
5780
6055
  });
5781
6056
 
5782
- test('rejects on Protocol V1 devices instead of sending an unknown message', async () => {
6057
+ test('rejects on Protocol V1 devices instead of sending an unknown message', () => {
5783
6058
  const method = buildMethod();
5784
6059
  const typedCall = jest.fn();
5785
6060
  (method as any).device = stubDevice({
@@ -5787,7 +6062,9 @@ describe('Protocol V2 raw device info method', () => {
5787
6062
  commands: { typedCall },
5788
6063
  });
5789
6064
 
5790
- await expect(method.run()).rejects.toThrow();
6065
+ expect(() => method.assertProtocolSupported('V1', EFirmwareType.Universal)).toThrow(
6066
+ expect.objectContaining({ errorCode: HardwareErrorCode.DeviceNotSupportMethod })
6067
+ );
5791
6068
  expect(typedCall).not.toHaveBeenCalled();
5792
6069
  });
5793
6070
  });