@onekeyfe/hd-transport-react-native 1.2.2-alpha.110 → 1.2.2-alpha.111

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 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -529,11 +529,20 @@ class ReactNativeBleTransport {
529
529
  },
530
530
  classifyError: () => 'link-fatal',
531
531
  onLinkInvalidated: (uuid, reason) => __awaiter(this, void 0, void 0, function* () {
532
- var _b;
532
+ var _b, _c;
533
533
  (_b = this.protocolV2Assemblers.get(uuid)) === null || _b === void 0 ? void 0 : _b.reset();
534
534
  this.rejectProtocolV2Frames(uuid, new Error(reason));
535
535
  Log === null || Log === void 0 ? void 0 : Log.debug('[ReactNativeBleTransport] Protocol V2 link invalidated:', uuid, reason);
536
536
  if (reason.startsWith('Protocol V2 link-fatal error:')) {
537
+ if (this.probingProtocols.get(uuid) !== 'V2') {
538
+ const transport = transportCache[uuid];
539
+ try {
540
+ this.emitDeviceDisconnect(uuid, (_c = transport === null || transport === void 0 ? void 0 : transport.device) === null || _c === void 0 ? void 0 : _c.name, transport === null || transport === void 0 ? void 0 : transport.monitorToken);
541
+ }
542
+ catch (_d) {
543
+ Log === null || Log === void 0 ? void 0 : Log.error('[ReactNativeBleTransport] Protocol V2 disconnect listener failed');
544
+ }
545
+ }
537
546
  yield this.releaseNative(uuid, true);
538
547
  }
539
548
  }),
@@ -1195,12 +1204,7 @@ class ReactNativeBleTransport {
1195
1204
  return { uuid, protocolType };
1196
1205
  }
1197
1206
  catch (error) {
1198
- if (hdShared.isBleStaleBondHardwareError(error) || shouldRethrowProtocolProbeError(error)) {
1199
- yield this.disconnectUnlocked(uuid);
1200
- }
1201
- else {
1202
- yield this.releaseUnlocked(uuid, true);
1203
- }
1207
+ yield this.disconnectUnlocked(uuid);
1204
1208
  throw error;
1205
1209
  }
1206
1210
  finally {
@@ -2378,6 +2382,7 @@ class ReactNativeBleTransport {
2378
2382
  if (!this._messages || !this._messagesV2) {
2379
2383
  throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.TransportNotConfigured);
2380
2384
  }
2385
+ const isProtocolProbe = this.probingProtocols.get(uuid) === 'V2';
2381
2386
  const callOptions = options;
2382
2387
  const highThroughputWrite = transport.isProtocolV2HighThroughputCall(name);
2383
2388
  if (highThroughputWrite) {
@@ -2418,6 +2423,14 @@ class ReactNativeBleTransport {
2418
2423
  }
2419
2424
  catch (e) {
2420
2425
  Log === null || Log === void 0 ? void 0 : Log.error('[ReactNativeBleTransport] Protocol V2 call error:', e);
2426
+ if (!isProtocolProbe &&
2427
+ (e === null || e === void 0 ? void 0 : e.errorCode) === hdShared.HardwareErrorCode.BleTimeoutError &&
2428
+ !this.monitorTokens.has(uuid)) {
2429
+ yield this.runLifecycleOperation(uuid, () => __awaiter(this, void 0, void 0, function* () {
2430
+ if (!this.monitorTokens.has(uuid))
2431
+ yield this.disconnectUnlocked(uuid);
2432
+ }));
2433
+ }
2421
2434
  throw e;
2422
2435
  }
2423
2436
  finally {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@onekeyfe/hd-transport-react-native",
3
- "version": "1.2.2-alpha.110",
3
+ "version": "1.2.2-alpha.111",
4
4
  "homepage": "https://github.com/OneKeyHQ/hardware-js-sdk#readme",
5
5
  "license": "MIT",
6
6
  "main": "dist/index.js",
@@ -20,11 +20,11 @@
20
20
  "lint:fix": "eslint . --fix"
21
21
  },
22
22
  "dependencies": {
23
- "@onekeyfe/hd-core": "1.2.2-alpha.110",
24
- "@onekeyfe/hd-shared": "1.2.2-alpha.110",
25
- "@onekeyfe/hd-transport": "1.2.2-alpha.110",
23
+ "@onekeyfe/hd-core": "1.2.2-alpha.111",
24
+ "@onekeyfe/hd-shared": "1.2.2-alpha.111",
25
+ "@onekeyfe/hd-transport": "1.2.2-alpha.111",
26
26
  "@onekeyfe/react-native-ble-utils": "0.1.6",
27
27
  "react-native-ble-plx": "3.5.1"
28
28
  },
29
- "gitHead": "80a959fb1e9383ce948b911fddece1265b40051f"
29
+ "gitHead": "a87be5a4ae4b59f91f853a9873a9e8e924bbdfd6"
30
30
  }
@@ -714,7 +714,72 @@ describe('ReactNativeBleTransport Protocol V2 link lifecycle', () => {
714
714
  });
715
715
 
716
716
  test.each(['ios', 'android'] as const)(
717
- 'keeps a first expected Protocol V2 probe miss retryable on %s',
717
+ 'waits for native disconnect after failed protocol detection before reconnecting on %s',
718
+ async platform => {
719
+ setPlatformOS(platform);
720
+ const { transport, uuid, device, bleManager } = createHarness();
721
+ const probes = transport as unknown as {
722
+ probeProtocolV1(uuid: string): Promise<boolean>;
723
+ probeProtocolV2(uuid: string): Promise<boolean>;
724
+ releaseNative(uuid: string, onclose: boolean): Promise<void>;
725
+ };
726
+ jest.spyOn(probes, 'probeProtocolV1').mockResolvedValueOnce(false);
727
+ const probesFinished = createDeferred<void>();
728
+ const probeProtocolV2 = jest
729
+ .spyOn(probes, 'probeProtocolV2')
730
+ .mockImplementationOnce(async () => {
731
+ // A link-fatal V2 timeout removes the cached transport before acquire fails.
732
+ await probes.releaseNative(uuid, true);
733
+ probesFinished.resolve();
734
+ return false;
735
+ });
736
+ let connected = true;
737
+ device.isConnected.mockImplementation(() => Promise.resolve(connected));
738
+ device.connect = jest.fn(() => {
739
+ connected = true;
740
+ return Promise.resolve(device);
741
+ });
742
+ const disconnectGate = createDeferred<void>();
743
+ bleManager.cancelDeviceConnection.mockImplementation(async () => {
744
+ await disconnectGate.promise;
745
+ connected = false;
746
+ });
747
+
748
+ const acquiring = transport.acquire({ uuid });
749
+ const failure = expect(acquiring).rejects.toMatchObject({
750
+ errorCode: HardwareErrorCode.BleTimeoutError,
751
+ });
752
+ const reconnecting = transport.acquire({ uuid, expectedProtocol: 'V2' });
753
+
754
+ try {
755
+ await probesFinished.promise;
756
+ await new Promise(resolve => {
757
+ setImmediate(resolve);
758
+ });
759
+ expect(bleManager.cancelDeviceConnection).toHaveBeenCalledWith(uuid);
760
+ expect(device.connect).not.toHaveBeenCalled();
761
+ expect(probeProtocolV2).toHaveBeenCalledTimes(1);
762
+
763
+ disconnectGate.resolve();
764
+ await failure;
765
+ await expect(reconnecting).resolves.toEqual({ uuid, protocolType: 'V2' });
766
+ expect(device.connect).toHaveBeenCalledTimes(1);
767
+ await expect(
768
+ transport.call(uuid, 'Ping', { message: 'after-reconnect' })
769
+ ).resolves.toMatchObject({
770
+ type: 'Success',
771
+ message: { message: 'ok' },
772
+ });
773
+ } finally {
774
+ disconnectGate.resolve();
775
+ await Promise.allSettled([failure, reconnecting]);
776
+ await transport.release(uuid, true);
777
+ }
778
+ }
779
+ );
780
+
781
+ test.each(['ios', 'android'] as const)(
782
+ 'disconnects after a first expected Protocol V2 probe miss while keeping it retryable on %s',
718
783
  async platform => {
719
784
  setPlatformOS(platform);
720
785
  const { transport, uuid, device } = createHarness();
@@ -724,13 +789,13 @@ describe('ReactNativeBleTransport Protocol V2 link lifecycle', () => {
724
789
  errorCode: HardwareErrorCode.RuntimeError,
725
790
  });
726
791
 
727
- expect(device.cancelConnection).not.toHaveBeenCalled();
792
+ expect(device.cancelConnection).toHaveBeenCalledTimes(1);
728
793
  expect(transport.getProtocolType(uuid)).toBeUndefined();
729
794
  }
730
795
  );
731
796
 
732
797
  test.each(['ios', 'android'] as const)(
733
- 'keeps a second expected Protocol V2 probe miss retryable on %s',
798
+ 'disconnects after each expected Protocol V2 probe miss while keeping it retryable on %s',
734
799
  async platform => {
735
800
  setPlatformOS(platform);
736
801
  const { transport, uuid, device } = createHarness();
@@ -743,7 +808,7 @@ describe('ReactNativeBleTransport Protocol V2 link lifecycle', () => {
743
808
  errorCode: HardwareErrorCode.RuntimeError,
744
809
  });
745
810
 
746
- expect(device.cancelConnection).not.toHaveBeenCalled();
811
+ expect(device.cancelConnection).toHaveBeenCalledTimes(2);
747
812
  expect(transport.getProtocolType(uuid)).toBeUndefined();
748
813
  }
749
814
  );
@@ -778,7 +843,7 @@ describe('ReactNativeBleTransport Protocol V2 link lifecycle', () => {
778
843
  );
779
844
 
780
845
  test.each(['ios', 'android'] as const)(
781
- 'keeps a confirmed Protocol V2 probe miss retryable on %s without native bond evidence',
846
+ 'disconnects after a confirmed Protocol V2 probe miss on %s without reporting a bond error',
782
847
  async platform => {
783
848
  setPlatformOS(platform);
784
849
  const { transport, uuid, device } = createHarness();
@@ -790,7 +855,7 @@ describe('ReactNativeBleTransport Protocol V2 link lifecycle', () => {
790
855
  errorCode: HardwareErrorCode.RuntimeError,
791
856
  });
792
857
 
793
- expect(device.cancelConnection).not.toHaveBeenCalled();
858
+ expect(device.cancelConnection).toHaveBeenCalledTimes(1);
794
859
  expect(transport.getProtocolType(uuid)).toBeUndefined();
795
860
  }
796
861
  );
@@ -974,7 +1039,7 @@ describe('ReactNativeBleTransport Protocol V2 link lifecycle', () => {
974
1039
  test.each(['V1', 'V2'] as const)(
975
1040
  'still falls back after a silent %s probe timeout',
976
1041
  async protocol => {
977
- const { transport, uuid } = createHarness();
1042
+ const { transport, uuid, device, bleManager } = createHarness();
978
1043
  jest
979
1044
  .spyOn(transport as any, protocol === 'V1' ? 'callProtocolV1' : 'callProtocolV2')
980
1045
  .mockRejectedValue(ERRORS.TypedError(HardwareErrorCode.BleTimeoutError));
@@ -988,6 +1053,8 @@ describe('ReactNativeBleTransport Protocol V2 link lifecycle', () => {
988
1053
  });
989
1054
 
990
1055
  expect(otherProbe).toHaveBeenCalledTimes(1);
1056
+ expect(bleManager.cancelDeviceConnection).not.toHaveBeenCalled();
1057
+ expect(device.cancelConnection).not.toHaveBeenCalled();
991
1058
  await transport.release(uuid, true);
992
1059
  }
993
1060
  );
@@ -1173,6 +1240,7 @@ describe('ReactNativeBleTransport Protocol V2 link lifecycle', () => {
1173
1240
  expect(notifySubscriptionRemovers[0]).toHaveBeenCalledTimes(1);
1174
1241
  expect(notifySubscriptionRemovers[1]).toHaveBeenCalledTimes(1);
1175
1242
  expect(bleManager.cancelTransaction).toHaveBeenCalled();
1243
+ expect(device.cancelConnection).toHaveBeenCalledTimes(1);
1176
1244
  expect(transport.getProtocolType(uuid)).toBeUndefined();
1177
1245
  });
1178
1246
 
@@ -1227,6 +1295,115 @@ describe('ReactNativeBleTransport Protocol V2 link lifecycle', () => {
1227
1295
  });
1228
1296
  });
1229
1297
 
1298
+ test.each(['ios', 'android'] as const)(
1299
+ 'disconnects after an active V2 timeout and reconnects even if a listener fails on %s',
1300
+ async platform => {
1301
+ setPlatformOS(platform);
1302
+ const harness = createHarness();
1303
+ const { transport, uuid, device, bleManager, sentSeqs, emitter } = harness;
1304
+ const disconnected = jest.fn(() => {
1305
+ throw new Error('Disconnect listener failed');
1306
+ });
1307
+ emitter.on(TRANSPORT_EVENT.DEVICE_DISCONNECT, disconnected);
1308
+ let connected = true;
1309
+ device.isConnected.mockImplementation(() => Promise.resolve(connected));
1310
+ device.connect = jest.fn(() => {
1311
+ connected = true;
1312
+ return Promise.resolve(device);
1313
+ });
1314
+ bleManager.cancelDeviceConnection.mockImplementation(() => {
1315
+ connected = false;
1316
+ return Promise.resolve();
1317
+ });
1318
+
1319
+ await transport.acquire({ uuid, expectedProtocol: 'V2' });
1320
+ harness.setShouldRespond(false);
1321
+ await expect(transport.call(uuid, 'Ping', {}, { timeoutMs: 10 })).rejects.toMatchObject({
1322
+ errorCode: HardwareErrorCode.BleTimeoutError,
1323
+ });
1324
+
1325
+ expect(bleManager.cancelDeviceConnection).toHaveBeenCalledWith(uuid);
1326
+ expect(connected).toBe(false);
1327
+ expect(transport.getProtocolType(uuid)).toBeUndefined();
1328
+ expect(disconnected).toHaveBeenCalledTimes(1);
1329
+ expect(disconnected).toHaveBeenCalledWith({
1330
+ id: uuid,
1331
+ connectId: uuid,
1332
+ name: device.name,
1333
+ });
1334
+
1335
+ harness.setShouldRespond(true);
1336
+ await transport.acquire({ uuid, expectedProtocol: 'V2' });
1337
+ await expect(transport.call(uuid, 'Ping', {})).resolves.toMatchObject({ type: 'Success' });
1338
+ expect(device.connect).toHaveBeenCalledTimes(1);
1339
+ expect(sentSeqs).toEqual([1, 2, 3, 4]);
1340
+ await transport.release(uuid, true);
1341
+ }
1342
+ );
1343
+
1344
+ test('does not disconnect an active Protocol V2 call when a queued call times out', async () => {
1345
+ const harness = createHarness();
1346
+ const { transport, uuid, bleManager } = harness;
1347
+ await transport.acquire({ uuid, expectedProtocol: 'V2' });
1348
+ harness.setShouldRespond(false);
1349
+ const active = transport.call(uuid, 'Ping', {}, { timeoutMs: 1000 }).catch(error => error);
1350
+ await new Promise(resolve => {
1351
+ setImmediate(resolve);
1352
+ });
1353
+
1354
+ try {
1355
+ await expect(transport.call(uuid, 'Ping', {}, { timeoutMs: 10 })).rejects.toMatchObject({
1356
+ errorCode: HardwareErrorCode.BleTimeoutError,
1357
+ });
1358
+ expect(bleManager.cancelDeviceConnection).not.toHaveBeenCalled();
1359
+ expect(transport.getProtocolType(uuid)).toBe('V2');
1360
+ } finally {
1361
+ await transport.disconnect(uuid);
1362
+ await active;
1363
+ }
1364
+ });
1365
+
1366
+ test('does not disconnect a newer acquire when V2 timeout cleanup waits for the lifecycle lock', async () => {
1367
+ const harness = createHarness();
1368
+ const { transport, uuid, bleManager } = harness;
1369
+ await transport.acquire({ uuid, expectedProtocol: 'V2' });
1370
+ const lifecycle = transport as unknown as {
1371
+ runLifecycleOperation(id: string, operation: () => Promise<void>): Promise<void>;
1372
+ releaseNative(id: string, onclose: boolean): Promise<boolean>;
1373
+ };
1374
+ const gate = createDeferred<void>();
1375
+ const holding = lifecycle.runLifecycleOperation(uuid, () => gate.promise);
1376
+ const reacquiring = transport.acquire({ uuid, expectedProtocol: 'V2' });
1377
+ const invalidated = createDeferred<void>();
1378
+ const releaseNative = lifecycle.releaseNative.bind(lifecycle);
1379
+ jest.spyOn(lifecycle, 'releaseNative').mockImplementationOnce(async (id, onclose) => {
1380
+ const result = await releaseNative(id, onclose);
1381
+ invalidated.resolve();
1382
+ return result;
1383
+ });
1384
+ harness.setShouldRespond(false);
1385
+ const failure = expect(
1386
+ transport.call(uuid, 'Ping', {}, { timeoutMs: 10 })
1387
+ ).rejects.toMatchObject({
1388
+ errorCode: HardwareErrorCode.BleTimeoutError,
1389
+ });
1390
+
1391
+ try {
1392
+ await invalidated.promise;
1393
+ harness.setShouldRespond(true);
1394
+ gate.resolve();
1395
+ await holding;
1396
+ await reacquiring;
1397
+ await failure;
1398
+ expect(bleManager.cancelDeviceConnection).not.toHaveBeenCalled();
1399
+ await expect(transport.call(uuid, 'Ping', {})).resolves.toMatchObject({ type: 'Success' });
1400
+ } finally {
1401
+ gate.resolve();
1402
+ await Promise.allSettled([holding, reacquiring, failure]);
1403
+ await transport.release(uuid, true);
1404
+ }
1405
+ });
1406
+
1230
1407
  test('retains the sequence cursor when a new monitor generation is acquired', async () => {
1231
1408
  const { transport, uuid, sentSeqs } = createHarness();
1232
1409
 
package/src/index.ts CHANGED
@@ -452,6 +452,14 @@ export default class ReactNativeBleTransport {
452
452
  this.rejectProtocolV2Frames(uuid, new Error(reason));
453
453
  Log?.debug('[ReactNativeBleTransport] Protocol V2 link invalidated:', uuid, reason);
454
454
  if (reason.startsWith('Protocol V2 link-fatal error:')) {
455
+ if (this.probingProtocols.get(uuid) !== 'V2') {
456
+ const transport = transportCache[uuid];
457
+ try {
458
+ this.emitDeviceDisconnect(uuid, transport?.device?.name, transport?.monitorToken);
459
+ } catch {
460
+ Log?.error('[ReactNativeBleTransport] Protocol V2 disconnect listener failed');
461
+ }
462
+ }
455
463
  await this.releaseNative(uuid, true);
456
464
  }
457
465
  },
@@ -1255,11 +1263,9 @@ export default class ReactNativeBleTransport {
1255
1263
  this.attachDisconnectSubscription(currentTransport, currentTransport.device, uuid);
1256
1264
  return { uuid, protocolType };
1257
1265
  } catch (error) {
1258
- if (isBleStaleBondHardwareError(error) || shouldRethrowProtocolProbeError(error)) {
1259
- await this.disconnectUnlocked(uuid);
1260
- } else {
1261
- await this.releaseUnlocked(uuid, true);
1262
- }
1266
+ // A failed acquire must retire the physical link before Core retries. Logical
1267
+ // release leaves GATT connected even when neither protocol receives a response.
1268
+ await this.disconnectUnlocked(uuid);
1263
1269
  throw error;
1264
1270
  } finally {
1265
1271
  this.acquiringProtocolV2.delete(uuid);
@@ -2738,6 +2744,7 @@ export default class ReactNativeBleTransport {
2738
2744
  throw ERRORS.TypedError(HardwareErrorCode.TransportNotConfigured);
2739
2745
  }
2740
2746
 
2747
+ const isProtocolProbe = this.probingProtocols.get(uuid) === 'V2';
2741
2748
  const callOptions = options;
2742
2749
  const highThroughputWrite = isProtocolV2HighThroughputCall(name);
2743
2750
 
@@ -2789,6 +2796,19 @@ export default class ReactNativeBleTransport {
2789
2796
  );
2790
2797
  } catch (e) {
2791
2798
  Log?.error('[ReactNativeBleTransport] Protocol V2 call error:', e);
2799
+ if (
2800
+ !isProtocolProbe &&
2801
+ e?.errorCode === HardwareErrorCode.BleTimeoutError &&
2802
+ !this.monitorTokens.has(uuid)
2803
+ ) {
2804
+ // The failed link has finished invalidating. Disconnect outside that
2805
+ // callback to avoid waiting on its own invalidation or acquire lock.
2806
+ await this.runLifecycleOperation(uuid, async () => {
2807
+ // A queued timeout leaves its active monitor intact; a newer acquire
2808
+ // may also have installed one while cleanup waited for the lifecycle lock.
2809
+ if (!this.monitorTokens.has(uuid)) await this.disconnectUnlocked(uuid);
2810
+ });
2811
+ }
2792
2812
  throw e;
2793
2813
  } finally {
2794
2814
  if (highThroughputWrite) {