@onekeyfe/hd-transport-web-device 1.2.2-alpha.106 → 1.2.2-alpha.107

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.
@@ -673,7 +673,7 @@ describe('ElectronBleTransport protocol detection', () => {
673
673
  }
674
674
  });
675
675
 
676
- test('reports a stale bond when a previously confirmed Protocol V2 device stops responding', async () => {
676
+ test('keeps a probe miss retryable after a previously confirmed Protocol V2 connection', async () => {
677
677
  const device = { id: 'reset-pro2-id', name: 'OneKey Pro 2' };
678
678
  const nobleBle = createNobleBle(device);
679
679
  const transport = configureTransport(nobleBle);
@@ -686,7 +686,7 @@ describe('ElectronBleTransport protocol detection', () => {
686
686
  await expect(
687
687
  transport.acquire({ uuid: device.id, expectedProtocol: 'V2' })
688
688
  ).rejects.toMatchObject({
689
- errorCode: HardwareErrorCode.BleDeviceBondError,
689
+ errorCode: HardwareErrorCode.RuntimeError,
690
690
  });
691
691
 
692
692
  expect(nobleBle.unsubscribe).toHaveBeenCalledWith(device.id);
@@ -694,6 +694,52 @@ describe('ElectronBleTransport protocol detection', () => {
694
694
  expect(transport.getProtocolType(device.id)).toBeUndefined();
695
695
  });
696
696
 
697
+ test.each([false, true])(
698
+ 'preserves an expected Protocol V2 Ping timeout with a prior successful connection: %s',
699
+ async previouslyConnected => {
700
+ const device = { id: 'timeout-pro2-id', name: 'OneKey Pro 2' };
701
+ const nobleBle = createNobleBle(device);
702
+ const transport = configureTransport(nobleBle);
703
+
704
+ if (previouslyConnected) {
705
+ echoProtocolV2(nobleBle, device.id);
706
+ await transport.acquire({ uuid: device.id, expectedProtocol: 'V2' });
707
+ await transport.release(device.id);
708
+ }
709
+ // Keep the real probe and response timer, but drop its notification.
710
+ nobleBle.write.mockImplementation(() => Promise.resolve());
711
+
712
+ await expect(
713
+ transport.acquire({ uuid: device.id, expectedProtocol: 'V2' })
714
+ ).rejects.toMatchObject({
715
+ errorCode: HardwareErrorCode.BleTimeoutError,
716
+ message: 'BLE response timeout after 5000ms for Ping',
717
+ });
718
+
719
+ expect(nobleBle.unsubscribe).toHaveBeenCalledWith(device.id);
720
+ expect(nobleBle.disconnect).toHaveBeenCalledWith(device.id);
721
+ expect(transport.getProtocolType(device.id)).toBeUndefined();
722
+ }
723
+ );
724
+
725
+ test('preserves a native stale-bond error during an expected Protocol V2 probe', async () => {
726
+ const device = { id: 'stale-bond-probe-id', name: 'OneKey Pro 2' };
727
+ const nobleBle = createNobleBle(device);
728
+ nobleBle.write.mockRejectedValue({
729
+ name: 'HardwareError',
730
+ message: 'Bluetooth pairing information is no longer valid',
731
+ errorCode: HardwareErrorCode.BleBondInvalid,
732
+ });
733
+ const transport = configureTransport(nobleBle);
734
+
735
+ await expect(
736
+ transport.acquire({ uuid: device.id, expectedProtocol: 'V2' })
737
+ ).rejects.toMatchObject({ errorCode: HardwareErrorCode.BleBondInvalid });
738
+
739
+ expect(nobleBle.unsubscribe).toHaveBeenCalledWith(device.id);
740
+ expect(nobleBle.disconnect).toHaveBeenCalledWith(device.id);
741
+ });
742
+
697
743
  test('does not take a Protocol V2 hint from the BLE name', async () => {
698
744
  const device = { id: 'named-pro2-id', name: 'OneKey Pro 2' };
699
745
  const nobleBle = createNobleBle(device);
@@ -27,7 +27,6 @@ export default class ElectronBleTransport {
27
27
  private connectedDevices;
28
28
  private deviceProtocol;
29
29
  private deviceProtocolHints;
30
- private confirmedProtocolV2;
31
30
  private deviceMtus;
32
31
  private devicePacketCapacities;
33
32
  private v1Buffers;
@@ -1 +1 @@
1
- {"version":3,"file":"electron-ble-transport.d.ts","sourceRoot":"","sources":["../src/electron-ble-transport.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"electron-ble-transport.d.ts","sourceRoot":"","sources":["../src/electron-ble-transport.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -218,8 +218,6 @@ declare class ElectronBleTransport {
218
218
  private connectedDevices;
219
219
  private deviceProtocol;
220
220
  private deviceProtocolHints;
221
- /** Endpoints that answered a V2 probe in this transport lifetime. Survives disconnect. */
222
- private confirmedProtocolV2;
223
221
  private deviceMtus;
224
222
  private devicePacketCapacities;
225
223
  private v1Buffers;
package/dist/index.js CHANGED
@@ -850,7 +850,6 @@ class ElectronBleTransport {
850
850
  this.connectedDevices = new Set();
851
851
  this.deviceProtocol = new Map();
852
852
  this.deviceProtocolHints = new Map();
853
- this.confirmedProtocolV2 = new Set();
854
853
  this.deviceMtus = new Map();
855
854
  this.devicePacketCapacities = new Map();
856
855
  this.v1Buffers = new Map();
@@ -1165,9 +1164,8 @@ class ElectronBleTransport {
1165
1164
  }
1166
1165
  });
1167
1166
  }
1168
- createProtocolMismatchError(expected, uuid) {
1169
- const isStaleV2Bond = expected === 'V2' && this.confirmedProtocolV2.has(uuid);
1170
- return hdShared.ERRORS.TypedError(isStaleV2Bond ? hdShared.HardwareErrorCode.BleDeviceBondError : hdShared.HardwareErrorCode.RuntimeError, `Device protocol mismatch: expected ${expected}, but device did not respond to expected protocol`);
1167
+ createProtocolMismatchError(expected) {
1168
+ return hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, `Device protocol mismatch: expected ${expected}, but device did not respond to expected protocol`);
1171
1169
  }
1172
1170
  createProtocolDetectionError() {
1173
1171
  return hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleTimeoutError, 'Unable to detect BLE protocol: device did not respond to Protocol V1 GetFeatures or Protocol V2 Ping');
@@ -1186,13 +1184,12 @@ class ElectronBleTransport {
1186
1184
  return 'V1';
1187
1185
  }
1188
1186
  if (expectedProtocol === 'V2') {
1189
- if (yield this.probeProtocolV2(uuid)) {
1187
+ if (yield this.probeProtocolV2(uuid, expectedProtocol)) {
1190
1188
  this.deviceProtocol.set(uuid, 'V2');
1191
- this.confirmedProtocolV2.add(uuid);
1192
1189
  (_b = this.Log) === null || _b === void 0 ? void 0 : _b.debug(`[Electron BLE] detectProtocol: uuid=${uuid} -> V2 (expected)`);
1193
1190
  return 'V2';
1194
1191
  }
1195
- throw this.createProtocolMismatchError(expectedProtocol, uuid);
1192
+ throw this.createProtocolMismatchError(expectedProtocol);
1196
1193
  }
1197
1194
  const probeOrder = protocolHint === 'V2' || this.deviceProtocol.get(uuid) === 'V2' ? ['V2', 'V1'] : ['V1', 'V2'];
1198
1195
  for (let i = 0; i < probeOrder.length; i += 1) {
@@ -1203,9 +1200,6 @@ class ElectronBleTransport {
1203
1200
  const detected = protocol === 'V1' ? yield this.probeProtocolV1(uuid) : yield this.probeProtocolV2(uuid);
1204
1201
  if (detected) {
1205
1202
  this.deviceProtocol.set(uuid, protocol);
1206
- if (protocol === 'V2') {
1207
- this.confirmedProtocolV2.add(uuid);
1208
- }
1209
1203
  (_c = this.Log) === null || _c === void 0 ? void 0 : _c.debug(`[Electron BLE] detectProtocol: uuid=${uuid} -> ${protocol}`);
1210
1204
  return protocol;
1211
1205
  }
@@ -1268,7 +1262,7 @@ class ElectronBleTransport {
1268
1262
  }
1269
1263
  });
1270
1264
  }
1271
- probeProtocolV2(uuid) {
1265
+ probeProtocolV2(uuid, expectedProtocol) {
1272
1266
  var _a;
1273
1267
  return __awaiter(this, void 0, void 0, function* () {
1274
1268
  if (!this._messages || !this._messagesV2) {
@@ -1286,7 +1280,9 @@ class ElectronBleTransport {
1286
1280
  (_a = this.v2Assemblers.get(uuid)) === null || _a === void 0 ? void 0 : _a.reset();
1287
1281
  this.resetProtocolV2Frames(uuid);
1288
1282
  },
1289
- shouldRethrow: error => hdShared.isBleStaleBondHardwareError(error) || transport.isProtocolV2LinkDisabledError(error),
1283
+ shouldRethrow: error => expectedProtocol === 'V2' ||
1284
+ hdShared.isBleStaleBondHardwareError(error) ||
1285
+ transport.isProtocolV2LinkDisabledError(error),
1290
1286
  });
1291
1287
  if (!detected) {
1292
1288
  this.clearProbeProtocol(uuid, 'V2');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@onekeyfe/hd-transport-web-device",
3
- "version": "1.2.2-alpha.106",
3
+ "version": "1.2.2-alpha.107",
4
4
  "author": "OneKey",
5
5
  "homepage": "https://github.com/OneKeyHQ/hardware-js-sdk#readme",
6
6
  "license": "MIT",
@@ -21,13 +21,13 @@
21
21
  "lint:fix": "eslint . --fix"
22
22
  },
23
23
  "dependencies": {
24
- "@onekeyfe/hd-shared": "1.2.2-alpha.106",
25
- "@onekeyfe/hd-transport": "1.2.2-alpha.106"
24
+ "@onekeyfe/hd-shared": "1.2.2-alpha.107",
25
+ "@onekeyfe/hd-transport": "1.2.2-alpha.107"
26
26
  },
27
27
  "devDependencies": {
28
- "@onekeyfe/hd-transport-electron": "1.2.2-alpha.106",
28
+ "@onekeyfe/hd-transport-electron": "1.2.2-alpha.107",
29
29
  "@types/w3c-web-usb": "^1.0.6",
30
30
  "@types/web-bluetooth": "^0.0.17"
31
31
  },
32
- "gitHead": "e52ad091098aaab6b2845154457ace5e2f8c9098"
32
+ "gitHead": "0139b6e93599824f13f1e7121a70a59ec424f466"
33
33
  }
@@ -121,9 +121,6 @@ export default class ElectronBleTransport {
121
121
 
122
122
  private deviceProtocolHints: Map<string, ProtocolType> = new Map();
123
123
 
124
- /** Endpoints that answered a V2 probe in this transport lifetime. Survives disconnect. */
125
- private confirmedProtocolV2 = new Set<string>();
126
-
127
124
  private deviceMtus: Map<string, number> = new Map();
128
125
 
129
126
  private devicePacketCapacities: Map<string, number> = new Map();
@@ -501,12 +498,9 @@ export default class ElectronBleTransport {
501
498
  }
502
499
  }
503
500
 
504
- private createProtocolMismatchError(expected: ProtocolType, uuid: string) {
505
- // A generic Ping miss is not a bond failure. Only a later miss after this
506
- // endpoint already answered V2, or a native encryption/pairing error, is.
507
- const isStaleV2Bond = expected === 'V2' && this.confirmedProtocolV2.has(uuid);
501
+ private createProtocolMismatchError(expected: ProtocolType) {
508
502
  return ERRORS.TypedError(
509
- isStaleV2Bond ? HardwareErrorCode.BleDeviceBondError : HardwareErrorCode.RuntimeError,
503
+ HardwareErrorCode.RuntimeError,
510
504
  `Device protocol mismatch: expected ${expected}, but device did not respond to expected protocol`
511
505
  );
512
506
  }
@@ -546,13 +540,12 @@ export default class ElectronBleTransport {
546
540
  }
547
541
 
548
542
  if (expectedProtocol === 'V2') {
549
- if (await this.probeProtocolV2(uuid)) {
543
+ if (await this.probeProtocolV2(uuid, expectedProtocol)) {
550
544
  this.deviceProtocol.set(uuid, 'V2');
551
- this.confirmedProtocolV2.add(uuid);
552
545
  this.Log?.debug(`[Electron BLE] detectProtocol: uuid=${uuid} -> V2 (expected)`);
553
546
  return 'V2';
554
547
  }
555
- throw this.createProtocolMismatchError(expectedProtocol, uuid);
548
+ throw this.createProtocolMismatchError(expectedProtocol);
556
549
  }
557
550
 
558
551
  // Protocol must be actively probed after connection. Name, PID, and descriptors only
@@ -571,9 +564,6 @@ export default class ElectronBleTransport {
571
564
  protocol === 'V1' ? await this.probeProtocolV1(uuid) : await this.probeProtocolV2(uuid);
572
565
  if (detected) {
573
566
  this.deviceProtocol.set(uuid, protocol);
574
- if (protocol === 'V2') {
575
- this.confirmedProtocolV2.add(uuid);
576
- }
577
567
  this.Log?.debug(`[Electron BLE] detectProtocol: uuid=${uuid} -> ${protocol}`);
578
568
  return protocol;
579
569
  }
@@ -644,7 +634,7 @@ export default class ElectronBleTransport {
644
634
  }
645
635
  }
646
636
 
647
- private async probeProtocolV2(uuid: string) {
637
+ private async probeProtocolV2(uuid: string, expectedProtocol?: ProtocolType) {
648
638
  if (!this._messages || !this._messagesV2) {
649
639
  return false;
650
640
  }
@@ -660,8 +650,11 @@ export default class ElectronBleTransport {
660
650
  this.v2Assemblers.get(uuid)?.reset();
661
651
  this.resetProtocolV2Frames(uuid);
662
652
  },
653
+ // A declared V2 protocol needs no fallback; preserve the actual link failure.
663
654
  shouldRethrow: error =>
664
- isBleStaleBondHardwareError(error) || isProtocolV2LinkDisabledError(error),
655
+ expectedProtocol === 'V2' ||
656
+ isBleStaleBondHardwareError(error) ||
657
+ isProtocolV2LinkDisabledError(error),
665
658
  });
666
659
  if (!detected) {
667
660
  this.clearProbeProtocol(uuid, 'V2');