@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 BLE_PACKET_SIZE = 192;
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
- for (let offset = 0; offset < buffer.length; offset += BLE_PACKET_SIZE) {
373
- const chunk = buffer.subarray(offset, Math.min(offset + BLE_PACKET_SIZE, buffer.length));
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.6",
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.6",
35
- "@onekeyfe/hd-core": "1.2.2-alpha.6",
36
- "@onekeyfe/hd-shared": "1.2.2-alpha.6",
37
- "@onekeyfe/hd-transport-usb": "1.2.2-alpha.6",
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": "538d5371d9369747beabf68c5dc7a617531bace2"
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 BLE_PACKET_SIZE = 192;
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
- for (let offset = 0; offset < buffer.length; offset += BLE_PACKET_SIZE) {
494
- const chunk = buffer.subarray(offset, Math.min(offset + BLE_PACKET_SIZE, buffer.length));
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
  },