@onekeyfe/hardware-cli 1.2.2-alpha.6 → 1.2.2-alpha.8
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,2 +1,4 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
1
2
|
import type { LowlevelTransportSharedPlugin } from '@onekeyfe/hd-transport';
|
|
3
|
+
export declare function resolveNobleProtocolV2PacketCapacity(mtu: number | null | undefined, platform?: NodeJS.Platform): number;
|
|
2
4
|
export declare function createNobleBlePlugin(): LowlevelTransportSharedPlugin;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.createNobleBlePlugin = void 0;
|
|
3
|
+
exports.createNobleBlePlugin = exports.resolveNobleProtocolV2PacketCapacity = void 0;
|
|
4
4
|
const hd_shared_1 = require("@onekeyfe/hd-shared");
|
|
5
5
|
const ONEKEY_SERVICE_UUIDS = [hd_shared_1.ONEKEY_SERVICE_UUID];
|
|
6
6
|
const ONEKEY_SERVICE_UUID_ALIASES = (0, hd_shared_1.createKnownBleUuidAliases)(hd_shared_1.ONEKEY_SERVICE_UUID);
|
|
@@ -11,8 +11,22 @@ const DEVICE_SCAN_TIMEOUT = 8000;
|
|
|
11
11
|
const CONNECTION_TIMEOUT = 8000;
|
|
12
12
|
const SERVICE_DISCOVERY_TIMEOUT = 10000;
|
|
13
13
|
const BLE_CLEANUP_TIMEOUT = 100;
|
|
14
|
-
const
|
|
14
|
+
const BLE_PACKET_SIZE_FALLBACK = 192;
|
|
15
|
+
const BLE_PACKET_SIZE_MAX = 244;
|
|
16
|
+
const ATT_WRITE_HEADER_SIZE = 3;
|
|
15
17
|
const BLE_ENCRYPTION_ERROR_PATTERNS = [/encryption is insufficient/i, /insufficient encryption/i];
|
|
18
|
+
function resolveNobleProtocolV2PacketCapacity(mtu, platform = process.platform) {
|
|
19
|
+
if (typeof mtu !== 'number' || !Number.isFinite(mtu) || mtu <= 0) {
|
|
20
|
+
return BLE_PACKET_SIZE_FALLBACK;
|
|
21
|
+
}
|
|
22
|
+
const reportedCapacity = Math.floor(mtu);
|
|
23
|
+
const payloadCapacity = platform === 'linux' ? reportedCapacity - ATT_WRITE_HEADER_SIZE : reportedCapacity;
|
|
24
|
+
if (payloadCapacity <= 0) {
|
|
25
|
+
return BLE_PACKET_SIZE_FALLBACK;
|
|
26
|
+
}
|
|
27
|
+
return Math.min(payloadCapacity, BLE_PACKET_SIZE_MAX);
|
|
28
|
+
}
|
|
29
|
+
exports.resolveNobleProtocolV2PacketCapacity = resolveNobleProtocolV2PacketCapacity;
|
|
16
30
|
let noble = null;
|
|
17
31
|
let nobleReadyPromise = null;
|
|
18
32
|
const discoveredDevices = new Map();
|
|
@@ -362,6 +376,9 @@ function createNobleBlePlugin() {
|
|
|
362
376
|
async disconnect(uuid) {
|
|
363
377
|
await disconnectDevice(uuid);
|
|
364
378
|
},
|
|
379
|
+
getProtocolV2PacketCapacity(uuid) {
|
|
380
|
+
return resolveNobleProtocolV2PacketCapacity(connectedDevices.get(uuid)?.mtu);
|
|
381
|
+
},
|
|
365
382
|
async send(uuid, data, options) {
|
|
366
383
|
const characteristics = deviceCharacteristics.get(uuid);
|
|
367
384
|
if (!characteristics) {
|
|
@@ -369,8 +386,9 @@ function createNobleBlePlugin() {
|
|
|
369
386
|
}
|
|
370
387
|
const buffer = Buffer.from(data, 'hex');
|
|
371
388
|
const withoutResponse = options?.withoutResponse ?? true;
|
|
372
|
-
|
|
373
|
-
|
|
389
|
+
const packetCapacity = resolveNobleProtocolV2PacketCapacity(connectedDevices.get(uuid)?.mtu);
|
|
390
|
+
for (let offset = 0; offset < buffer.length; offset += packetCapacity) {
|
|
391
|
+
const chunk = buffer.subarray(offset, Math.min(offset + packetCapacity, buffer.length));
|
|
374
392
|
await writeCharacteristic(characteristics.write, chunk, withoutResponse);
|
|
375
393
|
}
|
|
376
394
|
},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@onekeyfe/hardware-cli",
|
|
3
|
-
"version": "1.2.2-alpha.
|
|
3
|
+
"version": "1.2.2-alpha.8",
|
|
4
4
|
"description": "OneKey hardware wallet CLI for testing device communication",
|
|
5
5
|
"author": "OneKey",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -31,12 +31,12 @@
|
|
|
31
31
|
"test": "jest"
|
|
32
32
|
},
|
|
33
33
|
"dependencies": {
|
|
34
|
-
"@onekeyfe/hd-common-connect-sdk": "1.2.2-alpha.
|
|
35
|
-
"@onekeyfe/hd-core": "1.2.2-alpha.
|
|
36
|
-
"@onekeyfe/hd-shared": "1.2.2-alpha.
|
|
37
|
-
"@onekeyfe/hd-transport-usb": "1.2.2-alpha.
|
|
34
|
+
"@onekeyfe/hd-common-connect-sdk": "1.2.2-alpha.8",
|
|
35
|
+
"@onekeyfe/hd-core": "1.2.2-alpha.8",
|
|
36
|
+
"@onekeyfe/hd-shared": "1.2.2-alpha.8",
|
|
37
|
+
"@onekeyfe/hd-transport-usb": "1.2.2-alpha.8",
|
|
38
38
|
"@stoprocent/noble": "2.3.16",
|
|
39
39
|
"commander": "^12.0.0"
|
|
40
40
|
},
|
|
41
|
-
"gitHead": "
|
|
41
|
+
"gitHead": "7a5d129ea1db0b3eb230e309ab29ed3e9e7f141e"
|
|
42
42
|
}
|
|
@@ -31,6 +31,7 @@ const createPeripheral = (id: string) => {
|
|
|
31
31
|
const peripheral = Object.assign(new EventEmitter(), {
|
|
32
32
|
id,
|
|
33
33
|
state: 'connected',
|
|
34
|
+
mtu: null as number | null,
|
|
34
35
|
advertisement: {
|
|
35
36
|
localName: `OneKey Pro 2 ${id}`,
|
|
36
37
|
serviceUuids: ['0001'],
|
|
@@ -54,6 +55,15 @@ describe('Noble BLE plugin notification routing', () => {
|
|
|
54
55
|
jest.clearAllMocks();
|
|
55
56
|
});
|
|
56
57
|
|
|
58
|
+
test('normalizes the platform-specific Noble MTU to a safe write capacity', async () => {
|
|
59
|
+
const { resolveNobleProtocolV2PacketCapacity } = await import('../transports/nobleBlePlugin');
|
|
60
|
+
|
|
61
|
+
expect(resolveNobleProtocolV2PacketCapacity(null, 'darwin')).toBe(192);
|
|
62
|
+
expect(resolveNobleProtocolV2PacketCapacity(244, 'darwin')).toBe(244);
|
|
63
|
+
expect(resolveNobleProtocolV2PacketCapacity(247, 'linux')).toBe(244);
|
|
64
|
+
expect(resolveNobleProtocolV2PacketCapacity(512, 'win32')).toBe(244);
|
|
65
|
+
});
|
|
66
|
+
|
|
57
67
|
test('does not enumerate Find My advertisements that expose FFFD', async () => {
|
|
58
68
|
jest.useFakeTimers({ doNotFake: ['performance'] });
|
|
59
69
|
const oneKey = createPeripheral('onekey-device');
|
|
@@ -376,6 +386,33 @@ describe('Noble BLE plugin notification routing', () => {
|
|
|
376
386
|
expect(wait).not.toHaveBeenCalled();
|
|
377
387
|
});
|
|
378
388
|
|
|
389
|
+
test('uses the connected peripheral write capacity without padding', async () => {
|
|
390
|
+
const device = createPeripheral('device-a');
|
|
391
|
+
device.peripheral.mtu = process.platform === 'linux' ? 247 : 244;
|
|
392
|
+
const noble = new EventEmitter() as EventEmitter & {
|
|
393
|
+
state: string;
|
|
394
|
+
startScanning: jest.Mock;
|
|
395
|
+
stopScanning: jest.Mock;
|
|
396
|
+
};
|
|
397
|
+
noble.state = 'poweredOn';
|
|
398
|
+
noble.startScanning = jest.fn((_services, _duplicates, callback) => {
|
|
399
|
+
callback?.();
|
|
400
|
+
noble.emit('discover', device.peripheral);
|
|
401
|
+
});
|
|
402
|
+
noble.stopScanning = jest.fn(callback => callback?.());
|
|
403
|
+
jest.doMock('@stoprocent/noble', () => noble);
|
|
404
|
+
|
|
405
|
+
const { createNobleBlePlugin } = await import('../transports/nobleBlePlugin');
|
|
406
|
+
const plugin = createNobleBlePlugin();
|
|
407
|
+
await plugin.init();
|
|
408
|
+
await plugin.connect('device-a');
|
|
409
|
+
|
|
410
|
+
await plugin.send('device-a', 'aa'.repeat(245));
|
|
411
|
+
|
|
412
|
+
expect(plugin.getProtocolV2PacketCapacity?.('device-a')).toBe(244);
|
|
413
|
+
expect(device.write.write.mock.calls.map(([packet]) => packet.length)).toEqual([244, 1]);
|
|
414
|
+
});
|
|
415
|
+
|
|
379
416
|
test('preserves a short final BLE packet without padding', async () => {
|
|
380
417
|
const device = createPeripheral('device-a');
|
|
381
418
|
const noble = new EventEmitter() as EventEmitter & {
|
|
@@ -58,9 +58,27 @@ const DEVICE_SCAN_TIMEOUT = 8_000;
|
|
|
58
58
|
const CONNECTION_TIMEOUT = 8_000;
|
|
59
59
|
const SERVICE_DISCOVERY_TIMEOUT = 10_000;
|
|
60
60
|
const BLE_CLEANUP_TIMEOUT = 100;
|
|
61
|
-
const
|
|
61
|
+
const BLE_PACKET_SIZE_FALLBACK = 192;
|
|
62
|
+
const BLE_PACKET_SIZE_MAX = 244;
|
|
63
|
+
const ATT_WRITE_HEADER_SIZE = 3;
|
|
62
64
|
const BLE_ENCRYPTION_ERROR_PATTERNS = [/encryption is insufficient/i, /insufficient encryption/i];
|
|
63
65
|
|
|
66
|
+
export function resolveNobleProtocolV2PacketCapacity(
|
|
67
|
+
mtu: number | null | undefined,
|
|
68
|
+
platform: NodeJS.Platform = process.platform
|
|
69
|
+
) {
|
|
70
|
+
if (typeof mtu !== 'number' || !Number.isFinite(mtu) || mtu <= 0) {
|
|
71
|
+
return BLE_PACKET_SIZE_FALLBACK;
|
|
72
|
+
}
|
|
73
|
+
const reportedCapacity = Math.floor(mtu);
|
|
74
|
+
const payloadCapacity =
|
|
75
|
+
platform === 'linux' ? reportedCapacity - ATT_WRITE_HEADER_SIZE : reportedCapacity;
|
|
76
|
+
if (payloadCapacity <= 0) {
|
|
77
|
+
return BLE_PACKET_SIZE_FALLBACK;
|
|
78
|
+
}
|
|
79
|
+
return Math.min(payloadCapacity, BLE_PACKET_SIZE_MAX);
|
|
80
|
+
}
|
|
81
|
+
|
|
64
82
|
let noble: NobleModule | null = null;
|
|
65
83
|
let nobleReadyPromise: Promise<void> | null = null;
|
|
66
84
|
const discoveredDevices = new Map<string, Peripheral>();
|
|
@@ -479,6 +497,10 @@ export function createNobleBlePlugin(): LowlevelTransportSharedPlugin {
|
|
|
479
497
|
await disconnectDevice(uuid);
|
|
480
498
|
},
|
|
481
499
|
|
|
500
|
+
getProtocolV2PacketCapacity(uuid: string) {
|
|
501
|
+
return resolveNobleProtocolV2PacketCapacity(connectedDevices.get(uuid)?.mtu);
|
|
502
|
+
},
|
|
503
|
+
|
|
482
504
|
async send(uuid: string, data: string, options?: { withoutResponse?: boolean }) {
|
|
483
505
|
const characteristics = deviceCharacteristics.get(uuid);
|
|
484
506
|
if (!characteristics) {
|
|
@@ -490,8 +512,9 @@ export function createNobleBlePlugin(): LowlevelTransportSharedPlugin {
|
|
|
490
512
|
|
|
491
513
|
const buffer = Buffer.from(data, 'hex');
|
|
492
514
|
const withoutResponse = options?.withoutResponse ?? true;
|
|
493
|
-
|
|
494
|
-
|
|
515
|
+
const packetCapacity = resolveNobleProtocolV2PacketCapacity(connectedDevices.get(uuid)?.mtu);
|
|
516
|
+
for (let offset = 0; offset < buffer.length; offset += packetCapacity) {
|
|
517
|
+
const chunk = buffer.subarray(offset, Math.min(offset + packetCapacity, buffer.length));
|
|
495
518
|
await writeCharacteristic(characteristics.write, chunk, withoutResponse);
|
|
496
519
|
}
|
|
497
520
|
},
|