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

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 (202) hide show
  1. package/__tests__/AllNetworkGetAddressBase.tracing.test.ts +78 -0
  2. package/__tests__/DeviceEventRegistration.test.ts +6 -0
  3. package/__tests__/check-all-firmware-release-protocol-v2.test.ts +14 -1
  4. package/__tests__/connectSettings.test.ts +5 -47
  5. package/__tests__/deviceUploadNft.test.ts +272 -0
  6. package/__tests__/firmware-update/firmware-update-v2-download-before-boot.test.ts +31 -59
  7. package/__tests__/get-device-state.test.ts +132 -12
  8. package/__tests__/homescreen.test.ts +41 -1
  9. package/__tests__/logBlockEvent.test.ts +1 -1
  10. package/__tests__/open-wallet-session.test.ts +366 -31
  11. package/__tests__/pro2Nft.test.ts +108 -0
  12. package/__tests__/protocol-v2-resources.test.ts +204 -0
  13. package/__tests__/protocol-v2-ui-lifecycle.test.ts +91 -0
  14. package/__tests__/protocol-v2-unlock-policy.test.ts +196 -35
  15. package/__tests__/protocol-v2.test.ts +568 -957
  16. package/__tests__/protocolV2UiInteraction.test.ts +63 -0
  17. package/__tests__/public-pro2-api-boundary.test.ts +1 -0
  18. package/__tests__/uiProgressThrottle.test.ts +74 -0
  19. package/dist/api/BaseMethod.d.ts +3 -1
  20. package/dist/api/BaseMethod.d.ts.map +1 -1
  21. package/dist/api/CheckAllFirmwareRelease.d.ts.map +1 -1
  22. package/dist/api/FirmwareUpdateV2.d.ts +0 -11
  23. package/dist/api/FirmwareUpdateV2.d.ts.map +1 -1
  24. package/dist/api/FirmwareUpdateV3.d.ts +3 -7
  25. package/dist/api/FirmwareUpdateV3.d.ts.map +1 -1
  26. package/dist/api/FirmwareUpdateV4.d.ts +6 -25
  27. package/dist/api/FirmwareUpdateV4.d.ts.map +1 -1
  28. package/dist/api/GetPassphraseState.d.ts.map +1 -1
  29. package/dist/api/OpenWalletSession.d.ts.map +1 -1
  30. package/dist/api/allnetwork/AllNetworkGetAddressBase.d.ts.map +1 -1
  31. package/dist/api/device/DeviceUpdateBootloader.d.ts +1 -5
  32. package/dist/api/device/DeviceUpdateBootloader.d.ts.map +1 -1
  33. package/dist/api/firmware/FirmwareUpdateBaseMethod.d.ts +0 -8
  34. package/dist/api/firmware/FirmwareUpdateBaseMethod.d.ts.map +1 -1
  35. package/dist/api/firmware/getBinary.d.ts +0 -7
  36. package/dist/api/firmware/getBinary.d.ts.map +1 -1
  37. package/dist/api/firmware/updateBootloader.d.ts +0 -2
  38. package/dist/api/firmware/updateBootloader.d.ts.map +1 -1
  39. package/dist/api/firmware/uploadFirmware.d.ts +1 -9
  40. package/dist/api/firmware/uploadFirmware.d.ts.map +1 -1
  41. package/dist/api/helpers/protocolV2FileWrite.d.ts +2 -0
  42. package/dist/api/helpers/protocolV2FileWrite.d.ts.map +1 -1
  43. package/dist/api/index.d.ts +1 -0
  44. package/dist/api/index.d.ts.map +1 -1
  45. package/dist/api/protocol-v2/DeviceUploadNft.d.ts +31 -0
  46. package/dist/api/protocol-v2/DeviceUploadNft.d.ts.map +1 -0
  47. package/dist/api/protocol-v2/ProtocolInfoRequest.d.ts.map +1 -1
  48. package/dist/api/stellar/StellarSignTransaction.d.ts +1 -1
  49. package/dist/core/deviceEventRegistration.d.ts +2 -0
  50. package/dist/core/deviceEventRegistration.d.ts.map +1 -1
  51. package/dist/core/index.d.ts.map +1 -1
  52. package/dist/data-manager/DataManager.d.ts +3 -2
  53. package/dist/data-manager/DataManager.d.ts.map +1 -1
  54. package/dist/data-manager/connectSettings.d.ts.map +1 -1
  55. package/dist/device/Device.d.ts +24 -4
  56. package/dist/device/Device.d.ts.map +1 -1
  57. package/dist/device/DeviceCommands.d.ts +4 -4
  58. package/dist/events/device.d.ts +4 -0
  59. package/dist/events/device.d.ts.map +1 -1
  60. package/dist/events/logBlockEvent.d.ts.map +1 -1
  61. package/dist/events/ui-request.d.ts +28 -2
  62. package/dist/events/ui-request.d.ts.map +1 -1
  63. package/dist/index.d.ts +115 -184
  64. package/dist/index.d.ts.map +1 -1
  65. package/dist/index.js +2051 -3349
  66. package/dist/inject.d.ts.map +1 -1
  67. package/dist/lowLevelInject.d.ts.map +1 -1
  68. package/dist/protocols/protocol-v2/features.d.ts.map +1 -1
  69. package/dist/protocols/protocol-v2/resources.d.ts +30 -0
  70. package/dist/protocols/protocol-v2/resources.d.ts.map +1 -0
  71. package/dist/protocols/protocol-v2/uiInteraction.d.ts +7 -4
  72. package/dist/protocols/protocol-v2/uiInteraction.d.ts.map +1 -1
  73. package/dist/protocols/protocol-v2/unlockPolicy.d.ts +1 -3
  74. package/dist/protocols/protocol-v2/unlockPolicy.d.ts.map +1 -1
  75. package/dist/protocols/protocol-v2/unlockPolicyRunner.d.ts +22 -0
  76. package/dist/protocols/protocol-v2/unlockPolicyRunner.d.ts.map +1 -0
  77. package/dist/protocols/protocol-v2/walletSession.d.ts +4 -1
  78. package/dist/protocols/protocol-v2/walletSession.d.ts.map +1 -1
  79. package/dist/topLevelInject.d.ts.map +1 -1
  80. package/dist/types/api/checkAllFirmwareRelease.d.ts +1 -4
  81. package/dist/types/api/checkAllFirmwareRelease.d.ts.map +1 -1
  82. package/dist/types/api/deviceUpdateBootloader.d.ts +0 -6
  83. package/dist/types/api/deviceUpdateBootloader.d.ts.map +1 -1
  84. package/dist/types/api/export.d.ts +1 -4
  85. package/dist/types/api/export.d.ts.map +1 -1
  86. package/dist/types/api/firmwareUpdate.d.ts +0 -69
  87. package/dist/types/api/firmwareUpdate.d.ts.map +1 -1
  88. package/dist/types/api/index.d.ts +3 -10
  89. package/dist/types/api/index.d.ts.map +1 -1
  90. package/dist/types/api/protocolV2.d.ts +3 -0
  91. package/dist/types/api/protocolV2.d.ts.map +1 -1
  92. package/dist/types/settings.d.ts +12 -13
  93. package/dist/types/settings.d.ts.map +1 -1
  94. package/dist/utils/deviceFeaturesUtils.d.ts +2 -0
  95. package/dist/utils/deviceFeaturesUtils.d.ts.map +1 -1
  96. package/dist/utils/homescreen.d.ts +4 -0
  97. package/dist/utils/homescreen.d.ts.map +1 -1
  98. package/dist/utils/index.d.ts +1 -1
  99. package/dist/utils/index.d.ts.map +1 -1
  100. package/dist/utils/patch.d.ts +1 -1
  101. package/dist/utils/patch.d.ts.map +1 -1
  102. package/dist/utils/pro2Nft.d.ts +31 -0
  103. package/dist/utils/pro2Nft.d.ts.map +1 -0
  104. package/dist/utils/pro2Wallpaper.d.ts +10 -0
  105. package/dist/utils/pro2Wallpaper.d.ts.map +1 -1
  106. package/dist/utils/uiProgressThrottle.d.ts +3 -0
  107. package/dist/utils/uiProgressThrottle.d.ts.map +1 -0
  108. package/package.json +4 -4
  109. package/src/api/BaseMethod.ts +8 -10
  110. package/src/api/CheckAllFirmwareRelease.ts +40 -53
  111. package/src/api/FirmwareUpdateV2.ts +120 -298
  112. package/src/api/FirmwareUpdateV3.ts +57 -263
  113. package/src/api/FirmwareUpdateV4.ts +307 -912
  114. package/src/api/GetPassphraseState.ts +7 -1
  115. package/src/api/OpenWalletSession.ts +54 -17
  116. package/src/api/allnetwork/AllNetworkGetAddressBase.ts +32 -11
  117. package/src/api/device/DeviceUnlock.ts +1 -1
  118. package/src/api/device/DeviceUpdateBootloader.ts +6 -122
  119. package/src/api/firmware/FirmwareUpdateBaseMethod.ts +0 -57
  120. package/src/api/firmware/updateBootloader.ts +4 -19
  121. package/src/api/firmware/uploadFirmware.ts +22 -140
  122. package/src/api/helpers/protocolV2FileWrite.ts +11 -4
  123. package/src/api/index.ts +1 -0
  124. package/src/api/protocol-v2/DeviceUploadNft.ts +189 -0
  125. package/src/api/protocol-v2/ProtocolInfoRequest.ts +3 -1
  126. package/src/core/deviceEventRegistration.ts +4 -0
  127. package/src/core/index.ts +136 -77
  128. package/src/data/messages/messages-protocol-v2.json +68 -0
  129. package/src/data-manager/DataManager.ts +63 -38
  130. package/src/data-manager/connectSettings.ts +0 -11
  131. package/src/device/Device.ts +203 -21
  132. package/src/events/device.ts +4 -0
  133. package/src/events/logBlockEvent.ts +1 -0
  134. package/src/events/ui-request.ts +33 -2
  135. package/src/index.ts +0 -5
  136. package/src/inject.ts +3 -22
  137. package/src/lowLevelInject.ts +1 -5
  138. package/src/protocols/protocol-v2/features.ts +9 -2
  139. package/src/protocols/protocol-v2/resources.ts +233 -0
  140. package/src/protocols/protocol-v2/uiInteraction.ts +46 -6
  141. package/src/protocols/protocol-v2/unlockPolicy.ts +1 -105
  142. package/src/protocols/protocol-v2/unlockPolicyRunner.ts +124 -0
  143. package/src/protocols/protocol-v2/walletSession.ts +154 -30
  144. package/src/topLevelInject.ts +1 -5
  145. package/src/types/api/checkAllFirmwareRelease.ts +1 -4
  146. package/src/types/api/deviceUpdateBootloader.ts +0 -6
  147. package/src/types/api/export.ts +0 -18
  148. package/src/types/api/firmwareUpdate.ts +0 -76
  149. package/src/types/api/index.ts +2 -14
  150. package/src/types/api/protocolV2.ts +13 -0
  151. package/src/types/settings.ts +26 -13
  152. package/src/utils/deviceFeaturesUtils.ts +4 -0
  153. package/src/utils/homescreen.ts +32 -6
  154. package/src/utils/index.ts +6 -1
  155. package/src/utils/pro2Nft.ts +142 -0
  156. package/src/utils/pro2Wallpaper.ts +35 -8
  157. package/src/utils/uiProgressThrottle.ts +63 -0
  158. package/__tests__/firmware-update/check-all-firmware-release.test.ts +0 -175
  159. package/__tests__/firmware-update/firmware-artifact-source.test.ts +0 -119
  160. package/__tests__/firmware-update/firmware-host-binding.test.ts +0 -70
  161. package/__tests__/firmware-update/firmware-preparation-error.test.ts +0 -27
  162. package/__tests__/firmware-update/firmware-update-capabilities.test.ts +0 -13
  163. package/__tests__/firmware-update/firmware-update-plan.test.ts +0 -593
  164. package/__tests__/firmware-update/firmware-update-prepared-plan.test.ts +0 -213
  165. package/__tests__/firmware-update/firmware-update-v3-reconnect.test.ts +0 -58
  166. package/__tests__/firmware-update/firmware-upload-source.test.ts +0 -70
  167. package/dist/api/firmware/FirmwareArtifactSource.d.ts +0 -25
  168. package/dist/api/firmware/FirmwareArtifactSource.d.ts.map +0 -1
  169. package/dist/api/firmware/FirmwareHostBinding.d.ts +0 -6
  170. package/dist/api/firmware/FirmwareHostBinding.d.ts.map +0 -1
  171. package/dist/api/firmware/FirmwarePreparationError.d.ts +0 -3
  172. package/dist/api/firmware/FirmwarePreparationError.d.ts.map +0 -1
  173. package/dist/api/firmware/FirmwareUpdateCapabilities.d.ts +0 -3
  174. package/dist/api/firmware/FirmwareUpdateCapabilities.d.ts.map +0 -1
  175. package/dist/api/firmware/FirmwareUpdatePlan.d.ts +0 -25
  176. package/dist/api/firmware/FirmwareUpdatePlan.d.ts.map +0 -1
  177. package/dist/api/firmware/FirmwareUpdatePreparedPlan.d.ts +0 -30
  178. package/dist/api/firmware/FirmwareUpdatePreparedPlan.d.ts.map +0 -1
  179. package/dist/api/firmware/progressThrottle.d.ts +0 -3
  180. package/dist/api/firmware/progressThrottle.d.ts.map +0 -1
  181. package/dist/protocols/protocol-v2/lockedError.d.ts +0 -2
  182. package/dist/protocols/protocol-v2/lockedError.d.ts.map +0 -1
  183. package/dist/protocols/protocol-v2/unlockRetry.d.ts +0 -10
  184. package/dist/protocols/protocol-v2/unlockRetry.d.ts.map +0 -1
  185. package/dist/types/api/firmwareUpdateCapabilities.d.ts +0 -9
  186. package/dist/types/api/firmwareUpdateCapabilities.d.ts.map +0 -1
  187. package/dist/types/api/firmwareUpdatePlan.d.ts +0 -28
  188. package/dist/types/api/firmwareUpdatePlan.d.ts.map +0 -1
  189. package/dist/types/api/firmwareUpdatePreparedPlan.d.ts +0 -42
  190. package/dist/types/api/firmwareUpdatePreparedPlan.d.ts.map +0 -1
  191. package/src/api/firmware/FirmwareArtifactSource.ts +0 -278
  192. package/src/api/firmware/FirmwareHostBinding.ts +0 -100
  193. package/src/api/firmware/FirmwarePreparationError.ts +0 -12
  194. package/src/api/firmware/FirmwareUpdateCapabilities.ts +0 -9
  195. package/src/api/firmware/FirmwareUpdatePlan.ts +0 -745
  196. package/src/api/firmware/FirmwareUpdatePreparedPlan.ts +0 -392
  197. package/src/api/firmware/progressThrottle.ts +0 -44
  198. package/src/protocols/protocol-v2/lockedError.ts +0 -10
  199. package/src/protocols/protocol-v2/unlockRetry.ts +0 -109
  200. package/src/types/api/firmwareUpdateCapabilities.ts +0 -9
  201. package/src/types/api/firmwareUpdatePlan.ts +0 -38
  202. 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';
@@ -132,6 +134,8 @@ const isProtocolV2DeviceStatusUnsupportedError = (error: unknown) => {
132
134
 
133
135
  export interface DeviceEvents {
134
136
  [DEVICE.PIN]: [Device, PROTO.PinMatrixRequestType | undefined, (err: any, pin: string) => void];
137
+ [DEVICE.PIN_ON_DEVICE]: [Device, DeviceSessionPinType, ProtocolV2UiEventMetadata?];
138
+ [DEVICE.PIN_ON_DEVICE_COMPLETE]: [Device, HardwareUiInteractionMeta];
135
139
  [DEVICE.PASSPHRASE_ON_DEVICE]: [Device, PassphraseRequestPayload?];
136
140
  [DEVICE.ATTACH_PIN_ON_DEVICE]: [Device, PassphraseRequestPayload?];
137
141
  [DEVICE.BUTTON]: [Device, DeviceButtonRequestPayload];
@@ -230,6 +234,24 @@ export class Device extends EventEmitter {
230
234
  /** Force the next initialization to reload DeviceInfo after reconnect or reboot. */
231
235
  private protocolV2StateNeedsReload = false;
232
236
 
237
+ /** Runtime context negotiated once per active Protocol V2 link. */
238
+ private protocolV2RuntimeContext?: ProtocolInfo;
239
+
240
+ /** Coalesces concurrent first-use runtime negotiation on the same active link. */
241
+ private protocolV2RuntimeContextPromise?: Promise<ProtocolInfo>;
242
+
243
+ /** Invalidates an in-flight runtime-context response without adding a transport epoch. */
244
+ private protocolV2RuntimeContextRequestToken?: object;
245
+
246
+ private protocolV2UiInteraction?: {
247
+ interactionId: string;
248
+ phaseCounter: number;
249
+ sequence: number;
250
+ opened: boolean;
251
+ };
252
+
253
+ private protocolV2UiInteractionCounter = 0;
254
+
233
255
  get state() {
234
256
  return this.stateStore.getState();
235
257
  }
@@ -964,7 +986,10 @@ export class Device extends EventEmitter {
964
986
  await this.getFeatures();
965
987
  }
966
988
 
967
- if (!this.isProtocolV2() && refresh.has('verification')) {
989
+ const supportsProtocolV1OnekeyFeatures =
990
+ this.getCurrentDeviceType() === EDeviceType.Touch ||
991
+ this.getCurrentDeviceType() === EDeviceType.Pro;
992
+ if (!this.isProtocolV2() && refresh.has('verification') && supportsProtocolV1OnekeyFeatures) {
968
993
  const { message } = await this.commands.typedCall('OnekeyGetFeatures', 'OnekeyFeatures');
969
994
  this.updateState(mapProtocolV1OnekeyFeaturesToState(message), 'device-info');
970
995
  }
@@ -987,13 +1012,7 @@ export class Device extends EventEmitter {
987
1012
  }
988
1013
 
989
1014
  if (refresh.has('status') && !initializedWithDeviceInfo) {
990
- const deviceInfo =
991
- refreshedDeviceInfo ??
992
- (await requestProtocolV2DeviceInfo({
993
- commands: this.commands,
994
- request: getProtocolV2DeviceInfoRequest(),
995
- }));
996
- await this.probeProtocolV2RuntimeState(deviceInfo);
1015
+ await this.probeProtocolV2RuntimeState(refreshedDeviceInfo);
997
1016
  }
998
1017
 
999
1018
  if (refresh.has('settings') && this.state?.status.mode === 'normal') {
@@ -1064,15 +1083,58 @@ export class Device extends EventEmitter {
1064
1083
  return this.features;
1065
1084
  }
1066
1085
 
1067
- async probeProtocolV2RuntimeState(deviceInfo: ProtocolV2DeviceInfo, timeoutMs?: number) {
1068
- const protocolInfo = await requestProtocolV2ProtocolInfo({
1069
- commands: this.commands,
1070
- timeoutMs,
1071
- });
1086
+ async ensureProtocolV2RuntimeContext(timeoutMs?: number): Promise<ProtocolInfo> {
1087
+ const cachedProtocolInfo =
1088
+ this.protocolV2RuntimeContext ??
1089
+ (!this.protocolV2StateNeedsReload
1090
+ ? this.state?.raw?.protocolV2ProtocolInfo ?? undefined
1091
+ : undefined);
1092
+ if (cachedProtocolInfo) {
1093
+ this.protocolV2RuntimeContext = cachedProtocolInfo;
1094
+ return cachedProtocolInfo;
1095
+ }
1096
+
1097
+ if (this.protocolV2RuntimeContextPromise) {
1098
+ return this.protocolV2RuntimeContextPromise;
1099
+ }
1100
+
1101
+ const requestToken = {};
1102
+ const pendingRequest = (async () => {
1103
+ const protocolInfo = await requestProtocolV2ProtocolInfo({
1104
+ commands: this.commands,
1105
+ timeoutMs,
1106
+ });
1107
+ if (this.protocolV2RuntimeContextRequestToken !== requestToken) {
1108
+ throw ERRORS.TypedError(
1109
+ HardwareErrorCode.DeviceInitializeFailed,
1110
+ 'Protocol V2 runtime context was invalidated while loading.'
1111
+ );
1112
+ }
1113
+ this.protocolV2RuntimeContext = protocolInfo;
1114
+ return protocolInfo;
1115
+ })();
1116
+ this.protocolV2RuntimeContextRequestToken = requestToken;
1117
+ this.protocolV2RuntimeContextPromise = pendingRequest;
1118
+
1119
+ try {
1120
+ return await pendingRequest;
1121
+ } finally {
1122
+ if (this.protocolV2RuntimeContextPromise === pendingRequest) {
1123
+ this.protocolV2RuntimeContextPromise = undefined;
1124
+ }
1125
+ if (this.protocolV2RuntimeContextRequestToken === requestToken) {
1126
+ this.protocolV2RuntimeContextRequestToken = undefined;
1127
+ }
1128
+ }
1129
+ }
1130
+
1131
+ async probeProtocolV2RuntimeState(deviceInfo?: ProtocolV2DeviceInfo, timeoutMs?: number) {
1132
+ const protocolInfo = await this.ensureProtocolV2RuntimeContext(timeoutMs);
1072
1133
  const runtimeMode = getProtocolV2RuntimeMode(protocolInfo);
1073
- const protocolV2DeviceType = resolveProtocolV2DeviceIdentity(
1074
- deviceInfo.hw?.Device_type
1075
- ).deviceType;
1134
+ const runtimeDeviceInfo = deviceInfo ?? this.state?.raw?.protocolV2DeviceInfo;
1135
+ const protocolV2DeviceType = runtimeDeviceInfo
1136
+ ? resolveProtocolV2DeviceIdentity(runtimeDeviceInfo.hw?.Device_type).deviceType
1137
+ : this.getCurrentDeviceType();
1076
1138
  if (runtimeMode === 'romloader' && protocolV2DeviceType !== EDeviceType.Pro2) {
1077
1139
  throw ERRORS.TypedError(
1078
1140
  HardwareErrorCode.DeviceInitializeFailed,
@@ -1147,6 +1209,9 @@ export class Device extends EventEmitter {
1147
1209
  this.deviceAcquired = false;
1148
1210
  if (!this.isProtocolV2()) return;
1149
1211
  this.protocolV2StateNeedsReload = true;
1212
+ this.protocolV2RuntimeContext = undefined;
1213
+ this.protocolV2RuntimeContextPromise = undefined;
1214
+ this.protocolV2RuntimeContextRequestToken = undefined;
1150
1215
  this.clearPreInitialized();
1151
1216
  }
1152
1217
 
@@ -1155,9 +1220,14 @@ export class Device extends EventEmitter {
1155
1220
  if (deviceId) {
1156
1221
  deviceWalletSessionStore.deleteDevice(deviceId);
1157
1222
  }
1158
- if (this.isProtocolV2() && this.originalDescriptor.path !== deviceId) {
1159
- deviceWalletSessionStore.deleteDevice(this.originalDescriptor.path);
1223
+ if (this.isProtocolV2()) {
1224
+ if (this.originalDescriptor.path !== deviceId) {
1225
+ deviceWalletSessionStore.deleteDevice(this.originalDescriptor.path);
1226
+ }
1160
1227
  this.protocolV2StateNeedsReload = true;
1228
+ this.protocolV2RuntimeContext = undefined;
1229
+ this.protocolV2RuntimeContextPromise = undefined;
1230
+ this.protocolV2RuntimeContextRequestToken = undefined;
1161
1231
  }
1162
1232
 
1163
1233
  this.passphraseState = undefined;
@@ -1170,6 +1240,9 @@ export class Device extends EventEmitter {
1170
1240
  if (!this.isProtocolV2()) return;
1171
1241
 
1172
1242
  this.protocolV2StateNeedsReload = true;
1243
+ this.protocolV2RuntimeContext = undefined;
1244
+ this.protocolV2RuntimeContextPromise = undefined;
1245
+ this.protocolV2RuntimeContextRequestToken = undefined;
1173
1246
  this.clearPreInitialized();
1174
1247
  let loaderMode: 'bootloader' | 'romloader' | undefined;
1175
1248
  if (rebootType === DeviceRebootType.Bootloader) {
@@ -1522,6 +1595,85 @@ export class Device extends EventEmitter {
1522
1595
  return res.message;
1523
1596
  }
1524
1597
 
1598
+ beginProtocolV2UiInteraction() {
1599
+ if (!this.isProtocolV2()) return;
1600
+ this.protocolV2UiInteraction = {
1601
+ interactionId: `${this.instanceId}:${Date.now()}:${++this.protocolV2UiInteractionCounter}`,
1602
+ phaseCounter: 0,
1603
+ sequence: 0,
1604
+ opened: false,
1605
+ };
1606
+ }
1607
+
1608
+ createProtocolV2UiPhaseMetadata(
1609
+ phase: HardwareUiInteractionMeta['phase'],
1610
+ transition: HardwareUiInteractionMeta['transition'],
1611
+ options?: {
1612
+ phaseId?: string;
1613
+ outcome?: HardwareUiInteractionMeta['outcome'];
1614
+ }
1615
+ ): HardwareUiInteractionMeta | undefined {
1616
+ if (!this.isProtocolV2()) return undefined;
1617
+ if (!this.protocolV2UiInteraction) this.beginProtocolV2UiInteraction();
1618
+
1619
+ const interaction = this.protocolV2UiInteraction;
1620
+ if (!interaction) return undefined;
1621
+ const phaseId =
1622
+ options?.phaseId ?? `${interaction.interactionId}:phase-${++interaction.phaseCounter}`;
1623
+ interaction.opened = true;
1624
+ interaction.sequence += 1;
1625
+
1626
+ return {
1627
+ interactionId: interaction.interactionId,
1628
+ phaseId,
1629
+ sequence: interaction.sequence,
1630
+ phase,
1631
+ transition,
1632
+ ...(options?.outcome ? { outcome: options.outcome } : {}),
1633
+ protocol: 'V2',
1634
+ };
1635
+ }
1636
+
1637
+ completeProtocolV2UiPhase(
1638
+ phase: HardwareUiInteractionMeta,
1639
+ outcome: HardwareUiInteractionMeta['outcome'] = 'succeeded'
1640
+ ) {
1641
+ return this.createProtocolV2UiPhaseMetadata(phase.phase, 'complete', {
1642
+ phaseId: phase.phaseId,
1643
+ outcome,
1644
+ });
1645
+ }
1646
+
1647
+ finishProtocolV2UiInteraction(
1648
+ outcome?: HardwareUiInteractionMeta['outcome'],
1649
+ options?: { ensureMetadata?: boolean }
1650
+ ) {
1651
+ const interaction = this.protocolV2UiInteraction;
1652
+ if (!interaction || (!interaction.opened && !options?.ensureMetadata)) {
1653
+ this.protocolV2UiInteraction = undefined;
1654
+ return undefined;
1655
+ }
1656
+
1657
+ const phaseId = `${interaction.interactionId}:phase-${Math.max(interaction.phaseCounter, 1)}`;
1658
+ interaction.opened = true;
1659
+ interaction.sequence += 1;
1660
+ const metadata: HardwareUiInteractionMeta = {
1661
+ interactionId: interaction.interactionId,
1662
+ phaseId,
1663
+ sequence: interaction.sequence,
1664
+ phase: 'processing',
1665
+ transition: 'finish',
1666
+ outcome: outcome ?? 'succeeded',
1667
+ protocol: 'V2',
1668
+ };
1669
+ this.protocolV2UiInteraction = undefined;
1670
+ return metadata;
1671
+ }
1672
+
1673
+ hasOpenProtocolV2UiInteraction() {
1674
+ return this.protocolV2UiInteraction?.opened === true;
1675
+ }
1676
+
1525
1677
  supportUnlockVersionRange(): DeviceFirmwareRange {
1526
1678
  // This range applies to Protocol V1 Pro devices; Pro2 has a dedicated unlock flow.
1527
1679
  return {
@@ -1531,10 +1683,33 @@ export class Device extends EventEmitter {
1531
1683
  };
1532
1684
  }
1533
1685
 
1534
- async unlockDevice(pinType: DeviceSessionPinType = DeviceSessionPinType.Main) {
1686
+ async unlockDevice(
1687
+ pinType?: DeviceSessionPinType,
1688
+ options?: ProtocolV2UiEventMetadata & { emitUiEvent?: boolean }
1689
+ ) {
1535
1690
  if (this.isProtocolV2()) {
1691
+ const requestedPinType = pinType ?? DeviceSessionPinType.Main;
1692
+ const interaction =
1693
+ options?.interaction ??
1694
+ (options?.emitUiEvent === false
1695
+ ? undefined
1696
+ : this.createProtocolV2UiPhaseMetadata('pin', 'start'));
1697
+ if (options?.emitUiEvent !== false) {
1698
+ this.emit(DEVICE.PIN_ON_DEVICE, this, requestedPinType, {
1699
+ source: options?.source ?? 'unlock-coordinator',
1700
+ reason: options?.reason ?? 'device-unlock',
1701
+ deviceOnly: options?.deviceOnly ?? true,
1702
+ completion: options?.completion,
1703
+ method: options?.method,
1704
+ page: options?.page,
1705
+ operation: options?.operation,
1706
+ interaction: options?.interaction ?? interaction,
1707
+ });
1708
+ }
1536
1709
  try {
1537
- await this.commands.typedCall('DeviceSessionAskPin', 'Success', { type: pinType });
1710
+ await this.commands.typedCall('DeviceSessionAskPin', 'Success', {
1711
+ type: requestedPinType,
1712
+ });
1538
1713
  } catch (error) {
1539
1714
  const errorText =
1540
1715
  error instanceof Error
@@ -1546,6 +1721,11 @@ export class Device extends EventEmitter {
1546
1721
  throw error;
1547
1722
  }
1548
1723
 
1724
+ const completion = interaction ? this.completeProtocolV2UiPhase(interaction) : undefined;
1725
+ if (completion) {
1726
+ this.emit(DEVICE.PIN_ON_DEVICE_COMPLETE, this, completion);
1727
+ }
1728
+
1549
1729
  const status = await requestProtocolV2DeviceStatus({ commands: this.commands });
1550
1730
  return this.updateProtocolV2Status(status);
1551
1731
  }
@@ -1607,7 +1787,8 @@ export class Device extends EventEmitter {
1607
1787
  async checkPassphraseStateSafety(
1608
1788
  passphraseState?: string,
1609
1789
  useEmptyPassphrase?: boolean,
1610
- skipPassphraseCheck?: boolean
1790
+ skipPassphraseCheck?: boolean,
1791
+ deriveCardano?: boolean
1611
1792
  ) {
1612
1793
  if (this.isUnacquired()) return false;
1613
1794
 
@@ -1616,6 +1797,7 @@ export class Device extends EventEmitter {
1616
1797
  await getPassphraseStateWithRefreshDeviceInfo(this, {
1617
1798
  expectPassphraseState: expectedPassphraseState,
1618
1799
  onlyMainPin: useEmptyPassphrase,
1800
+ deriveCardano,
1619
1801
  });
1620
1802
 
1621
1803
  // Main wallet and unlock Attach Pin, throw safe error
@@ -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',
@@ -56,6 +56,17 @@ export type ProtocolV2UiEventSource =
56
56
 
57
57
  export type ProtocolV2UiCompletion = 'page-accepted' | 'operation-completed';
58
58
 
59
+ export type HardwareUiInteractionMeta = {
60
+ interactionId: string;
61
+ phaseId: string;
62
+ sequence: number;
63
+ phase: 'pin' | 'passphrase' | 'passphrase-on-device' | 'button' | 'processing';
64
+ transition: 'start' | 'complete' | 'finish';
65
+ outcome?: 'submitted' | 'succeeded' | 'failed' | 'cancelled' | 'disconnected';
66
+ protocol: 'V2';
67
+ device?: Device;
68
+ };
69
+
59
70
  export type ProtocolV2UiEventMetadata = {
60
71
  source?: ProtocolV2UiEventSource;
61
72
  reason?: string;
@@ -64,12 +75,29 @@ export type ProtocolV2UiEventMetadata = {
64
75
  method?: string;
65
76
  page?: string | number;
66
77
  operation?: string;
78
+ interaction?: HardwareUiInteractionMeta;
67
79
  };
68
80
 
81
+ export type UiRequestWindowClose =
82
+ | {
83
+ type: typeof UI_REQUEST.CLOSE_UI_WINDOW;
84
+ payload: HardwareUiInteractionMeta;
85
+ }
86
+ | {
87
+ type: typeof UI_REQUEST.CLOSE_UI_PIN_WINDOW;
88
+ payload: HardwareUiInteractionMeta;
89
+ }
90
+ | {
91
+ type: typeof UI_REQUEST.CLOSE_UI_WINDOW;
92
+ payload?: undefined;
93
+ }
94
+ | {
95
+ type: typeof UI_REQUEST.CLOSE_UI_PIN_WINDOW;
96
+ payload?: undefined;
97
+ };
98
+
69
99
  export interface UiRequestWithoutPayload {
70
100
  type:
71
- | typeof UI_REQUEST.CLOSE_UI_WINDOW
72
- | typeof UI_REQUEST.CLOSE_UI_PIN_WINDOW
73
101
  | typeof UI_REQUEST.BLUETOOTH_PERMISSION
74
102
  | typeof UI_REQUEST.BLUETOOTH_UNSUPPORTED
75
103
  | typeof UI_REQUEST.BLUETOOTH_POWERED_OFF
@@ -111,6 +139,7 @@ export interface UiRequestPassphrase {
111
139
  source?: 'wallet-session-coordinator';
112
140
  reason?: 'open-wallet' | 'session-recovery';
113
141
  expectedPassphraseState?: string;
142
+ interaction?: HardwareUiInteractionMeta;
114
143
  };
115
144
  }
116
145
 
@@ -121,6 +150,7 @@ export interface UiRequestPassphraseOnDevice {
121
150
  passphraseState?: string;
122
151
  source?: 'wallet-session-coordinator';
123
152
  reason?: 'open-wallet' | 'session-recovery';
153
+ interaction?: HardwareUiInteractionMeta;
124
154
  };
125
155
  }
126
156
 
@@ -191,6 +221,7 @@ export interface PreviousAddressResult {
191
221
 
192
222
  export type UiEvent =
193
223
  | UiRequestWithoutPayload
224
+ | UiRequestWindowClose
194
225
  | UiRequestDeviceAction
195
226
  | UiRequestButton
196
227
  | UiRequestPassphraseOnDevice
package/src/index.ts CHANGED
@@ -19,11 +19,6 @@ export * from './types';
19
19
  export { whitelist, whitelistExtension } from './data/config';
20
20
  export { executeCallback, cleanupCallback };
21
21
  export { preloadSessionCache } from './device/Device';
22
- export {
23
- getFirmwareUpdateHostBindingGeneration,
24
- registerFirmwareUpdateHostBinding,
25
- unregisterFirmwareUpdateHostBinding,
26
- } from './api/firmware/FirmwareHostBinding';
27
22
 
28
23
  const HardwareSdk = ({
29
24
  init,
package/src/inject.ts CHANGED
@@ -1,17 +1,6 @@
1
- import { getFirmwareUpdateCapabilities } from './api/firmware/FirmwareUpdateCapabilities';
2
- import {
3
- prepareFirmwareUpdatePlan,
4
- validateFirmwareUpdatePreparedPlan,
5
- } from './api/firmware/FirmwareUpdatePreparedPlan';
6
- import {
7
- getFirmwareUpdateHostBindingGeneration,
8
- registerFirmwareUpdateHostBinding,
9
- unregisterFirmwareUpdateHostBinding,
10
- } from './api/firmware/FirmwareHostBinding';
11
-
1
+ import type { Unsuccessful } from './types';
12
2
  import type { EventEmitter } from 'events';
13
3
  import type { CallMethod } from './events';
14
- import type { Unsuccessful } from './types';
15
4
  import type { CoreApi } from './types/api';
16
5
  import type { AllNetworkAddress } from './types/api/allNetworkGetAddress';
17
6
 
@@ -79,10 +68,7 @@ export const inject = ({
79
68
 
80
69
  call,
81
70
 
82
- dispose: async () => {
83
- unregisterFirmwareUpdateHostBinding();
84
- await dispose();
85
- },
71
+ dispose,
86
72
 
87
73
  uiResponse,
88
74
 
@@ -113,12 +99,6 @@ export const createCoreApi = (
113
99
  | 'updateSettings'
114
100
  | 'switchTransport'
115
101
  > => ({
116
- getFirmwareUpdateCapabilities,
117
- registerFirmwareUpdateHostBinding,
118
- unregisterFirmwareUpdateHostBinding,
119
- getFirmwareUpdateHostBindingGeneration,
120
- prepareFirmwareUpdatePlan,
121
- validateFirmwareUpdatePreparedPlan,
122
102
  getLogs: () => call({ method: 'getLogs' }),
123
103
  clearSessionCache: params => call({ ...params, method: 'clearSessionCache' }),
124
104
  /**
@@ -182,6 +162,7 @@ export const createCoreApi = (
182
162
  call({ ...params, connectId, method: 'deviceGetOnboardingStatus' }),
183
163
  deviceUploadWallpaper: (connectId, params) =>
184
164
  call({ ...params, connectId, method: 'deviceUploadWallpaper' }),
165
+ deviceUploadNft: (connectId, params) => call({ ...params, connectId, method: 'deviceUploadNft' }),
185
166
  uploadPortfolio: (connectId, params) => call({ ...params, connectId, method: 'uploadPortfolio' }),
186
167
  deviceRecovery: (connectId, params) => call({ ...params, connectId, method: 'deviceRecovery' }),
187
168
  deviceReset: (connectId, params) => call({ ...params, connectId, method: 'deviceReset' }),
@@ -1,5 +1,4 @@
1
1
  import { createCoreApi } from './inject';
2
- import { unregisterFirmwareUpdateHostBinding } from './api/firmware/FirmwareHostBinding';
3
2
 
4
3
  import type { EventEmitter } from 'events';
5
4
  import type { CallMethod, CoreMessage } from './events';
@@ -44,10 +43,7 @@ export const lowLevelInject = ({
44
43
 
45
44
  call,
46
45
 
47
- dispose: async () => {
48
- unregisterFirmwareUpdateHostBinding();
49
- await dispose();
50
- },
46
+ dispose,
51
47
 
52
48
  uiResponse,
53
49
 
@@ -168,8 +168,15 @@ export async function requestProtocolV2ProtocolInfo({
168
168
  }): Promise<ProtocolInfo> {
169
169
  const response =
170
170
  timeoutMs === undefined
171
- ? await commands.typedCall('ProtocolInfoRequest', 'ProtocolInfo', {})
172
- : await commands.typedCall('ProtocolInfoRequest', 'ProtocolInfo', {}, { timeoutMs });
171
+ ? await commands.typedCall('ProtocolInfoRequest', 'ProtocolInfo', {
172
+ eventless_wallet_session: true,
173
+ })
174
+ : await commands.typedCall(
175
+ 'ProtocolInfoRequest',
176
+ 'ProtocolInfo',
177
+ { eventless_wallet_session: true },
178
+ { timeoutMs }
179
+ );
173
180
  return response.message;
174
181
  }
175
182