@onekeyfe/hd-core 1.2.0-alpha.40 → 1.2.0-alpha.41

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 (195) hide show
  1. package/__tests__/AllNetworkGetAddressBase.tracing.test.ts +0 -78
  2. package/__tests__/DeviceEventRegistration.test.ts +0 -6
  3. package/__tests__/connectSettings.test.ts +47 -5
  4. package/__tests__/firmware-update/check-all-firmware-release.test.ts +175 -0
  5. package/__tests__/firmware-update/firmware-artifact-source.test.ts +119 -0
  6. package/__tests__/firmware-update/firmware-host-binding.test.ts +70 -0
  7. package/__tests__/firmware-update/firmware-preparation-error.test.ts +27 -0
  8. package/__tests__/firmware-update/firmware-update-capabilities.test.ts +13 -0
  9. package/__tests__/firmware-update/firmware-update-plan.test.ts +593 -0
  10. package/__tests__/firmware-update/firmware-update-prepared-plan.test.ts +213 -0
  11. package/__tests__/firmware-update/firmware-update-v2-download-before-boot.test.ts +59 -31
  12. package/__tests__/firmware-update/firmware-update-v3-reconnect.test.ts +58 -0
  13. package/__tests__/firmware-update/firmware-upload-source.test.ts +70 -0
  14. package/__tests__/get-device-state.test.ts +12 -132
  15. package/__tests__/homescreen.test.ts +1 -41
  16. package/__tests__/logBlockEvent.test.ts +1 -1
  17. package/__tests__/open-wallet-session.test.ts +18 -259
  18. package/__tests__/protocol-v2-unlock-policy.test.ts +35 -86
  19. package/__tests__/protocol-v2.test.ts +632 -333
  20. package/__tests__/public-pro2-api-boundary.test.ts +0 -1
  21. package/dist/api/BaseMethod.d.ts +1 -3
  22. package/dist/api/BaseMethod.d.ts.map +1 -1
  23. package/dist/api/CheckAllFirmwareRelease.d.ts.map +1 -1
  24. package/dist/api/FirmwareUpdateV2.d.ts +11 -0
  25. package/dist/api/FirmwareUpdateV2.d.ts.map +1 -1
  26. package/dist/api/FirmwareUpdateV3.d.ts +7 -3
  27. package/dist/api/FirmwareUpdateV3.d.ts.map +1 -1
  28. package/dist/api/FirmwareUpdateV4.d.ts +22 -5
  29. package/dist/api/FirmwareUpdateV4.d.ts.map +1 -1
  30. package/dist/api/GetPassphraseState.d.ts.map +1 -1
  31. package/dist/api/OpenWalletSession.d.ts.map +1 -1
  32. package/dist/api/allnetwork/AllNetworkGetAddressBase.d.ts.map +1 -1
  33. package/dist/api/device/DeviceUpdateBootloader.d.ts +5 -1
  34. package/dist/api/device/DeviceUpdateBootloader.d.ts.map +1 -1
  35. package/dist/api/firmware/FirmwareArtifactSource.d.ts +25 -0
  36. package/dist/api/firmware/FirmwareArtifactSource.d.ts.map +1 -0
  37. package/dist/api/firmware/FirmwareHostBinding.d.ts +6 -0
  38. package/dist/api/firmware/FirmwareHostBinding.d.ts.map +1 -0
  39. package/dist/api/firmware/FirmwarePreparationError.d.ts +3 -0
  40. package/dist/api/firmware/FirmwarePreparationError.d.ts.map +1 -0
  41. package/dist/api/firmware/FirmwareUpdateBaseMethod.d.ts +8 -0
  42. package/dist/api/firmware/FirmwareUpdateBaseMethod.d.ts.map +1 -1
  43. package/dist/api/firmware/FirmwareUpdateCapabilities.d.ts +3 -0
  44. package/dist/api/firmware/FirmwareUpdateCapabilities.d.ts.map +1 -0
  45. package/dist/api/firmware/FirmwareUpdatePlan.d.ts +25 -0
  46. package/dist/api/firmware/FirmwareUpdatePlan.d.ts.map +1 -0
  47. package/dist/api/firmware/FirmwareUpdatePreparedPlan.d.ts +30 -0
  48. package/dist/api/firmware/FirmwareUpdatePreparedPlan.d.ts.map +1 -0
  49. package/dist/api/firmware/getBinary.d.ts +7 -0
  50. package/dist/api/firmware/getBinary.d.ts.map +1 -1
  51. package/dist/api/firmware/progressThrottle.d.ts +3 -0
  52. package/dist/api/firmware/progressThrottle.d.ts.map +1 -0
  53. package/dist/api/firmware/updateBootloader.d.ts +2 -0
  54. package/dist/api/firmware/updateBootloader.d.ts.map +1 -1
  55. package/dist/api/firmware/uploadFirmware.d.ts +9 -1
  56. package/dist/api/firmware/uploadFirmware.d.ts.map +1 -1
  57. package/dist/api/helpers/protocolV2FileWrite.d.ts +0 -2
  58. package/dist/api/helpers/protocolV2FileWrite.d.ts.map +1 -1
  59. package/dist/api/index.d.ts +0 -1
  60. package/dist/api/index.d.ts.map +1 -1
  61. package/dist/api/protocol-v2/ProtocolInfoRequest.d.ts.map +1 -1
  62. package/dist/api/stellar/StellarSignTransaction.d.ts +1 -1
  63. package/dist/core/deviceEventRegistration.d.ts +0 -2
  64. package/dist/core/deviceEventRegistration.d.ts.map +1 -1
  65. package/dist/core/index.d.ts.map +1 -1
  66. package/dist/data-manager/DataManager.d.ts +1 -0
  67. package/dist/data-manager/DataManager.d.ts.map +1 -1
  68. package/dist/data-manager/connectSettings.d.ts.map +1 -1
  69. package/dist/device/Device.d.ts +4 -22
  70. package/dist/device/Device.d.ts.map +1 -1
  71. package/dist/events/device.d.ts +0 -4
  72. package/dist/events/device.d.ts.map +1 -1
  73. package/dist/events/logBlockEvent.d.ts.map +1 -1
  74. package/dist/events/ui-request.d.ts +2 -27
  75. package/dist/events/ui-request.d.ts.map +1 -1
  76. package/dist/index.d.ts +181 -88
  77. package/dist/index.d.ts.map +1 -1
  78. package/dist/index.js +3162 -1614
  79. package/dist/inject.d.ts.map +1 -1
  80. package/dist/lowLevelInject.d.ts.map +1 -1
  81. package/dist/protocols/protocol-v2/features.d.ts.map +1 -1
  82. package/dist/protocols/protocol-v2/lockedError.d.ts +2 -0
  83. package/dist/protocols/protocol-v2/lockedError.d.ts.map +1 -0
  84. package/dist/protocols/protocol-v2/uiInteraction.d.ts +3 -3
  85. package/dist/protocols/protocol-v2/uiInteraction.d.ts.map +1 -1
  86. package/dist/protocols/protocol-v2/unlockPolicy.d.ts +3 -1
  87. package/dist/protocols/protocol-v2/unlockPolicy.d.ts.map +1 -1
  88. package/dist/protocols/protocol-v2/unlockRetry.d.ts +10 -0
  89. package/dist/protocols/protocol-v2/unlockRetry.d.ts.map +1 -0
  90. package/dist/protocols/protocol-v2/walletSession.d.ts +1 -4
  91. package/dist/protocols/protocol-v2/walletSession.d.ts.map +1 -1
  92. package/dist/topLevelInject.d.ts.map +1 -1
  93. package/dist/types/api/checkAllFirmwareRelease.d.ts +4 -0
  94. package/dist/types/api/checkAllFirmwareRelease.d.ts.map +1 -1
  95. package/dist/types/api/deviceUpdateBootloader.d.ts +6 -0
  96. package/dist/types/api/deviceUpdateBootloader.d.ts.map +1 -1
  97. package/dist/types/api/export.d.ts +4 -1
  98. package/dist/types/api/export.d.ts.map +1 -1
  99. package/dist/types/api/firmwareUpdate.d.ts +69 -0
  100. package/dist/types/api/firmwareUpdate.d.ts.map +1 -1
  101. package/dist/types/api/firmwareUpdateCapabilities.d.ts +9 -0
  102. package/dist/types/api/firmwareUpdateCapabilities.d.ts.map +1 -0
  103. package/dist/types/api/firmwareUpdatePlan.d.ts +28 -0
  104. package/dist/types/api/firmwareUpdatePlan.d.ts.map +1 -0
  105. package/dist/types/api/firmwareUpdatePreparedPlan.d.ts +42 -0
  106. package/dist/types/api/firmwareUpdatePreparedPlan.d.ts.map +1 -0
  107. package/dist/types/api/index.d.ts +10 -3
  108. package/dist/types/api/index.d.ts.map +1 -1
  109. package/dist/types/api/protocolV2.d.ts +0 -3
  110. package/dist/types/api/protocolV2.d.ts.map +1 -1
  111. package/dist/types/settings.d.ts +13 -0
  112. package/dist/types/settings.d.ts.map +1 -1
  113. package/dist/utils/deviceFeaturesUtils.d.ts +0 -2
  114. package/dist/utils/deviceFeaturesUtils.d.ts.map +1 -1
  115. package/dist/utils/homescreen.d.ts +0 -4
  116. package/dist/utils/homescreen.d.ts.map +1 -1
  117. package/dist/utils/index.d.ts +1 -1
  118. package/dist/utils/index.d.ts.map +1 -1
  119. package/dist/utils/patch.d.ts +1 -1
  120. package/dist/utils/patch.d.ts.map +1 -1
  121. package/dist/utils/pro2Wallpaper.d.ts +0 -10
  122. package/dist/utils/pro2Wallpaper.d.ts.map +1 -1
  123. package/package.json +4 -4
  124. package/src/api/BaseMethod.ts +10 -8
  125. package/src/api/CheckAllFirmwareRelease.ts +51 -6
  126. package/src/api/FirmwareUpdateV2.ts +298 -120
  127. package/src/api/FirmwareUpdateV3.ts +263 -57
  128. package/src/api/FirmwareUpdateV4.ts +748 -281
  129. package/src/api/GetPassphraseState.ts +1 -7
  130. package/src/api/OpenWalletSession.ts +17 -54
  131. package/src/api/allnetwork/AllNetworkGetAddressBase.ts +11 -32
  132. package/src/api/device/DeviceUnlock.ts +1 -1
  133. package/src/api/device/DeviceUpdateBootloader.ts +122 -6
  134. package/src/api/firmware/FirmwareArtifactSource.ts +278 -0
  135. package/src/api/firmware/FirmwareHostBinding.ts +100 -0
  136. package/src/api/firmware/FirmwarePreparationError.ts +12 -0
  137. package/src/api/firmware/FirmwareUpdateBaseMethod.ts +57 -0
  138. package/src/api/firmware/FirmwareUpdateCapabilities.ts +9 -0
  139. package/src/api/firmware/FirmwareUpdatePlan.ts +745 -0
  140. package/src/api/firmware/FirmwareUpdatePreparedPlan.ts +392 -0
  141. package/src/api/firmware/progressThrottle.ts +44 -0
  142. package/src/api/firmware/updateBootloader.ts +19 -4
  143. package/src/api/firmware/uploadFirmware.ts +140 -22
  144. package/src/api/helpers/protocolV2FileWrite.ts +4 -11
  145. package/src/api/index.ts +0 -1
  146. package/src/api/protocol-v2/ProtocolInfoRequest.ts +1 -3
  147. package/src/core/deviceEventRegistration.ts +0 -4
  148. package/src/core/index.ts +75 -118
  149. package/src/data/messages/messages-protocol-v2.json +0 -10
  150. package/src/data-manager/DataManager.ts +33 -33
  151. package/src/data-manager/connectSettings.ts +11 -0
  152. package/src/device/Device.ts +21 -193
  153. package/src/events/device.ts +0 -4
  154. package/src/events/logBlockEvent.ts +0 -1
  155. package/src/events/ui-request.ts +2 -32
  156. package/src/index.ts +5 -0
  157. package/src/inject.ts +22 -3
  158. package/src/lowLevelInject.ts +5 -1
  159. package/src/protocols/protocol-v2/features.ts +2 -9
  160. package/src/protocols/protocol-v2/lockedError.ts +10 -0
  161. package/src/protocols/protocol-v2/uiInteraction.ts +5 -31
  162. package/src/protocols/protocol-v2/unlockPolicy.ts +105 -1
  163. package/src/protocols/protocol-v2/unlockRetry.ts +109 -0
  164. package/src/protocols/protocol-v2/walletSession.ts +18 -93
  165. package/src/topLevelInject.ts +5 -1
  166. package/src/types/api/checkAllFirmwareRelease.ts +4 -0
  167. package/src/types/api/deviceUpdateBootloader.ts +6 -0
  168. package/src/types/api/export.ts +18 -0
  169. package/src/types/api/firmwareUpdate.ts +76 -0
  170. package/src/types/api/firmwareUpdateCapabilities.ts +9 -0
  171. package/src/types/api/firmwareUpdatePlan.ts +38 -0
  172. package/src/types/api/firmwareUpdatePreparedPlan.ts +53 -0
  173. package/src/types/api/index.ts +14 -2
  174. package/src/types/api/protocolV2.ts +0 -13
  175. package/src/types/settings.ts +13 -0
  176. package/src/utils/deviceFeaturesUtils.ts +0 -4
  177. package/src/utils/homescreen.ts +6 -32
  178. package/src/utils/index.ts +1 -6
  179. package/src/utils/pro2Wallpaper.ts +8 -35
  180. package/__tests__/deviceUploadNft.test.ts +0 -187
  181. package/__tests__/pro2Nft.test.ts +0 -108
  182. package/__tests__/protocol-v2-ui-lifecycle.test.ts +0 -56
  183. package/__tests__/uiProgressThrottle.test.ts +0 -74
  184. package/dist/api/protocol-v2/DeviceUploadNft.d.ts +0 -30
  185. package/dist/api/protocol-v2/DeviceUploadNft.d.ts.map +0 -1
  186. package/dist/protocols/protocol-v2/unlockPolicyRunner.d.ts +0 -22
  187. package/dist/protocols/protocol-v2/unlockPolicyRunner.d.ts.map +0 -1
  188. package/dist/utils/pro2Nft.d.ts +0 -29
  189. package/dist/utils/pro2Nft.d.ts.map +0 -1
  190. package/dist/utils/uiProgressThrottle.d.ts +0 -3
  191. package/dist/utils/uiProgressThrottle.d.ts.map +0 -1
  192. package/src/api/protocol-v2/DeviceUploadNft.ts +0 -166
  193. package/src/protocols/protocol-v2/unlockPolicyRunner.ts +0 -117
  194. package/src/utils/pro2Nft.ts +0 -91
  195. package/src/utils/uiProgressThrottle.ts +0 -63
@@ -1,6 +1,6 @@
1
1
  import { UI_REQUEST, createUiMessage } from '../../events';
2
2
 
3
- import type { CoreMessage, HardwareUiInteractionMeta, ProtocolV2UiCompletion } from '../../events';
3
+ import type { CoreMessage, ProtocolV2UiCompletion } from '../../events';
4
4
  import type { Device } from '../../device/Device';
5
5
  import type { KnownDevice } from '../../types';
6
6
 
@@ -28,15 +28,7 @@ type ProtocolV2InteractionMethod = {
28
28
  protocolV2UiInteraction?: ProtocolV2InteractionDescriptor;
29
29
  };
30
30
 
31
- type InteractionDevice = Pick<Device, 'isProtocolV2' | 'toMessageObject'> &
32
- Partial<
33
- Pick<
34
- Device,
35
- | 'createProtocolV2UiPhaseMetadata'
36
- | 'finishProtocolV2UiInteraction'
37
- | 'hasOpenProtocolV2UiInteraction'
38
- >
39
- >;
31
+ type InteractionDevice = Pick<Device, 'isProtocolV2' | 'toMessageObject'>;
40
32
  type PostMessage = (message: CoreMessage) => void;
41
33
 
42
34
  export const isProtocolV2UiEnabled = (method: { protocolV2UiMode?: 'auto' | 'none' }) =>
@@ -164,17 +156,12 @@ export class ProtocolV2UiInteractionCoordinator {
164
156
  this.methodInteraction = interaction;
165
157
  if (!interaction) return;
166
158
  const { request, ...metadata } = interaction;
167
- const interactionMeta = this.device.createProtocolV2UiPhaseMetadata?.(
168
- request === 'pin' ? 'pin' : 'button',
169
- 'start'
170
- );
171
159
 
172
160
  this.emit(
173
161
  request === 'pin' ? UI_REQUEST.REQUEST_PIN : UI_REQUEST.REQUEST_BUTTON,
174
162
  {
175
163
  device: this.device.toMessageObject() as KnownDevice,
176
164
  ...metadata,
177
- ...(interactionMeta ? { interaction: interactionMeta } : {}),
178
165
  },
179
166
  `method:${request}:${interaction.reason}:${interaction.page ?? ''}:${
180
167
  interaction.operation ?? ''
@@ -182,8 +169,7 @@ export class ProtocolV2UiInteractionCoordinator {
182
169
  );
183
170
  }
184
171
 
185
- enterUnlockInteraction(method?: string): HardwareUiInteractionMeta | undefined {
186
- const interaction = this.device.createProtocolV2UiPhaseMetadata?.('pin', 'start');
172
+ enterUnlockInteraction(method?: string) {
187
173
  this.emit(
188
174
  UI_REQUEST.REQUEST_PIN,
189
175
  {
@@ -192,11 +178,9 @@ export class ProtocolV2UiInteractionCoordinator {
192
178
  reason: 'device-locked',
193
179
  deviceOnly: true,
194
180
  method,
195
- ...(interaction ? { interaction } : {}),
196
181
  },
197
182
  `unlock:${method ?? ''}`
198
183
  );
199
- return interaction;
200
184
  }
201
185
 
202
186
  resumeMethodInteraction() {
@@ -204,19 +188,9 @@ export class ProtocolV2UiInteractionCoordinator {
204
188
  }
205
189
 
206
190
  close() {
207
- if (
208
- !this.device.isProtocolV2() ||
209
- (!this.opened && !this.device.hasOpenProtocolV2UiInteraction?.()) ||
210
- this.closed
211
- )
212
- return;
191
+ if (!this.device.isProtocolV2() || !this.opened || this.closed) return;
213
192
  this.closed = true;
214
- const interaction = this.device.finishProtocolV2UiInteraction?.();
215
- this.postMessage(
216
- interaction
217
- ? createUiMessage(UI_REQUEST.CLOSE_UI_WINDOW, interaction)
218
- : createUiMessage(UI_REQUEST.CLOSE_UI_WINDOW)
219
- );
193
+ this.postMessage(createUiMessage(UI_REQUEST.CLOSE_UI_WINDOW));
220
194
  }
221
195
 
222
196
  private emit(
@@ -1 +1,105 @@
1
- export type UnlockPolicy = 'none' | 'unlock-before-run';
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';
@@ -0,0 +1,109 @@
1
+ import { LoggerNames, getLogger } from '../../utils';
2
+ import { isDeviceLockedError } from './lockedError';
3
+ import { isProtocolV2UiEnabled, resolveProtocolV2UiInteraction } from './uiInteraction';
4
+ import { refreshProtocolV2DeviceStatus, restoreProtocolV2WalletSession } from './walletSession';
5
+
6
+ import type { BaseMethod } from '../../api/BaseMethod';
7
+ import type { Device } from '../../device/Device';
8
+ import type { ProtocolV2UiInteractionCoordinator } from './uiInteraction';
9
+
10
+ const Log = getLogger(LoggerNames.Core);
11
+
12
+ type RunnableMethod = Pick<
13
+ BaseMethod,
14
+ | 'run'
15
+ | 'unlockPolicy'
16
+ | 'protocolV2UiInteraction'
17
+ | 'protocolV2UiMode'
18
+ | 'params'
19
+ | 'payload'
20
+ | 'useDevicePassphraseState'
21
+ > & { name?: string };
22
+ type UiInteractionCoordinator = Pick<
23
+ ProtocolV2UiInteractionCoordinator,
24
+ 'enterMethodInteraction' | 'enterUnlockInteraction' | 'resumeMethodInteraction'
25
+ >;
26
+
27
+ const restoreExpectedWalletSessionAfterUnlock = async (method: RunnableMethod, device: Device) => {
28
+ const expectedPassphraseState = method.payload?.useEmptyPassphrase
29
+ ? undefined
30
+ : method.payload?.passphraseState ?? device.passphraseState;
31
+ if (
32
+ !method.useDevicePassphraseState ||
33
+ typeof expectedPassphraseState !== 'string' ||
34
+ expectedPassphraseState.length === 0
35
+ ) {
36
+ return;
37
+ }
38
+
39
+ await restoreProtocolV2WalletSession(device, expectedPassphraseState);
40
+ Log.debug('Protocol V2 wallet session restored after unlock', { method: method.name });
41
+ };
42
+
43
+ export async function runMethodWithUnlockRetry(
44
+ method: RunnableMethod,
45
+ device: Device,
46
+ uiCoordinator?: UiInteractionCoordinator
47
+ ) {
48
+ const shouldEmitUi = isProtocolV2UiEnabled(method);
49
+ const isProtocolV2 = device.isProtocolV2();
50
+ const requiresFreshStatus =
51
+ isProtocolV2 &&
52
+ method.unlockPolicy === 'unlock-before-run' &&
53
+ !device.isBootloader?.() &&
54
+ !device.isRomloader?.();
55
+
56
+ if (requiresFreshStatus) {
57
+ await refreshProtocolV2DeviceStatus(device);
58
+ }
59
+
60
+ const shouldUnlockBeforeRun =
61
+ isProtocolV2 &&
62
+ method.unlockPolicy !== 'none' &&
63
+ !device.isBootloader?.() &&
64
+ !device.isRomloader?.() &&
65
+ device.features?.unlocked === false;
66
+
67
+ if (shouldUnlockBeforeRun) {
68
+ if (shouldEmitUi) {
69
+ uiCoordinator?.enterUnlockInteraction(method.name);
70
+ }
71
+ await device.unlockDevice();
72
+ Log.debug('Protocol V2 pre-unlock completed', { method: method.name });
73
+ await restoreExpectedWalletSessionAfterUnlock(method, device);
74
+ if (shouldEmitUi) {
75
+ uiCoordinator?.enterMethodInteraction(resolveProtocolV2UiInteraction(method));
76
+ }
77
+ return method.run();
78
+ }
79
+
80
+ if (shouldEmitUi) {
81
+ uiCoordinator?.enterMethodInteraction(resolveProtocolV2UiInteraction(method));
82
+ }
83
+ try {
84
+ return await method.run();
85
+ } catch (error) {
86
+ if (!isProtocolV2 || method.unlockPolicy !== 'retry-on-locked' || !isDeviceLockedError(error)) {
87
+ throw error;
88
+ }
89
+
90
+ Log.debug('Protocol V2 unlock retry triggered', { method: method.name });
91
+ if (shouldEmitUi) {
92
+ uiCoordinator?.enterUnlockInteraction(method.name);
93
+ }
94
+ await device.unlockDevice();
95
+ Log.debug('Protocol V2 unlock completed', { method: method.name });
96
+ await restoreExpectedWalletSessionAfterUnlock(method, device);
97
+ if (shouldEmitUi) {
98
+ uiCoordinator?.resumeMethodInteraction();
99
+ }
100
+ try {
101
+ const response = await method.run();
102
+ Log.debug('Protocol V2 method retry completed', { method: method.name, success: true });
103
+ return response;
104
+ } catch (retryError) {
105
+ Log.debug('Protocol V2 method retry completed', { method: method.name, success: false });
106
+ throw retryError;
107
+ }
108
+ }
109
+ }
@@ -38,26 +38,10 @@ export async function refreshProtocolV2DeviceStatus(device: Device) {
38
38
  return device.updateProtocolV2Status(status);
39
39
  }
40
40
 
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,
55
- });
56
- return true;
57
- }
58
-
59
41
  const negotiateEventlessWalletSession = async (device: Device) => {
60
- await device.ensureProtocolV2RuntimeContext();
42
+ await device.commands.typedCall('ProtocolInfoRequest', 'ProtocolInfo', {
43
+ eventless_wallet_session: true,
44
+ });
61
45
  };
62
46
 
63
47
  const getDeviceSession = async (device: Device, request: DeviceSessionGet) =>
@@ -75,13 +59,11 @@ const selectDeviceSession = async (device: Device, expectedPassphraseState?: str
75
59
  reason: expectedPassphraseState ? ('session-recovery' as const) : ('open-wallet' as const),
76
60
  ...(expectedPassphraseState ? { expectedPassphraseState } : {}),
77
61
  };
78
- const passphraseInteraction = device.createProtocolV2UiPhaseMetadata?.('passphrase', 'start');
79
62
  const response = await device.commands.promptPassphrase(
80
63
  {
81
64
  existsAttachPinUser,
82
65
  deviceOnly: false,
83
66
  ...metadata,
84
- ...(passphraseInteraction ? { interaction: passphraseInteraction } : {}),
85
67
  },
86
68
  { cancelDeviceOnReject: false }
87
69
  );
@@ -120,15 +102,8 @@ const selectDeviceSession = async (device: Device, expectedPassphraseState?: str
120
102
  'Attach PIN wallet selection is unavailable on this device.'
121
103
  );
122
104
  }
123
- const attachPinInteraction = device.createProtocolV2UiPhaseMetadata?.('pin', 'start');
124
- device.emit(DEVICE.ATTACH_PIN_ON_DEVICE, device, {
125
- ...metadata,
126
- ...(attachPinInteraction ? { interaction: attachPinInteraction } : {}),
127
- });
128
- await device.unlockDevice(DeviceSessionPinType.AttachToPin, {
129
- emitUiEvent: false,
130
- interaction: attachPinInteraction,
131
- });
105
+ device.emit(DEVICE.ATTACH_PIN_ON_DEVICE, device, metadata);
106
+ await device.unlockDevice(DeviceSessionPinType.AttachToPin);
132
107
  return getDeviceSession(device, {});
133
108
  }
134
109
 
@@ -140,10 +115,7 @@ const selectDeviceSession = async (device: Device, expectedPassphraseState?: str
140
115
  return getDeviceSession(device, {});
141
116
  }
142
117
 
143
- device.emit(DEVICE.PASSPHRASE_ON_DEVICE, device, {
144
- ...metadata,
145
- ...(passphraseInteraction ? { interaction: passphraseInteraction } : {}),
146
- });
118
+ device.emit(DEVICE.PASSPHRASE_ON_DEVICE, device, metadata);
147
119
  await askDevicePassphrase(device, { on_device: true });
148
120
  return getDeviceSession(device, {});
149
121
  };
@@ -156,9 +128,7 @@ export async function getProtocolV2WalletSession(
156
128
  initSession?: boolean;
157
129
  expectedPassphraseState?: string;
158
130
  onlyMainPin?: boolean;
159
- selectMainWalletBeforeRestore?: boolean;
160
131
  resumeOnly?: boolean;
161
- deriveCardano?: boolean;
162
132
  }
163
133
  ) {
164
134
  const forceWalletSelection =
@@ -191,48 +161,13 @@ export async function getProtocolV2WalletSession(
191
161
  : undefined;
192
162
  let response;
193
163
  let resumed = false;
194
- let mainWalletSelected = false;
195
-
196
- const clearCurrentWalletSession = () => {
197
- if (options?.onlyMainPin) {
198
- device.clearStandardInternalState?.();
199
- } else {
200
- device.clearInternalState();
201
- }
202
- };
203
-
204
- const rejectMismatchedAttachPinWallet = async () => {
205
- const features = await refreshProtocolV2DeviceStatus(device);
206
- if (features.unlockedAttachPin !== true) {
207
- return;
208
- }
209
-
210
- try {
211
- await device.lockDevice();
212
- } catch {
213
- // Reject the mismatched Attach PIN wallet even when older firmware cannot lock.
214
- }
215
- clearCurrentWalletSession();
216
- throw ERRORS.TypedError(HardwareErrorCode.DeviceCheckUnlockTypeError);
217
- };
218
-
219
- const selectMainWallet = async (force = false) => {
220
- if (force || !mainWalletSelected) {
221
- await device.unlockDevice(DeviceSessionPinType.Main, {
222
- source: 'wallet-session-coordinator',
223
- reason: expectedPassphraseState ? 'session-recovery' : 'open-wallet',
224
- deviceOnly: true,
225
- });
226
- mainWalletSelected = true;
227
- }
228
- };
229
164
 
230
165
  if (options?.onlyMainPin) {
231
166
  expectedPassphraseState = cachedStandardSession?.passphraseState;
232
167
  if (cachedStandardSession) {
233
168
  try {
234
- if (options?.selectMainWalletBeforeRestore) {
235
- await selectMainWallet();
169
+ if (device.features?.unlockedAttachPin === true) {
170
+ await device.unlockDevice(DeviceSessionPinType.Main);
236
171
  }
237
172
  response = await getDeviceSession(device, {
238
173
  session_id: cachedStandardSession.sessionId,
@@ -248,14 +183,12 @@ export async function getProtocolV2WalletSession(
248
183
  }
249
184
 
250
185
  if (!response) {
251
- await selectMainWallet();
186
+ await device.unlockDevice(DeviceSessionPinType.Main);
252
187
  response = await getDeviceSession(device, {});
253
188
  }
254
189
  } else if (cachedSessionId && expectedPassphraseState) {
255
190
  try {
256
- response = await getDeviceSession(device, {
257
- session_id: cachedSessionId,
258
- });
191
+ response = await getDeviceSession(device, { session_id: cachedSessionId });
259
192
  resumed = true;
260
193
  } catch (error) {
261
194
  device.clearInternalState();
@@ -264,14 +197,6 @@ export async function getProtocolV2WalletSession(
264
197
  }
265
198
  resumed = false;
266
199
  }
267
- } else if (expectedPassphraseState) {
268
- try {
269
- response = await getDeviceSession(device, {});
270
- } catch (error) {
271
- if (options?.resumeOnly || !isWalletSessionInvalidError(error)) {
272
- throw error;
273
- }
274
- }
275
200
  }
276
201
 
277
202
  if (!response) {
@@ -295,14 +220,13 @@ export async function getProtocolV2WalletSession(
295
220
  }
296
221
  if (expectedPassphraseState && expectedPassphraseState !== message.btc_test_address) {
297
222
  resumed = false;
298
- await rejectMismatchedAttachPinWallet();
299
223
  if (options?.resumeOnly) {
300
224
  device.clearInternalState();
301
225
  throw ERRORS.TypedError(HardwareErrorCode.WalletSessionInvalid);
302
226
  }
303
227
  if (options?.onlyMainPin) {
304
228
  device.clearStandardInternalState?.();
305
- await selectMainWallet(true);
229
+ await device.unlockDevice(DeviceSessionPinType.Main);
306
230
  response = await getDeviceSession(device, {});
307
231
  } else {
308
232
  device.clearInternalState();
@@ -320,8 +244,11 @@ export async function getProtocolV2WalletSession(
320
244
  throw error;
321
245
  }
322
246
  if (expectedPassphraseState !== message.btc_test_address) {
323
- await rejectMismatchedAttachPinWallet();
324
- clearCurrentWalletSession();
247
+ if (options?.onlyMainPin) {
248
+ device.clearStandardInternalState?.();
249
+ } else {
250
+ device.clearInternalState();
251
+ }
325
252
  throw ERRORS.TypedError(HardwareErrorCode.DeviceCheckPassphraseStateError);
326
253
  }
327
254
  }
@@ -342,19 +269,17 @@ export async function getProtocolV2WalletSession(
342
269
  return {
343
270
  passphraseState: message.btc_test_address,
344
271
  newSession: message.session_id,
345
- unlockedAttachPin: mainWalletSelected ? false : undefined,
272
+ unlockedAttachPin: device.features?.unlockedAttachPin ?? undefined,
346
273
  resumed,
347
274
  };
348
275
  }
349
276
 
350
277
  export async function restoreProtocolV2WalletSession(
351
278
  device: Device,
352
- expectedPassphraseState: string,
353
- deriveCardano?: boolean
279
+ expectedPassphraseState: string
354
280
  ) {
355
281
  return getProtocolV2WalletSession(device, {
356
282
  expectedPassphraseState,
357
283
  resumeOnly: true,
358
- deriveCardano,
359
284
  });
360
285
  }
@@ -1,6 +1,7 @@
1
1
  import EventEmitter from 'events';
2
2
 
3
3
  import { createCoreApi } from './inject';
4
+ import { unregisterFirmwareUpdateHostBinding } from './api/firmware/FirmwareHostBinding';
4
5
 
5
6
  import type { ConnectSettings } from './types/settings';
6
7
  import type { CoreApi } from './types/api';
@@ -46,7 +47,10 @@ export const topLevelInject = () => {
46
47
  lowLevelApi?.removeAllListeners(type);
47
48
  },
48
49
 
49
- dispose: () => lowLevelApi?.dispose(),
50
+ dispose: async () => {
51
+ unregisterFirmwareUpdateHostBinding();
52
+ await lowLevelApi?.dispose();
53
+ },
50
54
 
51
55
  uiResponse: response => lowLevelApi?.uiResponse(response),
52
56
 
@@ -12,6 +12,7 @@ import type {
12
12
  IProtocolV2FirmwareComponentTarget,
13
13
  } from '../settings';
14
14
  import type { FirmwareUpdateV4Target } from './firmwareUpdate';
15
+ import type { FirmwareUpdatePlan, FirmwareUpdatePlanForceTarget } from './firmwareUpdatePlan';
15
16
 
16
17
  export type FirmwareRelease = {
17
18
  shouldUpdate?: boolean;
@@ -63,11 +64,14 @@ export type AllFirmwareRelease = {
63
64
  components?: ProtocolV2FirmwareComponentRelease[];
64
65
  targetsToUpdate?: FirmwareUpdateV4Target[];
65
66
  release?: IFirmwareReleaseInfo;
67
+ firmwareUpdatePlan?: FirmwareUpdatePlan;
66
68
  };
67
69
 
68
70
  export type CheckAllFirmwareReleaseParams = {
69
71
  checkBridgeRelease?: boolean;
70
72
  firmwareType?: EFirmwareType;
73
+ platform?: 'native' | 'desktop' | 'ext' | 'web' | 'web-embed';
74
+ forceUpdateTargets?: FirmwareUpdatePlanForceTarget[];
71
75
  };
72
76
 
73
77
  export declare function checkAllFirmwareRelease(
@@ -1,9 +1,15 @@
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';
3
5
  import type { Response } from '../params';
4
6
 
5
7
  export type DeviceUpdateBootloaderParams = {
8
+ preparedPlan?: FirmwareUpdatePreparedPlan;
9
+ hostBindingGeneration?: number;
6
10
  binary?: ArrayBuffer;
11
+ artifact?: FirmwareArtifactReference;
12
+ artifactReader?: FirmwareArtifactReader;
7
13
  firmwareType?: EFirmwareType;
8
14
  };
9
15
 
@@ -25,12 +25,30 @@ export type {
25
25
  DeviceUploadResourceResponse,
26
26
  } from './deviceUploadResource';
27
27
  export type {
28
+ FirmwareArtifactReader,
29
+ FirmwareArtifactReference,
30
+ FirmwareUpdateHostBinding,
31
+ FirmwareUpdateArtifactParams,
28
32
  FirmwareUpdateParams,
29
33
  FirmwareUpdateBinaryParams,
30
34
  FirmwareUpdateV3Params,
31
35
  FirmwareUpdateV4Params,
32
36
  FirmwareUpdateV4Target,
33
37
  } from './firmwareUpdate';
38
+ export type {
39
+ FirmwareUpdatePlan,
40
+ FirmwareUpdatePlanArtifact,
41
+ FirmwareUpdatePlanArtifactRole,
42
+ FirmwareUpdatePlanForceTarget,
43
+ FirmwareUpdatePlanTarget,
44
+ } from './firmwareUpdatePlan';
45
+ export type {
46
+ FirmwareUpdatePreparedArtifact,
47
+ FirmwareUpdatePreparedArtifactInput,
48
+ FirmwareUpdatePreparedEntry,
49
+ FirmwareUpdatePreparedPlan,
50
+ } from './firmwareUpdatePreparedPlan';
51
+ export type { FirmwareUpdateCapabilities } from './firmwareUpdateCapabilities';
34
52
  export type { AllFirmwareRelease } from './checkAllFirmwareRelease';
35
53
  export type {
36
54
  ProtocolV2FirmwareComponentRelease,