@onekeyfe/hd-transport-react-native 1.2.0-alpha.22 → 1.2.0-alpha.24

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.d.ts CHANGED
@@ -55,6 +55,7 @@ declare class ReactNativeBleTransport {
55
55
  blePlxManager: BleManager | undefined;
56
56
  _messages: ReturnType<typeof transport__default.parseConfigure> | undefined;
57
57
  _messagesV2: ReturnType<typeof transport__default.parseConfigure> | undefined;
58
+ private protocolV2SchemaConfiguration;
58
59
  name: string;
59
60
  configured: boolean;
60
61
  stopped: boolean;
@@ -70,6 +71,7 @@ declare class ReactNativeBleTransport {
70
71
  private protocolV2FramePromises;
71
72
  private protocolV2Links;
72
73
  private monitorTokens;
74
+ private disconnectEventTokens;
73
75
  private nextMonitorToken;
74
76
  constructor(options: TransportOptions);
75
77
  init(logger: any, emitter: EventEmitter): void;
@@ -79,6 +81,7 @@ declare class ReactNativeBleTransport {
79
81
  getPlxManager(): Promise<BleManager>;
80
82
  resolveCharacteristics(device: Device): Promise<ResolvedBleCharacteristics>;
81
83
  attachDisconnectSubscription(transport: BleTransport, device: Device, uuid: string): void;
84
+ private emitDeviceDisconnect;
82
85
  reconnectFirmwareUploadTransport(uuid: string, transport: BleTransport): Promise<void>;
83
86
  /**
84
87
  * 获取设备列表
@@ -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
@@ -427,6 +427,7 @@ class ReactNativeBleTransport {
427
427
  }),
428
428
  });
429
429
  this.monitorTokens = new Map();
430
+ this.disconnectEventTokens = new Map();
430
431
  this.nextMonitorToken = 1;
431
432
  this.scanTimeout = (_a = options.scanTimeout) !== null && _a !== void 0 ? _a : DEVICE_SCAN_TIMEOUT_MS;
432
433
  }
@@ -440,10 +441,18 @@ class ReactNativeBleTransport {
440
441
  this._messages = messages;
441
442
  }
442
443
  configureProtocolV2(signedData) {
444
+ const configuration = typeof signedData === 'string' ? signedData : JSON.stringify(signedData);
445
+ if (this.protocolV2SchemaConfiguration === configuration) {
446
+ return;
447
+ }
448
+ const isReconfiguration = this.protocolV2SchemaConfiguration !== undefined;
443
449
  this._messagesV2 = parseConfigure(signedData);
444
- this.protocolV2Links
445
- .invalidateAllLinks('Protocol V2 schema reconfigured')
446
- .catch(error => Log === null || Log === void 0 ? void 0 : Log.debug('Protocol V2 schema link cleanup failed:', error));
450
+ this.protocolV2SchemaConfiguration = configuration;
451
+ if (isReconfiguration) {
452
+ this.protocolV2Links
453
+ .invalidateAllLinks('Protocol V2 schema reconfigured')
454
+ .catch(error => Log === null || Log === void 0 ? void 0 : Log.debug('Protocol V2 schema link cleanup failed:', error));
455
+ }
447
456
  }
448
457
  listen() {
449
458
  }
@@ -536,8 +545,8 @@ class ReactNativeBleTransport {
536
545
  attachDisconnectSubscription(transport, device, uuid) {
537
546
  var _a;
538
547
  (_a = transport.disconnectSubscription) === null || _a === void 0 ? void 0 : _a.remove();
548
+ const { monitorToken } = transport;
539
549
  transport.disconnectSubscription = device.onDisconnected(() => {
540
- var _a;
541
550
  if (this.firmwareUploadWriteRecoveryIds.has(uuid)) {
542
551
  Log === null || Log === void 0 ? void 0 : Log.debug('device disconnect ignored during FirmwareUpload write recovery: ', uuid);
543
552
  return;
@@ -546,13 +555,13 @@ class ReactNativeBleTransport {
546
555
  Log === null || Log === void 0 ? void 0 : Log.debug('device disconnect ignored for stale transport: ', device === null || device === void 0 ? void 0 : device.id);
547
556
  return;
548
557
  }
558
+ if (this.monitorTokens.get(uuid) !== monitorToken) {
559
+ Log === null || Log === void 0 ? void 0 : Log.debug('device disconnect ignored for stale generation: ', device === null || device === void 0 ? void 0 : device.id);
560
+ return;
561
+ }
549
562
  try {
550
563
  Log === null || Log === void 0 ? void 0 : Log.debug('device disconnect: ', device === null || device === void 0 ? void 0 : device.id);
551
- (_a = this.emitter) === null || _a === void 0 ? void 0 : _a.emit('device-disconnect', {
552
- name: device === null || device === void 0 ? void 0 : device.name,
553
- id: device === null || device === void 0 ? void 0 : device.id,
554
- connectId: device === null || device === void 0 ? void 0 : device.id,
555
- });
564
+ this.emitDeviceDisconnect(uuid, device === null || device === void 0 ? void 0 : device.name, monitorToken);
556
565
  if (this.runPromise) {
557
566
  const error = hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleConnectedError);
558
567
  this.runPromise.reject(error);
@@ -567,6 +576,22 @@ class ReactNativeBleTransport {
567
576
  }
568
577
  });
569
578
  }
579
+ emitDeviceDisconnect(uuid, name, token) {
580
+ var _a;
581
+ if (token === undefined || this.disconnectEventTokens.get(uuid) === token) {
582
+ return;
583
+ }
584
+ if (this.monitorTokens.get(uuid) !== token) {
585
+ Log === null || Log === void 0 ? void 0 : Log.debug('device disconnect event ignored for stale generation: ', uuid);
586
+ return;
587
+ }
588
+ this.disconnectEventTokens.set(uuid, token);
589
+ (_a = this.emitter) === null || _a === void 0 ? void 0 : _a.emit(transport.TRANSPORT_EVENT.DEVICE_DISCONNECT, {
590
+ name,
591
+ id: uuid,
592
+ connectId: uuid,
593
+ });
594
+ }
570
595
  reconnectFirmwareUploadTransport(uuid, transport) {
571
596
  var _a, _b;
572
597
  return __awaiter(this, void 0, void 0, function* () {
@@ -712,7 +737,7 @@ class ReactNativeBleTransport {
712
737
  });
713
738
  }
714
739
  acquire(input) {
715
- var _a, _b;
740
+ var _a;
716
741
  return __awaiter(this, void 0, void 0, function* () {
717
742
  const { uuid, forceCleanRunPromise, expectedProtocol } = input;
718
743
  if (!uuid) {
@@ -848,11 +873,6 @@ class ReactNativeBleTransport {
848
873
  yield delay(ANDROID_NOTIFY_READY_DELAY_MS);
849
874
  }
850
875
  const protocolType = yield this.detectProtocol(uuid, expectedProtocol, protocolHint);
851
- (_b = this.emitter) === null || _b === void 0 ? void 0 : _b.emit('device-connect', {
852
- name: device.name,
853
- id: device.id,
854
- connectId: device.id,
855
- });
856
876
  this.attachDisconnectSubscription(transport$1, device, uuid);
857
877
  return { uuid, protocolType };
858
878
  });
@@ -1232,6 +1252,7 @@ class ReactNativeBleTransport {
1232
1252
  return __awaiter(this, void 0, void 0, function* () {
1233
1253
  yield this.protocolV2Links.invalidateLink(session, 'React Native BLE transport disconnected');
1234
1254
  const transport = transportCache[session];
1255
+ const monitorToken = (_a = transport === null || transport === void 0 ? void 0 : transport.monitorToken) !== null && _a !== void 0 ? _a : this.monitorTokens.get(session);
1235
1256
  if (transport === null || transport === void 0 ? void 0 : transport.disconnectSubscription) {
1236
1257
  try {
1237
1258
  Log === null || Log === void 0 ? void 0 : Log.debug('disconnect: removing disconnect subscription');
@@ -1244,7 +1265,7 @@ class ReactNativeBleTransport {
1244
1265
  }
1245
1266
  if (transport === null || transport === void 0 ? void 0 : transport.notifySubscription) {
1246
1267
  try {
1247
- Log === null || Log === void 0 ? void 0 : Log.debug('disconnect: removing notify subscription, characteristic: ', (_a = transport.notifyCharacteristic) === null || _a === void 0 ? void 0 : _a.uuid);
1268
+ Log === null || Log === void 0 ? void 0 : Log.debug('disconnect: removing notify subscription, characteristic: ', (_b = transport.notifyCharacteristic) === null || _b === void 0 ? void 0 : _b.uuid);
1248
1269
  transport.notifySubscription.remove();
1249
1270
  transport.notifySubscription = undefined;
1250
1271
  }
@@ -1254,7 +1275,7 @@ class ReactNativeBleTransport {
1254
1275
  }
1255
1276
  if (session) {
1256
1277
  try {
1257
- yield ((_b = this.blePlxManager) === null || _b === void 0 ? void 0 : _b.cancelTransaction(session));
1278
+ yield ((_c = this.blePlxManager) === null || _c === void 0 ? void 0 : _c.cancelTransaction(session));
1258
1279
  }
1259
1280
  catch (e) {
1260
1281
  Log === null || Log === void 0 ? void 0 : Log.debug('resetSession: cancel transaction error (ignored): ', (e === null || e === void 0 ? void 0 : e.message) || e);
@@ -1269,7 +1290,7 @@ class ReactNativeBleTransport {
1269
1290
  }
1270
1291
  }
1271
1292
  try {
1272
- yield ((_c = this.blePlxManager) === null || _c === void 0 ? void 0 : _c.cancelDeviceConnection(session));
1293
+ yield ((_d = this.blePlxManager) === null || _d === void 0 ? void 0 : _d.cancelDeviceConnection(session));
1273
1294
  }
1274
1295
  catch (e) {
1275
1296
  Log === null || Log === void 0 ? void 0 : Log.debug('resetSession: manager.cancelDeviceConnection error (ignored): ', (e === null || e === void 0 ? void 0 : e.message) || e);
@@ -1282,15 +1303,14 @@ class ReactNativeBleTransport {
1282
1303
  this.protocolV2Assemblers.delete(session);
1283
1304
  this.resetProtocolV2Frames(session);
1284
1305
  try {
1285
- (_d = this.emitter) === null || _d === void 0 ? void 0 : _d.emit('device-disconnect', {
1286
- name: (_e = transport === null || transport === void 0 ? void 0 : transport.device) === null || _e === void 0 ? void 0 : _e.name,
1287
- id: session,
1288
- connectId: session,
1289
- });
1306
+ this.emitDeviceDisconnect(session, (_e = transport === null || transport === void 0 ? void 0 : transport.device) === null || _e === void 0 ? void 0 : _e.name, monitorToken);
1290
1307
  }
1291
1308
  catch (e) {
1292
1309
  Log === null || Log === void 0 ? void 0 : Log.error('resetSession: emit disconnect event error: ', e);
1293
1310
  }
1311
+ if (monitorToken !== undefined && this.monitorTokens.get(session) === monitorToken) {
1312
+ this.monitorTokens.delete(session);
1313
+ }
1294
1314
  yield new Promise(resolve => setTimeout(() => resolve(), 100));
1295
1315
  });
1296
1316
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@onekeyfe/hd-transport-react-native",
3
- "version": "1.2.0-alpha.22",
3
+ "version": "1.2.0-alpha.24",
4
4
  "homepage": "https://github.com/OneKeyHQ/hardware-js-sdk#readme",
5
5
  "license": "MIT",
6
6
  "main": "dist/index.js",
@@ -19,11 +19,11 @@
19
19
  "lint:fix": "eslint . --fix"
20
20
  },
21
21
  "dependencies": {
22
- "@onekeyfe/hd-core": "1.2.0-alpha.22",
23
- "@onekeyfe/hd-shared": "1.2.0-alpha.22",
24
- "@onekeyfe/hd-transport": "1.2.0-alpha.22",
22
+ "@onekeyfe/hd-core": "1.2.0-alpha.24",
23
+ "@onekeyfe/hd-shared": "1.2.0-alpha.24",
24
+ "@onekeyfe/hd-transport": "1.2.0-alpha.24",
25
25
  "@onekeyfe/react-native-ble-utils": "^0.1.6",
26
26
  "react-native-ble-plx": "3.5.1"
27
27
  },
28
- "gitHead": "ce94a5ebbe141b0c15db7c68d08085ca1ddb0166"
28
+ "gitHead": "43663337d94350430cc507c74d6eec5a076bd4e9"
29
29
  }
@@ -2,6 +2,7 @@ import { EventEmitter } from 'events';
2
2
  import transportPackage, {
3
3
  PROTOCOL_V2_CHANNEL_BLE_UART,
4
4
  ProtocolV2,
5
+ TRANSPORT_EVENT,
5
6
  bytesToHex,
6
7
  } from '@onekeyfe/hd-transport';
7
8
  import { HardwareErrorCode } from '@onekeyfe/hd-shared';
@@ -102,6 +103,7 @@ const createHarness = () => {
102
103
  characteristic: { value: string } | null
103
104
  ) => void)
104
105
  | undefined;
106
+ let disconnectCallback: (() => void) | undefined;
105
107
  const notifyCharacteristic = {
106
108
  uuid: '0003',
107
109
  deviceID: uuid,
@@ -140,7 +142,11 @@ const createHarness = () => {
140
142
  localName: 'OneKey Pro 2',
141
143
  serviceUUIDs: ['fffd'],
142
144
  isConnected: jest.fn(() => Promise.resolve(true)),
143
- onDisconnected: jest.fn(() => ({ remove: jest.fn() })),
145
+ cancelConnection: jest.fn(() => Promise.resolve()),
146
+ onDisconnected: jest.fn(callback => {
147
+ disconnectCallback = callback;
148
+ return { remove: jest.fn() };
149
+ }),
144
150
  };
145
151
  const bleManager = {
146
152
  devices: jest.fn(() => Promise.resolve([device])),
@@ -148,16 +154,18 @@ const createHarness = () => {
148
154
  cancelTransaction: jest.fn(() => Promise.resolve()),
149
155
  };
150
156
  const transport = new ReactNativeBleTransport({ scanTimeout: 1 });
157
+ const emitter = new EventEmitter();
151
158
  transport.blePlxManager = bleManager;
152
159
  transport.resolveCharacteristics = jest.fn(() =>
153
160
  Promise.resolve({ writeCharacteristic, notifyCharacteristic })
154
161
  );
155
- transport.init({ debug: jest.fn(), error: jest.fn() }, new EventEmitter());
162
+ transport.init({ debug: jest.fn(), error: jest.fn() }, emitter);
156
163
  transport.configure(protocolV1Schema);
157
164
  transport.configureProtocolV2(protocolV2Schema);
158
165
 
159
166
  return {
160
167
  transport,
168
+ emitter,
161
169
  uuid,
162
170
  sentSeqs,
163
171
  writeCharacteristic,
@@ -167,6 +175,9 @@ const createHarness = () => {
167
175
  emitMonitorError(error: Error & { reason?: string }) {
168
176
  notifyCallback?.(error, null);
169
177
  },
178
+ emitDisconnect() {
179
+ disconnectCallback?.();
180
+ },
170
181
  };
171
182
  };
172
183
 
@@ -250,6 +261,23 @@ describe('ReactNativeBleTransport Protocol V2 link lifecycle', () => {
250
261
  await rejection;
251
262
  });
252
263
 
264
+ test('emits one disconnect event when the physical callback races manual cleanup', async () => {
265
+ const harness = createHarness();
266
+ const disconnectListener = jest.fn();
267
+ harness.emitter.on(TRANSPORT_EVENT.DEVICE_DISCONNECT, disconnectListener);
268
+
269
+ await harness.transport.acquire({ uuid: harness.uuid });
270
+ harness.emitDisconnect();
271
+ await harness.transport.disconnect(harness.uuid);
272
+
273
+ expect(disconnectListener).toHaveBeenCalledTimes(1);
274
+ expect(disconnectListener).toHaveBeenCalledWith({
275
+ name: 'OneKey Pro 2',
276
+ id: harness.uuid,
277
+ connectId: harness.uuid,
278
+ });
279
+ });
280
+
253
281
  test('chunks large frames and retries only transient GATT congestion', async () => {
254
282
  const transport = new ReactNativeBleTransport({ scanTimeout: 1 }) as any;
255
283
  const congested = { status: 143, message: 'GATT_CONGESTED' };
package/src/index.ts CHANGED
@@ -18,6 +18,7 @@ import transport, {
18
18
  type ProtocolV2CallContext,
19
19
  ProtocolV2FrameAssembler,
20
20
  ProtocolV2LinkManager,
21
+ TRANSPORT_EVENT,
21
22
  type TransportCallOptions,
22
23
  probeProtocolV2 as probeProtocolV2Helper,
23
24
  } from '@onekeyfe/hd-transport';
@@ -245,6 +246,8 @@ export default class ReactNativeBleTransport {
245
246
 
246
247
  _messagesV2: ReturnType<typeof transport.parseConfigure> | undefined;
247
248
 
249
+ private protocolV2SchemaConfiguration: string | undefined;
250
+
248
251
  name = 'ReactNativeBleTransport';
249
252
 
250
253
  configured = false;
@@ -293,6 +296,8 @@ export default class ReactNativeBleTransport {
293
296
 
294
297
  private monitorTokens: Map<string, number> = new Map();
295
298
 
299
+ private disconnectEventTokens: Map<string, number> = new Map();
300
+
296
301
  private nextMonitorToken = 1;
297
302
 
298
303
  constructor(options: TransportOptions) {
@@ -311,10 +316,19 @@ export default class ReactNativeBleTransport {
311
316
  }
312
317
 
313
318
  configureProtocolV2(signedData: any) {
319
+ const configuration = typeof signedData === 'string' ? signedData : JSON.stringify(signedData);
320
+ if (this.protocolV2SchemaConfiguration === configuration) {
321
+ return;
322
+ }
323
+
324
+ const isReconfiguration = this.protocolV2SchemaConfiguration !== undefined;
314
325
  this._messagesV2 = parseConfigure(signedData);
315
- this.protocolV2Links
316
- .invalidateAllLinks('Protocol V2 schema reconfigured')
317
- .catch(error => Log?.debug('Protocol V2 schema link cleanup failed:', error));
326
+ this.protocolV2SchemaConfiguration = configuration;
327
+ if (isReconfiguration) {
328
+ this.protocolV2Links
329
+ .invalidateAllLinks('Protocol V2 schema reconfigured')
330
+ .catch(error => Log?.debug('Protocol V2 schema link cleanup failed:', error));
331
+ }
318
332
  }
319
333
 
320
334
  listen() {
@@ -428,6 +442,7 @@ export default class ReactNativeBleTransport {
428
442
 
429
443
  attachDisconnectSubscription(transport: BleTransport, device: Device, uuid: string) {
430
444
  transport.disconnectSubscription?.remove();
445
+ const { monitorToken } = transport;
431
446
  transport.disconnectSubscription = device.onDisconnected(() => {
432
447
  if (this.firmwareUploadWriteRecoveryIds.has(uuid)) {
433
448
  Log?.debug('device disconnect ignored during FirmwareUpload write recovery: ', uuid);
@@ -437,14 +452,14 @@ export default class ReactNativeBleTransport {
437
452
  Log?.debug('device disconnect ignored for stale transport: ', device?.id);
438
453
  return;
439
454
  }
455
+ if (this.monitorTokens.get(uuid) !== monitorToken) {
456
+ Log?.debug('device disconnect ignored for stale generation: ', device?.id);
457
+ return;
458
+ }
440
459
 
441
460
  try {
442
461
  Log?.debug('device disconnect: ', device?.id);
443
- this.emitter?.emit('device-disconnect', {
444
- name: device?.name,
445
- id: device?.id,
446
- connectId: device?.id,
447
- });
462
+ this.emitDeviceDisconnect(uuid, device?.name, monitorToken);
448
463
  if (this.runPromise) {
449
464
  const error = ERRORS.TypedError(HardwareErrorCode.BleConnectedError);
450
465
  this.runPromise.reject(error);
@@ -458,6 +473,22 @@ export default class ReactNativeBleTransport {
458
473
  });
459
474
  }
460
475
 
476
+ private emitDeviceDisconnect(uuid: string, name: string | null | undefined, token?: number) {
477
+ if (token === undefined || this.disconnectEventTokens.get(uuid) === token) {
478
+ return;
479
+ }
480
+ if (this.monitorTokens.get(uuid) !== token) {
481
+ Log?.debug('device disconnect event ignored for stale generation: ', uuid);
482
+ return;
483
+ }
484
+ this.disconnectEventTokens.set(uuid, token);
485
+ this.emitter?.emit(TRANSPORT_EVENT.DEVICE_DISCONNECT, {
486
+ name,
487
+ id: uuid,
488
+ connectId: uuid,
489
+ });
490
+ }
491
+
461
492
  async reconnectFirmwareUploadTransport(uuid: string, transport: BleTransport) {
462
493
  this.firmwareUploadWriteRecoveryIds.add(uuid);
463
494
  try {
@@ -800,12 +831,6 @@ export default class ReactNativeBleTransport {
800
831
 
801
832
  const protocolType = await this.detectProtocol(uuid, expectedProtocol, protocolHint);
802
833
 
803
- this.emitter?.emit('device-connect', {
804
- name: device.name,
805
- id: device.id,
806
- connectId: device.id,
807
- });
808
-
809
834
  this.attachDisconnectSubscription(transport, device, uuid);
810
835
 
811
836
  return { uuid, protocolType };
@@ -1262,6 +1287,7 @@ export default class ReactNativeBleTransport {
1262
1287
  async disconnect(session: string) {
1263
1288
  await this.protocolV2Links.invalidateLink(session, 'React Native BLE transport disconnected');
1264
1289
  const transport = transportCache[session];
1290
+ const monitorToken = transport?.monitorToken ?? this.monitorTokens.get(session);
1265
1291
 
1266
1292
  // Clean up disconnect subscription first to prevent onDisconnected callback
1267
1293
  // from being triggered when we cancel the connection below
@@ -1325,14 +1351,13 @@ export default class ReactNativeBleTransport {
1325
1351
 
1326
1352
  // emit the disconnect event
1327
1353
  try {
1328
- this.emitter?.emit('device-disconnect', {
1329
- name: transport?.device?.name,
1330
- id: session,
1331
- connectId: session,
1332
- });
1354
+ this.emitDeviceDisconnect(session, transport?.device?.name, monitorToken);
1333
1355
  } catch (e) {
1334
1356
  Log?.error('resetSession: emit disconnect event error: ', e);
1335
1357
  }
1358
+ if (monitorToken !== undefined && this.monitorTokens.get(session) === monitorToken) {
1359
+ this.monitorTokens.delete(session);
1360
+ }
1336
1361
  // eslint-disable-next-line no-promise-executor-return
1337
1362
  await new Promise<void>(resolve => setTimeout(() => resolve(), 100));
1338
1363
  }