@onekeyfe/hd-core 1.2.0-alpha.108 → 1.2.0-alpha.109

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 (31) hide show
  1. package/__tests__/DeviceCommands.test.ts +2 -2
  2. package/__tests__/device-lifecycle-events.test.ts +1 -1
  3. package/__tests__/device-state-mapper.test.ts +4 -4
  4. package/__tests__/device-utils.test.ts +1 -1
  5. package/__tests__/firmware-update/firmware-update-v4-install-poll.test.ts +36 -89
  6. package/__tests__/get-device-state.test.ts +8 -8
  7. package/__tests__/protocol-v2-resources.test.ts +8 -0
  8. package/__tests__/protocol-v2.test.ts +192 -236
  9. package/dist/api/FirmwareUpdateV4.d.ts +0 -3
  10. package/dist/api/FirmwareUpdateV4.d.ts.map +1 -1
  11. package/dist/api/protocol-v2/DeviceInfoGet.d.ts +1 -1
  12. package/dist/api/protocol-v2/DeviceInfoGet.d.ts.map +1 -1
  13. package/dist/index.d.ts +5 -20
  14. package/dist/index.js +128 -206
  15. package/dist/protocols/protocol-v2/features.d.ts +4 -4
  16. package/dist/protocols/protocol-v2/resources.d.ts.map +1 -1
  17. package/dist/types/settings.d.ts +4 -19
  18. package/dist/types/settings.d.ts.map +1 -1
  19. package/dist/utils/patch.d.ts +1 -1
  20. package/dist/utils/patch.d.ts.map +1 -1
  21. package/package.json +4 -4
  22. package/src/api/FirmwareUpdateV4.ts +84 -174
  23. package/src/api/protocol-v2/DeviceFactoryInfoSet.ts +1 -1
  24. package/src/api/protocol-v2/DeviceInfoGet.ts +3 -3
  25. package/src/api/ton/TonSignMessage.ts +1 -1
  26. package/src/data/messages/messages-protocol-v2.json +31 -14
  27. package/src/device/DeviceStateMapper.ts +15 -15
  28. package/src/deviceProfile/buildDeviceFeatures.ts +3 -3
  29. package/src/protocols/protocol-v2/features.ts +6 -6
  30. package/src/protocols/protocol-v2/resources.ts +9 -46
  31. package/src/types/settings.ts +4 -19
@@ -28,7 +28,6 @@ import { DevicePool } from '../device/DevicePool';
28
28
  import {
29
29
  PROTOCOL_V2_VERSIONS_DEVICE_INFO_REQUEST,
30
30
  ProtocolV2FirmwareTargetType,
31
- isLegacyProtocolV2ProtocolInfo,
32
31
  } from '../protocols/protocol-v2';
33
32
  import { requestProtocolV2DeviceInfo } from '../protocols/protocol-v2/features';
34
33
  import {
@@ -70,6 +69,7 @@ import type {
70
69
  Features,
71
70
  IFirmwareReleaseInfo,
72
71
  IProtocolV2FirmwareComponent,
72
+ IProtocolV2ResourceManifestFile,
73
73
  IVersionArray,
74
74
  } from '../types';
75
75
  import type { FirmwareByteSource } from './firmware/FirmwareArtifactSource';
@@ -89,7 +89,6 @@ const PROTOCOL_V2_BOOTLOADER_RECONNECT_TIMEOUT = 90 * 1000;
89
89
  const PROTOCOL_V2_FINAL_RECONNECT_TIMEOUT = 3 * 60 * 1000;
90
90
  const PROTOCOL_V2_SHORT_RESPONSE_TIMEOUT = 5 * 1000;
91
91
  const PROTOCOL_V2_FIRMWARE_STATUS_RESPONSE_TIMEOUT = 15 * 1000;
92
- const PROTOCOL_V2_START_UPDATE_TIMEOUT = 3 * 60 * 1000;
93
92
  const PROTOCOL_V2_INSTALL_TIMEOUT = 8 * 60 * 1000;
94
93
  const PROTOCOL_V2_MISSING_TARGET_STATUS_GRACE_TIMEOUT = 30 * 1000;
95
94
  const PROTOCOL_V2_TARGET_STATUS_PENDING = 0;
@@ -113,6 +112,13 @@ const PROTOCOL_V2_RESOURCE_MANIFEST_MAX_BYTES = 1024 * 1024;
113
112
  const PROTOCOL_V2_RESOURCE_FILE_MAX_COUNT = 512;
114
113
  const PROTOCOL_V2_RESOURCE_TOTAL_MAX_BYTES = 256 * 1024 * 1024;
115
114
 
115
+ const getProtocolV2LocalResourceArchivePath = (entryName: string) => {
116
+ const match = entryName.match(
117
+ /(?:^|\/)((?:bundles\/|loaders\/(?:bootloader|rom)\/).+\.okpkg)$/iu
118
+ );
119
+ return match?.[1];
120
+ };
121
+
116
122
  const PROTOCOL_V2_NEO_UNSUPPORTED_TARGETS = new Set<FirmwareUpdateV4Target>(['se03', 'se04']);
117
123
 
118
124
  const getProtocolV2ZipEntrySizes = (entry: JSZip.JSZipObject) => {
@@ -199,8 +205,6 @@ type ProtocolV2FirmwareUpdateStatusTarget = {
199
205
  path?: string;
200
206
  };
201
207
 
202
- type ProtocolV2FirmwareUpdateStartResponse = TypedResponseMessage<'Success'>;
203
-
204
208
  type ProtocolV2TargetBinary = { fileName: string; binary: ArrayBuffer; targetId: number };
205
209
  type ProtocolV2InstallItem = ProtocolV2TargetBinary & {
206
210
  kind: ProtocolV2RemoteComponentTarget['kind'];
@@ -377,31 +381,6 @@ const isProtocolV2ReconnectProbeError = (error: unknown) => {
377
381
  );
378
382
  };
379
383
 
380
- const PROTOCOL_V2_BLE_INSTALL_INTERRUPTION_ERROR_CODES = new Set<number>([
381
- HardwareErrorCode.BleConnectedError,
382
- HardwareErrorCode.BleCharacteristicNotifyError,
383
- HardwareErrorCode.BleForceCleanRunPromise,
384
- HardwareErrorCode.BleDeviceDisconnected,
385
- ]);
386
-
387
- const isProtocolV2BleInstallInterruptionError = (error: unknown) => {
388
- if (
389
- error instanceof HardwareError &&
390
- PROTOCOL_V2_BLE_INSTALL_INTERRUPTION_ERROR_CODES.has(error.errorCode)
391
- ) {
392
- return true;
393
- }
394
-
395
- const message = getProtocolV2UnknownErrorText(error).toLowerCase();
396
- const compactMessage = message.replace(/\s+/gu, '');
397
- return (
398
- /react native ble transport (?:released|disconnected)/u.test(message) ||
399
- (compactMessage.includes('rxerrorerror6') &&
400
- (compactMessage.includes('multiplatformbleadapter') ||
401
- compactMessage.includes('multipalformebleadapter')))
402
- );
403
- };
404
-
405
384
  const isProtocolV2FirmwareStatusEndpointUnavailable = (error: unknown) => {
406
385
  const message = getProtocolV2UnknownErrorText(error).toLowerCase();
407
386
  return (
@@ -411,15 +390,6 @@ const isProtocolV2FirmwareStatusEndpointUnavailable = (error: unknown) => {
411
390
  );
412
391
  };
413
392
 
414
- const isProtocolV2FirmwareUpdateEndpointUnavailable = (error: unknown) => {
415
- const message = getProtocolV2UnknownErrorText(error).toLowerCase();
416
- return (
417
- message.includes('handler not registered') ||
418
- message.includes('message handler not found') ||
419
- message.includes('unsupported message')
420
- );
421
- };
422
-
423
393
  const isProtocolV2TerminalInstallStatusError = (error: unknown) =>
424
394
  error instanceof HardwareError &&
425
395
  (error.errorCode === HardwareErrorCode.FirmwareError ||
@@ -596,7 +566,7 @@ export const assertProtocolV2ReconnectIdentity = (
596
566
  *
597
567
  * It intentionally does not fall back to FirmwareUpdateV3/V1 behavior:
598
568
  * - upload uses FilesystemFileWrite
599
- * - install uses DeviceFirmwareUpdateRequest
569
+ * - install uses DeviceFirmwareUpdateStage followed by an empty DeviceFirmwareUpdateRequest
600
570
  * - completion waits for target status to finish, reboots to normal, then polls DeviceInfo
601
571
  */
602
572
  export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareUpdateV4Params> {
@@ -614,8 +584,6 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
614
584
 
615
585
  private protocolV2ExecutionInLoader = false;
616
586
 
617
- private protocolV2LegacyDirectUpdate = false;
618
-
619
587
  private protocolV2BootResourceStagingSafe = false;
620
588
 
621
589
  private protocolV2CompletedTargetVersions = new Map<number, number>();
@@ -624,8 +592,6 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
624
592
 
625
593
  private protocolV2FinalStatusVerified = false;
626
594
 
627
- private protocolV2InstallAckReceived = false;
628
-
629
595
  private protocolV2InstallBaselineVersions = new Map<number, string>();
630
596
 
631
597
  private protocolV2LastRuntimeProbeFeatures?: Features;
@@ -1293,92 +1259,86 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
1293
1259
  );
1294
1260
  }
1295
1261
  const entries = zipEntries.filter(entry => !entry.dir);
1296
- if (entries.length === 0 || entries.length > PROTOCOL_V2_RESOURCE_FILE_MAX_COUNT + 1) {
1262
+ if (entries.length === 0) {
1297
1263
  throw ERRORS.TypedError(
1298
1264
  HardwareErrorCode.RuntimeError,
1299
1265
  'Protocol V2 local resource ZIP entry set is invalid',
1300
1266
  { firmwareUpdateCode: 'FirmwareArtifactsNotPrepared' }
1301
1267
  );
1302
1268
  }
1303
- let declaredUncompressedSize = 0;
1304
- let declaredCompressedSize = 0;
1305
- for (const entry of entries) {
1306
- const sizes = getProtocolV2ZipEntrySizes(entry);
1307
- declaredCompressedSize += sizes.compressedSize;
1308
- declaredUncompressedSize += sizes.uncompressedSize;
1309
- const entryLimit =
1310
- entry.name === 'manifest.json'
1311
- ? PROTOCOL_V2_RESOURCE_MANIFEST_MAX_BYTES
1312
- : PROTOCOL_V2_RESOURCE_TOTAL_MAX_BYTES;
1269
+ const manifestEntry = entries.find(entry => entry.name.split('/').pop() === 'manifest.json');
1270
+ let manifestBinary: ArrayBuffer | undefined;
1271
+ let manifestDirectory = '';
1272
+ let selectedFiles: IProtocolV2ResourceManifestFile[];
1273
+ if (manifestEntry) {
1313
1274
  if (
1314
- sizes.uncompressedSize > entryLimit ||
1315
- declaredCompressedSize > binary.byteLength ||
1316
- declaredUncompressedSize >
1317
- PROTOCOL_V2_RESOURCE_TOTAL_MAX_BYTES + PROTOCOL_V2_RESOURCE_MANIFEST_MAX_BYTES
1275
+ getProtocolV2ZipEntrySizes(manifestEntry).uncompressedSize >
1276
+ PROTOCOL_V2_RESOURCE_MANIFEST_MAX_BYTES
1318
1277
  ) {
1319
1278
  throw ERRORS.TypedError(
1320
1279
  HardwareErrorCode.RuntimeError,
1321
- 'Protocol V2 local resource ZIP declared size exceeds the allowed limit',
1280
+ 'Protocol V2 local resource manifest size is invalid',
1322
1281
  { firmwareUpdateCode: 'FirmwareArtifactsNotPrepared' }
1323
1282
  );
1324
1283
  }
1284
+ manifestBinary = await manifestEntry.async('arraybuffer');
1285
+ if (
1286
+ manifestBinary.byteLength <= 0 ||
1287
+ manifestBinary.byteLength > PROTOCOL_V2_RESOURCE_MANIFEST_MAX_BYTES
1288
+ ) {
1289
+ throw ERRORS.TypedError(
1290
+ HardwareErrorCode.RuntimeError,
1291
+ 'Protocol V2 local resource manifest size is invalid',
1292
+ { firmwareUpdateCode: 'FirmwareArtifactsNotPrepared' }
1293
+ );
1294
+ }
1295
+ let manifestValue: unknown;
1296
+ try {
1297
+ manifestValue = JSON.parse(new TextDecoder().decode(manifestBinary));
1298
+ } catch (error) {
1299
+ throw ERRORS.TypedError(
1300
+ HardwareErrorCode.RuntimeError,
1301
+ `Protocol V2 local resource manifest is invalid: ${String(error)}`,
1302
+ { firmwareUpdateCode: 'FirmwareArtifactsNotPrepared' }
1303
+ );
1304
+ }
1305
+ selectedFiles = selectProtocolV2ResourceManifestFiles({
1306
+ manifest: parseProtocolV2ResourceManifest(manifestValue),
1307
+ targetsToUpdate: this.params.targetsToUpdate ?? [],
1308
+ });
1309
+ manifestDirectory = manifestEntry.name.slice(0, -'manifest.json'.length);
1310
+ } else {
1311
+ selectedFiles = entries.flatMap(entry => {
1312
+ const archivePath = getProtocolV2LocalResourceArchivePath(entry.name);
1313
+ if (!archivePath) return [];
1314
+ return [
1315
+ {
1316
+ archive_path: archivePath,
1317
+ original_name: archivePath.split('/').pop() ?? archivePath,
1318
+ device_path: `vol0:/${archivePath}`,
1319
+ size: getProtocolV2ZipEntrySizes(entry).uncompressedSize,
1320
+ sha256: '',
1321
+ },
1322
+ ];
1323
+ });
1325
1324
  }
1326
- const manifestEntry = zip.file('manifest.json');
1327
- if (!manifestEntry) {
1328
- throw ERRORS.TypedError(
1329
- HardwareErrorCode.RuntimeError,
1330
- 'Protocol V2 local resource ZIP has no manifest.json',
1331
- { firmwareUpdateCode: 'FirmwareArtifactsNotPrepared' }
1332
- );
1333
- }
1334
- const manifestBinary = await manifestEntry.async('arraybuffer');
1335
- if (
1336
- manifestBinary.byteLength <= 0 ||
1337
- manifestBinary.byteLength > PROTOCOL_V2_RESOURCE_MANIFEST_MAX_BYTES
1338
- ) {
1339
- throw ERRORS.TypedError(
1340
- HardwareErrorCode.RuntimeError,
1341
- 'Protocol V2 local resource manifest size is invalid',
1342
- { firmwareUpdateCode: 'FirmwareArtifactsNotPrepared' }
1343
- );
1344
- }
1345
-
1346
- let manifestValue: unknown;
1347
- try {
1348
- manifestValue = JSON.parse(new TextDecoder().decode(manifestBinary));
1349
- } catch (error) {
1350
- throw ERRORS.TypedError(
1351
- HardwareErrorCode.RuntimeError,
1352
- `Protocol V2 local resource manifest is invalid: ${String(error)}`,
1353
- { firmwareUpdateCode: 'FirmwareArtifactsNotPrepared' }
1354
- );
1355
- }
1356
- const manifest = parseProtocolV2ResourceManifest(manifestValue);
1357
- const selectedFiles = selectProtocolV2ResourceManifestFiles({
1358
- manifest,
1359
- targetsToUpdate: this.params.targetsToUpdate ?? [],
1360
- });
1361
- const expectedEntryNames = new Set([
1362
- 'manifest.json',
1363
- ...selectedFiles.map(file => file.archive_path),
1364
- ]);
1365
- if (
1366
- entries.length !== expectedEntryNames.size ||
1367
- entries.some(entry => !expectedEntryNames.has(entry.name))
1368
- ) {
1325
+ if (selectedFiles.length === 0 || selectedFiles.length > PROTOCOL_V2_RESOURCE_FILE_MAX_COUNT) {
1369
1326
  throw ERRORS.TypedError(
1370
1327
  HardwareErrorCode.RuntimeError,
1371
- 'Protocol V2 local resource ZIP contains an unexpected entry',
1328
+ 'Protocol V2 local resource ZIP has no resource packages',
1372
1329
  { firmwareUpdateCode: 'FirmwareArtifactsNotPrepared' }
1373
1330
  );
1374
1331
  }
1375
1332
 
1376
1333
  let totalSize = 0;
1377
- const materializedEntries: FirmwareMemoryArtifactEntry[] = [
1378
- { entryName: 'manifest.json', binary: manifestBinary },
1379
- ];
1334
+ const materializedEntries: FirmwareMemoryArtifactEntry[] = [];
1335
+ const normalizedFiles: IProtocolV2ResourceManifestFile[] = [];
1380
1336
  for (const file of selectedFiles) {
1381
- const entry = zip.file(file.archive_path);
1337
+ const entry = manifestEntry
1338
+ ? zip.file(`${manifestDirectory}${file.archive_path}`)
1339
+ : entries.find(
1340
+ candidate => getProtocolV2LocalResourceArchivePath(candidate.name) === file.archive_path
1341
+ );
1382
1342
  if (!entry) {
1383
1343
  throw ERRORS.TypedError(
1384
1344
  HardwareErrorCode.RuntimeError,
@@ -1397,15 +1357,21 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
1397
1357
  }
1398
1358
  const fileBinary = await entry.async('arraybuffer');
1399
1359
  const digest = bytesToHex(sha256(new Uint8Array(fileBinary)));
1400
- if (fileBinary.byteLength !== file.size || digest !== file.sha256.toLowerCase()) {
1360
+ if (
1361
+ fileBinary.byteLength !== file.size ||
1362
+ (file.sha256 && digest !== file.sha256.toLowerCase())
1363
+ ) {
1401
1364
  throw ERRORS.TypedError(
1402
1365
  HardwareErrorCode.RuntimeError,
1403
1366
  `Protocol V2 local resource file does not match manifest: ${file.archive_path}`,
1404
1367
  { firmwareUpdateCode: 'FirmwareArtifactReceiptMismatch' }
1405
1368
  );
1406
1369
  }
1370
+ normalizedFiles.push({ ...file, sha256: digest });
1407
1371
  materializedEntries.push({ entryName: file.archive_path, binary: fileBinary });
1408
1372
  }
1373
+ manifestBinary ??= new TextEncoder().encode(JSON.stringify({ files: normalizedFiles })).buffer;
1374
+ materializedEntries.unshift({ entryName: 'manifest.json', binary: manifestBinary });
1409
1375
  return { binary, materializedEntries };
1410
1376
  }
1411
1377
 
@@ -2168,11 +2134,6 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
2168
2134
  return this.device.features?.mode === 'romloader';
2169
2135
  }
2170
2136
 
2171
- private isLegacyProtocolV2Runtime() {
2172
- const protocolInfo = this.device.state?.raw?.protocolV2ProtocolInfo;
2173
- return protocolInfo ? isLegacyProtocolV2ProtocolInfo(protocolInfo) : false;
2174
- }
2175
-
2176
2137
  private async rebootProtocolV2ToBootloader() {
2177
2138
  try {
2178
2139
  this.postTipMessage(FirmwareUpdateTipMessage.AutoRebootToBootloader);
@@ -2192,18 +2153,15 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
2192
2153
  }
2193
2154
 
2194
2155
  async enterProtocolV2BootloaderMode() {
2195
- this.protocolV2LegacyDirectUpdate = false;
2196
2156
  // romloader is the first update environment and forwards targets to bootloader.
2197
2157
  // It rejects DeviceRebootType.Bootloader, so reuse the current connection.
2198
2158
  if (this.isProtocolV2RomloaderMode()) {
2199
2159
  Log.debug('Protocol V2 device is in romloader mode; start firmware update directly');
2200
- this.protocolV2LegacyDirectUpdate = this.isLegacyProtocolV2Runtime();
2201
2160
  this.protocolV2ExecutionInLoader = true;
2202
2161
  return false;
2203
2162
  }
2204
2163
  if (this.isProtocolV2BootloaderMode()) {
2205
2164
  Log.debug('Protocol V2 device is already in bootloader mode, skip reboot');
2206
- this.protocolV2LegacyDirectUpdate = this.isLegacyProtocolV2Runtime();
2207
2165
  this.protocolV2ExecutionInLoader = true;
2208
2166
  this.postTipMessage(FirmwareUpdateTipMessage.GoToBootloaderSuccess);
2209
2167
  return false;
@@ -2714,7 +2672,7 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
2714
2672
  let missingTargetStatusSince: number | undefined;
2715
2673
  let missingTargetStatusKey: string | undefined;
2716
2674
  let normalModeWithoutInstallEvidenceSince: number | undefined;
2717
- let installEvidenceObserved = this.protocolV2InstallAckReceived;
2675
+ let installEvidenceObserved = false;
2718
2676
  const resetMissingTargetStatusGrace = () => {
2719
2677
  missingTargetStatusSince = undefined;
2720
2678
  missingTargetStatusKey = undefined;
@@ -2734,7 +2692,7 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
2734
2692
  try {
2735
2693
  const statusResponse = await this.device.getCommands().typedCall(
2736
2694
  'DeviceFirmwareUpdateStatusGet',
2737
- 'DeviceFirmwareUpdateStatus',
2695
+ ['DeviceFirmwareUpdateStatus', 'Success'],
2738
2696
  {
2739
2697
  fields: {
2740
2698
  status: true,
@@ -2744,6 +2702,11 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
2744
2702
  },
2745
2703
  { timeoutMs: PROTOCOL_V2_FIRMWARE_STATUS_RESPONSE_TIMEOUT }
2746
2704
  );
2705
+ if (statusResponse.type === 'Success') {
2706
+ this.protocolV2FinalStatusVerified = true;
2707
+ this.postProgressMessage(100, 'installingFirmware');
2708
+ return;
2709
+ }
2747
2710
  const statusTargets = (statusResponse.message.records ??
2748
2711
  []) as ProtocolV2FirmwareUpdateStatusTarget[];
2749
2712
  if (
@@ -3148,65 +3111,12 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
3148
3111
  }: {
3149
3112
  targets: Array<{ target_id: number; path: string }>;
3150
3113
  }) {
3151
- this.protocolV2InstallAckReceived = false;
3152
3114
  this.protocolV2LastRuntimeProbeFeatures = undefined;
3153
- const startUpdate = () =>
3154
- this.device
3155
- .getCommands()
3156
- .typedCall(
3157
- 'DeviceFirmwareUpdateRequest',
3158
- 'Success',
3159
- { targets },
3160
- { timeoutMs: PROTOCOL_V2_START_UPDATE_TIMEOUT }
3161
- );
3162
- let response: ProtocolV2FirmwareUpdateStartResponse | undefined;
3163
- try {
3164
- response = await startUpdate();
3165
- this.protocolV2InstallAckReceived = true;
3166
- } catch (error) {
3167
- if (this.isBleReconnect() && isProtocolV2BleInstallInterruptionError(error)) {
3168
- this.throwIfAborted();
3169
- // Installation can reboot the device before the Success response reaches
3170
- // the host. The request has side effects, so do not replay it; reconnect
3171
- // and let status polling determine whether installation was accepted.
3172
- Log.log(
3173
- '[FirmwareUpdateV4] install request interrupted by device reboot; continue status polling: ',
3174
- error
3175
- );
3176
- } else if (
3177
- this.protocolV2LegacyDirectUpdate &&
3178
- isProtocolV2FirmwareUpdateEndpointUnavailable(error)
3179
- ) {
3180
- // Both legacy loaders register this request. A missing handler therefore identifies
3181
- // a legacy App before dispatch, so it is safe to reboot and retry the unhandled request.
3182
- this.protocolV2LegacyDirectUpdate = false;
3183
- Log.debug(
3184
- '[FirmwareUpdateV4] legacy App does not expose DeviceFirmwareUpdateRequest; rebooting to bootloader'
3185
- );
3186
- await this.rebootProtocolV2ToBootloader();
3187
- try {
3188
- response = await startUpdate();
3189
- this.protocolV2InstallAckReceived = true;
3190
- } catch (retryError) {
3191
- if (!(this.isBleReconnect() && isProtocolV2BleInstallInterruptionError(retryError))) {
3192
- throw retryError;
3193
- }
3194
- this.throwIfAborted();
3195
- Log.log(
3196
- '[FirmwareUpdateV4] install request interrupted after legacy reboot; continue status polling: ',
3197
- retryError
3198
- );
3199
- }
3200
- } else {
3201
- throw error;
3202
- }
3203
- }
3204
- this.protocolV2LegacyDirectUpdate = false;
3205
- // A Success ACK or an install-time disconnect both end confirmation. In the
3206
- // latter case only status polling may establish the final outcome.
3115
+ const commands = this.device.getCommands();
3116
+ await commands.typedCall('DeviceFirmwareUpdateStage', 'Success', { targets });
3117
+ await commands.call('DeviceFirmwareUpdateRequest', {}, { returnAfterWrite: true });
3207
3118
  this.postTipMessage(FirmwareUpdateTipMessage.FirmwareUpdating);
3208
3119
  this.postProgressMessage(0, 'installingFirmware');
3209
- return response;
3210
3120
  }
3211
3121
 
3212
3122
  private async protocolV2Reboot(rebootType: DeviceRebootType) {
@@ -25,7 +25,7 @@ export default class DeviceFactoryInfoSet extends BaseMethod<DeviceFactoryInfoSe
25
25
  info: {
26
26
  version: this.params.version,
27
27
  serial_number: this.params.serial_number,
28
- burn_in_completed: this.params.burn_in_completed,
28
+ factory_burn_in_completed: this.params.burn_in_completed,
29
29
  factory_test_completed: this.params.factory_test_completed,
30
30
  manufacture_time: this.params.manufacture_time,
31
31
  },
@@ -5,7 +5,7 @@ import { invalidParameter } from '../helpers/filesystemValidation';
5
5
 
6
6
  export type DeviceInfoGetTargets = {
7
7
  hw?: boolean;
8
- fw?: boolean;
8
+ main_mcu?: boolean;
9
9
  coprocessor?: boolean;
10
10
  se1?: boolean;
11
11
  se2?: boolean;
@@ -27,7 +27,7 @@ export type DeviceInfoGetParams = {
27
27
 
28
28
  const TARGET_KEYS: (keyof DeviceInfoGetTargets)[] = [
29
29
  'hw',
30
- 'fw',
30
+ 'main_mcu',
31
31
  'coprocessor',
32
32
  'se1',
33
33
  'se2',
@@ -39,7 +39,7 @@ const TYPE_KEYS: (keyof DeviceInfoGetTypes)[] = ['version', 'build_id', 'hash',
39
39
 
40
40
  const DEFAULT_TARGETS: DeviceInfoGetTargets = {
41
41
  hw: true,
42
- fw: true,
42
+ main_mcu: true,
43
43
  coprocessor: true,
44
44
  };
45
45
 
@@ -174,7 +174,7 @@ export default class TonSignMessage extends BaseMethod<HardwareTonSignMessage> {
174
174
  if (!request.init_data_length) {
175
175
  const deviceType = this.device.getCurrentDeviceType();
176
176
  const hasClassic = DeviceModelToTypes.model_classic1s.includes(deviceType);
177
- const signingMessage = request.signing_message ?? request.signning_message;
177
+ const signingMessage = request.signning_message;
178
178
  // Blind signing omits the signing message in both protocol schemas.
179
179
  const shouldSkipValidation = signingMessage == null;
180
180
 
@@ -462,9 +462,10 @@
462
462
  "MessageType_FilesystemDirMake": 60809,
463
463
  "MessageType_FilesystemDirRemove": 60810,
464
464
  "MessageType_FilesystemFormat": 60811,
465
- "MessageType_DeviceFirmwareUpdateRequest": 61000,
466
- "MessageType_DeviceFirmwareUpdateStatusGet": 61001,
467
- "MessageType_DeviceFirmwareUpdateStatus": 61002,
465
+ "MessageType_DeviceFirmwareUpdateStage": 61000,
466
+ "MessageType_DeviceFirmwareUpdateRequest": 61001,
467
+ "MessageType_DeviceFirmwareUpdateStatusGet": 61002,
468
+ "MessageType_DeviceFirmwareUpdateStatus": 61003,
468
469
  "MessageType_DeviceSessionGet": 61200,
469
470
  "MessageType_DeviceSession": 61201,
470
471
  "MessageType_DeviceSessionAskPin": 61202,
@@ -10924,7 +10925,7 @@
10924
10925
  "type": "bytes",
10925
10926
  "id": 1
10926
10927
  },
10927
- "signing_message": {
10928
+ "signning_message": {
10928
10929
  "type": "bytes",
10929
10930
  "id": 2
10930
10931
  },
@@ -11813,14 +11814,14 @@
11813
11814
  "type": "string",
11814
11815
  "id": 2
11815
11816
  },
11816
- "burn_in_completed": {
11817
- "type": "bool",
11818
- "id": 3
11819
- },
11820
11817
  "factory_test_completed": {
11821
11818
  "type": "bool",
11822
11819
  "id": 4
11823
11820
  },
11821
+ "factory_burn_in_completed": {
11822
+ "type": "bool",
11823
+ "id": 3
11824
+ },
11824
11825
  "manufacture_time": {
11825
11826
  "type": "DeviceFactoryInfoManufactureTime",
11826
11827
  "id": 5
@@ -11906,7 +11907,7 @@
11906
11907
  }
11907
11908
  }
11908
11909
  },
11909
- "DeviceFirmwareUpdateRequest": {
11910
+ "DeviceFirmwareUpdateStage": {
11910
11911
  "fields": {
11911
11912
  "targets": {
11912
11913
  "rule": "repeated",
@@ -11915,6 +11916,9 @@
11915
11916
  }
11916
11917
  }
11917
11918
  },
11919
+ "DeviceFirmwareUpdateRequest": {
11920
+ "fields": {}
11921
+ },
11918
11922
  "DeviceFirmwareUpdateRecord": {
11919
11923
  "fields": {
11920
11924
  "target_id": {
@@ -12096,7 +12100,7 @@
12096
12100
  "type": "bool",
12097
12101
  "id": 100
12098
12102
  },
12099
- "fw": {
12103
+ "main_mcu": {
12100
12104
  "type": "bool",
12101
12105
  "id": 200
12102
12106
  },
@@ -12165,7 +12169,7 @@
12165
12169
  "type": "DeviceHardwareInfo",
12166
12170
  "id": 100
12167
12171
  },
12168
- "fw": {
12172
+ "main_mcu": {
12169
12173
  "type": "DeviceMainMcuInfo",
12170
12174
  "id": 200
12171
12175
  },
@@ -12703,9 +12707,12 @@
12703
12707
  "id": 1
12704
12708
  },
12705
12709
  "text": {
12706
- "rule": "required",
12707
12710
  "type": "string",
12708
12711
  "id": 2
12712
+ },
12713
+ "text_id": {
12714
+ "type": "uint32",
12715
+ "id": 3
12709
12716
  }
12710
12717
  }
12711
12718
  },
@@ -12736,7 +12743,6 @@
12736
12743
  "ViewSignPage": {
12737
12744
  "fields": {
12738
12745
  "title": {
12739
- "rule": "required",
12740
12746
  "type": "string",
12741
12747
  "id": 1
12742
12748
  },
@@ -12770,13 +12776,16 @@
12770
12776
  "options": {
12771
12777
  "default": "LayoutDefault"
12772
12778
  }
12779
+ },
12780
+ "title_id": {
12781
+ "type": "uint32",
12782
+ "id": 8
12773
12783
  }
12774
12784
  }
12775
12785
  },
12776
12786
  "ViewVerifyPage": {
12777
12787
  "fields": {
12778
12788
  "title": {
12779
- "rule": "required",
12780
12789
  "type": "string",
12781
12790
  "id": 1
12782
12791
  },
@@ -12801,6 +12810,14 @@
12801
12810
  "value_key": {
12802
12811
  "type": "uint32",
12803
12812
  "id": 6
12813
+ },
12814
+ "title_id": {
12815
+ "type": "uint32",
12816
+ "id": 7
12817
+ },
12818
+ "chain_id": {
12819
+ "type": "uint32",
12820
+ "id": 8
12804
12821
  }
12805
12822
  }
12806
12823
  },
@@ -267,11 +267,11 @@ export const mapProtocolV2DeviceInfoToState = (
267
267
  }
268
268
  : { mode },
269
269
  versions: definedEntries({
270
- firmware: imageVersion(info.fw?.application),
271
- applicationP1: imageVersion(info.fw?.application),
272
- applicationP2: imageVersion(info.fw?.application_data),
273
- bootloader: imageVersion(info.fw?.bootloader),
274
- board: imageVersion(info.fw?.romloader),
270
+ firmware: imageVersion(info.main_mcu?.application),
271
+ applicationP1: imageVersion(info.main_mcu?.application),
272
+ applicationP2: imageVersion(info.main_mcu?.application_data),
273
+ bootloader: imageVersion(info.main_mcu?.bootloader),
274
+ board: imageVersion(info.main_mcu?.romloader),
275
275
  ble: imageVersion(info.coprocessor?.application),
276
276
  se01: imageVersion(info.se1?.application),
277
277
  se02: imageVersion(info.se2?.application),
@@ -283,16 +283,16 @@ export const mapProtocolV2DeviceInfoToState = (
283
283
  se04Boot: imageVersion(info.se4?.bootloader),
284
284
  }),
285
285
  verification: definedEntries({
286
- firmwareBuildId: imageBuildId(info.fw?.application),
287
- firmwareHash: imageHash(info.fw?.application),
288
- applicationP1BuildId: imageBuildId(info.fw?.application),
289
- applicationP1Hash: imageHash(info.fw?.application),
290
- applicationP2BuildId: imageBuildId(info.fw?.application_data),
291
- applicationP2Hash: imageHash(info.fw?.application_data),
292
- bootloaderBuildId: imageBuildId(info.fw?.bootloader),
293
- bootloaderHash: imageHash(info.fw?.bootloader),
294
- boardBuildId: imageBuildId(info.fw?.romloader),
295
- boardHash: imageHash(info.fw?.romloader),
286
+ firmwareBuildId: imageBuildId(info.main_mcu?.application),
287
+ firmwareHash: imageHash(info.main_mcu?.application),
288
+ applicationP1BuildId: imageBuildId(info.main_mcu?.application),
289
+ applicationP1Hash: imageHash(info.main_mcu?.application),
290
+ applicationP2BuildId: imageBuildId(info.main_mcu?.application_data),
291
+ applicationP2Hash: imageHash(info.main_mcu?.application_data),
292
+ bootloaderBuildId: imageBuildId(info.main_mcu?.bootloader),
293
+ bootloaderHash: imageHash(info.main_mcu?.bootloader),
294
+ boardBuildId: imageBuildId(info.main_mcu?.romloader),
295
+ boardHash: imageHash(info.main_mcu?.romloader),
296
296
  bleBuildId: imageBuildId(info.coprocessor?.application),
297
297
  bleHash: imageHash(info.coprocessor?.application),
298
298
  se01BuildId: imageBuildId(info.se1?.application),
@@ -216,9 +216,9 @@ export const buildProtocolV2FeaturesPayload = ({
216
216
  runtimeMode?: ProtocolV2RuntimeMode;
217
217
  }): Features => {
218
218
  const info = deviceInfo;
219
- const fwApplication = info?.fw?.application;
220
- const fwBootloader = info?.fw?.bootloader;
221
- const fwBoard = info?.fw?.romloader;
219
+ const fwApplication = info?.main_mcu?.application;
220
+ const fwBootloader = info?.main_mcu?.bootloader;
221
+ const fwBoard = info?.main_mcu?.romloader;
222
222
  const bleApplication = info?.coprocessor?.application;
223
223
  const status = deviceStatus;
224
224
  const incomingSerialNo = info?.hw?.serial_no;