@onekeyfe/hd-core 1.2.0-alpha.140 → 1.2.0-alpha.141

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.
@@ -128,7 +128,7 @@ describe('public device lifecycle events', () => {
128
128
 
129
129
  await device.acquire();
130
130
 
131
- expect(acquire).toHaveBeenCalledWith('ble-id', undefined, true, 'V1', undefined);
131
+ expect(acquire).toHaveBeenCalledWith('ble-id', undefined, true, 'V1', undefined, undefined);
132
132
  expect(device.getProtocol()).toBe('V1');
133
133
  expect(device.originalDescriptor.protocolType).toBe('V1');
134
134
  });
@@ -146,7 +146,9 @@ describe('public device lifecycle events', () => {
146
146
 
147
147
  await device.acquire(undefined, { forceProtocolDetection: true });
148
148
 
149
- expect(acquire).toHaveBeenCalledWith('ble-id', undefined, true, undefined, undefined);
149
+ // Explicit active detection forwards forceProtocolDetection so the
150
+ // transport bypasses its protocol cache.
151
+ expect(acquire).toHaveBeenCalledWith('ble-id', undefined, true, undefined, undefined, true);
150
152
  expect(device.getProtocol()).toBe('V2');
151
153
  expect(device.originalDescriptor.protocolType).toBe('V2');
152
154
  });
@@ -247,7 +249,7 @@ describe('public device lifecycle events', () => {
247
249
 
248
250
  await device.acquire('V2');
249
251
 
250
- expect(acquire).toHaveBeenCalledWith('ble-id', undefined, true, 'V2', undefined);
252
+ expect(acquire).toHaveBeenCalledWith('ble-id', undefined, true, 'V2', undefined, undefined);
251
253
  expect(device.getProtocol()).toBe('V2');
252
254
  });
253
255
 
@@ -352,7 +352,75 @@ describe('Protocol V1 wallet identity initialization', () => {
352
352
  jest.restoreAllMocks();
353
353
  });
354
354
 
355
- test('verifies the live device id without resetting the cached wallet session', async () => {
355
+ test('sends no wallet context before identity is proven on first contact', async () => {
356
+ const device = Device.fromDescriptor({ id: 'connect-a', path: 'connect-a' } as never);
357
+ // No cached features: there is no local evidence which device sits here.
358
+ deviceWalletSessionStore.set('device-a', 'hidden-a', 'session-a');
359
+ const typedCall = jest.fn().mockResolvedValue({
360
+ type: 'Features',
361
+ message: { device_id: 'intruder-device', session_id: 'intruder-session' },
362
+ });
363
+ device.commands = { typedCall } as never;
364
+ jest.spyOn(TransportManager, 'reconfigure').mockResolvedValue(undefined);
365
+
366
+ await expect(
367
+ device.initialize({ deviceId: 'device-a', passphraseState: 'hidden-a' })
368
+ ).rejects.toMatchObject({ errorCode: HardwareErrorCode.DeviceCheckDeviceIdError });
369
+
370
+ // Exactly one context-free Initialize: neither the cached session_id nor
371
+ // the passphrase_state may reach an unproven device.
372
+ expect(typedCall).toHaveBeenCalledTimes(1);
373
+ expect(typedCall).toHaveBeenCalledWith(
374
+ 'Initialize',
375
+ 'Features',
376
+ { is_contains_attach: true },
377
+ expect.any(Object)
378
+ );
379
+ // The expected device's cached session is untouched.
380
+ expect(deviceWalletSessionStore.get('device-a', 'hidden-a')).toBe('session-a');
381
+ });
382
+
383
+ test('proves identity first, then resumes the wallet session on first contact', async () => {
384
+ const device = Device.fromDescriptor({ id: 'connect-a', path: 'connect-a' } as never);
385
+ deviceWalletSessionStore.set('device-a', 'hidden-a', 'session-a');
386
+ const typedCall = jest
387
+ .fn()
388
+ .mockResolvedValueOnce({
389
+ type: 'Features',
390
+ message: { device_id: 'device-a', session_id: 'standard-session' },
391
+ })
392
+ .mockResolvedValueOnce({
393
+ type: 'Features',
394
+ message: { device_id: 'device-a', session_id: 'session-a' },
395
+ });
396
+ device.commands = { typedCall } as never;
397
+ jest.spyOn(TransportManager, 'reconfigure').mockResolvedValue(undefined);
398
+
399
+ await device.initialize({ deviceId: 'device-a', passphraseState: 'hidden-a' });
400
+
401
+ expect(typedCall).toHaveBeenCalledTimes(2);
402
+ expect(typedCall).toHaveBeenNthCalledWith(
403
+ 1,
404
+ 'Initialize',
405
+ 'Features',
406
+ { is_contains_attach: true },
407
+ expect.any(Object)
408
+ );
409
+ expect(typedCall).toHaveBeenNthCalledWith(
410
+ 2,
411
+ 'Initialize',
412
+ 'Features',
413
+ expect.objectContaining({
414
+ session_id: 'session-a',
415
+ passphrase_state: 'hidden-a',
416
+ }),
417
+ expect.any(Object)
418
+ );
419
+ // The context-free identity call must not overwrite the cached session.
420
+ expect(deviceWalletSessionStore.get('device-a', 'hidden-a')).toBe('session-a');
421
+ });
422
+
423
+ test('purges cached sessions and rejects when the live device identity changes', async () => {
356
424
  const device = Device.fromDescriptor({ id: 'connect-b', path: 'connect-b' } as never);
357
425
  device.features = {
358
426
  protocol: 'V1',
@@ -363,7 +431,7 @@ describe('Protocol V1 wallet identity initialization', () => {
363
431
  deviceWalletSessionStore.set('cached-device-a', 'hidden-a', 'session-a');
364
432
  const typedCall = jest.fn().mockResolvedValue({
365
433
  type: 'Features',
366
- message: { device_id: 'live-device-b' },
434
+ message: { device_id: 'live-device-b', session_id: 'wrong-device-session' },
367
435
  });
368
436
  device.commands = { typedCall } as never;
369
437
  jest.spyOn(TransportManager, 'reconfigure').mockResolvedValue(undefined);
@@ -371,11 +439,76 @@ describe('Protocol V1 wallet identity initialization', () => {
371
439
  await expect(
372
440
  device.initialize({ deviceId: 'cached-device-a', passphraseState: 'hidden-a' })
373
441
  ).rejects.toMatchObject({ errorCode: HardwareErrorCode.DeviceCheckDeviceIdError });
442
+ // Identity is validated from the single Initialize round trip; no separate
443
+ // GetFeatures preflight.
374
444
  expect(typedCall).toHaveBeenCalledTimes(1);
375
- expect(typedCall).toHaveBeenCalledWith('GetFeatures', 'Features', {});
445
+ expect(typedCall).toHaveBeenCalledWith(
446
+ 'Initialize',
447
+ 'Features',
448
+ expect.objectContaining({ passphrase_state: 'hidden-a' }),
449
+ expect.any(Object)
450
+ );
451
+ // Identity change purges the previous device's cached sessions (pre-existing
452
+ // reconcileDeviceIdentity behavior — never carry sessions across devices)…
453
+ expect(deviceWalletSessionStore.get('cached-device-a', 'hidden-a')).toBeUndefined();
454
+ // …and the session the mismatched Initialize cached under the wrong
455
+ // device's identity is dropped as well.
456
+ expect(deviceWalletSessionStore.get('live-device-b', 'hidden-a')).toBeUndefined();
376
457
  });
377
458
 
378
- test('resumes a cached V1 wallet after a non-destructive live identity read', async () => {
459
+ test('drops the wrong-device session even when reconfigure fails after Initialize', async () => {
460
+ const device = Device.fromDescriptor({ id: 'connect-b', path: 'connect-b' } as never);
461
+ device.features = {
462
+ protocol: 'V1',
463
+ deviceId: 'cached-device-a',
464
+ unlocked: true,
465
+ passphraseProtection: true,
466
+ } as never;
467
+ deviceWalletSessionStore.set('cached-device-a', 'hidden-a', 'session-a');
468
+ const typedCall = jest.fn().mockResolvedValue({
469
+ type: 'Features',
470
+ message: { device_id: 'live-device-b', session_id: 'wrong-device-session' },
471
+ });
472
+ device.commands = { typedCall } as never;
473
+ // Pre-encode resync succeeds; the post-response reconfigure inside
474
+ // callInitialize rejects — the session write has already happened by then.
475
+ jest
476
+ .spyOn(TransportManager, 'reconfigure')
477
+ .mockResolvedValueOnce(undefined)
478
+ .mockRejectedValueOnce(new Error('configure failed'));
479
+
480
+ await expect(
481
+ device.initialize({ deviceId: 'cached-device-a', passphraseState: 'hidden-a' })
482
+ ).rejects.toMatchObject({ errorCode: HardwareErrorCode.DeviceCheckDeviceIdError });
483
+ // The wrong-device session must not survive the error path either.
484
+ expect(deviceWalletSessionStore.get('live-device-b', 'hidden-a')).toBeUndefined();
485
+ });
486
+
487
+ test('re-syncs the V1 message schema for this device before encoding Initialize', async () => {
488
+ const device = Device.fromDescriptor({ id: 'connect-a', path: 'connect-a' } as never);
489
+ device.features = {
490
+ protocol: 'V1',
491
+ deviceId: 'device-a',
492
+ unlocked: true,
493
+ passphraseProtection: true,
494
+ } as never;
495
+ const typedCall = jest.fn().mockResolvedValue({
496
+ type: 'Features',
497
+ message: { device_id: 'device-a' },
498
+ });
499
+ device.commands = { typedCall } as never;
500
+ const reconfigure = jest.spyOn(TransportManager, 'reconfigure').mockResolvedValue(undefined);
501
+
502
+ await device.initialize({ deviceId: 'device-a', passphraseState: 'hidden-a' });
503
+
504
+ // A stale process-global schema (from another device) would silently strip
505
+ // passphrase_state from the wire message, so the resync must come first.
506
+ expect(reconfigure.mock.invocationCallOrder[0]).toBeLessThan(
507
+ typedCall.mock.invocationCallOrder[0]
508
+ );
509
+ });
510
+
511
+ test('resumes a cached V1 wallet with a single identity-validated Initialize', async () => {
379
512
  const device = Device.fromDescriptor({ id: 'connect-a', path: 'connect-a' } as never);
380
513
  device.features = {
381
514
  protocol: 'V1',
@@ -384,22 +517,17 @@ describe('Protocol V1 wallet identity initialization', () => {
384
517
  passphraseProtection: true,
385
518
  } as never;
386
519
  deviceWalletSessionStore.set('device-a', 'hidden-a', 'session-a');
387
- const typedCall = jest
388
- .fn()
389
- .mockResolvedValueOnce({ type: 'Features', message: { device_id: 'device-a' } })
390
- .mockResolvedValueOnce({
391
- type: 'Features',
392
- message: { device_id: 'device-a', session_id: 'session-a' },
393
- });
520
+ const typedCall = jest.fn().mockResolvedValueOnce({
521
+ type: 'Features',
522
+ message: { device_id: 'device-a', session_id: 'session-a' },
523
+ });
394
524
  device.commands = { typedCall } as never;
395
525
  jest.spyOn(TransportManager, 'reconfigure').mockResolvedValue(undefined);
396
526
 
397
527
  await device.initialize({ deviceId: 'device-a', passphraseState: 'hidden-a' });
398
528
 
399
- expect(typedCall).toHaveBeenCalledTimes(2);
400
- expect(typedCall).toHaveBeenNthCalledWith(1, 'GetFeatures', 'Features', {});
401
- expect(typedCall).toHaveBeenNthCalledWith(
402
- 2,
529
+ expect(typedCall).toHaveBeenCalledTimes(1);
530
+ expect(typedCall).toHaveBeenCalledWith(
403
531
  'Initialize',
404
532
  'Features',
405
533
  expect.objectContaining({
@@ -408,9 +536,10 @@ describe('Protocol V1 wallet identity initialization', () => {
408
536
  }),
409
537
  expect.any(Object)
410
538
  );
539
+ expect(deviceWalletSessionStore.get('device-a', 'hidden-a')).toBe('session-a');
411
540
  });
412
541
 
413
- test('selects the standard V1 wallet after a non-destructive live identity read', async () => {
542
+ test('selects the standard V1 wallet with a single identity-validated Initialize', async () => {
414
543
  const device = Device.fromDescriptor({ id: 'connect-a', path: 'connect-a' } as never);
415
544
  device.features = {
416
545
  protocol: 'V1',
@@ -420,17 +549,14 @@ describe('Protocol V1 wallet identity initialization', () => {
420
549
  } as never;
421
550
  const typedCall = jest
422
551
  .fn()
423
- .mockResolvedValueOnce({ type: 'Features', message: { device_id: 'device-a' } })
424
552
  .mockResolvedValueOnce({ type: 'Features', message: { device_id: 'device-a' } });
425
553
  device.commands = { typedCall } as never;
426
554
  jest.spyOn(TransportManager, 'reconfigure').mockResolvedValue(undefined);
427
555
 
428
556
  await device.initialize({ deviceId: 'device-a' });
429
557
 
430
- expect(typedCall).toHaveBeenCalledTimes(2);
431
- expect(typedCall).toHaveBeenNthCalledWith(1, 'GetFeatures', 'Features', {});
432
- expect(typedCall).toHaveBeenNthCalledWith(
433
- 2,
558
+ expect(typedCall).toHaveBeenCalledTimes(1);
559
+ expect(typedCall).toHaveBeenCalledWith(
434
560
  'Initialize',
435
561
  'Features',
436
562
  {
@@ -5200,6 +5200,7 @@ describe('Protocol V2 firmware update targets', () => {
5200
5200
  expect(probeProtocolV2RuntimeState).toHaveBeenCalledWith(deviceInfo, 5000, {
5201
5201
  forceRuntimeContextRefresh: true,
5202
5202
  });
5203
+ expect((method as any).protocolV2LatestFinalDeviceInfo).toBe(deviceInfo);
5203
5204
  });
5204
5205
 
5205
5206
  test('reboots Protocol V2 firmware flow back to normal without legacy switch-firmware prompt', async () => {
@@ -5708,7 +5709,7 @@ describe('Protocol V2 firmware update targets', () => {
5708
5709
  ])
5709
5710
  ).rejects.toMatchObject({
5710
5711
  errorCode: HardwareErrorCode.FirmwareError,
5711
- message: 'Firmware installation failed',
5712
+ message: 'Protocol V2 firmware install timed out',
5712
5713
  params: { firmwareUpdateCode: 'FirmwareInstallTimeout' },
5713
5714
  });
5714
5715
 
@@ -5716,11 +5717,16 @@ describe('Protocol V2 firmware update targets', () => {
5716
5717
  expect(typedCall).toHaveBeenCalledTimes(5);
5717
5718
  });
5718
5719
 
5719
- test('accepts ACK-less normal mode after the requested target version changes', async () => {
5720
+ test('preserves multi-app completion evidence when App mode replaces the status endpoint', async () => {
5720
5721
  const method = new FirmwareUpdateV4({
5721
5722
  id: 1,
5722
5723
  payload: {
5723
5724
  method: 'firmwareUpdateV4',
5725
+ targetsToUpdate: ['app_v1', 'app_v2'],
5726
+ expectedTargetVersions: {
5727
+ app_v1: '2.0.0',
5728
+ app_v2: '2.0.0',
5729
+ },
5724
5730
  },
5725
5731
  });
5726
5732
  const typedCall = jest
@@ -5737,7 +5743,10 @@ describe('Protocol V2 firmware update targets', () => {
5737
5743
  getCommands: () => ({ typedCall }),
5738
5744
  probeProtocolV2RuntimeState,
5739
5745
  });
5740
- (method as any).protocolV2InstallBaselineVersions = new Map([[4, '1.0.0']]);
5746
+ (method as any).protocolV2InstallBaselineVersions = new Map([
5747
+ [4, '1.0.0'],
5748
+ [5, '1.0.0'],
5749
+ ]);
5741
5750
  (method as any).reconnectProtocolV2Device = jest.fn().mockResolvedValue(undefined);
5742
5751
  (method as any).verifyProtocolV2ReconnectIdentity = jest.fn().mockResolvedValue(deviceInfo);
5743
5752
  method.postProgressMessage = jest.fn();
@@ -5745,11 +5754,69 @@ describe('Protocol V2 firmware update targets', () => {
5745
5754
  await expect(
5746
5755
  (method as any).waitForProtocolV2FirmwareUpdateComplete([
5747
5756
  { target_id: 4, path: 'vol0:/application_p1.bin' },
5757
+ { target_id: 5, path: 'vol0:/application_p2.bin' },
5748
5758
  ])
5749
5759
  ).resolves.toBeUndefined();
5750
5760
 
5751
5761
  expect(probeProtocolV2RuntimeState).toHaveBeenCalledWith(deviceInfo, 5000);
5752
5762
  expect(method.postProgressMessage).toHaveBeenCalledWith(100, 'installingFirmware');
5763
+ expect(Array.from((method as any).protocolV2CompletedTargetIds)).toEqual([4, 5]);
5764
+
5765
+ (method as any).protocolV2LatestFinalFeatures = {
5766
+ firmwareVersion: '2.0.0',
5767
+ };
5768
+ (method as any).protocolV2LatestFinalDeviceInfo = {
5769
+ main_mcu: {
5770
+ application: { version: '2.0.0' },
5771
+ },
5772
+ };
5773
+ expect(() => (method as any).assertExpectedProtocolV2Versions()).not.toThrow();
5774
+ });
5775
+
5776
+ test('preserves all target completion evidence when status records disappear after reboot', async () => {
5777
+ const method = new FirmwareUpdateV4({
5778
+ id: 1,
5779
+ payload: {
5780
+ method: 'firmwareUpdateV4',
5781
+ },
5782
+ });
5783
+ const typedCall = jest
5784
+ .fn()
5785
+ .mockResolvedValueOnce({ type: 'Success', message: {} })
5786
+ .mockRejectedValueOnce(new Error('Pro2 is rebooting'))
5787
+ .mockResolvedValueOnce({
5788
+ type: 'DeviceFirmwareUpdateStatus',
5789
+ message: { records: [] },
5790
+ });
5791
+ const deviceInfo = { hw: { serial_no: 'PRO2-PHYSICAL-1' } };
5792
+ const setTimeoutSpy = jest.spyOn(global, 'setTimeout').mockImplementation(((
5793
+ callback: () => void
5794
+ ) => {
5795
+ callback();
5796
+ return 0 as any;
5797
+ }) as typeof setTimeout);
5798
+
5799
+ (method as any).device = stubDevice({
5800
+ getCommands: () => ({ typedCall }),
5801
+ });
5802
+ (method as any).reconnectProtocolV2Device = jest.fn().mockResolvedValue(undefined);
5803
+ (method as any).verifyProtocolV2ReconnectIdentity = jest.fn().mockResolvedValue(deviceInfo);
5804
+ (method as any).probeProtocolV2NormalMode = jest.fn().mockResolvedValue(true);
5805
+ method.postProgressMessage = jest.fn();
5806
+
5807
+ try {
5808
+ await expect(
5809
+ (method as any).waitForProtocolV2FirmwareUpdateComplete([
5810
+ { target_id: 4, path: 'vol0:/application_p1.bin' },
5811
+ { target_id: 5, path: 'vol0:/application_p2.bin' },
5812
+ ])
5813
+ ).resolves.toBeUndefined();
5814
+ } finally {
5815
+ setTimeoutSpy.mockRestore();
5816
+ }
5817
+
5818
+ expect(Array.from((method as any).protocolV2CompletedTargetIds)).toEqual([4, 5]);
5819
+ expect(method.postProgressMessage).toHaveBeenCalledWith(100, 'installingFirmware');
5753
5820
  });
5754
5821
 
5755
5822
  test.each([
@@ -5931,7 +5998,7 @@ describe('Protocol V2 firmware update targets', () => {
5931
5998
  ])
5932
5999
  ).rejects.toMatchObject({
5933
6000
  errorCode: HardwareErrorCode.FirmwareError,
5934
- message: 'Firmware installation failed',
6001
+ message: 'Protocol V2 firmware install status conflict',
5935
6002
  params: {
5936
6003
  firmwareUpdateCode: 'FirmwareInstallStatusConflict',
5937
6004
  },
@@ -5968,6 +6035,66 @@ describe('Protocol V2 firmware update targets', () => {
5968
6035
  expect(() => (method as any).assertExpectedProtocolV2Versions()).not.toThrow();
5969
6036
  });
5970
6037
 
6038
+ test('uses final DeviceInfo versions for both application slots after status polling ends', () => {
6039
+ const method = new FirmwareUpdateV4({
6040
+ id: 1,
6041
+ payload: {
6042
+ method: 'firmwareUpdateV4',
6043
+ platform: 'desktop',
6044
+ targetsToUpdate: ['app_v1', 'app_v2'],
6045
+ expectedTargetVersions: {
6046
+ app_v1: '1.0.0',
6047
+ app_v2: '2.0.0',
6048
+ },
6049
+ },
6050
+ });
6051
+ method.init();
6052
+ (method as any).protocolV2LatestFinalFeatures = {
6053
+ major_version: 3,
6054
+ minor_version: 0,
6055
+ patch_version: 0,
6056
+ };
6057
+ (method as any).protocolV2LatestFinalDeviceInfo = {
6058
+ main_mcu: {
6059
+ application: { version: '1.0.0' },
6060
+ application_data: { version: '2.0.0' },
6061
+ },
6062
+ };
6063
+
6064
+ expect(() => (method as any).assertExpectedProtocolV2Versions()).not.toThrow();
6065
+ });
6066
+
6067
+ test('rejects a mismatched final DeviceInfo application slot version', () => {
6068
+ const method = new FirmwareUpdateV4({
6069
+ id: 1,
6070
+ payload: {
6071
+ method: 'firmwareUpdateV4',
6072
+ platform: 'desktop',
6073
+ targetsToUpdate: ['app_v1', 'app_v2'],
6074
+ expectedTargetVersions: {
6075
+ app_v1: '1.0.0',
6076
+ app_v2: '2.0.0',
6077
+ },
6078
+ },
6079
+ });
6080
+ method.init();
6081
+ (method as any).protocolV2LatestFinalFeatures = {
6082
+ major_version: 3,
6083
+ minor_version: 0,
6084
+ patch_version: 0,
6085
+ };
6086
+ (method as any).protocolV2LatestFinalDeviceInfo = {
6087
+ main_mcu: {
6088
+ application: { version: '1.0.0' },
6089
+ application_data: { version: '2.0.1' },
6090
+ },
6091
+ };
6092
+
6093
+ expect(() => (method as any).assertExpectedProtocolV2Versions()).toThrow(
6094
+ 'target app_v2 reached 2.0.1, expected 2.0.0'
6095
+ );
6096
+ });
6097
+
5971
6098
  test('rejects unobservable multi-app versions without per-target completion evidence', () => {
5972
6099
  const method = new FirmwareUpdateV4({
5973
6100
  id: 1,
@@ -6096,7 +6223,7 @@ describe('Protocol V2 firmware update targets', () => {
6096
6223
  ])
6097
6224
  ).rejects.toMatchObject({
6098
6225
  errorCode: HardwareErrorCode.FirmwareError,
6099
- message: 'Firmware installation failed',
6226
+ message: 'Protocol V2 firmware install timed out',
6100
6227
  params: { firmwareUpdateCode: 'FirmwareInstallTimeout' },
6101
6228
  });
6102
6229
  expect(typedCall).toHaveBeenCalledTimes(5);
@@ -6173,7 +6300,7 @@ describe('Protocol V2 firmware update targets', () => {
6173
6300
  ])
6174
6301
  ).rejects.toMatchObject({
6175
6302
  errorCode: HardwareErrorCode.FirmwareError,
6176
- message: 'Firmware installation failed',
6303
+ message: 'Protocol V2 firmware install timed out',
6177
6304
  params: { firmwareUpdateCode: 'FirmwareInstallTimeout' },
6178
6305
  });
6179
6306
  });
@@ -6253,7 +6380,7 @@ describe('Protocol V2 firmware update targets', () => {
6253
6380
  ],
6254
6381
  new Set([4, 10])
6255
6382
  )
6256
- ).toThrow('Firmware installation failed');
6383
+ ).toThrow('Protocol V2 firmware install status conflict');
6257
6384
  expect(method.postProgressMessage).not.toHaveBeenCalled();
6258
6385
  expect(method.postProgressMessage).not.toHaveBeenCalledWith(100, 'installingFirmware');
6259
6386
 
@@ -6293,7 +6420,7 @@ describe('Protocol V2 firmware update targets', () => {
6293
6420
  throw new Error('Expected Protocol V2 failed firmware status to throw');
6294
6421
  } catch (error: any) {
6295
6422
  expect(error.errorCode).toBe(HardwareErrorCode.FirmwareError);
6296
- expect(error.message).toBe('Firmware installation failed');
6423
+ expect(error.message).toBe('Protocol V2 firmware install failed');
6297
6424
  expect(error.params).toEqual({ firmwareUpdateCode: 'FirmwareInstallFailed' });
6298
6425
  }
6299
6426
  });
@@ -6331,7 +6458,7 @@ describe('Protocol V2 firmware update targets', () => {
6331
6458
  ])
6332
6459
  ).rejects.toMatchObject({
6333
6460
  errorCode: HardwareErrorCode.FirmwareError,
6334
- message: 'Firmware installation failed',
6461
+ message: 'Protocol V2 firmware install failed',
6335
6462
  params: { firmwareUpdateCode: 'FirmwareInstallFailed' },
6336
6463
  });
6337
6464
  expect(typedCall).toHaveBeenCalledWith(
@@ -6859,6 +6986,9 @@ describe('Protocol V2 firmware update targets', () => {
6859
6986
  method: 'firmwareUpdateV4',
6860
6987
  platform: 'web',
6861
6988
  targetsToUpdate: ['app_v1', 'coprocessor'],
6989
+ expectedTargetVersions: {
6990
+ app_v1: '9.9.9',
6991
+ },
6862
6992
  },
6863
6993
  });
6864
6994
  method.init();
@@ -6877,12 +7007,14 @@ describe('Protocol V2 firmware update targets', () => {
6877
7007
  applicationP1: {
6878
7008
  target: 'APPLICATION_P1',
6879
7009
  url: 'https://example.com/applicationP1.pp.bin',
7010
+ version: [2, 0, 0],
6880
7011
  expectedSize: explicitApplicationBinary.byteLength,
6881
7012
  fingerprint: bytesToHex(sha256(new Uint8Array(explicitApplicationBinary))),
6882
7013
  },
6883
7014
  coprocessor: {
6884
7015
  target: 'COPROCESSOR',
6885
7016
  url: 'https://example.com/coprocessor.pp.bin',
7017
+ version: [1, 1, 0],
6886
7018
  expectedSize: remoteCoprocessorBinary.byteLength,
6887
7019
  fingerprint: bytesToHex(sha256(new Uint8Array(remoteCoprocessorBinary))),
6888
7020
  },
@@ -6923,6 +7055,10 @@ describe('Protocol V2 firmware update targets', () => {
6923
7055
  kind: 'firmware',
6924
7056
  },
6925
7057
  ]);
7058
+ expect((method as any).params.expectedTargetVersions).toEqual({
7059
+ app_v1: '9.9.9',
7060
+ coprocessor: '1.1.0',
7061
+ });
6926
7062
 
6927
7063
  getSysResourceBinarySpy.mockRestore();
6928
7064
  getFirmwareLatestReleaseSpy.mockRestore();
@@ -8139,6 +8275,66 @@ describe('Protocol V2 firmware update targets', () => {
8139
8275
  });
8140
8276
  });
8141
8277
 
8278
+ test('throttles repeated transfer progress while preserving file completion', async () => {
8279
+ const method = new FirmwareUpdateV4({
8280
+ id: 1,
8281
+ payload: {
8282
+ method: 'firmwareUpdateV4',
8283
+ },
8284
+ });
8285
+ const typedCall = jest.fn(
8286
+ (
8287
+ _name: string,
8288
+ _resType: string,
8289
+ params: { file: { offset: number; data: { byteLength: number } } }
8290
+ ) =>
8291
+ Promise.resolve({
8292
+ type: 'FilesystemFile',
8293
+ message: {
8294
+ processed_byte: params.file.offset + params.file.data.byteLength,
8295
+ },
8296
+ })
8297
+ );
8298
+
8299
+ (method as any).device = stubDevice({
8300
+ getCommands: () => ({ typedCall }),
8301
+ getCurrentDeviceType: () => 'pro2',
8302
+ });
8303
+ (method as any).getProtocolV2FirmwareChunkSize = jest.fn().mockReturnValue(1000);
8304
+ method.postProgressMessage = jest.fn();
8305
+ const dateNowSpy = jest.spyOn(Date, 'now').mockReturnValue(10_000);
8306
+
8307
+ const source = await openFirmwareByteSource({
8308
+ binary: new Uint8Array(2500).buffer,
8309
+ });
8310
+ try {
8311
+ await (method as any).protocolV2SourceUpdateProcess({
8312
+ source,
8313
+ filePath: 'vol0:/resource/images/images.okpkg',
8314
+ processedSize: 0,
8315
+ totalSize: 1_000_000,
8316
+ });
8317
+ } finally {
8318
+ dateNowSpy.mockRestore();
8319
+ await source?.close();
8320
+ }
8321
+
8322
+ expect(typedCall).toHaveBeenCalledTimes(3);
8323
+ expect(method.postProgressMessage).toHaveBeenCalledTimes(2);
8324
+ expect(method.postProgressMessage).toHaveBeenNthCalledWith(
8325
+ 1,
8326
+ 1,
8327
+ 'transferData',
8328
+ expect.objectContaining({ transferredBytes: 1000 })
8329
+ );
8330
+ expect(method.postProgressMessage).toHaveBeenNthCalledWith(
8331
+ 2,
8332
+ 1,
8333
+ 'transferData',
8334
+ expect.objectContaining({ transferredBytes: 2500 })
8335
+ );
8336
+ });
8337
+
8142
8338
  test('sends one monotonic device transfer progress range across multiple files', async () => {
8143
8339
  const method = new FirmwareUpdateV4({
8144
8340
  id: 1,
@@ -15,8 +15,11 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
15
15
  private protocolV2CompletedTargetVersions;
16
16
  private protocolV2CompletedTargetIds;
17
17
  private protocolV2LatestFinalFeatures?;
18
+ private protocolV2LatestFinalDeviceInfo?;
18
19
  private protocolV2InstallBaselineVersions;
19
20
  private protocolV2LastRuntimeProbeFeatures?;
21
+ private protocolV2LastTransferProgress?;
22
+ private protocolV2LastTransferProgressAt;
20
23
  init(): void;
21
24
  private getProtocolV2FirmwareChunkSize;
22
25
  run(): Promise<{
@@ -76,6 +79,7 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
76
79
  private getProtocolV2MissingTargetIds;
77
80
  private getProtocolV2ObservableTargetVersions;
78
81
  private hasProtocolV2InstallVersionChanged;
82
+ private recordProtocolV2AuthoritativeInstallCompletion;
79
83
  private waitForProtocolV2FirmwareUpdateComplete;
80
84
  private exitProtocolV2BootloaderToNormal;
81
85
  private probeProtocolV2NormalMode;
@@ -1 +1 @@
1
- {"version":3,"file":"FirmwareUpdateV4.d.ts","sourceRoot":"","sources":["../../src/api/FirmwareUpdateV4.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"FirmwareUpdateV4.d.ts","sourceRoot":"","sources":["../../src/api/FirmwareUpdateV4.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAkD,MAAM,qBAAqB,CAAC;AA0BlG,OAAO,EAAE,wBAAwB,EAAE,MAAM,qCAAqC,CAAC;AAkC/E,OAAO,KAAK,EAEV,sBAAsB,EAEvB,MAAM,6BAA6B,CAAC;AAsFrC,wBAAgB,wCAAwC,CACtD,UAAU,EAAE,WAAW,GAAG,MAAM,GAAG,SAAS,EAC5C,MAAM,EAAE,sBAAsB,EAC9B,0BAA0B,UAAQ,QAiCnC;AAuVD,eAAO,MAAM,oCAAoC,WACvC,WAAW,GAAG,UAAU,eACnB,MAAM,GAAG,SAAS,YAKhC,CAAC;AAEF,eAAO,MAAM,iCAAiC,0BACrB,MAAM,uBACR,MAAM,iBACZ,MAAM,eACR,MAAM,SAsBpB,CAAC;AAUF,MAAM,CAAC,OAAO,OAAO,gBAAiB,SAAQ,wBAAwB,CAAC,sBAAsB,CAAC;IAC5F,OAAO,CAAC,8BAA8B,CAAC,CAAS;IAEhD,OAAO,CAAC,sBAAsB,CAAC,CAAS;IAExC,OAAO,CAAC,oCAAoC,CAAS;IAErD,qBAAqB;IAIrB,OAAO,CAAC,yBAAyB,CAA4B;IAE7D,OAAO,CAAC,2BAA2B,CAAS;IAE5C,OAAO,CAAC,iCAAiC,CAAS;IAElD,OAAO,CAAC,iCAAiC,CAA6B;IAEtE,OAAO,CAAC,4BAA4B,CAAqB;IAEzD,OAAO,CAAC,6BAA6B,CAAC,CAAW;IAEjD,OAAO,CAAC,+BAA+B,CAAC,CAAuB;IAE/D,OAAO,CAAC,iCAAiC,CAA6B;IAEtE,OAAO,CAAC,kCAAkC,CAAC,CAAW;IAEtD,OAAO,CAAC,8BAA8B,CAAC,CAAS;IAEhD,OAAO,CAAC,gCAAgC,CAAK;IAE7C,IAAI;IA6LJ,OAAO,CAAC,8BAA8B;IAwBhC,GAAG;;;;;YAKK,aAAa;YAyJb,4BAA4B;YAkB5B,0BAA0B;YAY1B,8BAA8B;YAK9B,+BAA+B;YAqG/B,gCAAgC;YAiIhC,qCAAqC;YAmJrC,gCAAgC;YAgBhC,uCAAuC;YA+HvC,8BAA8B;IA8B5C,OAAO,CAAC,8BAA8B;IA0BtC,OAAO,CAAC,kCAAkC;IAc1C,OAAO,CAAC,gCAAgC;IAiExC,OAAO,CAAC,6BAA6B;YAsBvB,2BAA2B;IAmBzC,OAAO,CAAC,yBAAyB;IAKjC,OAAO,CAAC,oCAAoC;IAY5C,OAAO,CAAC,4BAA4B;IAUpC,OAAO,CAAC,kCAAkC;IAS1C,OAAO,CAAC,8BAA8B;YAMxB,iCAAiC;YAOjC,iCAAiC;YAmBjC,iCAAiC;IAM/C,OAAO,CAAC,uBAAuB;IAI/B,OAAO,CAAC,mCAAmC;IAe3C,OAAO,CAAC,iCAAiC;IAWzC,OAAO,CAAC,2BAA2B;IAsBnC,OAAO,CAAC,yBAAyB;IAiBjC,OAAO,CAAC,wBAAwB;YAkBlB,iCAAiC;YA6CjC,uCAAuC;YA0CvC,+BAA+B;IAmF7C,OAAO,CAAC,6BAA6B;YAMvB,8BAA8B;YA+C9B,kCAAkC;IA+BhD,OAAO,CAAC,0BAA0B;IAUlC,OAAO,CAAC,yBAAyB;YAcnB,4BAA4B;IAkBpC,6BAA6B;YAkBrB,+BAA+B;IAkD7C,OAAO,CAAC,6BAA6B;YAkCvB,6BAA6B;YA0B7B,0CAA0C;YA6B1C,uBAAuB;YAiCvB,8BAA8B;YA4E9B,6BAA6B;IA8E3C,OAAO,CAAC,mCAAmC;YAI7B,0BAA0B;IAaxC,OAAO,CAAC,4BAA4B;IA0GpC,OAAO,CAAC,6BAA6B;IAcrC,OAAO,CAAC,qCAAqC;IAyB7C,OAAO,CAAC,kCAAkC;IAgB1C,OAAO,CAAC,8CAA8C;YAIxC,uCAAuC;YAiNvC,gCAAgC;YAehC,yBAAyB;IASvC,OAAO,CAAC,2BAA2B;YAMrB,8BAA8B;IAQ5C,OAAO,CAAC,0BAA0B;YAkBpB,mCAAmC;YAWnC,qCAAqC;YAmDrC,yBAAyB;YA8DzB,8BAA8B;IAU5C,OAAO,CAAC,kCAAkC;YAQ5B,cAAc;YAuCd,6BAA6B;YAW7B,0BAA0B;YAS1B,6BAA6B;YAwB7B,gBAAgB;IAiB9B,OAAO,CAAC,qBAAqB;CAM9B"}
@@ -1 +1 @@
1
- {"version":3,"file":"Device.d.ts","sourceRoot":"","sources":["../../src/device/Device.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Device.d.ts","sourceRoot":"","sources":["../../src/device/Device.ts"],"names":[],"mappings":"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"}
@@ -14,7 +14,7 @@ export default class DeviceConnector {
14
14
  enumerate(): Promise<DeviceDescriptorDiff | undefined>;
15
15
  listen(): Promise<void>;
16
16
  stop(): void;
17
- acquire(path: string, session?: string | null, forceCleanRunPromise?: boolean, expectedProtocol?: HardwareConnectProtocol, protocolHint?: HardwareConnectProtocol): Promise<string | undefined>;
17
+ acquire(path: string, session?: string | null, forceCleanRunPromise?: boolean, expectedProtocol?: HardwareConnectProtocol, protocolHint?: HardwareConnectProtocol, forceProtocolDetection?: boolean): Promise<string | undefined>;
18
18
  release(session: string, onclose: boolean, keepSession?: boolean): Promise<void>;
19
19
  disconnect(session: string | undefined | null): Promise<void>;
20
20
  promptDeviceAccess(): Promise<USBDevice | BluetoothDevice | null>;
@@ -1 +1 @@
1
- {"version":3,"file":"DeviceConnector.d.ts","sourceRoot":"","sources":["../../src/device/DeviceConnector.ts"],"names":[],"mappings":";;AAUA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AACzD,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,qBAAqB,CAAC;AACnE,OAAO,KAAK,EAAE,gBAAgB,IAAI,gBAAgB,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAI9F,MAAM,CAAC,OAAO,OAAO,eAAe;IAClC,SAAS,CAAC,EAAE,SAAS,CAAC;IAEtB,eAAe,SAAK;IAEpB,OAAO,EAAE,gBAAgB,EAAE,GAAG,IAAI,CAAQ;IAE1C,QAAQ,EAAE,gBAAgB,EAAE,CAAM;IAElC,SAAS,UAAS;;IAQlB,OAAO,CAAC,kBAAkB;IAYpB,SAAS;IAWT,MAAM;IAgCZ,IAAI;IAIE,OAAO,CACX,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,EACvB,oBAAoB,CAAC,EAAE,OAAO,EAC9B,gBAAgB,CAAC,EAAE,uBAAuB,EAC1C,YAAY,CAAC,EAAE,uBAAuB;IAkDlC,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,WAAW,CAAC,EAAE,OAAO;IAShE,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI;IAWnD,kBAAkB,IAAI,OAAO,CAAC,SAAS,GAAG,eAAe,GAAG,IAAI,CAAC;IAQjE,oBAAoB;CAGrB"}
1
+ {"version":3,"file":"DeviceConnector.d.ts","sourceRoot":"","sources":["../../src/device/DeviceConnector.ts"],"names":[],"mappings":";;AAUA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AACzD,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,qBAAqB,CAAC;AACnE,OAAO,KAAK,EAAE,gBAAgB,IAAI,gBAAgB,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAI9F,MAAM,CAAC,OAAO,OAAO,eAAe;IAClC,SAAS,CAAC,EAAE,SAAS,CAAC;IAEtB,eAAe,SAAK;IAEpB,OAAO,EAAE,gBAAgB,EAAE,GAAG,IAAI,CAAQ;IAE1C,QAAQ,EAAE,gBAAgB,EAAE,CAAM;IAElC,SAAS,UAAS;;IAQlB,OAAO,CAAC,kBAAkB;IAYpB,SAAS;IAWT,MAAM;IAgCZ,IAAI;IAIE,OAAO,CACX,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,EACvB,oBAAoB,CAAC,EAAE,OAAO,EAC9B,gBAAgB,CAAC,EAAE,uBAAuB,EAC1C,YAAY,CAAC,EAAE,uBAAuB,EACtC,sBAAsB,CAAC,EAAE,OAAO;IAoD5B,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,WAAW,CAAC,EAAE,OAAO;IAShE,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI;IAWnD,kBAAkB,IAAI,OAAO,CAAC,SAAS,GAAG,eAAe,GAAG,IAAI,CAAC;IAQjE,oBAAoB;CAGrB"}
package/dist/index.d.ts CHANGED
@@ -713,7 +713,7 @@ declare class DeviceConnector {
713
713
  enumerate(): Promise<DeviceDescriptorDiff | undefined>;
714
714
  listen(): Promise<void>;
715
715
  stop(): void;
716
- acquire(path: string, session?: string | null, forceCleanRunPromise?: boolean, expectedProtocol?: HardwareConnectProtocol, protocolHint?: HardwareConnectProtocol): Promise<string | undefined>;
716
+ acquire(path: string, session?: string | null, forceCleanRunPromise?: boolean, expectedProtocol?: HardwareConnectProtocol, protocolHint?: HardwareConnectProtocol, forceProtocolDetection?: boolean): Promise<string | undefined>;
717
717
  release(session: string, onclose: boolean, keepSession?: boolean): Promise<void>;
718
718
  disconnect(session: string | undefined | null): Promise<void>;
719
719
  promptDeviceAccess(): Promise<USBDevice | BluetoothDevice | null>;
package/dist/index.js CHANGED
@@ -45243,12 +45243,12 @@ class Device extends events.exports {
45243
45243
  try {
45244
45244
  let acquireResult;
45245
45245
  if (DataManager.isBleConnect(env)) {
45246
- acquireResult = yield ((_a = this.deviceConnector) === null || _a === void 0 ? void 0 : _a.acquire(this.originalDescriptor.id, undefined, true, strictProtocol, undefined));
45246
+ acquireResult = yield ((_a = this.deviceConnector) === null || _a === void 0 ? void 0 : _a.acquire(this.originalDescriptor.id, undefined, true, strictProtocol, undefined, options === null || options === void 0 ? void 0 : options.forceProtocolDetection));
45247
45247
  this.mainId = (_b = acquireResult === null || acquireResult === void 0 ? void 0 : acquireResult.uuid) !== null && _b !== void 0 ? _b : '';
45248
45248
  Log$h.debug('Expected uuid:', this.mainId);
45249
45249
  }
45250
45250
  else {
45251
- acquireResult = yield ((_c = this.deviceConnector) === null || _c === void 0 ? void 0 : _c.acquire(this.originalDescriptor.path, this.originalDescriptor.session, undefined, strictProtocol, undefined));
45251
+ acquireResult = yield ((_c = this.deviceConnector) === null || _c === void 0 ? void 0 : _c.acquire(this.originalDescriptor.path, this.originalDescriptor.session, undefined, strictProtocol, undefined, options === null || options === void 0 ? void 0 : options.forceProtocolDetection));
45252
45252
  this.mainId = acquireResult;
45253
45253
  Log$h.debug('Expected session id:', this.mainId);
45254
45254
  }
@@ -45620,11 +45620,9 @@ class Device extends events.exports {
45620
45620
  yield TransportManager.reconfigure(this.features);
45621
45621
  });
45622
45622
  const expectedDeviceId = options === null || options === void 0 ? void 0 : options.deviceId;
45623
- if (expectedDeviceId) {
45623
+ if (expectedDeviceId && !(this.features && this.checkDeviceId(expectedDeviceId))) {
45624
45624
  this.passphraseState = undefined;
45625
- const { message } = yield this.commands.typedCall('GetFeatures', 'Features', {});
45626
- this._updateFeatures(message);
45627
- yield TransportManager.reconfigure(this.features);
45625
+ yield callInitialize({ is_contains_attach: true });
45628
45626
  if (!this.checkDeviceId(expectedDeviceId)) {
45629
45627
  throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.DeviceCheckDeviceIdError);
45630
45628
  }
@@ -45644,7 +45642,23 @@ class Device extends events.exports {
45644
45642
  if (options === null || options === void 0 ? void 0 : options.deriveCardano) {
45645
45643
  payload.derive_cardano = true;
45646
45644
  }
45647
- yield callInitialize(payload, options === null || options === void 0 ? void 0 : options.initSession);
45645
+ if (this.features) {
45646
+ yield TransportManager.reconfigure(this.features);
45647
+ }
45648
+ const assertExpectedDeviceIdentity = () => {
45649
+ if (expectedDeviceId && !this.checkDeviceId(expectedDeviceId)) {
45650
+ this.clearInternalState();
45651
+ throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.DeviceCheckDeviceIdError);
45652
+ }
45653
+ };
45654
+ try {
45655
+ yield callInitialize(payload, options === null || options === void 0 ? void 0 : options.initSession);
45656
+ }
45657
+ catch (error) {
45658
+ assertExpectedDeviceIdentity();
45659
+ throw error;
45660
+ }
45661
+ assertExpectedDeviceIdentity();
45648
45662
  }
45649
45663
  catch (error) {
45650
45664
  Log$h.error('Initialization failed:', error);
@@ -51753,6 +51767,7 @@ const PROTOCOL_V2_CONNECT_POLL_INTERVAL = 500;
51753
51767
  const PROTOCOL_V2_CONNECT_SINGLE_TIMEOUT = 75 * 1000;
51754
51768
  const PROTOCOL_V2_DEVICE_INFO_READY_TIMEOUT = 30 * 1000;
51755
51769
  const PROTOCOL_V2_FILE_TRANSFER_RETRY_COUNT = 3;
51770
+ const PROTOCOL_V2_TRANSFER_PROGRESS_HEARTBEAT_MS = 1000;
51756
51771
  const PROTOCOL_V2_INSTALL_STATUS_CONFLICT_CODE = 'FirmwareInstallStatusConflict';
51757
51772
  const PROTOCOL_V2_INSTALL_FAILED_CODE = 'FirmwareInstallFailed';
51758
51773
  const PROTOCOL_V2_INSTALL_TIMEOUT_CODE = 'FirmwareInstallTimeout';
@@ -52045,6 +52060,7 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
52045
52060
  this.protocolV2CompletedTargetVersions = new Map();
52046
52061
  this.protocolV2CompletedTargetIds = new Set();
52047
52062
  this.protocolV2InstallBaselineVersions = new Map();
52063
+ this.protocolV2LastTransferProgressAt = 0;
52048
52064
  }
52049
52065
  getSupportedProtocols() {
52050
52066
  return ['V2'];
@@ -52762,27 +52778,30 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
52762
52778
  return parts[0] * 0x10000 + parts[1] * 0x100 + parts[2];
52763
52779
  }
52764
52780
  assertExpectedProtocolV2Versions(targets) {
52765
- var _a, _b, _c, _d, _e, _f;
52781
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
52766
52782
  const expected = (_a = this.params) === null || _a === void 0 ? void 0 : _a.expectedTargetVersions;
52767
52783
  if (!expected)
52768
52784
  return;
52769
52785
  const features = this.protocolV2LatestFinalFeatures;
52786
+ const deviceInfo = this.protocolV2LatestFinalDeviceInfo;
52770
52787
  const requestedTargets = this.getProtocolV2RequestedTargets();
52771
52788
  const applicationTargets = requestedTargets.filter(target => target === 'app_v1' || target === 'app_v2');
52772
52789
  const visibleVersions = {
52773
52790
  boot: features ? getDeviceBootloaderVersion(features).join('.') : undefined,
52791
+ app_v1: (_c = (_b = deviceInfo === null || deviceInfo === void 0 ? void 0 : deviceInfo.main_mcu) === null || _b === void 0 ? void 0 : _b.application) === null || _c === void 0 ? void 0 : _c.version,
52792
+ app_v2: (_e = (_d = deviceInfo === null || deviceInfo === void 0 ? void 0 : deviceInfo.main_mcu) === null || _d === void 0 ? void 0 : _d.application_data) === null || _e === void 0 ? void 0 : _e.version,
52774
52793
  coprocessor: features ? getDeviceBLEFirmwareVersion(features).join('.') : undefined,
52775
- se01: (_b = features === null || features === void 0 ? void 0 : features.se01Version) !== null && _b !== void 0 ? _b : undefined,
52776
- se02: (_c = features === null || features === void 0 ? void 0 : features.se02Version) !== null && _c !== void 0 ? _c : undefined,
52777
- se03: (_d = features === null || features === void 0 ? void 0 : features.se03Version) !== null && _d !== void 0 ? _d : undefined,
52778
- se04: (_e = features === null || features === void 0 ? void 0 : features.se04Version) !== null && _e !== void 0 ? _e : undefined,
52794
+ se01: (_f = features === null || features === void 0 ? void 0 : features.se01Version) !== null && _f !== void 0 ? _f : undefined,
52795
+ se02: (_g = features === null || features === void 0 ? void 0 : features.se02Version) !== null && _g !== void 0 ? _g : undefined,
52796
+ se03: (_h = features === null || features === void 0 ? void 0 : features.se03Version) !== null && _h !== void 0 ? _h : undefined,
52797
+ se04: (_j = features === null || features === void 0 ? void 0 : features.se04Version) !== null && _j !== void 0 ? _j : undefined,
52779
52798
  };
52780
- if (features && applicationTargets.length === 1) {
52799
+ if (features && applicationTargets.length === 1 && !visibleVersions[applicationTargets[0]]) {
52781
52800
  visibleVersions[applicationTargets[0]] = getDeviceFirmwareVersion(features).join('.');
52782
52801
  }
52783
52802
  const expectedEntries = Object.entries(expected).filter(([target]) => !targets || targets.includes(target));
52784
52803
  for (const [target, expectedVersion] of expectedEntries) {
52785
- const targetId = (_f = Array.from(PROTOCOL_V2_UPDATE_TARGET_BY_TARGET_ID.entries()).find(([, mappedTarget]) => mappedTarget === target)) === null || _f === void 0 ? void 0 : _f[0];
52804
+ const targetId = (_k = Array.from(PROTOCOL_V2_UPDATE_TARGET_BY_TARGET_ID.entries()).find(([, mappedTarget]) => mappedTarget === target)) === null || _k === void 0 ? void 0 : _k[0];
52786
52805
  const statusVersion = targetId === undefined ? undefined : this.protocolV2CompletedTargetVersions.get(targetId);
52787
52806
  const observedVersion = statusVersion === undefined
52788
52807
  ? visibleVersions[target]
@@ -53066,12 +53085,15 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
53066
53085
  ? PROTOCOL_V2_UPDATE_TARGET_BY_TARGET_ID.get(target.targetId)
53067
53086
  : undefined;
53068
53087
  if (updateTarget && targetsToUpdate.has(updateTarget)) {
53069
- if (component.version) {
53070
- (_c = (_d = this.params).expectedTargetVersions) !== null && _c !== void 0 ? _c : (_d.expectedTargetVersions = {});
53071
- this.params.expectedTargetVersions[updateTarget] = component.version.join('.');
53072
- }
53073
53088
  const explicitInstallItem = explicitInstallItemByTargetId.get(target.targetId);
53074
- const installItem = explicitInstallItem !== null && explicitInstallItem !== void 0 ? explicitInstallItem : (yield this.downloadRemoteProtocolV2Component(key, component));
53089
+ let installItem = explicitInstallItem;
53090
+ if (!installItem) {
53091
+ installItem = yield this.downloadRemoteProtocolV2Component(key, component);
53092
+ if (component.version) {
53093
+ (_c = (_d = this.params).expectedTargetVersions) !== null && _c !== void 0 ? _c : (_d.expectedTargetVersions = {});
53094
+ this.params.expectedTargetVersions[updateTarget] = component.version.join('.');
53095
+ }
53096
+ }
53075
53097
  if (installItem.kind === 'bootloader') {
53076
53098
  bootloaderBinary = installItem.binary;
53077
53099
  }
@@ -53369,6 +53391,8 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
53369
53391
  }
53370
53392
  }
53371
53393
  this.postTipMessage(exports.FirmwareUpdateTipMessage.StartTransferData);
53394
+ this.protocolV2LastTransferProgress = undefined;
53395
+ this.protocolV2LastTransferProgressAt = 0;
53372
53396
  let processedSize = 0;
53373
53397
  for (const resource of resourcesToSync) {
53374
53398
  const writePath = resolveProtocolV2ResourceWritePath(resource.devicePath);
@@ -53438,13 +53462,23 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
53438
53462
  throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.EmmcFileWriteFirmwareError, `invalid processed_byte ${rawProcessedByte} for offset ${sourceOffset}`);
53439
53463
  }
53440
53464
  const transferredBytes = processedSize + chunkEnd;
53441
- const elapsedMs = Math.max(Date.now() - transferStartedAt, 0);
53442
- this.postProgressMessage(Math.min(Math.ceil((transferredBytes / totalSize) * 100), 99), 'transferData', {
53443
- transferredBytes,
53444
- totalBytes: totalSize,
53445
- rateBytesPerSecond: elapsedMs > 0 ? Math.round((chunkEnd / elapsedMs) * 1000) : undefined,
53446
- elapsedMs,
53447
- });
53465
+ const now = Date.now();
53466
+ const elapsedMs = Math.max(now - transferStartedAt, 0);
53467
+ const progress = Math.min(Math.ceil((transferredBytes / totalSize) * 100), 99);
53468
+ const shouldPostProgress = progress !== this.protocolV2LastTransferProgress ||
53469
+ now - this.protocolV2LastTransferProgressAt >=
53470
+ PROTOCOL_V2_TRANSFER_PROGRESS_HEARTBEAT_MS ||
53471
+ chunkEnd === source.size;
53472
+ if (shouldPostProgress) {
53473
+ this.protocolV2LastTransferProgress = progress;
53474
+ this.protocolV2LastTransferProgressAt = now;
53475
+ this.postProgressMessage(progress, 'transferData', {
53476
+ transferredBytes,
53477
+ totalBytes: totalSize,
53478
+ rateBytesPerSecond: elapsedMs > 0 ? Math.round((chunkEnd / elapsedMs) * 1000) : undefined,
53479
+ elapsedMs,
53480
+ });
53481
+ }
53448
53482
  return length;
53449
53483
  }),
53450
53484
  });
@@ -53489,7 +53523,7 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
53489
53523
  path: failedTarget.path,
53490
53524
  });
53491
53525
  Log$7.error(`[FirmwareUpdateV4] firmware install failed target=${failedTargetDetails}`);
53492
- throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.FirmwareError, undefined, {
53526
+ throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.FirmwareError, 'Protocol V2 firmware install failed', {
53493
53527
  firmwareUpdateCode: PROTOCOL_V2_INSTALL_FAILED_CODE,
53494
53528
  });
53495
53529
  }
@@ -53501,7 +53535,7 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
53501
53535
  seenTargetIds.has(targetId) ||
53502
53536
  (target.path && expectedPaths.get(targetId) && target.path !== expectedPaths.get(targetId))) {
53503
53537
  Log$7.error(`[FirmwareUpdateV4] install status conflicts with target=${target.target_id}`);
53504
- throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.FirmwareError, undefined, {
53538
+ throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.FirmwareError, 'Protocol V2 firmware install status conflict', {
53505
53539
  firmwareUpdateCode: PROTOCOL_V2_INSTALL_STATUS_CONFLICT_CODE,
53506
53540
  });
53507
53541
  }
@@ -53585,6 +53619,9 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
53585
53619
  previousVersion !== currentVersion);
53586
53620
  });
53587
53621
  }
53622
+ recordProtocolV2AuthoritativeInstallCompletion(expectedTargetIds) {
53623
+ expectedTargetIds.forEach(targetId => this.protocolV2CompletedTargetIds.add(targetId));
53624
+ }
53588
53625
  waitForProtocolV2FirmwareUpdateComplete(targets, requireCurrentInstallStatus = false) {
53589
53626
  var _a, _b;
53590
53627
  return __awaiter(this, void 0, void 0, function* () {
@@ -53657,6 +53694,7 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
53657
53694
  (installEvidenceObserved ||
53658
53695
  this.hasProtocolV2InstallVersionChanged(expectedTargetIds))) {
53659
53696
  Log$7.log('[FirmwareUpdateV4] empty firmware status after confirmed App reboot; update complete');
53697
+ this.recordProtocolV2AuthoritativeInstallCompletion(expectedTargetIds);
53660
53698
  this.postProgressMessage(100, 'installingFirmware');
53661
53699
  return;
53662
53700
  }
@@ -53690,6 +53728,7 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
53690
53728
  (installEvidenceObserved ||
53691
53729
  this.hasProtocolV2InstallVersionChanged(expectedTargetIds))) {
53692
53730
  Log$7.log('[FirmwareUpdateV4] firmware status endpoint unavailable after confirmed App reboot');
53731
+ this.recordProtocolV2AuthoritativeInstallCompletion(expectedTargetIds);
53693
53732
  this.postProgressMessage(100, 'installingFirmware');
53694
53733
  return;
53695
53734
  }
@@ -53727,7 +53766,7 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
53727
53766
  yield hdShared.wait(1000);
53728
53767
  }
53729
53768
  Log$7.error(`[FirmwareUpdateV4] install timed out after ${PROTOCOL_V2_INSTALL_TIMEOUT / 1000}s: ${this.normalizeErrorMessage(lastError)}`);
53730
- throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.FirmwareError, undefined, {
53769
+ throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.FirmwareError, 'Protocol V2 firmware install timed out', {
53731
53770
  firmwareUpdateCode: PROTOCOL_V2_INSTALL_TIMEOUT_CODE,
53732
53771
  });
53733
53772
  });
@@ -53796,6 +53835,7 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
53796
53835
  const startTime = Date.now();
53797
53836
  let lastError;
53798
53837
  let shouldReconnect = true;
53838
+ this.protocolV2LatestFinalDeviceInfo = undefined;
53799
53839
  while (Date.now() - startTime < timeout) {
53800
53840
  try {
53801
53841
  if (shouldReconnect) {
@@ -53810,6 +53850,7 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
53810
53850
  this.assertProtocolV2DeviceInfoIdentity(deviceInfo);
53811
53851
  const features = yield this.device.probeProtocolV2RuntimeState(deviceInfo, PROTOCOL_V2_SHORT_RESPONSE_TIMEOUT, { forceRuntimeContextRefresh: true });
53812
53852
  if (this.isProtocolV2ApplicationMode(features)) {
53853
+ this.protocolV2LatestFinalDeviceInfo = deviceInfo;
53813
53854
  return features;
53814
53855
  }
53815
53856
  lastError = hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.DeviceNotFound, 'Protocol V2 device is still in bootloader mode');
@@ -64749,7 +64790,7 @@ class DeviceConnector {
64749
64790
  stop() {
64750
64791
  this.listening = false;
64751
64792
  }
64752
- acquire(path, session, forceCleanRunPromise, expectedProtocol, protocolHint) {
64793
+ acquire(path, session, forceCleanRunPromise, expectedProtocol, protocolHint, forceProtocolDetection) {
64753
64794
  return __awaiter(this, void 0, void 0, function* () {
64754
64795
  Log$2.debug('acquire', path, session, expectedProtocol, protocolHint);
64755
64796
  const env = DataManager.getSettings('env');
@@ -64762,6 +64803,7 @@ class DeviceConnector {
64762
64803
  forceCleanRunPromise,
64763
64804
  expectedProtocol,
64764
64805
  protocolHint,
64806
+ forceProtocolDetection,
64765
64807
  });
64766
64808
  }
64767
64809
  else {
@@ -64770,6 +64812,7 @@ class DeviceConnector {
64770
64812
  previous: session !== null && session !== void 0 ? session : null,
64771
64813
  expectedProtocol,
64772
64814
  protocolHint,
64815
+ forceProtocolDetection,
64773
64816
  });
64774
64817
  }
64775
64818
  if (expectedProtocol) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@onekeyfe/hd-core",
3
- "version": "1.2.0-alpha.140",
3
+ "version": "1.2.0-alpha.141",
4
4
  "description": "Core processes and APIs for communicating with OneKey hardware devices.",
5
5
  "author": "OneKey",
6
6
  "homepage": "https://github.com/OneKeyHQ/hardware-js-sdk#readme",
@@ -25,8 +25,8 @@
25
25
  "url": "https://github.com/OneKeyHQ/hardware-js-sdk/issues"
26
26
  },
27
27
  "dependencies": {
28
- "@onekeyfe/hd-shared": "1.2.0-alpha.140",
29
- "@onekeyfe/hd-transport": "1.2.0-alpha.140",
28
+ "@onekeyfe/hd-shared": "1.2.0-alpha.141",
29
+ "@onekeyfe/hd-transport": "1.2.0-alpha.141",
30
30
  "axios": "1.15.2",
31
31
  "bignumber.js": "^9.0.2",
32
32
  "buffer": "^6.0.3",
@@ -46,5 +46,5 @@
46
46
  "@types/w3c-web-usb": "^1.0.10",
47
47
  "@types/web-bluetooth": "^0.0.21"
48
48
  },
49
- "gitHead": "15e3f0dc6c543c83a96e63b5d19aad70cdd6efb1"
49
+ "gitHead": "2fdadf97749fea76cf47f5b1899f18050abe01d1"
50
50
  }
@@ -105,6 +105,7 @@ const PROTOCOL_V2_CONNECT_POLL_INTERVAL = 500;
105
105
  const PROTOCOL_V2_CONNECT_SINGLE_TIMEOUT = 75 * 1000;
106
106
  const PROTOCOL_V2_DEVICE_INFO_READY_TIMEOUT = 30 * 1000;
107
107
  const PROTOCOL_V2_FILE_TRANSFER_RETRY_COUNT = 3;
108
+ const PROTOCOL_V2_TRANSFER_PROGRESS_HEARTBEAT_MS = 1000;
108
109
  const PROTOCOL_V2_INSTALL_STATUS_CONFLICT_CODE = 'FirmwareInstallStatusConflict';
109
110
  const PROTOCOL_V2_INSTALL_FAILED_CODE = 'FirmwareInstallFailed';
110
111
  const PROTOCOL_V2_INSTALL_TIMEOUT_CODE = 'FirmwareInstallTimeout';
@@ -594,10 +595,16 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
594
595
 
595
596
  private protocolV2LatestFinalFeatures?: Features;
596
597
 
598
+ private protocolV2LatestFinalDeviceInfo?: ProtocolV2DeviceInfo;
599
+
597
600
  private protocolV2InstallBaselineVersions = new Map<number, string>();
598
601
 
599
602
  private protocolV2LastRuntimeProbeFeatures?: Features;
600
603
 
604
+ private protocolV2LastTransferProgress?: number;
605
+
606
+ private protocolV2LastTransferProgressAt = 0;
607
+
601
608
  init() {
602
609
  this.allowDeviceMode = [UI_REQUEST.BOOTLOADER, UI_REQUEST.NOT_INITIALIZE];
603
610
  this.requireDeviceMode = [];
@@ -1598,19 +1605,22 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
1598
1605
  const expected = this.params?.expectedTargetVersions;
1599
1606
  if (!expected) return;
1600
1607
  const features = this.protocolV2LatestFinalFeatures;
1608
+ const deviceInfo = this.protocolV2LatestFinalDeviceInfo;
1601
1609
  const requestedTargets = this.getProtocolV2RequestedTargets();
1602
1610
  const applicationTargets = requestedTargets.filter(
1603
1611
  target => target === 'app_v1' || target === 'app_v2'
1604
1612
  );
1605
1613
  const visibleVersions: Partial<Record<FirmwareUpdateV4Target, string>> = {
1606
1614
  boot: features ? getDeviceBootloaderVersion(features).join('.') : undefined,
1615
+ app_v1: deviceInfo?.main_mcu?.application?.version,
1616
+ app_v2: deviceInfo?.main_mcu?.application_data?.version,
1607
1617
  coprocessor: features ? getDeviceBLEFirmwareVersion(features).join('.') : undefined,
1608
1618
  se01: features?.se01Version ?? undefined,
1609
1619
  se02: features?.se02Version ?? undefined,
1610
1620
  se03: features?.se03Version ?? undefined,
1611
1621
  se04: features?.se04Version ?? undefined,
1612
1622
  };
1613
- if (features && applicationTargets.length === 1) {
1623
+ if (features && applicationTargets.length === 1 && !visibleVersions[applicationTargets[0]]) {
1614
1624
  visibleVersions[applicationTargets[0]] = getDeviceFirmwareVersion(features).join('.');
1615
1625
  }
1616
1626
  const expectedEntries = (
@@ -1987,13 +1997,15 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
1987
1997
  ? PROTOCOL_V2_UPDATE_TARGET_BY_TARGET_ID.get(target.targetId)
1988
1998
  : undefined;
1989
1999
  if (updateTarget && targetsToUpdate.has(updateTarget)) {
1990
- if (component.version) {
1991
- this.params.expectedTargetVersions ??= {};
1992
- this.params.expectedTargetVersions[updateTarget] = component.version.join('.');
1993
- }
1994
2000
  const explicitInstallItem = explicitInstallItemByTargetId.get(target.targetId);
1995
- const installItem =
1996
- explicitInstallItem ?? (await this.downloadRemoteProtocolV2Component(key, component));
2001
+ let installItem = explicitInstallItem;
2002
+ if (!installItem) {
2003
+ installItem = await this.downloadRemoteProtocolV2Component(key, component);
2004
+ if (component.version) {
2005
+ this.params.expectedTargetVersions ??= {};
2006
+ this.params.expectedTargetVersions[updateTarget] = component.version.join('.');
2007
+ }
2008
+ }
1997
2009
  if (installItem.kind === 'bootloader') {
1998
2010
  bootloaderBinary = installItem.binary;
1999
2011
  } else {
@@ -2362,6 +2374,8 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
2362
2374
  }
2363
2375
 
2364
2376
  this.postTipMessage(FirmwareUpdateTipMessage.StartTransferData);
2377
+ this.protocolV2LastTransferProgress = undefined;
2378
+ this.protocolV2LastTransferProgressAt = 0;
2365
2379
  let processedSize = 0;
2366
2380
  for (const resource of resourcesToSync) {
2367
2381
  // The bootloader keeps its live resource package mounted. FatFs rejects
@@ -2458,18 +2472,25 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
2458
2472
  );
2459
2473
  }
2460
2474
  const transferredBytes = processedSize + chunkEnd;
2461
- const elapsedMs = Math.max(Date.now() - transferStartedAt, 0);
2462
- this.postProgressMessage(
2463
- Math.min(Math.ceil((transferredBytes / totalSize) * 100), 99),
2464
- 'transferData',
2465
- {
2475
+ const now = Date.now();
2476
+ const elapsedMs = Math.max(now - transferStartedAt, 0);
2477
+ const progress = Math.min(Math.ceil((transferredBytes / totalSize) * 100), 99);
2478
+ const shouldPostProgress =
2479
+ progress !== this.protocolV2LastTransferProgress ||
2480
+ now - this.protocolV2LastTransferProgressAt >=
2481
+ PROTOCOL_V2_TRANSFER_PROGRESS_HEARTBEAT_MS ||
2482
+ chunkEnd === source.size;
2483
+ if (shouldPostProgress) {
2484
+ this.protocolV2LastTransferProgress = progress;
2485
+ this.protocolV2LastTransferProgressAt = now;
2486
+ this.postProgressMessage(progress, 'transferData', {
2466
2487
  transferredBytes,
2467
2488
  totalBytes: totalSize,
2468
2489
  rateBytesPerSecond:
2469
2490
  elapsedMs > 0 ? Math.round((chunkEnd / elapsedMs) * 1000) : undefined,
2470
2491
  elapsedMs,
2471
- }
2472
- );
2492
+ });
2493
+ }
2473
2494
  return length;
2474
2495
  },
2475
2496
  });
@@ -2525,9 +2546,13 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
2525
2546
  path: failedTarget.path,
2526
2547
  });
2527
2548
  Log.error(`[FirmwareUpdateV4] firmware install failed target=${failedTargetDetails}`);
2528
- throw ERRORS.TypedError(HardwareErrorCode.FirmwareError, undefined, {
2529
- firmwareUpdateCode: PROTOCOL_V2_INSTALL_FAILED_CODE,
2530
- });
2549
+ throw ERRORS.TypedError(
2550
+ HardwareErrorCode.FirmwareError,
2551
+ 'Protocol V2 firmware install failed',
2552
+ {
2553
+ firmwareUpdateCode: PROTOCOL_V2_INSTALL_FAILED_CODE,
2554
+ }
2555
+ );
2531
2556
  }
2532
2557
 
2533
2558
  const matchingTargets = statusTargets.filter(target =>
@@ -2542,9 +2567,13 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
2542
2567
  (target.path && expectedPaths.get(targetId) && target.path !== expectedPaths.get(targetId))
2543
2568
  ) {
2544
2569
  Log.error(`[FirmwareUpdateV4] install status conflicts with target=${target.target_id}`);
2545
- throw ERRORS.TypedError(HardwareErrorCode.FirmwareError, undefined, {
2546
- firmwareUpdateCode: PROTOCOL_V2_INSTALL_STATUS_CONFLICT_CODE,
2547
- });
2570
+ throw ERRORS.TypedError(
2571
+ HardwareErrorCode.FirmwareError,
2572
+ 'Protocol V2 firmware install status conflict',
2573
+ {
2574
+ firmwareUpdateCode: PROTOCOL_V2_INSTALL_STATUS_CONFLICT_CODE,
2575
+ }
2576
+ );
2548
2577
  }
2549
2578
  seenTargetIds.add(targetId);
2550
2579
  }
@@ -2657,6 +2686,10 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
2657
2686
  });
2658
2687
  }
2659
2688
 
2689
+ private recordProtocolV2AuthoritativeInstallCompletion(expectedTargetIds: Set<number>) {
2690
+ expectedTargetIds.forEach(targetId => this.protocolV2CompletedTargetIds.add(targetId));
2691
+ }
2692
+
2660
2693
  private async waitForProtocolV2FirmwareUpdateComplete(
2661
2694
  targets: Array<{ target_id: number; path: string }>,
2662
2695
  requireCurrentInstallStatus = false
@@ -2760,6 +2793,7 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
2760
2793
  Log.log(
2761
2794
  '[FirmwareUpdateV4] empty firmware status after confirmed App reboot; update complete'
2762
2795
  );
2796
+ this.recordProtocolV2AuthoritativeInstallCompletion(expectedTargetIds);
2763
2797
  this.postProgressMessage(100, 'installingFirmware');
2764
2798
  return;
2765
2799
  }
@@ -2807,6 +2841,7 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
2807
2841
  Log.log(
2808
2842
  '[FirmwareUpdateV4] firmware status endpoint unavailable after confirmed App reboot'
2809
2843
  );
2844
+ this.recordProtocolV2AuthoritativeInstallCompletion(expectedTargetIds);
2810
2845
  this.postProgressMessage(100, 'installingFirmware');
2811
2846
  return;
2812
2847
  }
@@ -2855,9 +2890,13 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
2855
2890
  PROTOCOL_V2_INSTALL_TIMEOUT / 1000
2856
2891
  }s: ${this.normalizeErrorMessage(lastError)}`
2857
2892
  );
2858
- throw ERRORS.TypedError(HardwareErrorCode.FirmwareError, undefined, {
2859
- firmwareUpdateCode: PROTOCOL_V2_INSTALL_TIMEOUT_CODE,
2860
- });
2893
+ throw ERRORS.TypedError(
2894
+ HardwareErrorCode.FirmwareError,
2895
+ 'Protocol V2 firmware install timed out',
2896
+ {
2897
+ firmwareUpdateCode: PROTOCOL_V2_INSTALL_TIMEOUT_CODE,
2898
+ }
2899
+ );
2861
2900
  }
2862
2901
 
2863
2902
  private async exitProtocolV2BootloaderToNormal() {
@@ -2931,6 +2970,7 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
2931
2970
  const startTime = Date.now();
2932
2971
  let lastError: unknown;
2933
2972
  let shouldReconnect = true;
2973
+ this.protocolV2LatestFinalDeviceInfo = undefined;
2934
2974
 
2935
2975
  while (Date.now() - startTime < timeout) {
2936
2976
  try {
@@ -2951,6 +2991,7 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
2951
2991
  { forceRuntimeContextRefresh: true }
2952
2992
  );
2953
2993
  if (this.isProtocolV2ApplicationMode(features)) {
2994
+ this.protocolV2LatestFinalDeviceInfo = deviceInfo;
2954
2995
  return features;
2955
2996
  }
2956
2997
  lastError = ERRORS.TypedError(
@@ -449,7 +449,8 @@ export class Device extends EventEmitter {
449
449
  undefined,
450
450
  true,
451
451
  strictProtocol,
452
- undefined
452
+ undefined,
453
+ options?.forceProtocolDetection
453
454
  );
454
455
  this.mainId = (acquireResult as any)?.uuid ?? '';
455
456
  Log.debug('Expected uuid:', this.mainId);
@@ -459,7 +460,8 @@ export class Device extends EventEmitter {
459
460
  this.originalDescriptor.session,
460
461
  undefined,
461
462
  strictProtocol,
462
- undefined
463
+ undefined,
464
+ options?.forceProtocolDetection
463
465
  );
464
466
  this.mainId = acquireResult as string | undefined;
465
467
  Log.debug('Expected session id:', this.mainId);
@@ -930,13 +932,18 @@ export class Device extends EventEmitter {
930
932
  };
931
933
 
932
934
  const expectedDeviceId = options?.deviceId;
933
- if (expectedDeviceId) {
934
- // 先只读校验物理设备身份;钱包上下文仍由下方携带完整参数的
935
- // Initialize 选择,避免标准钱包请求复用此前的隐藏钱包上下文。
935
+
936
+ if (expectedDeviceId && !(this.features && this.checkDeviceId(expectedDeviceId))) {
937
+ // No locally-cached evidence that the device at this path is the
938
+ // expected one (first contact, or the cached features already disagree
939
+ // with the caller). Establish identity with a context-free Initialize
940
+ // BEFORE any wallet context (session_id / passphrase_state) goes on
941
+ // the wire. In normal flows features are always fresh — enumerate /
942
+ // getFeatures run first and every call response refreshes them — so
943
+ // this extra round trip is confined to the ambiguous cases where the
944
+ // disclosure risk actually lives.
936
945
  this.passphraseState = undefined;
937
- const { message } = await this.commands.typedCall('GetFeatures', 'Features', {});
938
- this._updateFeatures(message);
939
- await TransportManager.reconfigure(this.features);
946
+ await callInitialize({ is_contains_attach: true });
940
947
  if (!this.checkDeviceId(expectedDeviceId)) {
941
948
  throw ERRORS.TypedError(HardwareErrorCode.DeviceCheckDeviceIdError);
942
949
  }
@@ -960,7 +967,46 @@ export class Device extends EventEmitter {
960
967
  payload.derive_cardano = true;
961
968
  }
962
969
 
963
- await callInitialize(payload, options?.initSession);
970
+ if (this.features) {
971
+ // Re-sync the V1 message schema for THIS device before encoding
972
+ // Initialize: the process-global schema may still reflect another
973
+ // device (e.g. legacy-firmware Touch/Mini) on multi-device setups, and
974
+ // a stale legacy schema would silently strip passphrase_state /
975
+ // is_contains_attach from the wire message. Local operation, no wire
976
+ // I/O; a no-op when the schema is unchanged.
977
+ await TransportManager.reconfigure(this.features);
978
+ }
979
+
980
+ // Initialize's own Features response carries device_id, so the physical
981
+ // device identity is validated on the same round trip instead of via a
982
+ // separate read-only GetFeatures preflight (which doubled the wire cost
983
+ // of every deviceId-carrying call). The method fn has not run yet, so a
984
+ // mismatch still fails before any wallet data can be derived, with the
985
+ // same DeviceCheckDeviceIdError. Wallet-context selection is unchanged:
986
+ // it is decided by the Initialize payload above either way.
987
+ const assertExpectedDeviceIdentity = () => {
988
+ if (expectedDeviceId && !this.checkDeviceId(expectedDeviceId)) {
989
+ // The mismatched Initialize may have cached a session under the wrong
990
+ // device's identity; drop it so no wallet context survives from it.
991
+ // (This also evicts any session the wrong device legitimately cached
992
+ // under the same passphraseState — a deliberate conservative purge
993
+ // after a physical-swap event, consistent with
994
+ // reconcileDeviceIdentity purging the previous device's sessions.)
995
+ this.clearInternalState();
996
+ throw ERRORS.TypedError(HardwareErrorCode.DeviceCheckDeviceIdError);
997
+ }
998
+ };
999
+
1000
+ try {
1001
+ await callInitialize(payload, options?.initSession);
1002
+ } catch (error) {
1003
+ // callInitialize can fail AFTER the wire call cached the session (e.g.
1004
+ // TransportManager.reconfigure rejecting); the identity check must
1005
+ // still run so a wrong-device session never survives the error path.
1006
+ assertExpectedDeviceIdentity();
1007
+ throw error;
1008
+ }
1009
+ assertExpectedDeviceIdentity();
964
1010
  } catch (error) {
965
1011
  Log.error('Initialization failed:', error);
966
1012
  throw error;
@@ -95,7 +95,8 @@ export default class DeviceConnector {
95
95
  session?: string | null,
96
96
  forceCleanRunPromise?: boolean,
97
97
  expectedProtocol?: HardwareConnectProtocol,
98
- protocolHint?: HardwareConnectProtocol
98
+ protocolHint?: HardwareConnectProtocol,
99
+ forceProtocolDetection?: boolean
99
100
  ) {
100
101
  Log.debug('acquire', path, session, expectedProtocol, protocolHint);
101
102
  const env = DataManager.getSettings('env');
@@ -108,6 +109,7 @@ export default class DeviceConnector {
108
109
  forceCleanRunPromise,
109
110
  expectedProtocol,
110
111
  protocolHint,
112
+ forceProtocolDetection,
111
113
  });
112
114
  } else {
113
115
  res = await transport.acquire({
@@ -115,6 +117,7 @@ export default class DeviceConnector {
115
117
  previous: session ?? null,
116
118
  expectedProtocol,
117
119
  protocolHint,
120
+ forceProtocolDetection,
118
121
  });
119
122
  }
120
123
  if (expectedProtocol) {