@onekeyfe/hd-core 1.2.0-alpha.172 → 1.2.0-alpha.174

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.
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":";AACA,OAAO,YAAY,MAAM,QAAQ,CAAC;AAoClC,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAsB1C,OAAO,eAAe,MAAM,2BAA2B,CAAC;AAYxD,OAAO,KAAK,EAAE,eAAe,EAAyB,MAAM,UAAU,CAAC;AACvE,OAAO,KAAK,EAAE,WAAW,EAAmD,MAAM,WAAW,CAAC;AAI9F,OAAO,KAAK,EACV,6BAA6B,EAG9B,MAAM,wBAAwB,CAAC;AAChC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAWpD,MAAM,MAAM,WAAW,GAAG,UAAU,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC,CAAC;AAmE7D,eAAO,MAAM,OAAO,YAAmB,WAAW,WAAW,WAAW,iBAoFvE,CAAC;AAiqBF,wBAAgB,kCAAkC,CAAC,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,OAAO,WAWpF;AAED,wBAAgB,6BAA6B,CAAC,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,OAAO,WAW/E;AAED,wBAAgB,gCAAgC,CAAC,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,OAAO,WAQlF;AA0PD,eAAO,MAAM,MAAM,YAAa,WAAW,cAAc,MAAM,SAuG9D,CAAC;AAmGF,eAAO,MAAM,qBAAqB,gFAejC,CAAC;AAiLF,MAAM,CAAC,OAAO,OAAO,IAAK,SAAQ,YAAY;IAC5C,OAAO,CAAC,cAAc,CAAoB;IAE1C,SAAgB,aAAa,EAAE,MAAM,CAAC;IAEtC,OAAO,CAAC,YAAY,CAAsB;IAE1C,OAAO,CAAC,cAAc,CAAC,CAAgB;IAGvC,OAAO,CAAC,sBAAsB,CAAoC;IAElE,OAAO,CAAC,iBAAiB,CAAoB;;IAS7C,OAAO,CAAC,cAAc;IA6BhB,aAAa,CAAC,OAAO,EAAE,WAAW;IAuExC,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;YAOV,gBAAgB;CAiC/B;AAED,eAAO,MAAM,QAAQ,YAIpB,CAAC;AAEF,eAAO,MAAM,aAAa,uBAYzB,CAAC;AAMF,eAAO,MAAM,IAAI,aACL,eAAe,aACd,GAAG,WACL,6BAA6B,8BAiBvC,CAAC;AAEF,eAAO,MAAM,eAAe;SAKrB,eAAe,CAAC,KAAK,CAAC;eAChB,GAAG;;UASf,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":";AACA,OAAO,YAAY,MAAM,QAAQ,CAAC;AAoClC,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAsB1C,OAAO,eAAe,MAAM,2BAA2B,CAAC;AAYxD,OAAO,KAAK,EAAE,eAAe,EAAyB,MAAM,UAAU,CAAC;AACvE,OAAO,KAAK,EAAE,WAAW,EAAmD,MAAM,WAAW,CAAC;AAI9F,OAAO,KAAK,EACV,6BAA6B,EAG9B,MAAM,wBAAwB,CAAC;AAChC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAWpD,MAAM,MAAM,WAAW,GAAG,UAAU,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC,CAAC;AAmE7D,eAAO,MAAM,OAAO,YAAmB,WAAW,WAAW,WAAW,iBAoFvE,CAAC;AAwqBF,wBAAgB,kCAAkC,CAAC,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,OAAO,WAWpF;AAED,wBAAgB,6BAA6B,CAAC,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,OAAO,WAW/E;AAED,wBAAgB,gCAAgC,CAAC,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,OAAO,WAQlF;AAiVD,eAAO,MAAM,MAAM,YAAa,WAAW,cAAc,MAAM,SAuG9D,CAAC;AAmGF,eAAO,MAAM,qBAAqB,gFAejC,CAAC;AAiLF,MAAM,CAAC,OAAO,OAAO,IAAK,SAAQ,YAAY;IAC5C,OAAO,CAAC,cAAc,CAAoB;IAE1C,SAAgB,aAAa,EAAE,MAAM,CAAC;IAEtC,OAAO,CAAC,YAAY,CAAsB;IAE1C,OAAO,CAAC,cAAc,CAAC,CAAgB;IAGvC,OAAO,CAAC,sBAAsB,CAAoC;IAElE,OAAO,CAAC,iBAAiB,CAAoB;;IAS7C,OAAO,CAAC,cAAc;IA6BhB,aAAa,CAAC,OAAO,EAAE,WAAW;IAuExC,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;YAOV,gBAAgB;CAiC/B;AAED,eAAO,MAAM,QAAQ,YAIpB,CAAC;AAEF,eAAO,MAAM,aAAa,uBAYzB,CAAC;AAMF,eAAO,MAAM,IAAI,aACL,eAAe,aACd,GAAG,WACL,6BAA6B,8BAiBvC,CAAC;AAEF,eAAO,MAAM,eAAe;SAKrB,eAAe,CAAC,KAAK,CAAC;eAChB,GAAG;;UASf,CAAC"}
package/dist/index.js CHANGED
@@ -65191,6 +65191,8 @@ const onCallDevice = (context, message, method) => __awaiter(void 0, void 0, voi
65191
65191
  if ((_g = method.payload) === null || _g === void 0 ? void 0 : _g.onlyConnectBleDevice) {
65192
65192
  preWarmCallbackTask === null || preWarmCallbackTask === void 0 ? void 0 : preWarmCallbackTask.resolve();
65193
65193
  Log.debug('Call API - only connect ble device: ', device === null || device === void 0 ? void 0 : device.mainId);
65194
+ completeMethodRequestContext(method);
65195
+ requestQueue.releaseTask(method.responseID);
65194
65196
  return createResponseMessage(method.responseID, true, null);
65195
65197
  }
65196
65198
  Log.debug('Call API - setDevice: ', device.mainId);
@@ -65566,7 +65568,31 @@ function isMissingDetectedProtocolV2Error(method, error) {
65566
65568
  typeof typedError.message === 'string' &&
65567
65569
  typedError.message.includes('Device protocol has not been detected'));
65568
65570
  }
65569
- function connectDeviceForBle(method, device, retryCount = 0) {
65571
+ const BLE_ACQUIRE_DEADLINE_MS = 60 * 1000;
65572
+ function raceBleAcquire(acquirePromise, abortSignal) {
65573
+ return new Promise((resolve, reject) => {
65574
+ let settled = false;
65575
+ const settle = (fn) => {
65576
+ if (settled)
65577
+ return;
65578
+ settled = true;
65579
+ clearTimeout(deadline);
65580
+ abortSignal === null || abortSignal === void 0 ? void 0 : abortSignal.removeEventListener('abort', onAbort);
65581
+ fn();
65582
+ };
65583
+ const onAbort = () => settle(() => reject(hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.CallQueueActionCancelled)));
65584
+ const deadline = setTimeout(() => settle(() => reject(hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleTimeoutError, `BLE acquire exceeded ${BLE_ACQUIRE_DEADLINE_MS}ms deadline`))), BLE_ACQUIRE_DEADLINE_MS);
65585
+ acquirePromise.then(value => settle(() => resolve(value)), error => settle(() => reject(error)));
65586
+ if (abortSignal) {
65587
+ if (abortSignal.aborted) {
65588
+ onAbort();
65589
+ return;
65590
+ }
65591
+ abortSignal.addEventListener('abort', onAbort);
65592
+ }
65593
+ });
65594
+ }
65595
+ function connectDeviceForBle(method, device, abortSignal, retryCount = 0) {
65570
65596
  var _a;
65571
65597
  return __awaiter(this, void 0, void 0, function* () {
65572
65598
  try {
@@ -65581,9 +65607,31 @@ function connectDeviceForBle(method, device, retryCount = 0) {
65581
65607
  !device.commands ||
65582
65608
  device.commands.disposed;
65583
65609
  if (shouldAcquire) {
65584
- yield device.acquire(method.payload.connectProtocol, {
65585
- forceProtocolDetection: method.payload.forceProtocolDetection,
65586
- });
65610
+ const useAcquireGuards = DataManager.getSettings('env') === 'desktop-web-ble';
65611
+ if (useAcquireGuards && (abortSignal === null || abortSignal === void 0 ? void 0 : abortSignal.aborted)) {
65612
+ throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.CallQueueActionCancelled);
65613
+ }
65614
+ if (!useAcquireGuards) {
65615
+ yield device.acquire(method.payload.connectProtocol, {
65616
+ forceProtocolDetection: method.payload.forceProtocolDetection,
65617
+ });
65618
+ }
65619
+ else {
65620
+ try {
65621
+ yield raceBleAcquire(device.acquire(method.payload.connectProtocol, {
65622
+ forceProtocolDetection: method.payload.forceProtocolDetection,
65623
+ }), abortSignal);
65624
+ }
65625
+ catch (err) {
65626
+ if (err.errorCode === hdShared.HardwareErrorCode.BleTimeoutError &&
65627
+ device.mainId &&
65628
+ device.deviceConnector) {
65629
+ yield device.deviceConnector.disconnect(device.mainId).catch(() => undefined);
65630
+ device.markTransportDisconnected();
65631
+ }
65632
+ throw err;
65633
+ }
65634
+ }
65587
65635
  }
65588
65636
  if ((_a = method.payload) === null || _a === void 0 ? void 0 : _a.onlyConnectBleDevice) {
65589
65637
  if (shouldAcquire) {
@@ -65614,7 +65662,7 @@ function connectDeviceForBle(method, device, retryCount = 0) {
65614
65662
  const nextRetry = retryCount + 1;
65615
65663
  Log.debug(`Bluetooth connection will retry, retry count: ${nextRetry}`);
65616
65664
  yield wait(3000);
65617
- yield connectDeviceForBle(method, device, nextRetry);
65665
+ yield connectDeviceForBle(method, device, abortSignal, nextRetry);
65618
65666
  }
65619
65667
  else {
65620
65668
  throw err;
@@ -65699,7 +65747,7 @@ const ensureConnected = (_context, method, connectId, pollingId, abortSignal) =>
65699
65747
  if (tryCount === 1) {
65700
65748
  device.beginConnectionAttempt();
65701
65749
  }
65702
- yield connectDeviceForBle(method, device);
65750
+ yield connectDeviceForBle(method, device, abortSignal);
65703
65751
  }
65704
65752
  resolve(device);
65705
65753
  return;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@onekeyfe/hd-core",
3
- "version": "1.2.0-alpha.172",
3
+ "version": "1.2.0-alpha.174",
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.172",
29
- "@onekeyfe/hd-transport": "1.2.0-alpha.172",
28
+ "@onekeyfe/hd-shared": "1.2.0-alpha.174",
29
+ "@onekeyfe/hd-transport": "1.2.0-alpha.174",
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": "4c6c4a4fcc52bcdd0b3ec9c36454b2074fa17a8c"
49
+ "gitHead": "ea906ff2ef191338cbc98d083e8217ddfb23c92c"
50
50
  }
package/src/core/index.ts CHANGED
@@ -415,6 +415,13 @@ const onCallDevice = async (
415
415
  if (method.payload?.onlyConnectBleDevice) {
416
416
  preWarmCallbackTask?.resolve();
417
417
  Log.debug('Call API - only connect ble device: ', device?.mainId);
418
+ // This early return bypasses the normal-path bookkeeping at the end of the
419
+ // call. Without it the task leaks and haunts every later queue snapshot
420
+ // and cancel sweep (field log: a completed task lingered for 6 minutes),
421
+ // and the request stays in the active maps, so repeated preconnects pile
422
+ // up phantom work in diagnostics.
423
+ completeMethodRequestContext(method);
424
+ requestQueue.releaseTask(method.responseID);
418
425
  return createResponseMessage(method.responseID, true, null);
419
426
  }
420
427
 
@@ -954,7 +961,60 @@ export function isMissingDetectedProtocolV2Error(method: BaseMethod, error: unkn
954
961
  * If the Bluetooth connection times out, retry up to 6 times
955
962
  * @param retryCount - Current retry count (default 0)
956
963
  */
957
- async function connectDeviceForBle(method: BaseMethod, device: Device, retryCount = 0) {
964
+ // device.acquire awaits a transport reply with no deadline of its own; a
965
+ // transport that never settles (field case: Electron main lost an IPC reply,
966
+ // "reply was never sent" after 5 minutes) hangs the call forever and cancel()
967
+ // only takes effect at poll checkpoints. Race acquire against a deadline and
968
+ // the caller's abort signal so the hang is bounded and cancel is immediate.
969
+ const BLE_ACQUIRE_DEADLINE_MS = 60 * 1000;
970
+
971
+ function raceBleAcquire<T>(acquirePromise: Promise<T>, abortSignal?: AbortSignal): Promise<T> {
972
+ return new Promise<T>((resolve, reject) => {
973
+ let settled = false;
974
+ const settle = (fn: () => void) => {
975
+ if (settled) return;
976
+ settled = true;
977
+ clearTimeout(deadline);
978
+ abortSignal?.removeEventListener('abort', onAbort);
979
+ fn();
980
+ };
981
+ const onAbort = () =>
982
+ settle(() => reject(ERRORS.TypedError(HardwareErrorCode.CallQueueActionCancelled)));
983
+ const deadline = setTimeout(
984
+ () =>
985
+ settle(() =>
986
+ reject(
987
+ ERRORS.TypedError(
988
+ HardwareErrorCode.BleTimeoutError,
989
+ `BLE acquire exceeded ${BLE_ACQUIRE_DEADLINE_MS}ms deadline`
990
+ )
991
+ )
992
+ ),
993
+ BLE_ACQUIRE_DEADLINE_MS
994
+ );
995
+ // Attach before any early return so a late settlement of acquirePromise
996
+ // is always consumed — an abort or deadline must never leave the acquire
997
+ // rejection unhandled.
998
+ acquirePromise.then(
999
+ value => settle(() => resolve(value)),
1000
+ error => settle(() => reject(error))
1001
+ );
1002
+ if (abortSignal) {
1003
+ if (abortSignal.aborted) {
1004
+ onAbort();
1005
+ return;
1006
+ }
1007
+ abortSignal.addEventListener('abort', onAbort);
1008
+ }
1009
+ });
1010
+ }
1011
+
1012
+ async function connectDeviceForBle(
1013
+ method: BaseMethod,
1014
+ device: Device,
1015
+ abortSignal?: AbortSignal,
1016
+ retryCount = 0
1017
+ ) {
958
1018
  try {
959
1019
  if (device.wasInterruptedByUser()) {
960
1020
  throw ERRORS.TypedError(HardwareErrorCode.DeviceInterruptedFromUser);
@@ -968,9 +1028,43 @@ async function connectDeviceForBle(method: BaseMethod, device: Device, retryCoun
968
1028
  !device.commands ||
969
1029
  device.commands.disposed;
970
1030
  if (shouldAcquire) {
971
- await device.acquire(method.payload.connectProtocol, {
972
- forceProtocolDetection: method.payload.forceProtocolDetection,
973
- });
1031
+ // The deadline/abort guards are scoped to the desktop electron
1032
+ // transport: its IPC acquire is the only path with a proven
1033
+ // never-settling failure mode, while react-native/lowlevel acquire may
1034
+ // legitimately block on a user-driven system bonding prompt for longer
1035
+ // than any sane deadline. Other envs keep the plain acquire unchanged.
1036
+ const useAcquireGuards = DataManager.getSettings('env') === 'desktop-web-ble';
1037
+ // A cancel landing during the retry backoff must not start a new acquire.
1038
+ if (useAcquireGuards && abortSignal?.aborted) {
1039
+ throw ERRORS.TypedError(HardwareErrorCode.CallQueueActionCancelled);
1040
+ }
1041
+ if (!useAcquireGuards) {
1042
+ await device.acquire(method.payload.connectProtocol, {
1043
+ forceProtocolDetection: method.payload.forceProtocolDetection,
1044
+ });
1045
+ } else {
1046
+ try {
1047
+ await raceBleAcquire(
1048
+ device.acquire(method.payload.connectProtocol, {
1049
+ forceProtocolDetection: method.payload.forceProtocolDetection,
1050
+ }),
1051
+ abortSignal
1052
+ );
1053
+ } catch (err) {
1054
+ // A deadline hit means the transport is wedged mid-acquire; drop the
1055
+ // link before the retry so it cold-connects instead of stacking a
1056
+ // second connect onto the half-open one.
1057
+ if (
1058
+ err.errorCode === HardwareErrorCode.BleTimeoutError &&
1059
+ device.mainId &&
1060
+ device.deviceConnector
1061
+ ) {
1062
+ await device.deviceConnector.disconnect(device.mainId).catch(() => undefined);
1063
+ device.markTransportDisconnected();
1064
+ }
1065
+ throw err;
1066
+ }
1067
+ }
974
1068
  }
975
1069
  if (method.payload?.onlyConnectBleDevice) {
976
1070
  if (shouldAcquire) {
@@ -1010,7 +1104,7 @@ async function connectDeviceForBle(method: BaseMethod, device: Device, retryCoun
1010
1104
  const nextRetry = retryCount + 1;
1011
1105
  Log.debug(`Bluetooth connection will retry, retry count: ${nextRetry}`);
1012
1106
  await wait(3000);
1013
- await connectDeviceForBle(method, device, nextRetry);
1107
+ await connectDeviceForBle(method, device, abortSignal, nextRetry);
1014
1108
  } else {
1015
1109
  throw err;
1016
1110
  }
@@ -1120,7 +1214,7 @@ const ensureConnected = async (
1120
1214
  if (tryCount === 1) {
1121
1215
  device.beginConnectionAttempt();
1122
1216
  }
1123
- await connectDeviceForBle(method, device);
1217
+ await connectDeviceForBle(method, device, abortSignal);
1124
1218
  }
1125
1219
  resolve(device);
1126
1220
  return;