@onekeyfe/hd-core 1.2.0-alpha.133 → 1.2.0-alpha.133-ok59992

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@onekeyfe/hd-core",
3
- "version": "1.2.0-alpha.133",
3
+ "version": "1.2.0-alpha.133-ok59992",
4
4
  "description": "Core processes and APIs for communicating with OneKey hardware devices.",
5
5
  "author": "OneKey",
6
6
  "homepage": "https://github.com/OneKeyHQ/hardware-js-sdk#readme",
@@ -25,8 +25,8 @@
25
25
  "url": "https://github.com/OneKeyHQ/hardware-js-sdk/issues"
26
26
  },
27
27
  "dependencies": {
28
- "@onekeyfe/hd-shared": "1.2.0-alpha.133",
29
- "@onekeyfe/hd-transport": "1.2.0-alpha.133",
28
+ "@onekeyfe/hd-shared": "1.2.0-alpha.133-ok59992",
29
+ "@onekeyfe/hd-transport": "1.2.0-alpha.133-ok59992",
30
30
  "axios": "1.15.2",
31
31
  "bignumber.js": "^9.0.2",
32
32
  "buffer": "^6.0.3",
@@ -46,5 +46,5 @@
46
46
  "@types/w3c-web-usb": "^1.0.10",
47
47
  "@types/web-bluetooth": "^0.0.21"
48
48
  },
49
- "gitHead": "b6d3307b47c535c876655afd99a6681399453508"
49
+ "gitHead": "521eb4523f54abc5ceca28a48b7120158fea1ac0"
50
50
  }
@@ -168,7 +168,8 @@ export default class DeviceSettings extends BaseMethod<ApplySettings> {
168
168
  async run() {
169
169
  try {
170
170
  if (this.device.isProtocolV2()) {
171
- const refreshStatusAndSettings = () => this.device.refreshProtocolV2SettingsAfterMutation();
171
+ const refreshStatusAndSettings = () =>
172
+ this.device.getDeviceState({ refreshSections: ['status', 'settings'] });
172
173
  assertSettingsSupported(this.payload, DEVICE_SETTINGS_V1_ONLY_FIELDS, 'Protocol V2');
173
174
  const capabilities = getDeviceSettingsCapabilities(
174
175
  this.device.getCurrentDeviceType(),
@@ -200,7 +201,20 @@ export default class DeviceSettings extends BaseMethod<ApplySettings> {
200
201
  const res = await this.device.commands.typedCall('DeviceSettingsPageShow', 'Success', {
201
202
  page: DeviceSettingsPage.DevicePassphrase,
202
203
  });
203
- await refreshStatusAndSettings();
204
+ const updated = await refreshStatusAndSettings();
205
+ const lockedAfterDisabling =
206
+ requestedPassphrase === false &&
207
+ current.status.unlocked === true &&
208
+ updated.status.unlocked === false;
209
+ if (
210
+ updated.status.passphraseProtection !== requestedPassphrase &&
211
+ !lockedAfterDisabling
212
+ ) {
213
+ throw TypedError(
214
+ HardwareErrorCode.RuntimeError,
215
+ 'Protocol V2 passphrase setting did not reach the requested value.'
216
+ );
217
+ }
204
218
  return res.message;
205
219
  }
206
220
  if (requestedAirgap !== undefined) {
@@ -8,7 +8,6 @@ import { invalidParameter } from '../helpers/filesystemValidation';
8
8
  import { writeProtocolV2File } from '../helpers/protocolV2FileWrite';
9
9
  import { UI_REQUEST, createUiMessage } from '../../events/ui-request';
10
10
  import { supportsProtocolV2Message } from '../../protocols/protocol-v2/features';
11
- import { LoggerNames, getLogger } from '../../utils';
12
11
  import {
13
12
  PRO2_WALLPAPER_HEIGHT,
14
13
  PRO2_WALLPAPER_WIDTH,
@@ -34,7 +33,6 @@ const SAFE_FILE_NAME = /^[A-Za-z0-9_-]+(?:\.bin)?$/;
34
33
  const DEVICE_SETTINGS_SET_MESSAGE_TYPE = 60412;
35
34
  const FILESYSTEM_FILE_WRITE_MESSAGE_TYPE = 60805;
36
35
  const FILESYSTEM_DIR_MAKE_MESSAGE_TYPE = 60809;
37
- const Log = getLogger(LoggerNames.Method);
38
36
 
39
37
  function normalizeFileName(fileName: string | undefined, data: Uint8Array): string {
40
38
  if (fileName !== undefined && (!fileName || !SAFE_FILE_NAME.test(fileName))) {
@@ -145,15 +143,6 @@ export default class DeviceUploadWallpaper extends BaseMethod<DeviceUploadWallpa
145
143
  const response = await this.device.commands.typedCall('DeviceSettingsSet', 'Success', {
146
144
  settings: { wallpaper_path: this.path },
147
145
  });
148
- try {
149
- await this.device.refreshProtocolV2SettingsAfterMutation();
150
- } catch (error) {
151
- // The wallpaper is already applied. A transient read-back failure must not
152
- // make callers retry the completed file upload.
153
- Log.warn('Protocol V2 wallpaper settings refresh failed after apply', {
154
- error: error instanceof Error ? error.message : String(error),
155
- });
156
- }
157
146
  return {
158
147
  path: this.path,
159
148
  size: encoded.data.byteLength,
package/src/core/index.ts CHANGED
@@ -83,7 +83,6 @@ import type { BaseMethod } from '../api/BaseMethod';
83
83
 
84
84
  const Log = getLogger(LoggerNames.Core);
85
85
  const PRE_INITIALIZE_TTL_MS = 60 * 1000;
86
- const PRE_PENDING_CALL_TIMEOUT_MS = 15 * 1000;
87
86
 
88
87
  // Dedup/coalesce state for "pre-warm signal" methods (isPreWarmSignal),
89
88
  // keyed by getPreWarmKey(): coalesce in-flight, skip if warmed within TTL.
@@ -297,35 +296,26 @@ const handlePreWarmSignal = async (
297
296
  }
298
297
  };
299
298
 
299
+ const waitWithTimeout = async (promise: Promise<any>, timeout: number) => {
300
+ const timeoutPromise = new Promise((_, reject) => {
301
+ setTimeout(() => reject(new Error('Request timeout')), timeout);
302
+ });
303
+ return Promise.race([promise, timeoutPromise]);
304
+ };
305
+
300
306
  const waitForPendingPromise = async (
301
- connectId: string,
302
- getPrePendingCallPromise: (connectId: string) => Promise<void> | undefined,
303
- removePrePendingCallPromise?: (connectId: string, promise: Promise<void>) => void
307
+ getPrePendingCallPromise: () => Promise<void> | undefined,
308
+ removePrePendingCallPromise?: (promise: Promise<void> | undefined) => void
304
309
  ) => {
305
- const pendingPromise = getPrePendingCallPromise(connectId);
310
+ const pendingPromise = getPrePendingCallPromise();
306
311
  if (pendingPromise) {
307
312
  Log.debug('pre pending call promise before call method, wait for it');
308
- let timer: ReturnType<typeof setTimeout> | undefined;
309
- let timedOut = false;
310
313
  try {
311
- await Promise.race([
312
- pendingPromise,
313
- new Promise<void>(resolve => {
314
- timer = setTimeout(() => {
315
- timedOut = true;
316
- resolve();
317
- }, PRE_PENDING_CALL_TIMEOUT_MS);
318
- }),
319
- ]);
314
+ await waitWithTimeout(pendingPromise, 5 * 1000);
320
315
  } catch (error) {
321
- // Cancellation is best-effort; the transport teardown owns recovery.
322
- } finally {
323
- if (timer) clearTimeout(timer);
324
- removePrePendingCallPromise?.(connectId, pendingPromise);
325
- }
326
- if (timedOut) {
327
- Log.warn('pre pending call promise timed out before call method', { connectId });
316
+ // ignore timeout error
328
317
  }
318
+ removePrePendingCallPromise?.(pendingPromise);
329
319
  Log.debug('pre pending call promise before call method done');
330
320
  }
331
321
  };
@@ -337,7 +327,7 @@ const onCallDevice = async (
337
327
  ): Promise<any> => {
338
328
  let messageResponse: any;
339
329
 
340
- const { requestQueue, getPrePendingCallPromise, removePrePendingCallPromise } = context;
330
+ const { requestQueue, getPrePendingCallPromise, setPrePendingCallPromise } = context;
341
331
 
342
332
  updateMethodRequestContext(method, { status: 'running' });
343
333
 
@@ -365,11 +355,7 @@ const onCallDevice = async (
365
355
  await context.waitForCallbackTasks(method.connectId);
366
356
  }
367
357
 
368
- await waitForPendingPromise(
369
- method.connectId ?? '',
370
- getPrePendingCallPromise,
371
- removePrePendingCallPromise
372
- );
358
+ await waitForPendingPromise(getPrePendingCallPromise, setPrePendingCallPromise);
373
359
 
374
360
  const task = requestQueue.createTask(method);
375
361
 
@@ -468,11 +454,7 @@ const onCallDevice = async (
468
454
  await context.waitForCallbackTasks(method.connectId, preWarmCallbackTask);
469
455
  }
470
456
 
471
- await waitForPendingPromise(
472
- method.connectId ?? '',
473
- getPrePendingCallPromise,
474
- removePrePendingCallPromise
475
- );
457
+ await waitForPendingPromise(getPrePendingCallPromise, setPrePendingCallPromise);
476
458
 
477
459
  const inner = async (): Promise<void> => {
478
460
  // Protocol is established from an active device response during acquire/initialize.
@@ -924,16 +906,6 @@ function isRetryableBleProtocolV2ProbeError(method: BaseMethod, error: unknown)
924
906
  );
925
907
  }
926
908
 
927
- export function isMissingDetectedProtocolV2Error(method: BaseMethod, error: unknown) {
928
- const typedError = error as { errorCode?: unknown; message?: unknown };
929
- return (
930
- method.payload.connectProtocol === 'V2' &&
931
- typedError?.errorCode === HardwareErrorCode.RuntimeError &&
932
- typeof typedError.message === 'string' &&
933
- typedError.message.includes('Device protocol has not been detected')
934
- );
935
- }
936
-
937
909
  /**
938
910
  * If the Bluetooth connection times out, retry up to 6 times
939
911
  * @param retryCount - Current retry count (default 0)
@@ -971,13 +943,12 @@ async function connectDeviceForBle(method: BaseMethod, device: Device, retryCoun
971
943
  DevicePool.emitter.emit(DEVICE.CONNECT, device);
972
944
  }
973
945
  } catch (err) {
974
- const requiresColdReconnect = isMissingDetectedProtocolV2Error(method, err);
975
946
  // Device.run()'s REQUIRE_DISCONNECT handling never sees acquire/initialize
976
947
  // failures, so with keep-alive a wedged link would be reused by every retry
977
948
  // (field case: Initialize timing out at 25s per attempt, forever). Drop it
978
949
  // here so the next retry cold-connects.
979
950
  if (
980
- (ERROR_CODES_REQUIRE_DISCONNECT.includes(err.errorCode) || requiresColdReconnect) &&
951
+ ERROR_CODES_REQUIRE_DISCONNECT.includes(err.errorCode) &&
981
952
  device.mainId &&
982
953
  device.deviceConnector
983
954
  ) {
@@ -990,12 +961,11 @@ async function connectDeviceForBle(method: BaseMethod, device: Device, retryCoun
990
961
  if (
991
962
  (err.errorCode === HardwareErrorCode.BleTimeoutError ||
992
963
  err.errorCode === HardwareErrorCode.BleConnectedError ||
993
- isRetryableBleProtocolV2ProbeError(method, err) ||
994
- requiresColdReconnect) &&
964
+ isRetryableBleProtocolV2ProbeError(method, err)) &&
995
965
  retryCount < 6
996
966
  ) {
997
967
  const nextRetry = retryCount + 1;
998
- Log.debug(`Bluetooth connection will retry, retry count: ${nextRetry}`);
968
+ Log.debug(`Bluetooth connect timeout and will retry, retry count: ${nextRetry}`);
999
969
  await wait(3000);
1000
970
  await connectDeviceForBle(method, device, nextRetry);
1001
971
  } else {
@@ -1207,10 +1177,7 @@ export const cancel = (context: CoreContext, connectId?: string) => {
1207
1177
  if (task && task.method?.device) {
1208
1178
  if (!canceledDevices.includes(task.method.device)) {
1209
1179
  const { device } = task.method;
1210
- setPrePendingCallPromise(
1211
- task.method.connectId ?? connectId,
1212
- device.interruptionFromUser()
1213
- );
1180
+ setPrePendingCallPromise(device?.interruptionFromUser());
1214
1181
  canceledDevices.push(device);
1215
1182
  }
1216
1183
  requestQueue.rejectRequest(
@@ -1564,7 +1531,7 @@ export default class Core extends EventEmitter {
1564
1531
  private disposePromise?: Promise<void>;
1565
1532
 
1566
1533
  // background task
1567
- private prePendingCallPromises = new Map<string, Promise<void>>();
1534
+ private prePendingCallPromise: Promise<void> | undefined;
1568
1535
 
1569
1536
  private methodSynchronize = getSynchronize();
1570
1537
 
@@ -1581,18 +1548,9 @@ export default class Core extends EventEmitter {
1581
1548
  tracingContext: this.tracingContext,
1582
1549
  requestQueue: this.requestQueue,
1583
1550
  methodSynchronize: this.methodSynchronize,
1584
- getPrePendingCallPromise: (connectId: string) => this.prePendingCallPromises.get(connectId),
1585
- setPrePendingCallPromise: (connectId: string, promise?: Promise<void>) => {
1586
- if (!promise) {
1587
- this.prePendingCallPromises.delete(connectId);
1588
- return;
1589
- }
1590
- this.prePendingCallPromises.set(connectId, promise);
1591
- },
1592
- removePrePendingCallPromise: (connectId: string, promise: Promise<void>) => {
1593
- if (this.prePendingCallPromises.get(connectId) === promise) {
1594
- this.prePendingCallPromises.delete(connectId);
1595
- }
1551
+ getPrePendingCallPromise: () => this.prePendingCallPromise,
1552
+ setPrePendingCallPromise: (promise: Promise<void> | undefined) => {
1553
+ this.prePendingCallPromise = promise;
1596
1554
  },
1597
1555
  // callback 任务管理
1598
1556
  registerCallbackTask: (connectId: string, callbackPromise: Deferred<any>) => {
@@ -1707,7 +1665,7 @@ export default class Core extends EventEmitter {
1707
1665
  preWarmInflight.clear();
1708
1666
  preWarmDoneAt.clear();
1709
1667
  preConnectCache = { passphraseState: undefined };
1710
- this.prePendingCallPromises.clear();
1668
+ this.prePendingCallPromise = undefined;
1711
1669
  this.removeAllListeners();
1712
1670
  cleanupSdkInstance(this.sdkInstanceId);
1713
1671
  if (_core === this) _core = undefined;
@@ -284,9 +284,6 @@ export class Device extends EventEmitter {
284
284
 
285
285
  runPromise?: Deferred<void> | null;
286
286
 
287
- /** Resolves only after the active run has completed its release path. */
288
- private runCleanupPromise?: Promise<void>;
289
-
290
287
  externalState: string[] = [];
291
288
 
292
289
  unavailableCapabilities: UnavailableCapabilities = {};
@@ -1082,10 +1079,6 @@ export class Device extends EventEmitter {
1082
1079
  return params.includeRaw ? cloneDeviceState(this.state) : createPublicDeviceState(this.state);
1083
1080
  }
1084
1081
 
1085
- async refreshProtocolV2SettingsAfterMutation() {
1086
- return this.getDeviceState({ refreshSections: ['status', 'settings'] });
1087
- }
1088
-
1089
1082
  _updateFeatures(protoFeatures: PROTO.Features | Features, initSession?: boolean) {
1090
1083
  const previousDeviceId = this.getCurrentDeviceId();
1091
1084
  let feat =
@@ -1403,20 +1396,12 @@ export class Device extends EventEmitter {
1403
1396
 
1404
1397
  const runPromise = createDeferred<void>();
1405
1398
  this.runPromise = runPromise;
1406
- const cleanupPromise = this._runInner(fn, options, runPromise).catch(error => {
1399
+ this._runInner(fn, options, runPromise).catch(error => {
1407
1400
  if (this.runPromise === runPromise) {
1408
1401
  this.runPromise = null;
1409
1402
  }
1410
1403
  runPromise.reject(error);
1411
1404
  });
1412
- this.runCleanupPromise = cleanupPromise;
1413
- cleanupPromise
1414
- .finally(() => {
1415
- if (this.runCleanupPromise === cleanupPromise) {
1416
- this.runCleanupPromise = undefined;
1417
- }
1418
- })
1419
- .catch(() => undefined);
1420
1405
  return runPromise.promise;
1421
1406
  }
1422
1407
 
@@ -1528,26 +1513,13 @@ export class Device extends EventEmitter {
1528
1513
 
1529
1514
  async interruptionFromUser() {
1530
1515
  const error = ERRORS.TypedError(HardwareErrorCode.DeviceInterruptedFromUser);
1531
- const cleanupPromise = this.runCleanupPromise;
1532
- const { cancelableAction } = this;
1533
- if (cancelableAction) {
1534
- await cancelableAction(error);
1535
- } else if (
1536
- this.isProtocolV2() &&
1537
- DataManager.isBleConnect(DataManager.getSettings('env')) &&
1538
- this.hasDeviceAcquire()
1539
- ) {
1540
- await this.commands?.cancelDevice?.().catch(cancelError => {
1541
- Log.debug('Protocol V2 BLE fallback cancel error', cancelError);
1542
- });
1543
- }
1516
+ await this.cancelableAction?.(error);
1544
1517
  await this.commands?.cancel();
1545
1518
 
1546
1519
  if (this.runPromise) {
1547
1520
  this.runPromise.reject(error);
1548
1521
  this.runPromise = null;
1549
1522
  }
1550
- await cleanupPromise?.catch(() => undefined);
1551
1523
  }
1552
1524
 
1553
1525
  setCancelableAction(callback: (err?: Error) => Promise<unknown>) {
@@ -264,7 +264,6 @@ export class DeviceCommands {
264
264
  }
265
265
  const activeCall = this.callPromise;
266
266
  let timer: ReturnType<typeof setTimeout> | undefined;
267
- let timedOut = false;
268
267
  const cancellation = (async () => {
269
268
  await this.dispose(true);
270
269
  await activeCall?.catch(() => undefined);
@@ -274,23 +273,11 @@ export class DeviceCommands {
274
273
  await Promise.race([
275
274
  cancellation,
276
275
  new Promise<void>(resolve => {
277
- timer = setTimeout(() => {
278
- timedOut = true;
279
- resolve();
280
- }, 10 * 1000);
276
+ timer = setTimeout(resolve, 10 * 1000);
281
277
  }),
282
278
  ]);
283
279
  } finally {
284
280
  if (timer) clearTimeout(timer);
285
- if (
286
- timedOut &&
287
- this.transport.name === 'ReactNativeBleTransport' &&
288
- this.transport.disconnect
289
- ) {
290
- await this.transport.disconnect(this.mainId).catch(error => {
291
- Log.debug('BLE cancellation timeout disconnect error (ignored)', error);
292
- });
293
- }
294
281
  if (this.callPromise === activeCall) {
295
282
  this.callPromise = undefined;
296
283
  }