@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.
- package/__tests__/DeviceCommands.test.ts +140 -26
- package/__tests__/base64Data.test.ts +70 -0
- package/__tests__/device-lifecycle-events.test.ts +113 -2
- package/__tests__/device-pool-state.test.ts +25 -0
- package/__tests__/device-state-mapper.test.ts +4 -4
- package/__tests__/device-utils.test.ts +1 -1
- package/__tests__/deviceSettings.test.ts +0 -1
- package/__tests__/deviceUploadNft.test.ts +33 -4
- package/__tests__/firmware-update/firmware-update-v4-install-poll.test.ts +125 -0
- package/__tests__/get-device-state.test.ts +60 -21
- package/__tests__/logBlockEvent.test.ts +13 -1
- package/__tests__/protocol-v2-resources.test.ts +8 -0
- package/__tests__/protocol-v2.test.ts +821 -227
- package/__tests__/refresh-device-state.test.ts +3 -1
- package/__tests__/resourceBase64Boundary.test.ts +48 -0
- package/__tests__/ton-sign-message.test.ts +84 -0
- package/dist/api/FirmwareUpdateV4.d.ts +7 -3
- package/dist/api/FirmwareUpdateV4.d.ts.map +1 -1
- package/dist/api/UploadPortfolio.d.ts +1 -1
- package/dist/api/UploadPortfolio.d.ts.map +1 -1
- package/dist/api/helpers/base64Data.d.ts +16 -0
- package/dist/api/helpers/base64Data.d.ts.map +1 -0
- package/dist/api/protocol-v2/DeviceInfoGet.d.ts +1 -1
- package/dist/api/protocol-v2/DeviceInfoGet.d.ts.map +1 -1
- package/dist/api/protocol-v2/DeviceUploadNft.d.ts +2 -3
- package/dist/api/protocol-v2/DeviceUploadNft.d.ts.map +1 -1
- package/dist/api/protocol-v2/DeviceUploadWallpaper.d.ts +2 -3
- package/dist/api/protocol-v2/DeviceUploadWallpaper.d.ts.map +1 -1
- package/dist/api/ton/TonSignMessage.d.ts.map +1 -1
- package/dist/core/index.d.ts.map +1 -1
- package/dist/device/Device.d.ts +7 -2
- package/dist/device/Device.d.ts.map +1 -1
- package/dist/device/DeviceCommands.d.ts.map +1 -1
- package/dist/device/DevicePool.d.ts.map +1 -1
- package/dist/events/logBlockEvent.d.ts.map +1 -1
- package/dist/index.d.ts +16 -34
- package/dist/index.js +506 -329
- package/dist/protocols/protocol-v2/features.d.ts +13 -5
- package/dist/protocols/protocol-v2/features.d.ts.map +1 -1
- package/dist/protocols/protocol-v2/index.d.ts +2 -2
- package/dist/protocols/protocol-v2/index.d.ts.map +1 -1
- package/dist/protocols/protocol-v2/resources.d.ts.map +1 -1
- package/dist/types/api/protocolV2.d.ts +1 -1
- package/dist/types/api/protocolV2.d.ts.map +1 -1
- package/dist/types/settings.d.ts +4 -19
- package/dist/types/settings.d.ts.map +1 -1
- package/dist/utils/patch.d.ts +1 -1
- package/dist/utils/patch.d.ts.map +1 -1
- package/dist/utils/pro2Nft.d.ts +7 -0
- package/dist/utils/pro2Nft.d.ts.map +1 -1
- package/package.json +6 -4
- package/src/api/FirmwareUpdateV4.ts +307 -245
- package/src/api/UploadPortfolio.ts +9 -2
- package/src/api/helpers/base64Data.ts +85 -0
- package/src/api/protocol-v2/DeviceFactoryInfoSet.ts +1 -1
- package/src/api/protocol-v2/DeviceInfoGet.ts +3 -3
- package/src/api/protocol-v2/DeviceUploadNft.ts +56 -8
- package/src/api/protocol-v2/DeviceUploadWallpaper.ts +37 -18
- package/src/api/ton/TonSignMessage.ts +5 -3
- package/src/core/index.ts +6 -2
- package/src/data/messages/messages-protocol-v2.json +31 -14
- package/src/device/Device.ts +53 -31
- package/src/device/DeviceCommands.ts +4 -14
- package/src/device/DevicePool.ts +6 -2
- package/src/device/DeviceStateMapper.ts +15 -15
- package/src/deviceProfile/buildDeviceFeatures.ts +3 -3
- package/src/events/logBlockEvent.ts +14 -1
- package/src/protocols/protocol-v2/features.ts +22 -5
- package/src/protocols/protocol-v2/index.ts +2 -0
- package/src/protocols/protocol-v2/resources.ts +9 -46
- package/src/types/api/protocolV2.ts +1 -1
- package/src/types/settings.ts +4 -19
- package/src/utils/deviceSettings.ts +1 -1
- 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
|
-
|
|
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 {
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
'
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
24
|
-
|
|
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
|
-
|
|
58
|
-
|
|
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
|
-
|
|
83
|
-
|
|
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
|
-
|
|
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 {
|
|
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
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
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 = {
|
|
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
|
-
|
|
178
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
"
|
|
466
|
-
"
|
|
467
|
-
"
|
|
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
|
-
"
|
|
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
|
-
"
|
|
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
|
-
"
|
|
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
|
-
"
|
|
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
|
},
|