Skip to content

Commit fee35af

Browse files
authored
fix: desktop bluetooth issue (#612)
* fix: enhance subscription operation state management to prevent race conditions * chore: update version * chore: update version
1 parent fc9276c commit fee35af

File tree

16 files changed

+94
-74
lines changed

16 files changed

+94
-74
lines changed

packages/connect-examples/electron-example/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"name": "hardware-example",
33
"productName": "HardwareExample",
44
"executableName": "onekey-hardware-example",
5-
"version": "1.1.17",
5+
"version": "1.1.18",
66
"author": "OneKey",
77
"description": "End-to-end encrypted workspaces for teams",
88
"main": "dist/index.js",
@@ -22,7 +22,7 @@
2222
"ts:check": "yarn tsc --noEmit"
2323
},
2424
"dependencies": {
25-
"@onekeyfe/hd-transport-electron": "1.1.17",
25+
"@onekeyfe/hd-transport-electron": "1.1.18",
2626
"@stoprocent/noble": "2.3.4",
2727
"debug": "4.3.4",
2828
"electron-is-dev": "^3.0.1",

packages/connect-examples/expo-example/package.json

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "expo-example",
3-
"version": "1.1.17",
3+
"version": "1.1.18",
44
"scripts": {
55
"start": "cross-env CONNECT_SRC=https://localhost:8087/ yarn expo start --dev-client",
66
"android": "yarn expo run:android",
@@ -19,10 +19,10 @@
1919
"@noble/ed25519": "^2.1.0",
2020
"@noble/hashes": "^1.3.3",
2121
"@noble/secp256k1": "^1.7.1",
22-
"@onekeyfe/hd-ble-sdk": "1.1.17",
23-
"@onekeyfe/hd-common-connect-sdk": "1.1.17",
24-
"@onekeyfe/hd-core": "1.1.17",
25-
"@onekeyfe/hd-web-sdk": "1.1.17",
22+
"@onekeyfe/hd-ble-sdk": "1.1.18",
23+
"@onekeyfe/hd-common-connect-sdk": "1.1.18",
24+
"@onekeyfe/hd-core": "1.1.18",
25+
"@onekeyfe/hd-web-sdk": "1.1.18",
2626
"@onekeyfe/react-native-ble-utils": "^0.1.3",
2727
"@polkadot/util-crypto": "13.1.1",
2828
"@react-native-async-storage/async-storage": "1.21.0",

packages/connect-examples/expo-playground/package.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "onekey-hardware-playground",
3-
"version": "1.1.17",
3+
"version": "1.1.18",
44
"private": true,
55
"sideEffects": [
66
"app/utils/shim.js",
@@ -17,9 +17,9 @@
1717
},
1818
"dependencies": {
1919
"@noble/hashes": "^1.8.0",
20-
"@onekeyfe/hd-common-connect-sdk": "1.1.17",
21-
"@onekeyfe/hd-core": "1.1.17",
22-
"@onekeyfe/hd-shared": "1.1.17",
20+
"@onekeyfe/hd-common-connect-sdk": "1.1.18",
21+
"@onekeyfe/hd-core": "1.1.18",
22+
"@onekeyfe/hd-shared": "1.1.18",
2323
"@radix-ui/react-checkbox": "^1.3.2",
2424
"@radix-ui/react-dialog": "^1.1.14",
2525
"@radix-ui/react-dropdown-menu": "^2.1.15",

packages/core/package.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@onekeyfe/hd-core",
3-
"version": "1.1.17",
3+
"version": "1.1.18",
44
"description": "Core processes and APIs for communicating with OneKey hardware devices.",
55
"author": "OneKey",
66
"homepage": "https://github.com/OneKeyHQ/hardware-js-sdk#readme",
@@ -25,8 +25,8 @@
2525
"url": "https://github.com/OneKeyHQ/hardware-js-sdk/issues"
2626
},
2727
"dependencies": {
28-
"@onekeyfe/hd-shared": "1.1.17",
29-
"@onekeyfe/hd-transport": "1.1.17",
28+
"@onekeyfe/hd-shared": "1.1.18",
29+
"@onekeyfe/hd-transport": "1.1.18",
3030
"axios": "1.12.2",
3131
"bignumber.js": "^9.0.2",
3232
"bytebuffer": "^5.0.1",

packages/hd-ble-sdk/package.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@onekeyfe/hd-ble-sdk",
3-
"version": "1.1.17",
3+
"version": "1.1.18",
44
"author": "OneKey",
55
"homepage": "https://github.com/OneKeyHQ/hardware-js-sdk#readme",
66
"license": "ISC",
@@ -20,8 +20,8 @@
2020
"lint:fix": "eslint . --fix"
2121
},
2222
"dependencies": {
23-
"@onekeyfe/hd-core": "1.1.17",
24-
"@onekeyfe/hd-shared": "1.1.17",
25-
"@onekeyfe/hd-transport-react-native": "1.1.17"
23+
"@onekeyfe/hd-core": "1.1.18",
24+
"@onekeyfe/hd-shared": "1.1.18",
25+
"@onekeyfe/hd-transport-react-native": "1.1.18"
2626
}
2727
}

packages/hd-common-connect-sdk/package.json

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@onekeyfe/hd-common-connect-sdk",
3-
"version": "1.1.17",
3+
"version": "1.1.18",
44
"author": "OneKey",
55
"homepage": "https://github.com/OneKeyHQ/hardware-js-sdk#readme",
66
"license": "ISC",
@@ -20,11 +20,11 @@
2020
"lint:fix": "eslint . --fix"
2121
},
2222
"dependencies": {
23-
"@onekeyfe/hd-core": "1.1.17",
24-
"@onekeyfe/hd-shared": "1.1.17",
25-
"@onekeyfe/hd-transport-emulator": "1.1.17",
26-
"@onekeyfe/hd-transport-http": "1.1.17",
27-
"@onekeyfe/hd-transport-lowlevel": "1.1.17",
28-
"@onekeyfe/hd-transport-web-device": "1.1.17"
23+
"@onekeyfe/hd-core": "1.1.18",
24+
"@onekeyfe/hd-shared": "1.1.18",
25+
"@onekeyfe/hd-transport-emulator": "1.1.18",
26+
"@onekeyfe/hd-transport-http": "1.1.18",
27+
"@onekeyfe/hd-transport-lowlevel": "1.1.18",
28+
"@onekeyfe/hd-transport-web-device": "1.1.18"
2929
}
3030
}

packages/hd-transport-electron/package.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@onekeyfe/hd-transport-electron",
3-
"version": "1.1.17",
3+
"version": "1.1.18",
44
"author": "OneKey",
55
"homepage": "https://github.com/OneKeyHQ/hardware-js-sdk#readme",
66
"license": "MIT",
@@ -25,9 +25,9 @@
2525
"electron-log": ">=4.0.0"
2626
},
2727
"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",
29+
"@onekeyfe/hd-shared": "1.1.18",
30+
"@onekeyfe/hd-transport": "1.1.18",
3131
"@stoprocent/noble": "2.3.4",
3232
"p-retry": "^4.6.2"
3333
},

packages/hd-transport-electron/src/noble-ble-handler.ts

Lines changed: 42 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ const deviceCharacteristics = new Map<string, CharacteristicPair>();
5050
const notificationCallbacks = new Map<string, (data: string) => void>();
5151
const subscribedDevices = new Map<string, boolean>(); // Track subscription status
5252

53-
// 🔒 Add subscription operation state tracking to prevent race conditions
53+
// 🔒 Subscription operation state tracking to prevent race conditions
5454
const subscriptionOperations = new Map<string, 'subscribing' | 'unsubscribing' | 'idle'>();
5555

5656
// Packet reassembly state for each device
@@ -1367,25 +1367,28 @@ async function unsubscribeNotifications(deviceId: string): Promise<void> {
13671367
// 🔒 Set operation state to prevent race conditions
13681368
subscriptionOperations.set(deviceId, 'unsubscribing');
13691369

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+
});
13871381
});
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+
}
13891392
}
13901393

13911394
// Subscribe to notifications
@@ -1406,20 +1409,37 @@ async function subscribeNotifications(
14061409
const { notify: notifyCharacteristic } = characteristics;
14071410

14081411
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+
14091416
logger?.info('[NobleBLE] Subscribe context', {
14101417
deviceId,
1411-
opStateBefore: subscriptionOperations.get(deviceId) || 'idle',
1418+
opStateBefore: opState || 'idle',
14121419
paired: false,
14131420
hasController: false,
14141421
});
1422+
14151423
// If a subscription is already in progress, dedupe
1416-
const opState = subscriptionOperations.get(deviceId);
14171424
if (opState === 'subscribing') {
1418-
// Subscription in progress; update callback and return
1425+
logger?.info('[NobleBLE] Subscription already in progress, updating callback only');
14191426
notificationCallbacks.set(deviceId, callback);
14201427
return Promise.resolve();
14211428
}
14221429

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+
14231443
// 🔒 Set operation state to prevent race conditions
14241444
subscriptionOperations.set(deviceId, 'subscribing');
14251445

packages/hd-transport-emulator/package.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@onekeyfe/hd-transport-emulator",
3-
"version": "1.1.17",
3+
"version": "1.1.18",
44
"description": "hardware emulator transport",
55
"author": "OneKey",
66
"homepage": "https://github.com/OneKeyHQ/hardware-js-sdk#readme",
@@ -24,8 +24,8 @@
2424
"url": "https://github.com/OneKeyHQ/hardware-js-sdk/issues"
2525
},
2626
"dependencies": {
27-
"@onekeyfe/hd-shared": "1.1.17",
28-
"@onekeyfe/hd-transport": "1.1.17",
27+
"@onekeyfe/hd-shared": "1.1.18",
28+
"@onekeyfe/hd-transport": "1.1.18",
2929
"axios": "1.12.2",
3030
"secure-json-parse": "^4.0.0"
3131
}

packages/hd-transport-http/package.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@onekeyfe/hd-transport-http",
3-
"version": "1.1.17",
3+
"version": "1.1.18",
44
"description": "hardware http transport",
55
"author": "OneKey",
66
"homepage": "https://github.com/OneKeyHQ/hardware-js-sdk#readme",
@@ -24,8 +24,8 @@
2424
"url": "https://github.com/OneKeyHQ/hardware-js-sdk/issues"
2525
},
2626
"dependencies": {
27-
"@onekeyfe/hd-shared": "1.1.17",
28-
"@onekeyfe/hd-transport": "1.1.17",
27+
"@onekeyfe/hd-shared": "1.1.18",
28+
"@onekeyfe/hd-transport": "1.1.18",
2929
"axios": "1.12.2",
3030
"secure-json-parse": "^4.0.0"
3131
}

0 commit comments

Comments
 (0)