@onekeyfe/hd-core 1.2.0-alpha.102 → 1.2.0-alpha.103
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__/base64Data.test.ts +70 -0
- package/__tests__/deviceUploadNft.test.ts +33 -4
- package/__tests__/protocol-v2.test.ts +75 -16
- package/__tests__/resourceBase64Boundary.test.ts +48 -0
- 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/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/utils.d.ts.map +1 -1
- package/dist/index.d.ts +4 -12
- package/dist/index.js +154 -157
- package/dist/topLevelInject.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/utils/pro2Nft.d.ts +7 -0
- package/dist/utils/pro2Nft.d.ts.map +1 -1
- package/package.json +6 -4
- package/src/api/UploadPortfolio.ts +9 -2
- package/src/api/helpers/base64Data.ts +85 -0
- package/src/api/protocol-v2/DeviceUploadNft.ts +56 -8
- package/src/api/protocol-v2/DeviceUploadWallpaper.ts +37 -18
- package/src/api/utils.ts +2 -5
- package/src/topLevelInject.ts +2 -4
- package/src/types/api/protocolV2.ts +1 -1
- package/src/utils/pro2Nft.ts +31 -8
- package/__tests__/bridgeBinaryPayload.test.ts +0 -173
- package/dist/utils/bridgeBinaryPayload.d.ts +0 -3
- package/dist/utils/bridgeBinaryPayload.d.ts.map +0 -1
- package/src/utils/bridgeBinaryPayload.ts +0 -137
package/dist/index.js
CHANGED
|
@@ -7,13 +7,14 @@ var sha256 = require('@noble/hashes/sha256');
|
|
|
7
7
|
var utils = require('@noble/hashes/utils');
|
|
8
8
|
var semver = require('semver');
|
|
9
9
|
var hdTransport = require('@onekeyfe/hd-transport');
|
|
10
|
-
var buffer = require('buffer');
|
|
11
10
|
var axios = require('axios');
|
|
12
11
|
var lodash = require('lodash');
|
|
13
12
|
var ByteBuffer = require('bytebuffer');
|
|
14
13
|
var blake2s = require('@noble/hashes/blake2s');
|
|
15
14
|
var BigNumber = require('bignumber.js');
|
|
16
15
|
var JSZip = require('jszip');
|
|
16
|
+
var buffer = require('buffer');
|
|
17
|
+
var jpegJs = require('jpeg-js');
|
|
17
18
|
var sha3 = require('@noble/hashes/sha3');
|
|
18
19
|
var blake2b = require('@noble/hashes/blake2b');
|
|
19
20
|
|
|
@@ -2219,132 +2220,14 @@ function eventTargetAgnosticAddListener(emitter, name, listener, flags) {
|
|
|
2219
2220
|
}
|
|
2220
2221
|
}
|
|
2221
2222
|
|
|
2222
|
-
const BRIDGE_BINARY_PAYLOAD_MARKER = '__onekey_hd_bridge_binary_payload__';
|
|
2223
|
-
const BASE64_PATTERN = /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/;
|
|
2224
|
-
const invalidBinaryPayload = (message) => hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.CallMethodInvalidParameter, message);
|
|
2225
|
-
function isPlainObject(value) {
|
|
2226
|
-
if (!value || typeof value !== 'object' || Array.isArray(value))
|
|
2227
|
-
return false;
|
|
2228
|
-
const prototype = Object.getPrototypeOf(value);
|
|
2229
|
-
return prototype === Object.prototype || prototype === null;
|
|
2230
|
-
}
|
|
2231
|
-
function isArrayBufferValue(value) {
|
|
2232
|
-
return Boolean(typeof ArrayBuffer !== 'undefined' &&
|
|
2233
|
-
(value instanceof ArrayBuffer ||
|
|
2234
|
-
Object.prototype.toString.call(value) === '[object ArrayBuffer]'));
|
|
2235
|
-
}
|
|
2236
|
-
function isBlobValue(value) {
|
|
2237
|
-
return Boolean(typeof Blob !== 'undefined' &&
|
|
2238
|
-
(value instanceof Blob || Object.prototype.toString.call(value) === '[object Blob]') &&
|
|
2239
|
-
typeof value.arrayBuffer === 'function');
|
|
2240
|
-
}
|
|
2241
|
-
function readBinaryPayload(value) {
|
|
2242
|
-
if (!isPlainObject(value) || !(BRIDGE_BINARY_PAYLOAD_MARKER in value))
|
|
2243
|
-
return undefined;
|
|
2244
|
-
const payload = value;
|
|
2245
|
-
if (payload[BRIDGE_BINARY_PAYLOAD_MARKER] !== 1 ||
|
|
2246
|
-
(payload.type !== 'array-buffer' && payload.type !== 'uint8-array') ||
|
|
2247
|
-
typeof payload.data !== 'string') {
|
|
2248
|
-
throw invalidBinaryPayload('Invalid bridge binary payload');
|
|
2249
|
-
}
|
|
2250
|
-
return payload;
|
|
2251
|
-
}
|
|
2252
|
-
function bytesToPayload(bytes, type) {
|
|
2253
|
-
return {
|
|
2254
|
-
[BRIDGE_BINARY_PAYLOAD_MARKER]: 1,
|
|
2255
|
-
data: buffer.Buffer.from(bytes.buffer, bytes.byteOffset, bytes.byteLength).toString('base64'),
|
|
2256
|
-
type,
|
|
2257
|
-
};
|
|
2258
|
-
}
|
|
2259
|
-
function payloadToBytes(payload) {
|
|
2260
|
-
if (payload.data.length % 4 !== 0 || !BASE64_PATTERN.test(payload.data)) {
|
|
2261
|
-
throw invalidBinaryPayload('Invalid bridge binary payload data');
|
|
2262
|
-
}
|
|
2263
|
-
const decoded = buffer.Buffer.from(payload.data, 'base64');
|
|
2264
|
-
if (decoded.toString('base64') !== payload.data) {
|
|
2265
|
-
throw invalidBinaryPayload('Invalid bridge binary payload data');
|
|
2266
|
-
}
|
|
2267
|
-
return Uint8Array.from(decoded);
|
|
2268
|
-
}
|
|
2269
|
-
function encodeValue(value, seen) {
|
|
2270
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
2271
|
-
if (isArrayBufferValue(value)) {
|
|
2272
|
-
return bytesToPayload(new Uint8Array(value), 'array-buffer');
|
|
2273
|
-
}
|
|
2274
|
-
if (typeof ArrayBuffer !== 'undefined' && ArrayBuffer.isView(value)) {
|
|
2275
|
-
return bytesToPayload(new Uint8Array(value.buffer, value.byteOffset, value.byteLength), 'uint8-array');
|
|
2276
|
-
}
|
|
2277
|
-
if (isBlobValue(value)) {
|
|
2278
|
-
return bytesToPayload(new Uint8Array(yield value.arrayBuffer()), 'uint8-array');
|
|
2279
|
-
}
|
|
2280
|
-
const encodedPayload = readBinaryPayload(value);
|
|
2281
|
-
if (encodedPayload)
|
|
2282
|
-
return encodedPayload;
|
|
2283
|
-
if (Array.isArray(value)) {
|
|
2284
|
-
if (seen.has(value))
|
|
2285
|
-
throw invalidBinaryPayload('Circular bridge payload');
|
|
2286
|
-
seen.add(value);
|
|
2287
|
-
try {
|
|
2288
|
-
const encoded = [];
|
|
2289
|
-
for (const item of value) {
|
|
2290
|
-
encoded.push(yield encodeValue(item, seen));
|
|
2291
|
-
}
|
|
2292
|
-
return encoded.some((item, index) => item !== value[index]) ? encoded : value;
|
|
2293
|
-
}
|
|
2294
|
-
finally {
|
|
2295
|
-
seen.delete(value);
|
|
2296
|
-
}
|
|
2297
|
-
}
|
|
2298
|
-
if (!isPlainObject(value))
|
|
2299
|
-
return value;
|
|
2300
|
-
if (seen.has(value))
|
|
2301
|
-
throw invalidBinaryPayload('Circular bridge payload');
|
|
2302
|
-
seen.add(value);
|
|
2303
|
-
try {
|
|
2304
|
-
const entries = [];
|
|
2305
|
-
for (const [key, item] of Object.entries(value)) {
|
|
2306
|
-
entries.push([key, yield encodeValue(item, seen)]);
|
|
2307
|
-
}
|
|
2308
|
-
return entries.some(([key, item]) => item !== value[key]) ? Object.fromEntries(entries) : value;
|
|
2309
|
-
}
|
|
2310
|
-
finally {
|
|
2311
|
-
seen.delete(value);
|
|
2312
|
-
}
|
|
2313
|
-
});
|
|
2314
|
-
}
|
|
2315
|
-
function decodeValue(value) {
|
|
2316
|
-
const payload = readBinaryPayload(value);
|
|
2317
|
-
if (payload) {
|
|
2318
|
-
const bytes = payloadToBytes(payload);
|
|
2319
|
-
return payload.type === 'array-buffer' ? bytes.buffer : bytes;
|
|
2320
|
-
}
|
|
2321
|
-
if (Array.isArray(value)) {
|
|
2322
|
-
const decoded = value.map(decodeValue);
|
|
2323
|
-
return decoded.some((item, index) => item !== value[index]) ? decoded : value;
|
|
2324
|
-
}
|
|
2325
|
-
if (!isPlainObject(value))
|
|
2326
|
-
return value;
|
|
2327
|
-
const entries = Object.entries(value).map(([key, item]) => [key, decodeValue(item)]);
|
|
2328
|
-
return entries.some(([key, item]) => item !== value[key]) ? Object.fromEntries(entries) : value;
|
|
2329
|
-
}
|
|
2330
|
-
function encodeBridgeBinaryPayload(value) {
|
|
2331
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
2332
|
-
return encodeValue(value, new WeakSet());
|
|
2333
|
-
});
|
|
2334
|
-
}
|
|
2335
|
-
function decodeBridgeBinaryPayload(value) {
|
|
2336
|
-
return decodeValue(value);
|
|
2337
|
-
}
|
|
2338
|
-
|
|
2339
2223
|
const eventEmitter = new events.exports();
|
|
2340
2224
|
const topLevelInject = () => {
|
|
2341
2225
|
let lowLevelApi;
|
|
2342
|
-
const call = (params) =>
|
|
2226
|
+
const call = (params) => {
|
|
2343
2227
|
if (!lowLevelApi)
|
|
2344
2228
|
return Promise.resolve(undefined);
|
|
2345
|
-
|
|
2346
|
-
|
|
2347
|
-
});
|
|
2229
|
+
return lowLevelApi.call(params);
|
|
2230
|
+
};
|
|
2348
2231
|
const protocolAwareCall = createProtocolAwareCall(call);
|
|
2349
2232
|
const api = Object.assign(Object.assign({ on: (type, fn) => {
|
|
2350
2233
|
eventEmitter.on(type, fn);
|
|
@@ -42841,18 +42724,14 @@ function getCompletePro2NftBasenames(childFiles) {
|
|
|
42841
42724
|
function utf8Length(value) {
|
|
42842
42725
|
return new TextEncoder().encode(value).byteLength;
|
|
42843
42726
|
}
|
|
42844
|
-
function
|
|
42845
|
-
|
|
42846
|
-
|
|
42727
|
+
function buildPro2NftBundleFromEncodedImages(options) {
|
|
42728
|
+
const { image, thumbnail, title, subtitle, timestampMs } = options;
|
|
42729
|
+
if (!(image instanceof Uint8Array) || image.byteLength === 0) {
|
|
42730
|
+
throw invalidParameter$1('Parameter [image] must contain encoded NFT image data.');
|
|
42847
42731
|
}
|
|
42848
|
-
if (!(
|
|
42849
|
-
throw invalidParameter$1(
|
|
42732
|
+
if (!(thumbnail instanceof Uint8Array) || thumbnail.byteLength === 0) {
|
|
42733
|
+
throw invalidParameter$1('Parameter [thumbnail] must contain encoded NFT thumbnail data.');
|
|
42850
42734
|
}
|
|
42851
|
-
}
|
|
42852
|
-
function buildPro2NftBundle(options) {
|
|
42853
|
-
const { image, thumbnail, title, subtitle, timestampMs } = options;
|
|
42854
|
-
assertImage('image', image, PRO2_NFT_IMAGE_WIDTH, PRO2_NFT_IMAGE_HEIGHT);
|
|
42855
|
-
assertImage('thumbnail', thumbnail, PRO2_NFT_THUMBNAIL_WIDTH, PRO2_NFT_THUMBNAIL_HEIGHT);
|
|
42856
42735
|
const titleLength = typeof title === 'string' ? utf8Length(title) : 0;
|
|
42857
42736
|
const subtitleLength = typeof subtitle === 'string' ? utf8Length(subtitle) : Number.POSITIVE_INFINITY;
|
|
42858
42737
|
if (titleLength < 1 || titleLength > 63) {
|
|
@@ -42864,17 +42743,15 @@ function buildPro2NftBundle(options) {
|
|
|
42864
42743
|
if (!Number.isSafeInteger(timestampMs) || timestampMs <= 0) {
|
|
42865
42744
|
throw invalidParameter$1('Parameter [timestampMs] must be a positive safe integer.');
|
|
42866
42745
|
}
|
|
42867
|
-
const encodedImage = encodePro2Image(Object.assign(Object.assign({}, image), { alphaMode: 'black-background' })).data;
|
|
42868
|
-
const encodedThumbnail = encodePro2Image(Object.assign(Object.assign({}, thumbnail), { alphaMode: 'black-background' })).data;
|
|
42869
42746
|
const metadata = new TextEncoder().encode(JSON.stringify({ title, subtitle }));
|
|
42870
42747
|
if (metadata.byteLength === 0 || metadata.byteLength > 512) {
|
|
42871
42748
|
throw invalidParameter$1('Pro2 NFT metadata must contain 1 to 512 UTF-8 bytes.');
|
|
42872
42749
|
}
|
|
42873
|
-
const hash8 = utils.bytesToHex(blake2s.blake2s(
|
|
42750
|
+
const hash8 = utils.bytesToHex(blake2s.blake2s(image)).slice(0, 8);
|
|
42874
42751
|
return {
|
|
42875
42752
|
basename: `nft-${hash8}-${timestampMs}`,
|
|
42876
|
-
image
|
|
42877
|
-
thumbnail
|
|
42753
|
+
image,
|
|
42754
|
+
thumbnail,
|
|
42878
42755
|
metadata,
|
|
42879
42756
|
};
|
|
42880
42757
|
}
|
|
@@ -54094,6 +53971,61 @@ class DeviceGetOnboardingStatus extends BaseMethod {
|
|
|
54094
53971
|
}
|
|
54095
53972
|
}
|
|
54096
53973
|
|
|
53974
|
+
const BASE64_PATTERN = /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/;
|
|
53975
|
+
const JPEG_CONTAINER_OVERHEAD_BYTES = 64 * 1024;
|
|
53976
|
+
const JPEG_MAX_MEMORY_USAGE_IN_MB = 32;
|
|
53977
|
+
const JPEG_MAX_RESOLUTION_IN_MP = 1;
|
|
53978
|
+
function decodeCanonicalBase64({ value, parameterName, maxBytes, }) {
|
|
53979
|
+
if (typeof value !== 'string' || value.length === 0) {
|
|
53980
|
+
throw invalidParameter$1(`Parameter [${parameterName}] must be a non-empty Base64 string.`);
|
|
53981
|
+
}
|
|
53982
|
+
if (value.length > Math.ceil(maxBytes / 3) * 4) {
|
|
53983
|
+
throw invalidParameter$1(`Parameter [${parameterName}] exceeds the maximum supported size.`);
|
|
53984
|
+
}
|
|
53985
|
+
if (value.length % 4 !== 0 || !BASE64_PATTERN.test(value)) {
|
|
53986
|
+
throw invalidParameter$1(`Parameter [${parameterName}] must use canonical Base64 encoding.`);
|
|
53987
|
+
}
|
|
53988
|
+
const decoded = buffer.Buffer.from(value, 'base64');
|
|
53989
|
+
if (decoded.byteLength === 0 || decoded.byteLength > maxBytes) {
|
|
53990
|
+
throw invalidParameter$1(`Parameter [${parameterName}] exceeds the maximum supported size.`);
|
|
53991
|
+
}
|
|
53992
|
+
if (decoded.toString('base64') !== value) {
|
|
53993
|
+
throw invalidParameter$1(`Parameter [${parameterName}] must use canonical Base64 encoding.`);
|
|
53994
|
+
}
|
|
53995
|
+
return Uint8Array.from(decoded);
|
|
53996
|
+
}
|
|
53997
|
+
function decodeJpegBase64ToRgba({ jpegBase64, parameterName, expectedWidth, expectedHeight, }) {
|
|
53998
|
+
const jpegBytes = decodeCanonicalBase64({
|
|
53999
|
+
value: jpegBase64,
|
|
54000
|
+
parameterName,
|
|
54001
|
+
maxBytes: expectedWidth * expectedHeight * 8 + JPEG_CONTAINER_OVERHEAD_BYTES,
|
|
54002
|
+
});
|
|
54003
|
+
if (jpegBytes[0] !== 0xff || jpegBytes[1] !== 0xd8) {
|
|
54004
|
+
throw invalidParameter$1(`Parameter [${parameterName}] must contain a JPEG image.`);
|
|
54005
|
+
}
|
|
54006
|
+
let decoded;
|
|
54007
|
+
try {
|
|
54008
|
+
decoded = jpegJs.decode(jpegBytes, {
|
|
54009
|
+
useTArray: true,
|
|
54010
|
+
formatAsRGBA: true,
|
|
54011
|
+
tolerantDecoding: false,
|
|
54012
|
+
maxResolutionInMP: JPEG_MAX_RESOLUTION_IN_MP,
|
|
54013
|
+
maxMemoryUsageInMB: JPEG_MAX_MEMORY_USAGE_IN_MB,
|
|
54014
|
+
});
|
|
54015
|
+
}
|
|
54016
|
+
catch (_a) {
|
|
54017
|
+
throw invalidParameter$1(`Parameter [${parameterName}] must contain a valid JPEG image.`);
|
|
54018
|
+
}
|
|
54019
|
+
if (decoded.width !== expectedWidth || decoded.height !== expectedHeight) {
|
|
54020
|
+
throw invalidParameter$1(`Parameter [${parameterName}] must contain a ${expectedWidth}x${expectedHeight} JPEG image.`);
|
|
54021
|
+
}
|
|
54022
|
+
const expectedLength = expectedWidth * expectedHeight * 4;
|
|
54023
|
+
if (decoded.data.byteLength !== expectedLength) {
|
|
54024
|
+
throw invalidParameter$1(`Decoded parameter [${parameterName}] must contain ${expectedLength} RGBA bytes.`);
|
|
54025
|
+
}
|
|
54026
|
+
return decoded;
|
|
54027
|
+
}
|
|
54028
|
+
|
|
54097
54029
|
const Log$4 = getLogger(exports.LoggerNames.Core);
|
|
54098
54030
|
const MIN_FILE_CHUNK_SIZE = 64;
|
|
54099
54031
|
const FILE_TRANSFER_RATE_WINDOW_MS = 1000;
|
|
@@ -54370,6 +54302,9 @@ function writeProtocolV2File(options) {
|
|
|
54370
54302
|
|
|
54371
54303
|
const WALLPAPER_DIRECTORY = 'vol1:/wallpapers';
|
|
54372
54304
|
const SAFE_FILE_NAME = /^[A-Za-z0-9_-]+(?:\.bin)?$/;
|
|
54305
|
+
const DEVICE_SETTINGS_SET_MESSAGE_TYPE = 60412;
|
|
54306
|
+
const FILESYSTEM_FILE_WRITE_MESSAGE_TYPE$2 = 60805;
|
|
54307
|
+
const FILESYSTEM_DIR_MAKE_MESSAGE_TYPE = 60809;
|
|
54373
54308
|
function normalizeFileName(fileName, data) {
|
|
54374
54309
|
if (fileName !== undefined && (!fileName || !SAFE_FILE_NAME.test(fileName))) {
|
|
54375
54310
|
throw invalidParameter$1('Parameter [fileName] may only contain letters, numbers, underscores, hyphens and an optional .bin suffix.');
|
|
@@ -54388,26 +54323,40 @@ class DeviceUploadWallpaper extends BaseMethod {
|
|
|
54388
54323
|
return ['V2'];
|
|
54389
54324
|
}
|
|
54390
54325
|
init() {
|
|
54391
|
-
const {
|
|
54392
|
-
if (width !== PRO2_WALLPAPER_WIDTH || height !== PRO2_WALLPAPER_HEIGHT) {
|
|
54393
|
-
throw invalidParameter$1(`Pro2 wallpaper dimensions must be ${PRO2_WALLPAPER_WIDTH}x${PRO2_WALLPAPER_HEIGHT}.`);
|
|
54394
|
-
}
|
|
54395
|
-
if (!(rgba instanceof ArrayBuffer) && !ArrayBuffer.isView(rgba)) {
|
|
54396
|
-
throw invalidParameter$1('Parameter [rgba] must be an ArrayBuffer or Uint8Array.');
|
|
54397
|
-
}
|
|
54326
|
+
const { jpegBase64, fileName, chunkSize } = this.payload;
|
|
54398
54327
|
if (chunkSize !== undefined && (!Number.isInteger(chunkSize) || chunkSize <= 0)) {
|
|
54399
54328
|
throw invalidParameter$1('Parameter [chunkSize] must be a positive integer.');
|
|
54400
54329
|
}
|
|
54401
|
-
const
|
|
54402
|
-
|
|
54403
|
-
:
|
|
54404
|
-
|
|
54330
|
+
const decoded = decodeJpegBase64ToRgba({
|
|
54331
|
+
jpegBase64,
|
|
54332
|
+
parameterName: 'jpegBase64',
|
|
54333
|
+
expectedWidth: PRO2_WALLPAPER_WIDTH,
|
|
54334
|
+
expectedHeight: PRO2_WALLPAPER_HEIGHT,
|
|
54335
|
+
});
|
|
54336
|
+
this.encoded = encodePro2Wallpaper({
|
|
54337
|
+
width: PRO2_WALLPAPER_WIDTH,
|
|
54338
|
+
height: PRO2_WALLPAPER_HEIGHT,
|
|
54339
|
+
rgba: decoded.data,
|
|
54340
|
+
});
|
|
54405
54341
|
this.path = `${WALLPAPER_DIRECTORY}/${normalizeFileName(fileName, this.encoded.data)}`;
|
|
54406
|
-
this.params = {
|
|
54342
|
+
this.params = { jpegBase64, fileName, chunkSize };
|
|
54407
54343
|
this.unlockPolicy = 'none';
|
|
54408
54344
|
this.skipForceUpdateCheck = true;
|
|
54409
54345
|
this.useDevicePassphraseState = false;
|
|
54410
54346
|
}
|
|
54347
|
+
assertCapabilities() {
|
|
54348
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
54349
|
+
const protocolInfo = yield this.device.ensureProtocolV2RuntimeContext();
|
|
54350
|
+
const requiredMessageTypes = [
|
|
54351
|
+
DEVICE_SETTINGS_SET_MESSAGE_TYPE,
|
|
54352
|
+
FILESYSTEM_FILE_WRITE_MESSAGE_TYPE$2,
|
|
54353
|
+
FILESYSTEM_DIR_MAKE_MESSAGE_TYPE,
|
|
54354
|
+
];
|
|
54355
|
+
if (requiredMessageTypes.some(messageType => !supportsProtocolV2Message(protocolInfo, messageType))) {
|
|
54356
|
+
throw hdShared.createDeviceNotSupportMethodError(this.name, this.device.getCurrentFirmwareType());
|
|
54357
|
+
}
|
|
54358
|
+
});
|
|
54359
|
+
}
|
|
54411
54360
|
ensureDirectory() {
|
|
54412
54361
|
return __awaiter(this, void 0, void 0, function* () {
|
|
54413
54362
|
if (this.directoryReady)
|
|
@@ -54457,6 +54406,7 @@ class DeviceUploadWallpaper extends BaseMethod {
|
|
|
54457
54406
|
const { encoded } = this;
|
|
54458
54407
|
if (!encoded)
|
|
54459
54408
|
throw invalidParameter$1('Wallpaper data has not been initialized.');
|
|
54409
|
+
yield this.assertCapabilities();
|
|
54460
54410
|
yield this.ensureDirectory();
|
|
54461
54411
|
yield this.upload();
|
|
54462
54412
|
const response = yield this.device.commands.typedCall('DeviceSettingsSet', 'Success', {
|
|
@@ -54481,7 +54431,7 @@ class DeviceUploadNft extends BaseMethod {
|
|
|
54481
54431
|
return ['V2'];
|
|
54482
54432
|
}
|
|
54483
54433
|
init() {
|
|
54484
|
-
const {
|
|
54434
|
+
const { imageJpegBase64, thumbnailJpegBase64, title, subtitle, timestampMs = Date.now(), chunkSize = PRO2_NFT_DEFAULT_CHUNK_SIZE, paceMs = PRO2_NFT_DEFAULT_PACE_MS, timeoutMs = PRO2_NFT_DEFAULT_TIMEOUT_MS, } = this.payload;
|
|
54485
54435
|
if (!Number.isInteger(chunkSize) ||
|
|
54486
54436
|
chunkSize < PRO2_NFT_MIN_CHUNK_SIZE ||
|
|
54487
54437
|
chunkSize > PRO2_NFT_MAX_CHUNK_SIZE) {
|
|
@@ -54493,8 +54443,51 @@ class DeviceUploadNft extends BaseMethod {
|
|
|
54493
54443
|
if (!Number.isInteger(timeoutMs) || timeoutMs <= 0) {
|
|
54494
54444
|
throw invalidParameter$1('Parameter [timeoutMs] must be a positive integer.');
|
|
54495
54445
|
}
|
|
54496
|
-
|
|
54497
|
-
|
|
54446
|
+
const encodedImage = (() => {
|
|
54447
|
+
const decoded = decodeJpegBase64ToRgba({
|
|
54448
|
+
jpegBase64: imageJpegBase64,
|
|
54449
|
+
parameterName: 'imageJpegBase64',
|
|
54450
|
+
expectedWidth: PRO2_NFT_IMAGE_WIDTH,
|
|
54451
|
+
expectedHeight: PRO2_NFT_IMAGE_HEIGHT,
|
|
54452
|
+
});
|
|
54453
|
+
return encodePro2Image({
|
|
54454
|
+
width: PRO2_NFT_IMAGE_WIDTH,
|
|
54455
|
+
height: PRO2_NFT_IMAGE_HEIGHT,
|
|
54456
|
+
rgba: decoded.data,
|
|
54457
|
+
alphaMode: 'black-background',
|
|
54458
|
+
}).data;
|
|
54459
|
+
})();
|
|
54460
|
+
const encodedThumbnail = (() => {
|
|
54461
|
+
const decoded = decodeJpegBase64ToRgba({
|
|
54462
|
+
jpegBase64: thumbnailJpegBase64,
|
|
54463
|
+
parameterName: 'thumbnailJpegBase64',
|
|
54464
|
+
expectedWidth: PRO2_NFT_THUMBNAIL_WIDTH,
|
|
54465
|
+
expectedHeight: PRO2_NFT_THUMBNAIL_HEIGHT,
|
|
54466
|
+
});
|
|
54467
|
+
return encodePro2Image({
|
|
54468
|
+
width: PRO2_NFT_THUMBNAIL_WIDTH,
|
|
54469
|
+
height: PRO2_NFT_THUMBNAIL_HEIGHT,
|
|
54470
|
+
rgba: decoded.data,
|
|
54471
|
+
alphaMode: 'black-background',
|
|
54472
|
+
}).data;
|
|
54473
|
+
})();
|
|
54474
|
+
this.bundle = buildPro2NftBundleFromEncodedImages({
|
|
54475
|
+
image: encodedImage,
|
|
54476
|
+
thumbnail: encodedThumbnail,
|
|
54477
|
+
title,
|
|
54478
|
+
subtitle,
|
|
54479
|
+
timestampMs,
|
|
54480
|
+
});
|
|
54481
|
+
this.params = {
|
|
54482
|
+
imageJpegBase64,
|
|
54483
|
+
thumbnailJpegBase64,
|
|
54484
|
+
title,
|
|
54485
|
+
subtitle,
|
|
54486
|
+
timestampMs,
|
|
54487
|
+
chunkSize,
|
|
54488
|
+
paceMs,
|
|
54489
|
+
timeoutMs,
|
|
54490
|
+
};
|
|
54498
54491
|
this.unlockPolicy = 'none';
|
|
54499
54492
|
this.skipForceUpdateCheck = true;
|
|
54500
54493
|
this.useDevicePassphraseState = false;
|
|
@@ -54637,11 +54630,17 @@ class FileWrite extends BaseMethod {
|
|
|
54637
54630
|
|
|
54638
54631
|
const PORTFOLIO_PENDING_PATH = 'vol1:/portfolio/portfolio.okpkg.pending';
|
|
54639
54632
|
const PORTFOLIO_CHUNK_SIZE = 2048;
|
|
54633
|
+
const PORTFOLIO_PACKAGE_MAX_BYTES = 128 * 1024;
|
|
54640
54634
|
const FILESYSTEM_FILE_WRITE_MESSAGE_TYPE = 60805;
|
|
54641
54635
|
const PORTFOLIO_UPDATE_MESSAGE_TYPE = 61400;
|
|
54642
54636
|
class UploadPortfolio extends FileWrite {
|
|
54643
54637
|
init() {
|
|
54644
|
-
const {
|
|
54638
|
+
const { packageBase64, timeoutMs } = this.payload;
|
|
54639
|
+
const packageBytes = decodeCanonicalBase64({
|
|
54640
|
+
value: packageBase64,
|
|
54641
|
+
parameterName: 'packageBase64',
|
|
54642
|
+
maxBytes: PORTFOLIO_PACKAGE_MAX_BYTES,
|
|
54643
|
+
});
|
|
54645
54644
|
this.payload = Object.assign(Object.assign({}, this.payload), { path: PORTFOLIO_PENDING_PATH, offset: 0, data: packageBytes, chunkSize: PORTFOLIO_CHUNK_SIZE, overwrite: true, append: false, emitProgress: false, timeoutMs });
|
|
54646
54645
|
super.init();
|
|
54647
54646
|
this.unlockPolicy = 'none';
|
|
@@ -64541,15 +64540,13 @@ var ApiMethods = /*#__PURE__*/Object.freeze({
|
|
|
64541
64540
|
|
|
64542
64541
|
const publicMethodRegistry = ApiMethods;
|
|
64543
64542
|
function findMethod(message) {
|
|
64544
|
-
const
|
|
64545
|
-
const normalizedMessage = payload === message.payload ? message : Object.assign(Object.assign({}, message), { payload });
|
|
64546
|
-
const { method } = payload;
|
|
64543
|
+
const { method } = message.payload;
|
|
64547
64544
|
if (typeof method !== 'string') {
|
|
64548
64545
|
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.CallMethodInvalidParameter, 'Method is not set');
|
|
64549
64546
|
}
|
|
64550
64547
|
const MethodConstructor = publicMethodRegistry[method];
|
|
64551
64548
|
if (MethodConstructor) {
|
|
64552
|
-
return new MethodConstructor(
|
|
64549
|
+
return new MethodConstructor(message);
|
|
64553
64550
|
}
|
|
64554
64551
|
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.CallMethodInvalidParameter, `Method ${method} is not set`);
|
|
64555
64552
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"topLevelInject.d.ts","sourceRoot":"","sources":["../src/topLevelInject.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"topLevelInject.d.ts","sourceRoot":"","sources":["../src/topLevelInject.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAG3C,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;IACtB,IAAI,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;CACvB;AAID,eAAO,MAAM,cAAc,eAoD1B,CAAC"}
|
|
@@ -24,7 +24,7 @@ export declare function deviceGetOnboardingStatus(connectId: string, params?: Co
|
|
|
24
24
|
export declare function deviceUploadWallpaper(connectId: string, params: CommonParams & DeviceUploadWallpaperParams): Response<DeviceUploadWallpaperResponse>;
|
|
25
25
|
export declare function deviceUploadNft(connectId: string, params: CommonParams & DeviceUploadNftParams): Response<DeviceUploadNftResponse>;
|
|
26
26
|
export declare function uploadPortfolio(connectId: string, params: {
|
|
27
|
-
|
|
27
|
+
packageBase64: string;
|
|
28
28
|
timeoutMs?: number | string;
|
|
29
29
|
}): Response<FileInfo & {
|
|
30
30
|
portfolioUpdated: true;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"protocolV2.d.ts","sourceRoot":"","sources":["../../../src/types/api/protocolV2.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AACxD,OAAO,KAAK,EAAE,gBAAgB,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AACxE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AACxE,OAAO,KAAK,EACV,2BAA2B,EAC3B,6BAA6B,EAC9B,MAAM,6CAA6C,CAAC;AACrD,OAAO,KAAK,EACV,qBAAqB,EACrB,uBAAuB,EACxB,MAAM,uCAAuC,CAAC;AAG/C,YAAY,EAAE,kBAAkB,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AACzF,YAAY,EACV,2BAA2B,EAC3B,6BAA6B,GAC9B,MAAM,6CAA6C,CAAC;AACrD,YAAY,EACV,qBAAqB,EACrB,uBAAuB,GACxB,MAAM,uCAAuC,CAAC;AAI/C,MAAM,MAAM,QAAQ,GAAG;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAIF,MAAM,MAAM,wBAAwB,GAAG,YAAY,GAAG;IAEpD,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,MAAM,CAAC,OAAO,UAAU,kBAAkB,CACxC,SAAS,EAAE,MAAM,EACjB,MAAM,CAAC,EAAE,wBAAwB,GAChC,QAAQ,CAAC,OAAO,CAAC,CAAC;AAErB,MAAM,CAAC,OAAO,UAAU,YAAY,CAClC,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,YAAY,GAAG,kBAAkB,GACxC,QAAQ,CAAC,OAAO,CAAC,CAAC;AAErB,MAAM,CAAC,OAAO,UAAU,yBAAyB,CAC/C,SAAS,EAAE,MAAM,EACjB,MAAM,CAAC,EAAE,YAAY,GACpB,QAAQ,CAAC,gBAAgB,CAAC,CAAC;AAE9B,MAAM,CAAC,OAAO,UAAU,qBAAqB,CAC3C,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,YAAY,GAAG,2BAA2B,GACjD,QAAQ,CAAC,6BAA6B,CAAC,CAAC;AAE3C,MAAM,CAAC,OAAO,UAAU,eAAe,CACrC,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,YAAY,GAAG,qBAAqB,GAC3C,QAAQ,CAAC,uBAAuB,CAAC,CAAC;AAErC,MAAM,CAAC,OAAO,UAAU,eAAe,CACrC,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE;IACN,
|
|
1
|
+
{"version":3,"file":"protocolV2.d.ts","sourceRoot":"","sources":["../../../src/types/api/protocolV2.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AACxD,OAAO,KAAK,EAAE,gBAAgB,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AACxE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AACxE,OAAO,KAAK,EACV,2BAA2B,EAC3B,6BAA6B,EAC9B,MAAM,6CAA6C,CAAC;AACrD,OAAO,KAAK,EACV,qBAAqB,EACrB,uBAAuB,EACxB,MAAM,uCAAuC,CAAC;AAG/C,YAAY,EAAE,kBAAkB,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AACzF,YAAY,EACV,2BAA2B,EAC3B,6BAA6B,GAC9B,MAAM,6CAA6C,CAAC;AACrD,YAAY,EACV,qBAAqB,EACrB,uBAAuB,GACxB,MAAM,uCAAuC,CAAC;AAI/C,MAAM,MAAM,QAAQ,GAAG;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAIF,MAAM,MAAM,wBAAwB,GAAG,YAAY,GAAG;IAEpD,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,MAAM,CAAC,OAAO,UAAU,kBAAkB,CACxC,SAAS,EAAE,MAAM,EACjB,MAAM,CAAC,EAAE,wBAAwB,GAChC,QAAQ,CAAC,OAAO,CAAC,CAAC;AAErB,MAAM,CAAC,OAAO,UAAU,YAAY,CAClC,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,YAAY,GAAG,kBAAkB,GACxC,QAAQ,CAAC,OAAO,CAAC,CAAC;AAErB,MAAM,CAAC,OAAO,UAAU,yBAAyB,CAC/C,SAAS,EAAE,MAAM,EACjB,MAAM,CAAC,EAAE,YAAY,GACpB,QAAQ,CAAC,gBAAgB,CAAC,CAAC;AAE9B,MAAM,CAAC,OAAO,UAAU,qBAAqB,CAC3C,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,YAAY,GAAG,2BAA2B,GACjD,QAAQ,CAAC,6BAA6B,CAAC,CAAC;AAE3C,MAAM,CAAC,OAAO,UAAU,eAAe,CACrC,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,YAAY,GAAG,qBAAqB,GAC3C,QAAQ,CAAC,uBAAuB,CAAC,CAAC;AAErC,MAAM,CAAC,OAAO,UAAU,eAAe,CACrC,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE;IACN,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;CAC7B,GACA,QAAQ,CAAC,QAAQ,GAAG;IAAE,gBAAgB,EAAE,IAAI,CAAA;CAAE,CAAC,CAAC"}
|
package/dist/utils/pro2Nft.d.ts
CHANGED
|
@@ -28,4 +28,11 @@ export declare function buildPro2NftBundle(options: {
|
|
|
28
28
|
subtitle: string;
|
|
29
29
|
timestampMs: number;
|
|
30
30
|
}): Pro2NftBundle;
|
|
31
|
+
export declare function buildPro2NftBundleFromEncodedImages(options: {
|
|
32
|
+
image: Uint8Array;
|
|
33
|
+
thumbnail: Uint8Array;
|
|
34
|
+
title: string;
|
|
35
|
+
subtitle: string;
|
|
36
|
+
timestampMs: number;
|
|
37
|
+
}): Pro2NftBundle;
|
|
31
38
|
//# sourceMappingURL=pro2Nft.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pro2Nft.d.ts","sourceRoot":"","sources":["../../src/utils/pro2Nft.ts"],"names":[],"mappings":"AAMA,eAAO,MAAM,oBAAoB,MAAM,CAAC;AACxC,eAAO,MAAM,qBAAqB,MAAM,CAAC;AACzC,eAAO,MAAM,wBAAwB,MAAM,CAAC;AAC5C,eAAO,MAAM,yBAAyB,MAAM,CAAC;AAC7C,eAAO,MAAM,kBAAkB,cAAc,CAAC;AAC9C,eAAO,MAAM,2BAA2B,OAAO,CAAC;AAChD,eAAO,MAAM,wBAAwB,IAAI,CAAC;AAC1C,eAAO,MAAM,2BAA2B,QAAS,CAAC;AAClD,eAAO,MAAM,uBAAuB,KAAK,CAAC;AAC1C,eAAO,MAAM,uBAAuB,OAAO,CAAC;AAC5C,eAAO,MAAM,kBAAkB,KAAK,CAAC;AAErC,MAAM,MAAM,YAAY,GAAG;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,UAAU,GAAG,WAAW,CAAC;CAChC,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,UAAU,CAAC;IAClB,SAAS,EAAE,UAAU,CAAC;IACtB,QAAQ,EAAE,UAAU,CAAC;CACtB,CAAC;AAiCF,wBAAgB,2BAA2B,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,CAiB5E;AAsBD,wBAAgB,kBAAkB,CAAC,OAAO,EAAE;IAC1C,KAAK,EAAE,YAAY,CAAC;IACpB,SAAS,EAAE,YAAY,CAAC;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;CACrB,GAAG,aAAa,
|
|
1
|
+
{"version":3,"file":"pro2Nft.d.ts","sourceRoot":"","sources":["../../src/utils/pro2Nft.ts"],"names":[],"mappings":"AAMA,eAAO,MAAM,oBAAoB,MAAM,CAAC;AACxC,eAAO,MAAM,qBAAqB,MAAM,CAAC;AACzC,eAAO,MAAM,wBAAwB,MAAM,CAAC;AAC5C,eAAO,MAAM,yBAAyB,MAAM,CAAC;AAC7C,eAAO,MAAM,kBAAkB,cAAc,CAAC;AAC9C,eAAO,MAAM,2BAA2B,OAAO,CAAC;AAChD,eAAO,MAAM,wBAAwB,IAAI,CAAC;AAC1C,eAAO,MAAM,2BAA2B,QAAS,CAAC;AAClD,eAAO,MAAM,uBAAuB,KAAK,CAAC;AAC1C,eAAO,MAAM,uBAAuB,OAAO,CAAC;AAC5C,eAAO,MAAM,kBAAkB,KAAK,CAAC;AAErC,MAAM,MAAM,YAAY,GAAG;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,UAAU,GAAG,WAAW,CAAC;CAChC,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,UAAU,CAAC;IAClB,SAAS,EAAE,UAAU,CAAC;IACtB,QAAQ,EAAE,UAAU,CAAC;CACtB,CAAC;AAiCF,wBAAgB,2BAA2B,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,CAiB5E;AAsBD,wBAAgB,kBAAkB,CAAC,OAAO,EAAE;IAC1C,KAAK,EAAE,YAAY,CAAC;IACpB,SAAS,EAAE,YAAY,CAAC;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;CACrB,GAAG,aAAa,CAgBhB;AAED,wBAAgB,mCAAmC,CAAC,OAAO,EAAE;IAC3D,KAAK,EAAE,UAAU,CAAC;IAClB,SAAS,EAAE,UAAU,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;CACrB,GAAG,aAAa,CAiChB"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@onekeyfe/hd-core",
|
|
3
|
-
"version": "1.2.0-alpha.
|
|
3
|
+
"version": "1.2.0-alpha.103",
|
|
4
4
|
"description": "Core processes and APIs for communicating with OneKey hardware devices.",
|
|
5
5
|
"author": "OneKey",
|
|
6
6
|
"homepage": "https://github.com/OneKeyHQ/hardware-js-sdk#readme",
|
|
@@ -25,11 +25,13 @@
|
|
|
25
25
|
"url": "https://github.com/OneKeyHQ/hardware-js-sdk/issues"
|
|
26
26
|
},
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"@onekeyfe/hd-shared": "1.2.0-alpha.
|
|
29
|
-
"@onekeyfe/hd-transport": "1.2.0-alpha.
|
|
28
|
+
"@onekeyfe/hd-shared": "1.2.0-alpha.103",
|
|
29
|
+
"@onekeyfe/hd-transport": "1.2.0-alpha.103",
|
|
30
30
|
"axios": "1.15.2",
|
|
31
31
|
"bignumber.js": "^9.0.2",
|
|
32
|
+
"buffer": "^6.0.3",
|
|
32
33
|
"bytebuffer": "^5.0.1",
|
|
34
|
+
"jpeg-js": "^0.4.4",
|
|
33
35
|
"jszip": "^3.10.1",
|
|
34
36
|
"parse-uri": "^1.0.7",
|
|
35
37
|
"semver": "^7.3.7"
|
|
@@ -44,5 +46,5 @@
|
|
|
44
46
|
"@types/w3c-web-usb": "^1.0.10",
|
|
45
47
|
"@types/web-bluetooth": "^0.0.21"
|
|
46
48
|
},
|
|
47
|
-
"gitHead": "
|
|
49
|
+
"gitHead": "ba7c3866269200b25a514202b8286d0c9e9105d3"
|
|
48
50
|
}
|
|
@@ -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
|
+
}
|