@onekeyfe/hd-transport-usb 1.2.0-alpha.33 → 1.2.0-alpha.34

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.
@@ -253,6 +253,28 @@ const createHarness = () => {
253
253
  };
254
254
 
255
255
  describe('NodeUsbTransport Protocol V2 link lifecycle', () => {
256
+ test('falls back to Protocol V2 when a cached V1 hint is stale', async () => {
257
+ const transport = new NodeUsbTransport() as any;
258
+ const events: string[] = [];
259
+ transport.probeProtocolV1 = jest.fn().mockImplementation(() => {
260
+ events.push('probe-v1');
261
+ return Promise.resolve(false);
262
+ });
263
+ transport.resetConnectionAfterProbe = jest.fn().mockImplementation(() => {
264
+ events.push('reset');
265
+ return Promise.resolve();
266
+ });
267
+ transport.probeProtocolV2 = jest.fn().mockImplementation(() => {
268
+ events.push('probe-v2');
269
+ return Promise.resolve(true);
270
+ });
271
+
272
+ await expect(transport.detectProtocol('pro-usb', undefined, 'V1')).resolves.toBe('V2');
273
+
274
+ expect(events).toEqual(['probe-v1', 'reset', 'probe-v2']);
275
+ expect(transport.getProtocolType('pro-usb')).toBe('V2');
276
+ });
277
+
256
278
  test('keeps active links when the Protocol V2 schema is configured repeatedly', () => {
257
279
  const transport = new NodeUsbTransport() as any;
258
280
  transport.invalidateAllProtocolV2UsbLinks = jest.fn().mockResolvedValue(undefined);
@@ -286,6 +308,25 @@ describe('NodeUsbTransport Protocol V2 link lifecycle', () => {
286
308
  );
287
309
  });
288
310
 
311
+ test('releases the USB interface when protocol detection rejects acquire', async () => {
312
+ const harness = createHarness();
313
+ const { transport, path, device, iface } = harness;
314
+ await transport.enumerate();
315
+ device.close.mockClear();
316
+ iface.release.mockClear();
317
+ jest
318
+ .spyOn(transport as any, 'detectProtocol')
319
+ .mockRejectedValueOnce(new Error('terminal protocol probe failure'));
320
+
321
+ await expect(transport.acquire({ path })).rejects.toMatchObject({
322
+ errorCode: expect.any(Number),
323
+ });
324
+
325
+ expect(iface.release).toHaveBeenCalledTimes(1);
326
+ expect(device.close).toHaveBeenCalledTimes(1);
327
+ expect((transport as any).openDevices.has(path)).toBe(false);
328
+ });
329
+
289
330
  test('stop releases an acquired USB interface even before a Protocol V2 call', async () => {
290
331
  const harness = createHarness();
291
332
  const { transport, path, device, iface } = harness;
@@ -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
@@ -261,7 +261,7 @@ class NodeUsbTransport extends transport.ProtocolV2UsbTransportBase {
261
261
  });
262
262
  }
263
263
  acquire(input) {
264
- var _a, _b, _c;
264
+ var _a, _b, _c, _d;
265
265
  return __awaiter(this, void 0, void 0, function* () {
266
266
  this.cancelled = false;
267
267
  const path = (_a = input.path) !== null && _a !== void 0 ? _a : '';
@@ -272,12 +272,18 @@ class NodeUsbTransport extends transport.ProtocolV2UsbTransportBase {
272
272
  yield this.rotateProtocolV2UsbGeneration(path, 'Node USB transport acquired');
273
273
  yield this.closeOpenDevice(path);
274
274
  yield this.openDevice(path);
275
- yield this.detectProtocol(path, input.expectedProtocol);
275
+ yield this.detectProtocol(path, input.expectedProtocol, input.protocolHint);
276
276
  return path;
277
277
  }
278
278
  catch (error) {
279
279
  (_b = this.Log) === null || _b === void 0 ? void 0 : _b.debug('NodeUsbTransport acquire error: ', error);
280
- throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.DeviceNotFound, (_c = error.message) !== null && _c !== void 0 ? _c : String(error));
280
+ try {
281
+ yield this.release(path);
282
+ }
283
+ catch (cleanupError) {
284
+ (_c = this.Log) === null || _c === void 0 ? void 0 : _c.debug('NodeUsbTransport acquire cleanup error: ', cleanupError);
285
+ }
286
+ throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.DeviceNotFound, (_d = error.message) !== null && _d !== void 0 ? _d : String(error));
281
287
  }
282
288
  });
283
289
  }
@@ -650,7 +656,7 @@ class NodeUsbTransport extends transport.ProtocolV2UsbTransportBase {
650
656
  createProtocolDetectionError() {
651
657
  return hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, 'Unable to detect USB protocol: device did not respond to Protocol V1 Initialize or Protocol V2 Ping');
652
658
  }
653
- detectProtocol(path, expectedProtocol) {
659
+ detectProtocol(path, expectedProtocol, protocolHint) {
654
660
  var _a;
655
661
  return __awaiter(this, void 0, void 0, function* () {
656
662
  if (expectedProtocol === 'V2') {
@@ -668,17 +674,16 @@ class NodeUsbTransport extends transport.ProtocolV2UsbTransportBase {
668
674
  }
669
675
  throw this.createProtocolMismatchError(expectedProtocol);
670
676
  }
671
- if (this.deviceProtocol.get(path) === 'V2' && (yield this.probeProtocolV2(path))) {
672
- this.deviceProtocol.set(path, 'V2');
673
- return 'V2';
674
- }
675
- if (yield this.probeProtocolV1(path)) {
676
- this.deviceProtocol.set(path, 'V1');
677
- return 'V1';
678
- }
679
- if (yield this.probeProtocolV2(path)) {
680
- this.deviceProtocol.set(path, 'V2');
681
- return 'V2';
677
+ const probeOrder = protocolHint === 'V2' || this.deviceProtocol.get(path) === 'V2' ? ['V2', 'V1'] : ['V1', 'V2'];
678
+ for (const [index, protocol] of probeOrder.entries()) {
679
+ if (index > 0) {
680
+ yield this.resetConnectionAfterProbe(path);
681
+ }
682
+ const detected = protocol === 'V1' ? yield this.probeProtocolV1(path) : yield this.probeProtocolV2(path);
683
+ if (detected) {
684
+ this.deviceProtocol.set(path, protocol);
685
+ return protocol;
686
+ }
682
687
  }
683
688
  this.deviceProtocol.delete(path);
684
689
  throw this.createProtocolDetectionError();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@onekeyfe/hd-transport-usb",
3
- "version": "1.2.0-alpha.33",
3
+ "version": "1.2.0-alpha.34",
4
4
  "description": "OneKey hardware wallet direct USB transport plugin (libusb)",
5
5
  "homepage": "https://github.com/OneKeyHQ/hardware-js-sdk#readme",
6
6
  "license": "MIT",
@@ -21,10 +21,10 @@
21
21
  "lint:fix": "eslint . --fix"
22
22
  },
23
23
  "dependencies": {
24
- "@onekeyfe/hd-shared": "1.2.0-alpha.33",
25
- "@onekeyfe/hd-transport": "1.2.0-alpha.33",
24
+ "@onekeyfe/hd-shared": "1.2.0-alpha.34",
25
+ "@onekeyfe/hd-transport": "1.2.0-alpha.34",
26
26
  "bytebuffer": "^5.0.1",
27
27
  "usb": "^2.14.0"
28
28
  },
29
- "gitHead": "965e837c93fc67225ccfac28d22c3403ff96ad25"
29
+ "gitHead": "07f10b4c9fab177da7c36d976ec18b075492b57f"
30
30
  }
package/src/index.ts CHANGED
@@ -346,10 +346,15 @@ export default class NodeUsbTransport extends ProtocolV2UsbTransportBase<string>
346
346
  await this.rotateProtocolV2UsbGeneration(path, 'Node USB transport acquired');
347
347
  await this.closeOpenDevice(path);
348
348
  await this.openDevice(path);
349
- await this.detectProtocol(path, input.expectedProtocol);
349
+ await this.detectProtocol(path, input.expectedProtocol, input.protocolHint);
350
350
  return path;
351
351
  } catch (error: any) {
352
352
  this.Log?.debug('NodeUsbTransport acquire error: ', error);
353
+ try {
354
+ await this.release(path);
355
+ } catch (cleanupError) {
356
+ this.Log?.debug('NodeUsbTransport acquire cleanup error: ', cleanupError);
357
+ }
353
358
  throw ERRORS.TypedError(HardwareErrorCode.DeviceNotFound, error.message ?? String(error));
354
359
  }
355
360
  }
@@ -843,7 +848,8 @@ export default class NodeUsbTransport extends ProtocolV2UsbTransportBase<string>
843
848
 
844
849
  private async detectProtocol(
845
850
  path: string,
846
- expectedProtocol?: ProtocolType
851
+ expectedProtocol?: ProtocolType,
852
+ protocolHint?: ProtocolType
847
853
  ): Promise<ProtocolType> {
848
854
  if (expectedProtocol === 'V2') {
849
855
  if (await this.probeProtocolV2(path)) {
@@ -862,19 +868,19 @@ export default class NodeUsbTransport extends ProtocolV2UsbTransportBase<string>
862
868
  throw this.createProtocolMismatchError(expectedProtocol);
863
869
  }
864
870
 
865
- if (this.deviceProtocol.get(path) === 'V2' && (await this.probeProtocolV2(path))) {
866
- this.deviceProtocol.set(path, 'V2');
867
- return 'V2';
868
- }
871
+ const probeOrder: ProtocolType[] =
872
+ protocolHint === 'V2' || this.deviceProtocol.get(path) === 'V2' ? ['V2', 'V1'] : ['V1', 'V2'];
869
873
 
870
- if (await this.probeProtocolV1(path)) {
871
- this.deviceProtocol.set(path, 'V1');
872
- return 'V1';
873
- }
874
-
875
- if (await this.probeProtocolV2(path)) {
876
- this.deviceProtocol.set(path, 'V2');
877
- return 'V2';
874
+ for (const [index, protocol] of probeOrder.entries()) {
875
+ if (index > 0) {
876
+ await this.resetConnectionAfterProbe(path);
877
+ }
878
+ const detected =
879
+ protocol === 'V1' ? await this.probeProtocolV1(path) : await this.probeProtocolV2(path);
880
+ if (detected) {
881
+ this.deviceProtocol.set(path, protocol);
882
+ return protocol;
883
+ }
878
884
  }
879
885
 
880
886
  this.deviceProtocol.delete(path);