@onekeyfe/hd-core 1.2.0-alpha.22 → 1.2.0-alpha.24

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 (151) hide show
  1. package/__tests__/DeviceCommands.test.ts +43 -8
  2. package/__tests__/connectSettings.test.ts +5 -47
  3. package/__tests__/device-lifecycle-events.test.ts +59 -0
  4. package/__tests__/device-settings.test.ts +1 -1
  5. package/__tests__/device-wallet-session-store.test.ts +41 -0
  6. package/__tests__/firmware-update/firmware-update-v2-download-before-boot.test.ts +30 -39
  7. package/__tests__/logBlockEvent.test.ts +17 -0
  8. package/__tests__/open-wallet-session.test.ts +233 -111
  9. package/__tests__/protocol-v2-ping.test.ts +28 -0
  10. package/__tests__/protocol-v2.test.ts +513 -313
  11. package/__tests__/public-pro2-api-boundary.test.ts +22 -0
  12. package/dist/api/CheckAllFirmwareRelease.d.ts.map +1 -1
  13. package/dist/api/FirmwareUpdateV2.d.ts +0 -11
  14. package/dist/api/FirmwareUpdateV2.d.ts.map +1 -1
  15. package/dist/api/FirmwareUpdateV3.d.ts +3 -7
  16. package/dist/api/FirmwareUpdateV3.d.ts.map +1 -1
  17. package/dist/api/FirmwareUpdateV4.d.ts +5 -21
  18. package/dist/api/FirmwareUpdateV4.d.ts.map +1 -1
  19. package/dist/api/GetPassphraseState.d.ts.map +1 -1
  20. package/dist/api/OpenWalletSession.d.ts +1 -8
  21. package/dist/api/OpenWalletSession.d.ts.map +1 -1
  22. package/dist/api/device/DeviceUpdateBootloader.d.ts +1 -5
  23. package/dist/api/device/DeviceUpdateBootloader.d.ts.map +1 -1
  24. package/dist/api/device/DeviceWipe.d.ts.map +1 -1
  25. package/dist/api/firmware/FirmwareUpdateBaseMethod.d.ts +0 -7
  26. package/dist/api/firmware/FirmwareUpdateBaseMethod.d.ts.map +1 -1
  27. package/dist/api/firmware/getBinary.d.ts +0 -7
  28. package/dist/api/firmware/getBinary.d.ts.map +1 -1
  29. package/dist/api/firmware/updateBootloader.d.ts +0 -2
  30. package/dist/api/firmware/updateBootloader.d.ts.map +1 -1
  31. package/dist/api/firmware/uploadFirmware.d.ts +1 -9
  32. package/dist/api/firmware/uploadFirmware.d.ts.map +1 -1
  33. package/dist/api/index.d.ts +1 -0
  34. package/dist/api/index.d.ts.map +1 -1
  35. package/dist/api/protocol-v2/Ping.d.ts +2 -0
  36. package/dist/api/protocol-v2/Ping.d.ts.map +1 -1
  37. package/dist/api/stellar/StellarSignTransaction.d.ts +1 -1
  38. package/dist/core/index.d.ts.map +1 -1
  39. package/dist/data-manager/DataManager.d.ts +0 -1
  40. package/dist/data-manager/DataManager.d.ts.map +1 -1
  41. package/dist/data-manager/connectSettings.d.ts.map +1 -1
  42. package/dist/device/Device.d.ts +3 -2
  43. package/dist/device/Device.d.ts.map +1 -1
  44. package/dist/device/DeviceCommands.d.ts.map +1 -1
  45. package/dist/events/device.d.ts +1 -0
  46. package/dist/events/device.d.ts.map +1 -1
  47. package/dist/events/logBlockEvent.d.ts.map +1 -1
  48. package/dist/events/ui-request.d.ts +1 -0
  49. package/dist/events/ui-request.d.ts.map +1 -1
  50. package/dist/index.d.ts +98 -278
  51. package/dist/index.d.ts.map +1 -1
  52. package/dist/index.js +876 -2647
  53. package/dist/inject.d.ts.map +1 -1
  54. package/dist/lowLevelInject.d.ts.map +1 -1
  55. package/dist/protocols/protocol-v2/settingsUnlockPolicy.d.ts.map +1 -1
  56. package/dist/protocols/protocol-v2/unlockRetry.d.ts +2 -3
  57. package/dist/protocols/protocol-v2/unlockRetry.d.ts.map +1 -1
  58. package/dist/protocols/protocol-v2/walletSession.d.ts +12 -0
  59. package/dist/protocols/protocol-v2/walletSession.d.ts.map +1 -1
  60. package/dist/topLevelInject.d.ts.map +1 -1
  61. package/dist/types/api/checkAllFirmwareRelease.d.ts +0 -3
  62. package/dist/types/api/checkAllFirmwareRelease.d.ts.map +1 -1
  63. package/dist/types/api/deviceUpdateBootloader.d.ts +0 -6
  64. package/dist/types/api/deviceUpdateBootloader.d.ts.map +1 -1
  65. package/dist/types/api/export.d.ts +1 -4
  66. package/dist/types/api/export.d.ts.map +1 -1
  67. package/dist/types/api/firmwareUpdate.d.ts +0 -69
  68. package/dist/types/api/firmwareUpdate.d.ts.map +1 -1
  69. package/dist/types/api/getPassphraseState.d.ts.map +1 -1
  70. package/dist/types/api/index.d.ts +4 -10
  71. package/dist/types/api/index.d.ts.map +1 -1
  72. package/dist/types/api/openWalletSession.d.ts +0 -12
  73. package/dist/types/api/openWalletSession.d.ts.map +1 -1
  74. package/dist/types/api/protocolV2.d.ts +4 -0
  75. package/dist/types/api/protocolV2.d.ts.map +1 -1
  76. package/dist/types/settings.d.ts +0 -13
  77. package/dist/types/settings.d.ts.map +1 -1
  78. package/dist/utils/deviceInfoUtils.d.ts.map +1 -1
  79. package/dist/utils/patch.d.ts +1 -1
  80. package/dist/utils/patch.d.ts.map +1 -1
  81. package/package.json +4 -4
  82. package/src/api/CheckAllFirmwareRelease.ts +3 -16
  83. package/src/api/FirmwareUpdateV2.ts +119 -284
  84. package/src/api/FirmwareUpdateV3.ts +55 -248
  85. package/src/api/FirmwareUpdateV4.ts +293 -751
  86. package/src/api/GetPassphraseState.ts +11 -5
  87. package/src/api/OpenWalletSession.ts +23 -86
  88. package/src/api/device/DeviceUpdateBootloader.ts +6 -114
  89. package/src/api/device/DeviceWipe.ts +2 -0
  90. package/src/api/firmware/FirmwareUpdateBaseMethod.ts +0 -50
  91. package/src/api/firmware/updateBootloader.ts +4 -19
  92. package/src/api/firmware/uploadFirmware.ts +22 -140
  93. package/src/api/index.ts +1 -0
  94. package/src/api/protocol-v2/Ping.ts +32 -1
  95. package/src/core/index.ts +40 -7
  96. package/src/data/messages/messages-protocol-v2.json +49 -56
  97. package/src/data-manager/DataManager.ts +33 -33
  98. package/src/data-manager/connectSettings.ts +0 -11
  99. package/src/device/Device.ts +29 -8
  100. package/src/device/DeviceCommands.ts +43 -151
  101. package/src/events/device.ts +1 -0
  102. package/src/events/logBlockEvent.ts +1 -15
  103. package/src/events/ui-request.ts +1 -0
  104. package/src/index.ts +0 -5
  105. package/src/inject.ts +4 -22
  106. package/src/lowLevelInject.ts +1 -5
  107. package/src/protocols/protocol-v2/deviceSession.ts +1 -1
  108. package/src/protocols/protocol-v2/settingsUnlockPolicy.ts +0 -1
  109. package/src/protocols/protocol-v2/unlockRetry.ts +20 -3
  110. package/src/protocols/protocol-v2/walletSession.ts +57 -18
  111. package/src/topLevelInject.ts +1 -5
  112. package/src/types/api/checkAllFirmwareRelease.ts +0 -3
  113. package/src/types/api/deviceUpdateBootloader.ts +0 -6
  114. package/src/types/api/export.ts +0 -18
  115. package/src/types/api/firmwareUpdate.ts +0 -76
  116. package/src/types/api/getPassphraseState.ts +4 -3
  117. package/src/types/api/index.ts +3 -14
  118. package/src/types/api/openWalletSession.ts +0 -19
  119. package/src/types/api/protocolV2.ts +10 -0
  120. package/src/types/settings.ts +0 -13
  121. package/src/utils/deviceInfoUtils.ts +2 -3
  122. package/__tests__/firmware-update/firmware-artifact-source.test.ts +0 -119
  123. package/__tests__/firmware-update/firmware-host-binding.test.ts +0 -70
  124. package/__tests__/firmware-update/firmware-update-capabilities.test.ts +0 -13
  125. package/__tests__/firmware-update/firmware-update-plan.test.ts +0 -326
  126. package/__tests__/firmware-update/firmware-update-prepared-plan.test.ts +0 -200
  127. package/__tests__/firmware-update/firmware-upload-source.test.ts +0 -70
  128. package/dist/api/firmware/FirmwareArtifactSource.d.ts +0 -26
  129. package/dist/api/firmware/FirmwareArtifactSource.d.ts.map +0 -1
  130. package/dist/api/firmware/FirmwareHostBinding.d.ts +0 -6
  131. package/dist/api/firmware/FirmwareHostBinding.d.ts.map +0 -1
  132. package/dist/api/firmware/FirmwareUpdateCapabilities.d.ts +0 -3
  133. package/dist/api/firmware/FirmwareUpdateCapabilities.d.ts.map +0 -1
  134. package/dist/api/firmware/FirmwareUpdatePlan.d.ts +0 -24
  135. package/dist/api/firmware/FirmwareUpdatePlan.d.ts.map +0 -1
  136. package/dist/api/firmware/FirmwareUpdatePreparedPlan.d.ts +0 -25
  137. package/dist/api/firmware/FirmwareUpdatePreparedPlan.d.ts.map +0 -1
  138. package/dist/types/api/firmwareUpdateCapabilities.d.ts +0 -9
  139. package/dist/types/api/firmwareUpdateCapabilities.d.ts.map +0 -1
  140. package/dist/types/api/firmwareUpdatePlan.d.ts +0 -27
  141. package/dist/types/api/firmwareUpdatePlan.d.ts.map +0 -1
  142. package/dist/types/api/firmwareUpdatePreparedPlan.d.ts +0 -42
  143. package/dist/types/api/firmwareUpdatePreparedPlan.d.ts.map +0 -1
  144. package/src/api/firmware/FirmwareArtifactSource.ts +0 -278
  145. package/src/api/firmware/FirmwareHostBinding.ts +0 -100
  146. package/src/api/firmware/FirmwareUpdateCapabilities.ts +0 -9
  147. package/src/api/firmware/FirmwareUpdatePlan.ts +0 -621
  148. package/src/api/firmware/FirmwareUpdatePreparedPlan.ts +0 -378
  149. package/src/types/api/firmwareUpdateCapabilities.ts +0 -9
  150. package/src/types/api/firmwareUpdatePlan.ts +0 -36
  151. package/src/types/api/firmwareUpdatePreparedPlan.ts +0 -53
@@ -399,17 +399,7 @@ export default class DataManager {
399
399
 
400
400
  static async load(settings: ConnectSettings) {
401
401
  this.settings = settings;
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') {
402
+ if (!settings.fetchConfig) {
413
403
  return;
414
404
  }
415
405
 
@@ -419,50 +409,60 @@ export default class DataManager {
419
409
 
420
410
  const urlWithCache = `${url}?noCache=${getTimeStamp()}`;
421
411
  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)
422
415
  if (settings.configFetcher) {
423
- Log.debug('[DataConfig] Trying client configFetcher...');
416
+ Log.debug('[DataConfig] Trying configFetcher (client-side fetcher)...');
424
417
  try {
425
418
  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
+ }
426
425
  } catch (e) {
427
- Log.warn('[DataConfig] Client configFetcher failed:', e);
426
+ Log.warn('[DataConfig] ConfigFetcher error, will fallback to axios:', e);
428
427
  }
429
428
  }
429
+
430
+ // 2. Fallback to default axios request
430
431
  if (!data) {
431
- Log.debug('[DataConfig] Trying SDK-managed config request...');
432
+ Log.debug('[DataConfig] Trying axios (SDK default fetcher)...');
432
433
  try {
433
434
  const response = await axios.get<RemoteConfigResponse>(urlWithCache, {
434
435
  // because of iframe timeout is 10000
435
436
  timeout: 7000,
436
437
  });
437
438
  data = response.data;
438
- Log.log('[DataConfig] SDK-managed config request succeeded');
439
+ fetchMethod = 'axios';
440
+ Log.log('[DataConfig] Axios fetch success');
439
441
  } catch (e) {
440
- Log.warn('[DataConfig] SDK-managed config request failed:', e);
442
+ Log.warn('[DataConfig] Axios fetch error:', e);
441
443
  }
442
444
  }
443
445
 
446
+ // 3. Apply config if available
444
447
  if (data) {
445
- this.applyRemoteConfig(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
+ };
446
461
  } else {
447
- Log.warn('[DataConfig] SDK-managed config request failed, using built-in default config');
462
+ Log.warn('[DataConfig] All fetch methods failed, using built-in default config');
448
463
  }
449
464
  }
450
465
 
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,21 +115,10 @@ 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
-
125
118
  if (input.configFetcher) {
126
119
  settings.configFetcher = input.configFetcher;
127
120
  }
128
121
 
129
- if (input.preloadedConfig) {
130
- settings.preloadedConfig = input.preloadedConfig;
131
- }
132
-
133
122
  return settings;
134
123
  };
135
124
 
@@ -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,
@@ -322,8 +322,10 @@ export class Device extends EventEmitter {
322
322
  deviceId,
323
323
  path: this.originalDescriptor?.path,
324
324
  bleName,
325
- name: bleName || label || `OneKey ${deviceType?.toUpperCase()}`,
326
- 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 ?? '',
327
329
  mode: this.getMode(),
328
330
  features,
329
331
  state,
@@ -342,6 +344,10 @@ export class Device extends EventEmitter {
342
344
  // eslint-disable-next-line no-async-promise-executor
343
345
  return new Promise<boolean>(async (resolve, reject) => {
344
346
  if (DataManager.isBleConnect(env)) {
347
+ if (this.hasDeviceAcquire() && this.commands && !this.commands.disposed) {
348
+ resolve(true);
349
+ return;
350
+ }
345
351
  try {
346
352
  await this.acquire(connectProtocol);
347
353
  resolve(true);
@@ -1063,11 +1069,28 @@ export class Device extends EventEmitter {
1063
1069
  }
1064
1070
 
1065
1071
  markTransportDisconnected() {
1072
+ this.deviceAcquired = false;
1066
1073
  if (!this.isProtocolV2()) return;
1067
1074
  this.protocolV2StateNeedsReload = true;
1068
1075
  this.clearPreInitialized();
1069
1076
  }
1070
1077
 
1078
+ invalidateAfterWipe() {
1079
+ const deviceId = this.getCurrentDeviceId();
1080
+ if (deviceId) {
1081
+ deviceWalletSessionStore.deleteDevice(deviceId);
1082
+ }
1083
+ if (this.isProtocolV2() && this.originalDescriptor.path !== deviceId) {
1084
+ deviceWalletSessionStore.deleteDevice(this.originalDescriptor.path);
1085
+ this.protocolV2StateNeedsReload = true;
1086
+ }
1087
+
1088
+ this.passphraseState = undefined;
1089
+ this.stateStore = new DeviceStateStore();
1090
+ this.clearPreInitialized();
1091
+ this.needReloadDevice = true;
1092
+ }
1093
+
1071
1094
  markProtocolV2Reboot(rebootType: DeviceRebootType) {
1072
1095
  if (!this.isProtocolV2()) return;
1073
1096
 
@@ -1339,7 +1362,7 @@ export class Device extends EventEmitter {
1339
1362
  isUsedHere() {
1340
1363
  const env = DataManager.getSettings('env');
1341
1364
  if (DataManager.isBleConnect(env)) {
1342
- return false;
1365
+ return this.deviceAcquired;
1343
1366
  }
1344
1367
  return this.isUsed() && this.originalDescriptor.session === this.mainId;
1345
1368
  }
@@ -1418,12 +1441,10 @@ export class Device extends EventEmitter {
1418
1441
  };
1419
1442
  }
1420
1443
 
1421
- async unlockDevice() {
1444
+ async unlockDevice(pinType: DeviceSessionPinType = DeviceSessionPinType.Main) {
1422
1445
  if (this.isProtocolV2()) {
1423
1446
  try {
1424
- await this.commands.typedCall('DeviceSessionAskPin', 'Success', undefined, {
1425
- timeoutMs: 120_000,
1426
- });
1447
+ await this.commands.typedCall('DeviceSessionAskPin', 'Success', { type: pinType });
1427
1448
  } catch (error) {
1428
1449
  const errorText =
1429
1450
  error instanceof Error
@@ -9,7 +9,6 @@ import {
9
9
  } from '@onekeyfe/hd-transport';
10
10
 
11
11
  import TransportManager from '../data-manager/TransportManager';
12
- import DataManager from '../data-manager/DataManager';
13
12
  import { LoggerNames, getLogger, patchFeatures } from '../utils';
14
13
  import { DEVICE, type PassphraseRequestPayload } from '../events';
15
14
  import { DeviceModelToTypes } from '../types';
@@ -39,10 +38,6 @@ type TypedCallResponseMap = {
39
38
  };
40
39
  export type DefaultMessageResponse = TypedCallResponseMap[MessageKey];
41
40
 
42
- const MAX_DEBUG_ARRAY_ITEMS = 20;
43
- const MAX_DEBUG_OBJECT_KEYS = 40;
44
- const MAX_DEBUG_STRING_LENGTH = 512;
45
- const MAX_DEBUG_DEPTH = 4;
46
41
  const HIGH_VOLUME_DEBUG_CALLS = new Set([
47
42
  'FilesystemFileRead',
48
43
  'FilesystemFileWrite',
@@ -53,106 +48,16 @@ const HIGH_VOLUME_DEBUG_CALLS = new Set([
53
48
  'FirmwareUpload',
54
49
  'ResourceAck',
55
50
  ]);
56
- const SENSITIVE_DEBUG_CALLS = new Set(['DeviceSessionOpen']);
51
+ const DEVICE_SESSION_CALLS = new Set([
52
+ 'DeviceSessionGet',
53
+ 'DeviceSessionAskPin',
54
+ 'DeviceSessionAskPassphrase',
55
+ ]);
57
56
 
58
57
  function shouldReduceDebugForCall(type: string) {
59
58
  return HIGH_VOLUME_DEBUG_CALLS.has(type);
60
59
  }
61
60
 
62
- function shouldBlockDebugForCall(type: string) {
63
- return SENSITIVE_DEBUG_CALLS.has(type);
64
- }
65
-
66
- function getBinaryByteLength(value: unknown): number | undefined {
67
- if (value instanceof ArrayBuffer) {
68
- return value.byteLength;
69
- }
70
-
71
- if (ArrayBuffer.isView(value)) {
72
- return value.byteLength;
73
- }
74
-
75
- if (typeof Blob !== 'undefined' && value instanceof Blob) {
76
- return value.size;
77
- }
78
-
79
- return undefined;
80
- }
81
-
82
- function summarizeRedactedData(value: unknown): string {
83
- const byteLength = getBinaryByteLength(value);
84
- if (byteLength !== undefined) {
85
- return `[redacted data: ${byteLength} bytes]`;
86
- }
87
-
88
- if (typeof value === 'string') {
89
- return `[redacted data: string length=${value.length}]`;
90
- }
91
-
92
- if (Array.isArray(value)) {
93
- return `[redacted data: array length=${value.length}]`;
94
- }
95
-
96
- if (value && typeof value === 'object') {
97
- return `[redacted data: object keys=${Object.keys(value).length}]`;
98
- }
99
-
100
- return `[redacted data: ${typeof value}]`;
101
- }
102
-
103
- function sanitizeDebugPayload(value: unknown, key = '', depth = 0): unknown {
104
- if (key === 'data' && value !== null && value !== undefined) {
105
- return summarizeRedactedData(value);
106
- }
107
-
108
- // Redact passphrase-bearing keys as defense in depth so wallet identifiers and
109
- // host passphrases cannot reach diagnostic logs through a future call path.
110
- if (key && /passphrase/i.test(key)) {
111
- return '[redacted passphrase]';
112
- }
113
-
114
- const byteLength = getBinaryByteLength(value);
115
- if (byteLength !== undefined) {
116
- return `[binary: ${byteLength} bytes]`;
117
- }
118
-
119
- if (typeof value === 'string') {
120
- return value.length > MAX_DEBUG_STRING_LENGTH
121
- ? `${value.slice(0, MAX_DEBUG_STRING_LENGTH)}... (len=${value.length})`
122
- : value;
123
- }
124
-
125
- if (!value || typeof value !== 'object') {
126
- return value;
127
- }
128
-
129
- if (depth >= MAX_DEBUG_DEPTH) {
130
- return Array.isArray(value)
131
- ? `[array length=${value.length}]`
132
- : `[object keys=${Object.keys(value).length}]`;
133
- }
134
-
135
- if (Array.isArray(value)) {
136
- const items = value
137
- .slice(0, MAX_DEBUG_ARRAY_ITEMS)
138
- .map(item => sanitizeDebugPayload(item, key, depth + 1));
139
- if (value.length > MAX_DEBUG_ARRAY_ITEMS) {
140
- items.push(`... (${value.length - MAX_DEBUG_ARRAY_ITEMS} more)`);
141
- }
142
- return items;
143
- }
144
-
145
- const entries = Object.entries(value).slice(0, MAX_DEBUG_OBJECT_KEYS);
146
- const sanitized: Record<string, unknown> = {};
147
- entries.forEach(([entryKey, entryValue]) => {
148
- sanitized[entryKey] = sanitizeDebugPayload(entryValue, entryKey, depth + 1);
149
- });
150
- if (Object.keys(value).length > MAX_DEBUG_OBJECT_KEYS) {
151
- sanitized.__truncated__ = `${Object.keys(value).length - MAX_DEBUG_OBJECT_KEYS} more keys`;
152
- }
153
- return sanitized;
154
- }
155
-
156
61
  /**
157
62
  * Interactive acknowledgements must not inherit timeoutMs from the original call.
158
63
  * User confirmation and PIN/passphrase entry have unbounded think time. Preserve only
@@ -377,14 +282,15 @@ export class DeviceCommands {
377
282
  const promise = this.transport.call(this.mainId, type, msg ?? {}, options) as any;
378
283
  this.callPromise = promise;
379
284
  const res = await promise;
380
- if (res.type === 'Failure') {
381
- LogCore.debug('[DeviceCommands] [call] Received', res.type, res.message);
382
- } else if (!shouldReduceDebug) {
285
+ if (!shouldReduceDebug) {
383
286
  LogCore.debug('[DeviceCommands] [call] Received', res.type);
384
287
  }
385
288
  return res;
386
289
  } catch (error) {
387
- LogCore.debug('[DeviceCommands] [call] Received error', error);
290
+ LogCore.debug('[DeviceCommands] [call] Received error', {
291
+ request: type,
292
+ errorCode: error?.errorCode,
293
+ });
388
294
  if (error.errorCode === HardwareErrorCode.BleDeviceBondError) {
389
295
  return {
390
296
  type: 'BleDeviceBondError',
@@ -405,9 +311,6 @@ export class DeviceCommands {
405
311
  }
406
312
  }
407
313
 
408
- if (responseData) {
409
- Log.debug('error response', responseData);
410
- }
411
314
  if (responseError === 'device disconnected during action') {
412
315
  return { type: 'BridgeDeviceDisconnected', message: { error: responseError } } as any;
413
316
  }
@@ -452,32 +355,6 @@ export class DeviceCommands {
452
355
  );
453
356
  }
454
357
 
455
- // Structured log of actual outgoing payloads (skip acks)
456
- try {
457
- const skipTypes: MessageKey[] = [
458
- 'ButtonAck',
459
- 'PinMatrixAck',
460
- 'PassphraseAck',
461
- 'Cancel',
462
- 'DeviceSessionOpen',
463
- 'BixinPinInputOnDevice',
464
- 'FilesystemFileRead',
465
- 'FilesystemFileWrite',
466
- 'FileRead',
467
- 'FileWrite',
468
- 'EmmcFileRead',
469
- 'EmmcFileWrite',
470
- 'FirmwareUpload',
471
- 'ResourceAck',
472
- ] as any;
473
- if (!skipTypes.includes(type) && !shouldBlockDebugForCall(type) && msg) {
474
- // Use debug channel to avoid noise escalation
475
- Log.debug('[DeviceCommands] [typedCall] Sending payload', type, sanitizeDebugPayload(msg));
476
- }
477
- } catch (e) {
478
- // ignore logging errors
479
- }
480
-
481
358
  const expectedTypes = Array.isArray(resType) ? resType : resType.split('|');
482
359
  const response = await this._commonCall(type, msg, {
483
360
  ...options,
@@ -495,14 +372,11 @@ export class DeviceCommands {
495
372
  // throw bridge network error
496
373
  if (error instanceof HardwareError) {
497
374
  if (error.errorCode === HardwareErrorCode.ResponseUnexpectTypeError) {
498
- if (!shouldBlockDebugForCall(type)) {
499
- Log.debug('[DeviceCommands] [typedCall] Unexpected response type', {
500
- request: type,
501
- expected: resType,
502
- received: response.type,
503
- response: sanitizeDebugPayload(response.message),
504
- });
505
- }
375
+ Log.debug('[DeviceCommands] [typedCall] Unexpected response type', {
376
+ request: type,
377
+ expected: resType,
378
+ received: response.type,
379
+ });
506
380
  // Do not intercept CallMethodError
507
381
  // Do not intercept “assertType: Response of unexpected type” error
508
382
  // Blocking the above two messages will not know what the specific error message is, and the specific error should be handled by the subsequent business logic.
@@ -541,12 +415,11 @@ export class DeviceCommands {
541
415
  options?: TransportCallOptions
542
416
  ): Promise<DefaultMessageResponse> {
543
417
  try {
544
- if (shouldReduceDebugForCall(callType) || shouldBlockDebugForCall(callType)) {
545
- // Skip high-volume or security-sensitive response payloads.
546
- } else if (DataManager.getSettings('env') === 'react-native') {
547
- Log.debug('_filterCommonTypes: ', JSON.stringify(sanitizeDebugPayload(res)));
548
- } else {
549
- Log.debug('_filterCommonTypes: ', sanitizeDebugPayload(res));
418
+ if (!shouldReduceDebugForCall(callType)) {
419
+ Log.debug('_filterCommonTypes: ', {
420
+ request: callType,
421
+ response: res.type,
422
+ });
550
423
  }
551
424
  } catch (error) {
552
425
  // ignore
@@ -607,7 +480,7 @@ export class DeviceCommands {
607
480
  const isLegacyProtocolV2LockedFailure =
608
481
  this.device.isProtocolV2() && /^device (?:is )?locked$/i.test(normalizedMessage);
609
482
  if (
610
- callType === 'DeviceSessionOpen' &&
483
+ DEVICE_SESSION_CALLS.has(callType) &&
611
484
  subcode === DeviceSessionErrorCode.DeviceSessionError_InvalidSession
612
485
  ) {
613
486
  error = ERRORS.TypedError(HardwareErrorCode.WalletSessionInvalid, message, {
@@ -616,7 +489,7 @@ export class DeviceCommands {
616
489
  firmwareMessage: message,
617
490
  });
618
491
  } else if (
619
- callType === 'DeviceSessionOpen' &&
492
+ DEVICE_SESSION_CALLS.has(callType) &&
620
493
  subcode === DeviceSessionErrorCode.DeviceSessionError_UserCancelled
621
494
  ) {
622
495
  error = ERRORS.TypedError(HardwareErrorCode.ActionCancelled, message, {
@@ -625,7 +498,7 @@ export class DeviceCommands {
625
498
  firmwareMessage: message,
626
499
  });
627
500
  } else if (
628
- callType === 'DeviceSessionOpen' &&
501
+ DEVICE_SESSION_CALLS.has(callType) &&
629
502
  subcode === DeviceSessionErrorCode.DeviceSessionError_AttachPinUnavailable
630
503
  ) {
631
504
  error = ERRORS.TypedError(HardwareErrorCode.DeviceCheckUnlockTypeError, message, {
@@ -634,7 +507,7 @@ export class DeviceCommands {
634
507
  firmwareMessage: message,
635
508
  });
636
509
  } else if (
637
- callType === 'DeviceSessionOpen' &&
510
+ DEVICE_SESSION_CALLS.has(callType) &&
638
511
  subcode === DeviceSessionErrorCode.DeviceSessionError_PassphraseDisabled
639
512
  ) {
640
513
  error = ERRORS.TypedError(HardwareErrorCode.DeviceNotOpenedPassphrase, message, {
@@ -642,6 +515,25 @@ export class DeviceCommands {
642
515
  subcode,
643
516
  firmwareMessage: message,
644
517
  });
518
+ } else if (
519
+ DEVICE_SESSION_CALLS.has(callType) &&
520
+ (subcode === DeviceSessionErrorCode.DeviceSessionError_Busy ||
521
+ /^(?:busy|another flow in progress)$/i.test(normalizedMessage))
522
+ ) {
523
+ error = ERRORS.TypedError(HardwareErrorCode.DeviceBusy, message, {
524
+ failureCode: code,
525
+ subcode,
526
+ firmwareMessage: message,
527
+ });
528
+ } else if (
529
+ callType === 'DeviceSessionAskPin' &&
530
+ /^passphrase disabled$/i.test(normalizedMessage)
531
+ ) {
532
+ error = ERRORS.TypedError(HardwareErrorCode.DeviceNotOpenedPassphrase, message, {
533
+ failureCode: code,
534
+ subcode,
535
+ firmwareMessage: message,
536
+ });
645
537
  } else if (
646
538
  subcode === DeviceErrorCode.DeviceError_ActionCancelled ||
647
539
  isLegacyProtocolV2ActionCancelledFailure
@@ -54,6 +54,7 @@ export interface DeviceButtonRequestPayload extends Omit<PROTO.ButtonRequest, 'c
54
54
 
55
55
  export type PassphraseRequestPayload = {
56
56
  existsAttachPinUser?: boolean;
57
+ deviceOnly?: boolean;
57
58
  source?: 'wallet-session-coordinator';
58
59
  reason?: 'open-wallet' | 'session-recovery';
59
60
  expectedPassphraseState?: string;
@@ -5,16 +5,6 @@ export const LogBlockEvent: Set<string> = new Set([
5
5
  UI_RESPONSE.RECEIVE_PASSPHRASE,
6
6
  ]);
7
7
 
8
- const LogBlockMethod: Set<string> = new Set([
9
- 'evmSignTypedData',
10
- 'openWalletSession',
11
- 'DeviceSessionOpen',
12
- 'deviceUploadWallpaper',
13
- 'uploadPortfolio',
14
- 'fileWrite',
15
- 'fileRead',
16
- ]);
17
-
18
8
  export function getLogBlockLabel(message: unknown): string | undefined {
19
9
  if (!message || typeof message !== 'object') return undefined;
20
10
 
@@ -29,9 +19,5 @@ export function getLogBlockLabel(message: unknown): string | undefined {
29
19
  }
30
20
 
31
21
  const methodName = method ?? payload?.method;
32
- if (methodName && LogBlockMethod.has(methodName)) {
33
- return methodName;
34
- }
35
-
36
- return undefined;
22
+ return methodName;
37
23
  }
@@ -107,6 +107,7 @@ export interface UiRequestPassphrase {
107
107
  device: Device;
108
108
  passphraseState?: string;
109
109
  existsAttachPinUser?: boolean;
110
+ deviceOnly?: boolean;
110
111
  source?: 'wallet-session-coordinator';
111
112
  reason?: 'open-wallet' | 'session-recovery';
112
113
  expectedPassphraseState?: string;
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
  /**
@@ -167,6 +147,8 @@ export const createCoreApi = (
167
147
 
168
148
  testInitializeDeviceDuration: (connectId, params) =>
169
149
  call({ ...params, connectId, method: 'testInitializeDeviceDuration' }),
150
+ testProtocolV2Ping: (connectId, params) =>
151
+ call({ ...params, connectId, method: 'testProtocolV2Ping' }),
170
152
  preInitialize: (connectId, params) => call({ ...params, connectId, method: 'preInitialize' }),
171
153
  deviceBackup: connectId => call({ connectId, method: 'deviceBackup' }),
172
154
  deviceChangePin: (connectId, params) => call({ ...params, connectId, method: 'deviceChangePin' }),
@@ -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
 
@@ -18,7 +18,7 @@ export function assertCompleteDeviceSession(
18
18
  ) {
19
19
  throw ERRORS.TypedError(
20
20
  HardwareErrorCode.RuntimeError,
21
- 'DeviceSessionOpen returned an incomplete DeviceSession response.'
21
+ 'DeviceSessionGet returned an incomplete DeviceSession response.'
22
22
  );
23
23
  }
24
24
  }
@@ -3,7 +3,6 @@ import type { UnlockPolicy } from '../../api/BaseMethod';
3
3
  import type { ProtocolV2InteractionDescriptor } from './uiInteraction';
4
4
 
5
5
  const LOCK_FREE_DEVICE_SETTINGS = new Set<keyof DeviceSettings>([
6
- 'label',
7
6
  'language',
8
7
  'brightness',
9
8
  'haptic_feedback',