@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
@@ -74,7 +74,9 @@ import type { DeviceStateReadOptions } from '../types/api/getDeviceState';
74
74
  import type {
75
75
  DeviceButtonRequestPayload,
76
76
  DeviceFeaturesPayload,
77
+ HardwareUiInteractionMeta,
77
78
  PassphraseRequestPayload,
79
+ ProtocolV2UiEventMetadata,
78
80
  } from '../events';
79
81
  import type { PassphrasePromptResponse } from './DeviceCommands';
80
82
  import type { Deferred, HardwareConnectProtocol } from '@onekeyfe/hd-shared';
@@ -93,14 +95,10 @@ export type InitOptions = {
93
95
  passphraseState?: string;
94
96
  deriveCardano?: boolean;
95
97
  connectProtocol?: HardwareConnectProtocol;
98
+ forceProtocolDetection?: boolean;
96
99
  protocolV2DeviceInfoTimeoutMs?: number;
97
100
  /** Refresh Protocol V2 runtime state before returning discovery results. */
98
101
  refreshRuntimeState?: boolean;
99
- /**
100
- * Protocol V1 Initialize response timeout override. Reboot-wait polling passes a
101
- * short value so an unanswered probe settles before the next poll tick.
102
- */
103
- timeoutMs?: number;
104
102
  };
105
103
 
106
104
  export type RunOptions = {
@@ -137,6 +135,8 @@ const isProtocolV2DeviceStatusUnsupportedError = (error: unknown) => {
137
135
 
138
136
  export interface DeviceEvents {
139
137
  [DEVICE.PIN]: [Device, PROTO.PinMatrixRequestType | undefined, (err: any, pin: string) => void];
138
+ [DEVICE.PIN_ON_DEVICE]: [Device, DeviceSessionPinType, ProtocolV2UiEventMetadata?];
139
+ [DEVICE.PIN_ON_DEVICE_COMPLETE]: [Device, HardwareUiInteractionMeta];
140
140
  [DEVICE.PASSPHRASE_ON_DEVICE]: [Device, PassphraseRequestPayload?];
141
141
  [DEVICE.ATTACH_PIN_ON_DEVICE]: [Device, PassphraseRequestPayload?];
142
142
  [DEVICE.BUTTON]: [Device, DeviceButtonRequestPayload];
@@ -235,6 +235,24 @@ export class Device extends EventEmitter {
235
235
  /** Force the next initialization to reload DeviceInfo after reconnect or reboot. */
236
236
  private protocolV2StateNeedsReload = false;
237
237
 
238
+ /** Runtime context negotiated once per active Protocol V2 link. */
239
+ private protocolV2RuntimeContext?: ProtocolInfo;
240
+
241
+ /** Coalesces concurrent first-use runtime negotiation on the same active link. */
242
+ private protocolV2RuntimeContextPromise?: Promise<ProtocolInfo>;
243
+
244
+ /** Invalidates an in-flight runtime-context response without adding a transport epoch. */
245
+ private protocolV2RuntimeContextRequestToken?: object;
246
+
247
+ private protocolV2UiInteraction?: {
248
+ interactionId: string;
249
+ phaseCounter: number;
250
+ sequence: number;
251
+ opened: boolean;
252
+ };
253
+
254
+ private protocolV2UiInteractionCounter = 0;
255
+
238
256
  get state() {
239
257
  return this.stateStore.getState();
240
258
  }
@@ -360,7 +378,10 @@ export class Device extends EventEmitter {
360
378
  * Device connect
361
379
  * @returns {Promise<boolean>}
362
380
  */
363
- connect(connectProtocol?: HardwareConnectProtocol) {
381
+ connect(
382
+ connectProtocol?: HardwareConnectProtocol,
383
+ options?: { forceProtocolDetection?: boolean }
384
+ ) {
364
385
  const env = DataManager.getSettings('env');
365
386
  // eslint-disable-next-line no-async-promise-executor
366
387
  return new Promise<boolean>(async (resolve, reject) => {
@@ -370,7 +391,7 @@ export class Device extends EventEmitter {
370
391
  return;
371
392
  }
372
393
  try {
373
- await this.acquire(connectProtocol);
394
+ await this.acquire(connectProtocol, options);
374
395
  resolve(true);
375
396
  } catch (error) {
376
397
  reject(error);
@@ -380,7 +401,7 @@ export class Device extends EventEmitter {
380
401
  // 不存在 Session ID 或存在 Session ID 但设备在别处使用,都需要 acquire 获取最新 sessionID
381
402
  if (!this.mainId || (!this.isUsedHere() && this.originalDescriptor)) {
382
403
  try {
383
- await this.acquire(connectProtocol);
404
+ await this.acquire(connectProtocol, options);
384
405
  resolve(true);
385
406
  } catch (error) {
386
407
  reject(error);
@@ -397,11 +418,16 @@ export class Device extends EventEmitter {
397
418
 
398
419
  async acquire(
399
420
  expectedProtocol?: HardwareConnectProtocol,
400
- options?: { throwOnRunPromiseError?: boolean }
421
+ options?: { throwOnRunPromiseError?: boolean; forceProtocolDetection?: boolean }
401
422
  ) {
402
423
  const env = DataManager.getSettings('env');
403
424
  const mainIdKey = DataManager.isBleConnect(env) ? 'id' : 'session';
404
- const protocolHint = expectedProtocol ? undefined : this.originalDescriptor.protocolType;
425
+ const previousProtocol = this.originalDescriptor.protocolType;
426
+ // A protocol stored after a successful probe is authoritative. Only the explicit
427
+ // first-connection/recovery path may bypass it and probe both protocols again.
428
+ const strictProtocol = options?.forceProtocolDetection
429
+ ? undefined
430
+ : expectedProtocol ?? this.originalDescriptor.protocolType;
405
431
  try {
406
432
  let acquireResult: unknown;
407
433
  if (DataManager.isBleConnect(env)) {
@@ -413,8 +439,8 @@ export class Device extends EventEmitter {
413
439
  this.originalDescriptor.id,
414
440
  undefined,
415
441
  true,
416
- expectedProtocol,
417
- protocolHint
442
+ strictProtocol,
443
+ undefined
418
444
  );
419
445
  this.mainId = (acquireResult as any)?.uuid ?? '';
420
446
  Log.debug('Expected uuid:', this.mainId);
@@ -423,24 +449,31 @@ export class Device extends EventEmitter {
423
449
  this.originalDescriptor.path,
424
450
  this.originalDescriptor.session,
425
451
  undefined,
426
- expectedProtocol,
427
- protocolHint
452
+ strictProtocol,
453
+ undefined
428
454
  );
429
455
  this.mainId = acquireResult as string | undefined;
430
456
  Log.debug('Expected session id:', this.mainId);
431
457
  }
432
- this.deviceAcquired = true;
433
- this.updateDescriptor({ [mainIdKey]: this.mainId } as unknown as DeviceDescriptor);
434
-
435
458
  // Propagate protocol version detected during acquire.
436
459
  const detectedProtocol =
437
460
  (acquireResult as { protocolType?: HardwareConnectProtocol } | undefined)?.protocolType ??
438
461
  TransportManager.transport?.getProtocolType?.(
439
462
  DataManager.isBleConnect(env) ? this.originalDescriptor.id : this.originalDescriptor.path
440
463
  );
464
+ if (options?.forceProtocolDetection && !detectedProtocol) {
465
+ throw ERRORS.TypedError(
466
+ HardwareErrorCode.RuntimeError,
467
+ `Active protocol detection returned no protocol for ${
468
+ this.originalDescriptor.path || this.originalDescriptor.id
469
+ }`
470
+ );
471
+ }
441
472
  if (detectedProtocol) {
442
473
  this.originalDescriptor.protocolType = detectedProtocol;
443
474
  }
475
+ this.deviceAcquired = true;
476
+ this.updateDescriptor({ [mainIdKey]: this.mainId } as unknown as DeviceDescriptor);
444
477
 
445
478
  if (this.commands) {
446
479
  await this.commands.dispose(false);
@@ -448,6 +481,22 @@ export class Device extends EventEmitter {
448
481
 
449
482
  this.commands = new DeviceCommands(this, this.mainId ?? '');
450
483
  } catch (error) {
484
+ if (options?.forceProtocolDetection) {
485
+ this.originalDescriptor.protocolType = previousProtocol;
486
+ const failedSession = this.mainId;
487
+ this.deviceAcquired = false;
488
+ if (failedSession) {
489
+ try {
490
+ await this.deviceConnector?.release?.(failedSession, false);
491
+ } catch (releaseError) {
492
+ Log.debug('Failed to release an unsuccessful protocol probe', releaseError);
493
+ }
494
+ }
495
+ if (!DataManager.isBleConnect(env)) {
496
+ this.mainId = null;
497
+ this.updateDescriptor({ session: null } as DeviceDescriptor);
498
+ }
499
+ }
451
500
  if (options?.throwOnRunPromiseError) {
452
501
  throw error;
453
502
  }
@@ -856,7 +905,7 @@ export class Device extends EventEmitter {
856
905
  const initStartAt = Date.now();
857
906
  const { message } = await this.commands.typedCall('Initialize', 'Features', payload, {
858
907
  // iOS BLE bound devices can need close to 20 seconds.
859
- timeoutMs: options?.timeoutMs ?? 25 * 1000,
908
+ timeoutMs: 25 * 1000,
860
909
  });
861
910
  this.setLastInitializeDuration(Date.now() - initStartAt);
862
911
  this._updateFeatures(message, initSession);
@@ -969,7 +1018,10 @@ export class Device extends EventEmitter {
969
1018
  await this.getFeatures();
970
1019
  }
971
1020
 
972
- if (!this.isProtocolV2() && refresh.has('verification')) {
1021
+ const supportsProtocolV1OnekeyFeatures =
1022
+ this.getCurrentDeviceType() === EDeviceType.Touch ||
1023
+ this.getCurrentDeviceType() === EDeviceType.Pro;
1024
+ if (!this.isProtocolV2() && refresh.has('verification') && supportsProtocolV1OnekeyFeatures) {
973
1025
  const { message } = await this.commands.typedCall('OnekeyGetFeatures', 'OnekeyFeatures');
974
1026
  this.updateState(mapProtocolV1OnekeyFeaturesToState(message), 'device-info');
975
1027
  }
@@ -992,13 +1044,7 @@ export class Device extends EventEmitter {
992
1044
  }
993
1045
 
994
1046
  if (refresh.has('status') && !initializedWithDeviceInfo) {
995
- const deviceInfo =
996
- refreshedDeviceInfo ??
997
- (await requestProtocolV2DeviceInfo({
998
- commands: this.commands,
999
- request: getProtocolV2DeviceInfoRequest(),
1000
- }));
1001
- await this.probeProtocolV2RuntimeState(deviceInfo);
1047
+ await this.probeProtocolV2RuntimeState(refreshedDeviceInfo);
1002
1048
  }
1003
1049
 
1004
1050
  if (refresh.has('settings') && this.state?.status.mode === 'normal') {
@@ -1069,15 +1115,58 @@ export class Device extends EventEmitter {
1069
1115
  return this.features;
1070
1116
  }
1071
1117
 
1072
- async probeProtocolV2RuntimeState(deviceInfo: ProtocolV2DeviceInfo, timeoutMs?: number) {
1073
- const protocolInfo = await requestProtocolV2ProtocolInfo({
1074
- commands: this.commands,
1075
- timeoutMs,
1076
- });
1118
+ async ensureProtocolV2RuntimeContext(timeoutMs?: number): Promise<ProtocolInfo> {
1119
+ const cachedProtocolInfo =
1120
+ this.protocolV2RuntimeContext ??
1121
+ (!this.protocolV2StateNeedsReload
1122
+ ? this.state?.raw?.protocolV2ProtocolInfo ?? undefined
1123
+ : undefined);
1124
+ if (cachedProtocolInfo) {
1125
+ this.protocolV2RuntimeContext = cachedProtocolInfo;
1126
+ return cachedProtocolInfo;
1127
+ }
1128
+
1129
+ if (this.protocolV2RuntimeContextPromise) {
1130
+ return this.protocolV2RuntimeContextPromise;
1131
+ }
1132
+
1133
+ const requestToken = {};
1134
+ const pendingRequest = (async () => {
1135
+ const protocolInfo = await requestProtocolV2ProtocolInfo({
1136
+ commands: this.commands,
1137
+ timeoutMs,
1138
+ });
1139
+ if (this.protocolV2RuntimeContextRequestToken !== requestToken) {
1140
+ throw ERRORS.TypedError(
1141
+ HardwareErrorCode.DeviceInitializeFailed,
1142
+ 'Protocol V2 runtime context was invalidated while loading.'
1143
+ );
1144
+ }
1145
+ this.protocolV2RuntimeContext = protocolInfo;
1146
+ return protocolInfo;
1147
+ })();
1148
+ this.protocolV2RuntimeContextRequestToken = requestToken;
1149
+ this.protocolV2RuntimeContextPromise = pendingRequest;
1150
+
1151
+ try {
1152
+ return await pendingRequest;
1153
+ } finally {
1154
+ if (this.protocolV2RuntimeContextPromise === pendingRequest) {
1155
+ this.protocolV2RuntimeContextPromise = undefined;
1156
+ }
1157
+ if (this.protocolV2RuntimeContextRequestToken === requestToken) {
1158
+ this.protocolV2RuntimeContextRequestToken = undefined;
1159
+ }
1160
+ }
1161
+ }
1162
+
1163
+ async probeProtocolV2RuntimeState(deviceInfo?: ProtocolV2DeviceInfo, timeoutMs?: number) {
1164
+ const protocolInfo = await this.ensureProtocolV2RuntimeContext(timeoutMs);
1077
1165
  const runtimeMode = getProtocolV2RuntimeMode(protocolInfo);
1078
- const protocolV2DeviceType = resolveProtocolV2DeviceIdentity(
1079
- deviceInfo.hw?.Device_type
1080
- ).deviceType;
1166
+ const runtimeDeviceInfo = deviceInfo ?? this.state?.raw?.protocolV2DeviceInfo;
1167
+ const protocolV2DeviceType = runtimeDeviceInfo
1168
+ ? resolveProtocolV2DeviceIdentity(runtimeDeviceInfo.hw?.Device_type).deviceType
1169
+ : this.getCurrentDeviceType();
1081
1170
  if (runtimeMode === 'romloader' && protocolV2DeviceType !== EDeviceType.Pro2) {
1082
1171
  throw ERRORS.TypedError(
1083
1172
  HardwareErrorCode.DeviceInitializeFailed,
@@ -1152,6 +1241,9 @@ export class Device extends EventEmitter {
1152
1241
  this.deviceAcquired = false;
1153
1242
  if (!this.isProtocolV2()) return;
1154
1243
  this.protocolV2StateNeedsReload = true;
1244
+ this.protocolV2RuntimeContext = undefined;
1245
+ this.protocolV2RuntimeContextPromise = undefined;
1246
+ this.protocolV2RuntimeContextRequestToken = undefined;
1155
1247
  this.clearPreInitialized();
1156
1248
  }
1157
1249
 
@@ -1160,9 +1252,14 @@ export class Device extends EventEmitter {
1160
1252
  if (deviceId) {
1161
1253
  deviceWalletSessionStore.deleteDevice(deviceId);
1162
1254
  }
1163
- if (this.isProtocolV2() && this.originalDescriptor.path !== deviceId) {
1164
- deviceWalletSessionStore.deleteDevice(this.originalDescriptor.path);
1255
+ if (this.isProtocolV2()) {
1256
+ if (this.originalDescriptor.path !== deviceId) {
1257
+ deviceWalletSessionStore.deleteDevice(this.originalDescriptor.path);
1258
+ }
1165
1259
  this.protocolV2StateNeedsReload = true;
1260
+ this.protocolV2RuntimeContext = undefined;
1261
+ this.protocolV2RuntimeContextPromise = undefined;
1262
+ this.protocolV2RuntimeContextRequestToken = undefined;
1166
1263
  }
1167
1264
 
1168
1265
  this.passphraseState = undefined;
@@ -1175,6 +1272,9 @@ export class Device extends EventEmitter {
1175
1272
  if (!this.isProtocolV2()) return;
1176
1273
 
1177
1274
  this.protocolV2StateNeedsReload = true;
1275
+ this.protocolV2RuntimeContext = undefined;
1276
+ this.protocolV2RuntimeContextPromise = undefined;
1277
+ this.protocolV2RuntimeContextRequestToken = undefined;
1178
1278
  this.clearPreInitialized();
1179
1279
  let loaderMode: 'bootloader' | 'romloader' | undefined;
1180
1280
  if (rebootType === DeviceRebootType.Bootloader) {
@@ -1281,11 +1381,17 @@ export class Device extends EventEmitter {
1281
1381
  }
1282
1382
  };
1283
1383
 
1284
- if (!this.isUsedHere() || this.commands.disposed) {
1285
- const env = DataManager.getSettings('env');
1384
+ const env = DataManager.getSettings('env');
1385
+ if (options.forceProtocolDetection && env !== 'react-native' && this.isUsedHere()) {
1386
+ await this.release();
1387
+ }
1388
+
1389
+ if (options.forceProtocolDetection || !this.isUsedHere() || this.commands.disposed) {
1286
1390
  if (env !== 'react-native') {
1287
1391
  try {
1288
- await this.acquire(options.connectProtocol);
1392
+ await this.acquire(options.connectProtocol, {
1393
+ forceProtocolDetection: options.forceProtocolDetection,
1394
+ });
1289
1395
  } catch (error) {
1290
1396
  clearRunPromise();
1291
1397
  runPromise.reject(error);
@@ -1527,6 +1633,85 @@ export class Device extends EventEmitter {
1527
1633
  return res.message;
1528
1634
  }
1529
1635
 
1636
+ beginProtocolV2UiInteraction() {
1637
+ if (!this.isProtocolV2()) return;
1638
+ this.protocolV2UiInteraction = {
1639
+ interactionId: `${this.instanceId}:${Date.now()}:${++this.protocolV2UiInteractionCounter}`,
1640
+ phaseCounter: 0,
1641
+ sequence: 0,
1642
+ opened: false,
1643
+ };
1644
+ }
1645
+
1646
+ createProtocolV2UiPhaseMetadata(
1647
+ phase: HardwareUiInteractionMeta['phase'],
1648
+ transition: HardwareUiInteractionMeta['transition'],
1649
+ options?: {
1650
+ phaseId?: string;
1651
+ outcome?: HardwareUiInteractionMeta['outcome'];
1652
+ }
1653
+ ): HardwareUiInteractionMeta | undefined {
1654
+ if (!this.isProtocolV2()) return undefined;
1655
+ if (!this.protocolV2UiInteraction) this.beginProtocolV2UiInteraction();
1656
+
1657
+ const interaction = this.protocolV2UiInteraction;
1658
+ if (!interaction) return undefined;
1659
+ const phaseId =
1660
+ options?.phaseId ?? `${interaction.interactionId}:phase-${++interaction.phaseCounter}`;
1661
+ interaction.opened = true;
1662
+ interaction.sequence += 1;
1663
+
1664
+ return {
1665
+ interactionId: interaction.interactionId,
1666
+ phaseId,
1667
+ sequence: interaction.sequence,
1668
+ phase,
1669
+ transition,
1670
+ ...(options?.outcome ? { outcome: options.outcome } : {}),
1671
+ protocol: 'V2',
1672
+ };
1673
+ }
1674
+
1675
+ completeProtocolV2UiPhase(
1676
+ phase: HardwareUiInteractionMeta,
1677
+ outcome: HardwareUiInteractionMeta['outcome'] = 'succeeded'
1678
+ ) {
1679
+ return this.createProtocolV2UiPhaseMetadata(phase.phase, 'complete', {
1680
+ phaseId: phase.phaseId,
1681
+ outcome,
1682
+ });
1683
+ }
1684
+
1685
+ finishProtocolV2UiInteraction(
1686
+ outcome?: HardwareUiInteractionMeta['outcome'],
1687
+ options?: { ensureMetadata?: boolean }
1688
+ ) {
1689
+ const interaction = this.protocolV2UiInteraction;
1690
+ if (!interaction || (!interaction.opened && !options?.ensureMetadata)) {
1691
+ this.protocolV2UiInteraction = undefined;
1692
+ return undefined;
1693
+ }
1694
+
1695
+ const phaseId = `${interaction.interactionId}:phase-${Math.max(interaction.phaseCounter, 1)}`;
1696
+ interaction.opened = true;
1697
+ interaction.sequence += 1;
1698
+ const metadata: HardwareUiInteractionMeta = {
1699
+ interactionId: interaction.interactionId,
1700
+ phaseId,
1701
+ sequence: interaction.sequence,
1702
+ phase: 'processing',
1703
+ transition: 'finish',
1704
+ outcome: outcome ?? 'succeeded',
1705
+ protocol: 'V2',
1706
+ };
1707
+ this.protocolV2UiInteraction = undefined;
1708
+ return metadata;
1709
+ }
1710
+
1711
+ hasOpenProtocolV2UiInteraction() {
1712
+ return this.protocolV2UiInteraction?.opened === true;
1713
+ }
1714
+
1530
1715
  supportUnlockVersionRange(): DeviceFirmwareRange {
1531
1716
  // This range applies to Protocol V1 Pro devices; Pro2 has a dedicated unlock flow.
1532
1717
  return {
@@ -1536,10 +1721,33 @@ export class Device extends EventEmitter {
1536
1721
  };
1537
1722
  }
1538
1723
 
1539
- async unlockDevice(pinType: DeviceSessionPinType = DeviceSessionPinType.Main) {
1724
+ async unlockDevice(
1725
+ pinType?: DeviceSessionPinType,
1726
+ options?: ProtocolV2UiEventMetadata & { emitUiEvent?: boolean }
1727
+ ) {
1540
1728
  if (this.isProtocolV2()) {
1729
+ const requestedPinType = pinType ?? DeviceSessionPinType.Main;
1730
+ const interaction =
1731
+ options?.interaction ??
1732
+ (options?.emitUiEvent === false
1733
+ ? undefined
1734
+ : this.createProtocolV2UiPhaseMetadata('pin', 'start'));
1735
+ if (options?.emitUiEvent !== false) {
1736
+ this.emit(DEVICE.PIN_ON_DEVICE, this, requestedPinType, {
1737
+ source: options?.source ?? 'unlock-coordinator',
1738
+ reason: options?.reason ?? 'device-unlock',
1739
+ deviceOnly: options?.deviceOnly ?? true,
1740
+ completion: options?.completion,
1741
+ method: options?.method,
1742
+ page: options?.page,
1743
+ operation: options?.operation,
1744
+ interaction: options?.interaction ?? interaction,
1745
+ });
1746
+ }
1541
1747
  try {
1542
- await this.commands.typedCall('DeviceSessionAskPin', 'Success', { type: pinType });
1748
+ await this.commands.typedCall('DeviceSessionAskPin', 'Success', {
1749
+ type: requestedPinType,
1750
+ });
1543
1751
  } catch (error) {
1544
1752
  const errorText =
1545
1753
  error instanceof Error
@@ -1551,6 +1759,11 @@ export class Device extends EventEmitter {
1551
1759
  throw error;
1552
1760
  }
1553
1761
 
1762
+ const completion = interaction ? this.completeProtocolV2UiPhase(interaction) : undefined;
1763
+ if (completion) {
1764
+ this.emit(DEVICE.PIN_ON_DEVICE_COMPLETE, this, completion);
1765
+ }
1766
+
1554
1767
  const status = await requestProtocolV2DeviceStatus({ commands: this.commands });
1555
1768
  return this.updateProtocolV2Status(status);
1556
1769
  }
@@ -1612,7 +1825,8 @@ export class Device extends EventEmitter {
1612
1825
  async checkPassphraseStateSafety(
1613
1826
  passphraseState?: string,
1614
1827
  useEmptyPassphrase?: boolean,
1615
- skipPassphraseCheck?: boolean
1828
+ skipPassphraseCheck?: boolean,
1829
+ deriveCardano?: boolean
1616
1830
  ) {
1617
1831
  if (this.isUnacquired()) return false;
1618
1832
 
@@ -1621,6 +1835,8 @@ export class Device extends EventEmitter {
1621
1835
  await getPassphraseStateWithRefreshDeviceInfo(this, {
1622
1836
  expectPassphraseState: expectedPassphraseState,
1623
1837
  onlyMainPin: useEmptyPassphrase,
1838
+ deriveCardano,
1839
+ rejectAttachPinForMainWallet: useEmptyPassphrase === true,
1624
1840
  });
1625
1841
 
1626
1842
  // Main wallet and unlock Attach Pin, throw safe error
@@ -435,7 +435,13 @@ export class DeviceCommands {
435
435
  if (!shouldReduceDebugForCall(callType)) {
436
436
  Log.debug('_filterCommonTypes: ', {
437
437
  request: callType,
438
- response: res.type,
438
+ response:
439
+ callType === 'DeviceFirmwareUpdateStatusGet'
440
+ ? {
441
+ type: res.type,
442
+ message: getSafeTransportLogPayload(res.message, res.type),
443
+ }
444
+ : res.type,
439
445
  });
440
446
  }
441
447
  } catch (error) {
@@ -156,7 +156,9 @@ export class DevicePool extends EventEmitter {
156
156
  if (!device) {
157
157
  device = Device.fromDescriptor(descriptor);
158
158
  device.deviceConnector = this.connector;
159
- await device.connect(initOptions?.connectProtocol);
159
+ await device.connect(initOptions?.connectProtocol, {
160
+ forceProtocolDetection: initOptions?.forceProtocolDetection,
161
+ });
160
162
  try {
161
163
  await device.initialize(initOptions);
162
164
  if (initOptions?.refreshRuntimeState && device.isProtocolV2()) {
@@ -181,7 +183,10 @@ export class DevicePool extends EventEmitter {
181
183
  refreshError = error;
182
184
  }
183
185
  },
184
- { connectProtocol: initOptions.connectProtocol }
186
+ {
187
+ connectProtocol: initOptions.connectProtocol,
188
+ forceProtocolDetection: initOptions.forceProtocolDetection,
189
+ }
185
190
  );
186
191
  if (refreshError instanceof Error) throw refreshError;
187
192
  if (refreshError) throw new Error(String(refreshError));
@@ -1,4 +1,5 @@
1
1
  import type { MessageFactoryFn } from './utils';
2
+ import type { HardwareUiInteractionMeta } from './ui-request';
2
3
  import type { PROTO } from '../constants';
3
4
  import type {
4
5
  KnownDevice as Device,
@@ -26,6 +27,8 @@ export const DEVICE = {
26
27
  // onekey-transport events in protobuf format
27
28
  BUTTON: 'button',
28
29
  PIN: 'pin',
30
+ PIN_ON_DEVICE: 'pin_on_device',
31
+ PIN_ON_DEVICE_COMPLETE: 'pin_on_device_complete',
29
32
  PASSPHRASE: 'passphrase',
30
33
  PASSPHRASE_ON_DEVICE: 'passphrase_on_device',
31
34
  ATTACH_PIN_ON_DEVICE: 'attach_pin_on_device',
@@ -58,6 +61,7 @@ export type PassphraseRequestPayload = {
58
61
  source?: 'wallet-session-coordinator';
59
62
  reason?: 'open-wallet' | 'session-recovery';
60
63
  expectedPassphraseState?: string;
64
+ interaction?: HardwareUiInteractionMeta;
61
65
  };
62
66
 
63
67
  export interface DeviceButtonRequest {
@@ -10,6 +10,7 @@ export const LogBlockEvent: Set<string> = new Set([
10
10
 
11
11
  const LogLabelMethod: Set<string> = new Set([
12
12
  'openWalletSession',
13
+ 'deviceUploadNft',
13
14
  'deviceUploadWallpaper',
14
15
  'uploadPortfolio',
15
16
  'fileWrite',
@@ -1,7 +1,7 @@
1
1
  import type { Deferred } from '@onekeyfe/hd-shared';
2
2
  import type { DEVICE } from './device';
3
3
  import type { Device } from '../device/Device';
4
- import type { UiResponseEvent } from './ui-response';
4
+ import type { UiResponseCorrelation, UiResponseEvent } from './ui-response';
5
5
 
6
6
  export type UiPromiseResponse =
7
7
  | UiResponseEvent
@@ -11,4 +11,6 @@ export type UiPromise<T extends UiPromiseResponse['type']> = Deferred<
11
11
  Extract<UiPromiseResponse, { type: T }>,
12
12
  T,
13
13
  Device
14
- >;
14
+ > & {
15
+ responseCorrelation?: UiResponseCorrelation;
16
+ };
@@ -1,6 +1,7 @@
1
1
  import type { PROTO } from '../constants';
2
2
  import type { Device } from '../types';
3
3
  import type { DeviceButtonRequest } from './device';
4
+ import type { UiResponseCorrelation } from './ui-response';
4
5
  import type { MessageFactoryFn } from './utils';
5
6
 
6
7
  export const UI_EVENT = 'UI_EVENT';
@@ -56,6 +57,17 @@ export type ProtocolV2UiEventSource =
56
57
 
57
58
  export type ProtocolV2UiCompletion = 'page-accepted' | 'operation-completed';
58
59
 
60
+ export type HardwareUiInteractionMeta = {
61
+ interactionId: string;
62
+ phaseId: string;
63
+ sequence: number;
64
+ phase: 'pin' | 'passphrase' | 'passphrase-on-device' | 'button' | 'processing';
65
+ transition: 'start' | 'complete' | 'finish';
66
+ outcome?: 'submitted' | 'succeeded' | 'failed' | 'cancelled' | 'disconnected';
67
+ protocol: 'V2';
68
+ device?: Device;
69
+ };
70
+
59
71
  export type ProtocolV2UiEventMetadata = {
60
72
  source?: ProtocolV2UiEventSource;
61
73
  reason?: string;
@@ -64,12 +76,29 @@ export type ProtocolV2UiEventMetadata = {
64
76
  method?: string;
65
77
  page?: string | number;
66
78
  operation?: string;
79
+ interaction?: HardwareUiInteractionMeta;
67
80
  };
68
81
 
82
+ export type UiRequestWindowClose =
83
+ | {
84
+ type: typeof UI_REQUEST.CLOSE_UI_WINDOW;
85
+ payload: HardwareUiInteractionMeta;
86
+ }
87
+ | {
88
+ type: typeof UI_REQUEST.CLOSE_UI_PIN_WINDOW;
89
+ payload: HardwareUiInteractionMeta;
90
+ }
91
+ | {
92
+ type: typeof UI_REQUEST.CLOSE_UI_WINDOW;
93
+ payload?: undefined;
94
+ }
95
+ | {
96
+ type: typeof UI_REQUEST.CLOSE_UI_PIN_WINDOW;
97
+ payload?: undefined;
98
+ };
99
+
69
100
  export interface UiRequestWithoutPayload {
70
101
  type:
71
- | typeof UI_REQUEST.CLOSE_UI_WINDOW
72
- | typeof UI_REQUEST.CLOSE_UI_PIN_WINDOW
73
102
  | typeof UI_REQUEST.BLUETOOTH_PERMISSION
74
103
  | typeof UI_REQUEST.BLUETOOTH_UNSUPPORTED
75
104
  | typeof UI_REQUEST.BLUETOOTH_POWERED_OFF
@@ -93,6 +122,7 @@ export type UiRequestDeviceAction = {
93
122
  payload: ProtocolV2UiEventMetadata & {
94
123
  device: Device;
95
124
  type?: PROTO.PinMatrixRequestType | 'ButtonRequest_PinEntry' | 'ButtonRequest_AttachPin';
125
+ responseCorrelation?: UiResponseCorrelation;
96
126
  };
97
127
  };
98
128
 
@@ -111,6 +141,8 @@ export interface UiRequestPassphrase {
111
141
  source?: 'wallet-session-coordinator';
112
142
  reason?: 'open-wallet' | 'session-recovery';
113
143
  expectedPassphraseState?: string;
144
+ interaction?: HardwareUiInteractionMeta;
145
+ responseCorrelation?: UiResponseCorrelation;
114
146
  };
115
147
  }
116
148
 
@@ -121,6 +153,7 @@ export interface UiRequestPassphraseOnDevice {
121
153
  passphraseState?: string;
122
154
  source?: 'wallet-session-coordinator';
123
155
  reason?: 'open-wallet' | 'session-recovery';
156
+ interaction?: HardwareUiInteractionMeta;
124
157
  };
125
158
  }
126
159
 
@@ -191,6 +224,7 @@ export interface PreviousAddressResult {
191
224
 
192
225
  export type UiEvent =
193
226
  | UiRequestWithoutPayload
227
+ | UiRequestWindowClose
194
228
  | UiRequestDeviceAction
195
229
  | UiRequestButton
196
230
  | UiRequestPassphraseOnDevice
@@ -11,12 +11,22 @@ export const UI_RESPONSE = {
11
11
  'ui-receive_select-device-for-switch-firmware-web-device',
12
12
  } as const;
13
13
 
14
- export interface UiResponsePin {
14
+ export interface UiResponseCorrelation {
15
+ interactionId: string;
16
+ deviceId: string;
17
+ }
18
+
19
+ export interface UiResponseCorrelationFields {
20
+ interactionId?: string;
21
+ deviceId?: string;
22
+ }
23
+
24
+ export interface UiResponsePin extends UiResponseCorrelationFields {
15
25
  type: typeof UI_RESPONSE.RECEIVE_PIN;
16
26
  payload: string;
17
27
  }
18
28
 
19
- export interface UiResponsePassphrase {
29
+ export interface UiResponsePassphrase extends UiResponseCorrelationFields {
20
30
  type: typeof UI_RESPONSE.RECEIVE_PASSPHRASE;
21
31
  payload: {
22
32
  value: string;