@onekeyfe/hd-core 1.2.0-alpha.77 → 1.2.0-alpha.79

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 (57) hide show
  1. package/__tests__/check-all-firmware-release-protocol-v2.test.ts +12 -71
  2. package/__tests__/device-state-mapper.test.ts +16 -1
  3. package/__tests__/device-state-projector.test.ts +20 -0
  4. package/__tests__/device-state-store.test.ts +27 -0
  5. package/__tests__/homescreen.test.ts +17 -0
  6. package/__tests__/method-protocol-support.test.ts +13 -1
  7. package/__tests__/protocol-v2-resources.test.ts +113 -222
  8. package/__tests__/protocol-v2.test.ts +110 -380
  9. package/dist/api/CheckAllFirmwareRelease.d.ts.map +1 -1
  10. package/dist/api/FirmwareUpdateV4.d.ts +0 -6
  11. package/dist/api/FirmwareUpdateV4.d.ts.map +1 -1
  12. package/dist/api/UploadPortfolio.d.ts.map +1 -1
  13. package/dist/api/utils.d.ts +2 -0
  14. package/dist/api/utils.d.ts.map +1 -1
  15. package/dist/data-manager/DataManager.d.ts +1 -2
  16. package/dist/data-manager/DataManager.d.ts.map +1 -1
  17. package/dist/device/DeviceStateMapper.d.ts.map +1 -1
  18. package/dist/device/DeviceStateProjector.d.ts.map +1 -1
  19. package/dist/device/DeviceStateStore.d.ts.map +1 -1
  20. package/dist/index.d.ts +96 -33
  21. package/dist/index.d.ts.map +1 -1
  22. package/dist/index.js +515 -597
  23. package/dist/inject.d.ts.map +1 -1
  24. package/dist/protocols/protocol-v2/resources.d.ts +31 -28
  25. package/dist/protocols/protocol-v2/resources.d.ts.map +1 -1
  26. package/dist/types/api/checkAllFirmwareRelease.d.ts +1 -0
  27. package/dist/types/api/checkAllFirmwareRelease.d.ts.map +1 -1
  28. package/dist/types/api/export.d.ts +1 -0
  29. package/dist/types/api/export.d.ts.map +1 -1
  30. package/dist/types/api/index.d.ts +2 -0
  31. package/dist/types/api/index.d.ts.map +1 -1
  32. package/dist/types/api/protocolV2ResourceManifest.d.ts +17 -0
  33. package/dist/types/api/protocolV2ResourceManifest.d.ts.map +1 -0
  34. package/dist/types/device.d.ts +8 -0
  35. package/dist/types/device.d.ts.map +1 -1
  36. package/dist/types/settings.d.ts +30 -21
  37. package/dist/types/settings.d.ts.map +1 -1
  38. package/dist/utils/homescreen.d.ts.map +1 -1
  39. package/package.json +4 -4
  40. package/src/api/CheckAllFirmwareRelease.ts +5 -34
  41. package/src/api/FirmwareUpdateV4.ts +48 -220
  42. package/src/api/UploadPortfolio.ts +18 -0
  43. package/src/api/utils.ts +25 -0
  44. package/src/data-manager/DataManager.ts +17 -6
  45. package/src/device/DeviceStateMapper.ts +42 -0
  46. package/src/device/DeviceStateProjector.ts +58 -0
  47. package/src/device/DeviceStateStore.ts +31 -0
  48. package/src/index.ts +8 -0
  49. package/src/inject.ts +2 -0
  50. package/src/protocols/protocol-v2/resources.ts +193 -324
  51. package/src/types/api/checkAllFirmwareRelease.ts +1 -0
  52. package/src/types/api/export.ts +4 -0
  53. package/src/types/api/index.ts +2 -0
  54. package/src/types/api/protocolV2ResourceManifest.ts +19 -0
  55. package/src/types/device.ts +16 -0
  56. package/src/types/settings.ts +30 -36
  57. package/src/utils/homescreen.ts +5 -1
package/dist/index.js CHANGED
@@ -1265,6 +1265,204 @@ const assertFirmwareUpdatePreparedPlanBinding = ({ preparedPlan: value, executor
1265
1265
  return preparedPlan;
1266
1266
  };
1267
1267
 
1268
+ const PROTOCOL_V2_BOOT_RESOURCE_PACKAGE_PATH$1 = 'vol0:/loaders/bootloader/boot_resource.okpkg';
1269
+ const SHA256_HEX_LENGTH = 64;
1270
+ function normalizeHex$1(value, expectedLength, field) {
1271
+ if (typeof value !== 'string') {
1272
+ throw new Error(`Invalid Pro2 resource ${field}: expected a hexadecimal string`);
1273
+ }
1274
+ const normalized = value.replace(/^0x/i, '').toLowerCase();
1275
+ if (normalized.length !== expectedLength || !/^[0-9a-f]+$/.test(normalized)) {
1276
+ throw new Error(`Invalid Pro2 resource ${field}: expected ${expectedLength} hexadecimal characters`);
1277
+ }
1278
+ return normalized;
1279
+ }
1280
+ function parseProtocolV2Resources(value) {
1281
+ if (value === undefined)
1282
+ return undefined;
1283
+ if (!value || typeof value !== 'object') {
1284
+ throw new Error('Invalid Pro2 resources config');
1285
+ }
1286
+ const { source } = value;
1287
+ if (!source || typeof source !== 'object') {
1288
+ throw new Error('Invalid Pro2 resources config: source is required');
1289
+ }
1290
+ const { manifestUrl } = source;
1291
+ if (typeof manifestUrl !== 'string' || !manifestUrl.startsWith('https://')) {
1292
+ throw new Error('Invalid Pro2 resources config: source.manifestUrl must use HTTPS');
1293
+ }
1294
+ return {
1295
+ source: { manifestUrl },
1296
+ };
1297
+ }
1298
+ const PROTOCOL_V2_RESOURCE_MANIFEST_DEVICE_ROOTS = [
1299
+ 'vol0:/bundles/',
1300
+ 'vol0:/loaders/rom/',
1301
+ ];
1302
+ function isAllowedManifestDevicePath(path) {
1303
+ if (!path.endsWith('.okpkg') ||
1304
+ path.includes('\\') ||
1305
+ path.includes('//') ||
1306
+ path.split('/').some(part => part === '.' || part === '..')) {
1307
+ return false;
1308
+ }
1309
+ if (path === PROTOCOL_V2_BOOT_RESOURCE_PACKAGE_PATH$1) {
1310
+ return true;
1311
+ }
1312
+ return PROTOCOL_V2_RESOURCE_MANIFEST_DEVICE_ROOTS.some(root => path.startsWith(root));
1313
+ }
1314
+ function assertManifestString(value, field) {
1315
+ if (typeof value !== 'string' || value.length === 0) {
1316
+ throw new Error(`Invalid Pro2 resource manifest ${field}`);
1317
+ }
1318
+ return value;
1319
+ }
1320
+ function assertManifestRelativePath(value, field) {
1321
+ const path = assertManifestString(value, field);
1322
+ if (path.startsWith('/') ||
1323
+ path.includes('\\') ||
1324
+ path.includes(':') ||
1325
+ path.split('/').some(part => !part || part === '.' || part === '..')) {
1326
+ throw new Error(`Invalid Pro2 resource manifest ${field}`);
1327
+ }
1328
+ return path;
1329
+ }
1330
+ function parseProtocolV2ResourceManifestFile(value, index) {
1331
+ var _a;
1332
+ if (!value || typeof value !== 'object' || Array.isArray(value)) {
1333
+ throw new Error(`Invalid Pro2 resource manifest files[${index}]`);
1334
+ }
1335
+ const file = value;
1336
+ const archivePath = assertManifestRelativePath(file.archive_path, `files[${index}].archive_path`);
1337
+ const originalName = assertManifestRelativePath(file.original_name, `files[${index}].original_name`);
1338
+ if (originalName.includes('/')) {
1339
+ throw new Error(`Invalid Pro2 resource manifest files[${index}].original_name`);
1340
+ }
1341
+ const devicePath = assertManifestString(file.device_path, `files[${index}].device_path`);
1342
+ if (!isAllowedManifestDevicePath(devicePath)) {
1343
+ throw new Error(`Invalid Pro2 resource manifest files[${index}].device_path`);
1344
+ }
1345
+ if (!Number.isSafeInteger(file.size) || Number(file.size) <= 0) {
1346
+ throw new Error(`Invalid Pro2 resource manifest files[${index}].size`);
1347
+ }
1348
+ const digest = normalizeHex$1(file.sha256, SHA256_HEX_LENGTH, `files[${index}].sha256`);
1349
+ if (file.signed !== true) {
1350
+ throw new Error(`Invalid Pro2 resource manifest files[${index}].signed`);
1351
+ }
1352
+ if (file.sig_algo !== 'ed25519' && file.sig_algo !== 'mldsa65') {
1353
+ throw new Error(`Invalid Pro2 resource manifest files[${index}].sig_algo`);
1354
+ }
1355
+ if (file.payload_version !== null && typeof file.payload_version !== 'string') {
1356
+ throw new Error(`Invalid Pro2 resource manifest files[${index}].payload_version`);
1357
+ }
1358
+ if (!archivePath.endsWith('.okpkg') || !originalName.endsWith('.okpkg')) {
1359
+ throw new Error(`Invalid Pro2 resource manifest files[${index}] package extension`);
1360
+ }
1361
+ return {
1362
+ archive_path: archivePath,
1363
+ original_name: originalName,
1364
+ device_path: devicePath,
1365
+ size: Number(file.size),
1366
+ sha256: digest,
1367
+ signed: true,
1368
+ sig_algo: file.sig_algo,
1369
+ payload_version: (_a = file.payload_version) !== null && _a !== void 0 ? _a : null,
1370
+ };
1371
+ }
1372
+ function parseProtocolV2ResourceManifest(value) {
1373
+ if (!value || typeof value !== 'object' || Array.isArray(value)) {
1374
+ throw new Error('Invalid Pro2 resource manifest');
1375
+ }
1376
+ const manifest = value;
1377
+ if (manifest.schema !== 1 ||
1378
+ manifest.variant !== 'resource' ||
1379
+ manifest.device_root !== 'vol0:' ||
1380
+ manifest.restore_mode !== 'bootloader_update' ||
1381
+ !Array.isArray(manifest.trees) ||
1382
+ !Array.isArray(manifest.files)) {
1383
+ throw new Error('Invalid Pro2 resource manifest contract');
1384
+ }
1385
+ const files = manifest.files.map(parseProtocolV2ResourceManifestFile);
1386
+ const devicePaths = new Set(files.map(file => file.device_path));
1387
+ const archivePaths = new Set(files.map(file => file.archive_path));
1388
+ if (files.length === 0 ||
1389
+ devicePaths.size !== files.length ||
1390
+ archivePaths.size !== files.length ||
1391
+ !devicePaths.has(PROTOCOL_V2_BOOT_RESOURCE_PACKAGE_PATH$1) ||
1392
+ !files.some(file => file.device_path.startsWith('vol0:/bundles/'))) {
1393
+ throw new Error('Invalid Pro2 resource manifest file set');
1394
+ }
1395
+ return {
1396
+ schema: 1,
1397
+ artifact_name: assertManifestString(manifest.artifact_name, 'artifact_name'),
1398
+ release_name: assertManifestString(manifest.release_name, 'release_name'),
1399
+ variant: 'resource',
1400
+ commit: assertManifestString(manifest.commit, 'commit'),
1401
+ short_sha: assertManifestString(manifest.short_sha, 'short_sha'),
1402
+ timestamp_utc: assertManifestString(manifest.timestamp_utc, 'timestamp_utc'),
1403
+ core_version: assertManifestString(manifest.core_version, 'core_version'),
1404
+ key_set: assertManifestString(manifest.key_set, 'key_set'),
1405
+ device_root: 'vol0:',
1406
+ restore_mode: 'bootloader_update',
1407
+ trees: manifest.trees.map((tree, index) => {
1408
+ if (!tree || typeof tree !== 'object') {
1409
+ throw new Error(`Invalid Pro2 resource manifest trees[${index}]`);
1410
+ }
1411
+ const item = tree;
1412
+ return {
1413
+ path: assertManifestRelativePath(item.path, `trees[${index}].path`),
1414
+ device: assertManifestString(item.device, `trees[${index}].device`),
1415
+ };
1416
+ }),
1417
+ files,
1418
+ };
1419
+ }
1420
+ function selectProtocolV2ResourceManifestFiles({ manifest, targetsToUpdate, }) {
1421
+ const targets = new Set(targetsToUpdate);
1422
+ return manifest.files.filter(file => {
1423
+ if (file.device_path.startsWith('vol0:/bundles/')) {
1424
+ return targets.has('resource');
1425
+ }
1426
+ return targets.has('boot_resources');
1427
+ });
1428
+ }
1429
+ function resolveProtocolV2ResourceManifestFileUrl({ manifestUrl, archivePath, }) {
1430
+ const url = new URL(assertManifestRelativePath(archivePath, 'archive_path'), manifestUrl);
1431
+ if (url.protocol !== 'https:') {
1432
+ throw new Error('Invalid Pro2 resource manifest file URL');
1433
+ }
1434
+ return url.toString();
1435
+ }
1436
+ function prepareProtocolV2ResourceFiles({ manifest: value, files, targetsToUpdate, }) {
1437
+ const manifest = parseProtocolV2ResourceManifest(value);
1438
+ const selected = selectProtocolV2ResourceManifestFiles({ manifest, targetsToUpdate });
1439
+ const binaries = new Map(files.map(file => [file.archivePath, file.binary]));
1440
+ return selected.map(file => {
1441
+ const binary = binaries.get(file.archive_path);
1442
+ if (!binary ||
1443
+ !isProtocolV2ResourceFileValid(binary, {
1444
+ size: file.size,
1445
+ fileHash: file.sha256,
1446
+ })) {
1447
+ throw new Error(`Pro2 resource manifest file verification failed: ${file.archive_path}`);
1448
+ }
1449
+ return {
1450
+ binary,
1451
+ devicePath: file.device_path,
1452
+ size: file.size,
1453
+ fileHash: file.sha256,
1454
+ };
1455
+ });
1456
+ }
1457
+ function bytesToHex$3(bytes) {
1458
+ return Array.from(bytes, byte => byte.toString(16).padStart(2, '0')).join('');
1459
+ }
1460
+ function isProtocolV2ResourceFileValid(binary, resource) {
1461
+ if (binary.byteLength !== resource.size)
1462
+ return false;
1463
+ return bytesToHex$3(sha256.sha256(new Uint8Array(binary))) === resource.fileHash.toLowerCase();
1464
+ }
1465
+
1268
1466
  const bindingError = (message) => {
1269
1467
  throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, message, {
1270
1468
  firmwareUpdateCode: 'FirmwareArtifactReaderInvalid',
@@ -1414,6 +1612,7 @@ const createCoreApi = (call) => ({
1414
1612
  getFirmwareUpdateHostBindingGeneration,
1415
1613
  prepareFirmwareUpdatePlan,
1416
1614
  validateFirmwareUpdatePreparedPlan,
1615
+ prepareProtocolV2ResourceFiles,
1417
1616
  getLogs: () => call({ method: 'getLogs' }),
1418
1617
  clearSessionCache: params => call(Object.assign(Object.assign({}, params), { method: 'clearSessionCache' })),
1419
1618
  searchDevices: params => call(Object.assign(Object.assign({}, params), { method: 'searchDevices' })),
@@ -40504,282 +40703,8 @@ const findLatestRelease = (releases) => {
40504
40703
  return leastRelease;
40505
40704
  };
40506
40705
 
40507
- const PROTOCOL_V2_RESOURCE_TYPES = [
40508
- 'images',
40509
- 'animation',
40510
- 'wallpaper',
40511
- 'translations',
40512
- 'roobert',
40513
- 'noto',
40514
- 'firmware_logo',
40515
- ];
40516
- const PROTOCOL_V2_RESOURCE_DEVICE_PATHS = {
40517
- images: 'vol0:/bundles/images/images.okpkg',
40518
- animation: 'vol0:/bundles/images/animation.okpkg',
40519
- wallpaper: 'vol0:/bundles/images/wallpaper.okpkg',
40520
- translations: 'vol0:/bundles/translations/translations.okpkg',
40521
- roobert: 'vol0:/bundles/font/roobert.okpkg',
40522
- noto: 'vol0:/bundles/font/noto.okpkg',
40523
- firmware_logo: 'vol0:/bundles/firmware_logo.okpkg',
40524
- };
40525
- const RESOURCE_TYPE_SET = new Set(PROTOCOL_V2_RESOURCE_TYPES);
40526
- const SHA256_HEX_LENGTH = 64;
40527
- const SHA3_512_HEX_LENGTH = 128;
40528
- const PROTOCOL_V2_OKPP_HEADER_SIZE$1 = 0x52a0;
40529
- const PROTOCOL_V2_OKPP_TYPE_OFFSET = 0x08;
40530
- const PROTOCOL_V2_OKPP_HEADER_LENGTH_OFFSET = 0x0c;
40531
- const PROTOCOL_V2_OKPP_HEADER_HASH_OFFSET$1 = 0x240;
40532
- const PROTOCOL_V2_OKPP_HASH_SIZE$1 = 64;
40533
- const PROTOCOL_V2_RESOURCE_IDENTITY_READ_SIZE = PROTOCOL_V2_OKPP_HEADER_HASH_OFFSET$1 + PROTOCOL_V2_OKPP_HASH_SIZE$1;
40534
- const PROTOCOL_V2_MIN_FILE_READ_CHUNK_SIZE = 64;
40535
- const PROTOCOL_V2_RESOURCE_INVENTORY_TIMEOUT_MS = 5 * 1000;
40536
- function toFiniteNumber(value) {
40537
- if (typeof value === 'number' && Number.isFinite(value))
40538
- return value;
40539
- if (typeof value === 'string') {
40540
- const numeric = Number(value);
40541
- return Number.isFinite(numeric) ? numeric : undefined;
40542
- }
40543
- if (value && typeof value === 'object') {
40544
- const longLike = value;
40545
- if (typeof longLike.toNumber === 'function') {
40546
- const numeric = longLike.toNumber();
40547
- return Number.isFinite(numeric) ? numeric : undefined;
40548
- }
40549
- }
40550
- return undefined;
40551
- }
40552
- function toUint8Array(value) {
40553
- if (value instanceof Uint8Array)
40554
- return value;
40555
- if (value instanceof ArrayBuffer)
40556
- return new Uint8Array(value);
40557
- if (ArrayBuffer.isView(value)) {
40558
- return new Uint8Array(value.buffer, value.byteOffset, value.byteLength);
40559
- }
40560
- if (typeof value === 'string') {
40561
- const hex = value.replace(/^0x/i, '');
40562
- if (!hex || hex.length % 2 !== 0 || /[^0-9a-f]/i.test(hex)) {
40563
- return new Uint8Array(0);
40564
- }
40565
- const bytes = new Uint8Array(hex.length / 2);
40566
- for (let index = 0; index < bytes.length; index += 1) {
40567
- bytes[index] = Number.parseInt(hex.slice(index * 2, index * 2 + 2), 16);
40568
- }
40569
- return bytes;
40570
- }
40571
- return new Uint8Array(0);
40572
- }
40573
- function readAscii(bytes, offset, length) {
40574
- return Array.from(bytes.slice(offset, offset + length), byte => String.fromCharCode(byte)).join('');
40575
- }
40576
- function parseProtocolV2ResourceHeaderHash(bytes) {
40577
- if (bytes.byteLength < PROTOCOL_V2_RESOURCE_IDENTITY_READ_SIZE)
40578
- return undefined;
40579
- if (readAscii(bytes, 0, 4) !== 'OKPP')
40580
- return undefined;
40581
- if (readAscii(bytes, PROTOCOL_V2_OKPP_TYPE_OFFSET, 4) !== 'RESC')
40582
- return undefined;
40583
- const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
40584
- if (view.getUint32(PROTOCOL_V2_OKPP_HEADER_LENGTH_OFFSET, true) !== PROTOCOL_V2_OKPP_HEADER_SIZE$1) {
40585
- return undefined;
40586
- }
40587
- return bytesToHex$3(bytes.slice(PROTOCOL_V2_OKPP_HEADER_HASH_OFFSET$1, PROTOCOL_V2_OKPP_HEADER_HASH_OFFSET$1 + PROTOCOL_V2_OKPP_HASH_SIZE$1));
40588
- }
40589
- function readProtocolV2ResourceIdentity({ commands, resource, chunkSize, timeoutMs = PROTOCOL_V2_RESOURCE_INVENTORY_TIMEOUT_MS, }) {
40590
- var _a, _b, _c, _d;
40591
- return __awaiter(this, void 0, void 0, function* () {
40592
- const path = PROTOCOL_V2_RESOURCE_DEVICE_PATHS[resource.type];
40593
- const pathInfo = yield commands.typedCall('FilesystemPathInfoQuery', 'FilesystemPathInfo', { path }, { timeoutMs });
40594
- const size = toFiniteNumber((_a = pathInfo.message) === null || _a === void 0 ? void 0 : _a.size);
40595
- if (!((_b = pathInfo.message) === null || _b === void 0 ? void 0 : _b.exist) ||
40596
- ((_c = pathInfo.message) === null || _c === void 0 ? void 0 : _c.directory) ||
40597
- !Number.isSafeInteger(size) ||
40598
- size !== resource.size ||
40599
- size < PROTOCOL_V2_OKPP_HEADER_SIZE$1) {
40600
- return undefined;
40601
- }
40602
- const header = new Uint8Array(PROTOCOL_V2_RESOURCE_IDENTITY_READ_SIZE);
40603
- let offset = 0;
40604
- while (offset < header.byteLength) {
40605
- const readLength = Math.min(chunkSize, header.byteLength - offset);
40606
- const response = yield commands.typedCall('FilesystemFileRead', 'FilesystemFile', {
40607
- file: { path, offset, total_size: 0 },
40608
- chunk_len: readLength,
40609
- }, { timeoutMs });
40610
- const data = toUint8Array((_d = response.message) === null || _d === void 0 ? void 0 : _d.data);
40611
- if (data.byteLength === 0)
40612
- return undefined;
40613
- const copied = Math.min(data.byteLength, header.byteLength - offset);
40614
- header.set(data.subarray(0, copied), offset);
40615
- offset += copied;
40616
- }
40617
- const headerHash = parseProtocolV2ResourceHeaderHash(header);
40618
- return headerHash ? { type: resource.type, size, headerHash } : undefined;
40619
- });
40620
- }
40621
- function readProtocolV2ResourceInventory({ commands, resources, chunkSize = hdTransport.PROTOCOL_V2_BLE_FILE_READ_CHUNK_SIZE, timeoutMs = PROTOCOL_V2_RESOURCE_INVENTORY_TIMEOUT_MS, }) {
40622
- return __awaiter(this, void 0, void 0, function* () {
40623
- const normalizedChunkSize = Number.isFinite(chunkSize)
40624
- ? Math.max(Math.floor(chunkSize), PROTOCOL_V2_MIN_FILE_READ_CHUNK_SIZE)
40625
- : hdTransport.PROTOCOL_V2_BLE_FILE_READ_CHUNK_SIZE;
40626
- const inventory = [];
40627
- for (const resource of resources) {
40628
- try {
40629
- const item = yield readProtocolV2ResourceIdentity({
40630
- commands,
40631
- resource,
40632
- chunkSize: normalizedChunkSize,
40633
- timeoutMs,
40634
- });
40635
- if (item)
40636
- inventory.push(item);
40637
- }
40638
- catch (_a) {
40639
- }
40640
- }
40641
- return inventory;
40642
- });
40643
- }
40644
- function normalizeHex$1(value, expectedLength, field) {
40645
- if (typeof value !== 'string') {
40646
- throw new Error(`Invalid Pro2 resource ${field}: expected a hexadecimal string`);
40647
- }
40648
- const normalized = value.replace(/^0x/i, '').toLowerCase();
40649
- if (normalized.length !== expectedLength || !/^[0-9a-f]+$/.test(normalized)) {
40650
- throw new Error(`Invalid Pro2 resource ${field}: expected ${expectedLength} hexadecimal characters`);
40651
- }
40652
- return normalized;
40653
- }
40654
- function validateResource(value, index) {
40655
- if (!value || typeof value !== 'object') {
40656
- throw new Error(`Invalid Pro2 resource at stable[${index}]`);
40657
- }
40658
- const resource = value;
40659
- if (typeof resource.type !== 'string' || !RESOURCE_TYPE_SET.has(resource.type)) {
40660
- throw new Error(`Invalid Pro2 resource type at stable[${index}]`);
40661
- }
40662
- if (typeof resource.url !== 'string' || !resource.url.startsWith('https://')) {
40663
- throw new Error(`Invalid Pro2 resource url at stable[${index}]`);
40664
- }
40665
- if (!Number.isSafeInteger(resource.size) || Number(resource.size) <= 0) {
40666
- throw new Error(`Invalid Pro2 resource size at stable[${index}]`);
40667
- }
40668
- return {
40669
- type: resource.type,
40670
- url: resource.url,
40671
- size: Number(resource.size),
40672
- fileHash: normalizeHex$1(resource.fileHash, SHA256_HEX_LENGTH, 'fileHash'),
40673
- headerHash: normalizeHex$1(resource.headerHash, SHA3_512_HEX_LENGTH, 'headerHash'),
40674
- };
40675
- }
40676
- function validateBootResources(value) {
40677
- if (!value || typeof value !== 'object') {
40678
- throw new Error('Invalid Pro2 boot resources config');
40679
- }
40680
- const resource = value;
40681
- if (resource.required !== false) {
40682
- throw new Error('Invalid Pro2 boot resources required flag: expected false');
40683
- }
40684
- if (resource.target !== 'RES') {
40685
- throw new Error('Invalid Pro2 boot resources target: expected RES');
40686
- }
40687
- if (resource.manifestUrl !== undefined &&
40688
- (typeof resource.manifestUrl !== 'string' || !resource.manifestUrl.startsWith('https://'))) {
40689
- throw new Error('Invalid Pro2 boot resources manifestUrl');
40690
- }
40691
- if (!Array.isArray(resource.files) || resource.files.length === 0) {
40692
- throw new Error('Invalid Pro2 boot resources files');
40693
- }
40694
- const files = resource.files.map((value, index) => {
40695
- if (!value || typeof value !== 'object') {
40696
- throw new Error(`Invalid Pro2 boot resource file at files[${index}]`);
40697
- }
40698
- const file = value;
40699
- if (typeof file.url !== 'string' || !file.url.startsWith('https://')) {
40700
- throw new Error(`Invalid Pro2 boot resource url at files[${index}]`);
40701
- }
40702
- if (typeof file.devicePath !== 'string' ||
40703
- !file.devicePath.startsWith('vol0:/') ||
40704
- file.devicePath.includes('..') ||
40705
- file.devicePath.includes('\\')) {
40706
- throw new Error(`Invalid Pro2 boot resource devicePath at files[${index}]`);
40707
- }
40708
- if (!Number.isSafeInteger(file.size) || Number(file.size) <= 0) {
40709
- throw new Error(`Invalid Pro2 boot resource size at files[${index}]`);
40710
- }
40711
- return Object.assign(Object.assign({}, (typeof file.name === 'string' && file.name ? { name: file.name } : undefined)), { url: file.url, devicePath: file.devicePath, size: Number(file.size), fileHash: normalizeHex$1(file.fileHash, SHA256_HEX_LENGTH, `boot files[${index}].fileHash`) });
40712
- });
40713
- if (new Set(files.map(file => file.devicePath)).size !== files.length) {
40714
- throw new Error('Invalid Pro2 boot resources files: duplicate devicePath');
40715
- }
40716
- return Object.assign(Object.assign({ required: false, target: 'RES' }, (resource.manifestUrl ? { manifestUrl: resource.manifestUrl } : undefined)), { files });
40717
- }
40718
- function parseProtocolV2Resources(value) {
40719
- if (value === undefined)
40720
- return undefined;
40721
- if (!value ||
40722
- typeof value !== 'object' ||
40723
- !Array.isArray(value.stable)) {
40724
- throw new Error('Invalid Pro2 resources config: stable must be an array');
40725
- }
40726
- const config = value;
40727
- const stable = config.stable.map(validateResource);
40728
- const types = new Set(stable.map(resource => resource.type));
40729
- if (stable.length !== PROTOCOL_V2_RESOURCE_TYPES.length || types.size !== stable.length) {
40730
- throw new Error(`Invalid Pro2 resources config: stable must contain ${PROTOCOL_V2_RESOURCE_TYPES.length} unique resource types`);
40731
- }
40732
- for (const type of PROTOCOL_V2_RESOURCE_TYPES) {
40733
- if (!types.has(type)) {
40734
- throw new Error(`Invalid Pro2 resources config: stable is missing ${type}`);
40735
- }
40736
- }
40737
- const boot = config.boot === undefined ? undefined : validateBootResources(config.boot);
40738
- return Object.assign({ stable: PROTOCOL_V2_RESOURCE_TYPES.map(type => {
40739
- const resource = stable.find(item => item.type === type);
40740
- if (!resource) {
40741
- throw new Error(`Invalid Pro2 resources config: stable is missing ${type}`);
40742
- }
40743
- return resource;
40744
- }) }, (boot ? { boot } : undefined));
40745
- }
40746
- function buildProtocolV2ResourceUpdatePlan({ resources, inventory, mode, forced = false, }) {
40747
- if (forced) {
40748
- return {
40749
- status: resources.length > 0 ? 'outdated' : 'valid',
40750
- resources: [...resources],
40751
- };
40752
- }
40753
- if (!inventory) {
40754
- return mode === 'bootloader-recovery'
40755
- ? {
40756
- status: resources.length > 0 ? 'outdated' : 'valid',
40757
- resources: [...resources],
40758
- }
40759
- : { status: 'unknown', resources: [] };
40760
- }
40761
- const inventoryByType = new Map(inventory.map(item => [item.type, item]));
40762
- const changedResources = resources.filter(resource => {
40763
- const current = inventoryByType.get(resource.type);
40764
- return (!current ||
40765
- current.size !== resource.size ||
40766
- current.headerHash.toLowerCase() !== resource.headerHash.toLowerCase());
40767
- });
40768
- return {
40769
- status: changedResources.length === 0 ? 'valid' : 'outdated',
40770
- resources: changedResources,
40771
- };
40772
- }
40773
- function bytesToHex$3(bytes) {
40774
- return Array.from(bytes, byte => byte.toString(16).padStart(2, '0')).join('');
40775
- }
40776
- function isProtocolV2ResourceFileValid(binary, resource) {
40777
- if (binary.byteLength !== resource.size)
40778
- return false;
40779
- return bytesToHex$3(sha256.sha256(new Uint8Array(binary))) === resource.fileHash.toLowerCase();
40780
- }
40781
-
40782
40706
  var _a$1;
40707
+ const FIRMWARE_UPDATE_CONFIG_FRESHNESS_MS = 5 * 60 * 1000;
40783
40708
  const Log$k = getLogger(exports.LoggerNames.Core);
40784
40709
  const FIRMWARE_FIELDS = [
40785
40710
  'firmware',
@@ -40920,6 +40845,7 @@ class DataManager {
40920
40845
  this.assets = {
40921
40846
  bridge: data.bridge,
40922
40847
  };
40848
+ this.lastCheckTimestamp = getTimeStamp();
40923
40849
  }
40924
40850
  static updateEnv(newEnv) {
40925
40851
  if (this.settings) {
@@ -40943,6 +40869,14 @@ class DataManager {
40943
40869
  if (!this.settings) {
40944
40870
  throw new Error('Remote config settings are not initialized');
40945
40871
  }
40872
+ const hasFreshConfig = this.lastCheckTimestamp > 0 &&
40873
+ getTimeStamp() - this.lastCheckTimestamp <= FIRMWARE_UPDATE_CONFIG_FRESHNESS_MS;
40874
+ if (hasFreshConfig) {
40875
+ if (requireResources && this.protocolV2ResourcesConfigError) {
40876
+ throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.FirmwareUpdateDownloadFailed, `Invalid Pro2 resources config: ${this.protocolV2ResourcesConfigError.message}`);
40877
+ }
40878
+ return;
40879
+ }
40946
40880
  const loaded = yield this.load(this.settings);
40947
40881
  if (!loaded) {
40948
40882
  throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.NetworkError, 'Unable to refresh the latest remote config');
@@ -40953,13 +40887,9 @@ class DataManager {
40953
40887
  this.lastCheckTimestamp = getTimeStamp();
40954
40888
  });
40955
40889
  }
40956
- static getProtocolV2Resources(deviceType = hdShared.EDeviceType.Pro2) {
40957
- var _b, _c;
40958
- return (_c = (_b = this.deviceMap[deviceType]) === null || _b === void 0 ? void 0 : _b.resources) === null || _c === void 0 ? void 0 : _c.stable;
40959
- }
40960
- static getProtocolV2BootResources(deviceType = hdShared.EDeviceType.Pro2) {
40890
+ static getProtocolV2ResourceSource(deviceType = hdShared.EDeviceType.Pro2) {
40961
40891
  var _b, _c;
40962
- return (_c = (_b = this.deviceMap[deviceType]) === null || _b === void 0 ? void 0 : _b.resources) === null || _c === void 0 ? void 0 : _c.boot;
40892
+ return (_c = (_b = this.deviceMap[deviceType]) === null || _b === void 0 ? void 0 : _b.resources) === null || _c === void 0 ? void 0 : _c.source;
40963
40893
  }
40964
40894
  static getProtobufMessages(schema = 'v1CurrentSchema') {
40965
40895
  return this.messages[schema];
@@ -42996,11 +42926,15 @@ const getNftSize = ({ deviceType, thumbnail, }) => {
42996
42926
  full: { width: PRO2_NFT_IMAGE_WIDTH, height: PRO2_NFT_IMAGE_HEIGHT },
42997
42927
  thumbnail: { width: PRO2_NFT_THUMBNAIL_WIDTH, height: PRO2_NFT_THUMBNAIL_HEIGHT },
42998
42928
  },
42929
+ neo: {
42930
+ full: { width: PRO2_NFT_IMAGE_WIDTH, height: PRO2_NFT_IMAGE_HEIGHT },
42931
+ thumbnail: { width: PRO2_NFT_THUMBNAIL_WIDTH, height: PRO2_NFT_THUMBNAIL_HEIGHT },
42932
+ },
42999
42933
  };
43000
42934
  return (_a = sizes[deviceType]) === null || _a === void 0 ? void 0 : _a[thumbnail ? 'thumbnail' : 'full'];
43001
42935
  };
43002
42936
  const getHomeScreenSize = ({ deviceType, homeScreenType, thumbnail, }) => {
43003
- if (deviceType === hdShared.EDeviceType.Pro2) {
42937
+ if (deviceType === hdShared.EDeviceType.Pro2 || deviceType === hdShared.EDeviceType.Neo) {
43004
42938
  return thumbnail ? undefined : { width: PRO2_WALLPAPER_WIDTH, height: PRO2_WALLPAPER_HEIGHT };
43005
42939
  }
43006
42940
  const sizes = {
@@ -44138,6 +44072,123 @@ const buildProtocolV1FeaturesPayload = (protocolV1Features, previous) => {
44138
44072
  } });
44139
44073
  };
44140
44074
 
44075
+ const normalizeEnumValue = (enumObject, value) => {
44076
+ if (value == null)
44077
+ return null;
44078
+ if (typeof value === 'string')
44079
+ return value;
44080
+ const label = enumObject[value];
44081
+ return typeof label === 'string' ? label : null;
44082
+ };
44083
+ const getProtocolV2SeState = (se) => {
44084
+ const label = normalizeEnumValue(hdTransport.DeviceSEState, se === null || se === void 0 ? void 0 : se.state);
44085
+ switch (label) {
44086
+ case 'BOOT':
44087
+ return 'BOOT';
44088
+ case 'APP_FACTORY':
44089
+ return 'APP_FACTORY';
44090
+ case 'APP':
44091
+ return 'APP';
44092
+ default:
44093
+ return null;
44094
+ }
44095
+ };
44096
+ const getProtocolV2SeType = (se) => normalizeEnumValue(hdTransport.DeviceSeType, se === null || se === void 0 ? void 0 : se.type);
44097
+ const parseProtocolV2BuildFingerprint = (buildFingerprint) => {
44098
+ if (!buildFingerprint)
44099
+ return null;
44100
+ const [binary, version, commit, environment, buildType, ...extra] = buildFingerprint.split('__');
44101
+ if (extra.length > 0 ||
44102
+ (binary !== 'application' && binary !== 'bootloader' && binary !== 'romloader') ||
44103
+ !version ||
44104
+ !commit ||
44105
+ (environment !== 'PROD' && environment !== 'DEV') ||
44106
+ (buildType !== 'DEBUG' && buildType !== 'RELEASE')) {
44107
+ return null;
44108
+ }
44109
+ return { binary, version, commit, environment, buildType };
44110
+ };
44111
+ const getProtocolV2RuntimeMode = (protocolInfo) => {
44112
+ var _a;
44113
+ const binary = (_a = parseProtocolV2BuildFingerprint(protocolInfo.build_fingerprint)) === null || _a === void 0 ? void 0 : _a.binary;
44114
+ if (binary === 'application')
44115
+ return 'normal';
44116
+ return binary;
44117
+ };
44118
+ const PROTOCOL_V2_DEVICE_STATUS_GET_MESSAGE_TYPE = 60602;
44119
+ const supportsProtocolV2Message = (protocolInfo, messageType) => protocolInfo.supported_messages.includes(messageType);
44120
+ const PROTOCOL_V2_FEATURES_DEVICE_INFO_REQUEST = {
44121
+ targets: {
44122
+ hw: true,
44123
+ fw: true,
44124
+ coprocessor: true,
44125
+ },
44126
+ types: {
44127
+ version: true,
44128
+ specific: true,
44129
+ },
44130
+ };
44131
+ const PROTOCOL_V2_VERSIONS_DEVICE_INFO_REQUEST = {
44132
+ targets: {
44133
+ hw: true,
44134
+ fw: true,
44135
+ coprocessor: true,
44136
+ se1: true,
44137
+ se2: true,
44138
+ se3: true,
44139
+ se4: true,
44140
+ },
44141
+ types: {
44142
+ version: true,
44143
+ specific: true,
44144
+ },
44145
+ };
44146
+ const PROTOCOL_V2_FULL_DEVICE_INFO_REQUEST = {
44147
+ targets: {
44148
+ hw: true,
44149
+ fw: true,
44150
+ coprocessor: true,
44151
+ se1: true,
44152
+ se2: true,
44153
+ se3: true,
44154
+ se4: true,
44155
+ },
44156
+ types: {
44157
+ version: true,
44158
+ build_id: true,
44159
+ hash: true,
44160
+ specific: true,
44161
+ },
44162
+ };
44163
+ const PROTOCOL_V2_DEVICE_INFO_TIMEOUT_MS = 30 * 1000;
44164
+ function requestProtocolV2ProtocolInfo({ commands, timeoutMs, }) {
44165
+ return __awaiter(this, void 0, void 0, function* () {
44166
+ const response = timeoutMs === undefined
44167
+ ? yield commands.typedCall('ProtocolInfoRequest', 'ProtocolInfo', {
44168
+ eventless_wallet_session: true,
44169
+ })
44170
+ : yield commands.typedCall('ProtocolInfoRequest', 'ProtocolInfo', { eventless_wallet_session: true }, { timeoutMs });
44171
+ return response.message;
44172
+ });
44173
+ }
44174
+ function requestProtocolV2DeviceInfo({ commands, timeoutMs = PROTOCOL_V2_DEVICE_INFO_TIMEOUT_MS, request = PROTOCOL_V2_FEATURES_DEVICE_INFO_REQUEST, }) {
44175
+ return __awaiter(this, void 0, void 0, function* () {
44176
+ const { message } = yield commands.typedCall('DeviceInfoGet', 'DeviceInfo', request, {
44177
+ timeoutMs,
44178
+ });
44179
+ return message;
44180
+ });
44181
+ }
44182
+ function requestProtocolV2DeviceStatus({ commands, timeoutMs, }) {
44183
+ return __awaiter(this, void 0, void 0, function* () {
44184
+ const response = timeoutMs === undefined
44185
+ ? yield commands.typedCall('DeviceStatusGet', 'DeviceStatus', {})
44186
+ : yield commands.typedCall('DeviceStatusGet', 'DeviceStatus', {}, { timeoutMs });
44187
+ const { message } = response;
44188
+ return message;
44189
+ });
44190
+ }
44191
+
44141
44192
  const definedEntries = (value) => Object.fromEntries(Object.entries(value).filter(([, fieldValue]) => fieldValue !== undefined));
44142
44193
  const sanitizeRawFeatures = (features) => {
44143
44194
  if (!features.raw)
@@ -44265,6 +44316,11 @@ const meaningfulVersion = (version) => {
44265
44316
  parts.push('0');
44266
44317
  return parts.map(part => (Number.isNaN(Number.parseInt(part, 10)) ? '0' : part)).join('.');
44267
44318
  };
44319
+ const meaningfulText = (value) => {
44320
+ if (value === undefined || value === null || value === '')
44321
+ return null;
44322
+ return String(value);
44323
+ };
44268
44324
  const mapProtocolV1OnekeyFeaturesToState = (features) => {
44269
44325
  const verification = definedEntries({
44270
44326
  firmwareBuildId: features.onekey_firmware_build_id,
@@ -44305,7 +44361,24 @@ const mapProtocolV1OnekeyFeaturesToState = (features) => {
44305
44361
  se02Boot: meaningfulVersion(features.onekey_se02_boot_version),
44306
44362
  se03Boot: meaningfulVersion(features.onekey_se03_boot_version),
44307
44363
  se04Boot: meaningfulVersion(features.onekey_se04_boot_version),
44308
- }) }, (Object.keys(verification).length > 0 ? { verification } : {})), { raw: { protocolV1OneKeyFeatures: features } });
44364
+ }) }, (Object.keys(verification).length > 0 ? { verification } : {})), { securityElements: {
44365
+ se01: {
44366
+ type: meaningfulText(features.onekey_se_type),
44367
+ state: meaningfulText(features.onekey_se01_state),
44368
+ },
44369
+ se02: {
44370
+ type: null,
44371
+ state: meaningfulText(features.onekey_se02_state),
44372
+ },
44373
+ se03: {
44374
+ type: null,
44375
+ state: meaningfulText(features.onekey_se03_state),
44376
+ },
44377
+ se04: {
44378
+ type: null,
44379
+ state: meaningfulText(features.onekey_se04_state),
44380
+ },
44381
+ }, raw: { protocolV1OneKeyFeatures: features } });
44309
44382
  };
44310
44383
  const mapProtocolV2DeviceInfoToState = (info, mode = 'unknown') => {
44311
44384
  var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20;
@@ -44385,6 +44458,24 @@ const mapProtocolV2DeviceInfoToState = (info, mode = 'unknown') => {
44385
44458
  se04BootBuildId: imageBuildId((_19 = info.se4) === null || _19 === void 0 ? void 0 : _19.bootloader),
44386
44459
  se04BootHash: imageHash((_20 = info.se4) === null || _20 === void 0 ? void 0 : _20.bootloader),
44387
44460
  }),
44461
+ securityElements: {
44462
+ se01: {
44463
+ type: getProtocolV2SeType(info.se1),
44464
+ state: getProtocolV2SeState(info.se1),
44465
+ },
44466
+ se02: {
44467
+ type: getProtocolV2SeType(info.se2),
44468
+ state: getProtocolV2SeState(info.se2),
44469
+ },
44470
+ se03: {
44471
+ type: getProtocolV2SeType(info.se3),
44472
+ state: getProtocolV2SeState(info.se3),
44473
+ },
44474
+ se04: {
44475
+ type: getProtocolV2SeType(info.se4),
44476
+ state: getProtocolV2SeState(info.se4),
44477
+ },
44478
+ },
44388
44479
  raw: Object.assign({ protocolV2DeviceInfo: info }, (loader ? { protocolV2DeviceStatus: null } : {})),
44389
44480
  };
44390
44481
  };
@@ -44485,6 +44576,57 @@ const cloneDeviceState = (value) => {
44485
44576
  };
44486
44577
 
44487
44578
  const getBootloaderMode = (state) => state.status.mode === 'bootloader' || state.status.mode === 'romloader';
44579
+ const projectLegacyAdvancedFields = (state) => {
44580
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o;
44581
+ const verification = (_a = state.verification) !== null && _a !== void 0 ? _a : {};
44582
+ const securityElements = (_b = state.securityElements) !== null && _b !== void 0 ? _b : {};
44583
+ return {
44584
+ onekey_device_type: state.identity.deviceType,
44585
+ onekey_serial_no: state.identity.serialNo,
44586
+ onekey_se_type: (_h = (_f = (_d = (_c = securityElements.se01) === null || _c === void 0 ? void 0 : _c.type) !== null && _d !== void 0 ? _d : (_e = securityElements.se02) === null || _e === void 0 ? void 0 : _e.type) !== null && _f !== void 0 ? _f : (_g = securityElements.se03) === null || _g === void 0 ? void 0 : _g.type) !== null && _h !== void 0 ? _h : (_j = securityElements.se04) === null || _j === void 0 ? void 0 : _j.type,
44587
+ onekey_board_version: state.versions.board,
44588
+ onekey_board_hash: verification.boardHash,
44589
+ onekey_board_build_id: verification.boardBuildId,
44590
+ onekey_boot_version: state.versions.bootloader,
44591
+ onekey_boot_hash: verification.bootloaderHash,
44592
+ onekey_boot_build_id: verification.bootloaderBuildId,
44593
+ onekey_firmware_version: state.versions.firmware,
44594
+ onekey_firmware_hash: verification.firmwareHash,
44595
+ onekey_firmware_build_id: verification.firmwareBuildId,
44596
+ onekey_ble_version: state.versions.ble,
44597
+ onekey_ble_hash: verification.bleHash,
44598
+ onekey_ble_build_id: verification.bleBuildId,
44599
+ onekey_ble_name: state.identity.bleName,
44600
+ onekey_se01_version: state.versions.se01,
44601
+ onekey_se01_hash: verification.se01Hash,
44602
+ onekey_se01_build_id: verification.se01BuildId,
44603
+ onekey_se01_state: (_k = securityElements.se01) === null || _k === void 0 ? void 0 : _k.state,
44604
+ onekey_se01_boot_version: state.versions.se01Boot,
44605
+ onekey_se01_boot_hash: verification.se01BootHash,
44606
+ onekey_se01_boot_build_id: verification.se01BootBuildId,
44607
+ onekey_se02_version: state.versions.se02,
44608
+ onekey_se02_hash: verification.se02Hash,
44609
+ onekey_se02_build_id: verification.se02BuildId,
44610
+ onekey_se02_state: (_l = securityElements.se02) === null || _l === void 0 ? void 0 : _l.state,
44611
+ onekey_se02_boot_version: state.versions.se02Boot,
44612
+ onekey_se02_boot_hash: verification.se02BootHash,
44613
+ onekey_se02_boot_build_id: verification.se02BootBuildId,
44614
+ onekey_se03_version: state.versions.se03,
44615
+ onekey_se03_hash: verification.se03Hash,
44616
+ onekey_se03_build_id: verification.se03BuildId,
44617
+ onekey_se03_state: (_m = securityElements.se03) === null || _m === void 0 ? void 0 : _m.state,
44618
+ onekey_se03_boot_version: state.versions.se03Boot,
44619
+ onekey_se03_boot_hash: verification.se03BootHash,
44620
+ onekey_se03_boot_build_id: verification.se03BootBuildId,
44621
+ onekey_se04_version: state.versions.se04,
44622
+ onekey_se04_hash: verification.se04Hash,
44623
+ onekey_se04_build_id: verification.se04BuildId,
44624
+ onekey_se04_state: (_o = securityElements.se04) === null || _o === void 0 ? void 0 : _o.state,
44625
+ onekey_se04_boot_version: state.versions.se04Boot,
44626
+ onekey_se04_boot_hash: verification.se04BootHash,
44627
+ onekey_se04_boot_build_id: verification.se04BootBuildId,
44628
+ };
44629
+ };
44488
44630
  const projectFeatures = (state) => {
44489
44631
  var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
44490
44632
  const snapshot = cloneDeviceState(state);
@@ -44497,7 +44639,8 @@ const projectFeatures = (state) => {
44497
44639
  const bootloaderMode = snapshot.protocol === 'V1'
44498
44640
  ? (_e = rawFeatures.bootloader_mode) !== null && _e !== void 0 ? _e : null
44499
44641
  : getBootloaderMode(snapshot);
44500
- return Object.assign(Object.assign(Object.assign({}, publicRawFeatures), rawOneKeyFeatures), { protocol: snapshot.protocol, protocolVersion: (_f = snapshot.protocolVersion) !== null && _f !== void 0 ? _f : (snapshot.protocol === 'V1' ? 1 : null), deviceType: snapshot.identity.deviceType, firmwareType: snapshot.identity.firmwareType, model: snapshot.identity.model, vendor: snapshot.identity.vendor, deviceId: snapshot.identity.deviceId, serialNo: snapshot.identity.serialNo, label: snapshot.identity.label, bleName: snapshot.identity.bleName, capabilities: snapshot.capabilities, mode: snapshot.status.mode, initialized: snapshot.status.initialized, bootloaderMode, unlocked: snapshot.status.unlocked, firmwarePresent: snapshot.status.firmwarePresent, passphraseProtection: snapshot.status.passphraseProtection, pinProtection: snapshot.status.pinProtection, backupRequired: snapshot.status.backupRequired, noBackup: snapshot.status.noBackup, unfinishedBackup: snapshot.status.unfinishedBackup, recoveryMode: snapshot.status.recoveryMode, attachToPinEnabled: snapshot.status.attachToPinEnabled, unlockedAttachPin: (_g = snapshot.status.unlockedAttachPin) !== null && _g !== void 0 ? _g : undefined, language: snapshot.settings.language, bleEnabled: snapshot.settings.bleEnabled, sdCardPresent: snapshot.settings.sdCardPresent, sdProtection: snapshot.settings.sdProtection, wipeCodeProtection: snapshot.settings.wipeCodeProtection, passphraseAlwaysOnDevice: snapshot.settings.passphraseAlwaysOnDevice, safetyChecks: snapshot.settings.safetyChecks, autoLockDelayMs: snapshot.settings.autoLockDelayMs, autoShutdownDelayMs: snapshot.settings.autoShutdownDelayMs, displayRotation: snapshot.settings.displayRotation, experimentalFeatures: snapshot.settings.experimentalFeatures, wallpaperPath: snapshot.settings.wallpaperPath, brightness: snapshot.settings.brightness, animationEnabled: snapshot.settings.animationEnabled, tapToWake: snapshot.settings.tapToWake, hapticFeedback: snapshot.settings.hapticFeedback, deviceNameDisplayEnabled: snapshot.settings.deviceNameDisplayEnabled, airgapMode: snapshot.settings.airgapMode, fidoEnabled: snapshot.settings.fidoEnabled, usbLockEnabled: snapshot.settings.usbLockEnabled, randomKeypad: snapshot.settings.randomKeypad, firmwareVersion: snapshot.versions.firmware, bootloaderVersion: snapshot.versions.bootloader, boardVersion: snapshot.versions.board, bleVersion: snapshot.versions.ble, se01Version: snapshot.versions.se01, se02Version: snapshot.versions.se02, se03Version: snapshot.versions.se03, se04Version: snapshot.versions.se04, se01BootVersion: snapshot.versions.se01Boot, se02BootVersion: snapshot.versions.se02Boot, se03BootVersion: snapshot.versions.se03Boot, se04BootVersion: snapshot.versions.se04Boot, seVersion: (_h = snapshot.versions.se) !== null && _h !== void 0 ? _h : null, verify: snapshot.verification, device_id: (_j = snapshot.identity.deviceId) !== null && _j !== void 0 ? _j : undefined, ble_name: (_k = snapshot.identity.bleName) !== null && _k !== void 0 ? _k : undefined, passphrase_protection: (_l = snapshot.status.passphraseProtection) !== null && _l !== void 0 ? _l : undefined, bootloader_mode: bootloaderMode, sessionId: null, session_id: null });
44642
+ const legacyAdvancedFields = projectLegacyAdvancedFields(snapshot);
44643
+ return Object.assign(Object.assign(Object.assign(Object.assign({}, publicRawFeatures), rawOneKeyFeatures), legacyAdvancedFields), { protocol: snapshot.protocol, protocolVersion: (_f = snapshot.protocolVersion) !== null && _f !== void 0 ? _f : (snapshot.protocol === 'V1' ? 1 : null), deviceType: snapshot.identity.deviceType, firmwareType: snapshot.identity.firmwareType, model: snapshot.identity.model, vendor: snapshot.identity.vendor, deviceId: snapshot.identity.deviceId, serialNo: snapshot.identity.serialNo, label: snapshot.identity.label, bleName: snapshot.identity.bleName, capabilities: snapshot.capabilities, mode: snapshot.status.mode, initialized: snapshot.status.initialized, bootloaderMode, unlocked: snapshot.status.unlocked, firmwarePresent: snapshot.status.firmwarePresent, passphraseProtection: snapshot.status.passphraseProtection, pinProtection: snapshot.status.pinProtection, backupRequired: snapshot.status.backupRequired, noBackup: snapshot.status.noBackup, unfinishedBackup: snapshot.status.unfinishedBackup, recoveryMode: snapshot.status.recoveryMode, attachToPinEnabled: snapshot.status.attachToPinEnabled, unlockedAttachPin: (_g = snapshot.status.unlockedAttachPin) !== null && _g !== void 0 ? _g : undefined, language: snapshot.settings.language, bleEnabled: snapshot.settings.bleEnabled, sdCardPresent: snapshot.settings.sdCardPresent, sdProtection: snapshot.settings.sdProtection, wipeCodeProtection: snapshot.settings.wipeCodeProtection, passphraseAlwaysOnDevice: snapshot.settings.passphraseAlwaysOnDevice, safetyChecks: snapshot.settings.safetyChecks, autoLockDelayMs: snapshot.settings.autoLockDelayMs, autoShutdownDelayMs: snapshot.settings.autoShutdownDelayMs, displayRotation: snapshot.settings.displayRotation, experimentalFeatures: snapshot.settings.experimentalFeatures, wallpaperPath: snapshot.settings.wallpaperPath, brightness: snapshot.settings.brightness, animationEnabled: snapshot.settings.animationEnabled, tapToWake: snapshot.settings.tapToWake, hapticFeedback: snapshot.settings.hapticFeedback, deviceNameDisplayEnabled: snapshot.settings.deviceNameDisplayEnabled, airgapMode: snapshot.settings.airgapMode, fidoEnabled: snapshot.settings.fidoEnabled, usbLockEnabled: snapshot.settings.usbLockEnabled, randomKeypad: snapshot.settings.randomKeypad, firmwareVersion: snapshot.versions.firmware, bootloaderVersion: snapshot.versions.bootloader, boardVersion: snapshot.versions.board, bleVersion: snapshot.versions.ble, se01Version: snapshot.versions.se01, se02Version: snapshot.versions.se02, se03Version: snapshot.versions.se03, se04Version: snapshot.versions.se04, se01BootVersion: snapshot.versions.se01Boot, se02BootVersion: snapshot.versions.se02Boot, se03BootVersion: snapshot.versions.se03Boot, se04BootVersion: snapshot.versions.se04Boot, seVersion: (_h = snapshot.versions.se) !== null && _h !== void 0 ? _h : null, verify: snapshot.verification, device_id: (_j = snapshot.identity.deviceId) !== null && _j !== void 0 ? _j : undefined, ble_name: (_k = snapshot.identity.bleName) !== null && _k !== void 0 ? _k : undefined, passphrase_protection: (_l = snapshot.status.passphraseProtection) !== null && _l !== void 0 ? _l : undefined, bootloader_mode: bootloaderMode, sessionId: null, session_id: null });
44501
44644
  };
44502
44645
 
44503
44646
  function createEmptyDeviceState(identity = {}) {
@@ -44564,6 +44707,21 @@ const applySectionPatch = (target, patch, prefix, changedKeys) => {
44564
44707
  }
44565
44708
  }
44566
44709
  };
44710
+ const mergeSecurityElements = (current, patch) => {
44711
+ var _a, _b;
44712
+ const merged = cloneDeviceState(current !== null && current !== void 0 ? current : {});
44713
+ for (const key of Object.keys(patch)) {
44714
+ const elementPatch = patch[key];
44715
+ if (elementPatch !== undefined) {
44716
+ const currentElement = merged[key];
44717
+ merged[key] = {
44718
+ type: elementPatch.type !== undefined ? elementPatch.type : (_a = currentElement === null || currentElement === void 0 ? void 0 : currentElement.type) !== null && _a !== void 0 ? _a : null,
44719
+ state: elementPatch.state !== undefined ? elementPatch.state : (_b = currentElement === null || currentElement === void 0 ? void 0 : currentElement.state) !== null && _b !== void 0 ? _b : null,
44720
+ };
44721
+ }
44722
+ }
44723
+ return merged;
44724
+ };
44567
44725
  class DeviceStateStore {
44568
44726
  constructor(initial) {
44569
44727
  this.state = initial ? cloneDeviceState(initial) : undefined;
@@ -44602,6 +44760,13 @@ class DeviceStateStore {
44602
44760
  applySectionPatch(next.settings, patch.settings, 'settings', changedKeys);
44603
44761
  if (patch.versions)
44604
44762
  applySectionPatch(next.versions, patch.versions, 'versions', changedKeys);
44763
+ if (patch.securityElements !== undefined) {
44764
+ const mergedSecurityElements = mergeSecurityElements(next.securityElements, patch.securityElements);
44765
+ if (!isEqual(next.securityElements, mergedSecurityElements)) {
44766
+ next.securityElements = mergedSecurityElements;
44767
+ changedKeys.push('securityElements');
44768
+ }
44769
+ }
44605
44770
  if (patch.capabilities !== undefined && !isEqual(next.capabilities, patch.capabilities)) {
44606
44771
  next.capabilities = cloneDeviceState(patch.capabilities);
44607
44772
  changedKeys.push('capabilities');
@@ -44773,101 +44938,6 @@ class DeviceWalletSessionStore {
44773
44938
  }
44774
44939
  const deviceWalletSessionStore = new DeviceWalletSessionStore();
44775
44940
 
44776
- const parseProtocolV2BuildFingerprint = (buildFingerprint) => {
44777
- if (!buildFingerprint)
44778
- return null;
44779
- const [binary, version, commit, environment, buildType, ...extra] = buildFingerprint.split('__');
44780
- if (extra.length > 0 ||
44781
- (binary !== 'application' && binary !== 'bootloader' && binary !== 'romloader') ||
44782
- !version ||
44783
- !commit ||
44784
- (environment !== 'PROD' && environment !== 'DEV') ||
44785
- (buildType !== 'DEBUG' && buildType !== 'RELEASE')) {
44786
- return null;
44787
- }
44788
- return { binary, version, commit, environment, buildType };
44789
- };
44790
- const getProtocolV2RuntimeMode = (protocolInfo) => {
44791
- var _a;
44792
- const binary = (_a = parseProtocolV2BuildFingerprint(protocolInfo.build_fingerprint)) === null || _a === void 0 ? void 0 : _a.binary;
44793
- if (binary === 'application')
44794
- return 'normal';
44795
- return binary;
44796
- };
44797
- const PROTOCOL_V2_DEVICE_STATUS_GET_MESSAGE_TYPE = 60602;
44798
- const supportsProtocolV2Message = (protocolInfo, messageType) => protocolInfo.supported_messages.includes(messageType);
44799
- const PROTOCOL_V2_FEATURES_DEVICE_INFO_REQUEST = {
44800
- targets: {
44801
- hw: true,
44802
- fw: true,
44803
- coprocessor: true,
44804
- },
44805
- types: {
44806
- version: true,
44807
- specific: true,
44808
- },
44809
- };
44810
- const PROTOCOL_V2_VERSIONS_DEVICE_INFO_REQUEST = {
44811
- targets: {
44812
- hw: true,
44813
- fw: true,
44814
- coprocessor: true,
44815
- se1: true,
44816
- se2: true,
44817
- se3: true,
44818
- se4: true,
44819
- },
44820
- types: {
44821
- version: true,
44822
- specific: true,
44823
- },
44824
- };
44825
- const PROTOCOL_V2_FULL_DEVICE_INFO_REQUEST = {
44826
- targets: {
44827
- hw: true,
44828
- fw: true,
44829
- coprocessor: true,
44830
- se1: true,
44831
- se2: true,
44832
- se3: true,
44833
- se4: true,
44834
- },
44835
- types: {
44836
- version: true,
44837
- build_id: true,
44838
- hash: true,
44839
- specific: true,
44840
- },
44841
- };
44842
- const PROTOCOL_V2_DEVICE_INFO_TIMEOUT_MS = 30 * 1000;
44843
- function requestProtocolV2ProtocolInfo({ commands, timeoutMs, }) {
44844
- return __awaiter(this, void 0, void 0, function* () {
44845
- const response = timeoutMs === undefined
44846
- ? yield commands.typedCall('ProtocolInfoRequest', 'ProtocolInfo', {
44847
- eventless_wallet_session: true,
44848
- })
44849
- : yield commands.typedCall('ProtocolInfoRequest', 'ProtocolInfo', { eventless_wallet_session: true }, { timeoutMs });
44850
- return response.message;
44851
- });
44852
- }
44853
- function requestProtocolV2DeviceInfo({ commands, timeoutMs = PROTOCOL_V2_DEVICE_INFO_TIMEOUT_MS, request = PROTOCOL_V2_FEATURES_DEVICE_INFO_REQUEST, }) {
44854
- return __awaiter(this, void 0, void 0, function* () {
44855
- const { message } = yield commands.typedCall('DeviceInfoGet', 'DeviceInfo', request, {
44856
- timeoutMs,
44857
- });
44858
- return message;
44859
- });
44860
- }
44861
- function requestProtocolV2DeviceStatus({ commands, timeoutMs, }) {
44862
- return __awaiter(this, void 0, void 0, function* () {
44863
- const response = timeoutMs === undefined
44864
- ? yield commands.typedCall('DeviceStatusGet', 'DeviceStatus', {})
44865
- : yield commands.typedCall('DeviceStatusGet', 'DeviceStatus', {}, { timeoutMs });
44866
- const { message } = response;
44867
- return message;
44868
- });
44869
- }
44870
-
44871
44941
  const parseRunOptions = (options) => {
44872
44942
  if (!options)
44873
44943
  options = {};
@@ -47681,34 +47751,9 @@ class CheckAllFirmwareRelease extends BaseMethod {
47681
47751
  deviceType: state.identity.deviceType,
47682
47752
  });
47683
47753
  const resourceDeviceType = state.identity.deviceType === 'neo' ? hdShared.EDeviceType.Neo : hdShared.EDeviceType.Pro2;
47684
- const resources = DataManager.getProtocolV2Resources(resourceDeviceType);
47685
- let resourceStatus = 'unknown';
47686
- if (resources === null || resources === void 0 ? void 0 : resources.length) {
47687
- const loaderMode = state.status.mode === 'bootloader' || state.status.mode === 'romloader';
47688
- if (loaderMode) {
47689
- try {
47690
- const inventory = yield readProtocolV2ResourceInventory({
47691
- commands: this.device.getCommands(),
47692
- resources,
47693
- });
47694
- resourceStatus = buildProtocolV2ResourceUpdatePlan({
47695
- resources,
47696
- inventory,
47697
- mode: 'bootloader-recovery',
47698
- }).status;
47699
- }
47700
- catch (_b) {
47701
- resourceStatus = buildProtocolV2ResourceUpdatePlan({
47702
- resources,
47703
- mode: 'bootloader-recovery',
47704
- }).status;
47705
- }
47706
- }
47707
- }
47708
- const targetsToUpdate = [
47709
- ...plan.targetsToUpdate,
47710
- ...(resourceStatus === 'outdated' ? ['resource'] : []),
47711
- ];
47754
+ const resourceSource = DataManager.getProtocolV2ResourceSource(resourceDeviceType);
47755
+ const resourceStatus = 'unknown';
47756
+ const targetsToUpdate = [...plan.targetsToUpdate];
47712
47757
  const firmwareStatus = plan.status === 'unavailable' ? 'unknown' : plan.status;
47713
47758
  const emptyRelease = 'none';
47714
47759
  return Object.assign(Object.assign({ firmware: {
@@ -47722,7 +47767,7 @@ class CheckAllFirmwareRelease extends BaseMethod {
47722
47767
  }, bootloader: {
47723
47768
  status: 'valid',
47724
47769
  release: emptyRelease,
47725
- }, features, protocol: 'V2', deviceType: state.identity.deviceType }, plan), { resourceStatus, hasUpgrade: plan.hasUpgrade || resourceStatus === 'outdated', targetsToUpdate });
47770
+ }, features, protocol: 'V2', deviceType: state.identity.deviceType }, plan), { resourceStatus, resourceManifestUrl: resourceSource === null || resourceSource === void 0 ? void 0 : resourceSource.manifestUrl, hasUpgrade: plan.hasUpgrade, targetsToUpdate });
47726
47771
  });
47727
47772
  }
47728
47773
  }
@@ -51035,6 +51080,14 @@ const PROTOCOL_V2_REMOTE_COMPONENT_TARGETS = {
51035
51080
  },
51036
51081
  };
51037
51082
  const PROTOCOL_V2_FIRMWARE_STAGING_PATHS = new Set(Object.values(PROTOCOL_V2_REMOTE_COMPONENT_TARGETS).map(target => `${PROTOCOL_V2_FIRMWARE_STAGING_VOLUME}${target.fileName}`));
51083
+ const PROTOCOL_V2_BOOT_RESOURCE_PACKAGE_PATH = 'vol0:/loaders/bootloader/boot_resource.okpkg';
51084
+ const PROTOCOL_V2_BOOT_RESOURCE_PACKAGE_STAGING_PATH = `${PROTOCOL_V2_BOOT_RESOURCE_PACKAGE_PATH}.staging`;
51085
+ const resolveProtocolV2ResourceWritePath = (devicePath) => {
51086
+ const normalizedPath = devicePath.replace(/^vol0:(?!\/)/i, 'vol0:/').toLowerCase();
51087
+ return normalizedPath === PROTOCOL_V2_BOOT_RESOURCE_PACKAGE_PATH
51088
+ ? PROTOCOL_V2_BOOT_RESOURCE_PACKAGE_STAGING_PATH
51089
+ : devicePath;
51090
+ };
51038
51091
  const PROTOCOL_V2_UPDATE_TARGET_BY_TARGET_ID = new Map([
51039
51092
  [ProtocolV2FirmwareTargetType.FW_MGMT_TARGET_BOOTLOADER, 'boot'],
51040
51093
  [ProtocolV2FirmwareTargetType.FW_MGMT_TARGET_APPLICATION_P1, 'app_v1'],
@@ -51338,7 +51391,7 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
51338
51391
  });
51339
51392
  }
51340
51393
  runProtocolV2() {
51341
- var _a, _b, _c, _d, _e;
51394
+ var _a, _b, _c, _d, _e, _f;
51342
51395
  return __awaiter(this, void 0, void 0, function* () {
51343
51396
  yield this.captureProtocolV2PhysicalIdentity();
51344
51397
  const deviceFeatures = yield this.getProtocolV2DeviceFeatures();
@@ -51357,8 +51410,7 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
51357
51410
  const hasExplicitResourceFiles = !!((_c = this.params.resourceFiles) === null || _c === void 0 ? void 0 : _c.length);
51358
51411
  const wantsStableResources = !!((_d = this.params.targetsToUpdate) === null || _d === void 0 ? void 0 : _d.includes('resource'));
51359
51412
  const wantsBootResources = !!((_e = this.params.targetsToUpdate) === null || _e === void 0 ? void 0 : _e.includes('boot_resources'));
51360
- const needsRemoteResources = !hasExplicitResourceFiles && wantsStableResources;
51361
- const needsRemoteBootResources = !hasExplicitResourceFiles && (wantsBootResources || wantsStableResources);
51413
+ const needsPreparedResources = !hasExplicitResourceFiles && (wantsStableResources || wantsBootResources);
51362
51414
  let fwBinaryMap = [];
51363
51415
  let bootloaderBinary = null;
51364
51416
  let installItems;
@@ -51369,17 +51421,20 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
51369
51421
  fwBinaryMap = this.collectExplicitTargetBinaries();
51370
51422
  bootloaderBinary = this.prepareBootloaderBinary();
51371
51423
  const needsRemoteFirmware = !this.hasExplicitProtocolV2Payload(fwBinaryMap);
51372
- if ((needsRemoteFirmware || needsRemoteResources || needsRemoteBootResources) &&
51424
+ if (needsPreparedResources) {
51425
+ throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, 'Protocol V2 resource manifest must be prepared by the external firmware host', {
51426
+ firmwareUpdateCode: 'FirmwareArtifactsNotPrepared',
51427
+ });
51428
+ }
51429
+ if (needsRemoteFirmware &&
51373
51430
  (this.params.artifactReader ||
51374
51431
  DataManager.getSettings('firmwareManifestMode') === 'external-only')) {
51375
51432
  throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, 'Protocol V2 firmware artifacts must be prepared by the external firmware host', {
51376
51433
  firmwareUpdateCode: 'FirmwareArtifactsNotPrepared',
51377
51434
  });
51378
51435
  }
51379
- if (needsRemoteFirmware || needsRemoteResources || needsRemoteBootResources) {
51380
- yield DataManager.forceReloadData({
51381
- requireResources: needsRemoteResources || needsRemoteBootResources,
51382
- });
51436
+ if (needsRemoteFirmware) {
51437
+ yield DataManager.forceReloadData();
51383
51438
  }
51384
51439
  if (needsRemoteFirmware) {
51385
51440
  const remoteBinaries = yield this.prepareRemoteProtocolV2Binaries(firmwareType, deviceFeatures);
@@ -51387,15 +51442,15 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
51387
51442
  fwBinaryMap = remoteBinaries.fwBinaryMap;
51388
51443
  installItems = remoteBinaries.installItems;
51389
51444
  }
51390
- const bootResourceFiles = yield this.prepareProtocolV2BootResources();
51391
- if (bootResourceFiles === null || bootResourceFiles === void 0 ? void 0 : bootResourceFiles.length) {
51392
- resourceBundles = this.mergeProtocolV2ResourceBundles(resourceBundles, bootResourceFiles);
51393
- }
51394
- if (!needsRemoteResources) {
51395
- this.postTipMessage(exports.FirmwareUpdateTipMessage.FinishDownloadFirmware);
51396
- }
51445
+ this.postTipMessage(exports.FirmwareUpdateTipMessage.FinishDownloadFirmware);
51397
51446
  }
51398
51447
  catch (err) {
51448
+ if (typeof err === 'object' &&
51449
+ err !== null &&
51450
+ 'params' in err &&
51451
+ ((_f = err.params) === null || _f === void 0 ? void 0 : _f.firmwareUpdateCode) === 'FirmwareArtifactsNotPrepared') {
51452
+ throw err;
51453
+ }
51399
51454
  if (err instanceof hdShared.HardwareError && err.errorCode === hdShared.HardwareErrorCode.NetworkError) {
51400
51455
  throw err;
51401
51456
  }
@@ -51404,29 +51459,9 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
51404
51459
  if (!bootloaderBinary &&
51405
51460
  fwBinaryMap.length === 0 &&
51406
51461
  !(installItems === null || installItems === void 0 ? void 0 : installItems.length) &&
51407
- !(resourceBundles === null || resourceBundles === void 0 ? void 0 : resourceBundles.length) &&
51408
- !needsRemoteResources) {
51462
+ !(resourceBundles === null || resourceBundles === void 0 ? void 0 : resourceBundles.length)) {
51409
51463
  throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.FirmwareUpdateDownloadFailed, 'No firmware to update');
51410
51464
  }
51411
- if (needsRemoteResources) {
51412
- const enteredBootloader = yield this.enterProtocolV2BootloaderMode();
51413
- try {
51414
- const stableResources = yield this.prepareProtocolV2ResourceBundles();
51415
- resourceBundles = this.mergeProtocolV2ResourceBundles(resourceBundles, stableResources);
51416
- this.postTipMessage(exports.FirmwareUpdateTipMessage.FinishDownloadFirmware);
51417
- }
51418
- catch (err) {
51419
- if (enteredBootloader) {
51420
- try {
51421
- yield this.exitProtocolV2BootloaderToNormal();
51422
- }
51423
- catch (restoreError) {
51424
- Log$6.warn('[FirmwareUpdateV4] failed to restore App mode after resource preparation error:', restoreError);
51425
- }
51426
- }
51427
- throw normalizeFirmwarePreparationError(err);
51428
- }
51429
- }
51430
51465
  return this.executeProtocolV2Update(Object.assign(Object.assign({ fwBinaryMap,
51431
51466
  bootloaderBinary }, (installItems ? { installItems } : undefined)), ((resourceBundles === null || resourceBundles === void 0 ? void 0 : resourceBundles.length) ? { resourceBundles } : undefined)));
51432
51467
  });
@@ -51834,102 +51869,6 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
51834
51869
  };
51835
51870
  });
51836
51871
  }
51837
- getProtocolV2DeviceType() {
51838
- const deviceType = this.device.getCurrentDeviceType();
51839
- if (deviceType === hdShared.EDeviceType.Pro2 || deviceType === hdShared.EDeviceType.Neo)
51840
- return deviceType;
51841
- throw new Error(`Unsupported Protocol V2 device type: ${deviceType}`);
51842
- }
51843
- prepareProtocolV2BootResources() {
51844
- var _a, _b, _c, _d, _e;
51845
- return __awaiter(this, void 0, void 0, function* () {
51846
- const wantsStableResources = !!((_a = this.params.targetsToUpdate) === null || _a === void 0 ? void 0 : _a.includes('resource'));
51847
- const wantsBootResources = !!((_b = this.params.targetsToUpdate) === null || _b === void 0 ? void 0 : _b.includes('boot_resources'));
51848
- if (!wantsStableResources && !wantsBootResources) {
51849
- return undefined;
51850
- }
51851
- if ((_c = this.params.resourceFiles) === null || _c === void 0 ? void 0 : _c.length) {
51852
- return undefined;
51853
- }
51854
- const resource = DataManager.getProtocolV2BootResources(this.getProtocolV2DeviceType());
51855
- if (!resource) {
51856
- if (wantsBootResources) {
51857
- throw new Error('Missing Protocol V2 boot resources configuration');
51858
- }
51859
- Log$6.debug('[FirmwareUpdateV4] no boot resources configured; continue with stable resources');
51860
- return undefined;
51861
- }
51862
- const files = [];
51863
- for (const file of resource.files) {
51864
- const isCurrent = !this.params.forcedUpdateRes && (yield this.isProtocolV2BootResourceCurrent(file));
51865
- if (isCurrent) {
51866
- Log$6.log(`[FirmwareUpdateV4] boot resource unchanged, skipping ${file.devicePath}`);
51867
- }
51868
- else {
51869
- Log$6.log(`[FirmwareUpdateV4] downloading boot resource ${file.devicePath}`);
51870
- const { binary } = yield getSysResourceBinary(file.url);
51871
- if (!isProtocolV2ResourceFileValid(binary, file)) {
51872
- throw new Error(`Boot resource file verification failed: ${file.devicePath}`);
51873
- }
51874
- files.push({
51875
- name: (_e = (_d = file.name) !== null && _d !== void 0 ? _d : file.devicePath.split('/').pop()) !== null && _e !== void 0 ? _e : file.devicePath,
51876
- binary,
51877
- devicePath: file.devicePath,
51878
- });
51879
- }
51880
- }
51881
- return files;
51882
- });
51883
- }
51884
- isProtocolV2BootResourceCurrent(file) {
51885
- var _a, _b, _c, _d;
51886
- return __awaiter(this, void 0, void 0, function* () {
51887
- try {
51888
- const commands = this.device.getCommands();
51889
- const pathInfo = yield commands.typedCall('FilesystemPathInfoQuery', 'FilesystemPathInfo', { path: file.devicePath }, { timeoutMs: PROTOCOL_V2_SHORT_RESPONSE_TIMEOUT });
51890
- const size = toProtocolV2FiniteNumber((_a = pathInfo.message) === null || _a === void 0 ? void 0 : _a.size);
51891
- if (!((_b = pathInfo.message) === null || _b === void 0 ? void 0 : _b.exist) ||
51892
- ((_c = pathInfo.message) === null || _c === void 0 ? void 0 : _c.directory) ||
51893
- !Number.isSafeInteger(size) ||
51894
- size !== file.size) {
51895
- return false;
51896
- }
51897
- const digest = sha256.sha256.create();
51898
- const chunkSize = this.getProtocolV2FirmwareChunkSize('write');
51899
- let offset = 0;
51900
- while (offset < file.size) {
51901
- const response = yield commands.typedCall('FilesystemFileRead', 'FilesystemFile', {
51902
- file: { path: file.devicePath, offset, total_size: 0 },
51903
- chunk_len: Math.min(chunkSize, file.size - offset),
51904
- }, { timeoutMs: PROTOCOL_V2_SHORT_RESPONSE_TIMEOUT });
51905
- const data = toProtocolV2Bytes((_d = response.message) === null || _d === void 0 ? void 0 : _d.data);
51906
- if (data.byteLength === 0)
51907
- return false;
51908
- const consumed = data.subarray(0, Math.min(data.byteLength, file.size - offset));
51909
- digest.update(consumed);
51910
- offset += consumed.byteLength;
51911
- }
51912
- return bytesToHex(digest.digest()) === normalizeProtocolV2Hex(file.fileHash);
51913
- }
51914
- catch (error) {
51915
- Log$6.debug(`[FirmwareUpdateV4] unable to compare boot resource ${file.devicePath}; scheduling rewrite`, error);
51916
- return false;
51917
- }
51918
- });
51919
- }
51920
- mergeProtocolV2ResourceBundles(...groups) {
51921
- const merged = groups.flatMap(group => group !== null && group !== void 0 ? group : []);
51922
- if (!merged.length)
51923
- return undefined;
51924
- const seenPaths = new Set();
51925
- for (const bundle of merged) {
51926
- if (seenPaths.has(bundle.devicePath)) {
51927
- throw new Error(`Duplicate Protocol V2 resource devicePath: ${bundle.devicePath}`);
51928
- }
51929
- seenPaths.add(bundle.devicePath);
51930
- }
51931
- return merged;
51932
- }
51933
51872
  prepareExplicitProtocolV2ResourceFiles() {
51934
51873
  var _a;
51935
51874
  const files = (_a = this.params.resourceFiles) !== null && _a !== void 0 ? _a : [];
@@ -51960,52 +51899,6 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
51960
51899
  }
51961
51900
  return prepared;
51962
51901
  }
51963
- prepareProtocolV2ResourceBundles() {
51964
- var _a;
51965
- return __awaiter(this, void 0, void 0, function* () {
51966
- if (!((_a = this.params.targetsToUpdate) === null || _a === void 0 ? void 0 : _a.includes('resource'))) {
51967
- return undefined;
51968
- }
51969
- const resources = DataManager.getProtocolV2Resources(this.getProtocolV2DeviceType());
51970
- if (!(resources === null || resources === void 0 ? void 0 : resources.length)) {
51971
- throw new Error('Missing Pro2 stable resource configuration');
51972
- }
51973
- const inventory = this.params.forcedUpdateRes
51974
- ? undefined
51975
- : yield readProtocolV2ResourceInventory({
51976
- commands: this.device.getCommands(),
51977
- resources,
51978
- chunkSize: this.getProtocolV2FirmwareChunkSize('write'),
51979
- timeoutMs: PROTOCOL_V2_SHORT_RESPONSE_TIMEOUT,
51980
- });
51981
- const plan = buildProtocolV2ResourceUpdatePlan({
51982
- resources,
51983
- inventory,
51984
- mode: 'bootloader-recovery',
51985
- forced: this.params.forcedUpdateRes,
51986
- });
51987
- Log$6.log(`[FirmwareUpdateV4] Protocol V2 resource plan mode=bootloader-recovery status=${plan.status} count=${plan.resources.length}`);
51988
- const bundles = [];
51989
- for (const resource of plan.resources) {
51990
- bundles.push(yield this.downloadProtocolV2Resource(resource));
51991
- }
51992
- return bundles;
51993
- });
51994
- }
51995
- downloadProtocolV2Resource(resource) {
51996
- return __awaiter(this, void 0, void 0, function* () {
51997
- Log$6.log(`[FirmwareUpdateV4] downloading Pro2 resource ${resource.type}`);
51998
- const { binary } = yield getSysResourceBinary(resource.url);
51999
- if (!isProtocolV2ResourceFileValid(binary, resource)) {
52000
- throw new Error(`Pro2 resource file verification failed: ${resource.type}`);
52001
- }
52002
- return {
52003
- name: `${resource.type}.okpkg`,
52004
- binary,
52005
- devicePath: PROTOCOL_V2_RESOURCE_DEVICE_PATHS[resource.type],
52006
- };
52007
- });
52008
- }
52009
51902
  getProtocolV2ResourceFilePath(path) {
52010
51903
  if (path.startsWith('vol'))
52011
51904
  return path;
@@ -52197,13 +52090,6 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
52197
52090
  }
52198
52091
  buildProtocolV2ExecutionPhases({ installSources, resourceSources, }) {
52199
52092
  const phases = [];
52200
- if (resourceSources.length > 0) {
52201
- phases.push({
52202
- kind: 'resource-sync',
52203
- installSources: [],
52204
- resourceSources,
52205
- });
52206
- }
52207
52093
  const bootloaderSources = installSources.filter(source => source.kind === 'bootloader');
52208
52094
  if (bootloaderSources.length > 0) {
52209
52095
  phases.push({
@@ -52216,6 +52102,13 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
52216
52102
  resourceSources: [],
52217
52103
  });
52218
52104
  }
52105
+ if (resourceSources.length > 0) {
52106
+ phases.push({
52107
+ kind: 'resource-sync',
52108
+ installSources: [],
52109
+ resourceSources,
52110
+ });
52111
+ }
52219
52112
  const componentSources = installSources.filter(source => source.kind !== 'bootloader');
52220
52113
  if (componentSources.length > 0) {
52221
52114
  phases.push({
@@ -52314,13 +52207,14 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
52314
52207
  this.postTipMessage(exports.FirmwareUpdateTipMessage.StartTransferData);
52315
52208
  let processedSize = 0;
52316
52209
  for (const resource of resourcesToSync) {
52210
+ const writePath = resolveProtocolV2ResourceWritePath(resource.devicePath);
52317
52211
  processedSize = yield this.protocolV2SourceUpdateProcess({
52318
52212
  source: resource.source,
52319
- filePath: resource.devicePath,
52213
+ filePath: writePath,
52320
52214
  processedSize,
52321
52215
  totalSize,
52322
52216
  });
52323
- yield this.verifyProtocolV2StagedFile(resource.devicePath, resource.source.size);
52217
+ yield this.verifyProtocolV2StagedFile(writePath, resource.source.size);
52324
52218
  }
52325
52219
  const stagedInstallTargets = [];
52326
52220
  for (const item of installSources) {
@@ -53310,7 +53204,7 @@ class DeviceUploadWallpaper extends BaseMethod {
53310
53204
  }
53311
53205
 
53312
53206
  const FILESYSTEM_PATH_INFO_QUERY_MESSAGE_TYPE = 60802;
53313
- const FILESYSTEM_FILE_WRITE_MESSAGE_TYPE = 60805;
53207
+ const FILESYSTEM_FILE_WRITE_MESSAGE_TYPE$1 = 60805;
53314
53208
  const FILESYSTEM_DIR_LIST_MESSAGE_TYPE = 60808;
53315
53209
  const NFT_UPDATE_MESSAGE_TYPE = 61500;
53316
53210
  class DeviceUploadNft extends BaseMethod {
@@ -53339,7 +53233,7 @@ class DeviceUploadNft extends BaseMethod {
53339
53233
  assertCapabilities() {
53340
53234
  return __awaiter(this, void 0, void 0, function* () {
53341
53235
  const protocolInfo = yield this.device.ensureProtocolV2RuntimeContext();
53342
- const hasFileWrite = supportsProtocolV2Message(protocolInfo, FILESYSTEM_FILE_WRITE_MESSAGE_TYPE);
53236
+ const hasFileWrite = supportsProtocolV2Message(protocolInfo, FILESYSTEM_FILE_WRITE_MESSAGE_TYPE$1);
53343
53237
  const hasPathInfo = supportsProtocolV2Message(protocolInfo, FILESYSTEM_PATH_INFO_QUERY_MESSAGE_TYPE);
53344
53238
  const hasDirList = supportsProtocolV2Message(protocolInfo, FILESYSTEM_DIR_LIST_MESSAGE_TYPE);
53345
53239
  const hasNftUpdate = supportsProtocolV2Message(protocolInfo, NFT_UPDATE_MESSAGE_TYPE);
@@ -53474,6 +53368,8 @@ class FileWrite extends BaseMethod {
53474
53368
 
53475
53369
  const PORTFOLIO_PENDING_PATH = 'vol1:/portfolio/portfolio.okpkg.pending';
53476
53370
  const PORTFOLIO_CHUNK_SIZE = 2048;
53371
+ const FILESYSTEM_FILE_WRITE_MESSAGE_TYPE = 60805;
53372
+ const PORTFOLIO_UPDATE_MESSAGE_TYPE = 61400;
53477
53373
  class UploadPortfolio extends FileWrite {
53478
53374
  init() {
53479
53375
  const { packageBytes, timeoutMs } = this.payload;
@@ -53487,6 +53383,12 @@ class UploadPortfolio extends FileWrite {
53487
53383
  run: { get: () => super.run }
53488
53384
  });
53489
53385
  return __awaiter(this, void 0, void 0, function* () {
53386
+ const protocolInfo = yield this.device.ensureProtocolV2RuntimeContext();
53387
+ const hasFileWrite = supportsProtocolV2Message(protocolInfo, FILESYSTEM_FILE_WRITE_MESSAGE_TYPE);
53388
+ const hasPortfolioUpdate = supportsProtocolV2Message(protocolInfo, PORTFOLIO_UPDATE_MESSAGE_TYPE);
53389
+ if (!hasFileWrite || !hasPortfolioUpdate) {
53390
+ throw hdShared.createDeviceNotSupportMethodError(this.name, this.device.getCurrentFirmwareType());
53391
+ }
53490
53392
  const stagedFile = yield _super.run.call(this);
53491
53393
  this.throwIfAborted();
53492
53394
  yield this.device.commands.typedCall('PortfolioUpdate', 'Success', {});
@@ -63378,6 +63280,16 @@ function findMethod(message) {
63378
63280
  }
63379
63281
  throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.CallMethodInvalidParameter, `Method ${method} is not set`);
63380
63282
  }
63283
+ function getMethodSupportedProtocols(method, payload) {
63284
+ const instance = findMethod({
63285
+ id: 0,
63286
+ payload: Object.assign(Object.assign({}, payload), { method }),
63287
+ });
63288
+ if (payload !== undefined) {
63289
+ instance.init();
63290
+ }
63291
+ return instance.getSupportedProtocols();
63292
+ }
63381
63293
 
63382
63294
  const resolveAfter = (msec, value) => new Promise(resolve => {
63383
63295
  setTimeout(resolve, msec, value);
@@ -65001,6 +64913,7 @@ exports.getLanguageConfig = getLanguageConfig;
65001
64913
  exports.getLog = getLog;
65002
64914
  exports.getLogBlockLabel = getLogBlockLabel;
65003
64915
  exports.getLogger = getLogger;
64916
+ exports.getMethodSupportedProtocols = getMethodSupportedProtocols;
65004
64917
  exports.getMethodVersionRange = getMethodVersionRange;
65005
64918
  exports.getNftSize = getNftSize;
65006
64919
  exports.getOutputScriptType = getOutputScriptType;
@@ -65017,10 +64930,15 @@ exports.normalizeSafetyCheckLevel = normalizeSafetyCheckLevel;
65017
64930
  exports.normalizeVersionArray = normalizeVersionArray;
65018
64931
  exports.parseConnectSettings = parseConnectSettings;
65019
64932
  exports.parseMessage = parseMessage;
64933
+ exports.parseProtocolV2ResourceManifest = parseProtocolV2ResourceManifest;
65020
64934
  exports.patchFeatures = patchFeatures;
65021
64935
  exports.preloadSessionCache = preloadSessionCache;
64936
+ exports.prepareProtocolV2ResourceFiles = prepareProtocolV2ResourceFiles;
64937
+ exports.projectDeviceStateFeatures = projectFeatures;
65022
64938
  exports.registerFirmwareUpdateHostBinding = registerFirmwareUpdateHostBinding;
64939
+ exports.resolveProtocolV2ResourceManifestFileUrl = resolveProtocolV2ResourceManifestFileUrl;
65023
64940
  exports.safeThrowError = safeThrowError;
64941
+ exports.selectProtocolV2ResourceManifestFiles = selectProtocolV2ResourceManifestFiles;
65024
64942
  exports.setLoggerPostMessage = setLoggerPostMessage;
65025
64943
  exports.supportInputPinOnSoftware = supportInputPinOnSoftware;
65026
64944
  exports.switchTransport = switchTransport;