@onekeyfe/hd-core 1.2.0-alpha.146 → 1.2.0-alpha.147
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__/device-lifecycle-events.test.ts +1 -23
- package/__tests__/device-utils.test.ts +0 -8
- package/__tests__/deviceUploadNft.test.ts +0 -3
- package/__tests__/protocol-v2-resources.test.ts +89 -35
- package/__tests__/protocol-v2-unlock-policy.test.ts +0 -35
- package/__tests__/protocol-v2.test.ts +188 -49
- package/dist/api/FirmwareUpdateV4.d.ts.map +1 -1
- package/dist/api/protocol-v2/DeviceUploadNft.d.ts.map +1 -1
- package/dist/api/protocol-v2/DeviceUploadWallpaper.d.ts.map +1 -1
- package/dist/core/index.d.ts +0 -1
- package/dist/core/index.d.ts.map +1 -1
- package/dist/index.d.ts +20 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +298 -133
- package/dist/protocols/protocol-v2/resources.d.ts +7 -11
- package/dist/protocols/protocol-v2/resources.d.ts.map +1 -1
- package/dist/types/settings.d.ts +13 -0
- package/dist/types/settings.d.ts.map +1 -1
- package/dist/utils/deviceInfoUtils.d.ts.map +1 -1
- package/package.json +4 -4
- package/src/api/FirmwareUpdateV4.ts +238 -61
- package/src/api/PromptWebDeviceAccess.ts +2 -2
- package/src/api/protocol-v2/DeviceUploadNft.ts +1 -5
- package/src/api/protocol-v2/DeviceUploadWallpaper.ts +1 -5
- package/src/core/index.ts +99 -11
- package/src/index.ts +4 -0
- package/src/protocols/protocol-v2/resources.ts +102 -92
- package/src/types/settings.ts +15 -0
- package/src/utils/deviceInfoUtils.ts +2 -7
|
@@ -1,12 +1,7 @@
|
|
|
1
1
|
import { EDeviceType, ERRORS, HardwareErrorCode, createDeferred } from '@onekeyfe/hd-shared';
|
|
2
2
|
import { DeviceType, TRANSPORT_EVENT } from '@onekeyfe/hd-transport';
|
|
3
3
|
|
|
4
|
-
import {
|
|
5
|
-
initConnector,
|
|
6
|
-
initCore,
|
|
7
|
-
isMissingDetectedProtocolV2Error,
|
|
8
|
-
isRetryableBleProtocolV2ProbeError,
|
|
9
|
-
} from '../src/core';
|
|
4
|
+
import { initConnector, initCore, isMissingDetectedProtocolV2Error } from '../src/core';
|
|
10
5
|
import { DataManager } from '../src/data-manager';
|
|
11
6
|
import TransportManager from '../src/data-manager/TransportManager';
|
|
12
7
|
import { Device } from '../src/device/Device';
|
|
@@ -274,23 +269,6 @@ describe('public device lifecycle events', () => {
|
|
|
274
269
|
}
|
|
275
270
|
);
|
|
276
271
|
|
|
277
|
-
test.each([
|
|
278
|
-
[HardwareErrorCode.RuntimeError, true],
|
|
279
|
-
[HardwareErrorCode.BleDeviceBondError, false],
|
|
280
|
-
] as const)(
|
|
281
|
-
'retries a Protocol V2 probe mismatch with error code %s: %s',
|
|
282
|
-
(errorCode, expected) => {
|
|
283
|
-
const method = { payload: { connectProtocol: 'V2' } } as never;
|
|
284
|
-
const error = {
|
|
285
|
-
errorCode,
|
|
286
|
-
message:
|
|
287
|
-
'Device protocol mismatch: expected V2, but device did not respond to expected protocol',
|
|
288
|
-
};
|
|
289
|
-
|
|
290
|
-
expect(isRetryableBleProtocolV2ProbeError(method, error)).toBe(expected);
|
|
291
|
-
}
|
|
292
|
-
);
|
|
293
|
-
|
|
294
272
|
test('converts an internal transport disconnect into a public KnownDevice snapshot', () => {
|
|
295
273
|
jest.spyOn(DataManager, 'getSettings').mockReturnValue('react-native' as never);
|
|
296
274
|
core = initCore();
|
|
@@ -123,14 +123,6 @@ describe('device feature selectors', () => {
|
|
|
123
123
|
test('recognizes Neo discovery names before initialization', () => {
|
|
124
124
|
expect(getDeviceTypeByBleName('OneKey Neo 1234')).toBe(EDeviceType.Neo);
|
|
125
125
|
expect(getDeviceTypeByBleName('Neo 1234')).toBe(EDeviceType.Neo);
|
|
126
|
-
expect(getDeviceTypeByBleName('Neo22D8')).toBe(EDeviceType.Neo);
|
|
127
|
-
expect(getDeviceTypeByBleName('OneKeyNeo22D8')).toBe(EDeviceType.Neo);
|
|
128
|
-
});
|
|
129
|
-
|
|
130
|
-
test('recognizes compact Pro2 discovery names before initialization', () => {
|
|
131
|
-
expect(getDeviceTypeByBleName('Pro2 A1B2')).toBe(EDeviceType.Pro2);
|
|
132
|
-
expect(getDeviceTypeByBleName('Pro2A1B2')).toBe(EDeviceType.Pro2);
|
|
133
|
-
expect(getDeviceTypeByBleName('OneKeyPro2A1B2')).toBe(EDeviceType.Pro2);
|
|
134
126
|
});
|
|
135
127
|
|
|
136
128
|
test.each([EDeviceType.Pro2, EDeviceType.Neo])(
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { HardwareErrorCode } from '@onekeyfe/hd-shared';
|
|
2
|
-
import { DeviceSessionPinType } from '@onekeyfe/hd-transport';
|
|
3
2
|
import { encode as encodeJpeg } from 'jpeg-js';
|
|
4
3
|
|
|
5
4
|
import DeviceUploadNft from '../src/api/protocol-v2/DeviceUploadNft';
|
|
@@ -111,8 +110,6 @@ describe('DeviceUploadNft', () => {
|
|
|
111
110
|
|
|
112
111
|
method.init();
|
|
113
112
|
|
|
114
|
-
expect(method.unlockPolicy).toBe('unlock-before-run');
|
|
115
|
-
expect(method.protocolV2PreUnlockPinType).toBe(DeviceSessionPinType.Any);
|
|
116
113
|
expect((method as any).params).toMatchObject({
|
|
117
114
|
chunkSize: 2048,
|
|
118
115
|
paceMs: 0,
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import axios from 'axios';
|
|
2
|
+
import { sha256 } from '@noble/hashes/sha256';
|
|
2
3
|
import { EDeviceType, EFirmwareType, HardwareErrorCode } from '@onekeyfe/hd-shared';
|
|
3
4
|
|
|
4
5
|
import { DataManager } from '../src/data-manager';
|
|
5
6
|
import {
|
|
6
|
-
|
|
7
|
+
parseProtocolV2ResourceManifest,
|
|
7
8
|
parseProtocolV2Resources,
|
|
8
9
|
} from '../src/protocols/protocol-v2/resources';
|
|
9
10
|
|
|
@@ -15,6 +16,9 @@ jest.mock('../src/data/config', () => ({
|
|
|
15
16
|
DEFAULT_DOMAIN: 'https://jssdk.onekey.so/1.0.0-test/',
|
|
16
17
|
}));
|
|
17
18
|
|
|
19
|
+
const bytesToHex = (bytes: Uint8Array) =>
|
|
20
|
+
Array.from(bytes, byte => byte.toString(16).padStart(2, '0')).join('');
|
|
21
|
+
|
|
18
22
|
const resourceSource = {
|
|
19
23
|
archiveUrl: 'https://example.com/resource/pro2-resource.zip',
|
|
20
24
|
archiveSha256: 'a'.repeat(64),
|
|
@@ -27,21 +31,65 @@ const neoResourceSource = {
|
|
|
27
31
|
archiveSize: 12_345_678,
|
|
28
32
|
};
|
|
29
33
|
|
|
30
|
-
const
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
34
|
+
const manifestFiles = [
|
|
35
|
+
['bundles/firmware_logo-build.okpkg', 'firmware_logo.okpkg', 'vol0:/bundles/firmware_logo.okpkg'],
|
|
36
|
+
['bundles/font/noto-build.okpkg', 'noto.okpkg', 'vol0:/bundles/font/noto.okpkg'],
|
|
37
|
+
['bundles/font/roobert-build.okpkg', 'roobert.okpkg', 'vol0:/bundles/font/roobert.okpkg'],
|
|
38
|
+
[
|
|
39
|
+
'bundles/images/animation-build.okpkg',
|
|
40
|
+
'animation.okpkg',
|
|
41
|
+
'vol0:/bundles/images/animation.okpkg',
|
|
42
|
+
],
|
|
43
|
+
['bundles/images/images-build.okpkg', 'images.okpkg', 'vol0:/bundles/images/images.okpkg'],
|
|
44
|
+
[
|
|
45
|
+
'bundles/images/wallpaper-build.okpkg',
|
|
46
|
+
'wallpaper.okpkg',
|
|
47
|
+
'vol0:/bundles/images/wallpaper.okpkg',
|
|
48
|
+
],
|
|
49
|
+
[
|
|
50
|
+
'bundles/translations/translations-build.okpkg',
|
|
51
|
+
'translations.okpkg',
|
|
52
|
+
'vol0:/bundles/translations/translations.okpkg',
|
|
53
|
+
],
|
|
54
|
+
[
|
|
55
|
+
'loaders/bootloader/boot_resource-build.okpkg',
|
|
56
|
+
'boot_resource.okpkg',
|
|
57
|
+
'vol0:/loaders/bootloader/boot_resource.okpkg',
|
|
58
|
+
],
|
|
59
|
+
['loaders/rom/params-build.okpkg', 'params.okpkg', 'vol0:/loaders/rom/params.okpkg'],
|
|
60
|
+
].map(([archive_path, original_name, device_path], index) => {
|
|
61
|
+
const binary = new Uint8Array([index + 1]).buffer;
|
|
62
|
+
return {
|
|
63
|
+
archive_path,
|
|
64
|
+
original_name,
|
|
65
|
+
device_path,
|
|
66
|
+
size: 1,
|
|
67
|
+
sha256: bytesToHex(sha256(new Uint8Array(binary))),
|
|
68
|
+
signed: true,
|
|
69
|
+
sig_algo: device_path.startsWith('vol0:/bundles/') ? 'ed25519' : 'mldsa65',
|
|
70
|
+
payload_version: '1.0.0',
|
|
71
|
+
binary,
|
|
72
|
+
};
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
const resourceManifest = {
|
|
76
|
+
schema: 1,
|
|
77
|
+
artifact_name: 'pro2-resource-build',
|
|
78
|
+
release_name: 'resource-build',
|
|
79
|
+
variant: 'resource',
|
|
80
|
+
commit: 'a'.repeat(40),
|
|
81
|
+
short_sha: 'aaaaaaa',
|
|
82
|
+
timestamp_utc: '20260807_091424',
|
|
83
|
+
core_version: '1.0.0',
|
|
84
|
+
key_set: 'dev',
|
|
85
|
+
device_root: 'vol0:',
|
|
86
|
+
restore_mode: 'bootloader_update',
|
|
87
|
+
trees: [
|
|
88
|
+
{ path: 'bundles', device: 'vol0:/bundles' },
|
|
89
|
+
{ path: 'loaders/bootloader', device: 'vol0:/loaders/bootloader' },
|
|
90
|
+
{ path: 'loaders/rom', device: 'vol0:/loaders/rom' },
|
|
91
|
+
],
|
|
92
|
+
files: manifestFiles.map(({ binary: _binary, ...file }) => file),
|
|
45
93
|
};
|
|
46
94
|
|
|
47
95
|
const createSettings = (configFetcher: ConnectSettings['configFetcher']): ConnectSettings =>
|
|
@@ -98,36 +146,34 @@ describe('Pro2 resource configuration', () => {
|
|
|
98
146
|
DataManager.lastCheckTimestamp = 0;
|
|
99
147
|
});
|
|
100
148
|
|
|
101
|
-
test('accepts the
|
|
149
|
+
test('accepts the manifest source and the CI schema 1 file set', () => {
|
|
102
150
|
expect(parseProtocolV2Resources({ source: resourceSource })).toEqual({
|
|
103
151
|
source: resourceSource,
|
|
104
152
|
});
|
|
153
|
+
expect(parseProtocolV2ResourceManifest(resourceManifest).files).toHaveLength(9);
|
|
105
154
|
});
|
|
106
155
|
|
|
107
|
-
test('
|
|
156
|
+
test('uses only the resource file list from a manifest', () => {
|
|
108
157
|
expect(
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
devicePath: 'vol0:/bundles/images.okpkg',
|
|
114
|
-
payloadHash: '11'.repeat(64),
|
|
115
|
-
headerHash: '22'.repeat(64),
|
|
116
|
-
});
|
|
158
|
+
parseProtocolV2ResourceManifest({
|
|
159
|
+
files: resourceManifest.files,
|
|
160
|
+
})
|
|
161
|
+
).toEqual({ files: resourceManifest.files });
|
|
117
162
|
});
|
|
118
163
|
|
|
119
|
-
test('
|
|
164
|
+
test('ignores release metadata and accepts a partial resource file set', () => {
|
|
120
165
|
expect(
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
166
|
+
parseProtocolV2ResourceManifest({
|
|
167
|
+
schema: 1,
|
|
168
|
+
variant: 'dev_resource',
|
|
169
|
+
restore_mode: 'bootloader_update',
|
|
170
|
+
trees: [],
|
|
171
|
+
files: [resourceManifest.files[0]],
|
|
172
|
+
})
|
|
173
|
+
).toEqual({ files: [resourceManifest.files[0]] });
|
|
128
174
|
});
|
|
129
175
|
|
|
130
|
-
test('rejects missing
|
|
176
|
+
test('rejects missing source and malformed manifest paths', () => {
|
|
131
177
|
expect(() => parseProtocolV2Resources({})).toThrow('source is required');
|
|
132
178
|
expect(() =>
|
|
133
179
|
parseProtocolV2Resources({
|
|
@@ -147,6 +193,14 @@ describe('Pro2 resource configuration', () => {
|
|
|
147
193
|
source: { ...resourceSource, archiveSize: 0 },
|
|
148
194
|
})
|
|
149
195
|
).toThrow('positive integer');
|
|
196
|
+
expect(() =>
|
|
197
|
+
parseProtocolV2ResourceManifest({
|
|
198
|
+
...resourceManifest,
|
|
199
|
+
files: resourceManifest.files.map((file, index) =>
|
|
200
|
+
index === 0 ? { ...file, archive_path: '../outside.okpkg' } : file
|
|
201
|
+
),
|
|
202
|
+
})
|
|
203
|
+
).toThrow('archive_path');
|
|
150
204
|
});
|
|
151
205
|
|
|
152
206
|
test('applies a validated pre-release config and exposes its archive source', async () => {
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import TransportUtils, { DeviceSessionPinType } from '@onekeyfe/hd-transport';
|
|
2
|
-
import { encode as encodeJpeg } from 'jpeg-js';
|
|
3
2
|
|
|
4
3
|
import ConfluxSignMessageCIP23 from '../src/api/conflux/ConfluxSignMessageCIP23';
|
|
5
4
|
import DeviceChangePin from '../src/api/device/DeviceChangePin';
|
|
@@ -7,8 +6,6 @@ import DeviceLock from '../src/api/device/DeviceLock';
|
|
|
7
6
|
import DeviceSettings from '../src/api/device/DeviceSettings';
|
|
8
7
|
import DeviceVerify from '../src/api/device/DeviceVerify';
|
|
9
8
|
import DeviceWipe from '../src/api/device/DeviceWipe';
|
|
10
|
-
import DeviceUploadNft from '../src/api/protocol-v2/DeviceUploadNft';
|
|
11
|
-
import DeviceUploadWallpaper from '../src/api/protocol-v2/DeviceUploadWallpaper';
|
|
12
9
|
import FirmwareUpdateV4 from '../src/api/FirmwareUpdateV4';
|
|
13
10
|
import OpenWalletSession from '../src/api/OpenWalletSession';
|
|
14
11
|
import DataManager from '../src/data-manager/DataManager';
|
|
@@ -19,12 +16,6 @@ jest.mock('../src/data/config', () => ({
|
|
|
19
16
|
getSDKVersion: () => '0.0.0-test',
|
|
20
17
|
}));
|
|
21
18
|
|
|
22
|
-
const createJpegBase64 = (width: number, height: number) => {
|
|
23
|
-
const data = new Uint8Array(width * height * 4);
|
|
24
|
-
for (let index = 3; index < data.length; index += 4) data[index] = 0xff;
|
|
25
|
-
return encodeJpeg({ width, height, data }, 80).data.toString('base64');
|
|
26
|
-
};
|
|
27
|
-
|
|
28
19
|
describe('Protocol V2 unlock semantics', () => {
|
|
29
20
|
test('serializes genuine-device verification with Protocol V2 certificate messages', async () => {
|
|
30
21
|
const method = new DeviceVerify({
|
|
@@ -267,32 +258,6 @@ describe('Protocol V2 unlock semantics', () => {
|
|
|
267
258
|
payload: { method: 'deviceVerify', dataHex: '00' },
|
|
268
259
|
}),
|
|
269
260
|
],
|
|
270
|
-
[
|
|
271
|
-
'wallpaper uploads',
|
|
272
|
-
() =>
|
|
273
|
-
new DeviceUploadWallpaper({
|
|
274
|
-
id: 1,
|
|
275
|
-
payload: {
|
|
276
|
-
method: 'deviceUploadWallpaper',
|
|
277
|
-
jpegBase64: createJpegBase64(604, 1024),
|
|
278
|
-
},
|
|
279
|
-
}),
|
|
280
|
-
],
|
|
281
|
-
[
|
|
282
|
-
'NFT uploads',
|
|
283
|
-
() =>
|
|
284
|
-
new DeviceUploadNft({
|
|
285
|
-
id: 1,
|
|
286
|
-
payload: {
|
|
287
|
-
method: 'deviceUploadNft',
|
|
288
|
-
imageJpegBase64: createJpegBase64(540, 540),
|
|
289
|
-
thumbnailJpegBase64: createJpegBase64(263, 263),
|
|
290
|
-
title: 'NFT',
|
|
291
|
-
subtitle: '',
|
|
292
|
-
timestampMs: 1,
|
|
293
|
-
},
|
|
294
|
-
}),
|
|
295
|
-
],
|
|
296
261
|
])('allows either PIN type when pre-unlocking %s', async (_name, createMethod) => {
|
|
297
262
|
const method = createMethod();
|
|
298
263
|
method.init();
|