@onekeyfe/hd-core 1.2.0-alpha.107 → 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 (74) hide show
  1. package/__tests__/DeviceCommands.test.ts +140 -26
  2. package/__tests__/base64Data.test.ts +70 -0
  3. package/__tests__/device-lifecycle-events.test.ts +113 -2
  4. package/__tests__/device-pool-state.test.ts +25 -0
  5. package/__tests__/device-state-mapper.test.ts +4 -4
  6. package/__tests__/device-utils.test.ts +1 -1
  7. package/__tests__/deviceSettings.test.ts +0 -1
  8. package/__tests__/deviceUploadNft.test.ts +33 -4
  9. package/__tests__/firmware-update/firmware-update-v4-install-poll.test.ts +125 -0
  10. package/__tests__/get-device-state.test.ts +60 -21
  11. package/__tests__/logBlockEvent.test.ts +13 -1
  12. package/__tests__/protocol-v2-resources.test.ts +8 -0
  13. package/__tests__/protocol-v2.test.ts +821 -227
  14. package/__tests__/refresh-device-state.test.ts +3 -1
  15. package/__tests__/resourceBase64Boundary.test.ts +48 -0
  16. package/__tests__/ton-sign-message.test.ts +84 -0
  17. package/dist/api/FirmwareUpdateV4.d.ts +7 -3
  18. package/dist/api/FirmwareUpdateV4.d.ts.map +1 -1
  19. package/dist/api/UploadPortfolio.d.ts +1 -1
  20. package/dist/api/UploadPortfolio.d.ts.map +1 -1
  21. package/dist/api/helpers/base64Data.d.ts +16 -0
  22. package/dist/api/helpers/base64Data.d.ts.map +1 -0
  23. package/dist/api/protocol-v2/DeviceInfoGet.d.ts +1 -1
  24. package/dist/api/protocol-v2/DeviceInfoGet.d.ts.map +1 -1
  25. package/dist/api/protocol-v2/DeviceUploadNft.d.ts +2 -3
  26. package/dist/api/protocol-v2/DeviceUploadNft.d.ts.map +1 -1
  27. package/dist/api/protocol-v2/DeviceUploadWallpaper.d.ts +2 -3
  28. package/dist/api/protocol-v2/DeviceUploadWallpaper.d.ts.map +1 -1
  29. package/dist/api/ton/TonSignMessage.d.ts.map +1 -1
  30. package/dist/core/index.d.ts.map +1 -1
  31. package/dist/device/Device.d.ts +7 -2
  32. package/dist/device/Device.d.ts.map +1 -1
  33. package/dist/device/DeviceCommands.d.ts.map +1 -1
  34. package/dist/device/DevicePool.d.ts.map +1 -1
  35. package/dist/events/logBlockEvent.d.ts.map +1 -1
  36. package/dist/index.d.ts +16 -34
  37. package/dist/index.js +506 -329
  38. package/dist/protocols/protocol-v2/features.d.ts +13 -5
  39. package/dist/protocols/protocol-v2/features.d.ts.map +1 -1
  40. package/dist/protocols/protocol-v2/index.d.ts +2 -2
  41. package/dist/protocols/protocol-v2/index.d.ts.map +1 -1
  42. package/dist/protocols/protocol-v2/resources.d.ts.map +1 -1
  43. package/dist/types/api/protocolV2.d.ts +1 -1
  44. package/dist/types/api/protocolV2.d.ts.map +1 -1
  45. package/dist/types/settings.d.ts +4 -19
  46. package/dist/types/settings.d.ts.map +1 -1
  47. package/dist/utils/patch.d.ts +1 -1
  48. package/dist/utils/patch.d.ts.map +1 -1
  49. package/dist/utils/pro2Nft.d.ts +7 -0
  50. package/dist/utils/pro2Nft.d.ts.map +1 -1
  51. package/package.json +6 -4
  52. package/src/api/FirmwareUpdateV4.ts +307 -245
  53. package/src/api/UploadPortfolio.ts +9 -2
  54. package/src/api/helpers/base64Data.ts +85 -0
  55. package/src/api/protocol-v2/DeviceFactoryInfoSet.ts +1 -1
  56. package/src/api/protocol-v2/DeviceInfoGet.ts +3 -3
  57. package/src/api/protocol-v2/DeviceUploadNft.ts +56 -8
  58. package/src/api/protocol-v2/DeviceUploadWallpaper.ts +37 -18
  59. package/src/api/ton/TonSignMessage.ts +5 -3
  60. package/src/core/index.ts +6 -2
  61. package/src/data/messages/messages-protocol-v2.json +31 -14
  62. package/src/device/Device.ts +53 -31
  63. package/src/device/DeviceCommands.ts +4 -14
  64. package/src/device/DevicePool.ts +6 -2
  65. package/src/device/DeviceStateMapper.ts +15 -15
  66. package/src/deviceProfile/buildDeviceFeatures.ts +3 -3
  67. package/src/events/logBlockEvent.ts +14 -1
  68. package/src/protocols/protocol-v2/features.ts +22 -5
  69. package/src/protocols/protocol-v2/index.ts +2 -0
  70. package/src/protocols/protocol-v2/resources.ts +9 -46
  71. package/src/types/api/protocolV2.ts +1 -1
  72. package/src/types/settings.ts +4 -19
  73. package/src/utils/deviceSettings.ts +1 -1
  74. package/src/utils/pro2Nft.ts +31 -8
@@ -1,21 +1,28 @@
1
1
  import { createDeviceNotSupportMethodError } from '@onekeyfe/hd-shared';
2
2
 
3
3
  import { supportsProtocolV2Message } from '../protocols/protocol-v2/features';
4
+ import { decodeCanonicalBase64 } from './helpers/base64Data';
4
5
  import FileWrite from './FileWrite';
5
6
 
6
7
  export type UploadPortfolioParams = {
7
- packageBytes: ArrayBuffer | Uint8Array | Blob;
8
+ packageBase64: string;
8
9
  timeoutMs?: number | string;
9
10
  };
10
11
 
11
12
  const PORTFOLIO_PENDING_PATH = 'vol1:/portfolio/portfolio.okpkg.pending';
12
13
  const PORTFOLIO_CHUNK_SIZE = 2048;
14
+ const PORTFOLIO_PACKAGE_MAX_BYTES = 128 * 1024;
13
15
  const FILESYSTEM_FILE_WRITE_MESSAGE_TYPE = 60805;
14
16
  const PORTFOLIO_UPDATE_MESSAGE_TYPE = 61400;
15
17
 
16
18
  export default class UploadPortfolio extends FileWrite {
17
19
  init() {
18
- const { packageBytes, timeoutMs } = this.payload as UploadPortfolioParams;
20
+ const { packageBase64, timeoutMs } = this.payload as UploadPortfolioParams;
21
+ const packageBytes = decodeCanonicalBase64({
22
+ value: packageBase64,
23
+ parameterName: 'packageBase64',
24
+ maxBytes: PORTFOLIO_PACKAGE_MAX_BYTES,
25
+ });
19
26
  this.payload = {
20
27
  ...this.payload,
21
28
  path: PORTFOLIO_PENDING_PATH,
@@ -0,0 +1,85 @@
1
+ import { Buffer } from 'buffer';
2
+ import { decode as decodeJpeg } from 'jpeg-js';
3
+
4
+ import { invalidParameter } from './filesystemValidation';
5
+
6
+ const BASE64_PATTERN = /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/;
7
+ const JPEG_CONTAINER_OVERHEAD_BYTES = 64 * 1024;
8
+ const JPEG_MAX_MEMORY_USAGE_IN_MB = 32;
9
+ const JPEG_MAX_RESOLUTION_IN_MP = 1;
10
+
11
+ export function decodeCanonicalBase64({
12
+ value,
13
+ parameterName,
14
+ maxBytes,
15
+ }: {
16
+ value: unknown;
17
+ parameterName: string;
18
+ maxBytes: number;
19
+ }): Uint8Array {
20
+ if (typeof value !== 'string' || value.length === 0) {
21
+ throw invalidParameter(`Parameter [${parameterName}] must be a non-empty Base64 string.`);
22
+ }
23
+ if (value.length > Math.ceil(maxBytes / 3) * 4) {
24
+ throw invalidParameter(`Parameter [${parameterName}] exceeds the maximum supported size.`);
25
+ }
26
+ if (value.length % 4 !== 0 || !BASE64_PATTERN.test(value)) {
27
+ throw invalidParameter(`Parameter [${parameterName}] must use canonical Base64 encoding.`);
28
+ }
29
+
30
+ const decoded = Buffer.from(value, 'base64');
31
+ if (decoded.byteLength === 0 || decoded.byteLength > maxBytes) {
32
+ throw invalidParameter(`Parameter [${parameterName}] exceeds the maximum supported size.`);
33
+ }
34
+ if (decoded.toString('base64') !== value) {
35
+ throw invalidParameter(`Parameter [${parameterName}] must use canonical Base64 encoding.`);
36
+ }
37
+ return Uint8Array.from(decoded);
38
+ }
39
+
40
+ export function decodeJpegBase64ToRgba({
41
+ jpegBase64,
42
+ parameterName,
43
+ expectedWidth,
44
+ expectedHeight,
45
+ }: {
46
+ jpegBase64: unknown;
47
+ parameterName: string;
48
+ expectedWidth: number;
49
+ expectedHeight: number;
50
+ }): { width: number; height: number; data: Uint8Array } {
51
+ const jpegBytes = decodeCanonicalBase64({
52
+ value: jpegBase64,
53
+ parameterName,
54
+ maxBytes: expectedWidth * expectedHeight * 8 + JPEG_CONTAINER_OVERHEAD_BYTES,
55
+ });
56
+ if (jpegBytes[0] !== 0xff || jpegBytes[1] !== 0xd8) {
57
+ throw invalidParameter(`Parameter [${parameterName}] must contain a JPEG image.`);
58
+ }
59
+
60
+ let decoded: { width: number; height: number; data: Uint8Array };
61
+ try {
62
+ decoded = decodeJpeg(jpegBytes, {
63
+ useTArray: true,
64
+ formatAsRGBA: true,
65
+ tolerantDecoding: false,
66
+ maxResolutionInMP: JPEG_MAX_RESOLUTION_IN_MP,
67
+ maxMemoryUsageInMB: JPEG_MAX_MEMORY_USAGE_IN_MB,
68
+ });
69
+ } catch {
70
+ throw invalidParameter(`Parameter [${parameterName}] must contain a valid JPEG image.`);
71
+ }
72
+
73
+ if (decoded.width !== expectedWidth || decoded.height !== expectedHeight) {
74
+ throw invalidParameter(
75
+ `Parameter [${parameterName}] must contain a ${expectedWidth}x${expectedHeight} JPEG image.`
76
+ );
77
+ }
78
+ const expectedLength = expectedWidth * expectedHeight * 4;
79
+ if (decoded.data.byteLength !== expectedLength) {
80
+ throw invalidParameter(
81
+ `Decoded parameter [${parameterName}] must contain ${expectedLength} RGBA bytes.`
82
+ );
83
+ }
84
+ return decoded;
85
+ }
@@ -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
 
@@ -7,21 +7,26 @@ import {
7
7
  PRO2_NFT_DEFAULT_PACE_MS,
8
8
  PRO2_NFT_DEFAULT_TIMEOUT_MS,
9
9
  PRO2_NFT_DIRECTORY,
10
+ PRO2_NFT_IMAGE_HEIGHT,
11
+ PRO2_NFT_IMAGE_WIDTH,
10
12
  PRO2_NFT_MAX_CHUNK_SIZE,
11
13
  PRO2_NFT_MAX_ITEMS,
12
14
  PRO2_NFT_MIN_CHUNK_SIZE,
15
+ PRO2_NFT_THUMBNAIL_HEIGHT,
16
+ PRO2_NFT_THUMBNAIL_WIDTH,
13
17
  type Pro2NftBundle,
14
- type Pro2NftImage,
15
- buildPro2NftBundle,
18
+ buildPro2NftBundleFromEncodedImages,
16
19
  getCompletePro2NftBasenames,
17
20
  } from '../../utils/pro2Nft';
21
+ import { encodePro2Image } from '../../utils/pro2Wallpaper';
18
22
  import { BaseMethod } from '../BaseMethod';
23
+ import { decodeJpegBase64ToRgba } from '../helpers/base64Data';
19
24
  import { invalidParameter } from '../helpers/filesystemValidation';
20
25
  import { writeProtocolV2File } from '../helpers/protocolV2FileWrite';
21
26
 
22
27
  export type DeviceUploadNftParams = {
23
- image: Pro2NftImage;
24
- thumbnail: Pro2NftImage;
28
+ imageJpegBase64: string;
29
+ thumbnailJpegBase64: string;
25
30
  title: string;
26
31
  subtitle: string;
27
32
  timestampMs?: number;
@@ -54,8 +59,8 @@ export default class DeviceUploadNft extends BaseMethod<DeviceUploadNftParams> {
54
59
 
55
60
  init() {
56
61
  const {
57
- image,
58
- thumbnail,
62
+ imageJpegBase64,
63
+ thumbnailJpegBase64,
59
64
  title,
60
65
  subtitle,
61
66
  timestampMs = Date.now(),
@@ -79,8 +84,51 @@ export default class DeviceUploadNft extends BaseMethod<DeviceUploadNftParams> {
79
84
  throw invalidParameter('Parameter [timeoutMs] must be a positive integer.');
80
85
  }
81
86
 
82
- this.bundle = buildPro2NftBundle({ image, thumbnail, title, subtitle, timestampMs });
83
- this.params = { image, thumbnail, title, subtitle, timestampMs, chunkSize, paceMs, timeoutMs };
87
+ const encodedImage = (() => {
88
+ const decoded = decodeJpegBase64ToRgba({
89
+ jpegBase64: imageJpegBase64,
90
+ parameterName: 'imageJpegBase64',
91
+ expectedWidth: PRO2_NFT_IMAGE_WIDTH,
92
+ expectedHeight: PRO2_NFT_IMAGE_HEIGHT,
93
+ });
94
+ return encodePro2Image({
95
+ width: PRO2_NFT_IMAGE_WIDTH,
96
+ height: PRO2_NFT_IMAGE_HEIGHT,
97
+ rgba: decoded.data,
98
+ alphaMode: 'black-background',
99
+ }).data;
100
+ })();
101
+ const encodedThumbnail = (() => {
102
+ const decoded = decodeJpegBase64ToRgba({
103
+ jpegBase64: thumbnailJpegBase64,
104
+ parameterName: 'thumbnailJpegBase64',
105
+ expectedWidth: PRO2_NFT_THUMBNAIL_WIDTH,
106
+ expectedHeight: PRO2_NFT_THUMBNAIL_HEIGHT,
107
+ });
108
+ return encodePro2Image({
109
+ width: PRO2_NFT_THUMBNAIL_WIDTH,
110
+ height: PRO2_NFT_THUMBNAIL_HEIGHT,
111
+ rgba: decoded.data,
112
+ alphaMode: 'black-background',
113
+ }).data;
114
+ })();
115
+ this.bundle = buildPro2NftBundleFromEncodedImages({
116
+ image: encodedImage,
117
+ thumbnail: encodedThumbnail,
118
+ title,
119
+ subtitle,
120
+ timestampMs,
121
+ });
122
+ this.params = {
123
+ imageJpegBase64,
124
+ thumbnailJpegBase64,
125
+ title,
126
+ subtitle,
127
+ timestampMs,
128
+ chunkSize,
129
+ paceMs,
130
+ timeoutMs,
131
+ };
84
132
  this.unlockPolicy = 'none';
85
133
  this.skipForceUpdateCheck = true;
86
134
  this.useDevicePassphraseState = false;
@@ -1,10 +1,13 @@
1
1
  import { blake2s } from '@noble/hashes/blake2s';
2
2
  import { bytesToHex } from '@noble/hashes/utils';
3
+ import { createDeviceNotSupportMethodError } from '@onekeyfe/hd-shared';
3
4
 
4
5
  import { BaseMethod } from '../BaseMethod';
6
+ import { decodeJpegBase64ToRgba } from '../helpers/base64Data';
5
7
  import { invalidParameter } from '../helpers/filesystemValidation';
6
8
  import { writeProtocolV2File } from '../helpers/protocolV2FileWrite';
7
9
  import { UI_REQUEST, createUiMessage } from '../../events/ui-request';
10
+ import { supportsProtocolV2Message } from '../../protocols/protocol-v2/features';
8
11
  import {
9
12
  PRO2_WALLPAPER_HEIGHT,
10
13
  PRO2_WALLPAPER_WIDTH,
@@ -13,9 +16,7 @@ import {
13
16
  } from '../../utils/pro2Wallpaper';
14
17
 
15
18
  export type DeviceUploadWallpaperParams = {
16
- width: number;
17
- height: number;
18
- rgba: Uint8Array | ArrayBuffer;
19
+ jpegBase64: string;
19
20
  fileName?: string;
20
21
  chunkSize?: number;
21
22
  };
@@ -29,6 +30,9 @@ export type DeviceUploadWallpaperResponse = {
29
30
 
30
31
  const WALLPAPER_DIRECTORY = 'vol1:/wallpapers';
31
32
  const SAFE_FILE_NAME = /^[A-Za-z0-9_-]+(?:\.bin)?$/;
33
+ const DEVICE_SETTINGS_SET_MESSAGE_TYPE = 60412;
34
+ const FILESYSTEM_FILE_WRITE_MESSAGE_TYPE = 60805;
35
+ const FILESYSTEM_DIR_MAKE_MESSAGE_TYPE = 60809;
32
36
 
33
37
  function normalizeFileName(fileName: string | undefined, data: Uint8Array): string {
34
38
  if (fileName !== undefined && (!fileName || !SAFE_FILE_NAME.test(fileName))) {
@@ -54,31 +58,45 @@ export default class DeviceUploadWallpaper extends BaseMethod<DeviceUploadWallpa
54
58
  private path = '';
55
59
 
56
60
  init() {
57
- const { width, height, rgba, fileName, chunkSize } = this.payload;
58
- if (width !== PRO2_WALLPAPER_WIDTH || height !== PRO2_WALLPAPER_HEIGHT) {
59
- throw invalidParameter(
60
- `Pro2 wallpaper dimensions must be ${PRO2_WALLPAPER_WIDTH}x${PRO2_WALLPAPER_HEIGHT}.`
61
- );
62
- }
63
- if (!(rgba instanceof ArrayBuffer) && !ArrayBuffer.isView(rgba)) {
64
- throw invalidParameter('Parameter [rgba] must be an ArrayBuffer or Uint8Array.');
65
- }
61
+ const { jpegBase64, fileName, chunkSize } = this.payload;
66
62
  if (chunkSize !== undefined && (!Number.isInteger(chunkSize) || chunkSize <= 0)) {
67
63
  throw invalidParameter('Parameter [chunkSize] must be a positive integer.');
68
64
  }
69
65
 
70
- const rgbaBytes =
71
- rgba instanceof ArrayBuffer
72
- ? rgba
73
- : new Uint8Array(rgba.buffer, rgba.byteOffset, rgba.byteLength);
74
- this.encoded = encodePro2Wallpaper({ width, height, rgba: rgbaBytes });
66
+ const decoded = decodeJpegBase64ToRgba({
67
+ jpegBase64,
68
+ parameterName: 'jpegBase64',
69
+ expectedWidth: PRO2_WALLPAPER_WIDTH,
70
+ expectedHeight: PRO2_WALLPAPER_HEIGHT,
71
+ });
72
+ this.encoded = encodePro2Wallpaper({
73
+ width: PRO2_WALLPAPER_WIDTH,
74
+ height: PRO2_WALLPAPER_HEIGHT,
75
+ rgba: decoded.data,
76
+ });
75
77
  this.path = `${WALLPAPER_DIRECTORY}/${normalizeFileName(fileName, this.encoded.data)}`;
76
- this.params = { width, height, rgba: rgbaBytes, fileName, chunkSize };
78
+ this.params = { jpegBase64, fileName, chunkSize };
77
79
  this.unlockPolicy = 'none';
78
80
  this.skipForceUpdateCheck = true;
79
81
  this.useDevicePassphraseState = false;
80
82
  }
81
83
 
84
+ private async assertCapabilities() {
85
+ const protocolInfo = await this.device.ensureProtocolV2RuntimeContext();
86
+ const requiredMessageTypes = [
87
+ DEVICE_SETTINGS_SET_MESSAGE_TYPE,
88
+ FILESYSTEM_FILE_WRITE_MESSAGE_TYPE,
89
+ FILESYSTEM_DIR_MAKE_MESSAGE_TYPE,
90
+ ];
91
+ if (
92
+ requiredMessageTypes.some(
93
+ messageType => !supportsProtocolV2Message(protocolInfo, messageType)
94
+ )
95
+ ) {
96
+ throw createDeviceNotSupportMethodError(this.name, this.device.getCurrentFirmwareType());
97
+ }
98
+ }
99
+
82
100
  private async ensureDirectory() {
83
101
  if (this.directoryReady) return;
84
102
  try {
@@ -119,6 +137,7 @@ export default class DeviceUploadWallpaper extends BaseMethod<DeviceUploadWallpa
119
137
  async run(): Promise<DeviceUploadWallpaperResponse> {
120
138
  const { encoded } = this;
121
139
  if (!encoded) throw invalidParameter('Wallpaper data has not been initialized.');
140
+ await this.assertCapabilities();
122
141
  await this.ensureDirectory();
123
142
  await this.upload();
124
143
  const response = await this.device.commands.typedCall('DeviceSettingsSet', 'Success', {
@@ -174,12 +174,14 @@ 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
- // use signing_message_repr sign, not exists signning_message, skip validate
178
- const hasSigningMessageRepr = request.signning_message == null;
177
+ const signingMessage = request.signning_message;
178
+ // Blind signing omits the signing message in both protocol schemas.
179
+ const shouldSkipValidation = signingMessage == null;
179
180
 
180
181
  return Promise.resolve({
181
182
  ...request,
182
- skip_validate: hasClassic || hasSigningMessageRepr,
183
+ signing_message: signingMessage,
184
+ skip_validate: hasClassic || shouldSkipValidation,
183
185
  });
184
186
  }
185
187
 
package/src/core/index.ts CHANGED
@@ -136,6 +136,9 @@ const toError = (error: unknown): Error | undefined => {
136
136
  }
137
137
  };
138
138
 
139
+ const isExpectedCompatibilityError = (error: unknown) =>
140
+ error instanceof HardwareError && error.errorCode === HardwareErrorCode.DeviceNotSupportMethod;
141
+
139
142
  const updateMethodRequestContext = (method: BaseMethod, updates: any) => {
140
143
  if (method.requestContext) {
141
144
  updateRequestContext(method.requestContext.responseID, updates);
@@ -693,7 +696,9 @@ const onCallDevice = async (
693
696
  try {
694
697
  return await task.callPromise.promise;
695
698
  } catch (e) {
696
- Log.debug('Device Run Error: ', e);
699
+ if (!isExpectedCompatibilityError(e)) {
700
+ Log.debug('Device Run Error: ', e);
701
+ }
697
702
  completeMethodRequestContext(method, e);
698
703
  return createResponseMessage(method.responseID, false, { error: e });
699
704
  }
@@ -1248,7 +1253,6 @@ const cleanup = () => {
1248
1253
  pendingUiPromises,
1249
1254
  ERRORS.TypedError(HardwareErrorCode.ActionCancelled, 'UI request was cancelled')
1250
1255
  );
1251
- Log.debug('Cleanup...');
1252
1256
  };
1253
1257
 
1254
1258
  const removeDeviceListener = (device: Device) => {
@@ -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
  },