@onekeyfe/hd-core 1.2.0-alpha.99 → 1.2.1-alpha.0
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__/AllNetworkGetAddressBase.tracing.test.ts +20 -4
- package/__tests__/DeviceCommands.test.ts +203 -27
- package/__tests__/base64Data.test.ts +69 -0
- package/__tests__/check-all-firmware-release-protocol-v2.test.ts +48 -2
- package/__tests__/check-firmware-release-protocol-v2.test.ts +82 -13
- package/__tests__/device-connector-protocol.test.ts +21 -0
- package/__tests__/device-lifecycle-events.test.ts +427 -7
- package/__tests__/device-pool-state.test.ts +25 -0
- package/__tests__/device-settings.test.ts +237 -9
- package/__tests__/device-state-events.test.ts +2 -2
- package/__tests__/device-state-mapper.test.ts +61 -5
- package/__tests__/device-utils.test.ts +15 -1
- package/__tests__/device-wallet-session-store.test.ts +147 -21
- package/__tests__/deviceSettings.test.ts +7 -3
- package/__tests__/deviceUploadNft.test.ts +36 -4
- package/__tests__/firmware-update/device-update-bootloader.test.ts +13 -3
- package/__tests__/firmware-update/firmware-artifact-source.test.ts +61 -9
- package/__tests__/firmware-update/firmware-prepared-host-digest.test.ts +19 -9
- package/__tests__/firmware-update/firmware-prepared-resource-archive.test.ts +21 -0
- package/__tests__/firmware-update/firmware-update-bootloader-poll.test.ts +63 -0
- package/__tests__/firmware-update/firmware-update-plan.test.ts +59 -55
- package/__tests__/firmware-update/firmware-update-prepared-plan.test.ts +19 -5
- package/__tests__/firmware-update/firmware-update-v3-reconnect.test.ts +116 -0
- package/__tests__/firmware-update/firmware-update-v4-install-poll.test.ts +979 -0
- package/__tests__/firmware-update/firmware-update-v4-parameters.test.ts +85 -0
- package/__tests__/get-device-state.test.ts +60 -21
- package/__tests__/logBlockEvent.test.ts +13 -1
- package/__tests__/open-wallet-session.test.ts +127 -1
- package/__tests__/protocol-v2-firmware-targets.test.ts +23 -0
- package/__tests__/protocol-v2-resources.test.ts +185 -88
- package/__tests__/protocol-v2-unlock-policy.test.ts +235 -2
- package/__tests__/protocol-v2.test.ts +2199 -486
- package/__tests__/refresh-device-state.test.ts +3 -1
- package/__tests__/resourceBase64Boundary.test.ts +48 -0
- package/__tests__/search-devices.test.ts +79 -32
- package/__tests__/ton-sign-message.test.ts +84 -0
- package/dist/api/BaseMethod.d.ts +2 -1
- package/dist/api/BaseMethod.d.ts.map +1 -1
- package/dist/api/CheckAllFirmwareRelease.d.ts.map +1 -1
- package/dist/api/CheckBootloaderRelease.d.ts.map +1 -1
- package/dist/api/FirmwareUpdateV2.d.ts.map +1 -1
- package/dist/api/FirmwareUpdateV3.d.ts.map +1 -1
- package/dist/api/FirmwareUpdateV4.d.ts +20 -6
- package/dist/api/FirmwareUpdateV4.d.ts.map +1 -1
- package/dist/api/OpenWalletSession.d.ts.map +1 -1
- package/dist/api/SearchDevices.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/allnetwork/AllNetworkGetAddressBase.d.ts.map +1 -1
- package/dist/api/device/DeviceChangePin.d.ts.map +1 -1
- package/dist/api/device/DeviceRebootToBoardloader.d.ts.map +1 -1
- package/dist/api/device/DeviceRebootToBootloader.d.ts.map +1 -1
- package/dist/api/device/DeviceSettings.d.ts.map +1 -1
- package/dist/api/device/DeviceVerify.d.ts +1 -0
- package/dist/api/device/DeviceVerify.d.ts.map +1 -1
- package/dist/api/device/DeviceWipe.d.ts.map +1 -1
- package/dist/api/firmware/FirmwareArtifactSource.d.ts +5 -1
- package/dist/api/firmware/FirmwareArtifactSource.d.ts.map +1 -1
- package/dist/api/firmware/FirmwarePreparedResourceArchive.d.ts.map +1 -1
- package/dist/api/firmware/FirmwareUpdateBaseMethod.d.ts +2 -2
- package/dist/api/firmware/FirmwareUpdateBaseMethod.d.ts.map +1 -1
- package/dist/api/firmware/FirmwareUpdatePlan.d.ts +0 -15
- package/dist/api/firmware/FirmwareUpdatePlan.d.ts.map +1 -1
- package/dist/api/firmware/FirmwareUpdatePreparedPlan.d.ts.map +1 -1
- package/dist/api/firmware/getBinary.d.ts +3 -2
- package/dist/api/firmware/getBinary.d.ts.map +1 -1
- package/dist/api/firmware/protocolV2Release.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/DeviceFirmwareUpdate.d.ts +3 -1
- package/dist/api/protocol-v2/DeviceFirmwareUpdate.d.ts.map +1 -1
- package/dist/api/protocol-v2/DeviceGetFirmwareUpdateStatus.d.ts.map +1 -1
- 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/DeviceReboot.d.ts +1 -1
- package/dist/api/protocol-v2/DeviceReboot.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/protocol-v2/helpers.d.ts.map +1 -1
- package/dist/api/ton/TonSignMessage.d.ts.map +1 -1
- package/dist/core/index.d.ts +6 -1
- package/dist/core/index.d.ts.map +1 -1
- package/dist/data-manager/DataManager.d.ts +4 -3
- package/dist/data-manager/DataManager.d.ts.map +1 -1
- package/dist/data-manager/TransportManager.d.ts.map +1 -1
- package/dist/device/Device.d.ts +16 -3
- package/dist/device/Device.d.ts.map +1 -1
- package/dist/device/DeviceCommands.d.ts +4 -4
- package/dist/device/DeviceCommands.d.ts.map +1 -1
- package/dist/device/DeviceConnector.d.ts +1 -1
- package/dist/device/DeviceConnector.d.ts.map +1 -1
- package/dist/device/DevicePool.d.ts.map +1 -1
- package/dist/device/DeviceStateMapper.d.ts.map +1 -1
- package/dist/deviceProfile/buildDeviceFeatures.d.ts.map +1 -1
- package/dist/events/logBlockEvent.d.ts.map +1 -1
- package/dist/events/ui-request.d.ts +3 -0
- package/dist/events/ui-request.d.ts.map +1 -1
- package/dist/index.d.ts +54 -84
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2150 -1469
- 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 +12 -7
- package/dist/protocols/protocol-v2/resources.d.ts.map +1 -1
- package/dist/protocols/protocol-v2/unlockPolicyRunner.d.ts +3 -1
- package/dist/protocols/protocol-v2/unlockPolicyRunner.d.ts.map +1 -1
- package/dist/protocols/protocol-v2/walletSession.d.ts +3 -0
- package/dist/protocols/protocol-v2/walletSession.d.ts.map +1 -1
- package/dist/types/api/firmwareUpdatePlan.d.ts +2 -2
- package/dist/types/api/firmwareUpdatePlan.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/device.d.ts.map +1 -1
- package/dist/types/settings.d.ts +3 -31
- package/dist/types/settings.d.ts.map +1 -1
- package/dist/utils/deviceFeaturesCompat.d.ts.map +1 -1
- package/dist/utils/deviceFeaturesUtils.d.ts +3 -0
- package/dist/utils/deviceFeaturesUtils.d.ts.map +1 -1
- package/dist/utils/deviceInfoUtils.d.ts.map +1 -1
- package/dist/utils/deviceSettings.d.ts +1 -0
- package/dist/utils/deviceSettings.d.ts.map +1 -1
- package/dist/utils/index.d.ts +1 -1
- package/dist/utils/index.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/BaseMethod.ts +8 -1
- package/src/api/CheckAllFirmwareRelease.ts +2 -4
- package/src/api/CheckBLEFirmwareRelease.ts +2 -2
- package/src/api/CheckBootloaderRelease.ts +3 -2
- package/src/api/CheckFirmwareRelease.ts +2 -2
- package/src/api/FirmwareUpdateV2.ts +12 -9
- package/src/api/FirmwareUpdateV3.ts +29 -19
- package/src/api/FirmwareUpdateV4.ts +934 -739
- package/src/api/OpenWalletSession.ts +39 -9
- package/src/api/PromptWebDeviceAccess.ts +2 -2
- package/src/api/SearchDevices.ts +6 -3
- package/src/api/UploadPortfolio.ts +9 -2
- package/src/api/allnetwork/AllNetworkGetAddressBase.ts +2 -1
- package/src/api/device/DeviceChangePin.ts +4 -1
- package/src/api/device/DeviceRebootToBoardloader.ts +3 -1
- package/src/api/device/DeviceRebootToBootloader.ts +3 -1
- package/src/api/device/DeviceSettings.ts +34 -20
- package/src/api/device/DeviceVerify.ts +25 -0
- package/src/api/device/DeviceWipe.ts +4 -1
- package/src/api/firmware/FirmwareArtifactSource.ts +41 -14
- package/src/api/firmware/FirmwarePreparedResourceArchive.ts +16 -27
- package/src/api/firmware/FirmwareUpdateBaseMethod.ts +9 -3
- package/src/api/firmware/FirmwareUpdatePlan.ts +37 -77
- package/src/api/firmware/FirmwareUpdatePreparedPlan.ts +10 -6
- package/src/api/firmware/protocolV2Release.ts +7 -2
- package/src/api/helpers/base64Data.ts +85 -0
- package/src/api/protocol-v2/DeviceFactoryInfoSet.ts +1 -1
- package/src/api/protocol-v2/DeviceFirmwareUpdate.ts +6 -28
- package/src/api/protocol-v2/DeviceGetFirmwareUpdateStatus.ts +7 -1
- package/src/api/protocol-v2/DeviceInfoGet.ts +3 -3
- package/src/api/protocol-v2/DeviceReboot.ts +5 -0
- package/src/api/protocol-v2/DeviceUploadNft.ts +61 -9
- package/src/api/protocol-v2/DeviceUploadWallpaper.ts +53 -19
- package/src/api/protocol-v2/helpers.ts +8 -0
- package/src/api/ton/TonSignMessage.ts +5 -3
- package/src/core/index.ts +264 -55
- package/src/data/messages/messages-protocol-v2.json +140 -13
- package/src/data-manager/DataManager.ts +46 -39
- package/src/data-manager/TransportManager.ts +3 -1
- package/src/device/Device.ts +210 -44
- package/src/device/DeviceCommands.ts +27 -18
- package/src/device/DeviceConnector.ts +17 -3
- package/src/device/DevicePool.ts +9 -2
- package/src/device/DeviceStateMapper.ts +30 -24
- package/src/deviceProfile/buildDeviceFeatures.ts +10 -5
- package/src/events/logBlockEvent.ts +14 -1
- package/src/events/ui-request.ts +3 -0
- package/src/index.ts +0 -10
- 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 +110 -147
- package/src/protocols/protocol-v2/unlockPolicyRunner.ts +13 -1
- package/src/protocols/protocol-v2/walletSession.ts +65 -22
- package/src/types/api/firmwareUpdate.ts +1 -1
- package/src/types/api/firmwareUpdatePlan.ts +2 -2
- package/src/types/api/protocolV2.ts +1 -1
- package/src/types/device.ts +2 -1
- package/src/types/settings.ts +6 -34
- package/src/utils/deviceFeaturesCompat.ts +9 -4
- package/src/utils/deviceFeaturesUtils.ts +4 -0
- package/src/utils/deviceInfoUtils.ts +9 -2
- package/src/utils/deviceSettings.ts +11 -4
- package/src/utils/index.ts +1 -0
- package/src/utils/pro2Nft.ts +31 -8
- package/__tests__/firmware-memory-host.test.ts +0 -126
- package/dist/api/firmware/FirmwareMemoryHost.d.ts +0 -22
- package/dist/api/firmware/FirmwareMemoryHost.d.ts.map +0 -1
- package/src/api/firmware/FirmwareMemoryHost.ts +0 -143
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import axios from 'axios';
|
|
2
|
-
import {
|
|
3
|
-
import { EDeviceType, HardwareErrorCode } from '@onekeyfe/hd-shared';
|
|
2
|
+
import { EDeviceType, EFirmwareType, HardwareErrorCode } from '@onekeyfe/hd-shared';
|
|
4
3
|
|
|
5
4
|
import { DataManager } from '../src/data-manager';
|
|
6
5
|
import {
|
|
7
|
-
|
|
6
|
+
isProtocolV2ResourceArchiveEntryName,
|
|
7
|
+
parseProtocolV2ResourcePackage,
|
|
8
8
|
parseProtocolV2Resources,
|
|
9
9
|
} from '../src/protocols/protocol-v2/resources';
|
|
10
10
|
|
|
11
|
-
import type { ConnectSettings, RemoteConfigResponse } from '../src/types';
|
|
11
|
+
import type { ConnectSettings, Features, RemoteConfigResponse } from '../src/types';
|
|
12
12
|
|
|
13
13
|
jest.mock('axios');
|
|
14
14
|
jest.mock('../src/data/config', () => ({
|
|
@@ -16,9 +16,6 @@ jest.mock('../src/data/config', () => ({
|
|
|
16
16
|
DEFAULT_DOMAIN: 'https://jssdk.onekey.so/1.0.0-test/',
|
|
17
17
|
}));
|
|
18
18
|
|
|
19
|
-
const bytesToHex = (bytes: Uint8Array) =>
|
|
20
|
-
Array.from(bytes, byte => byte.toString(16).padStart(2, '0')).join('');
|
|
21
|
-
|
|
22
19
|
const resourceSource = {
|
|
23
20
|
archiveUrl: 'https://example.com/resource/pro2-resource.zip',
|
|
24
21
|
archiveSha256: 'a'.repeat(64),
|
|
@@ -31,65 +28,21 @@ const neoResourceSource = {
|
|
|
31
28
|
archiveSize: 12_345_678,
|
|
32
29
|
};
|
|
33
30
|
|
|
34
|
-
const
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
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),
|
|
31
|
+
const createResourcePackage = (devicePath: string) => {
|
|
32
|
+
const headerSize = 0x5f90;
|
|
33
|
+
const bytes = new Uint8Array(headerSize + 1);
|
|
34
|
+
bytes.set(new TextEncoder().encode('OKPP'), 0);
|
|
35
|
+
bytes.set(new TextEncoder().encode('RESC'), 0x08);
|
|
36
|
+
bytes.set(new TextEncoder().encode(devicePath), 0x6c);
|
|
37
|
+
const view = new DataView(bytes.buffer);
|
|
38
|
+
view.setUint32(0x04, 1, true);
|
|
39
|
+
view.setUint32(0x0c, headerSize, true);
|
|
40
|
+
view.setUint32(0x10, 0x010203, true);
|
|
41
|
+
view.setUint32(0x14, 1, true);
|
|
42
|
+
bytes.fill(0x11, 0x200, 0x240);
|
|
43
|
+
bytes.fill(0x22, 0x240, 0x280);
|
|
44
|
+
bytes[headerSize] = 0xaa;
|
|
45
|
+
return bytes;
|
|
93
46
|
};
|
|
94
47
|
|
|
95
48
|
const createSettings = (configFetcher: ConnectSettings['configFetcher']): ConnectSettings =>
|
|
@@ -108,25 +61,109 @@ const createRemoteConfig = (): RemoteConfigResponse =>
|
|
|
108
61
|
mini: { firmware: [], ble: [] },
|
|
109
62
|
touch: { firmware: [], ble: [] },
|
|
110
63
|
pro: { firmware: [], ble: [] },
|
|
111
|
-
pro2: {
|
|
112
|
-
|
|
64
|
+
pro2: {
|
|
65
|
+
'firmware-v1': [
|
|
66
|
+
{
|
|
67
|
+
required: false,
|
|
68
|
+
version: [1, 0, 0],
|
|
69
|
+
changelog: { 'zh-CN': 'Pro2', 'en-US': 'Pro2' },
|
|
70
|
+
resources: { source: resourceSource },
|
|
71
|
+
},
|
|
72
|
+
],
|
|
73
|
+
ble: [],
|
|
74
|
+
},
|
|
75
|
+
neo: {
|
|
76
|
+
'firmware-v1': [
|
|
77
|
+
{
|
|
78
|
+
required: false,
|
|
79
|
+
version: [1, 0, 0],
|
|
80
|
+
changelog: { 'zh-CN': 'Neo', 'en-US': 'Neo' },
|
|
81
|
+
resources: { source: neoResourceSource },
|
|
82
|
+
},
|
|
83
|
+
],
|
|
84
|
+
ble: [],
|
|
85
|
+
},
|
|
113
86
|
bridge: {},
|
|
114
87
|
} as unknown as RemoteConfigResponse);
|
|
115
88
|
|
|
89
|
+
const getProtocolV2Release = (deviceType: EDeviceType.Pro2 | EDeviceType.Neo) =>
|
|
90
|
+
DataManager.deviceMap[deviceType]?.['firmware-v1']?.[0];
|
|
91
|
+
|
|
116
92
|
describe('Pro2 resource configuration', () => {
|
|
117
93
|
beforeEach(() => {
|
|
118
94
|
jest.clearAllMocks();
|
|
119
95
|
DataManager.lastCheckTimestamp = 0;
|
|
120
96
|
});
|
|
121
97
|
|
|
122
|
-
test('accepts the
|
|
98
|
+
test('accepts the release archive source', () => {
|
|
123
99
|
expect(parseProtocolV2Resources({ source: resourceSource })).toEqual({
|
|
124
100
|
source: resourceSource,
|
|
125
101
|
});
|
|
126
|
-
expect(parseProtocolV2ResourceManifest(resourceManifest).files).toHaveLength(9);
|
|
127
102
|
});
|
|
128
103
|
|
|
129
|
-
test('
|
|
104
|
+
test('ignores macOS ZIP metadata that only looks like a resource package', () => {
|
|
105
|
+
expect(
|
|
106
|
+
isProtocolV2ResourceArchiveEntryName('bundles/firmware_logo-pro2-prod_resource-signed.okpkg')
|
|
107
|
+
).toBe(true);
|
|
108
|
+
expect(
|
|
109
|
+
isProtocolV2ResourceArchiveEntryName(
|
|
110
|
+
'pro2-prod_resource/bundles/firmware_logo-pro2-prod_resource-signed.okpkg'
|
|
111
|
+
)
|
|
112
|
+
).toBe(true);
|
|
113
|
+
expect(
|
|
114
|
+
isProtocolV2ResourceArchiveEntryName(
|
|
115
|
+
'__MACOSX/pro2-prod_resource 2/bundles/._firmware_logo-pro2-prod_resource-signed.okpkg'
|
|
116
|
+
)
|
|
117
|
+
).toBe(false);
|
|
118
|
+
expect(
|
|
119
|
+
isProtocolV2ResourceArchiveEntryName(
|
|
120
|
+
'bundles/._firmware_logo-pro2-prod_resource-signed.okpkg'
|
|
121
|
+
)
|
|
122
|
+
).toBe(false);
|
|
123
|
+
expect(isProtocolV2ResourceArchiveEntryName('pro2-prod_resource/manifest.json')).toBe(false);
|
|
124
|
+
expect(isProtocolV2ResourceArchiveEntryName('pro2-prod_resource/.DS_Store')).toBe(false);
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
test('reads the version, hashes, and direct device path from a RESC package', () => {
|
|
128
|
+
expect(
|
|
129
|
+
parseProtocolV2ResourcePackage(createResourcePackage('vol0:/bundles/images.okpkg'))
|
|
130
|
+
).toEqual({
|
|
131
|
+
version: [1, 2, 3],
|
|
132
|
+
payloadLength: 1,
|
|
133
|
+
devicePath: 'vol0:/bundles/images.okpkg',
|
|
134
|
+
payloadHash: '11'.repeat(64),
|
|
135
|
+
headerHash: '22'.repeat(64),
|
|
136
|
+
});
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
test('uses the RESC header device path and only rejects malformed paths', () => {
|
|
140
|
+
expect(
|
|
141
|
+
parseProtocolV2ResourcePackage(
|
|
142
|
+
createResourcePackage('vol0:/loaders/bootloader/boot_resource.okpkg.staging')
|
|
143
|
+
).devicePath
|
|
144
|
+
).toBe('vol0:/loaders/bootloader/boot_resource.okpkg.staging');
|
|
145
|
+
expect(
|
|
146
|
+
parseProtocolV2ResourcePackage(
|
|
147
|
+
createResourcePackage('vol0:/loaders/bootloader/params.okpkg.staging')
|
|
148
|
+
).devicePath
|
|
149
|
+
).toBe('vol0:/loaders/bootloader/params.okpkg.staging');
|
|
150
|
+
expect(
|
|
151
|
+
parseProtocolV2ResourcePackage(createResourcePackage('vol0:/loaders/rom/params.okpkg'))
|
|
152
|
+
.devicePath
|
|
153
|
+
).toBe('vol0:/loaders/rom/params.okpkg');
|
|
154
|
+
expect(
|
|
155
|
+
parseProtocolV2ResourcePackage(createResourcePackage('vol0:/unexpected/images.okpkg'))
|
|
156
|
+
.devicePath
|
|
157
|
+
).toBe('vol0:/unexpected/images.okpkg');
|
|
158
|
+
expect(() =>
|
|
159
|
+
parseProtocolV2ResourcePackage(createResourcePackage('vol0:/bundles/../images.okpkg'))
|
|
160
|
+
).toThrow('device path');
|
|
161
|
+
expect(() =>
|
|
162
|
+
parseProtocolV2ResourcePackage(createResourcePackage('vol0://bundles/images.okpkg'))
|
|
163
|
+
).toThrow('device path');
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
test('rejects missing or malformed release sources', () => {
|
|
130
167
|
expect(() => parseProtocolV2Resources({})).toThrow('source is required');
|
|
131
168
|
expect(() =>
|
|
132
169
|
parseProtocolV2Resources({
|
|
@@ -146,14 +183,6 @@ describe('Pro2 resource configuration', () => {
|
|
|
146
183
|
source: { ...resourceSource, archiveSize: 0 },
|
|
147
184
|
})
|
|
148
185
|
).toThrow('positive integer');
|
|
149
|
-
expect(() =>
|
|
150
|
-
parseProtocolV2ResourceManifest({
|
|
151
|
-
...resourceManifest,
|
|
152
|
-
files: resourceManifest.files.map((file, index) =>
|
|
153
|
-
index === 0 ? { ...file, archive_path: '../outside.okpkg' } : file
|
|
154
|
-
),
|
|
155
|
-
})
|
|
156
|
-
).toThrow('archive_path');
|
|
157
186
|
});
|
|
158
187
|
|
|
159
188
|
test('applies a validated pre-release config and exposes its archive source', async () => {
|
|
@@ -164,10 +193,70 @@ describe('Pro2 resource configuration', () => {
|
|
|
164
193
|
expect(configFetcher).toHaveBeenCalledWith(
|
|
165
194
|
expect.stringMatching(/^https:\/\/data\.onekey\.so\/pre-config\.json\?noCache=/)
|
|
166
195
|
);
|
|
167
|
-
expect(DataManager.getProtocolV2ResourceSource()).toEqual(
|
|
196
|
+
expect(DataManager.getProtocolV2ResourceSource(getProtocolV2Release(EDeviceType.Pro2))).toEqual(
|
|
197
|
+
resourceSource
|
|
198
|
+
);
|
|
168
199
|
expect(DataManager.lastCheckTimestamp).toBeGreaterThan(0);
|
|
169
200
|
});
|
|
170
201
|
|
|
202
|
+
test('uses the resource archive bound to the selected firmware release', async () => {
|
|
203
|
+
const newerResourceSource = {
|
|
204
|
+
archiveUrl: 'https://example.com/resource/pro2-resource-v2.zip',
|
|
205
|
+
archiveSha256: 'c'.repeat(64),
|
|
206
|
+
archiveSize: 20_000_000,
|
|
207
|
+
};
|
|
208
|
+
const remoteConfig = createRemoteConfig();
|
|
209
|
+
remoteConfig.pro2['firmware-v1']?.push({
|
|
210
|
+
...remoteConfig.pro2['firmware-v1'][0],
|
|
211
|
+
version: [2, 0, 0],
|
|
212
|
+
resources: { source: newerResourceSource },
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
await expect(
|
|
216
|
+
DataManager.load(createSettings(jest.fn().mockResolvedValue(remoteConfig)))
|
|
217
|
+
).resolves.toBe(true);
|
|
218
|
+
|
|
219
|
+
const selectedRelease = DataManager.getFirmwareLatestRelease(
|
|
220
|
+
{ deviceType: 'pro2', firmwareVersion: '1.0.0' } as Features,
|
|
221
|
+
EFirmwareType.Universal
|
|
222
|
+
);
|
|
223
|
+
expect(selectedRelease?.version).toEqual([2, 0, 0]);
|
|
224
|
+
expect(DataManager.getProtocolV2ResourceSource(selectedRelease)).toEqual(newerResourceSource);
|
|
225
|
+
});
|
|
226
|
+
|
|
227
|
+
test('does not use a device-level Protocol V2 resource archive', async () => {
|
|
228
|
+
const remoteConfig = createRemoteConfig();
|
|
229
|
+
delete remoteConfig.pro2['firmware-v1']?.[0].resources;
|
|
230
|
+
(remoteConfig.pro2 as unknown as { resources: unknown }).resources = {
|
|
231
|
+
source: resourceSource,
|
|
232
|
+
};
|
|
233
|
+
|
|
234
|
+
await expect(
|
|
235
|
+
DataManager.load(createSettings(jest.fn().mockResolvedValue(remoteConfig)))
|
|
236
|
+
).resolves.toBe(true);
|
|
237
|
+
|
|
238
|
+
expect(
|
|
239
|
+
DataManager.getProtocolV2ResourceSource(getProtocolV2Release(EDeviceType.Pro2))
|
|
240
|
+
).toBeUndefined();
|
|
241
|
+
});
|
|
242
|
+
|
|
243
|
+
test('does not block the latest release when an older release has invalid resources', async () => {
|
|
244
|
+
const remoteConfig = createRemoteConfig();
|
|
245
|
+
(remoteConfig.pro2['firmware-v1']?.[0] as { resources?: unknown }).resources = { source: {} };
|
|
246
|
+
remoteConfig.pro2['firmware-v1']?.push({
|
|
247
|
+
...remoteConfig.pro2['firmware-v1'][0],
|
|
248
|
+
version: [2, 0, 0],
|
|
249
|
+
resources: { source: resourceSource },
|
|
250
|
+
});
|
|
251
|
+
const configFetcher = jest.fn().mockResolvedValue(remoteConfig);
|
|
252
|
+
|
|
253
|
+
await expect(DataManager.load(createSettings(configFetcher))).resolves.toBe(true);
|
|
254
|
+
await expect(DataManager.forceReloadData({ requireResources: true })).resolves.toBeUndefined();
|
|
255
|
+
|
|
256
|
+
const latestRelease = DataManager.deviceMap[EDeviceType.Pro2]?.['firmware-v1']?.[1];
|
|
257
|
+
expect(DataManager.getProtocolV2ResourceSource(latestRelease)).toEqual(resourceSource);
|
|
258
|
+
});
|
|
259
|
+
|
|
171
260
|
test('reuses the configuration fetched during SDK initialization for an immediate update', async () => {
|
|
172
261
|
const configFetcher = jest.fn().mockResolvedValue(createRemoteConfig());
|
|
173
262
|
const settings = createSettings(configFetcher);
|
|
@@ -180,25 +269,33 @@ describe('Pro2 resource configuration', () => {
|
|
|
180
269
|
|
|
181
270
|
test('keeps base SDK initialization available when remote Pro2 resources are invalid', async () => {
|
|
182
271
|
const remoteConfig = createRemoteConfig();
|
|
183
|
-
(remoteConfig.pro2 as { resources?: unknown }).resources = { source: {} };
|
|
272
|
+
(remoteConfig.pro2['firmware-v1']?.[0] as { resources?: unknown }).resources = { source: {} };
|
|
184
273
|
const configFetcher = jest.fn().mockResolvedValue(remoteConfig);
|
|
185
274
|
|
|
186
275
|
await expect(DataManager.load(createSettings(configFetcher))).resolves.toBe(true);
|
|
187
276
|
|
|
188
|
-
expect(
|
|
277
|
+
expect(
|
|
278
|
+
DataManager.getProtocolV2ResourceSource(getProtocolV2Release(EDeviceType.Pro2))
|
|
279
|
+
).toBeUndefined();
|
|
189
280
|
expect(DataManager.protocolV2ResourcesConfigError).toBeInstanceOf(Error);
|
|
190
|
-
expect(DataManager.getProtocolV2ResourceSource(EDeviceType.Neo)).toEqual(
|
|
281
|
+
expect(DataManager.getProtocolV2ResourceSource(getProtocolV2Release(EDeviceType.Neo))).toEqual(
|
|
282
|
+
neoResourceSource
|
|
283
|
+
);
|
|
191
284
|
});
|
|
192
285
|
|
|
193
286
|
test('keeps Pro2 resources available when remote Neo resources are invalid', async () => {
|
|
194
287
|
const remoteConfig = createRemoteConfig();
|
|
195
|
-
(remoteConfig.neo as { resources?: unknown }).resources = { source: {} };
|
|
288
|
+
(remoteConfig.neo?.['firmware-v1']?.[0] as { resources?: unknown }).resources = { source: {} };
|
|
196
289
|
const configFetcher = jest.fn().mockResolvedValue(remoteConfig);
|
|
197
290
|
|
|
198
291
|
await expect(DataManager.load(createSettings(configFetcher))).resolves.toBe(true);
|
|
199
292
|
|
|
200
|
-
expect(DataManager.getProtocolV2ResourceSource(EDeviceType.Pro2)).toEqual(
|
|
201
|
-
|
|
293
|
+
expect(DataManager.getProtocolV2ResourceSource(getProtocolV2Release(EDeviceType.Pro2))).toEqual(
|
|
294
|
+
resourceSource
|
|
295
|
+
);
|
|
296
|
+
expect(
|
|
297
|
+
DataManager.getProtocolV2ResourceSource(getProtocolV2Release(EDeviceType.Neo))
|
|
298
|
+
).toBeUndefined();
|
|
202
299
|
await expect(
|
|
203
300
|
DataManager.forceReloadData({
|
|
204
301
|
requireResources: true,
|
|
@@ -218,7 +315,7 @@ describe('Pro2 resource configuration', () => {
|
|
|
218
315
|
|
|
219
316
|
test('only blocks resource mutation when the refreshed Pro2 resources are invalid', async () => {
|
|
220
317
|
const remoteConfig = createRemoteConfig();
|
|
221
|
-
(remoteConfig.pro2 as { resources?: unknown }).resources = { source: {} };
|
|
318
|
+
(remoteConfig.pro2['firmware-v1']?.[0] as { resources?: unknown }).resources = { source: {} };
|
|
222
319
|
const settings = createSettings(jest.fn().mockResolvedValue(remoteConfig));
|
|
223
320
|
DataManager.settings = settings;
|
|
224
321
|
|
|
@@ -232,7 +329,7 @@ describe('Pro2 resource configuration', () => {
|
|
|
232
329
|
|
|
233
330
|
test('checks resource configuration errors for the requested device only', async () => {
|
|
234
331
|
const remoteConfig = createRemoteConfig();
|
|
235
|
-
(remoteConfig.pro2 as { resources?: unknown }).resources = { source: {} };
|
|
332
|
+
(remoteConfig.pro2['firmware-v1']?.[0] as { resources?: unknown }).resources = { source: {} };
|
|
236
333
|
const settings = createSettings(jest.fn().mockResolvedValue(remoteConfig));
|
|
237
334
|
DataManager.settings = settings;
|
|
238
335
|
|
|
@@ -1,8 +1,20 @@
|
|
|
1
|
-
import { DeviceSessionPinType } from '@onekeyfe/hd-transport';
|
|
1
|
+
import TransportUtils, { DeviceSessionPinType } from '@onekeyfe/hd-transport';
|
|
2
|
+
import { encode as encodeJpeg } from 'jpeg-js';
|
|
2
3
|
|
|
3
4
|
import ConfluxSignMessageCIP23 from '../src/api/conflux/ConfluxSignMessageCIP23';
|
|
5
|
+
import DeviceChangePin from '../src/api/device/DeviceChangePin';
|
|
4
6
|
import DeviceLock from '../src/api/device/DeviceLock';
|
|
7
|
+
import DeviceRebootToBoardloader from '../src/api/device/DeviceRebootToBoardloader';
|
|
8
|
+
import DeviceRebootToBootloader from '../src/api/device/DeviceRebootToBootloader';
|
|
9
|
+
import DeviceSettings from '../src/api/device/DeviceSettings';
|
|
10
|
+
import DeviceVerify from '../src/api/device/DeviceVerify';
|
|
11
|
+
import DeviceWipe from '../src/api/device/DeviceWipe';
|
|
12
|
+
import DeviceReboot from '../src/api/protocol-v2/DeviceReboot';
|
|
13
|
+
import DeviceUploadNft from '../src/api/protocol-v2/DeviceUploadNft';
|
|
14
|
+
import DeviceUploadWallpaper from '../src/api/protocol-v2/DeviceUploadWallpaper';
|
|
15
|
+
import FirmwareUpdateV4 from '../src/api/FirmwareUpdateV4';
|
|
5
16
|
import OpenWalletSession from '../src/api/OpenWalletSession';
|
|
17
|
+
import DataManager from '../src/data-manager/DataManager';
|
|
6
18
|
import { runMethodWithUnlockPolicy } from '../src/protocols/protocol-v2/unlockPolicyRunner';
|
|
7
19
|
|
|
8
20
|
jest.mock('../src/data/config', () => ({
|
|
@@ -10,7 +22,49 @@ jest.mock('../src/data/config', () => ({
|
|
|
10
22
|
getSDKVersion: () => '0.0.0-test',
|
|
11
23
|
}));
|
|
12
24
|
|
|
25
|
+
const createJpegBase64 = (width: number, height: number) => {
|
|
26
|
+
const data = new Uint8Array(width * height * 4);
|
|
27
|
+
for (let index = 3; index < data.length; index += 4) data[index] = 0xff;
|
|
28
|
+
return encodeJpeg({ width, height, data }, 80).data.toString('base64');
|
|
29
|
+
};
|
|
30
|
+
|
|
13
31
|
describe('Protocol V2 unlock semantics', () => {
|
|
32
|
+
test('serializes genuine-device verification with Protocol V2 certificate messages', async () => {
|
|
33
|
+
const method = new DeviceVerify({
|
|
34
|
+
id: 1,
|
|
35
|
+
payload: { method: 'deviceVerify', dataHex: 'aabb' },
|
|
36
|
+
});
|
|
37
|
+
method.init();
|
|
38
|
+
const protocolV2Messages = TransportUtils.parseConfigure(
|
|
39
|
+
DataManager.getProtobufMessages('v2Schema')
|
|
40
|
+
);
|
|
41
|
+
const typedCall = jest.fn(
|
|
42
|
+
(requestType: string, responseType: string, payload: Record<string, unknown> = {}) => {
|
|
43
|
+
const request = TransportUtils.createMessageFromName(protocolV2Messages, requestType);
|
|
44
|
+
request.Message.encode(request.Message.create(payload)).finish();
|
|
45
|
+
TransportUtils.createMessageFromName(protocolV2Messages, responseType);
|
|
46
|
+
if (requestType === 'DeviceCertificateSign') {
|
|
47
|
+
return Promise.resolve({ message: { data: 'signature' } });
|
|
48
|
+
}
|
|
49
|
+
return Promise.resolve({ message: { cert_and_pubkey: 'certificate' } });
|
|
50
|
+
}
|
|
51
|
+
);
|
|
52
|
+
method.device = {
|
|
53
|
+
getCurrentDeviceType: () => 'pro2',
|
|
54
|
+
isProtocolV2: () => true,
|
|
55
|
+
commands: { typedCall },
|
|
56
|
+
} as any;
|
|
57
|
+
|
|
58
|
+
await expect(method.run()).resolves.toEqual({
|
|
59
|
+
cert: 'certificate',
|
|
60
|
+
signature: 'signature',
|
|
61
|
+
});
|
|
62
|
+
expect(typedCall.mock.calls.map(call => call.slice(0, 2))).toEqual([
|
|
63
|
+
['DeviceCertificateSign', 'DeviceCertificateSignature'],
|
|
64
|
+
['DeviceCertificateRead', 'DeviceCertificate'],
|
|
65
|
+
]);
|
|
66
|
+
});
|
|
67
|
+
|
|
14
68
|
test('wallet business methods inherit the wallet-session unlock requirement', () => {
|
|
15
69
|
const method = new ConfluxSignMessageCIP23({
|
|
16
70
|
id: 1,
|
|
@@ -22,6 +76,40 @@ describe('Protocol V2 unlock semantics', () => {
|
|
|
22
76
|
expect(method.getSupportedProtocols()).toContain('V2');
|
|
23
77
|
});
|
|
24
78
|
|
|
79
|
+
test.each([
|
|
80
|
+
[
|
|
81
|
+
'deviceReboot',
|
|
82
|
+
() =>
|
|
83
|
+
new DeviceReboot({
|
|
84
|
+
id: 1,
|
|
85
|
+
payload: { method: 'deviceReboot', rebootType: 2 },
|
|
86
|
+
}),
|
|
87
|
+
],
|
|
88
|
+
[
|
|
89
|
+
'deviceRebootToBootloader',
|
|
90
|
+
() =>
|
|
91
|
+
new DeviceRebootToBootloader({
|
|
92
|
+
id: 1,
|
|
93
|
+
payload: { method: 'deviceRebootToBootloader' },
|
|
94
|
+
}),
|
|
95
|
+
],
|
|
96
|
+
[
|
|
97
|
+
'deviceRebootToBoardloader',
|
|
98
|
+
() =>
|
|
99
|
+
new DeviceRebootToBoardloader({
|
|
100
|
+
id: 1,
|
|
101
|
+
payload: { method: 'deviceRebootToBoardloader' },
|
|
102
|
+
}),
|
|
103
|
+
],
|
|
104
|
+
])('pre-unlocks %s before sending DeviceReboot', (_name, createMethod) => {
|
|
105
|
+
const method = createMethod();
|
|
106
|
+
method.init();
|
|
107
|
+
|
|
108
|
+
expect(method.unlockPolicy).toBe('unlock-before-run');
|
|
109
|
+
expect(method.protocolV2PreUnlockPinType).toBe(DeviceSessionPinType.Any);
|
|
110
|
+
expect(method.useDevicePassphraseState).toBe(false);
|
|
111
|
+
});
|
|
112
|
+
|
|
25
113
|
test('lock-free Protocol V2 controls explicitly opt out of wallet-session handling', () => {
|
|
26
114
|
const method = new DeviceLock({
|
|
27
115
|
id: 1,
|
|
@@ -63,8 +151,42 @@ describe('Protocol V2 unlock semantics', () => {
|
|
|
63
151
|
});
|
|
64
152
|
|
|
65
153
|
expect(method.unlockPolicy).toBe('unlock-before-run');
|
|
66
|
-
expect(device.unlockDevice).
|
|
154
|
+
expect(device.unlockDevice).toHaveBeenCalledWith(DeviceSessionPinType.Main, expect.any(Object));
|
|
67
155
|
expect(run).toHaveBeenCalledTimes(1);
|
|
156
|
+
expect(method.protocolV2UnlockContext).toMatchObject({
|
|
157
|
+
preflightCompleted: true,
|
|
158
|
+
preflightStatusRefreshed: true,
|
|
159
|
+
preflightMainPinSelected: true,
|
|
160
|
+
});
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
test('allows either PIN type when pre-unlocking hidden-wallet selection', async () => {
|
|
164
|
+
const method = new OpenWalletSession({
|
|
165
|
+
id: 1,
|
|
166
|
+
payload: { method: 'openWalletSession', mode: 'select-hidden' },
|
|
167
|
+
});
|
|
168
|
+
method.init();
|
|
169
|
+
method.run = jest.fn().mockResolvedValue({ walletType: 'hidden' }) as any;
|
|
170
|
+
const features = { unlocked: false };
|
|
171
|
+
const device = {
|
|
172
|
+
features,
|
|
173
|
+
commands: {
|
|
174
|
+
typedCall: jest.fn().mockResolvedValue({ message: { unlocked: false } }),
|
|
175
|
+
},
|
|
176
|
+
isProtocolV2: () => true,
|
|
177
|
+
isBootloader: () => false,
|
|
178
|
+
isRomloader: () => false,
|
|
179
|
+
updateProtocolV2Status: jest.fn(() => features),
|
|
180
|
+
unlockDevice: jest.fn().mockImplementation(() => {
|
|
181
|
+
features.unlocked = true;
|
|
182
|
+
return Promise.resolve(features);
|
|
183
|
+
}),
|
|
184
|
+
};
|
|
185
|
+
|
|
186
|
+
await runMethodWithUnlockPolicy(method, device as any);
|
|
187
|
+
|
|
188
|
+
expect(device.unlockDevice).toHaveBeenCalledWith(DeviceSessionPinType.Any, expect.any(Object));
|
|
189
|
+
expect(method.protocolV2UnlockContext?.preflightMainPinSelected).toBe(false);
|
|
68
190
|
});
|
|
69
191
|
|
|
70
192
|
test('pre-unlocks an unregistered wallet business method', async () => {
|
|
@@ -160,6 +282,117 @@ describe('Protocol V2 unlock semantics', () => {
|
|
|
160
282
|
expect(device.unlockDevice).toHaveBeenCalledWith(DeviceSessionPinType.Main, expect.any(Object));
|
|
161
283
|
});
|
|
162
284
|
|
|
285
|
+
test('allows either PIN type when pre-unlocking device settings', async () => {
|
|
286
|
+
const method = new DeviceSettings({
|
|
287
|
+
id: 1,
|
|
288
|
+
payload: { method: 'deviceSettings', autoLockDelayMs: 60_000 },
|
|
289
|
+
});
|
|
290
|
+
method.init();
|
|
291
|
+
const features = { unlocked: false };
|
|
292
|
+
const device = {
|
|
293
|
+
features,
|
|
294
|
+
commands: {
|
|
295
|
+
typedCall: jest.fn().mockResolvedValue({ message: { unlocked: false } }),
|
|
296
|
+
},
|
|
297
|
+
isProtocolV2: () => true,
|
|
298
|
+
isBootloader: () => false,
|
|
299
|
+
isRomloader: () => false,
|
|
300
|
+
updateProtocolV2Status: jest.fn(() => features),
|
|
301
|
+
unlockDevice: jest.fn().mockImplementation(() => {
|
|
302
|
+
features.unlocked = true;
|
|
303
|
+
return Promise.resolve(features);
|
|
304
|
+
}),
|
|
305
|
+
};
|
|
306
|
+
method.run = jest.fn().mockResolvedValue({ message: 'ok' });
|
|
307
|
+
|
|
308
|
+
await expect(runMethodWithUnlockPolicy(method, device as any)).resolves.toEqual({
|
|
309
|
+
message: 'ok',
|
|
310
|
+
});
|
|
311
|
+
|
|
312
|
+
expect(device.unlockDevice).toHaveBeenCalledWith(DeviceSessionPinType.Any, expect.any(Object));
|
|
313
|
+
});
|
|
314
|
+
|
|
315
|
+
test.each([
|
|
316
|
+
[
|
|
317
|
+
'PIN changes',
|
|
318
|
+
() =>
|
|
319
|
+
new DeviceChangePin({
|
|
320
|
+
id: 1,
|
|
321
|
+
payload: { method: 'deviceChangePin', remove: false },
|
|
322
|
+
}),
|
|
323
|
+
],
|
|
324
|
+
['device wipe', () => new DeviceWipe({ id: 1, payload: { method: 'deviceWipe' } })],
|
|
325
|
+
[
|
|
326
|
+
'firmware updates',
|
|
327
|
+
() =>
|
|
328
|
+
new FirmwareUpdateV4({
|
|
329
|
+
id: 1,
|
|
330
|
+
payload: { method: 'firmwareUpdateV4', platform: 'desktop' } as any,
|
|
331
|
+
}),
|
|
332
|
+
],
|
|
333
|
+
[
|
|
334
|
+
'genuine-device verification',
|
|
335
|
+
() =>
|
|
336
|
+
new DeviceVerify({
|
|
337
|
+
id: 1,
|
|
338
|
+
payload: { method: 'deviceVerify', dataHex: '00' },
|
|
339
|
+
}),
|
|
340
|
+
],
|
|
341
|
+
[
|
|
342
|
+
'wallpaper uploads',
|
|
343
|
+
() =>
|
|
344
|
+
new DeviceUploadWallpaper({
|
|
345
|
+
id: 1,
|
|
346
|
+
payload: {
|
|
347
|
+
method: 'deviceUploadWallpaper',
|
|
348
|
+
jpegBase64: createJpegBase64(604, 1024),
|
|
349
|
+
},
|
|
350
|
+
}),
|
|
351
|
+
],
|
|
352
|
+
[
|
|
353
|
+
'NFT uploads',
|
|
354
|
+
() =>
|
|
355
|
+
new DeviceUploadNft({
|
|
356
|
+
id: 1,
|
|
357
|
+
payload: {
|
|
358
|
+
method: 'deviceUploadNft',
|
|
359
|
+
imageJpegBase64: createJpegBase64(540, 540),
|
|
360
|
+
thumbnailJpegBase64: createJpegBase64(263, 263),
|
|
361
|
+
title: 'NFT',
|
|
362
|
+
subtitle: '',
|
|
363
|
+
timestampMs: 1,
|
|
364
|
+
},
|
|
365
|
+
}),
|
|
366
|
+
],
|
|
367
|
+
])('allows either PIN type when pre-unlocking %s', async (_name, createMethod) => {
|
|
368
|
+
const method = createMethod();
|
|
369
|
+
method.init();
|
|
370
|
+
const features = { unlocked: false };
|
|
371
|
+
const device = {
|
|
372
|
+
features,
|
|
373
|
+
commands: {
|
|
374
|
+
typedCall: jest.fn().mockResolvedValue({ message: { unlocked: false } }),
|
|
375
|
+
},
|
|
376
|
+
isProtocolV2: () => true,
|
|
377
|
+
isBootloader: () => false,
|
|
378
|
+
isRomloader: () => false,
|
|
379
|
+
updateProtocolV2Status: jest.fn(() => features),
|
|
380
|
+
unlockDevice: jest.fn().mockImplementation(() => {
|
|
381
|
+
features.unlocked = true;
|
|
382
|
+
return Promise.resolve(features);
|
|
383
|
+
}),
|
|
384
|
+
};
|
|
385
|
+
method.run = jest.fn().mockResolvedValue({ message: 'ok' });
|
|
386
|
+
|
|
387
|
+
await expect(runMethodWithUnlockPolicy(method, device as any)).resolves.toEqual({
|
|
388
|
+
message: 'ok',
|
|
389
|
+
});
|
|
390
|
+
|
|
391
|
+
expect(method.unlockPolicy).toBe('unlock-before-run');
|
|
392
|
+
expect(method.getSupportedProtocols()).toContain('V2');
|
|
393
|
+
expect(device.unlockDevice).toHaveBeenCalledWith(DeviceSessionPinType.Any, expect.any(Object));
|
|
394
|
+
});
|
|
395
|
+
|
|
163
396
|
test('pre-unlocks a locked standard wallet before wallet-session preparation', async () => {
|
|
164
397
|
const calls: string[] = [];
|
|
165
398
|
const features = {
|