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

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 (200) 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 +187 -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 +259 -18
  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 +56 -0
  14. package/__tests__/protocol-v2-unlock-policy.test.ts +86 -35
  15. package/__tests__/protocol-v2.test.ts +526 -955
  16. package/__tests__/public-pro2-api-boundary.test.ts +1 -0
  17. package/__tests__/uiProgressThrottle.test.ts +74 -0
  18. package/dist/api/BaseMethod.d.ts +3 -1
  19. package/dist/api/BaseMethod.d.ts.map +1 -1
  20. package/dist/api/CheckAllFirmwareRelease.d.ts.map +1 -1
  21. package/dist/api/FirmwareUpdateV2.d.ts +0 -11
  22. package/dist/api/FirmwareUpdateV2.d.ts.map +1 -1
  23. package/dist/api/FirmwareUpdateV3.d.ts +3 -7
  24. package/dist/api/FirmwareUpdateV3.d.ts.map +1 -1
  25. package/dist/api/FirmwareUpdateV4.d.ts +6 -25
  26. package/dist/api/FirmwareUpdateV4.d.ts.map +1 -1
  27. package/dist/api/GetPassphraseState.d.ts.map +1 -1
  28. package/dist/api/OpenWalletSession.d.ts.map +1 -1
  29. package/dist/api/allnetwork/AllNetworkGetAddressBase.d.ts.map +1 -1
  30. package/dist/api/device/DeviceUpdateBootloader.d.ts +1 -5
  31. package/dist/api/device/DeviceUpdateBootloader.d.ts.map +1 -1
  32. package/dist/api/firmware/FirmwareUpdateBaseMethod.d.ts +0 -8
  33. package/dist/api/firmware/FirmwareUpdateBaseMethod.d.ts.map +1 -1
  34. package/dist/api/firmware/getBinary.d.ts +0 -7
  35. package/dist/api/firmware/getBinary.d.ts.map +1 -1
  36. package/dist/api/firmware/updateBootloader.d.ts +0 -2
  37. package/dist/api/firmware/updateBootloader.d.ts.map +1 -1
  38. package/dist/api/firmware/uploadFirmware.d.ts +1 -9
  39. package/dist/api/firmware/uploadFirmware.d.ts.map +1 -1
  40. package/dist/api/helpers/protocolV2FileWrite.d.ts +2 -0
  41. package/dist/api/helpers/protocolV2FileWrite.d.ts.map +1 -1
  42. package/dist/api/index.d.ts +1 -0
  43. package/dist/api/index.d.ts.map +1 -1
  44. package/dist/api/protocol-v2/DeviceUploadNft.d.ts +30 -0
  45. package/dist/api/protocol-v2/DeviceUploadNft.d.ts.map +1 -0
  46. package/dist/api/protocol-v2/ProtocolInfoRequest.d.ts.map +1 -1
  47. package/dist/api/stellar/StellarSignTransaction.d.ts +1 -1
  48. package/dist/core/deviceEventRegistration.d.ts +2 -0
  49. package/dist/core/deviceEventRegistration.d.ts.map +1 -1
  50. package/dist/core/index.d.ts.map +1 -1
  51. package/dist/data-manager/DataManager.d.ts +3 -2
  52. package/dist/data-manager/DataManager.d.ts.map +1 -1
  53. package/dist/data-manager/connectSettings.d.ts.map +1 -1
  54. package/dist/device/Device.d.ts +22 -4
  55. package/dist/device/Device.d.ts.map +1 -1
  56. package/dist/events/device.d.ts +4 -0
  57. package/dist/events/device.d.ts.map +1 -1
  58. package/dist/events/logBlockEvent.d.ts.map +1 -1
  59. package/dist/events/ui-request.d.ts +27 -2
  60. package/dist/events/ui-request.d.ts.map +1 -1
  61. package/dist/index.d.ts +110 -182
  62. package/dist/index.d.ts.map +1 -1
  63. package/dist/index.js +1919 -3336
  64. package/dist/inject.d.ts.map +1 -1
  65. package/dist/lowLevelInject.d.ts.map +1 -1
  66. package/dist/protocols/protocol-v2/features.d.ts.map +1 -1
  67. package/dist/protocols/protocol-v2/resources.d.ts +30 -0
  68. package/dist/protocols/protocol-v2/resources.d.ts.map +1 -0
  69. package/dist/protocols/protocol-v2/uiInteraction.d.ts +3 -3
  70. package/dist/protocols/protocol-v2/uiInteraction.d.ts.map +1 -1
  71. package/dist/protocols/protocol-v2/unlockPolicy.d.ts +1 -3
  72. package/dist/protocols/protocol-v2/unlockPolicy.d.ts.map +1 -1
  73. package/dist/protocols/protocol-v2/unlockPolicyRunner.d.ts +22 -0
  74. package/dist/protocols/protocol-v2/unlockPolicyRunner.d.ts.map +1 -0
  75. package/dist/protocols/protocol-v2/walletSession.d.ts +4 -1
  76. package/dist/protocols/protocol-v2/walletSession.d.ts.map +1 -1
  77. package/dist/topLevelInject.d.ts.map +1 -1
  78. package/dist/types/api/checkAllFirmwareRelease.d.ts +1 -4
  79. package/dist/types/api/checkAllFirmwareRelease.d.ts.map +1 -1
  80. package/dist/types/api/deviceUpdateBootloader.d.ts +0 -6
  81. package/dist/types/api/deviceUpdateBootloader.d.ts.map +1 -1
  82. package/dist/types/api/export.d.ts +1 -4
  83. package/dist/types/api/export.d.ts.map +1 -1
  84. package/dist/types/api/firmwareUpdate.d.ts +0 -69
  85. package/dist/types/api/firmwareUpdate.d.ts.map +1 -1
  86. package/dist/types/api/index.d.ts +3 -10
  87. package/dist/types/api/index.d.ts.map +1 -1
  88. package/dist/types/api/protocolV2.d.ts +3 -0
  89. package/dist/types/api/protocolV2.d.ts.map +1 -1
  90. package/dist/types/settings.d.ts +12 -13
  91. package/dist/types/settings.d.ts.map +1 -1
  92. package/dist/utils/deviceFeaturesUtils.d.ts +2 -0
  93. package/dist/utils/deviceFeaturesUtils.d.ts.map +1 -1
  94. package/dist/utils/homescreen.d.ts +4 -0
  95. package/dist/utils/homescreen.d.ts.map +1 -1
  96. package/dist/utils/index.d.ts +1 -1
  97. package/dist/utils/index.d.ts.map +1 -1
  98. package/dist/utils/patch.d.ts +1 -1
  99. package/dist/utils/patch.d.ts.map +1 -1
  100. package/dist/utils/pro2Nft.d.ts +29 -0
  101. package/dist/utils/pro2Nft.d.ts.map +1 -0
  102. package/dist/utils/pro2Wallpaper.d.ts +10 -0
  103. package/dist/utils/pro2Wallpaper.d.ts.map +1 -1
  104. package/dist/utils/uiProgressThrottle.d.ts +3 -0
  105. package/dist/utils/uiProgressThrottle.d.ts.map +1 -0
  106. package/package.json +4 -4
  107. package/src/api/BaseMethod.ts +8 -10
  108. package/src/api/CheckAllFirmwareRelease.ts +40 -53
  109. package/src/api/FirmwareUpdateV2.ts +120 -298
  110. package/src/api/FirmwareUpdateV3.ts +57 -263
  111. package/src/api/FirmwareUpdateV4.ts +307 -912
  112. package/src/api/GetPassphraseState.ts +7 -1
  113. package/src/api/OpenWalletSession.ts +54 -17
  114. package/src/api/allnetwork/AllNetworkGetAddressBase.ts +32 -11
  115. package/src/api/device/DeviceUnlock.ts +1 -1
  116. package/src/api/device/DeviceUpdateBootloader.ts +6 -122
  117. package/src/api/firmware/FirmwareUpdateBaseMethod.ts +0 -57
  118. package/src/api/firmware/updateBootloader.ts +4 -19
  119. package/src/api/firmware/uploadFirmware.ts +22 -140
  120. package/src/api/helpers/protocolV2FileWrite.ts +11 -4
  121. package/src/api/index.ts +1 -0
  122. package/src/api/protocol-v2/DeviceUploadNft.ts +166 -0
  123. package/src/api/protocol-v2/ProtocolInfoRequest.ts +3 -1
  124. package/src/core/deviceEventRegistration.ts +4 -0
  125. package/src/core/index.ts +118 -75
  126. package/src/data/messages/messages-protocol-v2.json +53 -0
  127. package/src/data-manager/DataManager.ts +63 -38
  128. package/src/data-manager/connectSettings.ts +0 -11
  129. package/src/device/Device.ts +193 -21
  130. package/src/events/device.ts +4 -0
  131. package/src/events/logBlockEvent.ts +1 -0
  132. package/src/events/ui-request.ts +32 -2
  133. package/src/index.ts +0 -5
  134. package/src/inject.ts +3 -22
  135. package/src/lowLevelInject.ts +1 -5
  136. package/src/protocols/protocol-v2/features.ts +9 -2
  137. package/src/protocols/protocol-v2/resources.ts +233 -0
  138. package/src/protocols/protocol-v2/uiInteraction.ts +31 -5
  139. package/src/protocols/protocol-v2/unlockPolicy.ts +1 -105
  140. package/src/protocols/protocol-v2/unlockPolicyRunner.ts +117 -0
  141. package/src/protocols/protocol-v2/walletSession.ts +93 -18
  142. package/src/topLevelInject.ts +1 -5
  143. package/src/types/api/checkAllFirmwareRelease.ts +1 -4
  144. package/src/types/api/deviceUpdateBootloader.ts +0 -6
  145. package/src/types/api/export.ts +0 -18
  146. package/src/types/api/firmwareUpdate.ts +0 -76
  147. package/src/types/api/index.ts +2 -14
  148. package/src/types/api/protocolV2.ts +13 -0
  149. package/src/types/settings.ts +26 -13
  150. package/src/utils/deviceFeaturesUtils.ts +4 -0
  151. package/src/utils/homescreen.ts +32 -6
  152. package/src/utils/index.ts +6 -1
  153. package/src/utils/pro2Nft.ts +91 -0
  154. package/src/utils/pro2Wallpaper.ts +35 -8
  155. package/src/utils/uiProgressThrottle.ts +63 -0
  156. package/__tests__/firmware-update/check-all-firmware-release.test.ts +0 -175
  157. package/__tests__/firmware-update/firmware-artifact-source.test.ts +0 -119
  158. package/__tests__/firmware-update/firmware-host-binding.test.ts +0 -70
  159. package/__tests__/firmware-update/firmware-preparation-error.test.ts +0 -27
  160. package/__tests__/firmware-update/firmware-update-capabilities.test.ts +0 -13
  161. package/__tests__/firmware-update/firmware-update-plan.test.ts +0 -593
  162. package/__tests__/firmware-update/firmware-update-prepared-plan.test.ts +0 -213
  163. package/__tests__/firmware-update/firmware-update-v3-reconnect.test.ts +0 -58
  164. package/__tests__/firmware-update/firmware-upload-source.test.ts +0 -70
  165. package/dist/api/firmware/FirmwareArtifactSource.d.ts +0 -25
  166. package/dist/api/firmware/FirmwareArtifactSource.d.ts.map +0 -1
  167. package/dist/api/firmware/FirmwareHostBinding.d.ts +0 -6
  168. package/dist/api/firmware/FirmwareHostBinding.d.ts.map +0 -1
  169. package/dist/api/firmware/FirmwarePreparationError.d.ts +0 -3
  170. package/dist/api/firmware/FirmwarePreparationError.d.ts.map +0 -1
  171. package/dist/api/firmware/FirmwareUpdateCapabilities.d.ts +0 -3
  172. package/dist/api/firmware/FirmwareUpdateCapabilities.d.ts.map +0 -1
  173. package/dist/api/firmware/FirmwareUpdatePlan.d.ts +0 -25
  174. package/dist/api/firmware/FirmwareUpdatePlan.d.ts.map +0 -1
  175. package/dist/api/firmware/FirmwareUpdatePreparedPlan.d.ts +0 -30
  176. package/dist/api/firmware/FirmwareUpdatePreparedPlan.d.ts.map +0 -1
  177. package/dist/api/firmware/progressThrottle.d.ts +0 -3
  178. package/dist/api/firmware/progressThrottle.d.ts.map +0 -1
  179. package/dist/protocols/protocol-v2/lockedError.d.ts +0 -2
  180. package/dist/protocols/protocol-v2/lockedError.d.ts.map +0 -1
  181. package/dist/protocols/protocol-v2/unlockRetry.d.ts +0 -10
  182. package/dist/protocols/protocol-v2/unlockRetry.d.ts.map +0 -1
  183. package/dist/types/api/firmwareUpdateCapabilities.d.ts +0 -9
  184. package/dist/types/api/firmwareUpdateCapabilities.d.ts.map +0 -1
  185. package/dist/types/api/firmwareUpdatePlan.d.ts +0 -28
  186. package/dist/types/api/firmwareUpdatePlan.d.ts.map +0 -1
  187. package/dist/types/api/firmwareUpdatePreparedPlan.d.ts +0 -42
  188. package/dist/types/api/firmwareUpdatePreparedPlan.d.ts.map +0 -1
  189. package/src/api/firmware/FirmwareArtifactSource.ts +0 -278
  190. package/src/api/firmware/FirmwareHostBinding.ts +0 -100
  191. package/src/api/firmware/FirmwarePreparationError.ts +0 -12
  192. package/src/api/firmware/FirmwareUpdateCapabilities.ts +0 -9
  193. package/src/api/firmware/FirmwareUpdatePlan.ts +0 -745
  194. package/src/api/firmware/FirmwareUpdatePreparedPlan.ts +0 -392
  195. package/src/api/firmware/progressThrottle.ts +0 -44
  196. package/src/protocols/protocol-v2/lockedError.ts +0 -10
  197. package/src/protocols/protocol-v2/unlockRetry.ts +0 -109
  198. package/src/types/api/firmwareUpdateCapabilities.ts +0 -9
  199. package/src/types/api/firmwareUpdatePlan.ts +0 -38
  200. 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,75 @@ 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(outcome: HardwareUiInteractionMeta['outcome'] = 'succeeded') {
1648
+ const interaction = this.protocolV2UiInteraction;
1649
+ if (!interaction?.opened) {
1650
+ this.protocolV2UiInteraction = undefined;
1651
+ return undefined;
1652
+ }
1653
+
1654
+ const phaseId = `${interaction.interactionId}:phase-${Math.max(interaction.phaseCounter, 1)}`;
1655
+ const metadata = this.createProtocolV2UiPhaseMetadata('processing', 'finish', {
1656
+ phaseId,
1657
+ outcome,
1658
+ });
1659
+ this.protocolV2UiInteraction = undefined;
1660
+ return metadata;
1661
+ }
1662
+
1663
+ hasOpenProtocolV2UiInteraction() {
1664
+ return this.protocolV2UiInteraction?.opened === true;
1665
+ }
1666
+
1525
1667
  supportUnlockVersionRange(): DeviceFirmwareRange {
1526
1668
  // This range applies to Protocol V1 Pro devices; Pro2 has a dedicated unlock flow.
1527
1669
  return {
@@ -1531,10 +1673,33 @@ export class Device extends EventEmitter {
1531
1673
  };
1532
1674
  }
1533
1675
 
1534
- async unlockDevice(pinType: DeviceSessionPinType = DeviceSessionPinType.Main) {
1676
+ async unlockDevice(
1677
+ pinType?: DeviceSessionPinType,
1678
+ options?: ProtocolV2UiEventMetadata & { emitUiEvent?: boolean }
1679
+ ) {
1535
1680
  if (this.isProtocolV2()) {
1681
+ const requestedPinType = pinType ?? DeviceSessionPinType.Main;
1682
+ const interaction =
1683
+ options?.interaction ??
1684
+ (options?.emitUiEvent === false
1685
+ ? undefined
1686
+ : this.createProtocolV2UiPhaseMetadata('pin', 'start'));
1687
+ if (options?.emitUiEvent !== false) {
1688
+ this.emit(DEVICE.PIN_ON_DEVICE, this, requestedPinType, {
1689
+ source: options?.source ?? 'unlock-coordinator',
1690
+ reason: options?.reason ?? 'device-unlock',
1691
+ deviceOnly: options?.deviceOnly ?? true,
1692
+ completion: options?.completion,
1693
+ method: options?.method,
1694
+ page: options?.page,
1695
+ operation: options?.operation,
1696
+ interaction: options?.interaction ?? interaction,
1697
+ });
1698
+ }
1536
1699
  try {
1537
- await this.commands.typedCall('DeviceSessionAskPin', 'Success', { type: pinType });
1700
+ await this.commands.typedCall('DeviceSessionAskPin', 'Success', {
1701
+ type: requestedPinType,
1702
+ });
1538
1703
  } catch (error) {
1539
1704
  const errorText =
1540
1705
  error instanceof Error
@@ -1546,6 +1711,11 @@ export class Device extends EventEmitter {
1546
1711
  throw error;
1547
1712
  }
1548
1713
 
1714
+ const completion = interaction ? this.completeProtocolV2UiPhase(interaction) : undefined;
1715
+ if (completion) {
1716
+ this.emit(DEVICE.PIN_ON_DEVICE_COMPLETE, this, completion);
1717
+ }
1718
+
1549
1719
  const status = await requestProtocolV2DeviceStatus({ commands: this.commands });
1550
1720
  return this.updateProtocolV2Status(status);
1551
1721
  }
@@ -1607,7 +1777,8 @@ export class Device extends EventEmitter {
1607
1777
  async checkPassphraseStateSafety(
1608
1778
  passphraseState?: string,
1609
1779
  useEmptyPassphrase?: boolean,
1610
- skipPassphraseCheck?: boolean
1780
+ skipPassphraseCheck?: boolean,
1781
+ deriveCardano?: boolean
1611
1782
  ) {
1612
1783
  if (this.isUnacquired()) return false;
1613
1784
 
@@ -1616,6 +1787,7 @@ export class Device extends EventEmitter {
1616
1787
  await getPassphraseStateWithRefreshDeviceInfo(this, {
1617
1788
  expectPassphraseState: expectedPassphraseState,
1618
1789
  onlyMainPin: useEmptyPassphrase,
1790
+ deriveCardano,
1619
1791
  });
1620
1792
 
1621
1793
  // 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,16 @@ 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
+ };
68
+
59
69
  export type ProtocolV2UiEventMetadata = {
60
70
  source?: ProtocolV2UiEventSource;
61
71
  reason?: string;
@@ -64,12 +74,29 @@ export type ProtocolV2UiEventMetadata = {
64
74
  method?: string;
65
75
  page?: string | number;
66
76
  operation?: string;
77
+ interaction?: HardwareUiInteractionMeta;
67
78
  };
68
79
 
80
+ export type UiRequestWindowClose =
81
+ | {
82
+ type: typeof UI_REQUEST.CLOSE_UI_WINDOW;
83
+ payload: HardwareUiInteractionMeta;
84
+ }
85
+ | {
86
+ type: typeof UI_REQUEST.CLOSE_UI_PIN_WINDOW;
87
+ payload: HardwareUiInteractionMeta;
88
+ }
89
+ | {
90
+ type: typeof UI_REQUEST.CLOSE_UI_WINDOW;
91
+ payload?: undefined;
92
+ }
93
+ | {
94
+ type: typeof UI_REQUEST.CLOSE_UI_PIN_WINDOW;
95
+ payload?: undefined;
96
+ };
97
+
69
98
  export interface UiRequestWithoutPayload {
70
99
  type:
71
- | typeof UI_REQUEST.CLOSE_UI_WINDOW
72
- | typeof UI_REQUEST.CLOSE_UI_PIN_WINDOW
73
100
  | typeof UI_REQUEST.BLUETOOTH_PERMISSION
74
101
  | typeof UI_REQUEST.BLUETOOTH_UNSUPPORTED
75
102
  | typeof UI_REQUEST.BLUETOOTH_POWERED_OFF
@@ -111,6 +138,7 @@ export interface UiRequestPassphrase {
111
138
  source?: 'wallet-session-coordinator';
112
139
  reason?: 'open-wallet' | 'session-recovery';
113
140
  expectedPassphraseState?: string;
141
+ interaction?: HardwareUiInteractionMeta;
114
142
  };
115
143
  }
116
144
 
@@ -121,6 +149,7 @@ export interface UiRequestPassphraseOnDevice {
121
149
  passphraseState?: string;
122
150
  source?: 'wallet-session-coordinator';
123
151
  reason?: 'open-wallet' | 'session-recovery';
152
+ interaction?: HardwareUiInteractionMeta;
124
153
  };
125
154
  }
126
155
 
@@ -191,6 +220,7 @@ export interface PreviousAddressResult {
191
220
 
192
221
  export type UiEvent =
193
222
  | UiRequestWithoutPayload
223
+ | UiRequestWindowClose
194
224
  | UiRequestDeviceAction
195
225
  | UiRequestButton
196
226
  | 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