@onekeyfe/hd-core 1.2.0-alpha.65 → 1.2.0-alpha.66

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 (314) hide show
  1. package/__tests__/AllNetworkGetAddressBase.tracing.test.ts +313 -0
  2. package/__tests__/DeviceCommands.test.ts +59 -13
  3. package/__tests__/DeviceEventRegistration.test.ts +6 -0
  4. package/__tests__/check-all-firmware-release-protocol-v2.test.ts +198 -3
  5. package/__tests__/connectSettings.test.ts +5 -47
  6. package/__tests__/core-initialization.test.ts +23 -0
  7. package/__tests__/device-connector-protocol.test.ts +81 -0
  8. package/__tests__/device-lifecycle-events.test.ts +105 -3
  9. package/__tests__/device-pool-state.test.ts +22 -0
  10. package/__tests__/device-settings.test.ts +39 -18
  11. package/__tests__/device-state-contract.test.ts +1 -0
  12. package/__tests__/device-state-mapper.test.ts +13 -1
  13. package/__tests__/device-utils.test.ts +48 -1
  14. package/__tests__/deviceSettings.test.ts +11 -1
  15. package/__tests__/deviceUploadNft.test.ts +316 -0
  16. package/__tests__/firmware-update/firmware-update-v2-download-before-boot.test.ts +31 -59
  17. package/__tests__/get-device-state.test.ts +132 -12
  18. package/__tests__/homescreen.test.ts +41 -1
  19. package/__tests__/kaspa-use-tweak-pro2.test.ts +2 -2
  20. package/__tests__/kaspaSignTransaction.test.ts +3 -26
  21. package/__tests__/logBlockEvent.test.ts +1 -1
  22. package/__tests__/method-protocol-support.test.ts +19 -0
  23. package/__tests__/open-wallet-session.test.ts +568 -37
  24. package/__tests__/pro2Nft.test.ts +108 -0
  25. package/__tests__/protocol-binding.test.ts +89 -0
  26. package/__tests__/protocol-v2-resources.test.ts +340 -0
  27. package/__tests__/protocol-v2-ui-lifecycle.test.ts +91 -0
  28. package/__tests__/protocol-v2-unlock-policy.test.ts +300 -37
  29. package/__tests__/protocol-v2.test.ts +1506 -1097
  30. package/__tests__/protocolV2FileWrite.test.ts +152 -0
  31. package/__tests__/protocolV2UiInteraction.test.ts +63 -0
  32. package/__tests__/public-pro2-api-boundary.test.ts +1 -0
  33. package/__tests__/search-devices.test.ts +12 -3
  34. package/__tests__/tron-sign-message-init.test.ts +2 -2
  35. package/__tests__/uiProgressThrottle.test.ts +74 -0
  36. package/__tests__/uiPromiseRegistry.test.ts +115 -0
  37. package/dist/api/BaseMethod.d.ts +3 -1
  38. package/dist/api/BaseMethod.d.ts.map +1 -1
  39. package/dist/api/CheckAllFirmwareRelease.d.ts +2 -1
  40. package/dist/api/CheckAllFirmwareRelease.d.ts.map +1 -1
  41. package/dist/api/DetectDeviceConnectProtocol.d.ts +7 -0
  42. package/dist/api/DetectDeviceConnectProtocol.d.ts.map +1 -0
  43. package/dist/api/FirmwareUpdate.d.ts.map +1 -1
  44. package/dist/api/FirmwareUpdateV2.d.ts +0 -11
  45. package/dist/api/FirmwareUpdateV2.d.ts.map +1 -1
  46. package/dist/api/FirmwareUpdateV3.d.ts +3 -7
  47. package/dist/api/FirmwareUpdateV3.d.ts.map +1 -1
  48. package/dist/api/FirmwareUpdateV4.d.ts +13 -27
  49. package/dist/api/FirmwareUpdateV4.d.ts.map +1 -1
  50. package/dist/api/GetPassphraseState.d.ts.map +1 -1
  51. package/dist/api/OpenWalletSession.d.ts.map +1 -1
  52. package/dist/api/SearchDevices.d.ts.map +1 -1
  53. package/dist/api/allnetwork/AllNetworkGetAddressBase.d.ts.map +1 -1
  54. package/dist/api/device/DeviceSettings.d.ts.map +1 -1
  55. package/dist/api/device/DeviceUnlock.d.ts +2 -2
  56. package/dist/api/device/DeviceUnlock.d.ts.map +1 -1
  57. package/dist/api/device/DeviceUpdateBootloader.d.ts +1 -5
  58. package/dist/api/device/DeviceUpdateBootloader.d.ts.map +1 -1
  59. package/dist/api/firmware/FirmwareUpdateBaseMethod.d.ts +4 -11
  60. package/dist/api/firmware/FirmwareUpdateBaseMethod.d.ts.map +1 -1
  61. package/dist/api/firmware/getBinary.d.ts +0 -7
  62. package/dist/api/firmware/getBinary.d.ts.map +1 -1
  63. package/dist/api/firmware/updateBootloader.d.ts +0 -2
  64. package/dist/api/firmware/updateBootloader.d.ts.map +1 -1
  65. package/dist/api/firmware/uploadFirmware.d.ts +1 -9
  66. package/dist/api/firmware/uploadFirmware.d.ts.map +1 -1
  67. package/dist/api/helpers/protocolV2FileWrite.d.ts +9 -0
  68. package/dist/api/helpers/protocolV2FileWrite.d.ts.map +1 -1
  69. package/dist/api/index.d.ts +2 -0
  70. package/dist/api/index.d.ts.map +1 -1
  71. package/dist/api/kaspa/KaspaGetAddress.d.ts +1 -1
  72. package/dist/api/kaspa/KaspaSignTransaction.d.ts +1 -1
  73. package/dist/api/kaspa/KaspaSignTransaction.d.ts.map +1 -1
  74. package/dist/api/polkadot/PolkadotGetAddress.d.ts +1 -1
  75. package/dist/api/polkadot/networks.d.ts +1 -1
  76. package/dist/api/protocol-v2/DeviceUploadNft.d.ts +31 -0
  77. package/dist/api/protocol-v2/DeviceUploadNft.d.ts.map +1 -0
  78. package/dist/api/protocol-v2/ProtocolInfoRequest.d.ts.map +1 -1
  79. package/dist/api/protocol-v2/helpers.d.ts.map +1 -1
  80. package/dist/api/solana/SolSignMessage.d.ts +1 -1
  81. package/dist/api/solana/SolSignOffchainMessage.d.ts +1 -1
  82. package/dist/api/solana/SolSignTransaction.d.ts +2 -2
  83. package/dist/api/stellar/StellarSignTransaction.d.ts +1 -1
  84. package/dist/api/sui/SuiGetAddress.d.ts +1 -1
  85. package/dist/api/sui/SuiGetPublicKey.d.ts +1 -1
  86. package/dist/api/sui/SuiSignMessage.d.ts +1 -1
  87. package/dist/api/sui/SuiSignTransaction.d.ts +1 -1
  88. package/dist/api/ton/TonGetAddress.d.ts +1 -1
  89. package/dist/api/ton/TonSignMessage.d.ts +1 -1
  90. package/dist/api/ton/TonSignProof.d.ts +1 -1
  91. package/dist/api/tron/TronSignMessage.d.ts +2 -2
  92. package/dist/api/tron/TronSignTransaction.d.ts +1 -1
  93. package/dist/core/deviceEventRegistration.d.ts +2 -0
  94. package/dist/core/deviceEventRegistration.d.ts.map +1 -1
  95. package/dist/core/index.d.ts.map +1 -1
  96. package/dist/core/uiPromiseRegistry.d.ts +6 -0
  97. package/dist/core/uiPromiseRegistry.d.ts.map +1 -0
  98. package/dist/data-manager/DataManager.d.ts +9 -4
  99. package/dist/data-manager/DataManager.d.ts.map +1 -1
  100. package/dist/data-manager/TransportManager.d.ts.map +1 -1
  101. package/dist/data-manager/connectSettings.d.ts.map +1 -1
  102. package/dist/device/Device.d.ts +29 -6
  103. package/dist/device/Device.d.ts.map +1 -1
  104. package/dist/device/DeviceCommands.d.ts +4 -4
  105. package/dist/device/DeviceCommands.d.ts.map +1 -1
  106. package/dist/device/DeviceConnector.d.ts +2 -1
  107. package/dist/device/DeviceConnector.d.ts.map +1 -1
  108. package/dist/device/DevicePool.d.ts.map +1 -1
  109. package/dist/deviceProfile/protocolV2DeviceIdentity.d.ts.map +1 -1
  110. package/dist/events/device.d.ts +4 -0
  111. package/dist/events/device.d.ts.map +1 -1
  112. package/dist/events/logBlockEvent.d.ts.map +1 -1
  113. package/dist/events/ui-promise.d.ts +4 -2
  114. package/dist/events/ui-promise.d.ts.map +1 -1
  115. package/dist/events/ui-request.d.ts +31 -2
  116. package/dist/events/ui-request.d.ts.map +1 -1
  117. package/dist/events/ui-response.d.ts +10 -2
  118. package/dist/events/ui-response.d.ts.map +1 -1
  119. package/dist/index.d.ts +243 -248
  120. package/dist/index.d.ts.map +1 -1
  121. package/dist/index.js +3051 -3774
  122. package/dist/inject.d.ts +6 -1
  123. package/dist/inject.d.ts.map +1 -1
  124. package/dist/lowLevelInject.d.ts.map +1 -1
  125. package/dist/protocols/protocol-v2/features.d.ts +0 -4
  126. package/dist/protocols/protocol-v2/features.d.ts.map +1 -1
  127. package/dist/protocols/protocol-v2/firmware.d.ts.map +1 -1
  128. package/dist/protocols/protocol-v2/resources.d.ts +30 -0
  129. package/dist/protocols/protocol-v2/resources.d.ts.map +1 -0
  130. package/dist/protocols/protocol-v2/uiInteraction.d.ts +7 -4
  131. package/dist/protocols/protocol-v2/uiInteraction.d.ts.map +1 -1
  132. package/dist/protocols/protocol-v2/unlockPolicy.d.ts +1 -3
  133. package/dist/protocols/protocol-v2/unlockPolicy.d.ts.map +1 -1
  134. package/dist/protocols/protocol-v2/unlockPolicyRunner.d.ts +22 -0
  135. package/dist/protocols/protocol-v2/unlockPolicyRunner.d.ts.map +1 -0
  136. package/dist/protocols/protocol-v2/walletSession.d.ts +6 -1
  137. package/dist/protocols/protocol-v2/walletSession.d.ts.map +1 -1
  138. package/dist/topLevelInject.d.ts.map +1 -1
  139. package/dist/types/api/checkAllFirmwareRelease.d.ts +3 -5
  140. package/dist/types/api/checkAllFirmwareRelease.d.ts.map +1 -1
  141. package/dist/types/api/detectDeviceConnectProtocol.d.ts +4 -0
  142. package/dist/types/api/detectDeviceConnectProtocol.d.ts.map +1 -0
  143. package/dist/types/api/deviceUnlock.d.ts +5 -1
  144. package/dist/types/api/deviceUnlock.d.ts.map +1 -1
  145. package/dist/types/api/deviceUpdateBootloader.d.ts +0 -6
  146. package/dist/types/api/deviceUpdateBootloader.d.ts.map +1 -1
  147. package/dist/types/api/export.d.ts +2 -4
  148. package/dist/types/api/export.d.ts.map +1 -1
  149. package/dist/types/api/firmwareUpdate.d.ts +4 -71
  150. package/dist/types/api/firmwareUpdate.d.ts.map +1 -1
  151. package/dist/types/api/index.d.ts +7 -10
  152. package/dist/types/api/index.d.ts.map +1 -1
  153. package/dist/types/api/protocolV2.d.ts +3 -0
  154. package/dist/types/api/protocolV2.d.ts.map +1 -1
  155. package/dist/types/device.d.ts +2 -2
  156. package/dist/types/device.d.ts.map +1 -1
  157. package/dist/types/params.d.ts +1 -0
  158. package/dist/types/params.d.ts.map +1 -1
  159. package/dist/types/settings.d.ts +38 -21
  160. package/dist/types/settings.d.ts.map +1 -1
  161. package/dist/utils/deviceFeaturesCompat.d.ts +0 -1
  162. package/dist/utils/deviceFeaturesCompat.d.ts.map +1 -1
  163. package/dist/utils/deviceFeaturesUtils.d.ts +4 -0
  164. package/dist/utils/deviceFeaturesUtils.d.ts.map +1 -1
  165. package/dist/utils/deviceInfoUtils.d.ts.map +1 -1
  166. package/dist/utils/deviceSettings.d.ts.map +1 -1
  167. package/dist/utils/homescreen.d.ts +4 -0
  168. package/dist/utils/homescreen.d.ts.map +1 -1
  169. package/dist/utils/index.d.ts +1 -1
  170. package/dist/utils/index.d.ts.map +1 -1
  171. package/dist/utils/patch.d.ts +1 -1
  172. package/dist/utils/patch.d.ts.map +1 -1
  173. package/dist/utils/pro2Nft.d.ts +31 -0
  174. package/dist/utils/pro2Nft.d.ts.map +1 -0
  175. package/dist/utils/pro2Wallpaper.d.ts +10 -0
  176. package/dist/utils/pro2Wallpaper.d.ts.map +1 -1
  177. package/dist/utils/uiProgressThrottle.d.ts +3 -0
  178. package/dist/utils/uiProgressThrottle.d.ts.map +1 -0
  179. package/package.json +4 -4
  180. package/src/api/BaseMethod.ts +8 -10
  181. package/src/api/CheckAllFirmwareRelease.ts +59 -60
  182. package/src/api/DetectDeviceConnectProtocol.ts +18 -0
  183. package/src/api/FirmwareUpdate.ts +7 -15
  184. package/src/api/FirmwareUpdateV2.ts +126 -316
  185. package/src/api/FirmwareUpdateV3.ts +63 -265
  186. package/src/api/FirmwareUpdateV4.ts +597 -1005
  187. package/src/api/GetPassphraseState.ts +7 -1
  188. package/src/api/OpenWalletSession.ts +71 -17
  189. package/src/api/SearchDevices.ts +3 -1
  190. package/src/api/allnetwork/AllNetworkGetAddress.ts +21 -21
  191. package/src/api/allnetwork/AllNetworkGetAddressBase.ts +36 -11
  192. package/src/api/device/DeviceSettings.ts +5 -4
  193. package/src/api/device/DeviceUnlock.ts +8 -3
  194. package/src/api/device/DeviceUpdateBootloader.ts +6 -125
  195. package/src/api/firmware/FirmwareUpdateBaseMethod.ts +27 -83
  196. package/src/api/firmware/updateBootloader.ts +4 -19
  197. package/src/api/firmware/uploadFirmware.ts +39 -144
  198. package/src/api/helpers/protocolV2FileWrite.ts +202 -63
  199. package/src/api/index.ts +2 -0
  200. package/src/api/kaspa/KaspaGetAddress.ts +1 -1
  201. package/src/api/kaspa/KaspaSignTransaction.ts +2 -13
  202. package/src/api/polkadot/networks.ts +3 -3
  203. package/src/api/protocol-v2/DeviceUploadNft.ts +197 -0
  204. package/src/api/protocol-v2/ProtocolInfoRequest.ts +3 -1
  205. package/src/api/protocol-v2/helpers.ts +1 -1
  206. package/src/api/solana/SolSignMessage.ts +1 -1
  207. package/src/api/solana/SolSignOffchainMessage.ts +1 -1
  208. package/src/api/solana/SolSignTransaction.ts +2 -2
  209. package/src/api/sui/SuiGetAddress.ts +1 -1
  210. package/src/api/sui/SuiGetPublicKey.ts +1 -1
  211. package/src/api/sui/SuiSignMessage.ts +1 -1
  212. package/src/api/sui/SuiSignTransaction.ts +1 -1
  213. package/src/api/ton/TonGetAddress.ts +1 -1
  214. package/src/api/ton/TonSignMessage.ts +1 -1
  215. package/src/api/ton/TonSignProof.ts +1 -1
  216. package/src/api/tron/TronSignMessage.ts +2 -2
  217. package/src/api/tron/TronSignTransaction.ts +1 -1
  218. package/src/core/deviceEventRegistration.ts +4 -0
  219. package/src/core/index.ts +213 -111
  220. package/src/core/uiPromiseRegistry.ts +63 -0
  221. package/src/data/messages/messages-protocol-v2.json +25 -0
  222. package/src/data-manager/DataManager.ts +113 -41
  223. package/src/data-manager/TransportManager.ts +6 -0
  224. package/src/data-manager/connectSettings.ts +0 -11
  225. package/src/device/Device.ts +274 -49
  226. package/src/device/DeviceCommands.ts +31 -4
  227. package/src/device/DeviceConnector.ts +33 -13
  228. package/src/device/DevicePool.ts +21 -7
  229. package/src/deviceProfile/buildDeviceFeatures.ts +2 -2
  230. package/src/deviceProfile/protocolV2DeviceIdentity.ts +3 -0
  231. package/src/events/device.ts +4 -0
  232. package/src/events/logBlockEvent.ts +1 -0
  233. package/src/events/ui-promise.ts +4 -2
  234. package/src/events/ui-request.ts +36 -2
  235. package/src/events/ui-response.ts +12 -2
  236. package/src/index.ts +0 -5
  237. package/src/inject.ts +60 -24
  238. package/src/lowLevelInject.ts +7 -8
  239. package/src/protocols/protocol-v2/features.ts +10 -7
  240. package/src/protocols/protocol-v2/firmware.ts +2 -0
  241. package/src/protocols/protocol-v2/resources.ts +390 -0
  242. package/src/protocols/protocol-v2/uiInteraction.ts +46 -6
  243. package/src/protocols/protocol-v2/unlockPolicy.ts +1 -105
  244. package/src/protocols/protocol-v2/unlockPolicyRunner.ts +131 -0
  245. package/src/protocols/protocol-v2/walletSession.ts +214 -36
  246. package/src/topLevelInject.ts +7 -8
  247. package/src/types/api/checkAllFirmwareRelease.ts +3 -5
  248. package/src/types/api/detectDeviceConnectProtocol.ts +6 -0
  249. package/src/types/api/deviceUnlock.ts +12 -1
  250. package/src/types/api/deviceUpdateBootloader.ts +0 -6
  251. package/src/types/api/export.ts +1 -18
  252. package/src/types/api/firmwareUpdate.ts +6 -79
  253. package/src/types/api/index.ts +13 -14
  254. package/src/types/api/protocolV2.ts +13 -0
  255. package/src/types/device.ts +15 -3
  256. package/src/types/params.ts +7 -1
  257. package/src/types/settings.ts +60 -22
  258. package/src/utils/deviceFeaturesCompat.ts +5 -6
  259. package/src/utils/deviceFeaturesUtils.ts +14 -3
  260. package/src/utils/deviceInfoUtils.ts +2 -0
  261. package/src/utils/deviceSettings.ts +3 -0
  262. package/src/utils/homescreen.ts +32 -6
  263. package/src/utils/index.ts +6 -1
  264. package/src/utils/pro2Nft.ts +142 -0
  265. package/src/utils/pro2Wallpaper.ts +35 -8
  266. package/src/utils/uiProgressThrottle.ts +63 -0
  267. package/__tests__/device-initialize-timeout.test.ts +0 -56
  268. package/__tests__/firmware-update/check-all-firmware-release.test.ts +0 -175
  269. package/__tests__/firmware-update/firmware-artifact-source.test.ts +0 -119
  270. package/__tests__/firmware-update/firmware-host-binding.test.ts +0 -70
  271. package/__tests__/firmware-update/firmware-preparation-error.test.ts +0 -27
  272. package/__tests__/firmware-update/firmware-update-bootloader-poll.test.ts +0 -200
  273. package/__tests__/firmware-update/firmware-update-capabilities.test.ts +0 -13
  274. package/__tests__/firmware-update/firmware-update-plan-bootloader-identity.test.ts +0 -394
  275. package/__tests__/firmware-update/firmware-update-plan.test.ts +0 -593
  276. package/__tests__/firmware-update/firmware-update-prepared-plan.test.ts +0 -213
  277. package/__tests__/firmware-update/firmware-update-v3-reconnect.test.ts +0 -58
  278. package/__tests__/firmware-update/firmware-upload-source.test.ts +0 -70
  279. package/dist/api/firmware/FirmwareArtifactSource.d.ts +0 -25
  280. package/dist/api/firmware/FirmwareArtifactSource.d.ts.map +0 -1
  281. package/dist/api/firmware/FirmwareHostBinding.d.ts +0 -6
  282. package/dist/api/firmware/FirmwareHostBinding.d.ts.map +0 -1
  283. package/dist/api/firmware/FirmwarePreparationError.d.ts +0 -3
  284. package/dist/api/firmware/FirmwarePreparationError.d.ts.map +0 -1
  285. package/dist/api/firmware/FirmwareUpdateCapabilities.d.ts +0 -3
  286. package/dist/api/firmware/FirmwareUpdateCapabilities.d.ts.map +0 -1
  287. package/dist/api/firmware/FirmwareUpdatePlan.d.ts +0 -25
  288. package/dist/api/firmware/FirmwareUpdatePlan.d.ts.map +0 -1
  289. package/dist/api/firmware/FirmwareUpdatePreparedPlan.d.ts +0 -32
  290. package/dist/api/firmware/FirmwareUpdatePreparedPlan.d.ts.map +0 -1
  291. package/dist/api/firmware/progressThrottle.d.ts +0 -3
  292. package/dist/api/firmware/progressThrottle.d.ts.map +0 -1
  293. package/dist/protocols/protocol-v2/lockedError.d.ts +0 -2
  294. package/dist/protocols/protocol-v2/lockedError.d.ts.map +0 -1
  295. package/dist/protocols/protocol-v2/unlockRetry.d.ts +0 -10
  296. package/dist/protocols/protocol-v2/unlockRetry.d.ts.map +0 -1
  297. package/dist/types/api/firmwareUpdateCapabilities.d.ts +0 -9
  298. package/dist/types/api/firmwareUpdateCapabilities.d.ts.map +0 -1
  299. package/dist/types/api/firmwareUpdatePlan.d.ts +0 -28
  300. package/dist/types/api/firmwareUpdatePlan.d.ts.map +0 -1
  301. package/dist/types/api/firmwareUpdatePreparedPlan.d.ts +0 -42
  302. package/dist/types/api/firmwareUpdatePreparedPlan.d.ts.map +0 -1
  303. package/src/api/firmware/FirmwareArtifactSource.ts +0 -278
  304. package/src/api/firmware/FirmwareHostBinding.ts +0 -100
  305. package/src/api/firmware/FirmwarePreparationError.ts +0 -12
  306. package/src/api/firmware/FirmwareUpdateCapabilities.ts +0 -9
  307. package/src/api/firmware/FirmwareUpdatePlan.ts +0 -772
  308. package/src/api/firmware/FirmwareUpdatePreparedPlan.ts +0 -449
  309. package/src/api/firmware/progressThrottle.ts +0 -44
  310. package/src/protocols/protocol-v2/lockedError.ts +0 -10
  311. package/src/protocols/protocol-v2/unlockRetry.ts +0 -109
  312. package/src/types/api/firmwareUpdateCapabilities.ts +0 -9
  313. package/src/types/api/firmwareUpdatePlan.ts +0 -38
  314. package/src/types/api/firmwareUpdatePreparedPlan.ts +0 -53
@@ -5,9 +5,12 @@ import {
5
5
  import { ERRORS, HardwareErrorCode } from '@onekeyfe/hd-shared';
6
6
 
7
7
  import { DataManager } from '../../data-manager';
8
+ import { LoggerNames, getLogger } from '../../utils/logger';
8
9
 
9
10
  import type { DeviceCommands } from '../../device/DeviceCommands';
10
11
 
12
+ const Log = getLogger(LoggerNames.Method);
13
+
11
14
  export type ProtocolV2FileWriteData = ArrayBuffer | Uint8Array | Blob | string;
12
15
 
13
16
  export type ProtocolV2FileWriteProgress = {
@@ -18,6 +21,12 @@ export type ProtocolV2FileWriteProgress = {
18
21
  elapsedMs: number;
19
22
  };
20
23
 
24
+ export type ProtocolV2FileWriteChunkContext = {
25
+ offset: number;
26
+ chunkLength: number;
27
+ totalSize: number;
28
+ };
29
+
21
30
  export type ProtocolV2FileWriteOptions = {
22
31
  commands: Pick<DeviceCommands, 'typedCall'>;
23
32
  path: string;
@@ -30,20 +39,63 @@ export type ProtocolV2FileWriteOptions = {
30
39
  append?: boolean;
31
40
  uiPercentage?: number;
32
41
  timeoutMs?: number;
42
+ writeWithResponse?: boolean;
33
43
  maxChunkRetries?: number;
44
+ paceMs?: number;
34
45
  throwIfAborted?: () => void;
46
+ getUiPercentage?: (context: ProtocolV2FileWriteChunkContext) => number | undefined;
35
47
  onProgress?: (progress: ProtocolV2FileWriteProgress) => void;
36
48
  };
37
49
 
38
50
  const MIN_FILE_CHUNK_SIZE = 64;
51
+ const FILE_TRANSFER_RATE_WINDOW_MS = 1000;
52
+ const FILE_TRANSFER_LOG_INTERVAL_MS = 10_000;
53
+ const SESSION_ERROR = 'session not found';
54
+
55
+ function formatFileTransferRate(bytesPerSecond: number) {
56
+ return (Math.max(bytesPerSecond, 0) / 1024).toFixed(2);
57
+ }
58
+
59
+ function getAverageFileTransferRate(transferredBytes: number, elapsedMs: number) {
60
+ if (elapsedMs <= 0) return 0;
61
+ return Math.round((Math.max(transferredBytes, 0) / elapsedMs) * 1000);
62
+ }
39
63
 
40
- function isRetryableFileWriteTimeout(error: unknown) {
64
+ function getFileTransferTransport() {
65
+ const env = DataManager.getSettings('env');
66
+ return env && DataManager.isBleConnect(env) ? 'BLE' : String(env ?? 'unknown');
67
+ }
68
+
69
+ function logFileTransferMetrics({
70
+ transport,
71
+ status,
72
+ transferredBytes,
73
+ totalBytes,
74
+ elapsedMs,
75
+ rateBytesPerSecond,
76
+ }: {
77
+ transport: string;
78
+ status: 'progress' | 'completed' | 'failed';
79
+ transferredBytes: number;
80
+ totalBytes: number;
81
+ elapsedMs: number;
82
+ rateBytesPerSecond: number;
83
+ }) {
84
+ Log.log(
85
+ `[FileWrite] metrics transport=${transport} status=${status} bytes=${transferredBytes}/${totalBytes} elapsed=${(
86
+ elapsedMs / 1000
87
+ ).toFixed(2)}s speed=${formatFileTransferRate(rateBytesPerSecond)} KiB/s`
88
+ );
89
+ }
90
+
91
+ export function isProtocolV2ResponseTimeout(error: unknown) {
41
92
  if (!error || typeof error !== 'object') return false;
42
- const candidate = error as { errorCode?: number; code?: number; message?: string };
93
+ const candidate = error as { errorCode?: number; code?: number | string; message?: string };
43
94
  const code = candidate.errorCode ?? candidate.code;
44
95
  return (
45
96
  code === HardwareErrorCode.BleTimeoutError ||
46
- /Lowlevel response timeout/i.test(candidate.message ?? '')
97
+ code === 'response-timeout' ||
98
+ /(?:BLE|Lowlevel|Protocol V2) response timeout/i.test(candidate.message ?? '')
47
99
  );
48
100
  }
49
101
 
@@ -119,75 +171,162 @@ export async function writeProtocolV2File(options: ProtocolV2FileWriteOptions) {
119
171
  let chunks = 0;
120
172
  let lastMessage: Record<string, unknown> | undefined;
121
173
  const startTime = Date.now();
174
+ let rateWindowStartedAt = startTime;
175
+ let rateWindowStartedBytes = 0;
176
+ let rateBytesPerSecond: number | undefined;
177
+ let lastConfirmedAt = startTime;
178
+ let logWindowStartedAt = startTime;
179
+ let logWindowStartedBytes = 0;
180
+ const transport = getFileTransferTransport();
122
181
 
123
- while (written < dataLength) {
124
- options.throwIfAborted?.();
125
- const chunk = data.slice(written, Math.min(written + chunkSize, dataLength));
126
- const offset = startOffset + written;
127
- const progress =
128
- options.uiPercentage ??
129
- getDeviceTransferProgress(offset, offset + chunk.byteLength, totalSize);
130
- const request = {
131
- file: { path: options.path, offset, total_size: totalSize, data: chunk },
132
- overwrite: chunks === 0 ? options.overwrite ?? false : false,
133
- append: options.append ?? false,
134
- ui_percentage: progress,
135
- };
136
- const maxChunkRetries = Math.max(Math.floor(options.maxChunkRetries ?? 0), 0);
137
- let retryCount = 0;
138
- let response;
139
- let isWritePending = true;
140
- while (isWritePending) {
141
- try {
142
- response = await options.commands.typedCall(
143
- 'FilesystemFileWrite',
144
- 'FilesystemFile',
145
- request,
146
- { timeoutMs: options.timeoutMs }
182
+ try {
183
+ while (written < dataLength) {
184
+ options.throwIfAborted?.();
185
+ const chunk = data.slice(written, Math.min(written + chunkSize, dataLength));
186
+ const offset = startOffset + written;
187
+ const progress =
188
+ options.uiPercentage ??
189
+ options.getUiPercentage?.({
190
+ offset,
191
+ chunkLength: chunk.byteLength,
192
+ totalSize,
193
+ }) ??
194
+ getDeviceTransferProgress(offset, offset + chunk.byteLength, totalSize);
195
+ const request = {
196
+ file: { path: options.path, offset, total_size: totalSize, data: chunk },
197
+ overwrite: chunks === 0 ? options.overwrite ?? false : false,
198
+ append: options.append ?? false,
199
+ ui_percentage: progress,
200
+ };
201
+ const maxChunkRetries = Math.max(Math.floor(options.maxChunkRetries ?? 0), 0);
202
+ let retryCount = 0;
203
+ let response;
204
+ let isWritePending = true;
205
+ while (isWritePending) {
206
+ try {
207
+ const callOptions =
208
+ options.writeWithResponse === undefined
209
+ ? { timeoutMs: options.timeoutMs }
210
+ : {
211
+ ...(options.timeoutMs === undefined ? {} : { timeoutMs: options.timeoutMs }),
212
+ writeWithResponse: options.writeWithResponse,
213
+ };
214
+ response = await options.commands.typedCall(
215
+ 'FilesystemFileWrite',
216
+ 'FilesystemFile',
217
+ request,
218
+ callOptions
219
+ );
220
+ isWritePending = false;
221
+ } catch (error) {
222
+ if (retryCount >= maxChunkRetries || !isProtocolV2ResponseTimeout(error)) throw error;
223
+ retryCount += 1;
224
+ options.throwIfAborted?.();
225
+ }
226
+ }
227
+ if (!response) {
228
+ throw ERRORS.TypedError(
229
+ HardwareErrorCode.RuntimeError,
230
+ 'FilesystemFileWrite completed without a response'
147
231
  );
148
- isWritePending = false;
149
- } catch (error) {
150
- if (retryCount >= maxChunkRetries || !isRetryableFileWriteTimeout(error)) throw error;
151
- retryCount += 1;
152
- options.throwIfAborted?.();
232
+ }
233
+ const responseType = (response as { type?: string }).type;
234
+ if (responseType && responseType !== 'FilesystemFile') {
235
+ const responseError = (response as { message?: { error?: unknown } }).message?.error;
236
+ if (typeof responseError === 'string' && responseError.includes(SESSION_ERROR)) {
237
+ throw ERRORS.TypedError(HardwareErrorCode.RuntimeError, SESSION_ERROR);
238
+ }
239
+ throw ERRORS.TypedError(
240
+ HardwareErrorCode.RuntimeError,
241
+ `FilesystemFileWrite received unexpected response ${responseType}`
242
+ );
243
+ }
244
+ options.throwIfAborted?.();
245
+ lastMessage = response.message;
246
+ const rawProcessedByte = response.message?.processed_byte;
247
+ const processedByte = Number(rawProcessedByte);
248
+ if (
249
+ rawProcessedByte !== undefined &&
250
+ (!Number.isFinite(processedByte) ||
251
+ processedByte <= offset ||
252
+ processedByte > offset + chunk.byteLength)
253
+ ) {
254
+ throw ERRORS.TypedError(
255
+ HardwareErrorCode.RuntimeError,
256
+ `FilesystemFileWrite invalid processed_byte ${processedByte}`
257
+ );
258
+ }
259
+ written =
260
+ rawProcessedByte === undefined ? written + chunk.byteLength : processedByte - startOffset;
261
+ chunks += 1;
262
+ const now = Date.now();
263
+ lastConfirmedAt = now;
264
+ const elapsedMs = now - startTime;
265
+ const transferredBytes = Math.min(written, dataLength);
266
+ const rateWindowElapsedMs = now - rateWindowStartedAt;
267
+ if (rateWindowElapsedMs >= FILE_TRANSFER_RATE_WINDOW_MS) {
268
+ const rateWindowBytes = Math.max(transferredBytes - rateWindowStartedBytes, 0);
269
+ rateBytesPerSecond = Math.round((rateWindowBytes / rateWindowElapsedMs) * 1000);
270
+ rateWindowStartedAt = now;
271
+ rateWindowStartedBytes = transferredBytes;
272
+ } else if (rateBytesPerSecond === undefined && elapsedMs > 0) {
273
+ rateBytesPerSecond = Math.round((transferredBytes / elapsedMs) * 1000);
274
+ }
275
+ options.onProgress?.({
276
+ progress: getConfirmedProgress(startOffset + written, totalSize, written, dataLength),
277
+ transferredBytes,
278
+ totalBytes: dataLength,
279
+ rateBytesPerSecond,
280
+ elapsedMs,
281
+ });
282
+ const logWindowElapsedMs = now - logWindowStartedAt;
283
+ if (logWindowElapsedMs >= FILE_TRANSFER_LOG_INTERVAL_MS && transferredBytes < dataLength) {
284
+ const logWindowBytes = Math.max(transferredBytes - logWindowStartedBytes, 0);
285
+ logFileTransferMetrics({
286
+ transport,
287
+ status: 'progress',
288
+ transferredBytes,
289
+ totalBytes: dataLength,
290
+ elapsedMs,
291
+ rateBytesPerSecond: getAverageFileTransferRate(logWindowBytes, logWindowElapsedMs),
292
+ });
293
+ logWindowStartedAt = now;
294
+ logWindowStartedBytes = transferredBytes;
295
+ }
296
+ if (options.paceMs && options.paceMs > 0) {
297
+ await new Promise(resolve => {
298
+ setTimeout(resolve, options.paceMs);
299
+ });
153
300
  }
154
301
  }
155
- if (!response) {
156
- throw ERRORS.TypedError(
157
- HardwareErrorCode.RuntimeError,
158
- 'FilesystemFileWrite completed without a response'
159
- );
160
- }
161
- options.throwIfAborted?.();
162
- lastMessage = response.message;
163
- const rawProcessedByte = response.message?.processed_byte;
164
- const processedByte = Number(rawProcessedByte);
165
- if (
166
- rawProcessedByte !== undefined &&
167
- (!Number.isFinite(processedByte) ||
168
- processedByte <= offset ||
169
- processedByte > offset + chunk.byteLength)
170
- ) {
171
- throw ERRORS.TypedError(
172
- HardwareErrorCode.RuntimeError,
173
- `FilesystemFileWrite invalid processed_byte ${processedByte}`
174
- );
175
- }
176
- written =
177
- rawProcessedByte === undefined ? written + chunk.byteLength : processedByte - startOffset;
178
- chunks += 1;
179
- const elapsedMs = Date.now() - startTime;
180
- const transferredBytes = Math.min(written, dataLength);
181
- options.onProgress?.({
182
- progress: getConfirmedProgress(startOffset + written, totalSize, written, dataLength),
183
- transferredBytes,
302
+ } catch (error) {
303
+ const now = Date.now();
304
+ const elapsedMs = Math.max(now - startTime, 0);
305
+ const logWindowElapsedMs = Math.max(now - logWindowStartedAt, 0);
306
+ const logWindowBytes = Math.max(written - logWindowStartedBytes, 0);
307
+ logFileTransferMetrics({
308
+ transport,
309
+ status: 'failed',
310
+ transferredBytes: written,
184
311
  totalBytes: dataLength,
185
- rateBytesPerSecond:
186
- elapsedMs > 0 ? Math.round((transferredBytes / elapsedMs) * 1000) : undefined,
187
312
  elapsedMs,
313
+ rateBytesPerSecond: getAverageFileTransferRate(logWindowBytes, logWindowElapsedMs),
188
314
  });
315
+ throw error;
189
316
  }
190
317
 
318
+ const elapsedMs = Math.max(lastConfirmedAt - startTime, 0);
319
+ const logWindowElapsedMs = Math.max(lastConfirmedAt - logWindowStartedAt, 0);
320
+ const logWindowBytes = Math.max(written - logWindowStartedBytes, 0);
321
+ logFileTransferMetrics({
322
+ transport,
323
+ status: 'completed',
324
+ transferredBytes: written,
325
+ totalBytes: dataLength,
326
+ elapsedMs,
327
+ rateBytesPerSecond: getAverageFileTransferRate(logWindowBytes, logWindowElapsedMs),
328
+ });
329
+
191
330
  return {
192
331
  ...lastMessage,
193
332
  path: options.path,
package/src/api/index.ts CHANGED
@@ -3,6 +3,7 @@ export { default as testProtocolV2Ping } from './protocol-v2/Ping';
3
3
  export { default as preInitialize } from './device/PreInitialize';
4
4
 
5
5
  export { default as searchDevices } from './SearchDevices';
6
+ export { default as detectDeviceConnectProtocol } from './DetectDeviceConnectProtocol';
6
7
  export { default as getFeatures } from './GetFeatures';
7
8
  export { default as getDeviceState } from './GetDeviceState';
8
9
  export { default as getOnekeyFeatures } from './GetOnekeyFeatures';
@@ -49,6 +50,7 @@ export { default as promptWebDeviceAccess } from './PromptWebDeviceAccess';
49
50
  export { default as deviceReboot } from './protocol-v2/DeviceReboot';
50
51
  export { default as deviceGetOnboardingStatus } from './protocol-v2/DeviceGetOnboardingStatus';
51
52
  export { default as deviceUploadWallpaper } from './protocol-v2/DeviceUploadWallpaper';
53
+ export { default as deviceUploadNft } from './protocol-v2/DeviceUploadNft';
52
54
  export { default as uploadPortfolio } from './UploadPortfolio';
53
55
 
54
56
  export { default as cipherKeyValue } from './CipherKeyValue';
@@ -67,7 +67,7 @@ export default class KaspaGetAddress extends BaseMethod<HardwareKaspaGetAddress[
67
67
  model_classic1s: {
68
68
  min: '3.12.0',
69
69
  },
70
- pro2: {
70
+ model_pro2: {
71
71
  min: '0.0.0',
72
72
  },
73
73
  };
@@ -190,7 +190,7 @@ export default class KaspaSignTransaction extends BaseMethod<KaspaSignTransactio
190
190
  model_classic1s: {
191
191
  min: '3.12.0',
192
192
  },
193
- pro2: {
193
+ model_pro2: {
194
194
  min: '0.0.0',
195
195
  },
196
196
  };
@@ -506,18 +506,7 @@ export default class KaspaSignTransaction extends BaseMethod<KaspaSignTransactio
506
506
  'KaspaSignTransaction: device firmware uses the streaming protocol; every output requires address or addressN'
507
507
  );
508
508
  }
509
- try {
510
- return await this.signTxStream(typedCall, response);
511
- } catch (error) {
512
- // Device rejected our refTxs; the caller decides whether to sign without them.
513
- if (
514
- error instanceof HardwareError &&
515
- String(error.message).toLowerCase().includes('previous transaction id mismatch')
516
- ) {
517
- throw ERRORS.TypedError(HardwareErrorCode.KaspaPrevTxIdMismatch, String(error.message));
518
- }
519
- throw error;
520
- }
509
+ return this.signTxStream(typedCall, response);
521
510
  }
522
511
 
523
512
  // Legacy answer to a streaming-only packet: no prehash material exists.
@@ -23,7 +23,7 @@ const baseVersionRange = {
23
23
  model_touch: {
24
24
  min: '4.3.0',
25
25
  },
26
- pro2: {
26
+ model_pro2: {
27
27
  min: '0.0.0',
28
28
  },
29
29
  };
@@ -36,7 +36,7 @@ const specialVersionRange: Record<string, DeviceFirmwareRange> = {
36
36
  model_touch: {
37
37
  min: '4.7.0',
38
38
  },
39
- pro2: {
39
+ model_pro2: {
40
40
  min: '0.0.0',
41
41
  },
42
42
  },
@@ -47,7 +47,7 @@ const specialVersionRange: Record<string, DeviceFirmwareRange> = {
47
47
  model_touch: {
48
48
  min: '4.9.0',
49
49
  },
50
- pro2: {
50
+ model_pro2: {
51
51
  min: '0.0.0',
52
52
  },
53
53
  },
@@ -0,0 +1,197 @@
1
+ import { ERRORS, HardwareErrorCode, createDeviceNotSupportMethodError } from '@onekeyfe/hd-shared';
2
+
3
+ import { UI_REQUEST, createUiMessage } from '../../events/ui-request';
4
+ import { supportsProtocolV2Message } from '../../protocols/protocol-v2/features';
5
+ import {
6
+ PRO2_NFT_DEFAULT_CHUNK_SIZE,
7
+ PRO2_NFT_DEFAULT_PACE_MS,
8
+ PRO2_NFT_DEFAULT_TIMEOUT_MS,
9
+ PRO2_NFT_DIRECTORY,
10
+ PRO2_NFT_MAX_CHUNK_SIZE,
11
+ PRO2_NFT_MAX_ITEMS,
12
+ PRO2_NFT_MIN_CHUNK_SIZE,
13
+ type Pro2NftBundle,
14
+ type Pro2NftImage,
15
+ buildPro2NftBundle,
16
+ getCompletePro2NftBasenames,
17
+ } from '../../utils/pro2Nft';
18
+ import { BaseMethod } from '../BaseMethod';
19
+ import { invalidParameter } from '../helpers/filesystemValidation';
20
+ import { writeProtocolV2File } from '../helpers/protocolV2FileWrite';
21
+
22
+ export type DeviceUploadNftParams = {
23
+ image: Pro2NftImage;
24
+ thumbnail: Pro2NftImage;
25
+ title: string;
26
+ subtitle: string;
27
+ timestampMs?: number;
28
+ chunkSize?: number;
29
+ paceMs?: number;
30
+ timeoutMs?: number;
31
+ };
32
+
33
+ export type DeviceUploadNftResponse = {
34
+ basename: string;
35
+ imagePath: string;
36
+ thumbnailPath: string;
37
+ metadataPath: string;
38
+ totalSize: number;
39
+ nftUpdated: true;
40
+ message?: string;
41
+ };
42
+
43
+ const FILESYSTEM_PATH_INFO_QUERY_MESSAGE_TYPE = 60802;
44
+ const FILESYSTEM_FILE_WRITE_MESSAGE_TYPE = 60805;
45
+ const FILESYSTEM_DIR_LIST_MESSAGE_TYPE = 60808;
46
+ const NFT_UPDATE_MESSAGE_TYPE = 61500;
47
+
48
+ export default class DeviceUploadNft extends BaseMethod<DeviceUploadNftParams> {
49
+ private bundle?: Pro2NftBundle;
50
+
51
+ getSupportedProtocols() {
52
+ return ['V2'] as const;
53
+ }
54
+
55
+ init() {
56
+ const {
57
+ image,
58
+ thumbnail,
59
+ title,
60
+ subtitle,
61
+ timestampMs = Date.now(),
62
+ chunkSize = PRO2_NFT_DEFAULT_CHUNK_SIZE,
63
+ paceMs = PRO2_NFT_DEFAULT_PACE_MS,
64
+ timeoutMs = PRO2_NFT_DEFAULT_TIMEOUT_MS,
65
+ } = this.payload;
66
+ if (
67
+ !Number.isInteger(chunkSize) ||
68
+ chunkSize < PRO2_NFT_MIN_CHUNK_SIZE ||
69
+ chunkSize > PRO2_NFT_MAX_CHUNK_SIZE
70
+ ) {
71
+ throw invalidParameter(
72
+ `Parameter [chunkSize] must be an integer between ${PRO2_NFT_MIN_CHUNK_SIZE} and ${PRO2_NFT_MAX_CHUNK_SIZE}.`
73
+ );
74
+ }
75
+ if (!Number.isInteger(paceMs) || paceMs < 0) {
76
+ throw invalidParameter('Parameter [paceMs] must be a non-negative integer.');
77
+ }
78
+ if (!Number.isInteger(timeoutMs) || timeoutMs <= 0) {
79
+ throw invalidParameter('Parameter [timeoutMs] must be a positive integer.');
80
+ }
81
+
82
+ this.bundle = buildPro2NftBundle({ image, thumbnail, title, subtitle, timestampMs });
83
+ this.params = { image, thumbnail, title, subtitle, timestampMs, chunkSize, paceMs, timeoutMs };
84
+ this.unlockPolicy = 'none';
85
+ this.skipForceUpdateCheck = true;
86
+ this.useDevicePassphraseState = false;
87
+ }
88
+
89
+ private async assertCapabilities() {
90
+ const protocolInfo = await this.device.ensureProtocolV2RuntimeContext();
91
+ const hasFileWrite = supportsProtocolV2Message(
92
+ protocolInfo,
93
+ FILESYSTEM_FILE_WRITE_MESSAGE_TYPE
94
+ );
95
+ const hasPathInfo = supportsProtocolV2Message(
96
+ protocolInfo,
97
+ FILESYSTEM_PATH_INFO_QUERY_MESSAGE_TYPE
98
+ );
99
+ const hasDirList = supportsProtocolV2Message(protocolInfo, FILESYSTEM_DIR_LIST_MESSAGE_TYPE);
100
+ const hasNftUpdate = supportsProtocolV2Message(protocolInfo, NFT_UPDATE_MESSAGE_TYPE);
101
+ if (!hasFileWrite || !hasPathInfo || !hasDirList || !hasNftUpdate) {
102
+ throw createDeviceNotSupportMethodError(this.name, this.device.getCurrentFirmwareType());
103
+ }
104
+ }
105
+
106
+ private async assertStorageCapacity(basename: string) {
107
+ const { message: pathInfo } = await this.device.commands.typedCall(
108
+ 'FilesystemPathInfoQuery',
109
+ 'FilesystemPathInfo',
110
+ { path: PRO2_NFT_DIRECTORY },
111
+ { timeoutMs: this.params.timeoutMs }
112
+ );
113
+ if (!pathInfo.exist) return;
114
+
115
+ const { message } = await this.device.commands.typedCall(
116
+ 'FilesystemDirList',
117
+ 'FilesystemDir',
118
+ { path: PRO2_NFT_DIRECTORY, depth: 1 },
119
+ { timeoutMs: this.params.timeoutMs }
120
+ );
121
+ const existingBasenames = getCompletePro2NftBasenames(message.child_files);
122
+ if (existingBasenames.size >= PRO2_NFT_MAX_ITEMS && !existingBasenames.has(basename)) {
123
+ throw ERRORS.TypedError(HardwareErrorCode.NftStorageLimitReached, undefined, {
124
+ count: existingBasenames.size,
125
+ limit: PRO2_NFT_MAX_ITEMS,
126
+ });
127
+ }
128
+ }
129
+
130
+ private async updateNft(basename: string) {
131
+ return this.device.commands.typedCall(
132
+ 'NftUpdate',
133
+ 'Success',
134
+ { file_name_no_ext: basename },
135
+ { timeoutMs: this.params.timeoutMs }
136
+ );
137
+ }
138
+
139
+ async run(): Promise<DeviceUploadNftResponse> {
140
+ const { bundle } = this;
141
+ if (!bundle) throw invalidParameter('NFT data has not been initialized.');
142
+
143
+ await this.assertCapabilities();
144
+ this.throwIfAborted();
145
+ await this.assertStorageCapacity(bundle.basename);
146
+ this.throwIfAborted();
147
+
148
+ const files = [
149
+ { path: `${PRO2_NFT_DIRECTORY}/${bundle.basename}.bin`, data: bundle.image },
150
+ { path: `${PRO2_NFT_DIRECTORY}/${bundle.basename}_m.bin`, data: bundle.thumbnail },
151
+ { path: `${PRO2_NFT_DIRECTORY}/${bundle.basename}.json`, data: bundle.metadata },
152
+ ];
153
+ const totalSize = files.reduce((sum, file) => sum + file.data.byteLength, 0);
154
+ let transferredBeforeFile = 0;
155
+
156
+ for (const file of files) {
157
+ const transferredAtFileStart = transferredBeforeFile;
158
+ await writeProtocolV2File({
159
+ commands: this.device.commands,
160
+ path: file.path,
161
+ data: file.data,
162
+ totalSize: file.data.byteLength,
163
+ chunkSize: this.params.chunkSize,
164
+ timeoutMs: this.params.timeoutMs,
165
+ paceMs: this.params.paceMs,
166
+ overwrite: true,
167
+ append: false,
168
+ throwIfAborted: () => this.throwIfAborted(),
169
+ onProgress: progress => {
170
+ if (typeof this.postMessage !== 'function') return;
171
+ const transferredBytes = transferredAtFileStart + progress.transferredBytes;
172
+ this.postMessage(
173
+ createUiMessage(UI_REQUEST.DEVICE_PROGRESS, {
174
+ ...progress,
175
+ progress: Math.floor((transferredBytes / totalSize) * 100),
176
+ transferredBytes,
177
+ totalBytes: totalSize,
178
+ })
179
+ );
180
+ },
181
+ });
182
+ transferredBeforeFile += file.data.byteLength;
183
+ }
184
+
185
+ this.throwIfAborted();
186
+ const response = await this.updateNft(bundle.basename);
187
+ return {
188
+ basename: bundle.basename,
189
+ imagePath: files[0].path,
190
+ thumbnailPath: files[1].path,
191
+ metadataPath: files[2].path,
192
+ totalSize,
193
+ nftUpdated: true,
194
+ message: response.message?.message,
195
+ };
196
+ }
197
+ }
@@ -13,7 +13,9 @@ export default class ProtocolInfoRequest extends BaseMethod {
13
13
  }
14
14
 
15
15
  async run() {
16
- const res = await this.device.commands.typedCall('ProtocolInfoRequest', 'ProtocolInfo', {});
16
+ const res = await this.device.commands.typedCall('ProtocolInfoRequest', 'ProtocolInfo', {
17
+ eventless_wallet_session: true,
18
+ });
17
19
  return Promise.resolve(res.message);
18
20
  }
19
21
  }
@@ -118,6 +118,7 @@ export const isProtocolV2DeviceDisconnectedError = (error: unknown) => {
118
118
  message.includes('connection has timed out unexpectedly') ||
119
119
  message.includes('connection error has occured') ||
120
120
  message.includes('connection error has occurred') ||
121
+ message.includes('react native ble transport released') ||
121
122
  message.includes('multiplatformbleadapter') ||
122
123
  message.includes('multipalformebleadapter') ||
123
124
  compactMessage.includes('rxerrorerror6') ||
@@ -137,7 +138,6 @@ export function normalizeRebootType(value: RebootTypeInput | undefined): DeviceR
137
138
 
138
139
  // 与 firmware-pro2 的 proto_target_to_firmware_target 安装白名单保持一致。
139
140
  const INSTALLABLE_FIRMWARE_TARGET_IDS = new Set<number>([
140
- ProtocolV2FirmwareTargetType.FW_MGMT_TARGET_CRATE,
141
141
  ProtocolV2FirmwareTargetType.FW_MGMT_TARGET_BOOTLOADER,
142
142
  ProtocolV2FirmwareTargetType.FW_MGMT_TARGET_APPLICATION_P1,
143
143
  ProtocolV2FirmwareTargetType.FW_MGMT_TARGET_APPLICATION_P2,
@@ -34,7 +34,7 @@ export default class SolSignMessage extends BaseMethod<HardwareSolSignUnsafeMess
34
34
 
35
35
  getVersionRange() {
36
36
  return {
37
- pro2: {
37
+ model_pro2: {
38
38
  min: '0.0.0',
39
39
  },
40
40
  pro: {
@@ -40,7 +40,7 @@ export default class SolSignOffchainMessage extends BaseMethod<HardwareSolSignOf
40
40
 
41
41
  getVersionRange() {
42
42
  return {
43
- pro2: {
43
+ model_pro2: {
44
44
  min: '0.0.0',
45
45
  },
46
46
  pro: {
@@ -47,7 +47,7 @@ export default class SolSignTransaction extends BaseMethod<HardwareSolanaSignTx[
47
47
  getVersionRange() {
48
48
  if (this.existsVersionedTx()) {
49
49
  return {
50
- pro2: {
50
+ model_pro2: {
51
51
  min: '0.0.0',
52
52
  },
53
53
  model_mini: {
@@ -60,7 +60,7 @@ export default class SolSignTransaction extends BaseMethod<HardwareSolanaSignTx[
60
60
  }
61
61
 
62
62
  return {
63
- pro2: {
63
+ model_pro2: {
64
64
  min: '0.0.0',
65
65
  },
66
66
  classic: {
@@ -52,7 +52,7 @@ export default class SuiGetAddress extends BaseMethod<HardwareSuiGetAddress[]> {
52
52
 
53
53
  getVersionRange() {
54
54
  return {
55
- pro2: {
55
+ model_pro2: {
56
56
  min: '0.0.0',
57
57
  },
58
58
  model_mini: {
@@ -44,7 +44,7 @@ export default class SuiGetPublicKey extends BaseMethod<any> {
44
44
 
45
45
  getVersionRange() {
46
46
  return {
47
- pro2: {
47
+ model_pro2: {
48
48
  min: '0.0.0',
49
49
  },
50
50
  model_mini: {