Skip to content
Open
Show file tree
Hide file tree
Changes from 19 commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
0ccaa0d
fix: drop stale peripheral cache on disconnect and keep BLE state lis…
originalix Aug 18, 2026
006f903
fix: bound BLE acquire with a desktop-scoped deadline, wire cancel in…
originalix Aug 19, 2026
d1fa81c
chore: bump version to 1.2.0-alpha.151
originalix Aug 19, 2026
f6ceaf5
fix: unsubscribe notifications before keep-alive disconnect and confi…
originalix Aug 19, 2026
6f1d6ce
chore: bump version to 1.2.0-alpha.153
originalix Aug 19, 2026
2544b0b
fix: declare warn on the transport Logger interface
originalix Aug 19, 2026
82a9616
fix: shorten keep-alive idle disconnect to 20s to stay inside the hot…
originalix Aug 19, 2026
0b81bf2
chore: bump version to 1.2.0-alpha.154
originalix Aug 19, 2026
f15c0e2
merge: onekey (report desktop USB and BLE device disconnects #891)
originalix Aug 19, 2026
881065c
chore: bump version to 1.2.0-alpha.156
originalix Aug 19, 2026
4eff565
chore: bump version to 1.2.0-alpha.158
originalix Aug 19, 2026
66fdd17
fix: reset the BLE link before protocol traffic on every cold setup
originalix Aug 20, 2026
0631611
chore: bump version to 1.2.0-alpha.161
originalix Aug 20, 2026
b1161c7
fix: scan for the advertisement before connecting a cold BLE link by id
originalix Aug 20, 2026
afed1c8
chore: bump version to 1.2.0-alpha.163
originalix Aug 20, 2026
17d6012
fix: pick the BLE cold-connect route per device family and cap the sc…
originalix Aug 20, 2026
8a6f829
chore: bump version to 1.2.0-alpha.164
originalix Aug 20, 2026
ceb65f7
merge: onekey (canonicalize Pro2 BLE names #890)
originalix Aug 20, 2026
dc82ee3
chore: bump version to 1.2.0-alpha.165
originalix Aug 20, 2026
d6be62d
fix: address BLE review findings on acquire timeout, preconnect bookk…
originalix Aug 20, 2026
3dd1b96
chore: bump version to 1.2.0-alpha.166
originalix Aug 20, 2026
72e137f
revert: defer BLE connection-path review fixes until field validation…
originalix Aug 20, 2026
dcbf3a7
chore: log BLE write, subscription and notify frames for field diagnosis
originalix Aug 20, 2026
aa45004
chore: bump version to 1.2.0-alpha.167
originalix Aug 20, 2026
25e3854
merge: onekey (#894)
originalix Aug 20, 2026
64dcbd5
fix: discover the OneKey BLE service by UUID so a stalled device is d…
originalix Aug 20, 2026
ce2d8e3
chore: bump version to 1.2.0-alpha.168
originalix Aug 20, 2026
b2fa03f
chore: bump version to 1.2.0-alpha.173
originalix Aug 20, 2026
25680af
fix: take a declared V1 protocol at face value on desktop BLE
originalix Aug 20, 2026
ea906ff
chore: bump version to 1.2.0-alpha.174
originalix Aug 20, 2026
b46341b
fix: take a declared V1 protocol at face value on mobile BLE too
originalix Aug 20, 2026
b2cb245
chore: bump version to 1.2.0-alpha.175
originalix Aug 20, 2026
f177b02
perf: shorten desktop BLE recovery by failing over to a cold reconnec…
originalix Aug 21, 2026
12d79d1
chore: bump version to 1.2.0-alpha.176
originalix Aug 21, 2026
be22a5d
merge: onekey (harden Protocol V2 firmware install polling #896)
originalix Aug 21, 2026
294d4c3
chore: bump version to 1.2.0-alpha.177
originalix Aug 21, 2026
081c18f
perf: skip the futile fresh scan while the link is still up
originalix Aug 21, 2026
5df24cf
chore: bump version to 1.2.0-alpha.178
originalix Aug 21, 2026
7148e31
test: assert a declared V1 acquire sends no probe frame
originalix Aug 21, 2026
dcdc438
chore: bump version to 1.2.0-alpha.179
originalix Aug 21, 2026
bfb070f
test: stop asserting an exact leftover timeout budget
originalix Aug 21, 2026
37976e1
chore: bump version to 1.2.0-alpha.180
originalix Aug 21, 2026
268ee94
fix: recover in-process when BLE service discovery fails
originalix Aug 21, 2026
cb79652
chore: bump version to 1.2.0-alpha.181
originalix Aug 21, 2026
aaf7b7e
fix: stop logging BLE continuation packet payload bytes
originalix Aug 21, 2026
2e4b245
fix: only record session protocols the device actually answered on
originalix Aug 22, 2026
86d5a6b
chore: bump version to 1.2.0-alpha.182
originalix Aug 22, 2026
106abb2
chore: drop per-packet BLE frame diagnostics
originalix Aug 22, 2026
fd9b6e7
chore: bump version to 1.2.0-alpha.183
originalix Aug 22, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions packages/connect-examples/electron-example/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "hardware-example",
"productName": "HardwareExample",
"executableName": "onekey-hardware-example",
"version": "1.2.0-alpha.162",
"version": "1.2.0-alpha.165",
"author": "OneKey",
"description": "OneKey Hardware SDK Electron BLE example",
"main": "dist/index.js",
Expand All @@ -21,7 +21,7 @@
"ts:check": "yarn tsc --noEmit"
},
"dependencies": {
"@onekeyfe/hd-transport-electron": "1.2.0-alpha.162",
"@onekeyfe/hd-transport-electron": "1.2.0-alpha.165",
"@stoprocent/noble": "2.3.16",
"debug": "4.3.4",
"electron-is-dev": "^3.0.1",
Expand Down
12 changes: 6 additions & 6 deletions packages/connect-examples/expo-example/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "expo-example",
"version": "1.2.0-alpha.162",
"version": "1.2.0-alpha.165",
"scripts": {
"start": "yarn expo start --dev-client",
"android": "yarn expo run:android",
Expand All @@ -19,11 +19,11 @@
"@noble/ed25519": "^2.1.0",
"@noble/hashes": "^1.3.3",
"@noble/secp256k1": "^1.7.1",
"@onekeyfe/hd-ble-sdk": "1.2.0-alpha.162",
"@onekeyfe/hd-common-connect-sdk": "1.2.0-alpha.162",
"@onekeyfe/hd-core": "1.2.0-alpha.162",
"@onekeyfe/hd-shared": "1.2.0-alpha.162",
"@onekeyfe/hd-transport": "1.2.0-alpha.162",
"@onekeyfe/hd-ble-sdk": "1.2.0-alpha.165",
"@onekeyfe/hd-common-connect-sdk": "1.2.0-alpha.165",
"@onekeyfe/hd-core": "1.2.0-alpha.165",
"@onekeyfe/hd-shared": "1.2.0-alpha.165",
"@onekeyfe/hd-transport": "1.2.0-alpha.165",
"@onekeyfe/react-native-ble-utils": "^0.1.3",
"@polkadot/util-crypto": "13.1.1",
"@react-native-async-storage/async-storage": "1.21.0",
Expand Down
10 changes: 5 additions & 5 deletions packages/connect-examples/expo-playground/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "onekey-hardware-playground",
"version": "1.2.0-alpha.162",
"version": "1.2.0-alpha.165",
"private": true,
"sideEffects": [
"app/utils/shim.js",
Expand All @@ -19,10 +19,10 @@
},
"dependencies": {
"@noble/hashes": "^1.8.0",
"@onekeyfe/hd-common-connect-sdk": "1.2.0-alpha.162",
"@onekeyfe/hd-core": "1.2.0-alpha.162",
"@onekeyfe/hd-shared": "1.2.0-alpha.162",
"@onekeyfe/hd-transport": "1.2.0-alpha.162",
"@onekeyfe/hd-common-connect-sdk": "1.2.0-alpha.165",
"@onekeyfe/hd-core": "1.2.0-alpha.165",
"@onekeyfe/hd-shared": "1.2.0-alpha.165",
"@onekeyfe/hd-transport": "1.2.0-alpha.165",
"@radix-ui/react-checkbox": "^1.3.2",
"@radix-ui/react-dialog": "^1.1.14",
"@radix-ui/react-dropdown-menu": "^2.1.15",
Expand Down
2 changes: 1 addition & 1 deletion packages/connect-examples/hwk-demo/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "hwk-demo",
"version": "1.2.0-alpha.162",
"version": "1.2.0-alpha.165",
"private": true,
"main": "index.js",
"scripts": {
Expand Down
6 changes: 3 additions & 3 deletions packages/core/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@onekeyfe/hd-core",
"version": "1.2.0-alpha.162",
"version": "1.2.0-alpha.165",
"description": "Core processes and APIs for communicating with OneKey hardware devices.",
"author": "OneKey",
"homepage": "https://github.com/OneKeyHQ/hardware-js-sdk#readme",
Expand All @@ -25,8 +25,8 @@
"url": "https://github.com/OneKeyHQ/hardware-js-sdk/issues"
},
"dependencies": {
"@onekeyfe/hd-shared": "1.2.0-alpha.162",
"@onekeyfe/hd-transport": "1.2.0-alpha.162",
"@onekeyfe/hd-shared": "1.2.0-alpha.165",
"@onekeyfe/hd-transport": "1.2.0-alpha.165",
"axios": "1.15.2",
"bignumber.js": "^9.0.2",
"buffer": "^6.0.3",
Expand Down
103 changes: 97 additions & 6 deletions packages/core/src/core/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -415,6 +415,10 @@ const onCallDevice = async (
if (method.payload?.onlyConnectBleDevice) {
Comment thread
originalix marked this conversation as resolved.
Comment thread
originalix marked this conversation as resolved.
Comment thread
originalix marked this conversation as resolved.
Comment thread
originalix marked this conversation as resolved.
preWarmCallbackTask?.resolve();
Log.debug('Call API - only connect ble device: ', device?.mainId);
// This early return bypasses the normal-path releaseTask at the end of the
// call; without it the task leaks and haunts every later queue snapshot
// and cancel sweep (field log: a completed task lingered for 6 minutes).
requestQueue.releaseTask(method.responseID);
Comment thread
originalix marked this conversation as resolved.
Comment thread
originalix marked this conversation as resolved.
Comment thread
originalix marked this conversation as resolved.
Comment thread
originalix marked this conversation as resolved.
return createResponseMessage(method.responseID, true, null);
}

Expand Down Expand Up @@ -954,7 +958,60 @@ export function isMissingDetectedProtocolV2Error(method: BaseMethod, error: unkn
* If the Bluetooth connection times out, retry up to 6 times
* @param retryCount - Current retry count (default 0)
*/
async function connectDeviceForBle(method: BaseMethod, device: Device, retryCount = 0) {
// device.acquire awaits a transport reply with no deadline of its own; a
// transport that never settles (field case: Electron main lost an IPC reply,
// "reply was never sent" after 5 minutes) hangs the call forever and cancel()
// only takes effect at poll checkpoints. Race acquire against a deadline and
// the caller's abort signal so the hang is bounded and cancel is immediate.
const BLE_ACQUIRE_DEADLINE_MS = 60 * 1000;

function raceBleAcquire<T>(acquirePromise: Promise<T>, abortSignal?: AbortSignal): Promise<T> {
return new Promise<T>((resolve, reject) => {
let settled = false;
const settle = (fn: () => void) => {
if (settled) return;
settled = true;
clearTimeout(deadline);
abortSignal?.removeEventListener('abort', onAbort);
fn();
};
const onAbort = () =>
settle(() => reject(ERRORS.TypedError(HardwareErrorCode.CallQueueActionCancelled)));
const deadline = setTimeout(
() =>
settle(() =>
reject(
ERRORS.TypedError(
HardwareErrorCode.BleTimeoutError,
`BLE acquire exceeded ${BLE_ACQUIRE_DEADLINE_MS}ms deadline`
)
)
),
BLE_ACQUIRE_DEADLINE_MS
);
// Attach before any early return so a late settlement of acquirePromise
// is always consumed — an abort or deadline must never leave the acquire
// rejection unhandled.
acquirePromise.then(
value => settle(() => resolve(value)),
error => settle(() => reject(error))
);
if (abortSignal) {
if (abortSignal.aborted) {
onAbort();
return;
}
abortSignal.addEventListener('abort', onAbort);
}
});
}

async function connectDeviceForBle(
method: BaseMethod,
device: Device,
abortSignal?: AbortSignal,
retryCount = 0
) {
try {
if (device.wasInterruptedByUser()) {
throw ERRORS.TypedError(HardwareErrorCode.DeviceInterruptedFromUser);
Expand All @@ -968,9 +1025,43 @@ async function connectDeviceForBle(method: BaseMethod, device: Device, retryCoun
!device.commands ||
device.commands.disposed;
if (shouldAcquire) {
await device.acquire(method.payload.connectProtocol, {
forceProtocolDetection: method.payload.forceProtocolDetection,
});
// The deadline/abort guards are scoped to the desktop electron
// transport: its IPC acquire is the only path with a proven
// never-settling failure mode, while react-native/lowlevel acquire may
// legitimately block on a user-driven system bonding prompt for longer
// than any sane deadline. Other envs keep the plain acquire unchanged.
const useAcquireGuards = DataManager.getSettings('env') === 'desktop-web-ble';
// A cancel landing during the retry backoff must not start a new acquire.
if (useAcquireGuards && abortSignal?.aborted) {
throw ERRORS.TypedError(HardwareErrorCode.CallQueueActionCancelled);
}
if (!useAcquireGuards) {
await device.acquire(method.payload.connectProtocol, {
forceProtocolDetection: method.payload.forceProtocolDetection,
});
} else {
try {
await raceBleAcquire(
Comment thread
originalix marked this conversation as resolved.
Comment thread
originalix marked this conversation as resolved.
Comment thread
originalix marked this conversation as resolved.
Comment thread
originalix marked this conversation as resolved.
Comment thread
originalix marked this conversation as resolved.
Comment thread
originalix marked this conversation as resolved.
Comment thread
originalix marked this conversation as resolved.
Comment thread
originalix marked this conversation as resolved.
Comment thread
originalix marked this conversation as resolved.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1: [Acquire deadline allows overlapping native acquires]

When this deadline wins, only raceBleAcquire rejects; the underlying device.acquire() keeps running. Because mainId is normally assigned after that promise resolves, the cleanup guard usually skips the first in-flight link, and the recursive retry starts another acquire while the expired one can still complete and mutate Device commands or protocol state.

Please assign each acquire a cancellable generation, invalidate that generation on deadline, disconnect using the known BLE connect ID, and await teardown before retrying so a late settlement cannot update Device state.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1: [Acquire deadline allows overlapping native acquires]

When this deadline wins, only raceBleAcquire rejects; the underlying device.acquire() keeps running. Because mainId is normally assigned after that promise resolves, cleanup can miss the first in-flight link, and the recursive retry starts another acquire while the expired one can still complete and mutate Device commands or protocol state.

Please invalidate the Device connection-attempt generation, hard-disconnect method.connectId, and await teardown before retrying so a late settlement cannot update Device state.

device.acquire(method.payload.connectProtocol, {
forceProtocolDetection: method.payload.forceProtocolDetection,
}),
abortSignal
);
} catch (err) {
// A deadline hit means the transport is wedged mid-acquire; drop the
// link before the retry so it cold-connects instead of stacking a
// second connect onto the half-open one.
if (
Comment thread
originalix marked this conversation as resolved.
Comment thread
originalix marked this conversation as resolved.
Comment thread
originalix marked this conversation as resolved.
Comment thread
originalix marked this conversation as resolved.
err.errorCode === HardwareErrorCode.BleTimeoutError &&
Comment thread
originalix marked this conversation as resolved.
Comment thread
originalix marked this conversation as resolved.
Comment thread
originalix marked this conversation as resolved.
device.mainId &&
device.deviceConnector
) {
await device.deviceConnector.disconnect(device.mainId).catch(() => undefined);
device.markTransportDisconnected();
}
throw err;
}
}
}
if (method.payload?.onlyConnectBleDevice) {
if (shouldAcquire) {
Expand Down Expand Up @@ -1010,7 +1101,7 @@ async function connectDeviceForBle(method: BaseMethod, device: Device, retryCoun
const nextRetry = retryCount + 1;
Log.debug(`Bluetooth connection will retry, retry count: ${nextRetry}`);
await wait(3000);
await connectDeviceForBle(method, device, nextRetry);
await connectDeviceForBle(method, device, abortSignal, nextRetry);
} else {
throw err;
}
Expand Down Expand Up @@ -1120,7 +1211,7 @@ const ensureConnected = async (
if (tryCount === 1) {
device.beginConnectionAttempt();
}
await connectDeviceForBle(method, device);
await connectDeviceForBle(method, device, abortSignal);
}
resolve(device);
return;
Expand Down
8 changes: 4 additions & 4 deletions packages/hd-ble-sdk/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@onekeyfe/hd-ble-sdk",
"version": "1.2.0-alpha.162",
"version": "1.2.0-alpha.165",
"author": "OneKey",
"homepage": "https://github.com/OneKeyHQ/hardware-js-sdk#readme",
"license": "ISC",
Expand All @@ -20,8 +20,8 @@
"lint:fix": "eslint . --fix"
},
"dependencies": {
"@onekeyfe/hd-core": "1.2.0-alpha.162",
"@onekeyfe/hd-shared": "1.2.0-alpha.162",
"@onekeyfe/hd-transport-react-native": "1.2.0-alpha.162"
"@onekeyfe/hd-core": "1.2.0-alpha.165",
"@onekeyfe/hd-shared": "1.2.0-alpha.165",
"@onekeyfe/hd-transport-react-native": "1.2.0-alpha.165"
}
}
10 changes: 5 additions & 5 deletions packages/hd-cli/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@onekeyfe/hardware-cli",
"version": "1.2.0-alpha.162",
"version": "1.2.0-alpha.165",
"description": "OneKey hardware wallet CLI for testing device communication",
"author": "OneKey",
"license": "Apache-2.0",
Expand Down Expand Up @@ -31,10 +31,10 @@
"test": "jest"
},
"dependencies": {
"@onekeyfe/hd-common-connect-sdk": "1.2.0-alpha.162",
"@onekeyfe/hd-core": "1.2.0-alpha.162",
"@onekeyfe/hd-shared": "1.2.0-alpha.162",
"@onekeyfe/hd-transport-usb": "1.2.0-alpha.162",
"@onekeyfe/hd-common-connect-sdk": "1.2.0-alpha.165",
"@onekeyfe/hd-core": "1.2.0-alpha.165",
"@onekeyfe/hd-shared": "1.2.0-alpha.165",
"@onekeyfe/hd-transport-usb": "1.2.0-alpha.165",
"@stoprocent/noble": "2.3.16",
"commander": "^12.0.0"
}
Expand Down
16 changes: 8 additions & 8 deletions packages/hd-common-connect-sdk/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@onekeyfe/hd-common-connect-sdk",
"version": "1.2.0-alpha.162",
"version": "1.2.0-alpha.165",
"author": "OneKey",
"homepage": "https://github.com/OneKeyHQ/hardware-js-sdk#readme",
"license": "ISC",
Expand All @@ -20,12 +20,12 @@
"lint:fix": "eslint . --fix"
},
"dependencies": {
"@onekeyfe/hd-core": "1.2.0-alpha.162",
"@onekeyfe/hd-shared": "1.2.0-alpha.162",
"@onekeyfe/hd-transport-emulator": "1.2.0-alpha.162",
"@onekeyfe/hd-transport-http": "1.2.0-alpha.162",
"@onekeyfe/hd-transport-lowlevel": "1.2.0-alpha.162",
"@onekeyfe/hd-transport-usb": "1.2.0-alpha.162",
"@onekeyfe/hd-transport-web-device": "1.2.0-alpha.162"
"@onekeyfe/hd-core": "1.2.0-alpha.165",
"@onekeyfe/hd-shared": "1.2.0-alpha.165",
"@onekeyfe/hd-transport-emulator": "1.2.0-alpha.165",
"@onekeyfe/hd-transport-http": "1.2.0-alpha.165",
"@onekeyfe/hd-transport-lowlevel": "1.2.0-alpha.165",
"@onekeyfe/hd-transport-usb": "1.2.0-alpha.165",
"@onekeyfe/hd-transport-web-device": "1.2.0-alpha.165"
}
}
8 changes: 4 additions & 4 deletions packages/hd-transport-electron/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@onekeyfe/hd-transport-electron",
"version": "1.2.0-alpha.162",
"version": "1.2.0-alpha.165",
"author": "OneKey",
"homepage": "https://github.com/OneKeyHQ/hardware-js-sdk#readme",
"license": "MIT",
Expand All @@ -25,9 +25,9 @@
"electron-log": ">=4.0.0"
},
"dependencies": {
"@onekeyfe/hd-core": "1.2.0-alpha.162",
"@onekeyfe/hd-shared": "1.2.0-alpha.162",
"@onekeyfe/hd-transport": "1.2.0-alpha.162",
"@onekeyfe/hd-core": "1.2.0-alpha.165",
"@onekeyfe/hd-shared": "1.2.0-alpha.165",
"@onekeyfe/hd-transport": "1.2.0-alpha.165",
"@stoprocent/noble": "2.3.16",
"p-retry": "^4.6.2"
},
Expand Down
Loading
Loading