@onekeyfe/hd-core 1.2.0-alpha.21 → 1.2.0-alpha.23

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 (192) hide show
  1. package/__tests__/DeviceCommands.test.ts +85 -0
  2. package/__tests__/connectSettings.test.ts +47 -5
  3. package/__tests__/device-identity.test.ts +24 -2
  4. package/__tests__/device-settings.test.ts +2 -2
  5. package/__tests__/device-wallet-session-store.test.ts +152 -7
  6. package/__tests__/firmware-update/check-all-firmware-release.test.ts +86 -0
  7. package/__tests__/firmware-update/firmware-artifact-source.test.ts +119 -0
  8. package/__tests__/firmware-update/firmware-host-binding.test.ts +70 -0
  9. package/__tests__/firmware-update/firmware-update-capabilities.test.ts +13 -0
  10. package/__tests__/firmware-update/firmware-update-plan.test.ts +326 -0
  11. package/__tests__/firmware-update/firmware-update-prepared-plan.test.ts +213 -0
  12. package/__tests__/firmware-update/firmware-update-v2-download-before-boot.test.ts +39 -30
  13. package/__tests__/firmware-update/firmware-upload-source.test.ts +70 -0
  14. package/__tests__/logBlockEvent.test.ts +17 -0
  15. package/__tests__/open-wallet-session.test.ts +311 -12
  16. package/__tests__/pro2Wallpaper.test.ts +7 -18
  17. package/__tests__/protocol-v2-unlock-policy.test.ts +45 -0
  18. package/__tests__/protocol-v2.test.ts +685 -177
  19. package/__tests__/public-device-state-api.test.ts +69 -62
  20. package/__tests__/public-pro2-api-boundary.test.ts +8 -34
  21. package/dist/api/BaseMethod.d.ts +2 -1
  22. package/dist/api/BaseMethod.d.ts.map +1 -1
  23. package/dist/api/CheckAllFirmwareRelease.d.ts.map +1 -1
  24. package/dist/api/ClearSessionCache.d.ts.map +1 -1
  25. package/dist/api/FirmwareUpdate.d.ts.map +1 -1
  26. package/dist/api/FirmwareUpdateV2.d.ts +11 -0
  27. package/dist/api/FirmwareUpdateV2.d.ts.map +1 -1
  28. package/dist/api/FirmwareUpdateV3.d.ts +7 -3
  29. package/dist/api/FirmwareUpdateV3.d.ts.map +1 -1
  30. package/dist/api/FirmwareUpdateV4.d.ts +29 -10
  31. package/dist/api/FirmwareUpdateV4.d.ts.map +1 -1
  32. package/dist/api/GetPassphraseState.d.ts.map +1 -1
  33. package/dist/api/OpenWalletSession.d.ts.map +1 -1
  34. package/dist/api/conflux/ConfluxGetAddress.d.ts +1 -0
  35. package/dist/api/conflux/ConfluxGetAddress.d.ts.map +1 -1
  36. package/dist/api/conflux/ConfluxSignMessage.d.ts +1 -0
  37. package/dist/api/conflux/ConfluxSignMessage.d.ts.map +1 -1
  38. package/dist/api/conflux/ConfluxSignMessageCIP23.d.ts +1 -0
  39. package/dist/api/conflux/ConfluxSignMessageCIP23.d.ts.map +1 -1
  40. package/dist/api/conflux/ConfluxSignTransaction.d.ts +1 -0
  41. package/dist/api/conflux/ConfluxSignTransaction.d.ts.map +1 -1
  42. package/dist/api/device/DeviceUnlock.d.ts +1 -1
  43. package/dist/api/device/DeviceUnlock.d.ts.map +1 -1
  44. package/dist/api/device/DeviceUpdateBootloader.d.ts +5 -1
  45. package/dist/api/device/DeviceUpdateBootloader.d.ts.map +1 -1
  46. package/dist/api/device/DeviceWipe.d.ts.map +1 -1
  47. package/dist/api/firmware/FirmwareArtifactSource.d.ts +25 -0
  48. package/dist/api/firmware/FirmwareArtifactSource.d.ts.map +1 -0
  49. package/dist/api/firmware/FirmwareHostBinding.d.ts +6 -0
  50. package/dist/api/firmware/FirmwareHostBinding.d.ts.map +1 -0
  51. package/dist/api/firmware/FirmwareUpdateBaseMethod.d.ts +7 -0
  52. package/dist/api/firmware/FirmwareUpdateBaseMethod.d.ts.map +1 -1
  53. package/dist/api/firmware/FirmwareUpdateCapabilities.d.ts +3 -0
  54. package/dist/api/firmware/FirmwareUpdateCapabilities.d.ts.map +1 -0
  55. package/dist/api/firmware/FirmwareUpdatePlan.d.ts +23 -0
  56. package/dist/api/firmware/FirmwareUpdatePlan.d.ts.map +1 -0
  57. package/dist/api/firmware/FirmwareUpdatePreparedPlan.d.ts +30 -0
  58. package/dist/api/firmware/FirmwareUpdatePreparedPlan.d.ts.map +1 -0
  59. package/dist/api/firmware/getBinary.d.ts +7 -0
  60. package/dist/api/firmware/getBinary.d.ts.map +1 -1
  61. package/dist/api/firmware/updateBootloader.d.ts +2 -0
  62. package/dist/api/firmware/updateBootloader.d.ts.map +1 -1
  63. package/dist/api/firmware/uploadFirmware.d.ts +9 -1
  64. package/dist/api/firmware/uploadFirmware.d.ts.map +1 -1
  65. package/dist/api/helpers/protocolV2FileWrite.d.ts.map +1 -1
  66. package/dist/api/index.d.ts +0 -17
  67. package/dist/api/index.d.ts.map +1 -1
  68. package/dist/api/nexa/NexaSignTransaction.d.ts +1 -0
  69. package/dist/api/nexa/NexaSignTransaction.d.ts.map +1 -1
  70. package/dist/api/stellar/StellarSignTransaction.d.ts +1 -1
  71. package/dist/core/index.d.ts.map +1 -1
  72. package/dist/data-manager/DataManager.d.ts +1 -0
  73. package/dist/data-manager/DataManager.d.ts.map +1 -1
  74. package/dist/data-manager/connectSettings.d.ts.map +1 -1
  75. package/dist/device/Device.d.ts +3 -2
  76. package/dist/device/Device.d.ts.map +1 -1
  77. package/dist/device/DeviceCommands.d.ts.map +1 -1
  78. package/dist/device/DeviceStateMapper.d.ts.map +1 -1
  79. package/dist/device/DeviceStateProjector.d.ts.map +1 -1
  80. package/dist/events/device.d.ts +1 -0
  81. package/dist/events/device.d.ts.map +1 -1
  82. package/dist/events/logBlockEvent.d.ts.map +1 -1
  83. package/dist/events/ui-request.d.ts +1 -0
  84. package/dist/events/ui-request.d.ts.map +1 -1
  85. package/dist/index.d.ts +273 -230
  86. package/dist/index.d.ts.map +1 -1
  87. package/dist/index.js +3060 -1676
  88. package/dist/inject.d.ts.map +1 -1
  89. package/dist/lowLevelInject.d.ts.map +1 -1
  90. package/dist/protocols/protocol-v2/settingsUnlockPolicy.d.ts.map +1 -1
  91. package/dist/protocols/protocol-v2/unlockPolicy.d.ts +4 -0
  92. package/dist/protocols/protocol-v2/unlockPolicy.d.ts.map +1 -0
  93. package/dist/protocols/protocol-v2/unlockRetry.d.ts.map +1 -1
  94. package/dist/protocols/protocol-v2/walletSession.d.ts.map +1 -1
  95. package/dist/topLevelInject.d.ts.map +1 -1
  96. package/dist/types/api/checkAllFirmwareRelease.d.ts +3 -0
  97. package/dist/types/api/checkAllFirmwareRelease.d.ts.map +1 -1
  98. package/dist/types/api/deviceUnlock.d.ts +2 -2
  99. package/dist/types/api/deviceUnlock.d.ts.map +1 -1
  100. package/dist/types/api/deviceUpdateBootloader.d.ts +6 -0
  101. package/dist/types/api/deviceUpdateBootloader.d.ts.map +1 -1
  102. package/dist/types/api/export.d.ts +4 -1
  103. package/dist/types/api/export.d.ts.map +1 -1
  104. package/dist/types/api/firmwareUpdate.d.ts +69 -0
  105. package/dist/types/api/firmwareUpdate.d.ts.map +1 -1
  106. package/dist/types/api/firmwareUpdateCapabilities.d.ts +9 -0
  107. package/dist/types/api/firmwareUpdateCapabilities.d.ts.map +1 -0
  108. package/dist/types/api/firmwareUpdatePlan.d.ts +27 -0
  109. package/dist/types/api/firmwareUpdatePlan.d.ts.map +1 -0
  110. package/dist/types/api/firmwareUpdatePreparedPlan.d.ts +42 -0
  111. package/dist/types/api/firmwareUpdatePreparedPlan.d.ts.map +1 -0
  112. package/dist/types/api/getPassphraseState.d.ts.map +1 -1
  113. package/dist/types/api/index.d.ts +10 -19
  114. package/dist/types/api/index.d.ts.map +1 -1
  115. package/dist/types/api/openWalletSession.d.ts +1 -0
  116. package/dist/types/api/openWalletSession.d.ts.map +1 -1
  117. package/dist/types/api/protocolV2.d.ts +3 -76
  118. package/dist/types/api/protocolV2.d.ts.map +1 -1
  119. package/dist/types/api/sessionCache.d.ts +4 -1
  120. package/dist/types/api/sessionCache.d.ts.map +1 -1
  121. package/dist/types/settings.d.ts +13 -0
  122. package/dist/types/settings.d.ts.map +1 -1
  123. package/dist/utils/deviceFeaturesUtils.d.ts.map +1 -1
  124. package/dist/utils/deviceInfoUtils.d.ts.map +1 -1
  125. package/dist/utils/patch.d.ts +1 -1
  126. package/dist/utils/patch.d.ts.map +1 -1
  127. package/package.json +4 -4
  128. package/src/api/BaseMethod.ts +8 -3
  129. package/src/api/CheckAllFirmwareRelease.ts +23 -3
  130. package/src/api/ClearSessionCache.ts +4 -0
  131. package/src/api/FirmwareUpdate.ts +8 -1
  132. package/src/api/FirmwareUpdateV2.ts +292 -120
  133. package/src/api/FirmwareUpdateV3.ts +256 -55
  134. package/src/api/FirmwareUpdateV4.ts +821 -331
  135. package/src/api/GetPassphraseState.ts +11 -5
  136. package/src/api/OpenWalletSession.ts +74 -25
  137. package/src/api/UploadPortfolio.ts +1 -1
  138. package/src/api/conflux/ConfluxGetAddress.ts +2 -0
  139. package/src/api/conflux/ConfluxSignMessage.ts +2 -0
  140. package/src/api/conflux/ConfluxSignMessageCIP23.ts +2 -0
  141. package/src/api/conflux/ConfluxSignTransaction.ts +2 -0
  142. package/src/api/device/DeviceChangePin.ts +1 -1
  143. package/src/api/device/DeviceUnlock.ts +1 -2
  144. package/src/api/device/DeviceUpdateBootloader.ts +122 -6
  145. package/src/api/device/DeviceWipe.ts +3 -1
  146. package/src/api/firmware/FirmwareArtifactSource.ts +278 -0
  147. package/src/api/firmware/FirmwareHostBinding.ts +100 -0
  148. package/src/api/firmware/FirmwareUpdateBaseMethod.ts +50 -0
  149. package/src/api/firmware/FirmwareUpdateCapabilities.ts +9 -0
  150. package/src/api/firmware/FirmwareUpdatePlan.ts +621 -0
  151. package/src/api/firmware/FirmwareUpdatePreparedPlan.ts +392 -0
  152. package/src/api/firmware/updateBootloader.ts +19 -4
  153. package/src/api/firmware/uploadFirmware.ts +140 -22
  154. package/src/api/helpers/protocolV2FileWrite.ts +6 -0
  155. package/src/api/index.ts +0 -18
  156. package/src/api/nexa/NexaSignTransaction.ts +2 -0
  157. package/src/api/protocol-v2/DeviceUploadWallpaper.ts +1 -1
  158. package/src/core/index.ts +1 -0
  159. package/src/data/messages/messages-protocol-v2.json +35 -1
  160. package/src/data-manager/DataManager.ts +33 -33
  161. package/src/data-manager/connectSettings.ts +11 -0
  162. package/src/device/Device.ts +80 -67
  163. package/src/device/DeviceCommands.ts +76 -159
  164. package/src/device/DeviceStateMapper.ts +18 -1
  165. package/src/device/DeviceStateProjector.ts +7 -1
  166. package/src/events/device.ts +1 -0
  167. package/src/events/logBlockEvent.ts +1 -14
  168. package/src/events/ui-request.ts +1 -0
  169. package/src/index.ts +5 -0
  170. package/src/inject.ts +22 -25
  171. package/src/lowLevelInject.ts +5 -1
  172. package/src/protocols/protocol-v2/settingsUnlockPolicy.ts +2 -3
  173. package/src/protocols/protocol-v2/unlockPolicy.ts +105 -0
  174. package/src/protocols/protocol-v2/unlockRetry.ts +1 -3
  175. package/src/protocols/protocol-v2/walletSession.ts +86 -9
  176. package/src/topLevelInject.ts +5 -1
  177. package/src/types/api/checkAllFirmwareRelease.ts +3 -0
  178. package/src/types/api/deviceUnlock.ts +2 -5
  179. package/src/types/api/deviceUpdateBootloader.ts +6 -0
  180. package/src/types/api/export.ts +18 -0
  181. package/src/types/api/firmwareUpdate.ts +76 -0
  182. package/src/types/api/firmwareUpdateCapabilities.ts +9 -0
  183. package/src/types/api/firmwareUpdatePlan.ts +36 -0
  184. package/src/types/api/firmwareUpdatePreparedPlan.ts +53 -0
  185. package/src/types/api/getPassphraseState.ts +4 -3
  186. package/src/types/api/index.ts +14 -34
  187. package/src/types/api/openWalletSession.ts +2 -0
  188. package/src/types/api/protocolV2.ts +3 -156
  189. package/src/types/api/sessionCache.ts +9 -4
  190. package/src/types/settings.ts +13 -0
  191. package/src/utils/deviceFeaturesUtils.ts +5 -1
  192. package/src/utils/deviceInfoUtils.ts +3 -16
@@ -152,6 +152,12 @@ export async function writeProtocolV2File(options: ProtocolV2FileWriteOptions) {
152
152
  options.throwIfAborted?.();
153
153
  }
154
154
  }
155
+ if (!response) {
156
+ throw ERRORS.TypedError(
157
+ HardwareErrorCode.RuntimeError,
158
+ 'FilesystemFileWrite completed without a response'
159
+ );
160
+ }
155
161
  options.throwIfAborted?.();
156
162
  lastMessage = response.message;
157
163
  const rawProcessedByte = response.message?.processed_byte;
package/src/api/index.ts CHANGED
@@ -48,24 +48,6 @@ export { default as promptWebDeviceAccess } from './PromptWebDeviceAccess';
48
48
  export { default as deviceReboot } from './protocol-v2/DeviceReboot';
49
49
  export { default as deviceGetOnboardingStatus } from './protocol-v2/DeviceGetOnboardingStatus';
50
50
  export { default as deviceUploadWallpaper } from './protocol-v2/DeviceUploadWallpaper';
51
- // Protocol V2 development APIs. These remain public while Pro2 integration is in development.
52
- export { default as deviceInfoGet } from './protocol-v2/DeviceInfoGet';
53
- export { default as deviceStatusGet } from './protocol-v2/DeviceStatusGet';
54
- export { default as protocolInfoRequest } from './protocol-v2/ProtocolInfoRequest';
55
- export { default as ping } from './protocol-v2/Ping';
56
- export { default as deviceFirmwareUpdate } from './protocol-v2/DeviceFirmwareUpdate';
57
- export { default as deviceGetFirmwareUpdateStatus } from './protocol-v2/DeviceGetFirmwareUpdateStatus';
58
- export { default as deviceFactoryInfoSet } from './protocol-v2/DeviceFactoryInfoSet';
59
- export { default as deviceFactoryInfoGet } from './protocol-v2/DeviceFactoryInfoGet';
60
- export { default as filesystemPermissionFix } from './protocol-v2/FilesystemPermissionFix';
61
- export { default as filesystemFormat } from './protocol-v2/FilesystemFormat';
62
- export { default as fileRead } from './FileRead';
63
- export { default as fileWrite } from './FileWrite';
64
- export { default as fileDelete } from './FileDelete';
65
- export { default as dirList } from './DirList';
66
- export { default as dirMake } from './DirMake';
67
- export { default as dirRemove } from './DirRemove';
68
- export { default as pathInfo } from './PathInfo';
69
51
  export { default as uploadPortfolio } from './UploadPortfolio';
70
52
 
71
53
  export { default as cipherKeyValue } from './CipherKeyValue';
@@ -9,6 +9,8 @@ import type { TypedCall } from '@onekeyfe/hd-transport';
9
9
  import type { DeviceFirmwareRange, NexaSignTransactionParams, NexaSignature } from '../../types';
10
10
 
11
11
  export default class NexaSignTransaction extends BaseMethod<NexaSignTransactionParams> {
12
+ checkDeviceId = true;
13
+
12
14
  hasBundle = false;
13
15
 
14
16
  init() {
@@ -71,7 +71,7 @@ export default class DeviceUploadWallpaper extends BaseMethod<DeviceUploadWallpa
71
71
  this.path = `${WALLPAPER_DIRECTORY}/${normalizeFileName(fileName, this.encoded.data)}`;
72
72
  this.params = { width, height, rgba: rgbaBytes, fileName, chunkSize };
73
73
  this.requireProtocolV2 = true;
74
- this.unlockPolicy = 'retry-on-locked';
74
+ this.unlockPolicy = 'unlock-before-run';
75
75
  this.skipForceUpdateCheck = true;
76
76
  this.useDevicePassphraseState = false;
77
77
  }
package/src/core/index.ts CHANGED
@@ -1262,6 +1262,7 @@ const onDevicePassphraseHandler = async (
1262
1262
  device: device.toMessageObject() as KnownDevice,
1263
1263
  passphraseState: device.passphraseState,
1264
1264
  existsAttachPinUser: requestPayload.existsAttachPinUser,
1265
+ deviceOnly: requestPayload.deviceOnly,
1265
1266
  source: requestPayload.source,
1266
1267
  reason: requestPayload.reason,
1267
1268
  expectedPassphraseState: requestPayload.expectedPassphraseState,
@@ -485,6 +485,7 @@
485
485
  "MessageType_DeviceSessionGet": 60606,
486
486
  "MessageType_DeviceSession": 60607,
487
487
  "MessageType_DeviceSessionAskPin": 60608,
488
+ "MessageType_DeviceSessionAskPassphrase": 60609,
488
489
  "MessageType_FilesystemPermissionFix": 60800,
489
490
  "MessageType_FilesystemPathInfo": 60801,
490
491
  "MessageType_FilesystemPathInfoQuery": 60802,
@@ -11744,7 +11745,15 @@
11744
11745
  }
11745
11746
  },
11746
11747
  "ProtocolInfoRequest": {
11747
- "fields": {}
11748
+ "fields": {
11749
+ "eventless_wallet_session": {
11750
+ "type": "bool",
11751
+ "id": 1,
11752
+ "options": {
11753
+ "default": false
11754
+ }
11755
+ }
11756
+ }
11748
11757
  },
11749
11758
  "ProtocolInfo": {
11750
11759
  "fields": {
@@ -12427,6 +12436,16 @@
12427
12436
  }
12428
12437
  }
12429
12438
  },
12439
+ "DeviceSessionErrorCode": {
12440
+ "values": {
12441
+ "DeviceSessionError_None": 0,
12442
+ "DeviceSessionError_UserCancelled": 1,
12443
+ "DeviceSessionError_InvalidSession": 2,
12444
+ "DeviceSessionError_AttachPinUnavailable": 3,
12445
+ "DeviceSessionError_PassphraseDisabled": 4,
12446
+ "DeviceSessionError_Busy": 5
12447
+ }
12448
+ },
12430
12449
  "DeviceSessionGet": {
12431
12450
  "fields": {
12432
12451
  "session_id": {
@@ -12447,7 +12466,22 @@
12447
12466
  }
12448
12467
  }
12449
12468
  },
12469
+ "DeviceSessionPinType": {
12470
+ "values": {
12471
+ "Any": 1,
12472
+ "Main": 2,
12473
+ "AttachToPin": 3
12474
+ }
12475
+ },
12450
12476
  "DeviceSessionAskPin": {
12477
+ "fields": {
12478
+ "type": {
12479
+ "type": "DeviceSessionPinType",
12480
+ "id": 1
12481
+ }
12482
+ }
12483
+ },
12484
+ "DeviceSessionAskPassphrase": {
12451
12485
  "fields": {}
12452
12486
  },
12453
12487
  "DeviceSessionAskPin_FailureSubCodes": {
@@ -399,7 +399,17 @@ export default class DataManager {
399
399
 
400
400
  static async load(settings: ConnectSettings) {
401
401
  this.settings = settings;
402
- if (!settings.fetchConfig) {
402
+ const manifestMode =
403
+ settings.firmwareManifestMode ?? (settings.fetchConfig ? 'sdk-managed' : undefined);
404
+ if (settings.preloadedConfig) {
405
+ this.applyRemoteConfig(settings.preloadedConfig);
406
+ Log.log('[DataConfig] Preloaded firmware config loaded');
407
+ return;
408
+ }
409
+ if (manifestMode === 'external-only') {
410
+ throw new Error('External firmware config snapshot is required');
411
+ }
412
+ if (manifestMode !== 'sdk-managed') {
403
413
  return;
404
414
  }
405
415
 
@@ -409,60 +419,50 @@ export default class DataManager {
409
419
 
410
420
  const urlWithCache = `${url}?noCache=${getTimeStamp()}`;
411
421
  let data: RemoteConfigResponse | null = null;
412
- let fetchMethod: 'configFetcher' | 'axios' | 'none' = 'none';
413
-
414
- // 1. Try custom configFetcher first (client-side IP direct connection support)
415
422
  if (settings.configFetcher) {
416
- Log.debug('[DataConfig] Trying configFetcher (client-side fetcher)...');
423
+ Log.debug('[DataConfig] Trying client configFetcher...');
417
424
  try {
418
425
  data = await settings.configFetcher(urlWithCache);
419
- if (data) {
420
- fetchMethod = 'configFetcher';
421
- Log.log('[DataConfig] ConfigFetcher success');
422
- } else {
423
- Log.debug('[DataConfig] ConfigFetcher returned null, will fallback to axios');
424
- }
425
426
  } catch (e) {
426
- Log.warn('[DataConfig] ConfigFetcher error, will fallback to axios:', e);
427
+ Log.warn('[DataConfig] Client configFetcher failed:', e);
427
428
  }
428
429
  }
429
-
430
- // 2. Fallback to default axios request
431
430
  if (!data) {
432
- Log.debug('[DataConfig] Trying axios (SDK default fetcher)...');
431
+ Log.debug('[DataConfig] Trying SDK-managed config request...');
433
432
  try {
434
433
  const response = await axios.get<RemoteConfigResponse>(urlWithCache, {
435
434
  // because of iframe timeout is 10000
436
435
  timeout: 7000,
437
436
  });
438
437
  data = response.data;
439
- fetchMethod = 'axios';
440
- Log.log('[DataConfig] Axios fetch success');
438
+ Log.log('[DataConfig] SDK-managed config request succeeded');
441
439
  } catch (e) {
442
- Log.warn('[DataConfig] Axios fetch error:', e);
440
+ Log.warn('[DataConfig] SDK-managed config request failed:', e);
443
441
  }
444
442
  }
445
443
 
446
- // 3. Apply config if available
447
444
  if (data) {
448
- Log.log(`[DataConfig] Config loaded successfully via [${fetchMethod}]`);
449
- this.deviceMap = {
450
- [EDeviceType.Classic]: this.enrichFirmwareReleaseInfo(data.classic),
451
- [EDeviceType.Classic1s]: this.enrichFirmwareReleaseInfo(data.classic1s),
452
- [EDeviceType.ClassicPure]: this.enrichFirmwareReleaseInfo(data.classicpure),
453
- [EDeviceType.Mini]: this.enrichFirmwareReleaseInfo(data.mini),
454
- [EDeviceType.Touch]: this.enrichFirmwareReleaseInfo(data.touch),
455
- [EDeviceType.Pro]: this.enrichFirmwareReleaseInfo(data.pro),
456
- [EDeviceType.Pro2]: this.enrichFirmwareReleaseInfo(data.pro2),
457
- };
458
- this.assets = {
459
- bridge: data.bridge,
460
- };
445
+ this.applyRemoteConfig(data);
461
446
  } else {
462
- Log.warn('[DataConfig] All fetch methods failed, using built-in default config');
447
+ Log.warn('[DataConfig] SDK-managed config request failed, using built-in default config');
463
448
  }
464
449
  }
465
450
 
451
+ private static applyRemoteConfig(data: RemoteConfigResponse) {
452
+ this.deviceMap = {
453
+ [EDeviceType.Classic]: this.enrichFirmwareReleaseInfo(data.classic),
454
+ [EDeviceType.Classic1s]: this.enrichFirmwareReleaseInfo(data.classic1s),
455
+ [EDeviceType.ClassicPure]: this.enrichFirmwareReleaseInfo(data.classicpure),
456
+ [EDeviceType.Mini]: this.enrichFirmwareReleaseInfo(data.mini),
457
+ [EDeviceType.Touch]: this.enrichFirmwareReleaseInfo(data.touch),
458
+ [EDeviceType.Pro]: this.enrichFirmwareReleaseInfo(data.pro),
459
+ [EDeviceType.Pro2]: this.enrichFirmwareReleaseInfo(data.pro2),
460
+ };
461
+ this.assets = {
462
+ bridge: data.bridge,
463
+ };
464
+ }
465
+
466
466
  static updateEnv(newEnv: ConnectSettings['env']) {
467
467
  if (this.settings) {
468
468
  const prevEnv = this.settings.env;
@@ -115,10 +115,21 @@ export const parseConnectSettings = (input: Partial<ConnectSettings> = {}) => {
115
115
  settings.fetchConfig = input.fetchConfig;
116
116
  }
117
117
 
118
+ if (
119
+ input.firmwareManifestMode === 'sdk-managed' ||
120
+ input.firmwareManifestMode === 'external-only'
121
+ ) {
122
+ settings.firmwareManifestMode = input.firmwareManifestMode;
123
+ }
124
+
118
125
  if (input.configFetcher) {
119
126
  settings.configFetcher = input.configFetcher;
120
127
  }
121
128
 
129
+ if (input.preloadedConfig) {
130
+ settings.preloadedConfig = input.preloadedConfig;
131
+ }
132
+
122
133
  return settings;
123
134
  };
124
135
 
@@ -1,6 +1,6 @@
1
1
  import EventEmitter from 'events';
2
2
  import semver from 'semver';
3
- import { DeviceRebootType, Enum_Capability } from '@onekeyfe/hd-transport';
3
+ import { DeviceRebootType, DeviceSessionPinType, Enum_Capability } from '@onekeyfe/hd-transport';
4
4
  import {
5
5
  EDeviceType,
6
6
  ERRORS,
@@ -153,7 +153,8 @@ export interface Device {
153
153
  * This allows short-lived processes (e.g. CLI) to restore a previously
154
154
  * obtained session, avoiding the need to re-enter passphrase on every
155
155
  * invocation. The session must have been obtained from a prior
156
- * getPassphraseState() call on the same device.
156
+ * wallet-session call on the same device. This compatibility hook is intended
157
+ * for a trusted CLI process restoring its own OS-keychain entry.
157
158
  *
158
159
  * @param deviceId - The device's device_id (from features)
159
160
  * @param passphraseState - The passphrase state token
@@ -222,24 +223,7 @@ export class Device extends EventEmitter {
222
223
 
223
224
  get features(): Features | undefined {
224
225
  if (!this.state) return undefined;
225
- const features = projectFeatures(this.state);
226
- const sessionCacheDeviceKey =
227
- this.state.identity.deviceId ||
228
- (this.isProtocolV2()
229
- ? this.originalDescriptor.path || this.originalDescriptor.id
230
- : undefined);
231
- const sessionId =
232
- sessionCacheDeviceKey && this.passphraseState
233
- ? deviceWalletSessionStore.get(sessionCacheDeviceKey, this.passphraseState)
234
- : undefined;
235
- return sessionId
236
- ? {
237
- ...features,
238
- sessionId,
239
- session_id: sessionId,
240
- passphraseState: this.passphraseState,
241
- }
242
- : features;
226
+ return projectFeatures(this.state);
243
227
  }
244
228
 
245
229
  set features(features: Features | undefined) {
@@ -334,12 +318,14 @@ export class Device extends EventEmitter {
334
318
  instanceId: this.instanceId,
335
319
  createdAt: this.createdAt,
336
320
  deviceType,
337
- /** ID for current seeds, will clear after replace a new seed at device */
321
+ /** Wallet-lifecycle ID; changes after the device is wiped or reinitialized. */
338
322
  deviceId,
339
323
  path: this.originalDescriptor?.path,
340
324
  bleName,
341
- name: bleName || label || `OneKey ${deviceType?.toUpperCase()}`,
342
- label: label || 'OneKey',
325
+ name: label || bleName || `OneKey ${deviceType?.toUpperCase()}`,
326
+ // Keep the legacy top-level field string-compatible while preserving
327
+ // the canonical nullable value at state.identity.label.
328
+ label: label ?? '',
343
329
  mode: this.getMode(),
344
330
  features,
345
331
  state,
@@ -691,16 +677,14 @@ export class Device extends EventEmitter {
691
677
  const deviceId = _deviceId || this.getCurrentDeviceId();
692
678
  if (deviceId) return deviceId;
693
679
  if (this.isProtocolV2()) {
694
- return this.originalDescriptor.path || this.originalDescriptor.id;
680
+ return this.originalDescriptor.path;
695
681
  }
696
682
  return undefined;
697
683
  }
698
684
 
699
685
  private reconcileSessionCacheDeviceIdentity(previousDeviceId?: string) {
700
686
  deviceWalletSessionStore.reconcileDeviceIdentity({
701
- temporaryKey: this.isProtocolV2()
702
- ? this.originalDescriptor.path || this.originalDescriptor.id
703
- : undefined,
687
+ temporaryKey: this.isProtocolV2() ? this.originalDescriptor.path : undefined,
704
688
  previousDeviceId,
705
689
  nextDeviceId: this.getCurrentDeviceId(),
706
690
  });
@@ -806,43 +790,55 @@ export class Device extends EventEmitter {
806
790
  return;
807
791
  }
808
792
 
809
- // Log.debug('initialize param:', options);
793
+ try {
794
+ const callInitialize = async (payload: Record<string, unknown>, initSession?: boolean) => {
795
+ const initStartAt = Date.now();
796
+ const { message } = await this.commands.typedCall('Initialize', 'Features', payload, {
797
+ // iOS BLE bound devices can need close to 20 seconds.
798
+ timeoutMs: 25 * 1000,
799
+ });
800
+ this.setLastInitializeDuration(Date.now() - initStartAt);
801
+ this._updateFeatures(message, initSession);
802
+ await TransportManager.reconfigure(this.features);
803
+ };
810
804
 
811
- this.passphraseState = options?.passphraseState;
805
+ const expectedDeviceId = options?.deviceId;
806
+ if (expectedDeviceId) {
807
+ // Establish the live physical identity before sending wallet-bound state.
808
+ this.passphraseState = undefined;
809
+ await callInitialize({ is_contains_attach: true });
810
+ if (!this.checkDeviceId(expectedDeviceId)) {
811
+ throw ERRORS.TypedError(HardwareErrorCode.DeviceCheckDeviceIdError);
812
+ }
813
+ }
812
814
 
813
- if (options?.initSession) {
814
- this.clearInternalState(options?.deviceId);
815
- }
815
+ this.passphraseState = options?.passphraseState;
816
816
 
817
- const internalState = this.getInternalState(options?.deviceId);
818
- const payload: any = {};
819
- if (internalState) {
820
- payload.session_id = internalState;
821
- }
817
+ if (options?.initSession) {
818
+ this.clearInternalState(options?.deviceId);
819
+ }
822
820
 
823
- if (options?.deriveCardano) {
824
- payload.derive_cardano = true;
825
- }
826
- payload.passphrase_state = options?.passphraseState;
827
- payload.is_contains_attach = true;
821
+ const internalState = this.getInternalState(options?.deviceId);
822
+ const payload: Record<string, unknown> = {
823
+ passphrase_state: options?.passphraseState,
824
+ is_contains_attach: true,
825
+ };
826
+ if (internalState) {
827
+ payload.session_id = internalState;
828
+ }
829
+ if (options?.deriveCardano) {
830
+ payload.derive_cardano = true;
831
+ }
828
832
 
829
- const initStartAt = Date.now();
830
- try {
831
- // @ts-expect-error
832
- const { message } = await Promise.race([
833
- this.commands.typedCall('Initialize', 'Features', payload),
834
- new Promise((_, reject) => {
835
- setTimeout(() => {
836
- reject(ERRORS.TypedError(HardwareErrorCode.DeviceInitializeFailed));
837
- // iOS ble bound device timeout 20s
838
- }, 25 * 1000);
839
- }),
840
- ]);
841
-
842
- const initCostMs = Date.now() - initStartAt;
843
- this.setLastInitializeDuration(initCostMs);
844
- this._updateFeatures(message, options?.initSession);
845
- await TransportManager.reconfigure(this.features);
833
+ const requiresWalletInitialize =
834
+ !expectedDeviceId ||
835
+ Boolean(internalState) ||
836
+ Boolean(options?.passphraseState) ||
837
+ options?.deriveCardano === true ||
838
+ options?.initSession === true;
839
+ if (requiresWalletInitialize) {
840
+ await callInitialize(payload, options?.initSession);
841
+ }
846
842
  } catch (error) {
847
843
  Log.error('Initialization failed:', error);
848
844
  throw error;
@@ -972,10 +968,6 @@ export class Device extends EventEmitter {
972
968
  ? protoFeatures
973
969
  : buildProtocolV1FeaturesPayload(protoFeatures, this.features);
974
970
 
975
- // GetFeatures doesn't return 'session_id'
976
- if (this.features?.sessionId && !feat.sessionId) {
977
- feat.sessionId = this.features.sessionId;
978
- }
979
971
  feat.unlocked = feat.unlocked ?? true;
980
972
 
981
973
  feat = fixFeaturesFirmwareVersion(feat);
@@ -1078,6 +1070,22 @@ export class Device extends EventEmitter {
1078
1070
  this.clearPreInitialized();
1079
1071
  }
1080
1072
 
1073
+ invalidateAfterWipe() {
1074
+ const deviceId = this.getCurrentDeviceId();
1075
+ if (deviceId) {
1076
+ deviceWalletSessionStore.deleteDevice(deviceId);
1077
+ }
1078
+ if (this.isProtocolV2() && this.originalDescriptor.path !== deviceId) {
1079
+ deviceWalletSessionStore.deleteDevice(this.originalDescriptor.path);
1080
+ this.protocolV2StateNeedsReload = true;
1081
+ }
1082
+
1083
+ this.passphraseState = undefined;
1084
+ this.stateStore = new DeviceStateStore();
1085
+ this.clearPreInitialized();
1086
+ this.needReloadDevice = true;
1087
+ }
1088
+
1081
1089
  markProtocolV2Reboot(rebootType: DeviceRebootType) {
1082
1090
  if (!this.isProtocolV2()) return;
1083
1091
 
@@ -1428,12 +1436,17 @@ export class Device extends EventEmitter {
1428
1436
  };
1429
1437
  }
1430
1438
 
1431
- async unlockDevice() {
1439
+ async unlockDevice(pinType: DeviceSessionPinType = DeviceSessionPinType.Main) {
1432
1440
  if (this.isProtocolV2()) {
1433
1441
  try {
1434
- await this.commands.typedCall('DeviceSessionAskPin', 'Success', undefined, {
1435
- timeoutMs: 120_000,
1436
- });
1442
+ await this.commands.typedCall(
1443
+ 'DeviceSessionAskPin',
1444
+ 'Success',
1445
+ { type: pinType },
1446
+ {
1447
+ timeoutMs: 120_000,
1448
+ }
1449
+ );
1437
1450
  } catch (error) {
1438
1451
  const errorText =
1439
1452
  error instanceof Error