@onekeyfe/hd-transport-electron 1.1.17 → 1.1.18-alpha.0

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.
@@ -32,7 +32,7 @@ typeof SuppressedError === "function" ? SuppressedError : function (error, suppr
32
32
 
33
33
  function initNobleBleSupport(webContents) {
34
34
  return __awaiter(this, void 0, void 0, function* () {
35
- const { setupNobleBleHandlers } = yield Promise.resolve().then(function () { return require('./noble-ble-handler-cdfacb43.js'); });
35
+ const { setupNobleBleHandlers } = yield Promise.resolve().then(function () { return require('./noble-ble-handler-24e390db.js'); });
36
36
  setupNobleBleHandlers(webContents);
37
37
  });
38
38
  }
package/dist/index.js CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
- var index = require('./index-f13d8b92.js');
5
+ var index = require('./index-28d46641.js');
6
6
 
7
7
 
8
8
 
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var index = require('./index-f13d8b92.js');
3
+ var index = require('./index-28d46641.js');
4
4
  var hdShared = require('@onekeyfe/hd-shared');
5
5
  var hdTransport = require('@onekeyfe/hd-transport');
6
6
  var pRetry = require('p-retry');
@@ -1001,22 +1001,27 @@ function unsubscribeNotifications(deviceId) {
1001
1001
  const { notify: notifyCharacteristic } = characteristics;
1002
1002
  logger === null || logger === void 0 ? void 0 : logger.info('[NobleBLE] Unsubscribing from notifications for device:', deviceId);
1003
1003
  subscriptionOperations.set(deviceId, 'unsubscribing');
1004
- return new Promise(resolve => {
1005
- notifyCharacteristic.unsubscribe((error) => {
1006
- if (error) {
1007
- logger === null || logger === void 0 ? void 0 : logger.error('[NobleBLE] Notification unsubscription failed:', error);
1008
- }
1009
- else {
1010
- logger === null || logger === void 0 ? void 0 : logger.info('[NobleBLE] Notification unsubscription successful');
1011
- }
1012
- notifyCharacteristic.removeAllListeners('data');
1013
- notificationCallbacks.delete(deviceId);
1014
- devicePacketStates.delete(deviceId);
1015
- subscribedDevices.delete(deviceId);
1016
- subscriptionOperations.set(deviceId, 'idle');
1017
- resolve();
1004
+ try {
1005
+ yield new Promise((resolve, reject) => {
1006
+ notifyCharacteristic.unsubscribe((error) => {
1007
+ if (error) {
1008
+ logger === null || logger === void 0 ? void 0 : logger.error('[NobleBLE] Notification unsubscription failed:', error);
1009
+ reject(error);
1010
+ }
1011
+ else {
1012
+ logger === null || logger === void 0 ? void 0 : logger.info('[NobleBLE] Notification unsubscription successful');
1013
+ resolve();
1014
+ }
1015
+ });
1018
1016
  });
1019
- });
1017
+ notifyCharacteristic.removeAllListeners('data');
1018
+ notificationCallbacks.delete(deviceId);
1019
+ devicePacketStates.delete(deviceId);
1020
+ subscribedDevices.delete(deviceId);
1021
+ }
1022
+ finally {
1023
+ subscriptionOperations.set(deviceId, 'idle');
1024
+ }
1020
1025
  });
1021
1026
  }
1022
1027
  function subscribeNotifications(deviceId, callback) {
@@ -1028,17 +1033,25 @@ function subscribeNotifications(deviceId, callback) {
1028
1033
  }
1029
1034
  const { notify: notifyCharacteristic } = characteristics;
1030
1035
  logger === null || logger === void 0 ? void 0 : logger.info('[NobleBLE] Subscribing to notifications for device:', deviceId);
1036
+ const opState = subscriptionOperations.get(deviceId);
1031
1037
  logger === null || logger === void 0 ? void 0 : logger.info('[NobleBLE] Subscribe context', {
1032
1038
  deviceId,
1033
- opStateBefore: subscriptionOperations.get(deviceId) || 'idle',
1039
+ opStateBefore: opState || 'idle',
1034
1040
  paired: false,
1035
1041
  hasController: false,
1036
1042
  });
1037
- const opState = subscriptionOperations.get(deviceId);
1038
1043
  if (opState === 'subscribing') {
1044
+ logger === null || logger === void 0 ? void 0 : logger.info('[NobleBLE] Subscription already in progress, updating callback only');
1039
1045
  notificationCallbacks.set(deviceId, callback);
1040
1046
  return Promise.resolve();
1041
1047
  }
1048
+ if (opState === 'unsubscribing') {
1049
+ logger === null || logger === void 0 ? void 0 : logger.error('[NobleBLE] Cannot subscribe while unsubscribe is in progress', {
1050
+ deviceId,
1051
+ opState,
1052
+ });
1053
+ throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.DeviceBusy, `Device ${deviceId} is currently unsubscribing, please retry after reconnection`);
1054
+ }
1042
1055
  subscriptionOperations.set(deviceId, 'subscribing');
1043
1056
  if (subscribedDevices.get(deviceId)) {
1044
1057
  logger === null || logger === void 0 ? void 0 : logger.info('[NobleBLE] Device already subscribed to characteristic, updating callback only');
@@ -1 +1 @@
1
- {"version":3,"file":"noble-ble-handler.d.ts","sourceRoot":"","sources":["../src/noble-ble-handler.ts"],"names":[],"mappings":"AAmBA,OAAO,KAAK,EAAE,WAAW,EAAsB,MAAM,UAAU,CAAC;AAq9ChE,wBAAgB,qBAAqB,CAAC,WAAW,EAAE,WAAW,GAAG,IAAI,CAsKpE"}
1
+ {"version":3,"file":"noble-ble-handler.d.ts","sourceRoot":"","sources":["../src/noble-ble-handler.ts"],"names":[],"mappings":"AAmBA,OAAO,KAAK,EAAE,WAAW,EAAsB,MAAM,UAAU,CAAC;AAy+ChE,wBAAgB,qBAAqB,CAAC,WAAW,EAAE,WAAW,GAAG,IAAI,CAsKpE"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@onekeyfe/hd-transport-electron",
3
- "version": "1.1.17",
3
+ "version": "1.1.18-alpha.0",
4
4
  "author": "OneKey",
5
5
  "homepage": "https://github.com/OneKeyHQ/hardware-js-sdk#readme",
6
6
  "license": "MIT",
@@ -25,9 +25,9 @@
25
25
  "electron-log": ">=4.0.0"
26
26
  },
27
27
  "dependencies": {
28
- "@onekeyfe/hd-core": "1.1.17",
29
- "@onekeyfe/hd-shared": "1.1.17",
30
- "@onekeyfe/hd-transport": "1.1.17",
28
+ "@onekeyfe/hd-core": "1.1.18-alpha.0",
29
+ "@onekeyfe/hd-shared": "1.1.18-alpha.0",
30
+ "@onekeyfe/hd-transport": "1.1.18-alpha.0",
31
31
  "@stoprocent/noble": "2.3.4",
32
32
  "p-retry": "^4.6.2"
33
33
  },
@@ -36,5 +36,5 @@
36
36
  "electron": "^25.0.0",
37
37
  "typescript": "^5.3.3"
38
38
  },
39
- "gitHead": "fc9276c5fdefe528e32f463446759ac74065e680"
39
+ "gitHead": "bec196c57a2a5be4e239dbb14338ddbcd8d4e14f"
40
40
  }
@@ -50,7 +50,7 @@ const deviceCharacteristics = new Map<string, CharacteristicPair>();
50
50
  const notificationCallbacks = new Map<string, (data: string) => void>();
51
51
  const subscribedDevices = new Map<string, boolean>(); // Track subscription status
52
52
 
53
- // 🔒 Add subscription operation state tracking to prevent race conditions
53
+ // 🔒 Subscription operation state tracking to prevent race conditions
54
54
  const subscriptionOperations = new Map<string, 'subscribing' | 'unsubscribing' | 'idle'>();
55
55
 
56
56
  // Packet reassembly state for each device
@@ -1367,25 +1367,28 @@ async function unsubscribeNotifications(deviceId: string): Promise<void> {
1367
1367
  // 🔒 Set operation state to prevent race conditions
1368
1368
  subscriptionOperations.set(deviceId, 'unsubscribing');
1369
1369
 
1370
- return new Promise<void>(resolve => {
1371
- notifyCharacteristic.unsubscribe((error: Error | undefined) => {
1372
- if (error) {
1373
- logger?.error('[NobleBLE] Notification unsubscription failed:', error);
1374
- } else {
1375
- logger?.info('[NobleBLE] Notification unsubscription successful');
1376
- }
1377
-
1378
- // Remove all listeners and clear subscription status
1379
- notifyCharacteristic.removeAllListeners('data');
1380
- notificationCallbacks.delete(deviceId);
1381
- devicePacketStates.delete(deviceId);
1382
- subscribedDevices.delete(deviceId);
1383
-
1384
- // 🔒 Clear operation state
1385
- subscriptionOperations.set(deviceId, 'idle');
1386
- resolve();
1370
+ try {
1371
+ await new Promise<void>((resolve, reject) => {
1372
+ notifyCharacteristic.unsubscribe((error: Error | undefined) => {
1373
+ if (error) {
1374
+ logger?.error('[NobleBLE] Notification unsubscription failed:', error);
1375
+ reject(error);
1376
+ } else {
1377
+ logger?.info('[NobleBLE] Notification unsubscription successful');
1378
+ resolve();
1379
+ }
1380
+ });
1387
1381
  });
1388
- });
1382
+
1383
+ // Remove all listeners and clear subscription status
1384
+ notifyCharacteristic.removeAllListeners('data');
1385
+ notificationCallbacks.delete(deviceId);
1386
+ devicePacketStates.delete(deviceId);
1387
+ subscribedDevices.delete(deviceId);
1388
+ } finally {
1389
+ // 🔒 CRITICAL: Always clear operation state (even on error)
1390
+ subscriptionOperations.set(deviceId, 'idle');
1391
+ }
1389
1392
  }
1390
1393
 
1391
1394
  // Subscribe to notifications
@@ -1406,20 +1409,37 @@ async function subscribeNotifications(
1406
1409
  const { notify: notifyCharacteristic } = characteristics;
1407
1410
 
1408
1411
  logger?.info('[NobleBLE] Subscribing to notifications for device:', deviceId);
1412
+
1413
+ // 🔒 CRITICAL: Check operation state FIRST to prevent race conditions
1414
+ const opState = subscriptionOperations.get(deviceId);
1415
+
1409
1416
  logger?.info('[NobleBLE] Subscribe context', {
1410
1417
  deviceId,
1411
- opStateBefore: subscriptionOperations.get(deviceId) || 'idle',
1418
+ opStateBefore: opState || 'idle',
1412
1419
  paired: false,
1413
1420
  hasController: false,
1414
1421
  });
1422
+
1415
1423
  // If a subscription is already in progress, dedupe
1416
- const opState = subscriptionOperations.get(deviceId);
1417
1424
  if (opState === 'subscribing') {
1418
- // Subscription in progress; update callback and return
1425
+ logger?.info('[NobleBLE] Subscription already in progress, updating callback only');
1419
1426
  notificationCallbacks.set(deviceId, callback);
1420
1427
  return Promise.resolve();
1421
1428
  }
1422
1429
 
1430
+ // 🚨 CRITICAL: Reject subscribe if unsubscribe is in progress
1431
+ // Let upper layer handle retry after device reconnection
1432
+ if (opState === 'unsubscribing') {
1433
+ logger?.error('[NobleBLE] Cannot subscribe while unsubscribe is in progress', {
1434
+ deviceId,
1435
+ opState,
1436
+ });
1437
+ throw ERRORS.TypedError(
1438
+ HardwareErrorCode.DeviceBusy,
1439
+ `Device ${deviceId} is currently unsubscribing, please retry after reconnection`
1440
+ );
1441
+ }
1442
+
1423
1443
  // 🔒 Set operation state to prevent race conditions
1424
1444
  subscriptionOperations.set(deviceId, 'subscribing');
1425
1445