@onekeyfe/hd-core 1.2.8-alpha.129 → 1.2.8-alpha.130

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.
@@ -9427,12 +9427,12 @@ describe('Protocol V2 firmware update targets', () => {
9427
9427
  method.postProgressMessage = jest.fn();
9428
9428
  return method;
9429
9429
  };
9430
- const transfer = async (method: FirmwareUpdateV4) => {
9430
+ const transfer = async (method: FirmwareUpdateV4, filePath = 'vol0:/application_p1.bin') => {
9431
9431
  const source = await openFirmwareByteSource({ binary: new Uint8Array(2500).buffer });
9432
9432
  try {
9433
9433
  const processedSize: number = await (method as any).protocolV2SourceUpdateProcess({
9434
9434
  source,
9435
- filePath: 'vol0:/application_p1.bin',
9435
+ filePath,
9436
9436
  processedSize: 500,
9437
9437
  totalSize: 3000,
9438
9438
  });
@@ -9506,49 +9506,56 @@ describe('Protocol V2 firmware update targets', () => {
9506
9506
  }
9507
9507
  );
9508
9508
 
9509
- const failOnceThenSucceed = (requests: any[]) =>
9510
- jest
9511
- .fn()
9512
- .mockRejectedValueOnce(new Error('Protocol V2 file write response does not match'))
9513
- .mockImplementation(streamAll(requests));
9509
+ const failWindowThenWriteSerial = (requests: any[]) => {
9510
+ const writeSerial = streamAll(requests);
9511
+ return jest.fn((name: string, resType: string, first: any, options: any) => {
9512
+ if (options.fileWritePipeline) {
9513
+ return Promise.reject(new Error('Protocol V2 file write response does not match'));
9514
+ }
9515
+ return writeSerial(name, resType, first, options);
9516
+ });
9517
+ };
9514
9518
 
9515
- test('restarts the whole file with dual frames after a failed windowed write', async () => {
9519
+ test('falls back to serial whole-file overwrite after a failed windowed exchange', async () => {
9516
9520
  const requests: any[] = [];
9517
- const typedCall = failOnceThenSucceed(requests);
9521
+ const typedCall = failWindowThenWriteSerial(requests);
9518
9522
  const method = createMethod(typedCall);
9519
9523
 
9520
9524
  await expect(transfer(method)).resolves.toBe(3000);
9521
9525
 
9522
9526
  expect((method as any).recoverProtocolV2FileTransfer).toHaveBeenCalledTimes(1);
9523
- // One failed pipeline, then a fresh pipeline overwriting the file from offset 0.
9524
- expect(typedCall).toHaveBeenCalledTimes(2);
9527
+ // One failed pipeline, then serial chunks overwriting the file from offset 0.
9528
+ expect(typedCall).toHaveBeenCalledTimes(4);
9529
+ expect(typedCall.mock.calls[0][3]).toHaveProperty('fileWritePipeline');
9525
9530
  typedCall.mock.calls
9526
9531
  .slice(1)
9527
- .forEach(call => expect(call[3]).toHaveProperty('fileWritePipeline'));
9532
+ .forEach(call => expect(call[3]).not.toHaveProperty('fileWritePipeline'));
9528
9533
  expect(typedCall.mock.calls[1][2]).toEqual(
9529
9534
  expect.objectContaining({ overwrite: true, file: expect.objectContaining({ offset: 0 }) })
9530
9535
  );
9531
9536
  expect(requests.map(request => request.file.offset)).toEqual([0, 1000, 2000]);
9532
- // Retries retain the two-frame chunk limit.
9533
9537
  const chunkSize = (method as any).getProtocolV2FirmwareChunkSize as jest.Mock;
9534
9538
  expect(chunkSize).toHaveBeenNthCalledWith(1, 'write', 'vol0:/application_p1.bin', true);
9535
- expect(chunkSize).toHaveBeenNthCalledWith(2, 'write', 'vol0:/application_p1.bin', true);
9539
+ expect(chunkSize).toHaveBeenNthCalledWith(2, 'write', 'vol0:/application_p1.bin', false);
9536
9540
  });
9537
9541
 
9538
- test('keeps later files on dual frames after a windowed attempt failed', async () => {
9539
- const typedCall = failOnceThenSucceed([]);
9542
+ test('keeps subsequent files serial after a failed windowed exchange', async () => {
9543
+ const typedCall = failWindowThenWriteSerial([]);
9540
9544
  const method = createMethod(typedCall);
9541
9545
  await transfer(method);
9542
9546
  typedCall.mockClear();
9543
9547
 
9544
- await expect(transfer(method)).resolves.toBe(3000);
9548
+ await expect(transfer(method, 'vol0:/resource.bin')).resolves.toBe(3000);
9545
9549
 
9546
- expect(typedCall).toHaveBeenCalledTimes(1);
9547
- typedCall.mock.calls.forEach(call => expect(call[3]).toHaveProperty('fileWritePipeline'));
9548
- expect((method as any).shouldUseProtocolV2BleFileWriteWindow).toHaveBeenCalledTimes(3);
9550
+ expect(typedCall).toHaveBeenCalledTimes(3);
9551
+ typedCall.mock.calls.forEach(call => {
9552
+ expect(call[3]).not.toHaveProperty('fileWritePipeline');
9553
+ expect(call[2].file.path).toBe('vol0:/resource.bin');
9554
+ });
9555
+ expect((method as any).shouldUseProtocolV2BleFileWriteWindow).toHaveBeenCalledTimes(1);
9549
9556
  });
9550
9557
 
9551
- test('bounds failed dual-frame transfers to three attempts', async () => {
9558
+ test('bounds failed file transfers to three attempts after serial fallback', async () => {
9552
9559
  const typedCall = jest.fn().mockRejectedValue(new Error('BLE response timeout'));
9553
9560
  const method = createMethod(typedCall);
9554
9561
  await expect(transfer(method)).rejects.toMatchObject({
@@ -9556,7 +9563,10 @@ describe('Protocol V2 firmware update targets', () => {
9556
9563
  });
9557
9564
  expect(typedCall).toHaveBeenCalledTimes(3);
9558
9565
  expect((method as any).recoverProtocolV2FileTransfer).toHaveBeenCalledTimes(2);
9559
- typedCall.mock.calls.forEach(call => expect(call[3]).toHaveProperty('fileWritePipeline'));
9566
+ expect(typedCall.mock.calls[0][3]).toHaveProperty('fileWritePipeline');
9567
+ typedCall.mock.calls
9568
+ .slice(1)
9569
+ .forEach(call => expect(call[3]).not.toHaveProperty('fileWritePipeline'));
9560
9570
  });
9561
9571
 
9562
9572
  test('logs confirmed progress every ten seconds and average speed through Core', async () => {
@@ -26,6 +26,7 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
26
26
  private protocolV2LastTransferProgress?;
27
27
  private protocolV2LastTransferProgressAt;
28
28
  private protocolV2LastTransferredBytes;
29
+ private protocolV2FileWriteWindowDisabled;
29
30
  init(): void;
30
31
  private getProtocolV2FirmwareChunkSize;
31
32
  run(): Promise<{
@@ -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":"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"}
package/dist/index.js CHANGED
@@ -53547,6 +53547,7 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
53547
53547
  this.protocolV2InstallTerminalSuccessObserved = false;
53548
53548
  this.protocolV2LastTransferProgressAt = 0;
53549
53549
  this.protocolV2LastTransferredBytes = 0;
53550
+ this.protocolV2FileWriteWindowDisabled = false;
53550
53551
  }
53551
53552
  getSupportedProtocols() {
53552
53553
  return ['V2'];
@@ -54876,7 +54877,8 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
54876
54877
  }
54877
54878
  };
54878
54879
  try {
54879
- windowed = this.shouldUseProtocolV2BleFileWriteWindow();
54880
+ windowed =
54881
+ !this.protocolV2FileWriteWindowDisabled && this.shouldUseProtocolV2BleFileWriteWindow();
54880
54882
  chunkSize = this.getProtocolV2FirmwareChunkSize('write', filePath, windowed);
54881
54883
  logTransfer('started');
54882
54884
  if (windowed) {
@@ -55662,12 +55664,17 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
55662
55664
  onChunkConfirmed(Number(confirmed.message.processed_byte));
55663
55665
  },
55664
55666
  },
55667
+ })
55668
+ .catch((error) => {
55669
+ this.protocolV2FileWriteWindowDisabled = true;
55670
+ throw error;
55665
55671
  });
55666
55672
  this.throwIfAborted();
55667
55673
  if (sourceError)
55668
55674
  throw sourceError;
55669
55675
  const rawProcessedByte = response.message.processed_byte;
55670
55676
  if (Number(rawProcessedByte) !== source.size) {
55677
+ this.protocolV2FileWriteWindowDisabled = true;
55671
55678
  throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.EmmcFileWriteFirmwareError, `invalid processed_byte ${rawProcessedByte} for file size ${source.size}`);
55672
55679
  }
55673
55680
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@onekeyfe/hd-core",
3
- "version": "1.2.8-alpha.129",
3
+ "version": "1.2.8-alpha.130",
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.8-alpha.129",
29
- "@onekeyfe/hd-transport": "1.2.8-alpha.129",
28
+ "@onekeyfe/hd-shared": "1.2.8-alpha.130",
29
+ "@onekeyfe/hd-transport": "1.2.8-alpha.130",
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": "e340d9447b375a9d79afd737bec50ff8c5a46aba"
49
+ "gitHead": "bacd066a15648891f9683586fcd06e063b98dfec"
50
50
  }
@@ -634,6 +634,8 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
634
634
 
635
635
  private protocolV2LastTransferredBytes = 0;
636
636
 
637
+ private protocolV2FileWriteWindowDisabled = false;
638
+
637
639
  init() {
638
640
  this.allowDeviceMode = [UI_REQUEST.BOOTLOADER, UI_REQUEST.NOT_INITIALIZE];
639
641
  this.requireDeviceMode = [];
@@ -2373,7 +2375,8 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
2373
2375
  }
2374
2376
  };
2375
2377
  try {
2376
- windowed = this.shouldUseProtocolV2BleFileWriteWindow();
2378
+ windowed =
2379
+ !this.protocolV2FileWriteWindowDisabled && this.shouldUseProtocolV2BleFileWriteWindow();
2377
2380
  chunkSize = this.getProtocolV2FirmwareChunkSize('write', filePath, windowed);
2378
2381
  logTransfer('started');
2379
2382
  if (windowed) {
@@ -3438,8 +3441,8 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
3438
3441
  if (source.size === 0) return;
3439
3442
  const firstRequest = await readRequest();
3440
3443
 
3441
- // Core retries the whole overwriting file after a verified reconnect. Keep the same
3442
- // window on retries and subsequent files; the running bootloader version gates support.
3444
+ // A failed exchange disables the window for the rest of this update. Source read
3445
+ // failures are raised separately and do not change the bootloader capability decision.
3443
3446
  const response = await this.device
3444
3447
  .getCommands()
3445
3448
  .typedCall('FilesystemFileWrite', 'FilesystemFile', firstRequest, {
@@ -3453,11 +3456,16 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
3453
3456
  onChunkConfirmed(Number(confirmed.message.processed_byte));
3454
3457
  },
3455
3458
  },
3459
+ })
3460
+ .catch((error: unknown) => {
3461
+ this.protocolV2FileWriteWindowDisabled = true;
3462
+ throw error;
3456
3463
  });
3457
3464
  this.throwIfAborted();
3458
3465
  if (sourceError) throw sourceError;
3459
3466
  const rawProcessedByte = response.message.processed_byte;
3460
3467
  if (Number(rawProcessedByte) !== source.size) {
3468
+ this.protocolV2FileWriteWindowDisabled = true;
3461
3469
  throw ERRORS.TypedError(
3462
3470
  HardwareErrorCode.EmmcFileWriteFirmwareError,
3463
3471
  `invalid processed_byte ${rawProcessedByte} for file size ${source.size}`