@onekeyfe/hd-core 1.2.0-alpha.52 → 1.2.0-alpha.53

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 (251) hide show
  1. package/__tests__/AllNetworkGetAddressBase.tracing.test.ts +78 -0
  2. package/__tests__/DeviceCommands.test.ts +45 -0
  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__/device-lifecycle-events.test.ts +105 -3
  7. package/__tests__/deviceUploadNft.test.ts +293 -0
  8. package/__tests__/firmware-update/firmware-update-v2-download-before-boot.test.ts +31 -59
  9. package/__tests__/get-device-state.test.ts +132 -12
  10. package/__tests__/homescreen.test.ts +41 -1
  11. package/__tests__/logBlockEvent.test.ts +1 -1
  12. package/__tests__/method-protocol-support.test.ts +19 -0
  13. package/__tests__/open-wallet-session.test.ts +446 -33
  14. package/__tests__/pro2Nft.test.ts +108 -0
  15. package/__tests__/protocol-binding.test.ts +89 -0
  16. package/__tests__/protocol-v2-resources.test.ts +284 -0
  17. package/__tests__/protocol-v2-ui-lifecycle.test.ts +91 -0
  18. package/__tests__/protocol-v2-unlock-policy.test.ts +201 -35
  19. package/__tests__/protocol-v2.test.ts +1349 -1005
  20. package/__tests__/protocolV2UiInteraction.test.ts +63 -0
  21. package/__tests__/public-pro2-api-boundary.test.ts +1 -0
  22. package/__tests__/search-devices.test.ts +12 -3
  23. package/__tests__/uiProgressThrottle.test.ts +74 -0
  24. package/__tests__/uiPromiseRegistry.test.ts +86 -0
  25. package/dist/api/BaseMethod.d.ts +3 -1
  26. package/dist/api/BaseMethod.d.ts.map +1 -1
  27. package/dist/api/CheckAllFirmwareRelease.d.ts +2 -1
  28. package/dist/api/CheckAllFirmwareRelease.d.ts.map +1 -1
  29. package/dist/api/DetectDeviceConnectProtocol.d.ts +7 -0
  30. package/dist/api/DetectDeviceConnectProtocol.d.ts.map +1 -0
  31. package/dist/api/FirmwareUpdate.d.ts.map +1 -1
  32. package/dist/api/FirmwareUpdateV2.d.ts +0 -11
  33. package/dist/api/FirmwareUpdateV2.d.ts.map +1 -1
  34. package/dist/api/FirmwareUpdateV3.d.ts +3 -7
  35. package/dist/api/FirmwareUpdateV3.d.ts.map +1 -1
  36. package/dist/api/FirmwareUpdateV4.d.ts +11 -25
  37. package/dist/api/FirmwareUpdateV4.d.ts.map +1 -1
  38. package/dist/api/GetPassphraseState.d.ts.map +1 -1
  39. package/dist/api/OpenWalletSession.d.ts.map +1 -1
  40. package/dist/api/SearchDevices.d.ts.map +1 -1
  41. package/dist/api/allnetwork/AllNetworkGetAddressBase.d.ts.map +1 -1
  42. package/dist/api/device/DeviceUnlock.d.ts +2 -2
  43. package/dist/api/device/DeviceUnlock.d.ts.map +1 -1
  44. package/dist/api/device/DeviceUpdateBootloader.d.ts +1 -5
  45. package/dist/api/device/DeviceUpdateBootloader.d.ts.map +1 -1
  46. package/dist/api/firmware/FirmwareUpdateBaseMethod.d.ts +0 -9
  47. package/dist/api/firmware/FirmwareUpdateBaseMethod.d.ts.map +1 -1
  48. package/dist/api/firmware/getBinary.d.ts +0 -7
  49. package/dist/api/firmware/getBinary.d.ts.map +1 -1
  50. package/dist/api/firmware/updateBootloader.d.ts +0 -2
  51. package/dist/api/firmware/updateBootloader.d.ts.map +1 -1
  52. package/dist/api/firmware/uploadFirmware.d.ts +1 -9
  53. package/dist/api/firmware/uploadFirmware.d.ts.map +1 -1
  54. package/dist/api/helpers/protocolV2FileWrite.d.ts +2 -0
  55. package/dist/api/helpers/protocolV2FileWrite.d.ts.map +1 -1
  56. package/dist/api/index.d.ts +2 -0
  57. package/dist/api/index.d.ts.map +1 -1
  58. package/dist/api/protocol-v2/DeviceUploadNft.d.ts +31 -0
  59. package/dist/api/protocol-v2/DeviceUploadNft.d.ts.map +1 -0
  60. package/dist/api/protocol-v2/ProtocolInfoRequest.d.ts.map +1 -1
  61. package/dist/api/protocol-v2/helpers.d.ts.map +1 -1
  62. package/dist/api/stellar/StellarSignTransaction.d.ts +1 -1
  63. package/dist/core/deviceEventRegistration.d.ts +2 -0
  64. package/dist/core/deviceEventRegistration.d.ts.map +1 -1
  65. package/dist/core/index.d.ts.map +1 -1
  66. package/dist/core/uiPromiseRegistry.d.ts +4 -0
  67. package/dist/core/uiPromiseRegistry.d.ts.map +1 -0
  68. package/dist/data-manager/DataManager.d.ts +4 -2
  69. package/dist/data-manager/DataManager.d.ts.map +1 -1
  70. package/dist/data-manager/connectSettings.d.ts.map +1 -1
  71. package/dist/device/Device.d.ts +29 -6
  72. package/dist/device/Device.d.ts.map +1 -1
  73. package/dist/device/DeviceCommands.d.ts +4 -4
  74. package/dist/device/DeviceCommands.d.ts.map +1 -1
  75. package/dist/device/DevicePool.d.ts.map +1 -1
  76. package/dist/events/device.d.ts +4 -0
  77. package/dist/events/device.d.ts.map +1 -1
  78. package/dist/events/logBlockEvent.d.ts.map +1 -1
  79. package/dist/events/ui-promise.d.ts +4 -2
  80. package/dist/events/ui-promise.d.ts.map +1 -1
  81. package/dist/events/ui-request.d.ts +31 -2
  82. package/dist/events/ui-request.d.ts.map +1 -1
  83. package/dist/events/ui-response.d.ts +10 -2
  84. package/dist/events/ui-response.d.ts.map +1 -1
  85. package/dist/index.d.ts +214 -231
  86. package/dist/index.d.ts.map +1 -1
  87. package/dist/index.js +2559 -3497
  88. package/dist/inject.d.ts +6 -1
  89. package/dist/inject.d.ts.map +1 -1
  90. package/dist/lowLevelInject.d.ts.map +1 -1
  91. package/dist/protocols/protocol-v2/features.d.ts.map +1 -1
  92. package/dist/protocols/protocol-v2/resources.d.ts +30 -0
  93. package/dist/protocols/protocol-v2/resources.d.ts.map +1 -0
  94. package/dist/protocols/protocol-v2/uiInteraction.d.ts +7 -4
  95. package/dist/protocols/protocol-v2/uiInteraction.d.ts.map +1 -1
  96. package/dist/protocols/protocol-v2/unlockPolicy.d.ts +1 -3
  97. package/dist/protocols/protocol-v2/unlockPolicy.d.ts.map +1 -1
  98. package/dist/protocols/protocol-v2/unlockPolicyRunner.d.ts +22 -0
  99. package/dist/protocols/protocol-v2/unlockPolicyRunner.d.ts.map +1 -0
  100. package/dist/protocols/protocol-v2/walletSession.d.ts +5 -1
  101. package/dist/protocols/protocol-v2/walletSession.d.ts.map +1 -1
  102. package/dist/topLevelInject.d.ts.map +1 -1
  103. package/dist/types/api/checkAllFirmwareRelease.d.ts +2 -4
  104. package/dist/types/api/checkAllFirmwareRelease.d.ts.map +1 -1
  105. package/dist/types/api/detectDeviceConnectProtocol.d.ts +4 -0
  106. package/dist/types/api/detectDeviceConnectProtocol.d.ts.map +1 -0
  107. package/dist/types/api/deviceUnlock.d.ts +5 -1
  108. package/dist/types/api/deviceUnlock.d.ts.map +1 -1
  109. package/dist/types/api/deviceUpdateBootloader.d.ts +0 -6
  110. package/dist/types/api/deviceUpdateBootloader.d.ts.map +1 -1
  111. package/dist/types/api/export.d.ts +2 -4
  112. package/dist/types/api/export.d.ts.map +1 -1
  113. package/dist/types/api/firmwareUpdate.d.ts +2 -70
  114. package/dist/types/api/firmwareUpdate.d.ts.map +1 -1
  115. package/dist/types/api/index.d.ts +7 -10
  116. package/dist/types/api/index.d.ts.map +1 -1
  117. package/dist/types/api/protocolV2.d.ts +3 -0
  118. package/dist/types/api/protocolV2.d.ts.map +1 -1
  119. package/dist/types/device.d.ts.map +1 -1
  120. package/dist/types/params.d.ts +1 -0
  121. package/dist/types/params.d.ts.map +1 -1
  122. package/dist/types/settings.d.ts +22 -13
  123. package/dist/types/settings.d.ts.map +1 -1
  124. package/dist/utils/deviceFeaturesCompat.d.ts +0 -1
  125. package/dist/utils/deviceFeaturesCompat.d.ts.map +1 -1
  126. package/dist/utils/deviceFeaturesUtils.d.ts +4 -0
  127. package/dist/utils/deviceFeaturesUtils.d.ts.map +1 -1
  128. package/dist/utils/homescreen.d.ts +4 -0
  129. package/dist/utils/homescreen.d.ts.map +1 -1
  130. package/dist/utils/index.d.ts +1 -1
  131. package/dist/utils/index.d.ts.map +1 -1
  132. package/dist/utils/patch.d.ts +1 -1
  133. package/dist/utils/patch.d.ts.map +1 -1
  134. package/dist/utils/pro2Nft.d.ts +31 -0
  135. package/dist/utils/pro2Nft.d.ts.map +1 -0
  136. package/dist/utils/pro2Wallpaper.d.ts +10 -0
  137. package/dist/utils/pro2Wallpaper.d.ts.map +1 -1
  138. package/dist/utils/uiProgressThrottle.d.ts +3 -0
  139. package/dist/utils/uiProgressThrottle.d.ts.map +1 -0
  140. package/package.json +4 -4
  141. package/src/api/BaseMethod.ts +8 -10
  142. package/src/api/CheckAllFirmwareRelease.ts +54 -57
  143. package/src/api/DetectDeviceConnectProtocol.ts +18 -0
  144. package/src/api/FirmwareUpdate.ts +7 -15
  145. package/src/api/FirmwareUpdateV2.ts +126 -316
  146. package/src/api/FirmwareUpdateV3.ts +63 -265
  147. package/src/api/FirmwareUpdateV4.ts +566 -965
  148. package/src/api/GetPassphraseState.ts +7 -1
  149. package/src/api/OpenWalletSession.ts +54 -17
  150. package/src/api/SearchDevices.ts +3 -1
  151. package/src/api/allnetwork/AllNetworkGetAddressBase.ts +32 -11
  152. package/src/api/device/DeviceUnlock.ts +8 -3
  153. package/src/api/device/DeviceUpdateBootloader.ts +6 -122
  154. package/src/api/firmware/FirmwareUpdateBaseMethod.ts +16 -83
  155. package/src/api/firmware/updateBootloader.ts +4 -19
  156. package/src/api/firmware/uploadFirmware.ts +39 -144
  157. package/src/api/helpers/protocolV2FileWrite.ts +11 -4
  158. package/src/api/index.ts +2 -0
  159. package/src/api/protocol-v2/DeviceUploadNft.ts +189 -0
  160. package/src/api/protocol-v2/ProtocolInfoRequest.ts +3 -1
  161. package/src/api/protocol-v2/helpers.ts +1 -0
  162. package/src/core/deviceEventRegistration.ts +4 -0
  163. package/src/core/index.ts +167 -83
  164. package/src/core/uiPromiseRegistry.ts +41 -0
  165. package/src/data/messages/messages-protocol-v2.json +25 -0
  166. package/src/data-manager/DataManager.ts +67 -38
  167. package/src/data-manager/connectSettings.ts +0 -11
  168. package/src/device/Device.ts +258 -42
  169. package/src/device/DeviceCommands.ts +7 -1
  170. package/src/device/DevicePool.ts +7 -2
  171. package/src/events/device.ts +4 -0
  172. package/src/events/logBlockEvent.ts +1 -0
  173. package/src/events/ui-promise.ts +4 -2
  174. package/src/events/ui-request.ts +36 -2
  175. package/src/events/ui-response.ts +12 -2
  176. package/src/index.ts +0 -5
  177. package/src/inject.ts +60 -24
  178. package/src/lowLevelInject.ts +7 -8
  179. package/src/protocols/protocol-v2/features.ts +10 -3
  180. package/src/protocols/protocol-v2/resources.ts +359 -0
  181. package/src/protocols/protocol-v2/uiInteraction.ts +46 -6
  182. package/src/protocols/protocol-v2/unlockPolicy.ts +1 -105
  183. package/src/protocols/protocol-v2/unlockPolicyRunner.ts +118 -0
  184. package/src/protocols/protocol-v2/walletSession.ts +180 -30
  185. package/src/topLevelInject.ts +7 -8
  186. package/src/types/api/checkAllFirmwareRelease.ts +2 -4
  187. package/src/types/api/detectDeviceConnectProtocol.ts +7 -0
  188. package/src/types/api/deviceUnlock.ts +12 -1
  189. package/src/types/api/deviceUpdateBootloader.ts +0 -6
  190. package/src/types/api/export.ts +1 -18
  191. package/src/types/api/firmwareUpdate.ts +3 -76
  192. package/src/types/api/index.ts +13 -14
  193. package/src/types/api/protocolV2.ts +13 -0
  194. package/src/types/device.ts +3 -0
  195. package/src/types/params.ts +7 -1
  196. package/src/types/settings.ts +42 -13
  197. package/src/utils/deviceFeaturesCompat.ts +0 -6
  198. package/src/utils/deviceFeaturesUtils.ts +8 -0
  199. package/src/utils/homescreen.ts +32 -6
  200. package/src/utils/index.ts +6 -1
  201. package/src/utils/pro2Nft.ts +142 -0
  202. package/src/utils/pro2Wallpaper.ts +35 -8
  203. package/src/utils/uiProgressThrottle.ts +63 -0
  204. package/__tests__/device-initialize-timeout.test.ts +0 -56
  205. package/__tests__/firmware-update/check-all-firmware-release.test.ts +0 -175
  206. package/__tests__/firmware-update/firmware-artifact-source.test.ts +0 -119
  207. package/__tests__/firmware-update/firmware-host-binding.test.ts +0 -70
  208. package/__tests__/firmware-update/firmware-preparation-error.test.ts +0 -27
  209. package/__tests__/firmware-update/firmware-update-bootloader-poll.test.ts +0 -200
  210. package/__tests__/firmware-update/firmware-update-capabilities.test.ts +0 -13
  211. package/__tests__/firmware-update/firmware-update-plan-bootloader-identity.test.ts +0 -294
  212. package/__tests__/firmware-update/firmware-update-plan.test.ts +0 -593
  213. package/__tests__/firmware-update/firmware-update-prepared-plan.test.ts +0 -213
  214. package/__tests__/firmware-update/firmware-update-v3-reconnect.test.ts +0 -58
  215. package/__tests__/firmware-update/firmware-upload-source.test.ts +0 -70
  216. package/dist/api/firmware/FirmwareArtifactSource.d.ts +0 -25
  217. package/dist/api/firmware/FirmwareArtifactSource.d.ts.map +0 -1
  218. package/dist/api/firmware/FirmwareHostBinding.d.ts +0 -6
  219. package/dist/api/firmware/FirmwareHostBinding.d.ts.map +0 -1
  220. package/dist/api/firmware/FirmwarePreparationError.d.ts +0 -3
  221. package/dist/api/firmware/FirmwarePreparationError.d.ts.map +0 -1
  222. package/dist/api/firmware/FirmwareUpdateCapabilities.d.ts +0 -3
  223. package/dist/api/firmware/FirmwareUpdateCapabilities.d.ts.map +0 -1
  224. package/dist/api/firmware/FirmwareUpdatePlan.d.ts +0 -25
  225. package/dist/api/firmware/FirmwareUpdatePlan.d.ts.map +0 -1
  226. package/dist/api/firmware/FirmwareUpdatePreparedPlan.d.ts +0 -32
  227. package/dist/api/firmware/FirmwareUpdatePreparedPlan.d.ts.map +0 -1
  228. package/dist/api/firmware/progressThrottle.d.ts +0 -3
  229. package/dist/api/firmware/progressThrottle.d.ts.map +0 -1
  230. package/dist/protocols/protocol-v2/lockedError.d.ts +0 -2
  231. package/dist/protocols/protocol-v2/lockedError.d.ts.map +0 -1
  232. package/dist/protocols/protocol-v2/unlockRetry.d.ts +0 -10
  233. package/dist/protocols/protocol-v2/unlockRetry.d.ts.map +0 -1
  234. package/dist/types/api/firmwareUpdateCapabilities.d.ts +0 -9
  235. package/dist/types/api/firmwareUpdateCapabilities.d.ts.map +0 -1
  236. package/dist/types/api/firmwareUpdatePlan.d.ts +0 -28
  237. package/dist/types/api/firmwareUpdatePlan.d.ts.map +0 -1
  238. package/dist/types/api/firmwareUpdatePreparedPlan.d.ts +0 -42
  239. package/dist/types/api/firmwareUpdatePreparedPlan.d.ts.map +0 -1
  240. package/src/api/firmware/FirmwareArtifactSource.ts +0 -278
  241. package/src/api/firmware/FirmwareHostBinding.ts +0 -100
  242. package/src/api/firmware/FirmwarePreparationError.ts +0 -12
  243. package/src/api/firmware/FirmwareUpdateCapabilities.ts +0 -9
  244. package/src/api/firmware/FirmwareUpdatePlan.ts +0 -772
  245. package/src/api/firmware/FirmwareUpdatePreparedPlan.ts +0 -415
  246. package/src/api/firmware/progressThrottle.ts +0 -44
  247. package/src/protocols/protocol-v2/lockedError.ts +0 -10
  248. package/src/protocols/protocol-v2/unlockRetry.ts +0 -109
  249. package/src/types/api/firmwareUpdateCapabilities.ts +0 -9
  250. package/src/types/api/firmwareUpdatePlan.ts +0 -38
  251. package/src/types/api/firmwareUpdatePreparedPlan.ts +0 -53
@@ -1,105 +1 @@
1
- export type UnlockPolicy = 'none' | 'unlock-before-run' | 'retry-on-locked';
2
-
3
- /**
4
- * Protocol V2 methods that are safe to replay after a locked response.
5
- *
6
- * Keep this as an exact allowlist. Name-pattern matching can silently make a new
7
- * state-changing method replayable when it happens to share a suffix.
8
- */
9
- export const PROTOCOL_V2_RETRY_ON_LOCKED_METHODS = [
10
- 'cipherKeyValue',
11
- 'allNetworkGetAddress',
12
- 'allNetworkGetAddressByLoop',
13
- 'btcGetAddress',
14
- 'btcGetPublicKey',
15
- 'btcSignMessage',
16
- 'btcSignPsbt',
17
- 'btcSignTransaction',
18
- 'btcVerifyMessage',
19
- 'confluxGetAddress',
20
- 'confluxSignMessage',
21
- 'confluxSignTransaction',
22
- 'evmGetAddress',
23
- 'evmGetPublicKey',
24
- 'evmSignMessage',
25
- 'evmSignTransaction',
26
- 'evmSignTypedData',
27
- 'evmVerifyMessage',
28
- 'starcoinGetAddress',
29
- 'starcoinGetPublicKey',
30
- 'starcoinSignMessage',
31
- 'starcoinSignTransaction',
32
- 'starcoinVerifyMessage',
33
- 'nemGetAddress',
34
- 'nemSignTransaction',
35
- 'solGetAddress',
36
- 'solSignTransaction',
37
- 'solSignOffchainMessage',
38
- 'solSignMessage',
39
- 'stellarGetAddress',
40
- 'stellarSignTransaction',
41
- 'tronGetAddress',
42
- 'tronSignMessage',
43
- 'tronSignTransaction',
44
- 'nearGetAddress',
45
- 'nearSignTransaction',
46
- 'aptosGetAddress',
47
- 'aptosGetPublicKey',
48
- 'aptosSignTransaction',
49
- 'aptosSignMessage',
50
- 'aptosSignInMessage',
51
- 'algoGetAddress',
52
- 'algoSignTransaction',
53
- 'cosmosGetAddress',
54
- 'cosmosGetPublicKey',
55
- 'cosmosSignTransaction',
56
- 'xrpGetAddress',
57
- 'xrpSignTransaction',
58
- 'suiGetAddress',
59
- 'suiGetPublicKey',
60
- 'suiSignMessage',
61
- 'suiSignTransaction',
62
- 'cardanoGetAddress',
63
- 'cardanoGetPublicKey',
64
- 'cardanoSignTransaction',
65
- 'cardanoSignMessage',
66
- 'filecoinGetAddress',
67
- 'filecoinSignTransaction',
68
- 'polkadotGetAddress',
69
- 'polkadotSignTransaction',
70
- 'kaspaGetAddress',
71
- 'kaspaSignTransaction',
72
- 'nexaGetAddress',
73
- 'nexaSignTransaction',
74
- 'nostrGetPublicKey',
75
- 'nostrSignEvent',
76
- 'nostrEncryptMessage',
77
- 'nostrDecryptMessage',
78
- 'nostrSignSchnorr',
79
- 'lnurlAuth',
80
- 'nervosGetAddress',
81
- 'nervosSignTransaction',
82
- 'dnxGetAddress',
83
- 'dnxSignTransaction',
84
- 'tonGetAddress',
85
- 'tonSignMessage',
86
- 'tonSignProof',
87
- 'tonSignData',
88
- 'scdoGetAddress',
89
- 'scdoSignTransaction',
90
- 'scdoSignMessage',
91
- 'alephiumGetAddress',
92
- 'alephiumSignTransaction',
93
- 'alephiumSignMessage',
94
- 'benfenGetAddress',
95
- 'benfenGetPublicKey',
96
- 'benfenSignMessage',
97
- 'benfenSignTransaction',
98
- 'neoGetAddress',
99
- 'neoSignTransaction',
100
- ] as const;
101
-
102
- const retryOnLockedMethods = new Set<string>(PROTOCOL_V2_RETRY_ON_LOCKED_METHODS);
103
-
104
- export const getProtocolV2UnlockPolicy = (methodName: string): UnlockPolicy =>
105
- retryOnLockedMethods.has(methodName) ? 'retry-on-locked' : 'none';
1
+ export type UnlockPolicy = 'none' | 'unlock-before-run';
@@ -0,0 +1,118 @@
1
+ import { ERRORS, HardwareErrorCode } from '@onekeyfe/hd-shared';
2
+ import { DeviceSessionPinType } from '@onekeyfe/hd-transport';
3
+
4
+ import { LoggerNames, getLogger } from '../../utils';
5
+ import { isProtocolV2UiEnabled, resolveProtocolV2UiInteraction } from './uiInteraction';
6
+ import { refreshProtocolV2DeviceStatus } from './walletSession';
7
+
8
+ import type { BaseMethod } from '../../api/BaseMethod';
9
+ import type { Device } from '../../device/Device';
10
+ import type { HardwareUiInteractionMeta } from '../../events';
11
+ import type { ProtocolV2UiInteractionCoordinator } from './uiInteraction';
12
+
13
+ const Log = getLogger(LoggerNames.Core);
14
+
15
+ export type ProtocolV2UnlockContext = {
16
+ preflightCompleted: boolean;
17
+ };
18
+
19
+ export const createProtocolV2UnlockContext = (): ProtocolV2UnlockContext => ({
20
+ preflightCompleted: false,
21
+ });
22
+
23
+ type RunnableMethod = Pick<
24
+ BaseMethod,
25
+ | 'run'
26
+ | 'unlockPolicy'
27
+ | 'useDevicePassphraseState'
28
+ | 'protocolV2UiInteraction'
29
+ | 'protocolV2UiMode'
30
+ | 'params'
31
+ | 'payload'
32
+ > & {
33
+ name?: string;
34
+ protocolV2UnlockContext?: ProtocolV2UnlockContext;
35
+ };
36
+
37
+ type UiInteractionCoordinator = Pick<
38
+ ProtocolV2UiInteractionCoordinator,
39
+ 'enterMethodInteraction' | 'enterUnlockInteraction'
40
+ >;
41
+
42
+ type RunMethodWithUnlockPolicyOptions<T> = {
43
+ context?: ProtocolV2UnlockContext;
44
+ uiCoordinator?: UiInteractionCoordinator;
45
+ afterStatusBeforeUnlock?: () => void | Promise<void>;
46
+ prepare?: () => Promise<void>;
47
+ run?: () => Promise<T>;
48
+ };
49
+
50
+ export async function runMethodWithUnlockPolicy<T = unknown>(
51
+ method: RunnableMethod,
52
+ device: Device,
53
+ options: RunMethodWithUnlockPolicyOptions<T> = {}
54
+ ): Promise<T> {
55
+ const {
56
+ context = createProtocolV2UnlockContext(),
57
+ uiCoordinator,
58
+ afterStatusBeforeUnlock,
59
+ prepare,
60
+ run: configuredRun,
61
+ } = options;
62
+ const run = configuredRun ?? (() => method.run() as Promise<T>);
63
+ method.protocolV2UnlockContext = context;
64
+
65
+ const shouldEmitUi = isProtocolV2UiEnabled(method);
66
+ const shouldCoordinateUi = shouldEmitUi && uiCoordinator !== undefined;
67
+ const requiresPreUnlock =
68
+ device.isProtocolV2() &&
69
+ (method.useDevicePassphraseState || method.unlockPolicy === 'unlock-before-run') &&
70
+ !device.isBootloader?.() &&
71
+ !device.isRomloader?.();
72
+
73
+ if (requiresPreUnlock && !context.preflightCompleted) {
74
+ const status = await refreshProtocolV2DeviceStatus(device);
75
+ if (typeof status?.unlocked !== 'boolean') {
76
+ throw ERRORS.TypedError(
77
+ HardwareErrorCode.RuntimeError,
78
+ 'Protocol V2 DeviceStatus did not report an explicit unlock state.'
79
+ );
80
+ }
81
+
82
+ await afterStatusBeforeUnlock?.();
83
+
84
+ if (!status.unlocked) {
85
+ const unlockInteraction: HardwareUiInteractionMeta | undefined = shouldCoordinateUi
86
+ ? uiCoordinator.enterUnlockInteraction(method.name)
87
+ : undefined;
88
+ const unlockedStatus = await device.unlockDevice(
89
+ DeviceSessionPinType.Main,
90
+ shouldCoordinateUi
91
+ ? { emitUiEvent: false, interaction: unlockInteraction }
92
+ : {
93
+ source: 'unlock-coordinator',
94
+ reason: 'device-locked',
95
+ deviceOnly: true,
96
+ method: method.name,
97
+ }
98
+ );
99
+ if (unlockedStatus?.unlocked !== true) {
100
+ throw ERRORS.TypedError(
101
+ HardwareErrorCode.RuntimeError,
102
+ 'Protocol V2 device remained locked after the unlock flow.'
103
+ );
104
+ }
105
+ Log.debug('Protocol V2 pre-unlock completed', { method: method.name });
106
+ }
107
+
108
+ context.preflightCompleted = true;
109
+ }
110
+
111
+ await prepare?.();
112
+
113
+ if (shouldCoordinateUi) {
114
+ uiCoordinator.enterMethodInteraction(resolveProtocolV2UiInteraction(method));
115
+ }
116
+
117
+ return run();
118
+ }
@@ -1,5 +1,5 @@
1
1
  import { ERRORS, HardwareErrorCode } from '@onekeyfe/hd-shared';
2
- import { DeviceSessionPinType } from '@onekeyfe/hd-transport';
2
+ import { DeviceSessionPinType, DeviceSessionSeedDomain } from '@onekeyfe/hd-transport';
3
3
 
4
4
  import { DEVICE } from '../../events';
5
5
  import { assertCompleteDeviceSession } from './deviceSession';
@@ -38,32 +38,74 @@ export async function refreshProtocolV2DeviceStatus(device: Device) {
38
38
  return device.updateProtocolV2Status(status);
39
39
  }
40
40
 
41
- const negotiateEventlessWalletSession = async (device: Device) => {
42
- await device.commands.typedCall('ProtocolInfoRequest', 'ProtocolInfo', {
43
- eventless_wallet_session: true,
41
+ export async function ensureProtocolV2WalletSessionUnlocked(device: Device) {
42
+ if (!device.isProtocolV2() || device.isBootloader?.() || device.isRomloader?.()) {
43
+ return false;
44
+ }
45
+
46
+ await refreshProtocolV2DeviceStatus(device);
47
+ if (device.state?.status.unlocked !== false) {
48
+ return false;
49
+ }
50
+
51
+ await device.unlockDevice(DeviceSessionPinType.Main, {
52
+ source: 'unlock-coordinator',
53
+ reason: 'device-locked',
54
+ deviceOnly: true,
44
55
  });
56
+ return true;
57
+ }
58
+
59
+ const negotiateEventlessWalletSession = async (device: Device) => {
60
+ await device.ensureProtocolV2RuntimeContext();
45
61
  };
46
62
 
47
63
  const getDeviceSession = async (device: Device, request: DeviceSessionGet) =>
48
64
  device.commands.typedCall('DeviceSessionGet', 'DeviceSession', request);
49
65
 
66
+ const buildDeviceSessionGetRequest = ({
67
+ sessionId,
68
+ expectedPassphraseState,
69
+ deriveCardano,
70
+ }: {
71
+ sessionId?: string;
72
+ expectedPassphraseState?: string;
73
+ deriveCardano?: boolean;
74
+ } = {}): DeviceSessionGet => ({
75
+ ...(sessionId ? { session_id: sessionId } : {}),
76
+ ...(expectedPassphraseState ? { btc_test_address: expectedPassphraseState } : {}),
77
+ seed_domains:
78
+ deriveCardano === undefined
79
+ ? []
80
+ : [
81
+ DeviceSessionSeedDomain.SeedDomain_Standard,
82
+ ...(deriveCardano ? [DeviceSessionSeedDomain.SeedDomain_Cardano] : []),
83
+ ],
84
+ });
85
+
50
86
  const askDevicePassphrase = async (device: Device, requestPayload: DeviceSessionAskPassphrase) => {
51
87
  await device.commands.typedCall('DeviceSessionAskPassphrase', 'Success', requestPayload);
52
88
  await refreshProtocolV2DeviceStatus(device);
53
89
  };
54
90
 
55
- const selectDeviceSession = async (device: Device, expectedPassphraseState?: string) => {
91
+ const selectDeviceSession = async (
92
+ device: Device,
93
+ expectedPassphraseState?: string,
94
+ deriveCardano?: boolean
95
+ ) => {
56
96
  const existsAttachPinUser = device.features?.attachToPinEnabled === true;
57
97
  const metadata = {
58
98
  source: 'wallet-session-coordinator' as const,
59
99
  reason: expectedPassphraseState ? ('session-recovery' as const) : ('open-wallet' as const),
60
100
  ...(expectedPassphraseState ? { expectedPassphraseState } : {}),
61
101
  };
102
+ const passphraseInteraction = device.createProtocolV2UiPhaseMetadata?.('passphrase', 'start');
62
103
  const response = await device.commands.promptPassphrase(
63
104
  {
64
105
  existsAttachPinUser,
65
106
  deviceOnly: false,
66
107
  ...metadata,
108
+ ...(passphraseInteraction ? { interaction: passphraseInteraction } : {}),
67
109
  },
68
110
  { cancelDeviceOnReject: false }
69
111
  );
@@ -102,9 +144,16 @@ const selectDeviceSession = async (device: Device, expectedPassphraseState?: str
102
144
  'Attach PIN wallet selection is unavailable on this device.'
103
145
  );
104
146
  }
105
- device.emit(DEVICE.ATTACH_PIN_ON_DEVICE, device, metadata);
106
- await device.unlockDevice(DeviceSessionPinType.AttachToPin);
107
- return getDeviceSession(device, {});
147
+ const attachPinInteraction = device.createProtocolV2UiPhaseMetadata?.('pin', 'start');
148
+ device.emit(DEVICE.ATTACH_PIN_ON_DEVICE, device, {
149
+ ...metadata,
150
+ ...(attachPinInteraction ? { interaction: attachPinInteraction } : {}),
151
+ });
152
+ await device.unlockDevice(DeviceSessionPinType.AttachToPin, {
153
+ emitUiEvent: false,
154
+ interaction: attachPinInteraction,
155
+ });
156
+ return getDeviceSession(device, buildDeviceSessionGetRequest({ deriveCardano }));
108
157
  }
109
158
 
110
159
  if (hasHostPassphrase) {
@@ -112,12 +161,19 @@ const selectDeviceSession = async (device: Device, expectedPassphraseState?: str
112
161
  passphrase: hostPassphrase,
113
162
  on_device: false,
114
163
  });
115
- return getDeviceSession(device, {});
164
+ return getDeviceSession(device, buildDeviceSessionGetRequest({ deriveCardano }));
116
165
  }
117
166
 
118
- device.emit(DEVICE.PASSPHRASE_ON_DEVICE, device, metadata);
167
+ const passphraseOnDeviceInteraction = device.createProtocolV2UiPhaseMetadata?.(
168
+ 'passphrase-on-device',
169
+ 'start'
170
+ );
171
+ device.emit(DEVICE.PASSPHRASE_ON_DEVICE, device, {
172
+ ...metadata,
173
+ ...(passphraseOnDeviceInteraction ? { interaction: passphraseOnDeviceInteraction } : {}),
174
+ });
119
175
  await askDevicePassphrase(device, { on_device: true });
120
- return getDeviceSession(device, {});
176
+ return getDeviceSession(device, buildDeviceSessionGetRequest({ deriveCardano }));
121
177
  };
122
178
 
123
179
  export async function getProtocolV2WalletSession(
@@ -128,7 +184,11 @@ export async function getProtocolV2WalletSession(
128
184
  initSession?: boolean;
129
185
  expectedPassphraseState?: string;
130
186
  onlyMainPin?: boolean;
187
+ /** 业务安全校验遇到 Attach PIN 上下文时直接拒绝,不主动切换钱包。 */
188
+ rejectAttachPinForMainWallet?: boolean;
189
+ selectMainWalletBeforeRestore?: boolean;
131
190
  resumeOnly?: boolean;
191
+ deriveCardano?: boolean;
132
192
  }
133
193
  ) {
134
194
  const forceWalletSelection =
@@ -161,17 +221,80 @@ export async function getProtocolV2WalletSession(
161
221
  : undefined;
162
222
  let response;
163
223
  let resumed = false;
224
+ let mainPinSelected =
225
+ options?.onlyMainPin === true &&
226
+ device.features?.unlocked === true &&
227
+ device.features?.unlockedAttachPin === false;
228
+
229
+ const clearCurrentWalletSession = () => {
230
+ if (options?.onlyMainPin) {
231
+ device.clearStandardInternalState?.();
232
+ } else {
233
+ device.clearInternalState();
234
+ }
235
+ };
236
+
237
+ const rejectMismatchedAttachPinWallet = async () => {
238
+ const features = await refreshProtocolV2DeviceStatus(device);
239
+ if (features.unlockedAttachPin !== true) {
240
+ return;
241
+ }
242
+
243
+ try {
244
+ await device.lockDevice();
245
+ } catch {
246
+ // Reject the mismatched Attach PIN wallet even when older firmware cannot lock.
247
+ }
248
+ if (options?.rejectAttachPinForMainWallet) {
249
+ device.clearStandardInternalState?.();
250
+ device.clearInternalState();
251
+ } else {
252
+ clearCurrentWalletSession();
253
+ }
254
+ throw ERRORS.TypedError(HardwareErrorCode.DeviceCheckUnlockTypeError);
255
+ };
256
+
257
+ if (options?.onlyMainPin && options.rejectAttachPinForMainWallet) {
258
+ await rejectMismatchedAttachPinWallet();
259
+ }
260
+
261
+ const selectMainPin = async (force = false) => {
262
+ if (force || !mainPinSelected) {
263
+ await device.unlockDevice(DeviceSessionPinType.Main, {
264
+ source: 'wallet-session-coordinator',
265
+ reason: expectedPassphraseState ? 'session-recovery' : 'open-wallet',
266
+ deviceOnly: true,
267
+ });
268
+ mainPinSelected = true;
269
+ }
270
+ };
271
+
272
+ const selectStandardWallet = async () => {
273
+ // Main PIN authenticates the device; an empty host passphrase selects the standard derivation.
274
+ await selectMainPin();
275
+ if (device.features?.passphraseProtection === true) {
276
+ await askDevicePassphrase(device, {
277
+ passphrase: '',
278
+ on_device: false,
279
+ });
280
+ }
281
+ };
164
282
 
165
283
  if (options?.onlyMainPin) {
166
284
  expectedPassphraseState = cachedStandardSession?.passphraseState;
167
285
  if (cachedStandardSession) {
168
286
  try {
169
- if (device.features?.unlockedAttachPin === true) {
170
- await device.unlockDevice(DeviceSessionPinType.Main);
287
+ if (options?.selectMainWalletBeforeRestore) {
288
+ await selectMainPin();
171
289
  }
172
- response = await getDeviceSession(device, {
173
- session_id: cachedStandardSession.sessionId,
174
- });
290
+ response = await getDeviceSession(
291
+ device,
292
+ buildDeviceSessionGetRequest({
293
+ sessionId: cachedStandardSession.sessionId,
294
+ expectedPassphraseState,
295
+ deriveCardano: options?.deriveCardano,
296
+ })
297
+ );
175
298
  resumed = true;
176
299
  } catch (error) {
177
300
  device.clearStandardInternalState?.();
@@ -183,12 +306,22 @@ export async function getProtocolV2WalletSession(
183
306
  }
184
307
 
185
308
  if (!response) {
186
- await device.unlockDevice(DeviceSessionPinType.Main);
187
- response = await getDeviceSession(device, {});
309
+ await selectStandardWallet();
310
+ response = await getDeviceSession(
311
+ device,
312
+ buildDeviceSessionGetRequest({ deriveCardano: options?.deriveCardano })
313
+ );
188
314
  }
189
315
  } else if (cachedSessionId && expectedPassphraseState) {
190
316
  try {
191
- response = await getDeviceSession(device, { session_id: cachedSessionId });
317
+ response = await getDeviceSession(
318
+ device,
319
+ buildDeviceSessionGetRequest({
320
+ sessionId: cachedSessionId,
321
+ expectedPassphraseState,
322
+ deriveCardano: options?.deriveCardano,
323
+ })
324
+ );
192
325
  resumed = true;
193
326
  } catch (error) {
194
327
  device.clearInternalState();
@@ -197,6 +330,20 @@ export async function getProtocolV2WalletSession(
197
330
  }
198
331
  resumed = false;
199
332
  }
333
+ } else if (expectedPassphraseState) {
334
+ try {
335
+ response = await getDeviceSession(
336
+ device,
337
+ buildDeviceSessionGetRequest({
338
+ expectedPassphraseState,
339
+ deriveCardano: options?.deriveCardano,
340
+ })
341
+ );
342
+ } catch (error) {
343
+ if (options?.resumeOnly || !isWalletSessionInvalidError(error)) {
344
+ throw error;
345
+ }
346
+ }
200
347
  }
201
348
 
202
349
  if (!response) {
@@ -204,7 +351,7 @@ export async function getProtocolV2WalletSession(
204
351
  device.clearInternalState();
205
352
  throw ERRORS.TypedError(HardwareErrorCode.WalletSessionInvalid);
206
353
  }
207
- response = await selectDeviceSession(device, expectedPassphraseState);
354
+ response = await selectDeviceSession(device, expectedPassphraseState, options?.deriveCardano);
208
355
  }
209
356
 
210
357
  let { message } = response;
@@ -220,17 +367,21 @@ export async function getProtocolV2WalletSession(
220
367
  }
221
368
  if (expectedPassphraseState && expectedPassphraseState !== message.btc_test_address) {
222
369
  resumed = false;
370
+ await rejectMismatchedAttachPinWallet();
223
371
  if (options?.resumeOnly) {
224
372
  device.clearInternalState();
225
373
  throw ERRORS.TypedError(HardwareErrorCode.WalletSessionInvalid);
226
374
  }
227
375
  if (options?.onlyMainPin) {
228
376
  device.clearStandardInternalState?.();
229
- await device.unlockDevice(DeviceSessionPinType.Main);
230
- response = await getDeviceSession(device, {});
377
+ await selectStandardWallet();
378
+ response = await getDeviceSession(
379
+ device,
380
+ buildDeviceSessionGetRequest({ deriveCardano: options?.deriveCardano })
381
+ );
231
382
  } else {
232
383
  device.clearInternalState();
233
- response = await selectDeviceSession(device, expectedPassphraseState);
384
+ response = await selectDeviceSession(device, expectedPassphraseState, options?.deriveCardano);
234
385
  }
235
386
  message = response.message;
236
387
  try {
@@ -244,11 +395,8 @@ export async function getProtocolV2WalletSession(
244
395
  throw error;
245
396
  }
246
397
  if (expectedPassphraseState !== message.btc_test_address) {
247
- if (options?.onlyMainPin) {
248
- device.clearStandardInternalState?.();
249
- } else {
250
- device.clearInternalState();
251
- }
398
+ await rejectMismatchedAttachPinWallet();
399
+ clearCurrentWalletSession();
252
400
  throw ERRORS.TypedError(HardwareErrorCode.DeviceCheckPassphraseStateError);
253
401
  }
254
402
  }
@@ -269,17 +417,19 @@ export async function getProtocolV2WalletSession(
269
417
  return {
270
418
  passphraseState: message.btc_test_address,
271
419
  newSession: message.session_id,
272
- unlockedAttachPin: device.features?.unlockedAttachPin ?? undefined,
420
+ unlockedAttachPin: mainPinSelected ? false : undefined,
273
421
  resumed,
274
422
  };
275
423
  }
276
424
 
277
425
  export async function restoreProtocolV2WalletSession(
278
426
  device: Device,
279
- expectedPassphraseState: string
427
+ expectedPassphraseState: string,
428
+ deriveCardano?: boolean
280
429
  ) {
281
430
  return getProtocolV2WalletSession(device, {
282
431
  expectedPassphraseState,
283
432
  resumeOnly: true,
433
+ deriveCardano,
284
434
  });
285
435
  }
@@ -1,7 +1,6 @@
1
1
  import EventEmitter from 'events';
2
2
 
3
- import { createCoreApi } from './inject';
4
- import { unregisterFirmwareUpdateHostBinding } from './api/firmware/FirmwareHostBinding';
3
+ import { createCoreApi, createProtocolAwareCall } from './inject';
5
4
 
6
5
  import type { ConnectSettings } from './types/settings';
7
6
  import type { CoreApi } from './types/api';
@@ -20,6 +19,7 @@ export const topLevelInject = () => {
20
19
  if (!lowLevelApi) return Promise.resolve(undefined);
21
20
  return lowLevelApi.call(params);
22
21
  };
22
+ const protocolAwareCall = createProtocolAwareCall(call);
23
23
  const api: CoreApi = {
24
24
  on: <T extends string, P extends (...args: any[]) => any>(type: T, fn: P) => {
25
25
  eventEmitter.on(type, fn);
@@ -38,19 +38,18 @@ export const topLevelInject = () => {
38
38
  return lowLevelApi?.init(settings) ?? Promise.resolve(false);
39
39
  },
40
40
 
41
- call,
41
+ call: protocolAwareCall.call,
42
42
 
43
- ...createCoreApi(call),
43
+ setDeviceConnectProtocol: protocolAwareCall.setDeviceConnectProtocol,
44
+
45
+ ...createCoreApi(protocolAwareCall.call),
44
46
 
45
47
  removeAllListeners: type => {
46
48
  eventEmitter.removeAllListeners(type);
47
49
  lowLevelApi?.removeAllListeners(type);
48
50
  },
49
51
 
50
- dispose: async () => {
51
- unregisterFirmwareUpdateHostBinding();
52
- await lowLevelApi?.dispose();
53
- },
52
+ dispose: () => lowLevelApi?.dispose(),
54
53
 
55
54
  uiResponse: response => lowLevelApi?.uiResponse(response),
56
55
 
@@ -12,7 +12,6 @@ import type {
12
12
  IProtocolV2FirmwareComponentTarget,
13
13
  } from '../settings';
14
14
  import type { FirmwareUpdateV4Target } from './firmwareUpdate';
15
- import type { FirmwareUpdatePlan, FirmwareUpdatePlanForceTarget } from './firmwareUpdatePlan';
16
15
 
17
16
  export type FirmwareRelease = {
18
17
  shouldUpdate?: boolean;
@@ -60,18 +59,17 @@ export type AllFirmwareRelease = {
60
59
  status?: ProtocolV2FirmwareReleaseStatus;
61
60
  hasUpgrade?: boolean;
62
61
  required?: boolean;
62
+ resourceStatus?: 'valid' | 'outdated' | 'unknown';
63
63
  currentVersions?: DeviceStateVersions;
64
64
  components?: ProtocolV2FirmwareComponentRelease[];
65
65
  targetsToUpdate?: FirmwareUpdateV4Target[];
66
66
  release?: IFirmwareReleaseInfo;
67
- firmwareUpdatePlan?: FirmwareUpdatePlan;
68
67
  };
69
68
 
70
69
  export type CheckAllFirmwareReleaseParams = {
71
70
  checkBridgeRelease?: boolean;
71
+ checkFirmwareHash?: boolean;
72
72
  firmwareType?: EFirmwareType;
73
- platform?: 'native' | 'desktop' | 'ext' | 'web' | 'web-embed';
74
- forceUpdateTargets?: FirmwareUpdatePlanForceTarget[];
75
73
  };
76
74
 
77
75
  export declare function checkAllFirmwareRelease(
@@ -0,0 +1,7 @@
1
+ import type { HardwareConnectProtocol } from '@onekeyfe/hd-shared';
2
+
3
+ import type { Response } from '../params';
4
+
5
+ export declare function detectDeviceConnectProtocol(
6
+ connectId: string
7
+ ): Response<HardwareConnectProtocol>;
@@ -1,4 +1,15 @@
1
+ import type { DeviceSessionPinType } from '@onekeyfe/hd-transport';
1
2
  import type { Features } from '../device';
2
3
  import type { CommonParams, Response } from '../params';
3
4
 
4
- export declare function deviceUnlock(connectId: string, params?: CommonParams): Response<Features>;
5
+ export type DeviceUnlockParams = {
6
+ /**
7
+ * 限定本次解锁允许使用的 PIN 类型。省略时保持兼容行为,仅允许主 PIN。
8
+ */
9
+ pinType?: DeviceSessionPinType;
10
+ };
11
+
12
+ export declare function deviceUnlock(
13
+ connectId: string,
14
+ params?: CommonParams & DeviceUnlockParams
15
+ ): Response<Features>;
@@ -1,15 +1,9 @@
1
1
  import type { Success } from '@onekeyfe/hd-transport';
2
2
  import type { EFirmwareType } from '@onekeyfe/hd-shared';
3
- import type { FirmwareArtifactReader, FirmwareArtifactReference } from './firmwareUpdate';
4
- import type { FirmwareUpdatePreparedPlan } from './firmwareUpdatePreparedPlan';
5
3
  import type { Response } from '../params';
6
4
 
7
5
  export type DeviceUpdateBootloaderParams = {
8
- preparedPlan?: FirmwareUpdatePreparedPlan;
9
- hostBindingGeneration?: number;
10
6
  binary?: ArrayBuffer;
11
- artifact?: FirmwareArtifactReference;
12
- artifactReader?: FirmwareArtifactReader;
13
7
  firmwareType?: EFirmwareType;
14
8
  };
15
9