@onekeyfe/hd-core 1.2.0-alpha.2 → 1.2.0-alpha.21

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 (406) hide show
  1. package/__tests__/AllNetworkGetAddressBase.tracing.test.ts +75 -0
  2. package/__tests__/DeviceCommands.test.ts +285 -0
  3. package/__tests__/DeviceEventRegistration.test.ts +43 -0
  4. package/__tests__/connectSettings.test.ts +19 -0
  5. package/__tests__/core-dispose.test.ts +34 -0
  6. package/__tests__/core-error-output.test.ts +39 -0
  7. package/__tests__/device-features-state.test.ts +78 -0
  8. package/__tests__/device-identity.test.ts +30 -0
  9. package/__tests__/device-lifecycle-events.test.ts +117 -0
  10. package/__tests__/device-pool-state.test.ts +132 -0
  11. package/__tests__/device-settings.test.ts +391 -0
  12. package/__tests__/device-state-contract.test.ts +27 -0
  13. package/__tests__/device-state-events.test.ts +162 -0
  14. package/__tests__/device-state-mapper.test.ts +241 -0
  15. package/__tests__/device-state-projector.test.ts +94 -0
  16. package/__tests__/device-state-store.test.ts +82 -0
  17. package/__tests__/device-utils.test.ts +106 -0
  18. package/__tests__/device-wallet-session-store.test.ts +213 -0
  19. package/__tests__/deviceFeaturesUtils.test.ts +39 -0
  20. package/__tests__/deviceSettings.test.ts +103 -0
  21. package/__tests__/evmLedgerLegacySafety.test.ts +10 -6
  22. package/__tests__/evmSignTypedData.test.ts +80 -0
  23. package/__tests__/filesystemValidation.test.ts +53 -0
  24. package/__tests__/firmware-update/firmware-update-v2-download-before-boot.test.ts +402 -0
  25. package/__tests__/get-device-state.test.ts +410 -0
  26. package/__tests__/homescreen.test.ts +24 -0
  27. package/__tests__/kaspaSignTransaction.test.ts +591 -0
  28. package/__tests__/logBlockEvent.test.ts +26 -0
  29. package/__tests__/networkUtils.test.ts +386 -0
  30. package/__tests__/open-wallet-session-error-response.test.ts +43 -0
  31. package/__tests__/open-wallet-session.test.ts +559 -0
  32. package/__tests__/preInitialize.test.ts +33 -0
  33. package/__tests__/pro2Wallpaper.test.ts +50 -0
  34. package/__tests__/protocol-v2-bootloader-mode.test.ts +37 -0
  35. package/__tests__/protocol-v2-firmware-targets.test.ts +19 -0
  36. package/__tests__/protocol-v2.test.ts +3954 -1191
  37. package/__tests__/protocolV2FileWrite.test.ts +92 -0
  38. package/__tests__/protocolV2UiInteraction.test.ts +266 -0
  39. package/__tests__/public-device-state-api.test.ts +257 -0
  40. package/__tests__/public-pro2-api-boundary.test.ts +110 -0
  41. package/__tests__/refresh-device-state.test.ts +101 -0
  42. package/__tests__/request-context-logging.test.ts +16 -0
  43. package/__tests__/search-devices.test.ts +136 -0
  44. package/dist/api/BaseMethod.d.ts +8 -0
  45. package/dist/api/BaseMethod.d.ts.map +1 -1
  46. package/dist/api/CheckBootloaderRelease.d.ts.map +1 -1
  47. package/dist/api/CheckFirmwareRelease.d.ts.map +1 -1
  48. package/dist/api/ClearSessionCache.d.ts +9 -0
  49. package/dist/api/ClearSessionCache.d.ts.map +1 -0
  50. package/dist/api/DirList.d.ts.map +1 -1
  51. package/dist/api/FileRead.d.ts.map +1 -1
  52. package/dist/api/FileWrite.d.ts +1 -0
  53. package/dist/api/FileWrite.d.ts.map +1 -1
  54. package/dist/api/FirmwareUpdateV2.d.ts +2 -2
  55. package/dist/api/FirmwareUpdateV2.d.ts.map +1 -1
  56. package/dist/api/FirmwareUpdateV3.d.ts.map +1 -1
  57. package/dist/api/FirmwareUpdateV4.d.ts +25 -5
  58. package/dist/api/FirmwareUpdateV4.d.ts.map +1 -1
  59. package/dist/api/GetDeviceState.d.ts +7 -0
  60. package/dist/api/GetDeviceState.d.ts.map +1 -0
  61. package/dist/api/GetFeatures.d.ts +1 -1
  62. package/dist/api/GetFeatures.d.ts.map +1 -1
  63. package/dist/api/GetOnekeyFeatures.d.ts.map +1 -1
  64. package/dist/api/GetPassphraseState.d.ts +1 -6
  65. package/dist/api/GetPassphraseState.d.ts.map +1 -1
  66. package/dist/api/OpenWalletSession.d.ts +14 -0
  67. package/dist/api/OpenWalletSession.d.ts.map +1 -0
  68. package/dist/api/PathInfo.d.ts.map +1 -1
  69. package/dist/api/PromptWebDeviceAccess.d.ts.map +1 -1
  70. package/dist/api/SearchDevices.d.ts +3 -0
  71. package/dist/api/SearchDevices.d.ts.map +1 -1
  72. package/dist/api/UploadPortfolio.d.ts +17 -0
  73. package/dist/api/UploadPortfolio.d.ts.map +1 -0
  74. package/dist/api/allnetwork/AllNetworkGetAddressBase.d.ts.map +1 -1
  75. package/dist/api/device/DeviceCancel.d.ts.map +1 -1
  76. package/dist/api/device/DeviceChangePin.d.ts.map +1 -1
  77. package/dist/api/device/DeviceFullyUploadResource.d.ts +1 -2
  78. package/dist/api/device/DeviceFullyUploadResource.d.ts.map +1 -1
  79. package/dist/api/device/DeviceLock.d.ts.map +1 -1
  80. package/dist/api/device/DeviceRebootToBoardloader.d.ts.map +1 -1
  81. package/dist/api/device/DeviceRebootToBootloader.d.ts.map +1 -1
  82. package/dist/api/device/DeviceSettings.d.ts.map +1 -1
  83. package/dist/api/device/DeviceUnlock.d.ts +1 -1
  84. package/dist/api/device/DeviceUnlock.d.ts.map +1 -1
  85. package/dist/api/device/DeviceUpdateBootloader.d.ts.map +1 -1
  86. package/dist/api/device/DeviceWipe.d.ts.map +1 -1
  87. package/dist/api/evm/EVMSignTypedData.d.ts.map +1 -1
  88. package/dist/api/firmware/FirmwareUpdateBaseMethod.d.ts +1 -0
  89. package/dist/api/firmware/FirmwareUpdateBaseMethod.d.ts.map +1 -1
  90. package/dist/api/firmware/getBinary.d.ts +11 -3
  91. package/dist/api/firmware/getBinary.d.ts.map +1 -1
  92. package/dist/api/firmware/progressThrottle.d.ts +3 -0
  93. package/dist/api/firmware/progressThrottle.d.ts.map +1 -0
  94. package/dist/api/helpers/filesystemValidation.d.ts +3 -0
  95. package/dist/api/helpers/filesystemValidation.d.ts.map +1 -1
  96. package/dist/api/helpers/paramsValidator.d.ts +1 -0
  97. package/dist/api/helpers/paramsValidator.d.ts.map +1 -1
  98. package/dist/api/helpers/protocolV2FileWrite.d.ts +33 -0
  99. package/dist/api/helpers/protocolV2FileWrite.d.ts.map +1 -0
  100. package/dist/api/index.d.ts +12 -19
  101. package/dist/api/index.d.ts.map +1 -1
  102. package/dist/api/kaspa/KaspaSignTransaction.d.ts +5 -1
  103. package/dist/api/kaspa/KaspaSignTransaction.d.ts.map +1 -1
  104. package/dist/api/kaspa/helpers/TransferSerialize.d.ts.map +1 -1
  105. package/dist/api/protocol-v2/DeviceFactoryInfoGet.d.ts +6 -0
  106. package/dist/api/protocol-v2/DeviceFactoryInfoGet.d.ts.map +1 -0
  107. package/dist/api/protocol-v2/DeviceFactoryInfoSet.d.ts +7 -0
  108. package/dist/api/protocol-v2/DeviceFactoryInfoSet.d.ts.map +1 -0
  109. package/dist/api/protocol-v2/DeviceFirmwareUpdate.d.ts +1 -1
  110. package/dist/api/protocol-v2/DeviceFirmwareUpdate.d.ts.map +1 -1
  111. package/dist/api/protocol-v2/DeviceGetFirmwareUpdateStatus.d.ts +3 -2
  112. package/dist/api/protocol-v2/DeviceGetFirmwareUpdateStatus.d.ts.map +1 -1
  113. package/dist/api/protocol-v2/DeviceGetOnboardingStatus.d.ts +1 -1
  114. package/dist/api/protocol-v2/DeviceGetOnboardingStatus.d.ts.map +1 -1
  115. package/dist/api/protocol-v2/DeviceInfoGet.d.ts +28 -0
  116. package/dist/api/protocol-v2/DeviceInfoGet.d.ts.map +1 -0
  117. package/dist/api/protocol-v2/DeviceReboot.d.ts.map +1 -1
  118. package/dist/api/protocol-v2/DeviceStatusGet.d.ts +6 -0
  119. package/dist/api/protocol-v2/DeviceStatusGet.d.ts.map +1 -0
  120. package/dist/api/protocol-v2/DeviceUploadWallpaper.d.ts +26 -0
  121. package/dist/api/protocol-v2/DeviceUploadWallpaper.d.ts.map +1 -0
  122. package/dist/api/protocol-v2/FilesystemFormat.d.ts.map +1 -1
  123. package/dist/api/protocol-v2/{FilesystemFixPermission.d.ts → FilesystemPermissionFix.d.ts} +2 -2
  124. package/dist/api/protocol-v2/FilesystemPermissionFix.d.ts.map +1 -0
  125. package/dist/api/protocol-v2/ProtocolInfoRequest.d.ts +6 -0
  126. package/dist/api/protocol-v2/ProtocolInfoRequest.d.ts.map +1 -0
  127. package/dist/api/protocol-v2/helpers.d.ts +27 -19
  128. package/dist/api/protocol-v2/helpers.d.ts.map +1 -1
  129. package/dist/api/ton/TonSignData.d.ts +1 -5
  130. package/dist/api/ton/TonSignData.d.ts.map +1 -1
  131. package/dist/api/utils.d.ts +2 -1
  132. package/dist/api/utils.d.ts.map +1 -1
  133. package/dist/constants/index.d.ts +2 -1
  134. package/dist/constants/index.d.ts.map +1 -1
  135. package/dist/core/RequestQueue.d.ts.map +1 -1
  136. package/dist/core/deviceEventRegistration.d.ts +11 -0
  137. package/dist/core/deviceEventRegistration.d.ts.map +1 -0
  138. package/dist/core/index.d.ts +3 -1
  139. package/dist/core/index.d.ts.map +1 -1
  140. package/dist/data-manager/DataManager.d.ts +1 -1
  141. package/dist/data-manager/DataManager.d.ts.map +1 -1
  142. package/dist/data-manager/connectSettings.d.ts.map +1 -1
  143. package/dist/device/Device.d.ts +35 -11
  144. package/dist/device/Device.d.ts.map +1 -1
  145. package/dist/device/DeviceCommands.d.ts +8 -6
  146. package/dist/device/DeviceCommands.d.ts.map +1 -1
  147. package/dist/device/DeviceFeaturesState.d.ts +3 -0
  148. package/dist/device/DeviceFeaturesState.d.ts.map +1 -0
  149. package/dist/device/DevicePool.d.ts +4 -2
  150. package/dist/device/DevicePool.d.ts.map +1 -1
  151. package/dist/device/DeviceStateMapper.d.ts +13 -0
  152. package/dist/device/DeviceStateMapper.d.ts.map +1 -0
  153. package/dist/device/DeviceStateProjector.d.ts +7 -0
  154. package/dist/device/DeviceStateProjector.d.ts.map +1 -0
  155. package/dist/device/DeviceStateStore.d.ts +21 -0
  156. package/dist/device/DeviceStateStore.d.ts.map +1 -0
  157. package/dist/device/DeviceWalletSessionStore.d.ts +20 -0
  158. package/dist/device/DeviceWalletSessionStore.d.ts.map +1 -0
  159. package/dist/device/cloneDeviceState.d.ts +2 -0
  160. package/dist/device/cloneDeviceState.d.ts.map +1 -0
  161. package/dist/device/deviceIdentity.d.ts +5 -0
  162. package/dist/device/deviceIdentity.d.ts.map +1 -0
  163. package/dist/deviceProfile/buildDeviceFeatures.d.ts +9 -3
  164. package/dist/deviceProfile/buildDeviceFeatures.d.ts.map +1 -1
  165. package/dist/deviceProfile/index.d.ts +0 -1
  166. package/dist/deviceProfile/index.d.ts.map +1 -1
  167. package/dist/events/device.d.ts +11 -2
  168. package/dist/events/device.d.ts.map +1 -1
  169. package/dist/events/logBlockEvent.d.ts.map +1 -1
  170. package/dist/events/ui-request.d.ts +18 -2
  171. package/dist/events/ui-request.d.ts.map +1 -1
  172. package/dist/index.d.ts +1361 -609
  173. package/dist/index.js +5898 -2860
  174. package/dist/inject.d.ts.map +1 -1
  175. package/dist/protocols/protocol-v2/deviceSession.d.ts +7 -0
  176. package/dist/protocols/protocol-v2/deviceSession.d.ts.map +1 -0
  177. package/dist/protocols/protocol-v2/features.d.ts +23 -28
  178. package/dist/protocols/protocol-v2/features.d.ts.map +1 -1
  179. package/dist/protocols/protocol-v2/firmware.d.ts +11 -9
  180. package/dist/protocols/protocol-v2/firmware.d.ts.map +1 -1
  181. package/dist/protocols/protocol-v2/index.d.ts +3 -2
  182. package/dist/protocols/protocol-v2/index.d.ts.map +1 -1
  183. package/dist/protocols/protocol-v2/lockedError.d.ts +2 -0
  184. package/dist/protocols/protocol-v2/lockedError.d.ts.map +1 -0
  185. package/dist/protocols/protocol-v2/settingsUnlockPolicy.d.ts +16 -0
  186. package/dist/protocols/protocol-v2/settingsUnlockPolicy.d.ts.map +1 -0
  187. package/dist/protocols/protocol-v2/uiInteraction.d.ts +39 -0
  188. package/dist/protocols/protocol-v2/uiInteraction.d.ts.map +1 -0
  189. package/dist/protocols/protocol-v2/unlockRetry.d.ts +11 -0
  190. package/dist/protocols/protocol-v2/unlockRetry.d.ts.map +1 -0
  191. package/dist/protocols/protocol-v2/walletSession.d.ts +19 -0
  192. package/dist/protocols/protocol-v2/walletSession.d.ts.map +1 -0
  193. package/dist/types/api/checkAllFirmwareRelease.d.ts +1 -2
  194. package/dist/types/api/checkAllFirmwareRelease.d.ts.map +1 -1
  195. package/dist/types/api/deviceSettings.d.ts +11 -2
  196. package/dist/types/api/deviceSettings.d.ts.map +1 -1
  197. package/dist/types/api/deviceUnlock.d.ts +2 -2
  198. package/dist/types/api/deviceUnlock.d.ts.map +1 -1
  199. package/dist/types/api/firmwareUpdate.d.ts +6 -6
  200. package/dist/types/api/firmwareUpdate.d.ts.map +1 -1
  201. package/dist/types/api/getDeviceState.d.ts +12 -0
  202. package/dist/types/api/getDeviceState.d.ts.map +1 -0
  203. package/dist/types/api/getFeatures.d.ts.map +1 -1
  204. package/dist/types/api/getOnekeyFeatures.d.ts.map +1 -1
  205. package/dist/types/api/getPassphraseState.d.ts +2 -10
  206. package/dist/types/api/getPassphraseState.d.ts.map +1 -1
  207. package/dist/types/api/index.d.ts +22 -25
  208. package/dist/types/api/index.d.ts.map +1 -1
  209. package/dist/types/api/kaspaSignTransaction.d.ts +27 -2
  210. package/dist/types/api/kaspaSignTransaction.d.ts.map +1 -1
  211. package/dist/types/api/openWalletSession.d.ts +41 -0
  212. package/dist/types/api/openWalletSession.d.ts.map +1 -0
  213. package/dist/types/api/protocolV2.d.ts +23 -28
  214. package/dist/types/api/protocolV2.d.ts.map +1 -1
  215. package/dist/types/api/sessionCache.d.ts +10 -0
  216. package/dist/types/api/sessionCache.d.ts.map +1 -0
  217. package/dist/types/device.d.ts +121 -5
  218. package/dist/types/device.d.ts.map +1 -1
  219. package/dist/types/params.d.ts +1 -0
  220. package/dist/types/params.d.ts.map +1 -1
  221. package/dist/types/settings.d.ts +21 -1
  222. package/dist/types/settings.d.ts.map +1 -1
  223. package/dist/utils/assets.d.ts +2 -1
  224. package/dist/utils/assets.d.ts.map +1 -1
  225. package/dist/utils/deviceFeaturesCompat.d.ts +13 -0
  226. package/dist/utils/deviceFeaturesCompat.d.ts.map +1 -0
  227. package/dist/utils/deviceFeaturesUtils.d.ts +13 -3
  228. package/dist/utils/deviceFeaturesUtils.d.ts.map +1 -1
  229. package/dist/utils/deviceInfoUtils.d.ts +9 -8
  230. package/dist/utils/deviceInfoUtils.d.ts.map +1 -1
  231. package/dist/utils/deviceSettings.d.ts +38 -7
  232. package/dist/utils/deviceSettings.d.ts.map +1 -1
  233. package/dist/utils/deviceVersionUtils.d.ts +6 -5
  234. package/dist/utils/deviceVersionUtils.d.ts.map +1 -1
  235. package/dist/utils/homescreen.d.ts.map +1 -1
  236. package/dist/utils/index.d.ts +5 -2
  237. package/dist/utils/index.d.ts.map +1 -1
  238. package/dist/utils/networkUtils.d.ts +9 -1
  239. package/dist/utils/networkUtils.d.ts.map +1 -1
  240. package/dist/utils/patch.d.ts +1 -1
  241. package/dist/utils/patch.d.ts.map +1 -1
  242. package/dist/utils/pro2Wallpaper.d.ts +12 -0
  243. package/dist/utils/pro2Wallpaper.d.ts.map +1 -0
  244. package/dist/utils/tracing.d.ts.map +1 -1
  245. package/package.json +4 -4
  246. package/src/api/BaseMethod.ts +36 -9
  247. package/src/api/CheckBootloaderRelease.ts +1 -2
  248. package/src/api/CheckFirmwareRelease.ts +1 -2
  249. package/src/api/ClearSessionCache.ts +28 -0
  250. package/src/api/DirList.ts +5 -3
  251. package/src/api/DirMake.ts +3 -3
  252. package/src/api/DirRemove.ts +3 -3
  253. package/src/api/FileDelete.ts +3 -3
  254. package/src/api/FileRead.ts +23 -7
  255. package/src/api/FileWrite.ts +23 -168
  256. package/src/api/FirmwareUpdate.ts +4 -4
  257. package/src/api/FirmwareUpdateV2.ts +133 -45
  258. package/src/api/FirmwareUpdateV3.ts +3 -5
  259. package/src/api/FirmwareUpdateV4.ts +1138 -357
  260. package/src/api/GetDeviceState.ts +55 -0
  261. package/src/api/GetFeatures.ts +8 -3
  262. package/src/api/GetOnekeyFeatures.ts +3 -72
  263. package/src/api/GetPassphraseState.ts +11 -18
  264. package/src/api/OpenWalletSession.ts +221 -0
  265. package/src/api/PathInfo.ts +5 -3
  266. package/src/api/PromptWebDeviceAccess.ts +2 -3
  267. package/src/api/SearchDevices.ts +29 -4
  268. package/src/api/UploadPortfolio.ts +40 -0
  269. package/src/api/alephium/AlephiumSignTransaction.ts +2 -2
  270. package/src/api/allnetwork/AllNetworkGetAddressBase.ts +4 -8
  271. package/src/api/benfen/BenfenGetAddress.ts +1 -1
  272. package/src/api/btc/BTCGetPublicKey.ts +1 -1
  273. package/src/api/cardano/CardanoSignMessage.ts +1 -1
  274. package/src/api/cardano/CardanoSignTransaction.ts +1 -1
  275. package/src/api/device/DeviceCancel.ts +1 -0
  276. package/src/api/device/DeviceChangePin.ts +24 -0
  277. package/src/api/device/DeviceFullyUploadResource.ts +4 -5
  278. package/src/api/device/DeviceLock.ts +1 -0
  279. package/src/api/device/DeviceRebootToBoardloader.ts +5 -4
  280. package/src/api/device/DeviceRebootToBootloader.ts +5 -4
  281. package/src/api/device/DeviceSettings.ts +183 -1
  282. package/src/api/device/DeviceUnlock.ts +11 -1
  283. package/src/api/device/DeviceUpdateBootloader.ts +1 -2
  284. package/src/api/device/DeviceWipe.ts +19 -0
  285. package/src/api/evm/EVMSignTypedData.ts +3 -5
  286. package/src/api/evm/legacyV1/getAddress.ts +2 -2
  287. package/src/api/evm/legacyV1/getPublicKey.ts +2 -2
  288. package/src/api/evm/legacyV1/signMessage.ts +2 -2
  289. package/src/api/evm/legacyV1/signTypedData.ts +2 -2
  290. package/src/api/evm/legacyV1/signTypedHash.ts +2 -2
  291. package/src/api/evm/legacyV1/verifyMessage.ts +2 -2
  292. package/src/api/firmware/FirmwareUpdateBaseMethod.ts +21 -7
  293. package/src/api/firmware/getBinary.ts +8 -3
  294. package/src/api/firmware/progressThrottle.ts +44 -0
  295. package/src/api/helpers/batchGetPublickeys.ts +2 -2
  296. package/src/api/helpers/filesystemValidation.ts +61 -0
  297. package/src/api/helpers/paramsValidator.ts +1 -1
  298. package/src/api/helpers/protocolV2FileWrite.ts +193 -0
  299. package/src/api/index.ts +14 -20
  300. package/src/api/kaspa/KaspaSignTransaction.ts +341 -22
  301. package/src/api/kaspa/helpers/TransferSerialize.ts +14 -0
  302. package/src/api/nervos/NervosSignTransaction.ts +2 -2
  303. package/src/api/nexa/NexaSignTransaction.ts +1 -1
  304. package/src/api/protocol-v2/{FactoryGetDeviceInfo.ts → DeviceFactoryInfoGet.ts} +4 -4
  305. package/src/api/protocol-v2/DeviceFactoryInfoSet.ts +32 -0
  306. package/src/api/protocol-v2/DeviceFirmwareUpdate.ts +7 -9
  307. package/src/api/protocol-v2/DeviceGetFirmwareUpdateStatus.ts +41 -6
  308. package/src/api/protocol-v2/DeviceGetOnboardingStatus.ts +6 -4
  309. package/src/api/protocol-v2/DeviceInfoGet.ts +145 -0
  310. package/src/api/protocol-v2/DeviceReboot.ts +5 -3
  311. package/src/api/protocol-v2/DeviceStatusGet.ts +16 -0
  312. package/src/api/protocol-v2/DeviceUploadWallpaper.ts +131 -0
  313. package/src/api/protocol-v2/FilesystemFormat.ts +5 -2
  314. package/src/api/protocol-v2/{FilesystemFixPermission.ts → FilesystemPermissionFix.ts} +3 -3
  315. package/src/api/protocol-v2/Ping.ts +1 -1
  316. package/src/api/protocol-v2/{GetProtoVersion.ts → ProtocolInfoRequest.ts} +3 -3
  317. package/src/api/protocol-v2/helpers.ts +58 -62
  318. package/src/api/ton/TonSignData.ts +1 -5
  319. package/src/api/utils.ts +7 -3
  320. package/src/constants/index.ts +7 -1
  321. package/src/core/RequestQueue.ts +1 -0
  322. package/src/core/deviceEventRegistration.ts +23 -0
  323. package/src/core/index.ts +140 -35
  324. package/src/data/messages/messages-protocol-v2.json +825 -709
  325. package/src/data/messages/messages.json +286 -1
  326. package/src/data-manager/DataManager.ts +13 -6
  327. package/src/data-manager/connectSettings.ts +4 -0
  328. package/src/device/Device.ts +480 -192
  329. package/src/device/DeviceCommands.ts +81 -25
  330. package/src/device/DeviceFeaturesState.ts +25 -0
  331. package/src/device/DevicePool.ts +67 -19
  332. package/src/device/DeviceStateMapper.ts +349 -0
  333. package/src/device/DeviceStateProjector.ts +95 -0
  334. package/src/device/DeviceStateStore.ts +201 -0
  335. package/src/device/DeviceWalletSessionStore.ts +105 -0
  336. package/src/device/cloneDeviceState.ts +39 -0
  337. package/src/device/deviceIdentity.ts +18 -0
  338. package/src/deviceProfile/buildDeviceFeatures.ts +235 -210
  339. package/src/deviceProfile/index.ts +0 -1
  340. package/src/events/device.ts +17 -1
  341. package/src/events/logBlockEvent.ts +8 -1
  342. package/src/events/ui-request.ts +24 -2
  343. package/src/inject.ts +23 -34
  344. package/src/protocols/protocol-v2/deviceSession.ts +24 -0
  345. package/src/protocols/protocol-v2/features.ts +68 -82
  346. package/src/protocols/protocol-v2/firmware.ts +12 -36
  347. package/src/protocols/protocol-v2/index.ts +3 -1
  348. package/src/protocols/protocol-v2/lockedError.ts +10 -0
  349. package/src/protocols/protocol-v2/settingsUnlockPolicy.ts +61 -0
  350. package/src/protocols/protocol-v2/uiInteraction.ts +210 -0
  351. package/src/protocols/protocol-v2/unlockRetry.ts +76 -0
  352. package/src/protocols/protocol-v2/walletSession.ts +107 -0
  353. package/src/types/api/checkAllFirmwareRelease.ts +1 -2
  354. package/src/types/api/deviceSettings.ts +26 -2
  355. package/src/types/api/deviceUnlock.ts +5 -2
  356. package/src/types/api/firmwareUpdate.ts +28 -20
  357. package/src/types/api/getDeviceState.ts +19 -0
  358. package/src/types/api/getFeatures.ts +3 -0
  359. package/src/types/api/getOnekeyFeatures.ts +3 -0
  360. package/src/types/api/getPassphraseState.ts +8 -11
  361. package/src/types/api/index.ts +30 -53
  362. package/src/types/api/kaspaSignTransaction.ts +40 -2
  363. package/src/types/api/openWalletSession.ts +64 -0
  364. package/src/types/api/protocolV2.ts +58 -55
  365. package/src/types/api/sessionCache.ts +14 -0
  366. package/src/types/device.ts +170 -4
  367. package/src/types/params.ts +4 -0
  368. package/src/types/settings.ts +42 -30
  369. package/src/utils/assets.ts +4 -1
  370. package/src/utils/deviceFeaturesCompat.ts +173 -0
  371. package/src/utils/deviceFeaturesUtils.ts +68 -24
  372. package/src/utils/deviceInfoUtils.ts +26 -64
  373. package/src/utils/deviceSettings.ts +161 -39
  374. package/src/utils/deviceVersionUtils.ts +25 -44
  375. package/src/utils/findDefectiveBatchDevice.ts +3 -3
  376. package/src/utils/homescreen.ts +10 -0
  377. package/src/utils/index.ts +21 -1
  378. package/src/utils/networkUtils.ts +270 -14
  379. package/src/utils/pro2Wallpaper.ts +109 -0
  380. package/src/utils/tracing.ts +3 -1
  381. package/dist/api/GetDeviceInfo.d.ts +0 -9
  382. package/dist/api/GetDeviceInfo.d.ts.map +0 -1
  383. package/dist/api/protocol-v2/DevReboot.d.ts +0 -7
  384. package/dist/api/protocol-v2/DevReboot.d.ts.map +0 -1
  385. package/dist/api/protocol-v2/DeviceGetDeviceInfo.d.ts +0 -29
  386. package/dist/api/protocol-v2/DeviceGetDeviceInfo.d.ts.map +0 -1
  387. package/dist/api/protocol-v2/FactoryDeviceInfoSettings.d.ts +0 -7
  388. package/dist/api/protocol-v2/FactoryDeviceInfoSettings.d.ts.map +0 -1
  389. package/dist/api/protocol-v2/FactoryGetDeviceInfo.d.ts +0 -6
  390. package/dist/api/protocol-v2/FactoryGetDeviceInfo.d.ts.map +0 -1
  391. package/dist/api/protocol-v2/FilesystemDiskControl.d.ts +0 -13
  392. package/dist/api/protocol-v2/FilesystemDiskControl.d.ts.map +0 -1
  393. package/dist/api/protocol-v2/FilesystemFixPermission.d.ts.map +0 -1
  394. package/dist/api/protocol-v2/GetProtoVersion.d.ts +0 -6
  395. package/dist/api/protocol-v2/GetProtoVersion.d.ts.map +0 -1
  396. package/dist/deviceProfile/buildDeviceProfile.d.ts +0 -21
  397. package/dist/deviceProfile/buildDeviceProfile.d.ts.map +0 -1
  398. package/dist/types/api/getDeviceInfo.d.ts +0 -85
  399. package/dist/types/api/getDeviceInfo.d.ts.map +0 -1
  400. package/src/api/GetDeviceInfo.ts +0 -145
  401. package/src/api/protocol-v2/DevReboot.ts +0 -24
  402. package/src/api/protocol-v2/DeviceGetDeviceInfo.ts +0 -118
  403. package/src/api/protocol-v2/FactoryDeviceInfoSettings.ts +0 -29
  404. package/src/api/protocol-v2/FilesystemDiskControl.ts +0 -50
  405. package/src/deviceProfile/buildDeviceProfile.ts +0 -334
  406. package/src/types/api/getDeviceInfo.ts +0 -99
@@ -1,4 +1,5 @@
1
1
  import { bytesToHex } from '@noble/hashes/utils';
2
+ import { ERRORS, HardwareError, HardwareErrorCode } from '@onekeyfe/hd-shared';
2
3
 
3
4
  import { UI_REQUEST } from '../../constants/ui-request';
4
5
  import { validatePath } from '../helpers/pathUtils';
@@ -14,11 +15,27 @@ import type {
14
15
  KaspaSignTransactionParams,
15
16
  KaspaSignature,
16
17
  } from '../../types';
17
- import type { TypedCall } from '@onekeyfe/hd-transport';
18
+ import type {
19
+ KaspaInputScriptType,
20
+ KaspaTxRequest,
21
+ KaspaTxRequestSignature,
22
+ TypedCall,
23
+ } from '@onekeyfe/hd-transport';
24
+
25
+ // Streaming only handles plain P2PK scripts; anything else (e.g. KRC20 P2SH)
26
+ // must blind-sign. Absent script means a streaming-only caller.
27
+ const P2PK_SCRIPT = /^(20[0-9a-f]{64}ac|21[0-9a-f]{66}ab)$/i;
28
+
29
+ const isStreamableScript = (script?: string) => !script || P2PK_SCRIPT.test(script);
18
30
 
19
31
  export default class KaspaSignTransaction extends BaseMethod<KaspaSignTransactionParams> {
20
32
  hasBundle = false;
21
33
 
34
+ // Protocols this tx can be signed with; the device picks via its first response.
35
+ supportsLegacy = false;
36
+
37
+ supportsStreaming = false;
38
+
22
39
  init() {
23
40
  this.checkDeviceId = true;
24
41
  this.allowDeviceMode = [...this.allowDeviceMode, UI_REQUEST.NOT_INITIALIZE];
@@ -29,17 +46,17 @@ export default class KaspaSignTransaction extends BaseMethod<KaspaSignTransactio
29
46
  // check payload
30
47
  validateParams(payload, [
31
48
  { name: 'version', type: 'number' },
32
- { name: 'sigHashType', type: 'number', required: true },
49
+ { name: 'sigHashType', type: 'number' },
33
50
  { name: 'inputs', type: 'array', required: true },
34
51
  { name: 'outputs', type: 'array', required: true },
35
52
  { name: 'lockTime', required: true },
36
53
  { name: 'sigOpCount', type: 'number' },
37
54
  { name: 'subNetworkID', type: 'string' },
55
+ { name: 'payload', type: 'hexString' },
56
+ { name: 'refTxs', type: 'array', allowEmpty: true },
38
57
  { name: 'useTweak', type: 'boolean' },
39
58
  ]);
40
59
 
41
- // if(!payload.inputs.length) throw
42
-
43
60
  const inputs: KaspaSignInputParams[] = payload.inputs.map(input => {
44
61
  validateParams(input, [
45
62
  { name: 'path', type: 'string', required: true },
@@ -47,6 +64,7 @@ export default class KaspaSignTransaction extends BaseMethod<KaspaSignTransactio
47
64
  { name: 'outputIndex', type: 'number', required: true },
48
65
  { name: 'sequenceNumber', required: true },
49
66
  ]);
67
+ validateParams(input.output, [{ name: 'satoshis', required: true }]);
50
68
 
51
69
  const addressN = validatePath(input.path, 3);
52
70
 
@@ -57,15 +75,28 @@ export default class KaspaSignTransaction extends BaseMethod<KaspaSignTransactio
57
75
  };
58
76
  });
59
77
 
78
+ payload.refTxs?.forEach(refTx => {
79
+ validateParams(refTx, [
80
+ { name: 'txId', type: 'string', required: true },
81
+ { name: 'version', type: 'number', required: true },
82
+ // Coinbase transactions legitimately have zero inputs.
83
+ { name: 'inputs', type: 'array', required: true, allowEmpty: true },
84
+ { name: 'outputs', type: 'array', required: true, allowEmpty: true },
85
+ { name: 'payload', type: 'hexString' },
86
+ ]);
87
+ });
88
+
60
89
  const outputs: KaspaSignOutputParams[] = payload.outputs.map(output => {
61
90
  validateParams(output, [
62
91
  { name: 'satoshis', required: true },
63
- { name: 'script', type: 'string', required: true },
92
+ { name: 'address', type: 'string' },
93
+ { name: 'script', type: 'string' },
64
94
  { name: 'scriptVersion', type: 'number' },
65
95
  ]);
66
96
 
67
97
  return {
68
98
  ...output,
99
+ addressN: output.addressN ? validatePath(output.addressN, 3) : undefined,
69
100
  scriptVersion: output.scriptVersion ?? 0,
70
101
  };
71
102
  });
@@ -80,8 +111,37 @@ export default class KaspaSignTransaction extends BaseMethod<KaspaSignTransactio
80
111
  sigHashType: payload.sigHashType ?? SignatureType.SIGHASH_ALL | SignatureType.SIGHASH_FORKID,
81
112
  sigOpCount: payload.sigOpCount ?? 1,
82
113
  subNetworkID: payload.subNetworkID ?? bytesToHex(zeroSubnetworkID()),
114
+ gas: payload.gas ?? 0,
83
115
  useTweak: payload.useTweak,
84
116
  };
117
+
118
+ // Legacy prehashes on the host with payload/gas/subnetworkID hardcoded to
119
+ // zero (TransferSerialize), so those rule it out.
120
+ this.supportsLegacy =
121
+ this.params.outputs.every(output => !!output.script) &&
122
+ this.params.inputs.every(input => !!input.output.script) &&
123
+ !this.params.payload &&
124
+ Number(this.params.gas ?? 0) === 0 &&
125
+ /^0*$/.test(this.params.subNetworkID ?? '');
126
+
127
+ // The streaming protocol has no sighash-type field (device signs SIGHASH_ALL).
128
+ const isDefaultSigHashType =
129
+ this.params.sigHashType === SignatureType.SIGHASH_ALL ||
130
+ // eslint-disable-next-line no-bitwise
131
+ this.params.sigHashType === (SignatureType.SIGHASH_ALL | SignatureType.SIGHASH_FORKID);
132
+
133
+ this.supportsStreaming =
134
+ isDefaultSigHashType &&
135
+ this.params.outputs.every(output => !!output.address || !!output.addressN) &&
136
+ this.params.inputs.every(input => isStreamableScript(input.output.script)) &&
137
+ this.params.outputs.every(output => isStreamableScript(output.script));
138
+
139
+ if (!this.supportsLegacy && !this.supportsStreaming) {
140
+ throw ERRORS.TypedError(
141
+ HardwareErrorCode.CallMethodInvalidParameter,
142
+ 'KaspaSignTransaction: outputs require either address/addressN (streaming protocol) or script (legacy protocol)'
143
+ );
144
+ }
85
145
  }
86
146
 
87
147
  getVersionRange() {
@@ -106,6 +166,10 @@ export default class KaspaSignTransaction extends BaseMethod<KaspaSignTransactio
106
166
  };
107
167
  }
108
168
 
169
+ /**
170
+ * Legacy blind-sign flow: run() sent input 0's prehash in raw_message; feed
171
+ * each next prehash via KaspaTxInputAck until KaspaSignedTx.
172
+ */
109
173
  async processTxRequest(
110
174
  typedCall: TypedCall,
111
175
  res: TypedResponseMessage<'KaspaTxInputRequest'> | TypedResponseMessage<'KaspaSignedTx'>,
@@ -136,7 +200,6 @@ export default class KaspaSignTransaction extends BaseMethod<KaspaSignTransactio
136
200
  'KaspaTxInputAck',
137
201
  ['KaspaTxInputRequest', 'KaspaSignedTx'],
138
202
  {
139
- // params.inputs 的 path 可能是字符串或已解析数组,统一归一为 address_n 数组
140
203
  address_n: validatePath(input.path, 3),
141
204
  raw_message: bytesToHex(rawMessage),
142
205
  }
@@ -148,6 +211,190 @@ export default class KaspaSignTransaction extends BaseMethod<KaspaSignTransactio
148
211
  return signature;
149
212
  }
150
213
 
214
+ /**
215
+ * Answer a previous-transaction request (selected by prev_tx_id) from
216
+ * refTxs; the device uses them to verify input amounts.
217
+ */
218
+ async ackPrevRequest(typedCall: TypedCall, request: KaspaTxRequest, requestIndex: number) {
219
+ const prevTxId = (request.prev_tx_id ?? '').toLowerCase();
220
+ const refTx = (this.params.refTxs ?? []).find(tx => tx.txId.toLowerCase() === prevTxId);
221
+ if (!refTx) {
222
+ throw ERRORS.TypedError(
223
+ HardwareErrorCode.CallMethodInvalidParameter,
224
+ `KaspaSignTransaction: device requested previous transaction ${
225
+ prevTxId || '(unknown)'
226
+ }; provide it via refTxs`
227
+ );
228
+ }
229
+
230
+ const requestType = request.request_type;
231
+
232
+ if (requestType === 'KASPA_TX_PREV_META') {
233
+ return typedCall('KaspaTxAckPrevMeta', 'KaspaTxRequest', {
234
+ version: refTx.version,
235
+ input_count: refTx.inputs.length,
236
+ output_count: refTx.outputs.length,
237
+ lock_time: (refTx.lockTime ?? 0) as number,
238
+ subnetwork_id: refTx.subNetworkID ?? bytesToHex(zeroSubnetworkID()),
239
+ gas: (refTx.gas ?? 0) as number,
240
+ payload_length: (refTx.payload ?? '').length / 2,
241
+ });
242
+ }
243
+
244
+ if (requestType === 'KASPA_TX_INPUT') {
245
+ const input = refTx.inputs[requestIndex];
246
+ if (!input) {
247
+ throw ERRORS.TypedError(
248
+ HardwareErrorCode.RuntimeError,
249
+ `KaspaSignTransaction: device requested input ${requestIndex} of previous tx out of range`
250
+ );
251
+ }
252
+ return typedCall('KaspaTxAckPrevInput', 'KaspaTxRequest', {
253
+ previous_outpoint: {
254
+ tx_id: input.prevTxId,
255
+ index: input.outputIndex,
256
+ },
257
+ sequence: input.sequenceNumber as number,
258
+ });
259
+ }
260
+
261
+ if (requestType === 'KASPA_TX_OUTPUT') {
262
+ const output = refTx.outputs[requestIndex];
263
+ if (!output) {
264
+ throw ERRORS.TypedError(
265
+ HardwareErrorCode.RuntimeError,
266
+ `KaspaSignTransaction: device requested output ${requestIndex} of previous tx out of range`
267
+ );
268
+ }
269
+ return typedCall('KaspaTxAckPrevOutput', 'KaspaTxRequest', {
270
+ amount: output.satoshis,
271
+ script_version: output.scriptVersion ?? 0,
272
+ script_public_key: output.script,
273
+ });
274
+ }
275
+
276
+ if (requestType === 'KASPA_TX_PAYLOAD') {
277
+ const payloadHex = refTx.payload ?? '';
278
+ const payloadLength = payloadHex.length / 2;
279
+ const length = request.request_payload_length ?? payloadLength - requestIndex;
280
+ return typedCall('KaspaTxAckPayloadChunk', 'KaspaTxRequest', {
281
+ payload_chunk: payloadHex.substring(requestIndex * 2, (requestIndex + length) * 2),
282
+ });
283
+ }
284
+
285
+ throw ERRORS.TypedError(
286
+ HardwareErrorCode.RuntimeError,
287
+ `KaspaSignTransaction: unknown previous-tx request type ${requestType ?? 'undefined'}`
288
+ );
289
+ }
290
+
291
+ /**
292
+ * Streaming flow (device computes the sighash): the device drives via
293
+ * KaspaTxRequest, asking for inputs/outputs/payload chunks and carrying
294
+ * finished signatures back, until FINISHED. Mirrors BTC signtx.
295
+ */
296
+ async signTxStream(
297
+ typedCall: TypedCall,
298
+ firstResponse: TypedResponseMessage<'KaspaTxRequest'>
299
+ ): Promise<KaspaSignature[]> {
300
+ const { params } = this;
301
+ const signatures: KaspaSignature[] = [];
302
+
303
+ const inputScriptType: KaspaInputScriptType =
304
+ params.scheme === 'ecdsa' ? 'KASPA_SPEND_P2PK_ECDSA' : 'KASPA_SPEND_P2PK_SCHNORR';
305
+
306
+ const saveSignature = (signature?: KaspaTxRequestSignature) => {
307
+ if (signature && typeof signature.signature_index === 'number' && signature.signature) {
308
+ signatures[signature.signature_index] = {
309
+ index: signature.signature_index,
310
+ signature: signature.signature,
311
+ };
312
+ }
313
+ };
314
+
315
+ const payloadHex = params.payload ?? '';
316
+ const payloadLength = payloadHex.length / 2;
317
+
318
+ let response = firstResponse;
319
+
320
+ // eslint-disable-next-line no-constant-condition
321
+ while (true) {
322
+ const request = response.message;
323
+ // Save first so the last input's signature (carried on the FINISHED request) is captured.
324
+ saveSignature(request.signature);
325
+
326
+ const requestType = request.request_type;
327
+ if (requestType === 'KASPA_TX_FINISHED') {
328
+ break;
329
+ }
330
+
331
+ const requestIndex = request.request_index ?? 0;
332
+
333
+ // prev_tx_id selects a previous-transaction request; answer from refTxs.
334
+ if (request.prev_tx_id || requestType === 'KASPA_TX_PREV_META') {
335
+ response = await this.ackPrevRequest(typedCall, request, requestIndex);
336
+ } else if (requestType === 'KASPA_TX_INPUT') {
337
+ const input = params.inputs[requestIndex];
338
+ if (!input) {
339
+ throw ERRORS.TypedError(
340
+ HardwareErrorCode.RuntimeError,
341
+ `KaspaSignTransaction: device requested input ${requestIndex} out of range`
342
+ );
343
+ }
344
+ response = await typedCall('KaspaTxAckInput', 'KaspaTxRequest', {
345
+ address_n: input.path as number[],
346
+ previous_outpoint: {
347
+ tx_id: input.prevTxId,
348
+ index: input.outputIndex,
349
+ },
350
+ amount: input.output.satoshis,
351
+ sequence: input.sequenceNumber as number,
352
+ sig_op_count: input.sigOpCount ?? 1,
353
+ script_type: inputScriptType,
354
+ use_tweak: params.useTweak,
355
+ });
356
+ } else if (requestType === 'KASPA_TX_OUTPUT') {
357
+ const output = params.outputs[requestIndex];
358
+ if (!output) {
359
+ throw ERRORS.TypedError(
360
+ HardwareErrorCode.RuntimeError,
361
+ `KaspaSignTransaction: device requested output ${requestIndex} out of range`
362
+ );
363
+ }
364
+ const isChange = !!output.addressN;
365
+ response = await typedCall('KaspaTxAckOutput', 'KaspaTxRequest', {
366
+ script_type: isChange ? 'KASPA_PAYTOCHANGE' : 'KASPA_PAYTOADDRESS',
367
+ amount: output.satoshis,
368
+ address_n: (output.addressN as number[]) ?? [],
369
+ address: output.address,
370
+ scheme: params.scheme,
371
+ use_tweak: params.useTweak,
372
+ });
373
+ } else if (requestType === 'KASPA_TX_PAYLOAD') {
374
+ const offset = requestIndex;
375
+ const length = request.request_payload_length ?? payloadLength - offset;
376
+ const chunk = payloadHex.substring(offset * 2, (offset + length) * 2);
377
+ response = await typedCall('KaspaTxAckPayloadChunk', 'KaspaTxRequest', {
378
+ payload_chunk: chunk,
379
+ });
380
+ } else {
381
+ throw ERRORS.TypedError(
382
+ HardwareErrorCode.RuntimeError,
383
+ `KaspaSignTransaction: unknown request type ${requestType ?? 'undefined'}`
384
+ );
385
+ }
386
+ }
387
+
388
+ const collected = signatures.filter(Boolean);
389
+ if (collected.length !== params.inputs.length) {
390
+ throw ERRORS.TypedError(
391
+ HardwareErrorCode.RuntimeError,
392
+ `KaspaSignTransaction: expected ${params.inputs.length} signatures, received ${collected.length}`
393
+ );
394
+ }
395
+ return collected;
396
+ }
397
+
151
398
  async run() {
152
399
  this.checkFeatureVersionLimit(
153
400
  // exists use_tweak is false check firmware version
@@ -158,25 +405,97 @@ export default class KaspaSignTransaction extends BaseMethod<KaspaSignTransactio
158
405
  }
159
406
  );
160
407
 
161
- const { raw: rawMessage } = serialize(this.params, 0);
162
- const input = this.params.inputs[0];
163
-
164
408
  const { device, params } = this;
409
+ const payloadHex = params.payload ?? '';
165
410
 
166
- const response = await device.commands.typedCall(
167
- 'KaspaSignTx',
168
- ['KaspaTxInputRequest', 'KaspaSignedTx'],
169
- {
170
- // init() 已把 path 归一为数组,这里再过一遍 validatePath 收窄类型
171
- address_n: validatePath(input.path, 3),
172
- raw_message: bytesToHex(rawMessage),
173
- scheme: params.scheme,
174
- prefix: params.prefix,
175
- input_count: params.inputs.length,
176
- use_tweak: params.useTweak,
411
+ // output_count is the protocol discriminator: attach streaming fields only
412
+ // when the tx can stream. Streaming verification needs refTxs, so without
413
+ // them prefer blind signing when available; a streaming-only tx still
414
+ // streams and fails clearly if the device requests previous txs.
415
+ const hasRefTxs = (params.refTxs?.length ?? 0) > 0;
416
+ const streamingReady = this.supportsStreaming && (hasRefTxs || !this.supportsLegacy);
417
+
418
+ const streamingFields = streamingReady
419
+ ? {
420
+ output_count: params.outputs.length,
421
+ version: params.version,
422
+ lock_time: params.lockTime as number,
423
+ subnetwork_id: params.subNetworkID,
424
+ gas: params.gas as number,
425
+ payload_length: payloadHex.length / 2,
426
+ }
427
+ : {};
428
+
429
+ // raw_message (input 0's prehash) is only computable/correct when legacy-signable.
430
+ const legacyFields = this.supportsLegacy
431
+ ? { raw_message: bytesToHex(serialize(params, 0).raw) }
432
+ : {};
433
+
434
+ // Legacy firmware reads raw_message and skips unknown streaming fields;
435
+ // new firmware streams iff output_count is present.
436
+ let response;
437
+ try {
438
+ response = await device.commands.typedCall(
439
+ 'KaspaSignTx',
440
+ ['KaspaTxRequest', 'KaspaTxInputRequest', 'KaspaSignedTx'],
441
+ {
442
+ address_n: params.inputs[0].path as number[],
443
+ scheme: params.scheme,
444
+ prefix: params.prefix,
445
+ input_count: params.inputs.length,
446
+ use_tweak: params.useTweak,
447
+ ...streamingFields,
448
+ ...legacyFields,
449
+ }
450
+ );
451
+ } catch (error) {
452
+ // Old firmware cannot decode a packet without raw_message
453
+ // (Failure_DataError); map it to an actionable upgrade error.
454
+ if (
455
+ !this.supportsLegacy &&
456
+ error instanceof HardwareError &&
457
+ error.errorCode === HardwareErrorCode.RuntimeError &&
458
+ String(error.message).includes('Failure_DataError')
459
+ ) {
460
+ throw ERRORS.TypedError(
461
+ HardwareErrorCode.CallMethodNeedUpgradeFirmware,
462
+ 'KaspaSignTransaction: this transaction requires firmware with Kaspa streaming support'
463
+ );
177
464
  }
178
- );
465
+ throw error;
466
+ }
467
+
468
+ const typedCall = device.commands.typedCall.bind(device.commands);
469
+
470
+ if (response.type === 'KaspaTxRequest') {
471
+ if (!this.supportsStreaming) {
472
+ throw ERRORS.TypedError(
473
+ HardwareErrorCode.CallMethodInvalidParameter,
474
+ 'KaspaSignTransaction: device firmware uses the streaming protocol; every output requires address or addressN'
475
+ );
476
+ }
477
+ try {
478
+ return await this.signTxStream(typedCall, response);
479
+ } catch (error) {
480
+ // Device rejected our refTxs; the caller decides whether to sign without them.
481
+ if (
482
+ error instanceof HardwareError &&
483
+ String(error.message).toLowerCase().includes('previous transaction id mismatch')
484
+ ) {
485
+ throw ERRORS.TypedError(HardwareErrorCode.KaspaPrevTxIdMismatch, String(error.message));
486
+ }
487
+ throw error;
488
+ }
489
+ }
490
+
491
+ // Legacy answer to a streaming-only packet: no prehash material exists.
492
+ if (!this.supportsLegacy) {
493
+ throw ERRORS.TypedError(
494
+ HardwareErrorCode.RuntimeError,
495
+ 'KaspaSignTransaction: device chose the legacy protocol but the transaction is not legacy-signable'
496
+ );
497
+ }
179
498
 
180
- return this.processTxRequest(device.commands.typedCall.bind(device.commands), response, 0, []);
499
+ return this.processTxRequest(typedCall, response, 0, []);
181
500
  }
182
501
  }
@@ -1,4 +1,6 @@
1
1
  /* eslint-disable @typescript-eslint/no-non-null-assertion */
2
+ import { ERRORS, HardwareErrorCode } from '@onekeyfe/hd-shared';
3
+
2
4
  import { SignatureType } from './SignatureType';
3
5
  import { HashWriter } from './HashWriter';
4
6
 
@@ -76,6 +78,12 @@ function getSigOpCountsHash(transaction: KaspaSignTransactionParams, sighashType
76
78
  function hashTxOut(hashWriter: HashWriter, output: KaspaSignOutputParams) {
77
79
  hashWriter.writeUInt64LE(output.satoshis);
78
80
  hashWriter.writeUInt16LE(0); // TODO: USE REAL SCRIPT VERSION
81
+ if (output.script === undefined) {
82
+ throw ERRORS.TypedError(
83
+ HardwareErrorCode.CallMethodInvalidParameter,
84
+ 'Kaspa legacy sighash requires output.script'
85
+ );
86
+ }
79
87
  hashWriter.writeVarBytes(Buffer.from(output.script, 'hex'));
80
88
  }
81
89
 
@@ -126,6 +134,12 @@ export function serialize(transaction: KaspaSignTransactionParams, inputNumber:
126
134
  const input = transaction.inputs[inputNumber];
127
135
  hashOutpoint(hashWriter, input);
128
136
  hashWriter.writeUInt16LE(0); // TODO: USE REAL SCRIPT VERSION
137
+ if (input.output.script === undefined) {
138
+ throw ERRORS.TypedError(
139
+ HardwareErrorCode.CallMethodInvalidParameter,
140
+ 'Kaspa legacy sighash requires input.output.script'
141
+ );
142
+ }
129
143
  hashWriter.writeVarBytes(Buffer.from(input.output.script, 'hex'));
130
144
  hashWriter.writeUInt64LE(input.output.satoshis);
131
145
  hashWriter.writeUInt64LE(input.sequenceNumber);
@@ -67,8 +67,8 @@ export default class NervosSignTransaction extends BaseMethod<NervosSignTx> {
67
67
  res: TypedResponseMessage<'NervosSignedTx'> | TypedResponseMessage<'NervosTxRequest'>,
68
68
  data: Buffer,
69
69
  offset = 0
70
- // 设备可能在最后一个 NervosTxRequest(无 data_length)里返回签名,
71
- // 该消息没有 address 字段,返回类型如实声明为联合类型
70
+ // The final NervosTxRequest may return a signature without data_length or address,
71
+ // so the result accurately uses a union type.
72
72
  ): Promise<NervosSignedTx | (NervosTxRequest & { path: string })> => {
73
73
  if (res.type === 'NervosSignedTx') {
74
74
  if (!res?.message?.signature) {
@@ -73,7 +73,7 @@ export default class NexaSignTransaction extends BaseMethod<NexaSignTransactionP
73
73
  const nextIndex = res.message.request_index;
74
74
  const input = this.params.inputs[nextIndex];
75
75
  const response = await typedCall('NexaTxInputAck', ['NexaTxInputRequest', 'NexaSignedTx'], {
76
- // path 为字符串形式,归一为 address_n 数组(与 run() 中首个 input 的处理一致)
76
+ // Normalize a string path to address_n, matching the first input handled by run().
77
77
  address_n: validatePath(input.path, 3),
78
78
  raw_message: input.message,
79
79
  });
@@ -1,8 +1,8 @@
1
1
  import { BaseMethod } from '../BaseMethod';
2
2
 
3
- export default class FactoryGetDeviceInfo extends BaseMethod {
3
+ export default class DeviceFactoryInfoGet extends BaseMethod {
4
4
  init() {
5
- // Protocol V2 (Pro2) 专属方法,core 调度层统一做非 V2 设备守卫
5
+ // Protocol V2 (Pro2) only; Core rejects non-V2 devices.
6
6
  this.requireProtocolV2 = true;
7
7
  this.skipForceUpdateCheck = true;
8
8
  this.useDevicePassphraseState = false;
@@ -11,8 +11,8 @@ export default class FactoryGetDeviceInfo extends BaseMethod {
11
11
 
12
12
  async run() {
13
13
  const res = await this.device.commands.typedCall(
14
- 'FactoryGetDeviceInfo',
15
- 'FactoryDeviceInfo',
14
+ 'DeviceFactoryInfoGet',
15
+ 'DeviceFactoryInfo',
16
16
  {}
17
17
  );
18
18
  return Promise.resolve(res.message);
@@ -0,0 +1,32 @@
1
+ import { BaseMethod } from '../BaseMethod';
2
+
3
+ import type { DeviceFactoryInfoSetParams } from './helpers';
4
+
5
+ export default class DeviceFactoryInfoSet extends BaseMethod<DeviceFactoryInfoSetParams> {
6
+ init() {
7
+ // Protocol V2 (Pro2) only; Core rejects non-V2 devices.
8
+ this.requireProtocolV2 = true;
9
+ this.skipForceUpdateCheck = true;
10
+ this.useDevicePassphraseState = false;
11
+ this.params = {
12
+ version: this.payload.version,
13
+ serial_number: this.payload.serial_number,
14
+ burn_in_completed: this.payload.burn_in_completed,
15
+ factory_test_completed: this.payload.factory_test_completed,
16
+ manufacture_time: this.payload.manufacture_time,
17
+ };
18
+ }
19
+
20
+ async run() {
21
+ const res = await this.device.commands.typedCall('DeviceFactoryInfoSet', 'Success', {
22
+ info: {
23
+ version: this.params.version,
24
+ serial_number: this.params.serial_number,
25
+ burn_in_completed: this.params.burn_in_completed,
26
+ factory_test_completed: this.params.factory_test_completed,
27
+ manufacture_time: this.params.manufacture_time,
28
+ },
29
+ });
30
+ return Promise.resolve(res.message);
31
+ }
32
+ }
@@ -13,7 +13,7 @@ import type { DeviceFirmwareUpdateParams } from './helpers';
13
13
 
14
14
  export default class DeviceFirmwareUpdate extends BaseMethod<DeviceFirmwareUpdateParams> {
15
15
  init() {
16
- // Protocol V2 (Pro2) 专属方法,core 调度层统一做非 V2 设备守卫
16
+ // Protocol V2 (Pro2) only; Core rejects non-V2 devices.
17
17
  this.requireProtocolV2 = true;
18
18
  this.skipForceUpdateCheck = true;
19
19
  this.useDevicePassphraseState = false;
@@ -29,7 +29,7 @@ export default class DeviceFirmwareUpdate extends BaseMethod<DeviceFirmwareUpdat
29
29
  const targets = normalizeFirmwareTargets(this.params);
30
30
  try {
31
31
  const res = await this.device.commands.typedCall(
32
- 'DevFirmwareUpdate',
32
+ 'DeviceFirmwareUpdateRequest',
33
33
  PROTOCOL_V2_FIRMWARE_UPDATE_RESPONSE_TYPES,
34
34
  {
35
35
  targets,
@@ -37,25 +37,23 @@ export default class DeviceFirmwareUpdate extends BaseMethod<DeviceFirmwareUpdat
37
37
  {
38
38
  ...PROTOCOL_V2_FIRMWARE_UPDATE_OPTIONS,
39
39
  onIntermediateResponse: (response: MessageFromOneKey) => {
40
- if (response.type !== 'DevFirmwareInstallProgress') return;
41
- const progress = Number(response.message?.progress);
42
- if (!Number.isFinite(progress)) return;
40
+ if (response.type !== 'DeviceFirmwareUpdateStatus') return;
43
41
  this.postMessage(
44
42
  createUiMessage(UI_REQUEST.FIRMWARE_PROGRESS, {
45
43
  device: this.device.toMessageObject() as KnownDevice,
46
- progress: Math.min(Math.max(progress, 0), 100),
44
+ progress: 99,
47
45
  progressType: 'installingFirmware',
48
46
  })
49
47
  );
50
48
  },
51
49
  }
52
50
  );
53
- return Promise.resolve(res.message);
51
+ return res.message;
54
52
  } catch (error) {
55
53
  if (isProtocolV2DeviceDisconnectedError(error)) {
56
- return Promise.resolve({
54
+ return {
57
55
  message: 'Device firmware update started',
58
- });
56
+ };
59
57
  }
60
58
  throw error;
61
59
  }
@@ -1,19 +1,54 @@
1
1
  import { BaseMethod } from '../BaseMethod';
2
+ import { invalidParameter } from '../helpers/filesystemValidation';
2
3
 
3
- export default class DeviceGetFirmwareUpdateStatus extends BaseMethod {
4
+ import type { DeviceFirmwareUpdateStatusGetParams } from './helpers';
5
+ import type { DeviceFirmwareUpdateRecordFields } from '@onekeyfe/hd-transport';
6
+
7
+ const DEVICE_FIRMWARE_UPDATE_STATUS_FIELDS = ['status', 'payload_version', 'path'] as const;
8
+
9
+ function normalizeStatusFields(
10
+ fields: DeviceFirmwareUpdateStatusGetParams['fields']
11
+ ): DeviceFirmwareUpdateRecordFields | undefined {
12
+ if (fields === undefined || fields === null) return undefined;
13
+ if (typeof fields !== 'object' || Array.isArray(fields)) {
14
+ throw invalidParameter('Parameter [fields] must be an object.');
15
+ }
16
+
17
+ const unknownField = Object.keys(fields).find(
18
+ field => !DEVICE_FIRMWARE_UPDATE_STATUS_FIELDS.includes(field as any)
19
+ );
20
+ if (unknownField) {
21
+ throw invalidParameter(`Unsupported firmware update status field: ${unknownField}`);
22
+ }
23
+
24
+ const normalized: DeviceFirmwareUpdateRecordFields = {};
25
+ for (const field of DEVICE_FIRMWARE_UPDATE_STATUS_FIELDS) {
26
+ const value = fields[field];
27
+ if (value !== undefined) {
28
+ if (typeof value !== 'boolean') {
29
+ throw invalidParameter(`Parameter [fields.${field}] must be a boolean.`);
30
+ }
31
+ normalized[field] = value;
32
+ }
33
+ }
34
+ return normalized;
35
+ }
36
+
37
+ export default class DeviceGetFirmwareUpdateStatus extends BaseMethod<DeviceFirmwareUpdateStatusGetParams> {
4
38
  init() {
5
- // Protocol V2 (Pro2) 专属方法,core 调度层统一做非 V2 设备守卫
39
+ // Protocol V2 (Pro2) only; Core rejects non-V2 devices.
6
40
  this.requireProtocolV2 = true;
7
41
  this.skipForceUpdateCheck = true;
8
42
  this.useDevicePassphraseState = false;
9
- this.params = undefined;
43
+ const fields = normalizeStatusFields(this.payload.fields);
44
+ this.params = fields ? { fields } : {};
10
45
  }
11
46
 
12
47
  async run() {
13
48
  const res = await this.device.commands.typedCall(
14
- 'DevGetFirmwareUpdateStatus',
15
- 'DevFirmwareUpdateStatus',
16
- {}
49
+ 'DeviceFirmwareUpdateStatusGet',
50
+ 'DeviceFirmwareUpdateStatus',
51
+ this.params
17
52
  );
18
53
  return Promise.resolve(res.message);
19
54
  }