@onekeyfe/hd-transport-electron 1.2.2-alpha.14 → 1.2.2-alpha.17
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/dist/{index-ef6298f9.js → index-d51c7da6.js} +1 -1
- package/dist/index.d.ts +12 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/{noble-ble-handler-de8d60e9.js → noble-ble-handler-0b455c4f.js} +35 -3
- package/dist/noble-ble-handler.d.ts +8 -2
- package/dist/noble-ble-handler.d.ts.map +1 -1
- package/dist/types/desktop-api.d.ts +11 -0
- package/dist/types/desktop-api.d.ts.map +1 -1
- package/package.json +5 -5
- package/src/__tests__/noble-ble-handler.test.ts +75 -14
- package/src/index.ts +7 -1
- package/src/noble-ble-handler.ts +51 -5
- package/src/types/desktop-api.ts +13 -0
|
@@ -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-
|
|
35
|
+
const { setupNobleBleHandlers } = yield Promise.resolve().then(function () { return require('./noble-ble-handler-0b455c4f.js'); });
|
|
36
36
|
setupNobleBleHandlers(webContents);
|
|
37
37
|
});
|
|
38
38
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -37,6 +37,17 @@ interface Logger {
|
|
|
37
37
|
interface NobleBleWriteOptions {
|
|
38
38
|
pacingDelayMs?: number;
|
|
39
39
|
}
|
|
40
|
+
type NobleBleIpcErrorPayload = {
|
|
41
|
+
name: string;
|
|
42
|
+
message: string;
|
|
43
|
+
errorCode: number;
|
|
44
|
+
params?: unknown;
|
|
45
|
+
};
|
|
46
|
+
type NobleBleIpcErrorResponse = {
|
|
47
|
+
type: 'NobleBleIpcError';
|
|
48
|
+
success: false;
|
|
49
|
+
error: NobleBleIpcErrorPayload;
|
|
50
|
+
};
|
|
40
51
|
interface NobleBleAPI {
|
|
41
52
|
enumerate: () => Promise<{
|
|
42
53
|
id: string;
|
|
@@ -82,4 +93,4 @@ interface DesktopAPI {
|
|
|
82
93
|
|
|
83
94
|
declare function initNobleBleSupport(webContents: WebContents): Promise<void>;
|
|
84
95
|
|
|
85
|
-
export { CharacteristicPair, DesktopAPI, DeviceInfo, Logger, NobleBleAPI, NobleBleWriteOptions, NobleModule, initNobleBleSupport };
|
|
96
|
+
export { CharacteristicPair, DesktopAPI, DeviceInfo, Logger, NobleBleAPI, NobleBleIpcErrorPayload, NobleBleIpcErrorResponse, NobleBleWriteOptions, NobleModule, initNobleBleSupport };
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAE5C,cAAc,SAAS,CAAC;AAGxB,YAAY,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAE5C,cAAc,SAAS,CAAC;AAGxB,YAAY,EACV,UAAU,EACV,WAAW,EACX,uBAAuB,EACvB,wBAAwB,EACxB,oBAAoB,GACrB,MAAM,qBAAqB,CAAC;AAE7B,wBAAsB,mBAAmB,CAAC,WAAW,EAAE,WAAW,iBAGjE"}
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var index = require('./index-
|
|
3
|
+
var index = require('./index-d51c7da6.js');
|
|
4
4
|
var hdShared = require('@onekeyfe/hd-shared');
|
|
5
5
|
var pRetry = require('p-retry');
|
|
6
6
|
|
|
@@ -102,7 +102,8 @@ let noble = null;
|
|
|
102
102
|
let logger = null;
|
|
103
103
|
function createNobleBleConnectionError(error, messagePrefix = '') {
|
|
104
104
|
const errorMessage = error.message;
|
|
105
|
-
|
|
105
|
+
const isInvalidMacOsBond = error.nativeErrorCode === 14 && error.nativeErrorDomain === 'CBErrorDomain';
|
|
106
|
+
if (isInvalidMacOsBond) {
|
|
106
107
|
const nativeErrorMessage = `${messagePrefix}${errorMessage}`;
|
|
107
108
|
return hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleBondInvalid, `${hdShared.HardwareErrorCodeMessage[hdShared.HardwareErrorCode.BleBondInvalid]} (${nativeErrorMessage})`, {
|
|
108
109
|
nativeErrorMessage,
|
|
@@ -110,6 +111,29 @@ function createNobleBleConnectionError(error, messagePrefix = '') {
|
|
|
110
111
|
}
|
|
111
112
|
return hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleConnectedError, `${messagePrefix}${errorMessage}`);
|
|
112
113
|
}
|
|
114
|
+
function createNobleBleIpcErrorResponse(error) {
|
|
115
|
+
const candidate = error;
|
|
116
|
+
const errorCode = typeof (candidate === null || candidate === void 0 ? void 0 : candidate.errorCode) === 'number' ? candidate.errorCode : hdShared.HardwareErrorCode.UnknownError;
|
|
117
|
+
const message = typeof (candidate === null || candidate === void 0 ? void 0 : candidate.message) === 'string' ? candidate.message : String(error !== null && error !== void 0 ? error : 'Unknown error');
|
|
118
|
+
const name = typeof (candidate === null || candidate === void 0 ? void 0 : candidate.name) === 'string' ? candidate.name : 'Error';
|
|
119
|
+
let params;
|
|
120
|
+
if ((candidate === null || candidate === void 0 ? void 0 : candidate.params) !== undefined) {
|
|
121
|
+
try {
|
|
122
|
+
const serializedParams = JSON.stringify(candidate.params);
|
|
123
|
+
params = serializedParams === undefined ? undefined : JSON.parse(serializedParams);
|
|
124
|
+
}
|
|
125
|
+
catch (_a) {
|
|
126
|
+
params = undefined;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
return {
|
|
130
|
+
type: 'NobleBleIpcError',
|
|
131
|
+
success: false,
|
|
132
|
+
error: Object.assign({ name,
|
|
133
|
+
message,
|
|
134
|
+
errorCode }, (params !== undefined ? { params } : {})),
|
|
135
|
+
};
|
|
136
|
+
}
|
|
113
137
|
const bluetoothState = {
|
|
114
138
|
available: false,
|
|
115
139
|
unsupported: false,
|
|
@@ -1351,7 +1375,14 @@ function setupNobleBleHandlers(webContents) {
|
|
|
1351
1375
|
const { ipcMain } = require('electron');
|
|
1352
1376
|
const handle = (channel, listener) => {
|
|
1353
1377
|
ipcMain.removeHandler(channel);
|
|
1354
|
-
ipcMain.handle(channel,
|
|
1378
|
+
ipcMain.handle(channel, (...args) => index.__awaiter(this, void 0, void 0, function* () {
|
|
1379
|
+
try {
|
|
1380
|
+
return yield Promise.resolve(listener(...args));
|
|
1381
|
+
}
|
|
1382
|
+
catch (error) {
|
|
1383
|
+
return createNobleBleIpcErrorResponse(error);
|
|
1384
|
+
}
|
|
1385
|
+
}));
|
|
1355
1386
|
};
|
|
1356
1387
|
safeLog(logger, 'info', 'Setting up Noble BLE IPC handlers');
|
|
1357
1388
|
handle(hdShared.EOneKeyBleMessageKeys.NOBLE_BLE_ENUMERATE, () => index.__awaiter(this, void 0, void 0, function* () {
|
|
@@ -1472,5 +1503,6 @@ function setupNobleBleHandlers(webContents) {
|
|
|
1472
1503
|
}
|
|
1473
1504
|
|
|
1474
1505
|
exports.createNobleBleConnectionError = createNobleBleConnectionError;
|
|
1506
|
+
exports.createNobleBleIpcErrorResponse = createNobleBleIpcErrorResponse;
|
|
1475
1507
|
exports.resolveNobleBleWritePacingDelay = resolveNobleBleWritePacingDelay;
|
|
1476
1508
|
exports.setupNobleBleHandlers = setupNobleBleHandlers;
|
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
import type { WebContents } from 'electron';
|
|
2
|
-
import type { NobleBleWriteOptions } from './types/desktop-api';
|
|
3
|
-
|
|
2
|
+
import type { NobleBleIpcErrorResponse, NobleBleWriteOptions } from './types/desktop-api';
|
|
3
|
+
type NobleBleNativeError = Error & {
|
|
4
|
+
nativeErrorCode?: number;
|
|
5
|
+
nativeErrorDomain?: string;
|
|
6
|
+
};
|
|
7
|
+
export declare function createNobleBleConnectionError(error: NobleBleNativeError, messagePrefix?: string): import("@onekeyfe/hd-shared").HardwareError;
|
|
8
|
+
export declare function createNobleBleIpcErrorResponse(error: unknown): NobleBleIpcErrorResponse;
|
|
4
9
|
export declare function resolveNobleBleWritePacingDelay(options?: NobleBleWriteOptions): number;
|
|
5
10
|
export declare function setupNobleBleHandlers(webContents: WebContents): void;
|
|
11
|
+
export {};
|
|
6
12
|
//# sourceMappingURL=noble-ble-handler.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"noble-ble-handler.d.ts","sourceRoot":"","sources":["../src/noble-ble-handler.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"noble-ble-handler.d.ts","sourceRoot":"","sources":["../src/noble-ble-handler.ts"],"names":[],"mappings":"AAkCA,OAAO,KAAK,EAA+B,WAAW,EAAE,MAAM,UAAU,CAAC;AAEzE,OAAO,KAAK,EAAE,wBAAwB,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAO1F,KAAK,mBAAmB,GAAG,KAAK,GAAG;IACjC,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B,CAAC;AAEF,wBAAgB,6BAA6B,CAAC,KAAK,EAAE,mBAAmB,EAAE,aAAa,SAAK,+CAgB3F;AAED,wBAAgB,8BAA8B,CAAC,KAAK,EAAE,OAAO,GAAG,wBAAwB,CAgCvF;AA+ED,wBAAgB,+BAA+B,CAAC,OAAO,CAAC,EAAE,oBAAoB,UAI7E;AAuuDD,wBAAgB,qBAAqB,CAAC,WAAW,EAAE,WAAW,GAAG,IAAI,CAwMpE"}
|
|
@@ -2,6 +2,17 @@ import type { EBleDisconnectReason } from '@onekeyfe/hd-shared';
|
|
|
2
2
|
export interface NobleBleWriteOptions {
|
|
3
3
|
pacingDelayMs?: number;
|
|
4
4
|
}
|
|
5
|
+
export type NobleBleIpcErrorPayload = {
|
|
6
|
+
name: string;
|
|
7
|
+
message: string;
|
|
8
|
+
errorCode: number;
|
|
9
|
+
params?: unknown;
|
|
10
|
+
};
|
|
11
|
+
export type NobleBleIpcErrorResponse = {
|
|
12
|
+
type: 'NobleBleIpcError';
|
|
13
|
+
success: false;
|
|
14
|
+
error: NobleBleIpcErrorPayload;
|
|
15
|
+
};
|
|
5
16
|
export interface NobleBleAPI {
|
|
6
17
|
enumerate: () => Promise<{
|
|
7
18
|
id: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"desktop-api.d.ts","sourceRoot":"","sources":["../../src/types/desktop-api.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAGhE,MAAM,WAAW,oBAAoB;IACnC,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,WAAW;IAC1B,SAAS,EAAE,MAAM,OAAO,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC,CAAC;IACzD,SAAS,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,GAAG,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC,CAAC;IACxF,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAGzC,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,OAAO,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACjE,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5C,SAAS,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3C,WAAW,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7C,KAAK,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,oBAAoB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACrF,cAAc,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,IAAI,KAAK,MAAM,IAAI,CAAC;IACnF,YAAY,CAAC,EAAE,CAAC,QAAQ,EAAE,CAAC,MAAM,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,KAAK,MAAM,IAAI,CAAC;IAOvF,oBAAoB,EAAE,CACpB,QAAQ,EAAE,CAAC,MAAM,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,oBAAoB,CAAA;KAAE,KAAK,IAAI,KACpF,MAAM,IAAI,CAAC;IAChB,iBAAiB,EAAE,MAAM,OAAO,CAAC;QAC/B,SAAS,EAAE,OAAO,CAAC;QACnB,KAAK,EAAE,MAAM,CAAC;QACd,WAAW,EAAE,OAAO,CAAC;QACrB,WAAW,EAAE,OAAO,CAAC;KACtB,CAAC,CAAC;CACJ;AAGD,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,EAAE,WAAW,CAAC;CACxB"}
|
|
1
|
+
{"version":3,"file":"desktop-api.d.ts","sourceRoot":"","sources":["../../src/types/desktop-api.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAGhE,MAAM,WAAW,oBAAoB;IACnC,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,MAAM,uBAAuB,GAAG;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,wBAAwB,GAAG;IACrC,IAAI,EAAE,kBAAkB,CAAC;IACzB,OAAO,EAAE,KAAK,CAAC;IACf,KAAK,EAAE,uBAAuB,CAAC;CAChC,CAAC;AAEF,MAAM,WAAW,WAAW;IAC1B,SAAS,EAAE,MAAM,OAAO,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC,CAAC;IACzD,SAAS,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,GAAG,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC,CAAC;IACxF,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAGzC,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,OAAO,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACjE,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5C,SAAS,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3C,WAAW,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7C,KAAK,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,oBAAoB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACrF,cAAc,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,IAAI,KAAK,MAAM,IAAI,CAAC;IACnF,YAAY,CAAC,EAAE,CAAC,QAAQ,EAAE,CAAC,MAAM,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,KAAK,MAAM,IAAI,CAAC;IAOvF,oBAAoB,EAAE,CACpB,QAAQ,EAAE,CAAC,MAAM,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,oBAAoB,CAAA;KAAE,KAAK,IAAI,KACpF,MAAM,IAAI,CAAC;IAChB,iBAAiB,EAAE,MAAM,OAAO,CAAC;QAC/B,SAAS,EAAE,OAAO,CAAC;QACnB,KAAK,EAAE,MAAM,CAAC;QACd,WAAW,EAAE,OAAO,CAAC;QACrB,WAAW,EAAE,OAAO,CAAC;KACtB,CAAC,CAAC;CACJ;AAGD,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,EAAE,WAAW,CAAC;CACxB"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@onekeyfe/hd-transport-electron",
|
|
3
|
-
"version": "1.2.2-alpha.
|
|
3
|
+
"version": "1.2.2-alpha.17",
|
|
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.2.2-alpha.
|
|
29
|
-
"@onekeyfe/hd-shared": "1.2.2-alpha.
|
|
30
|
-
"@onekeyfe/hd-transport": "1.2.2-alpha.
|
|
28
|
+
"@onekeyfe/hd-core": "1.2.2-alpha.17",
|
|
29
|
+
"@onekeyfe/hd-shared": "1.2.2-alpha.17",
|
|
30
|
+
"@onekeyfe/hd-transport": "1.2.2-alpha.17",
|
|
31
31
|
"@stoprocent/noble": "2.3.16",
|
|
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": "
|
|
39
|
+
"gitHead": "b6c48b842d1c325dcd5ce42c03a07ee4377002dd"
|
|
40
40
|
}
|
|
@@ -31,37 +31,90 @@ describe('Electron Noble BLE device discovery', () => {
|
|
|
31
31
|
expect(NOBLE_BLE_SUBSCRIBE_TIMEOUT_MS).toBe(10_000);
|
|
32
32
|
});
|
|
33
33
|
|
|
34
|
-
test('maps macOS stale pairing failures without
|
|
34
|
+
test('maps structured macOS stale pairing failures without parsing localized text', async () => {
|
|
35
35
|
const { createNobleBleConnectionError } = await import('../noble-ble-handler');
|
|
36
36
|
|
|
37
37
|
const staleBondError = createNobleBleConnectionError(
|
|
38
|
-
new Error('
|
|
38
|
+
Object.assign(new Error('Peer removed pairing information on the device side'), {
|
|
39
|
+
nativeErrorCode: 14,
|
|
40
|
+
nativeErrorDomain: 'CBErrorDomain',
|
|
41
|
+
})
|
|
39
42
|
);
|
|
40
43
|
expect(staleBondError).toMatchObject({
|
|
41
44
|
errorCode: HardwareErrorCode.BleBondInvalid,
|
|
42
45
|
params: {
|
|
43
|
-
nativeErrorMessage: '
|
|
46
|
+
nativeErrorMessage: 'Peer removed pairing information on the device side',
|
|
44
47
|
},
|
|
45
48
|
});
|
|
46
|
-
expect(staleBondError.message).toContain(
|
|
47
|
-
'CBErrorDomain:14 Peer removed pairing information on the device side'
|
|
48
|
-
);
|
|
49
|
+
expect(staleBondError.message).toContain('Peer removed pairing information on the device side');
|
|
49
50
|
expect(createNobleBleConnectionError(new Error('Encryption is insufficient'))).toMatchObject({
|
|
50
|
-
errorCode: HardwareErrorCode.
|
|
51
|
-
params: {
|
|
52
|
-
nativeErrorMessage: 'Encryption is insufficient',
|
|
53
|
-
},
|
|
51
|
+
errorCode: HardwareErrorCode.BleConnectedError,
|
|
54
52
|
});
|
|
55
53
|
expect(
|
|
56
|
-
createNobleBleConnectionError(
|
|
54
|
+
createNobleBleConnectionError(
|
|
55
|
+
Object.assign(new Error('localized native message'), {
|
|
56
|
+
nativeErrorCode: 14,
|
|
57
|
+
nativeErrorDomain: 'CBATTErrorDomain',
|
|
58
|
+
})
|
|
59
|
+
)
|
|
57
60
|
).toMatchObject({
|
|
58
|
-
errorCode: HardwareErrorCode.
|
|
61
|
+
errorCode: HardwareErrorCode.BleConnectedError,
|
|
59
62
|
});
|
|
60
63
|
expect(createNobleBleConnectionError(new Error('connection failed'))).toMatchObject({
|
|
61
64
|
errorCode: HardwareErrorCode.BleConnectedError,
|
|
62
65
|
});
|
|
63
66
|
});
|
|
64
67
|
|
|
68
|
+
test('serializes HardwareError fields for the Noble IPC boundary', async () => {
|
|
69
|
+
const { createNobleBleIpcErrorResponse } = await import('../noble-ble-handler');
|
|
70
|
+
|
|
71
|
+
expect(
|
|
72
|
+
createNobleBleIpcErrorResponse({
|
|
73
|
+
name: 'HardwareError',
|
|
74
|
+
message: 'Bluetooth pairing information is no longer valid',
|
|
75
|
+
errorCode: HardwareErrorCode.BleBondInvalid,
|
|
76
|
+
params: { nativeErrorMessage: 'native message' },
|
|
77
|
+
})
|
|
78
|
+
).toEqual({
|
|
79
|
+
type: 'NobleBleIpcError',
|
|
80
|
+
success: false,
|
|
81
|
+
error: {
|
|
82
|
+
name: 'HardwareError',
|
|
83
|
+
message: 'Bluetooth pairing information is no longer valid',
|
|
84
|
+
errorCode: HardwareErrorCode.BleBondInvalid,
|
|
85
|
+
params: { nativeErrorMessage: 'native message' },
|
|
86
|
+
},
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
expect(createNobleBleIpcErrorResponse(new Error('untyped failure'))).toEqual({
|
|
90
|
+
type: 'NobleBleIpcError',
|
|
91
|
+
success: false,
|
|
92
|
+
error: {
|
|
93
|
+
name: 'Error',
|
|
94
|
+
message: 'untyped failure',
|
|
95
|
+
errorCode: HardwareErrorCode.UnknownError,
|
|
96
|
+
},
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
const circularParams: { self?: unknown } = {};
|
|
100
|
+
circularParams.self = circularParams;
|
|
101
|
+
expect(
|
|
102
|
+
createNobleBleIpcErrorResponse({
|
|
103
|
+
message: 'failure with unsafe params',
|
|
104
|
+
errorCode: HardwareErrorCode.BleConnectedError,
|
|
105
|
+
params: circularParams,
|
|
106
|
+
})
|
|
107
|
+
).toEqual({
|
|
108
|
+
type: 'NobleBleIpcError',
|
|
109
|
+
success: false,
|
|
110
|
+
error: {
|
|
111
|
+
name: 'Error',
|
|
112
|
+
message: 'failure with unsafe params',
|
|
113
|
+
errorCode: HardwareErrorCode.BleConnectedError,
|
|
114
|
+
},
|
|
115
|
+
});
|
|
116
|
+
});
|
|
117
|
+
|
|
65
118
|
test('keeps safe pacing by default and allows an explicit high-throughput bypass', async () => {
|
|
66
119
|
const { resolveNobleBleWritePacingDelay } = await import('../noble-ble-handler');
|
|
67
120
|
|
|
@@ -207,7 +260,15 @@ describe('Electron Noble BLE device discovery', () => {
|
|
|
207
260
|
expect(peripheral.connect).not.toHaveBeenCalled();
|
|
208
261
|
|
|
209
262
|
stopScanningCallback?.();
|
|
210
|
-
await expect(connectPromise).
|
|
263
|
+
await expect(connectPromise).resolves.toEqual({
|
|
264
|
+
type: 'NobleBleIpcError',
|
|
265
|
+
success: false,
|
|
266
|
+
error: {
|
|
267
|
+
name: 'HardwareError',
|
|
268
|
+
message: 'expected test connection failure',
|
|
269
|
+
errorCode: HardwareErrorCode.BleConnectedError,
|
|
270
|
+
},
|
|
271
|
+
});
|
|
211
272
|
expect(peripheral.connect).toHaveBeenCalledTimes(1);
|
|
212
273
|
});
|
|
213
274
|
|
|
@@ -232,7 +293,7 @@ describe('Electron Noble BLE device discovery', () => {
|
|
|
232
293
|
|
|
233
294
|
peripheral.connect(connectCallback);
|
|
234
295
|
const nativeError = new Error(
|
|
235
|
-
'
|
|
296
|
+
'CBErrorDomain:14 Peer removed pairing information on the device side'
|
|
236
297
|
);
|
|
237
298
|
bindings.emit('disconnect', 'aabbccdd', nativeError);
|
|
238
299
|
|
package/src/index.ts
CHANGED
|
@@ -3,7 +3,13 @@ import type { WebContents } from 'electron';
|
|
|
3
3
|
export * from './types';
|
|
4
4
|
|
|
5
5
|
// Export Desktop API types for other packages to reuse
|
|
6
|
-
export type {
|
|
6
|
+
export type {
|
|
7
|
+
DesktopAPI,
|
|
8
|
+
NobleBleAPI,
|
|
9
|
+
NobleBleIpcErrorPayload,
|
|
10
|
+
NobleBleIpcErrorResponse,
|
|
11
|
+
NobleBleWriteOptions,
|
|
12
|
+
} from './types/desktop-api';
|
|
7
13
|
|
|
8
14
|
export async function initNobleBleSupport(webContents: WebContents) {
|
|
9
15
|
const { setupNobleBleHandlers } = await import('./noble-ble-handler');
|
package/src/noble-ble-handler.ts
CHANGED
|
@@ -16,7 +16,6 @@ import {
|
|
|
16
16
|
ONEKEY_WRITE_CHARACTERISTIC_UUID,
|
|
17
17
|
createKnownBleUuidAliases,
|
|
18
18
|
hasOnekeyCommunicationService,
|
|
19
|
-
isBleStaleBondErrorText,
|
|
20
19
|
isBleStaleBondHardwareError,
|
|
21
20
|
isOnekeyBluetoothDevice,
|
|
22
21
|
isPro2FamilyBleName,
|
|
@@ -35,16 +34,23 @@ import {
|
|
|
35
34
|
|
|
36
35
|
import type { IpcMain, IpcMainInvokeEvent, WebContents } from 'electron';
|
|
37
36
|
import type { Characteristic, Peripheral, Service } from '@stoprocent/noble';
|
|
38
|
-
import type { NobleBleWriteOptions } from './types/desktop-api';
|
|
37
|
+
import type { NobleBleIpcErrorResponse, NobleBleWriteOptions } from './types/desktop-api';
|
|
39
38
|
import type { CharacteristicPair, DeviceInfo, Logger, NobleModule } from './types/noble-extended';
|
|
40
39
|
|
|
41
40
|
// Noble will be dynamically imported to avoid bundling issues
|
|
42
41
|
let noble: NobleModule | null = null;
|
|
43
42
|
let logger: Logger | null = null;
|
|
44
43
|
|
|
45
|
-
|
|
44
|
+
type NobleBleNativeError = Error & {
|
|
45
|
+
nativeErrorCode?: number;
|
|
46
|
+
nativeErrorDomain?: string;
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
export function createNobleBleConnectionError(error: NobleBleNativeError, messagePrefix = '') {
|
|
46
50
|
const errorMessage = error.message;
|
|
47
|
-
|
|
51
|
+
const isInvalidMacOsBond =
|
|
52
|
+
error.nativeErrorCode === 14 && error.nativeErrorDomain === 'CBErrorDomain';
|
|
53
|
+
if (isInvalidMacOsBond) {
|
|
48
54
|
const nativeErrorMessage = `${messagePrefix}${errorMessage}`;
|
|
49
55
|
return ERRORS.TypedError(
|
|
50
56
|
HardwareErrorCode.BleBondInvalid,
|
|
@@ -58,6 +64,40 @@ export function createNobleBleConnectionError(error: Error, messagePrefix = '')
|
|
|
58
64
|
return ERRORS.TypedError(HardwareErrorCode.BleConnectedError, `${messagePrefix}${errorMessage}`);
|
|
59
65
|
}
|
|
60
66
|
|
|
67
|
+
export function createNobleBleIpcErrorResponse(error: unknown): NobleBleIpcErrorResponse {
|
|
68
|
+
const candidate = error as {
|
|
69
|
+
errorCode?: unknown;
|
|
70
|
+
message?: unknown;
|
|
71
|
+
name?: unknown;
|
|
72
|
+
params?: unknown;
|
|
73
|
+
};
|
|
74
|
+
const errorCode =
|
|
75
|
+
typeof candidate?.errorCode === 'number' ? candidate.errorCode : HardwareErrorCode.UnknownError;
|
|
76
|
+
const message =
|
|
77
|
+
typeof candidate?.message === 'string' ? candidate.message : String(error ?? 'Unknown error');
|
|
78
|
+
const name = typeof candidate?.name === 'string' ? candidate.name : 'Error';
|
|
79
|
+
let params: unknown;
|
|
80
|
+
if (candidate?.params !== undefined) {
|
|
81
|
+
try {
|
|
82
|
+
const serializedParams = JSON.stringify(candidate.params);
|
|
83
|
+
params = serializedParams === undefined ? undefined : JSON.parse(serializedParams);
|
|
84
|
+
} catch {
|
|
85
|
+
params = undefined;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
return {
|
|
90
|
+
type: 'NobleBleIpcError',
|
|
91
|
+
success: false,
|
|
92
|
+
error: {
|
|
93
|
+
name,
|
|
94
|
+
message,
|
|
95
|
+
errorCode,
|
|
96
|
+
...(params !== undefined ? { params } : {}),
|
|
97
|
+
},
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
|
|
61
101
|
// Bluetooth state management
|
|
62
102
|
const bluetoothState: {
|
|
63
103
|
available: boolean;
|
|
@@ -1919,7 +1959,13 @@ export function setupNobleBleHandlers(webContents: WebContents): void {
|
|
|
1919
1959
|
// Electron throws on duplicate channels and setup re-runs on soft restart.
|
|
1920
1960
|
const handle: IpcMain['handle'] = (channel, listener) => {
|
|
1921
1961
|
ipcMain.removeHandler(channel);
|
|
1922
|
-
ipcMain.handle(channel,
|
|
1962
|
+
ipcMain.handle(channel, async (...args) => {
|
|
1963
|
+
try {
|
|
1964
|
+
return await Promise.resolve(listener(...args));
|
|
1965
|
+
} catch (error) {
|
|
1966
|
+
return createNobleBleIpcErrorResponse(error);
|
|
1967
|
+
}
|
|
1968
|
+
});
|
|
1923
1969
|
};
|
|
1924
1970
|
|
|
1925
1971
|
safeLog(logger, 'info', 'Setting up Noble BLE IPC handlers');
|
package/src/types/desktop-api.ts
CHANGED
|
@@ -10,6 +10,19 @@ export interface NobleBleWriteOptions {
|
|
|
10
10
|
pacingDelayMs?: number;
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
+
export type NobleBleIpcErrorPayload = {
|
|
14
|
+
name: string;
|
|
15
|
+
message: string;
|
|
16
|
+
errorCode: number;
|
|
17
|
+
params?: unknown;
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export type NobleBleIpcErrorResponse = {
|
|
21
|
+
type: 'NobleBleIpcError';
|
|
22
|
+
success: false;
|
|
23
|
+
error: NobleBleIpcErrorPayload;
|
|
24
|
+
};
|
|
25
|
+
|
|
13
26
|
export interface NobleBleAPI {
|
|
14
27
|
enumerate: () => Promise<{ id: string; name: string }[]>;
|
|
15
28
|
getDevice: (uuid: string) => Promise<{ id: string; name: string; mtu?: number } | null>;
|