@onekeyfe/hd-core 1.2.0-alpha.82 → 1.2.0-alpha.85

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.
Files changed (53) hide show
  1. package/__tests__/check-all-firmware-release-protocol-v2.test.ts +285 -13
  2. package/__tests__/check-firmware-release-protocol-v2.test.ts +6 -0
  3. package/__tests__/firmware-memory-host.test.ts +105 -0
  4. package/__tests__/firmware-update/firmware-update-plan.test.ts +15 -70
  5. package/__tests__/firmware-update/firmware-update-prepared-plan.test.ts +53 -1
  6. package/__tests__/protocol-v2-resources.test.ts +0 -38
  7. package/__tests__/protocol-v2.test.ts +212 -320
  8. package/dist/api/CheckAllFirmwareRelease.d.ts.map +1 -1
  9. package/dist/api/FirmwareUpdateV4.d.ts +1 -2
  10. package/dist/api/FirmwareUpdateV4.d.ts.map +1 -1
  11. package/dist/api/firmware/FirmwareMemoryHost.d.ts +27 -0
  12. package/dist/api/firmware/FirmwareMemoryHost.d.ts.map +1 -0
  13. package/dist/api/firmware/FirmwareUpdatePlan.d.ts +33 -1
  14. package/dist/api/firmware/FirmwareUpdatePlan.d.ts.map +1 -1
  15. package/dist/api/firmware/FirmwareUpdatePreparedPlan.d.ts.map +1 -1
  16. package/dist/api/firmware/getBinary.d.ts +0 -1
  17. package/dist/api/firmware/getBinary.d.ts.map +1 -1
  18. package/dist/api/firmware/protocolV2Release.d.ts.map +1 -1
  19. package/dist/index.d.ts +25 -64
  20. package/dist/index.d.ts.map +1 -1
  21. package/dist/index.js +546 -387
  22. package/dist/inject.d.ts.map +1 -1
  23. package/dist/protocols/protocol-v2/resources.d.ts +0 -17
  24. package/dist/protocols/protocol-v2/resources.d.ts.map +1 -1
  25. package/dist/types/api/checkAllFirmwareRelease.d.ts +1 -0
  26. package/dist/types/api/checkAllFirmwareRelease.d.ts.map +1 -1
  27. package/dist/types/api/export.d.ts +0 -1
  28. package/dist/types/api/export.d.ts.map +1 -1
  29. package/dist/types/api/firmwareUpdate.d.ts +0 -10
  30. package/dist/types/api/firmwareUpdate.d.ts.map +1 -1
  31. package/dist/types/api/index.d.ts +0 -2
  32. package/dist/types/api/index.d.ts.map +1 -1
  33. package/dist/types/settings.d.ts +0 -11
  34. package/dist/types/settings.d.ts.map +1 -1
  35. package/package.json +4 -4
  36. package/src/api/CheckAllFirmwareRelease.ts +72 -5
  37. package/src/api/FirmwareUpdateV4.ts +154 -165
  38. package/src/api/firmware/FirmwareMemoryHost.ts +171 -0
  39. package/src/api/firmware/FirmwareUpdatePlan.ts +176 -79
  40. package/src/api/firmware/FirmwareUpdatePreparedPlan.ts +8 -1
  41. package/src/api/firmware/protocolV2Release.ts +2 -0
  42. package/src/index.ts +6 -1
  43. package/src/inject.ts +0 -2
  44. package/src/protocols/protocol-v2/resources.ts +0 -47
  45. package/src/types/api/checkAllFirmwareRelease.ts +1 -0
  46. package/src/types/api/export.ts +0 -4
  47. package/src/types/api/firmwareUpdate.ts +0 -15
  48. package/src/types/api/index.ts +0 -2
  49. package/src/types/settings.ts +0 -20
  50. package/src/utils/deviceFeaturesUtils.ts +2 -2
  51. package/dist/types/api/protocolV2ResourceManifest.d.ts +0 -17
  52. package/dist/types/api/protocolV2ResourceManifest.d.ts.map +0 -1
  53. package/src/types/api/protocolV2ResourceManifest.ts +0 -19
@@ -10,13 +10,14 @@ import {
10
10
  getDeviceFirmwareVersion,
11
11
  } from '../../utils/deviceVersionUtils';
12
12
 
13
+ import type { FirmwareUpdateV4Target } from '../../types/api/firmwareUpdate';
13
14
  import type {
14
15
  FirmwareUpdatePlan,
15
16
  FirmwareUpdatePlanArtifact,
16
17
  FirmwareUpdatePlanForceTarget,
17
18
  FirmwareUpdatePlanTarget,
18
19
  } from '../../types/api/firmwareUpdatePlan';
19
- import type { Features } from '../../types';
20
+ import type { Features, IProtocolV2ResourceSource } from '../../types';
20
21
 
21
22
  type FirmwareUpdatePlatform = 'native' | 'desktop' | 'ext' | 'web' | 'web-embed';
22
23
 
@@ -30,7 +31,6 @@ type ReleaseRecord = {
30
31
  version?: unknown;
31
32
  components?: unknown;
32
33
  installOrder?: unknown;
33
- resourceBundles?: unknown;
34
34
  fingerprint?: unknown;
35
35
  fingerprintWeb?: unknown;
36
36
  expectedSize?: unknown;
@@ -62,6 +62,11 @@ const PROTOCOL_V2_TARGETS: Readonly<
62
62
  SE04: 'se04',
63
63
  };
64
64
 
65
+ const PROTOCOL_V2_FIRMWARE_UPDATE_TARGETS = new Set<FirmwareUpdateV4Target>([
66
+ ...Object.values(PROTOCOL_V2_TARGETS),
67
+ 'resource',
68
+ ]);
69
+
65
70
  const asRecord = (value: unknown): Record<string, unknown> | undefined =>
66
71
  value && typeof value === 'object' && !Array.isArray(value)
67
72
  ? (value as Record<string, unknown>)
@@ -191,6 +196,23 @@ export const validateFirmwareUpdatePlanForceTargets = (
191
196
  return [...value] as FirmwareUpdatePlanForceTarget[];
192
197
  };
193
198
 
199
+ export const validateProtocolV2FirmwareUpdateTargets = (
200
+ value: unknown
201
+ ): FirmwareUpdateV4Target[] => {
202
+ if (value === undefined) {
203
+ return [];
204
+ }
205
+ if (
206
+ !Array.isArray(value) ||
207
+ value.length > PROTOCOL_V2_FIRMWARE_UPDATE_TARGETS.size ||
208
+ value.some(target => !PROTOCOL_V2_FIRMWARE_UPDATE_TARGETS.has(target)) ||
209
+ new Set(value).size !== value.length
210
+ ) {
211
+ return planError('Protocol V2 firmware update targets are invalid');
212
+ }
213
+ return [...value] as FirmwareUpdateV4Target[];
214
+ };
215
+
194
216
  const assertExactKeys = (
195
217
  value: Record<string, unknown>,
196
218
  required: readonly string[],
@@ -405,7 +427,7 @@ const selectResourceUrl = ({
405
427
 
406
428
  const getExecutor = (features: Features): FirmwareUpdatePlan['executor'] => {
407
429
  const deviceType = getDeviceType(features);
408
- if (deviceType === EDeviceType.Pro2) {
430
+ if (deviceType === EDeviceType.Pro2 || deviceType === EDeviceType.Neo) {
409
431
  return 'v4';
410
432
  }
411
433
  if (
@@ -421,10 +443,10 @@ const buildProtocolV2Artifacts = (
421
443
  release: ReleaseRecord,
422
444
  {
423
445
  includeComponents = true,
424
- includeResources = true,
446
+ componentTargets: selectedComponentTargets,
425
447
  }: {
426
448
  includeComponents?: boolean;
427
- includeResources?: boolean;
449
+ componentTargets?: ReadonlySet<FirmwareUpdatePlanTarget>;
428
450
  } = {}
429
451
  ): {
430
452
  artifacts: FirmwareUpdatePlanArtifact[];
@@ -445,12 +467,21 @@ const buildProtocolV2Artifacts = (
445
467
  includeComponents && components
446
468
  ? [...installOrder, ...Object.keys(components).filter(key => !installOrder.includes(key))]
447
469
  : [];
470
+ const selectedComponentKeys = selectedComponentTargets
471
+ ? componentKeys.filter(key => {
472
+ const component = asRecord(components?.[key]);
473
+ const targetName = asString(component?.target)?.toUpperCase();
474
+ const target = targetName ? PROTOCOL_V2_TARGETS[targetName] : undefined;
475
+ return !!target && selectedComponentTargets.has(target);
476
+ })
477
+ : componentKeys;
448
478
  const artifacts: FirmwareUpdatePlanArtifact[] = [];
449
479
  const targets: FirmwareUpdatePlanTarget[] = [];
450
- const componentTargets = new Set<FirmwareUpdatePlanTarget>();
451
- for (const key of componentKeys) {
480
+ const componentTargetSet = new Set<FirmwareUpdatePlanTarget>();
481
+ for (const key of selectedComponentKeys) {
452
482
  const component = asRecord(components?.[key]);
453
483
  const targetName = asString(component?.target)?.toUpperCase();
484
+ const target = targetName ? PROTOCOL_V2_TARGETS[targetName] : undefined;
454
485
  if (targetName === 'ROMLOADER') {
455
486
  throw ERRORS.TypedError(
456
487
  HardwareErrorCode.RuntimeError,
@@ -458,7 +489,6 @@ const buildProtocolV2Artifacts = (
458
489
  { firmwareUpdateCode: 'FirmwarePlanInvalid' }
459
490
  );
460
491
  }
461
- const target = targetName ? PROTOCOL_V2_TARGETS[targetName] : undefined;
462
492
  if (!component || !target) {
463
493
  throw ERRORS.TypedError(
464
494
  HardwareErrorCode.RuntimeError,
@@ -466,14 +496,14 @@ const buildProtocolV2Artifacts = (
466
496
  { firmwareUpdateCode: 'FirmwarePlanInvalid' }
467
497
  );
468
498
  }
469
- if (componentTargets.has(target)) {
499
+ if (componentTargetSet.has(target)) {
470
500
  throw ERRORS.TypedError(
471
501
  HardwareErrorCode.RuntimeError,
472
502
  `Protocol V2 component ${key} duplicates target ${target}`,
473
503
  { firmwareUpdateCode: 'FirmwarePlanInvalid' }
474
504
  );
475
505
  }
476
- componentTargets.add(target);
506
+ componentTargetSet.add(target);
477
507
  artifacts.push({
478
508
  artifactId: `component:${target}`,
479
509
  role: 'component',
@@ -490,43 +520,6 @@ const buildProtocolV2Artifacts = (
490
520
  targets.push(target);
491
521
  }
492
522
 
493
- const bundles =
494
- includeResources && Array.isArray(release.resourceBundles) ? release.resourceBundles : [];
495
- const resourceBundleNames = new Set<string>();
496
- for (const value of bundles) {
497
- const bundle = asRecord(value);
498
- const name = asString(bundle?.name);
499
- if (!bundle || !name) {
500
- throw ERRORS.TypedError(
501
- HardwareErrorCode.RuntimeError,
502
- 'Protocol V2 resource bundle is invalid',
503
- { firmwareUpdateCode: 'FirmwarePlanInvalid' }
504
- );
505
- }
506
- if (resourceBundleNames.has(name)) {
507
- throw ERRORS.TypedError(
508
- HardwareErrorCode.RuntimeError,
509
- `Protocol V2 resource bundle duplicates name ${name}`,
510
- { firmwareUpdateCode: 'FirmwarePlanInvalid' }
511
- );
512
- }
513
- resourceBundleNames.add(name);
514
- artifacts.push({
515
- artifactId: `resourceBundle:${name}`,
516
- role: 'resourceBundle',
517
- target: 'resource',
518
- url: assertArtifactUrl(bundle.url, `Protocol V2 resource bundle ${name}`),
519
- container: 'raw',
520
- logicalName: name,
521
- ...asIntegrity({
522
- size: bundle.expectedSize,
523
- sha256: bundle.fingerprint,
524
- }),
525
- });
526
- }
527
- if (bundles.length > 0) {
528
- targets.push('resource');
529
- }
530
523
  return { artifacts, targets: [...new Set(targets)] };
531
524
  };
532
525
 
@@ -587,6 +580,140 @@ const assertForcedTargetsRepresented = ({
587
580
  }
588
581
  };
589
582
 
583
+ const finalizeFirmwareUpdatePlan = ({
584
+ features,
585
+ firmwareType,
586
+ platform,
587
+ artifacts,
588
+ targetsToUpdate,
589
+ }: {
590
+ features: Features;
591
+ firmwareType: EFirmwareType;
592
+ platform: FirmwareUpdatePlatform;
593
+ artifacts: FirmwareUpdatePlanArtifact[];
594
+ targetsToUpdate: FirmwareUpdatePlanTarget[];
595
+ }): FirmwareUpdatePlan => {
596
+ const executor = getExecutor(features);
597
+ const bootloaderMode = resolveDeviceBootloaderMode(features);
598
+ // 'unavailable' is the reserved degraded-identity sentinel; a device-reported
599
+ // serial must never be able to collide with it.
600
+ const reportedIdentity = getDeviceUUID(features);
601
+ const deviceIdentity = reportedIdentity === 'unavailable' ? '' : reportedIdentity;
602
+ // Bootloader-mode classic-family devices (executor v2, e.g. classic1s) cannot report
603
+ // a serial number, so their recovery plans fall back to the degraded 'unavailable'
604
+ // identity. Binding is then enforced against the live device at install time instead
605
+ // (assertFirmwareUpdatePreparedPlanDeviceIdentity), and plan integrity by the digest.
606
+ // Pro (v3), Pro2, and Neo (v4) report a serial even in loader mode and stay strict.
607
+ if (
608
+ artifacts.length > 0 &&
609
+ (platform === 'native' || platform === 'desktop') &&
610
+ !deviceIdentity &&
611
+ !(bootloaderMode && executor === 'v2')
612
+ ) {
613
+ throw ERRORS.TypedError(
614
+ HardwareErrorCode.RuntimeError,
615
+ 'Prepared firmware update requires a stable device identity',
616
+ { firmwareUpdateCode: 'FirmwarePlanInvalid' }
617
+ );
618
+ }
619
+ const planWithoutDigest: Omit<FirmwareUpdatePlan, 'planDigest'> = {
620
+ schemaVersion: 2,
621
+ executor,
622
+ deviceIdentity: deviceIdentity || 'unavailable',
623
+ deviceModel: String(getDeviceType(features)),
624
+ firmwareType,
625
+ platform,
626
+ artifacts,
627
+ targetsToUpdate,
628
+ };
629
+ return assertFirmwareUpdatePlan({
630
+ ...planWithoutDigest,
631
+ planDigest: digestFirmwareUpdatePlan(planWithoutDigest),
632
+ });
633
+ };
634
+
635
+ export const buildProtocolV2FirmwareUpdatePlan = ({
636
+ features,
637
+ firmwareType,
638
+ platform,
639
+ release,
640
+ targetsToUpdate,
641
+ forceUpdateTargets,
642
+ resourceArchive,
643
+ }: {
644
+ features: Features;
645
+ firmwareType: EFirmwareType;
646
+ platform: FirmwareUpdatePlatform;
647
+ release: ReleaseRecord | undefined;
648
+ targetsToUpdate: readonly FirmwareUpdateV4Target[];
649
+ forceUpdateTargets?: FirmwareUpdatePlanForceTarget[];
650
+ resourceArchive: IProtocolV2ResourceSource | undefined;
651
+ }): FirmwareUpdatePlan => {
652
+ const validatedForceTargets = validateFirmwareUpdatePlanForceTargets(forceUpdateTargets);
653
+ if (validatedForceTargets.some(target => target === 'ble' || target === 'bootloader')) {
654
+ planError('Protocol V2 does not support forced BLE or legacy bootloader targets');
655
+ }
656
+
657
+ const requestedComponentTargets = new Set<FirmwareUpdatePlanTarget>(
658
+ targetsToUpdate.filter(target => target !== 'resource')
659
+ );
660
+ if (
661
+ getDeviceType(features) === EDeviceType.Neo &&
662
+ (requestedComponentTargets.has('se03') || requestedComponentTargets.has('se04'))
663
+ ) {
664
+ planError('Neo does not support Protocol V2 targets se03 or se04');
665
+ }
666
+ const protocolV2 = buildProtocolV2Artifacts(release ?? {}, {
667
+ includeComponents: requestedComponentTargets.size > 0,
668
+ componentTargets: requestedComponentTargets,
669
+ });
670
+ const resourceRequested = targetsToUpdate.includes('resource');
671
+ if (resourceRequested) {
672
+ const archive = resourceArchive;
673
+ if (!archive) {
674
+ return planError('Protocol V2 resource target has no resource archive');
675
+ }
676
+ const integrity = asIntegrity({
677
+ size: archive.archiveSize,
678
+ sha256: archive.archiveSha256,
679
+ });
680
+ if (integrity.expectedSize === undefined || integrity.expectedSha256 === undefined) {
681
+ planError('Protocol V2 resource archive integrity metadata is invalid');
682
+ }
683
+ protocolV2.artifacts.push({
684
+ artifactId: 'resource:archive',
685
+ role: 'resourceBundle',
686
+ target: 'resource',
687
+ url: assertArtifactUrl(archive.archiveUrl, 'Protocol V2 resource archive'),
688
+ container: 'zip',
689
+ logicalName: 'protocol-v2-resource-archive',
690
+ ...integrity,
691
+ });
692
+ protocolV2.targets.push('resource');
693
+ }
694
+ const representedTargets = new Set(protocolV2.targets);
695
+ const missingTarget = Array.from(requestedComponentTargets).find(
696
+ target => !representedTargets.has(target)
697
+ );
698
+ if (missingTarget) {
699
+ planError(`Protocol V2 release does not contain requested target ${missingTarget}`);
700
+ }
701
+ if (validatedForceTargets.includes('firmware') && protocolV2.targets.length === 0) {
702
+ planError('Forced firmware update target firmware is not represented by the plan');
703
+ }
704
+ if (validatedForceTargets.includes('resource') && !resourceArchive) {
705
+ planError('Forced firmware update target resource has no Protocol V2 resource archive');
706
+ }
707
+
708
+ return finalizeFirmwareUpdatePlan({
709
+ features,
710
+ firmwareType,
711
+ platform,
712
+ artifacts: protocolV2.artifacts,
713
+ targetsToUpdate: protocolV2.targets,
714
+ });
715
+ };
716
+
590
717
  export const buildFirmwareUpdatePlan = ({
591
718
  features,
592
719
  firmwareType,
@@ -635,7 +762,6 @@ export const buildFirmwareUpdatePlan = ({
635
762
  if (executor === 'v4' && (shouldUpdateFirmware || shouldUpdateResource)) {
636
763
  const protocolV2 = buildProtocolV2Artifacts(firmwareRelease ?? {}, {
637
764
  includeComponents: shouldUpdateFirmware,
638
- includeResources: shouldUpdateResource,
639
765
  });
640
766
  artifacts = protocolV2.artifacts;
641
767
  targetsToUpdate = protocolV2.targets;
@@ -733,40 +859,11 @@ export const buildFirmwareUpdatePlan = ({
733
859
  artifacts,
734
860
  targetsToUpdate,
735
861
  });
736
-
737
- // 'unavailable' is the reserved degraded-identity sentinel; a device-reported
738
- // serial must never be able to collide with it.
739
- const reportedIdentity = getDeviceUUID(features);
740
- const deviceIdentity = reportedIdentity === 'unavailable' ? '' : reportedIdentity;
741
- // Bootloader-mode classic-family devices (executor v2, e.g. classic1s) cannot report
742
- // a serial number, so their recovery plans fall back to the degraded 'unavailable'
743
- // identity. Binding is then enforced against the live device at install time instead
744
- // (assertFirmwareUpdatePreparedPlanDeviceIdentity), and plan integrity by the digest.
745
- // Pro (v3) and Pro2 (v4) report a serial even in bootloader mode and stay strict.
746
- if (
747
- artifacts.length > 0 &&
748
- (platform === 'native' || platform === 'desktop') &&
749
- !deviceIdentity &&
750
- !(bootloaderMode && executor === 'v2')
751
- ) {
752
- throw ERRORS.TypedError(
753
- HardwareErrorCode.RuntimeError,
754
- 'Prepared firmware update requires a stable device identity',
755
- { firmwareUpdateCode: 'FirmwarePlanInvalid' }
756
- );
757
- }
758
- const planWithoutDigest: Omit<FirmwareUpdatePlan, 'planDigest'> = {
759
- schemaVersion: 2,
760
- executor,
761
- deviceIdentity: deviceIdentity || 'unavailable',
762
- deviceModel: String(getDeviceType(features)),
862
+ return finalizeFirmwareUpdatePlan({
863
+ features,
763
864
  firmwareType,
764
865
  platform,
765
866
  artifacts,
766
867
  targetsToUpdate,
767
- };
768
- return assertFirmwareUpdatePlan({
769
- ...planWithoutDigest,
770
- planDigest: digestFirmwareUpdatePlan(planWithoutDigest),
771
868
  });
772
869
  };
@@ -278,7 +278,14 @@ export const validateFirmwareUpdatePreparedPlan = (value: unknown): FirmwareUpda
278
278
  artifactIds.add(artifact.artifactId);
279
279
  artifactTargets.add(artifact.target);
280
280
  assertFirmwareArtifactReference(artifact.artifact);
281
- artifact.materializedEntries?.forEach(assertPreparedEntry);
281
+ const materializedEntryNames =
282
+ artifact.materializedEntries?.map(entry => {
283
+ assertPreparedEntry(entry);
284
+ return getFirmwareUpdateResourceName(entry.entryName).toLowerCase();
285
+ }) ?? [];
286
+ if (new Set(materializedEntryNames).size !== materializedEntryNames.length) {
287
+ return preparedPlanError('Firmware prepared plan contains duplicate entry names');
288
+ }
282
289
  }
283
290
  if (
284
291
  preparedPlan.targetsToUpdate.some(target => !FIRMWARE_UPDATE_PLAN_TARGETS.has(target)) ||
@@ -135,6 +135,8 @@ export function toProtocolV2FirmwareReleaseInfo({
135
135
  return {
136
136
  shouldUpdate: plan.hasUpgrade,
137
137
  status: plan.status === 'unavailable' ? 'unknown' : plan.status,
138
+ // Protocol V2 components share package-set release notes. The optional
139
+ // bootloaderChangelog field belongs to the legacy Protocol V1 release model.
138
140
  changelog: plan.release ? [plan.release.changelog] : [],
139
141
  release,
140
142
  bootloaderMode: state.status.mode === 'bootloader' || state.status.mode === 'romloader',
package/src/index.ts CHANGED
@@ -23,9 +23,14 @@ export { projectFeatures as projectDeviceStateFeatures } from './device/DeviceSt
23
23
  export { getMethodSupportedProtocols } from './api/utils';
24
24
  export {
25
25
  parseProtocolV2ResourceManifest,
26
- prepareProtocolV2ResourceFiles,
27
26
  selectProtocolV2ResourceManifestFiles,
28
27
  } from './protocols/protocol-v2/resources';
28
+ export { prepareFirmwareUpdateV4MemoryHost } from './api/firmware/FirmwareMemoryHost';
29
+ export type {
30
+ FirmwareMemoryArtifact,
31
+ FirmwareMemoryArtifactEntry,
32
+ FirmwareUpdateV4MemoryHost,
33
+ } from './api/firmware/FirmwareMemoryHost';
29
34
  export {
30
35
  getFirmwareUpdateHostBindingGeneration,
31
36
  registerFirmwareUpdateHostBinding,
package/src/inject.ts CHANGED
@@ -3,7 +3,6 @@ import {
3
3
  prepareFirmwareUpdatePlan,
4
4
  validateFirmwareUpdatePreparedPlan,
5
5
  } from './api/firmware/FirmwareUpdatePreparedPlan';
6
- import { prepareProtocolV2ResourceFiles } from './protocols/protocol-v2/resources';
7
6
  import {
8
7
  getFirmwareUpdateHostBindingGeneration,
9
8
  registerFirmwareUpdateHostBinding,
@@ -169,7 +168,6 @@ export const createCoreApi = (
169
168
  getFirmwareUpdateHostBindingGeneration,
170
169
  prepareFirmwareUpdatePlan,
171
170
  validateFirmwareUpdatePreparedPlan,
172
- prepareProtocolV2ResourceFiles,
173
171
  getLogs: () => call({ method: 'getLogs' }),
174
172
  clearSessionCache: params => call({ ...params, method: 'clearSessionCache' }),
175
173
  /**
@@ -1,5 +1,3 @@
1
- import { sha256 } from '@noble/hashes/sha256';
2
-
3
1
  import type {
4
2
  IProtocolV2ResourceManifest,
5
3
  IProtocolV2ResourceManifestFile,
@@ -210,48 +208,3 @@ export function selectProtocolV2ResourceManifestFiles({
210
208
  }): IProtocolV2ResourceManifestFile[] {
211
209
  return targetsToUpdate.includes('resource') ? [...manifest.files] : [];
212
210
  }
213
-
214
- export function prepareProtocolV2ResourceFiles({
215
- manifest: value,
216
- files,
217
- targetsToUpdate,
218
- }: {
219
- manifest: unknown;
220
- files: Array<{ archivePath: string; binary: ArrayBuffer }>;
221
- targetsToUpdate: readonly FirmwareUpdateV4Target[];
222
- }): Array<{ binary: ArrayBuffer; devicePath: string; size: number; fileHash: string }> {
223
- const manifest = parseProtocolV2ResourceManifest(value);
224
- const selected = selectProtocolV2ResourceManifestFiles({ manifest, targetsToUpdate });
225
- const binaries = new Map(files.map(file => [file.archivePath, file.binary] as const));
226
- return selected.map(file => {
227
- const binary = binaries.get(file.archive_path);
228
- if (
229
- !binary ||
230
- !isProtocolV2ResourceFileValid(binary, {
231
- size: file.size,
232
- fileHash: file.sha256,
233
- })
234
- ) {
235
- throw new Error(`Pro2 resource manifest file verification failed: ${file.archive_path}`);
236
- }
237
- return {
238
- binary,
239
- devicePath: file.device_path,
240
- size: file.size,
241
- fileHash: file.sha256,
242
- };
243
- });
244
- }
245
-
246
- function bytesToHex(bytes: Uint8Array): string {
247
- return Array.from(bytes, byte => byte.toString(16).padStart(2, '0')).join('');
248
- }
249
-
250
- /** Verify the complete downloaded file before any device mutation. */
251
- export function isProtocolV2ResourceFileValid(
252
- binary: ArrayBuffer,
253
- resource: { size: number; fileHash: string }
254
- ): boolean {
255
- if (binary.byteLength !== resource.size) return false;
256
- return bytesToHex(sha256(new Uint8Array(binary))) === resource.fileHash.toLowerCase();
257
- }
@@ -89,6 +89,7 @@ export type CheckAllFirmwareReleaseParams = {
89
89
  firmwareType?: EFirmwareType;
90
90
  platform?: 'native' | 'desktop' | 'ext' | 'web' | 'web-embed';
91
91
  forceUpdateTargets?: FirmwareUpdatePlanForceTarget[];
92
+ protocolV2ForceUpdateTargets?: FirmwareUpdateV4Target[];
92
93
  };
93
94
 
94
95
  export declare function checkAllFirmwareRelease(
@@ -49,10 +49,6 @@ export type {
49
49
  FirmwareUpdatePreparedEntry,
50
50
  FirmwareUpdatePreparedPlan,
51
51
  } from './firmwareUpdatePreparedPlan';
52
- export type {
53
- ProtocolV2PreparedResourceFile,
54
- ProtocolV2ResourceManifestBinary,
55
- } from './protocolV2ResourceManifest';
56
52
  export type { FirmwareUpdateCapabilities } from './firmwareUpdateCapabilities';
57
53
  export type {
58
54
  AllFirmwareRelease,
@@ -153,25 +153,10 @@ export interface FirmwareUpdateV4Params {
153
153
  se03Binary?: ArrayBuffer;
154
154
  se04Binary?: ArrayBuffer;
155
155
  forcedUpdateRes?: boolean;
156
- /**
157
- * Arbitrary Protocol V2 resource files written directly with FilesystemFileWrite.
158
- * Use this for every file selected from the manifest-driven resource archive.
159
- * When provided, these files are authoritative for the resource target.
160
- */
161
- resourceFiles?: Array<{
162
- binary: ArrayBuffer;
163
- devicePath: string;
164
- size?: number;
165
- fileHash?: string;
166
- }>;
167
156
  artifactReader?: FirmwareArtifactReader;
168
157
  componentArtifacts?: Partial<
169
158
  Record<Exclude<FirmwareUpdateV4Target, 'resource'>, FirmwareArtifactReference>
170
159
  >;
171
- resourceBundleArtifacts?: Array<{
172
- name: string;
173
- artifact: FirmwareArtifactReference;
174
- }>;
175
160
  }
176
161
 
177
162
  export declare function registerFirmwareUpdateHostBinding(
@@ -41,7 +41,6 @@ import type {
41
41
  prepareFirmwareUpdatePlan,
42
42
  validateFirmwareUpdatePreparedPlan,
43
43
  } from './firmwareUpdatePreparedPlan';
44
- import type { prepareProtocolV2ResourceFiles } from './protocolV2ResourceManifest';
45
44
  import type { promptWebDeviceAccess } from './promptWebDeviceAccess';
46
45
  import type { deviceReset } from './deviceReset';
47
46
  import type { deviceRecovery } from './deviceRecovery';
@@ -254,7 +253,6 @@ export type CoreApi = {
254
253
  getFirmwareUpdateCapabilities: typeof getFirmwareUpdateCapabilities;
255
254
  prepareFirmwareUpdatePlan: typeof prepareFirmwareUpdatePlan;
256
255
  validateFirmwareUpdatePreparedPlan: typeof validateFirmwareUpdatePreparedPlan;
257
- prepareProtocolV2ResourceFiles: typeof prepareProtocolV2ResourceFiles;
258
256
  cipherKeyValue: typeof cipherKeyValue;
259
257
 
260
258
  /**
@@ -104,24 +104,6 @@ export type IProtocolV2ResourceManifest = {
104
104
  files: IProtocolV2ResourceManifestFile[];
105
105
  };
106
106
 
107
- /** Pro2 RESC bundle okpkg descriptor for incremental FileWrite synchronization. */
108
- export type IProtocolV2ResourceBundle = {
109
- /** Bundle name, such as images, animation, translations, or fonts_roobert. */
110
- name: string;
111
- /** Download URL. */
112
- url: string;
113
- fingerprint?: string;
114
- expectedSize?: number;
115
- /** Device target path, such as vol0:/bundles/images/images.okpkg. */
116
- devicePath: string;
117
- /** okpkg payload_version used to skip matching content after FileRead. */
118
- version?: IVersionArray;
119
- /** okpkg payload_hash used for SHA3-512 comparison after FileRead. */
120
- payloadHash?: string;
121
- /** okpkg header_hash used for SHA3-512 comparison after FileRead. */
122
- headerHash?: string;
123
- };
124
-
125
107
  /** STM32 firmware config */
126
108
  export type IFirmwareReleaseInfo = {
127
109
  required: boolean;
@@ -149,8 +131,6 @@ export type IFirmwareReleaseInfo = {
149
131
  upgradeType?: 'payload-package-set' | string;
150
132
  components?: Record<string, IProtocolV2FirmwareComponent>;
151
133
  installOrder?: string[];
152
- /** Pro2 RESC bundles for incremental direct FileWrite synchronization. */
153
- resourceBundles?: IProtocolV2ResourceBundle[];
154
134
  bootloaderChangelog?: {
155
135
  [k in ILocale]: string;
156
136
  };
@@ -328,7 +328,7 @@ export const getFirmwareUpdateField = ({
328
328
  if (deviceType === EDeviceType.Pro) {
329
329
  return latestFirmwareField;
330
330
  }
331
- if (deviceType === EDeviceType.Pro2) {
331
+ if (deviceType === EDeviceType.Pro2 || deviceType === EDeviceType.Neo) {
332
332
  return 'firmware-v1';
333
333
  }
334
334
  return 'firmware';
@@ -374,7 +374,7 @@ export const getFirmwareUpdateFieldArray = (
374
374
  return ['firmware-v8'];
375
375
  }
376
376
 
377
- if (deviceType === 'pro2') {
377
+ if (deviceType === 'pro2' || deviceType === 'neo') {
378
378
  return ['firmware-v1'];
379
379
  }
380
380
 
@@ -1,17 +0,0 @@
1
- import type { FirmwareUpdateV4Target } from './firmwareUpdate';
2
- export type ProtocolV2ResourceManifestBinary = {
3
- archivePath: string;
4
- binary: ArrayBuffer;
5
- };
6
- export type ProtocolV2PreparedResourceFile = {
7
- binary: ArrayBuffer;
8
- devicePath: string;
9
- size: number;
10
- fileHash: string;
11
- };
12
- export declare function prepareProtocolV2ResourceFiles(input: {
13
- manifest: unknown;
14
- files: ProtocolV2ResourceManifestBinary[];
15
- targetsToUpdate: readonly FirmwareUpdateV4Target[];
16
- }): ProtocolV2PreparedResourceFile[];
17
- //# sourceMappingURL=protocolV2ResourceManifest.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"protocolV2ResourceManifest.d.ts","sourceRoot":"","sources":["../../../src/types/api/protocolV2ResourceManifest.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,kBAAkB,CAAC;AAE/D,MAAM,MAAM,gCAAgC,GAAG;IAC7C,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,WAAW,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,8BAA8B,GAAG;IAC3C,MAAM,EAAE,WAAW,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,MAAM,CAAC,OAAO,UAAU,8BAA8B,CAAC,KAAK,EAAE;IAC5D,QAAQ,EAAE,OAAO,CAAC;IAClB,KAAK,EAAE,gCAAgC,EAAE,CAAC;IAC1C,eAAe,EAAE,SAAS,sBAAsB,EAAE,CAAC;CACpD,GAAG,8BAA8B,EAAE,CAAC"}
@@ -1,19 +0,0 @@
1
- import type { FirmwareUpdateV4Target } from './firmwareUpdate';
2
-
3
- export type ProtocolV2ResourceManifestBinary = {
4
- archivePath: string;
5
- binary: ArrayBuffer;
6
- };
7
-
8
- export type ProtocolV2PreparedResourceFile = {
9
- binary: ArrayBuffer;
10
- devicePath: string;
11
- size: number;
12
- fileHash: string;
13
- };
14
-
15
- export declare function prepareProtocolV2ResourceFiles(input: {
16
- manifest: unknown;
17
- files: ProtocolV2ResourceManifestBinary[];
18
- targetsToUpdate: readonly FirmwareUpdateV4Target[];
19
- }): ProtocolV2PreparedResourceFile[];