@onekeyfe/hd-core 1.2.0-alpha.67 → 1.2.0-alpha.69
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 +313 -0
- package/__tests__/DeviceCommands.test.ts +59 -13
- package/__tests__/DeviceEventRegistration.test.ts +6 -0
- package/__tests__/check-all-firmware-release-protocol-v2.test.ts +226 -3
- package/__tests__/connectSettings.test.ts +5 -47
- package/__tests__/core-initialization.test.ts +23 -0
- package/__tests__/device-connector-protocol.test.ts +81 -0
- package/__tests__/device-lifecycle-events.test.ts +105 -3
- package/__tests__/device-pool-state.test.ts +22 -0
- package/__tests__/device-settings.test.ts +39 -18
- package/__tests__/device-state-contract.test.ts +1 -0
- package/__tests__/device-state-mapper.test.ts +13 -1
- package/__tests__/device-utils.test.ts +48 -1
- package/__tests__/deviceSettings.test.ts +11 -1
- package/__tests__/deviceUploadNft.test.ts +316 -0
- package/__tests__/firmware-update/firmware-update-v2-download-before-boot.test.ts +31 -59
- package/__tests__/get-device-state.test.ts +132 -12
- package/__tests__/homescreen.test.ts +41 -1
- package/__tests__/kaspa-use-tweak-pro2.test.ts +2 -2
- package/__tests__/kaspaSignTransaction.test.ts +3 -26
- package/__tests__/logBlockEvent.test.ts +1 -1
- package/__tests__/method-protocol-support.test.ts +19 -0
- package/__tests__/open-wallet-session.test.ts +568 -37
- package/__tests__/pro2Nft.test.ts +108 -0
- package/__tests__/protocol-binding.test.ts +89 -0
- package/__tests__/protocol-v2-firmware-targets.test.ts +33 -1
- package/__tests__/protocol-v2-resources.test.ts +343 -0
- package/__tests__/protocol-v2-ui-lifecycle.test.ts +91 -0
- package/__tests__/protocol-v2-unlock-policy.test.ts +300 -37
- package/__tests__/protocol-v2.test.ts +1586 -1213
- package/__tests__/protocolV2FileWrite.test.ts +193 -0
- package/__tests__/protocolV2UiInteraction.test.ts +63 -0
- package/__tests__/public-pro2-api-boundary.test.ts +1 -0
- package/__tests__/search-devices.test.ts +12 -3
- package/__tests__/tron-sign-message-init.test.ts +2 -2
- package/__tests__/uiProgressThrottle.test.ts +74 -0
- package/__tests__/uiPromiseRegistry.test.ts +115 -0
- package/dist/api/BaseMethod.d.ts +3 -1
- package/dist/api/BaseMethod.d.ts.map +1 -1
- package/dist/api/CheckAllFirmwareRelease.d.ts +3 -1
- package/dist/api/CheckAllFirmwareRelease.d.ts.map +1 -1
- package/dist/api/DetectDeviceConnectProtocol.d.ts +7 -0
- package/dist/api/DetectDeviceConnectProtocol.d.ts.map +1 -0
- package/dist/api/FirmwareUpdate.d.ts.map +1 -1
- package/dist/api/FirmwareUpdateV2.d.ts +0 -10
- package/dist/api/FirmwareUpdateV2.d.ts.map +1 -1
- package/dist/api/FirmwareUpdateV3.d.ts +3 -7
- package/dist/api/FirmwareUpdateV3.d.ts.map +1 -1
- package/dist/api/FirmwareUpdateV4.d.ts +15 -27
- package/dist/api/FirmwareUpdateV4.d.ts.map +1 -1
- package/dist/api/GetPassphraseState.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/allnetwork/AllNetworkGetAddressBase.d.ts.map +1 -1
- package/dist/api/device/DeviceSettings.d.ts.map +1 -1
- package/dist/api/device/DeviceUnlock.d.ts +2 -2
- package/dist/api/device/DeviceUnlock.d.ts.map +1 -1
- package/dist/api/device/DeviceUpdateBootloader.d.ts +1 -5
- package/dist/api/device/DeviceUpdateBootloader.d.ts.map +1 -1
- package/dist/api/firmware/FirmwareUpdateBaseMethod.d.ts +4 -11
- package/dist/api/firmware/FirmwareUpdateBaseMethod.d.ts.map +1 -1
- package/dist/api/firmware/getBinary.d.ts +0 -7
- package/dist/api/firmware/getBinary.d.ts.map +1 -1
- package/dist/api/firmware/updateBootloader.d.ts +0 -2
- package/dist/api/firmware/updateBootloader.d.ts.map +1 -1
- package/dist/api/firmware/uploadFirmware.d.ts +1 -9
- package/dist/api/firmware/uploadFirmware.d.ts.map +1 -1
- package/dist/api/helpers/protocolV2FileWrite.d.ts +9 -0
- package/dist/api/helpers/protocolV2FileWrite.d.ts.map +1 -1
- package/dist/api/index.d.ts +2 -0
- package/dist/api/index.d.ts.map +1 -1
- package/dist/api/kaspa/KaspaGetAddress.d.ts +1 -1
- package/dist/api/kaspa/KaspaSignTransaction.d.ts +1 -1
- package/dist/api/kaspa/KaspaSignTransaction.d.ts.map +1 -1
- package/dist/api/polkadot/PolkadotGetAddress.d.ts +1 -1
- package/dist/api/polkadot/networks.d.ts +1 -1
- package/dist/api/protocol-v2/DeviceUploadNft.d.ts +31 -0
- package/dist/api/protocol-v2/DeviceUploadNft.d.ts.map +1 -0
- package/dist/api/protocol-v2/ProtocolInfoRequest.d.ts.map +1 -1
- package/dist/api/protocol-v2/helpers.d.ts.map +1 -1
- package/dist/api/solana/SolSignMessage.d.ts +1 -1
- package/dist/api/solana/SolSignOffchainMessage.d.ts +1 -1
- package/dist/api/solana/SolSignTransaction.d.ts +2 -2
- package/dist/api/stellar/StellarSignTransaction.d.ts +1 -1
- package/dist/api/sui/SuiGetAddress.d.ts +1 -1
- package/dist/api/sui/SuiGetPublicKey.d.ts +1 -1
- package/dist/api/sui/SuiSignMessage.d.ts +1 -1
- package/dist/api/sui/SuiSignTransaction.d.ts +1 -1
- package/dist/api/ton/TonGetAddress.d.ts +1 -1
- package/dist/api/ton/TonSignMessage.d.ts +1 -1
- package/dist/api/ton/TonSignProof.d.ts +1 -1
- package/dist/api/tron/TronSignMessage.d.ts +2 -2
- package/dist/api/tron/TronSignTransaction.d.ts +1 -1
- package/dist/core/deviceEventRegistration.d.ts +2 -0
- package/dist/core/deviceEventRegistration.d.ts.map +1 -1
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/uiPromiseRegistry.d.ts +6 -0
- package/dist/core/uiPromiseRegistry.d.ts.map +1 -0
- package/dist/data-manager/DataManager.d.ts +9 -4
- package/dist/data-manager/DataManager.d.ts.map +1 -1
- package/dist/data-manager/TransportManager.d.ts.map +1 -1
- package/dist/data-manager/connectSettings.d.ts.map +1 -1
- package/dist/device/Device.d.ts +29 -6
- 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 +2 -1
- package/dist/device/DeviceConnector.d.ts.map +1 -1
- package/dist/device/DevicePool.d.ts.map +1 -1
- package/dist/deviceProfile/protocolV2DeviceIdentity.d.ts.map +1 -1
- package/dist/events/device.d.ts +4 -0
- package/dist/events/device.d.ts.map +1 -1
- package/dist/events/logBlockEvent.d.ts.map +1 -1
- package/dist/events/ui-promise.d.ts +4 -2
- package/dist/events/ui-promise.d.ts.map +1 -1
- package/dist/events/ui-request.d.ts +31 -2
- package/dist/events/ui-request.d.ts.map +1 -1
- package/dist/events/ui-response.d.ts +10 -2
- package/dist/events/ui-response.d.ts.map +1 -1
- package/dist/index.d.ts +243 -247
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3135 -3785
- package/dist/inject.d.ts +6 -1
- package/dist/inject.d.ts.map +1 -1
- package/dist/lowLevelInject.d.ts.map +1 -1
- package/dist/protocols/protocol-v2/features.d.ts +0 -4
- package/dist/protocols/protocol-v2/features.d.ts.map +1 -1
- package/dist/protocols/protocol-v2/firmware.d.ts.map +1 -1
- package/dist/protocols/protocol-v2/resources.d.ts +30 -0
- package/dist/protocols/protocol-v2/resources.d.ts.map +1 -0
- package/dist/protocols/protocol-v2/uiInteraction.d.ts +7 -4
- package/dist/protocols/protocol-v2/uiInteraction.d.ts.map +1 -1
- package/dist/protocols/protocol-v2/unlockPolicy.d.ts +1 -3
- package/dist/protocols/protocol-v2/unlockPolicy.d.ts.map +1 -1
- package/dist/protocols/protocol-v2/unlockPolicyRunner.d.ts +22 -0
- package/dist/protocols/protocol-v2/unlockPolicyRunner.d.ts.map +1 -0
- package/dist/protocols/protocol-v2/walletSession.d.ts +6 -1
- package/dist/protocols/protocol-v2/walletSession.d.ts.map +1 -1
- package/dist/topLevelInject.d.ts.map +1 -1
- package/dist/types/api/checkAllFirmwareRelease.d.ts +3 -5
- package/dist/types/api/checkAllFirmwareRelease.d.ts.map +1 -1
- package/dist/types/api/detectDeviceConnectProtocol.d.ts +4 -0
- package/dist/types/api/detectDeviceConnectProtocol.d.ts.map +1 -0
- package/dist/types/api/deviceUnlock.d.ts +5 -1
- package/dist/types/api/deviceUnlock.d.ts.map +1 -1
- package/dist/types/api/deviceUpdateBootloader.d.ts +0 -6
- package/dist/types/api/deviceUpdateBootloader.d.ts.map +1 -1
- package/dist/types/api/export.d.ts +2 -4
- package/dist/types/api/export.d.ts.map +1 -1
- package/dist/types/api/firmwareUpdate.d.ts +4 -70
- package/dist/types/api/firmwareUpdate.d.ts.map +1 -1
- package/dist/types/api/index.d.ts +7 -10
- package/dist/types/api/index.d.ts.map +1 -1
- package/dist/types/api/protocolV2.d.ts +3 -0
- package/dist/types/api/protocolV2.d.ts.map +1 -1
- package/dist/types/device.d.ts +2 -2
- package/dist/types/device.d.ts.map +1 -1
- package/dist/types/params.d.ts +1 -0
- package/dist/types/params.d.ts.map +1 -1
- package/dist/types/settings.d.ts +38 -21
- package/dist/types/settings.d.ts.map +1 -1
- package/dist/utils/deviceFeaturesCompat.d.ts +0 -1
- package/dist/utils/deviceFeaturesCompat.d.ts.map +1 -1
- package/dist/utils/deviceFeaturesUtils.d.ts +4 -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.map +1 -1
- package/dist/utils/homescreen.d.ts +4 -0
- package/dist/utils/homescreen.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 +31 -0
- package/dist/utils/pro2Nft.d.ts.map +1 -0
- package/dist/utils/pro2Wallpaper.d.ts +10 -0
- package/dist/utils/pro2Wallpaper.d.ts.map +1 -1
- package/dist/utils/uiProgressThrottle.d.ts +3 -0
- package/dist/utils/uiProgressThrottle.d.ts.map +1 -0
- package/package.json +4 -4
- package/src/api/BaseMethod.ts +8 -10
- package/src/api/CheckAllFirmwareRelease.ts +78 -64
- package/src/api/DetectDeviceConnectProtocol.ts +18 -0
- package/src/api/FirmwareUpdate.ts +7 -15
- package/src/api/FirmwareUpdateV2.ts +126 -298
- package/src/api/FirmwareUpdateV3.ts +63 -265
- package/src/api/FirmwareUpdateV4.ts +645 -1018
- package/src/api/GetPassphraseState.ts +7 -1
- package/src/api/OpenWalletSession.ts +71 -17
- package/src/api/SearchDevices.ts +3 -1
- package/src/api/allnetwork/AllNetworkGetAddress.ts +21 -21
- package/src/api/allnetwork/AllNetworkGetAddressBase.ts +36 -11
- package/src/api/device/DeviceSettings.ts +5 -4
- package/src/api/device/DeviceUnlock.ts +8 -3
- package/src/api/device/DeviceUpdateBootloader.ts +6 -125
- package/src/api/firmware/FirmwareUpdateBaseMethod.ts +27 -83
- package/src/api/firmware/updateBootloader.ts +4 -19
- package/src/api/firmware/uploadFirmware.ts +39 -144
- package/src/api/helpers/protocolV2FileWrite.ts +252 -63
- package/src/api/index.ts +2 -0
- package/src/api/kaspa/KaspaGetAddress.ts +1 -1
- package/src/api/kaspa/KaspaSignTransaction.ts +2 -13
- package/src/api/polkadot/networks.ts +3 -3
- package/src/api/protocol-v2/DeviceUploadNft.ts +197 -0
- package/src/api/protocol-v2/ProtocolInfoRequest.ts +3 -1
- package/src/api/protocol-v2/helpers.ts +1 -1
- package/src/api/solana/SolSignMessage.ts +1 -1
- package/src/api/solana/SolSignOffchainMessage.ts +1 -1
- package/src/api/solana/SolSignTransaction.ts +2 -2
- package/src/api/sui/SuiGetAddress.ts +1 -1
- package/src/api/sui/SuiGetPublicKey.ts +1 -1
- package/src/api/sui/SuiSignMessage.ts +1 -1
- package/src/api/sui/SuiSignTransaction.ts +1 -1
- package/src/api/ton/TonGetAddress.ts +1 -1
- package/src/api/ton/TonSignMessage.ts +1 -1
- package/src/api/ton/TonSignProof.ts +1 -1
- package/src/api/tron/TronSignMessage.ts +2 -2
- package/src/api/tron/TronSignTransaction.ts +1 -1
- package/src/core/deviceEventRegistration.ts +4 -0
- package/src/core/index.ts +213 -111
- package/src/core/uiPromiseRegistry.ts +63 -0
- package/src/data/messages/messages-protocol-v2.json +25 -0
- package/src/data-manager/DataManager.ts +113 -41
- package/src/data-manager/TransportManager.ts +6 -0
- package/src/data-manager/connectSettings.ts +0 -11
- package/src/device/Device.ts +274 -49
- package/src/device/DeviceCommands.ts +31 -4
- package/src/device/DeviceConnector.ts +33 -13
- package/src/device/DevicePool.ts +21 -7
- package/src/deviceProfile/buildDeviceFeatures.ts +2 -2
- package/src/deviceProfile/protocolV2DeviceIdentity.ts +3 -0
- package/src/events/device.ts +4 -0
- package/src/events/logBlockEvent.ts +1 -0
- package/src/events/ui-promise.ts +4 -2
- package/src/events/ui-request.ts +36 -2
- package/src/events/ui-response.ts +12 -2
- package/src/index.ts +0 -5
- package/src/inject.ts +60 -24
- package/src/lowLevelInject.ts +7 -8
- package/src/protocols/protocol-v2/features.ts +10 -7
- package/src/protocols/protocol-v2/firmware.ts +2 -0
- package/src/protocols/protocol-v2/resources.ts +394 -0
- package/src/protocols/protocol-v2/uiInteraction.ts +46 -6
- package/src/protocols/protocol-v2/unlockPolicy.ts +1 -105
- package/src/protocols/protocol-v2/unlockPolicyRunner.ts +131 -0
- package/src/protocols/protocol-v2/walletSession.ts +214 -36
- package/src/topLevelInject.ts +7 -8
- package/src/types/api/checkAllFirmwareRelease.ts +3 -5
- package/src/types/api/detectDeviceConnectProtocol.ts +6 -0
- package/src/types/api/deviceUnlock.ts +12 -1
- package/src/types/api/deviceUpdateBootloader.ts +0 -6
- package/src/types/api/export.ts +1 -18
- package/src/types/api/firmwareUpdate.ts +6 -78
- package/src/types/api/index.ts +13 -14
- package/src/types/api/protocolV2.ts +13 -0
- package/src/types/device.ts +15 -3
- package/src/types/params.ts +7 -1
- package/src/types/settings.ts +61 -22
- package/src/utils/deviceFeaturesCompat.ts +5 -6
- package/src/utils/deviceFeaturesUtils.ts +14 -3
- package/src/utils/deviceInfoUtils.ts +2 -0
- package/src/utils/deviceSettings.ts +3 -0
- package/src/utils/homescreen.ts +32 -6
- package/src/utils/index.ts +6 -1
- package/src/utils/pro2Nft.ts +142 -0
- package/src/utils/pro2Wallpaper.ts +35 -8
- package/src/utils/uiProgressThrottle.ts +63 -0
- package/__tests__/device-initialize-timeout.test.ts +0 -56
- package/__tests__/firmware-update/check-all-firmware-release.test.ts +0 -175
- package/__tests__/firmware-update/device-update-bootloader.test.ts +0 -87
- package/__tests__/firmware-update/firmware-artifact-source.test.ts +0 -119
- package/__tests__/firmware-update/firmware-host-binding.test.ts +0 -70
- package/__tests__/firmware-update/firmware-preparation-error.test.ts +0 -27
- package/__tests__/firmware-update/firmware-update-bootloader-poll.test.ts +0 -200
- package/__tests__/firmware-update/firmware-update-capabilities.test.ts +0 -13
- package/__tests__/firmware-update/firmware-update-plan-bootloader-identity.test.ts +0 -394
- package/__tests__/firmware-update/firmware-update-plan.test.ts +0 -593
- package/__tests__/firmware-update/firmware-update-prepared-plan.test.ts +0 -231
- package/__tests__/firmware-update/firmware-update-v3-reconnect.test.ts +0 -58
- package/__tests__/firmware-update/firmware-upload-source.test.ts +0 -70
- package/dist/api/firmware/FirmwareArtifactSource.d.ts +0 -25
- package/dist/api/firmware/FirmwareArtifactSource.d.ts.map +0 -1
- package/dist/api/firmware/FirmwareHostBinding.d.ts +0 -6
- package/dist/api/firmware/FirmwareHostBinding.d.ts.map +0 -1
- package/dist/api/firmware/FirmwarePreparationError.d.ts +0 -3
- package/dist/api/firmware/FirmwarePreparationError.d.ts.map +0 -1
- package/dist/api/firmware/FirmwareUpdateCapabilities.d.ts +0 -3
- package/dist/api/firmware/FirmwareUpdateCapabilities.d.ts.map +0 -1
- package/dist/api/firmware/FirmwareUpdatePlan.d.ts +0 -25
- package/dist/api/firmware/FirmwareUpdatePlan.d.ts.map +0 -1
- package/dist/api/firmware/FirmwareUpdatePreparedPlan.d.ts +0 -32
- package/dist/api/firmware/FirmwareUpdatePreparedPlan.d.ts.map +0 -1
- package/dist/api/firmware/progressThrottle.d.ts +0 -3
- package/dist/api/firmware/progressThrottle.d.ts.map +0 -1
- package/dist/protocols/protocol-v2/lockedError.d.ts +0 -2
- package/dist/protocols/protocol-v2/lockedError.d.ts.map +0 -1
- package/dist/protocols/protocol-v2/unlockRetry.d.ts +0 -10
- package/dist/protocols/protocol-v2/unlockRetry.d.ts.map +0 -1
- package/dist/types/api/firmwareUpdateCapabilities.d.ts +0 -9
- package/dist/types/api/firmwareUpdateCapabilities.d.ts.map +0 -1
- package/dist/types/api/firmwareUpdatePlan.d.ts +0 -28
- package/dist/types/api/firmwareUpdatePlan.d.ts.map +0 -1
- package/dist/types/api/firmwareUpdatePreparedPlan.d.ts +0 -42
- package/dist/types/api/firmwareUpdatePreparedPlan.d.ts.map +0 -1
- package/src/api/firmware/FirmwareArtifactSource.ts +0 -278
- package/src/api/firmware/FirmwareHostBinding.ts +0 -100
- package/src/api/firmware/FirmwarePreparationError.ts +0 -12
- package/src/api/firmware/FirmwareUpdateCapabilities.ts +0 -9
- package/src/api/firmware/FirmwareUpdatePlan.ts +0 -772
- package/src/api/firmware/FirmwareUpdatePreparedPlan.ts +0 -449
- package/src/api/firmware/progressThrottle.ts +0 -44
- package/src/protocols/protocol-v2/lockedError.ts +0 -10
- package/src/protocols/protocol-v2/unlockRetry.ts +0 -109
- package/src/types/api/firmwareUpdateCapabilities.ts +0 -9
- package/src/types/api/firmwareUpdatePlan.ts +0 -38
- package/src/types/api/firmwareUpdatePreparedPlan.ts +0 -53
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import { blake2s } from '@noble/hashes/blake2s';
|
|
2
|
+
import { bytesToHex } from '@noble/hashes/utils';
|
|
3
|
+
|
|
4
|
+
import { invalidParameter } from '../api/helpers/filesystemValidation';
|
|
5
|
+
import { encodePro2Image } from './pro2Wallpaper';
|
|
6
|
+
|
|
7
|
+
export const PRO2_NFT_IMAGE_WIDTH = 540;
|
|
8
|
+
export const PRO2_NFT_IMAGE_HEIGHT = 540;
|
|
9
|
+
export const PRO2_NFT_THUMBNAIL_WIDTH = 263;
|
|
10
|
+
export const PRO2_NFT_THUMBNAIL_HEIGHT = 263;
|
|
11
|
+
export const PRO2_NFT_DIRECTORY = 'vol1:/nft';
|
|
12
|
+
export const PRO2_NFT_DEFAULT_CHUNK_SIZE = 2048;
|
|
13
|
+
export const PRO2_NFT_DEFAULT_PACE_MS = 0;
|
|
14
|
+
export const PRO2_NFT_DEFAULT_TIMEOUT_MS = 15_000;
|
|
15
|
+
export const PRO2_NFT_MIN_CHUNK_SIZE = 64;
|
|
16
|
+
export const PRO2_NFT_MAX_CHUNK_SIZE = 2048;
|
|
17
|
+
export const PRO2_NFT_MAX_ITEMS = 10;
|
|
18
|
+
|
|
19
|
+
export type Pro2NftImage = {
|
|
20
|
+
width: number;
|
|
21
|
+
height: number;
|
|
22
|
+
rgba: Uint8Array | ArrayBuffer;
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export type Pro2NftBundle = {
|
|
26
|
+
basename: string;
|
|
27
|
+
image: Uint8Array;
|
|
28
|
+
thumbnail: Uint8Array;
|
|
29
|
+
metadata: Uint8Array;
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
const PRO2_NFT_BASENAME_PATTERN = /^nft-[0-9a-f]{8}-[1-9][0-9]*$/;
|
|
33
|
+
|
|
34
|
+
type Pro2NftFileType = 'image' | 'thumbnail' | 'metadata';
|
|
35
|
+
|
|
36
|
+
function parsePro2NftFile(listedPath: string):
|
|
37
|
+
| {
|
|
38
|
+
basename: string;
|
|
39
|
+
fileType: Pro2NftFileType;
|
|
40
|
+
}
|
|
41
|
+
| undefined {
|
|
42
|
+
const filename = listedPath.trim().split('/').at(-1);
|
|
43
|
+
if (!filename) return undefined;
|
|
44
|
+
|
|
45
|
+
let basename: string | undefined;
|
|
46
|
+
let fileType: Pro2NftFileType | undefined;
|
|
47
|
+
if (filename.endsWith('_m.bin')) {
|
|
48
|
+
basename = filename.slice(0, -'_m.bin'.length);
|
|
49
|
+
fileType = 'thumbnail';
|
|
50
|
+
} else if (filename.endsWith('.json')) {
|
|
51
|
+
basename = filename.slice(0, -'.json'.length);
|
|
52
|
+
fileType = 'metadata';
|
|
53
|
+
} else if (filename.endsWith('.bin')) {
|
|
54
|
+
basename = filename.slice(0, -'.bin'.length);
|
|
55
|
+
fileType = 'image';
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
return basename && fileType && PRO2_NFT_BASENAME_PATTERN.test(basename)
|
|
59
|
+
? { basename, fileType }
|
|
60
|
+
: undefined;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export function getCompletePro2NftBasenames(childFiles?: string): Set<string> {
|
|
64
|
+
const filesByBasename = new Map<string, Set<Pro2NftFileType>>();
|
|
65
|
+
|
|
66
|
+
for (const listedPath of childFiles?.split('\n') ?? []) {
|
|
67
|
+
const file = parsePro2NftFile(listedPath);
|
|
68
|
+
if (file) {
|
|
69
|
+
const fileTypes = filesByBasename.get(file.basename) ?? new Set<Pro2NftFileType>();
|
|
70
|
+
fileTypes.add(file.fileType);
|
|
71
|
+
filesByBasename.set(file.basename, fileTypes);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
return new Set(
|
|
76
|
+
[...filesByBasename.entries()]
|
|
77
|
+
.filter(([, fileTypes]) => fileTypes.size === 3)
|
|
78
|
+
.map(([basename]) => basename)
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function utf8Length(value: string): number {
|
|
83
|
+
return new TextEncoder().encode(value).byteLength;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function assertImage(
|
|
87
|
+
name: string,
|
|
88
|
+
image: Pro2NftImage,
|
|
89
|
+
expectedWidth: number,
|
|
90
|
+
expectedHeight: number
|
|
91
|
+
) {
|
|
92
|
+
if (image.width !== expectedWidth || image.height !== expectedHeight) {
|
|
93
|
+
throw invalidParameter(
|
|
94
|
+
`Pro2 NFT ${name} dimensions must be ${expectedWidth}x${expectedHeight}.`
|
|
95
|
+
);
|
|
96
|
+
}
|
|
97
|
+
if (!(image.rgba instanceof ArrayBuffer) && !ArrayBuffer.isView(image.rgba)) {
|
|
98
|
+
throw invalidParameter(`Parameter [${name}.rgba] must be an ArrayBuffer or Uint8Array.`);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
export function buildPro2NftBundle(options: {
|
|
103
|
+
image: Pro2NftImage;
|
|
104
|
+
thumbnail: Pro2NftImage;
|
|
105
|
+
title: string;
|
|
106
|
+
subtitle: string;
|
|
107
|
+
timestampMs: number;
|
|
108
|
+
}): Pro2NftBundle {
|
|
109
|
+
const { image, thumbnail, title, subtitle, timestampMs } = options;
|
|
110
|
+
assertImage('image', image, PRO2_NFT_IMAGE_WIDTH, PRO2_NFT_IMAGE_HEIGHT);
|
|
111
|
+
assertImage('thumbnail', thumbnail, PRO2_NFT_THUMBNAIL_WIDTH, PRO2_NFT_THUMBNAIL_HEIGHT);
|
|
112
|
+
const titleLength = typeof title === 'string' ? utf8Length(title) : 0;
|
|
113
|
+
const subtitleLength =
|
|
114
|
+
typeof subtitle === 'string' ? utf8Length(subtitle) : Number.POSITIVE_INFINITY;
|
|
115
|
+
if (titleLength < 1 || titleLength > 63) {
|
|
116
|
+
throw invalidParameter('Pro2 NFT title must contain 1 to 63 UTF-8 bytes.');
|
|
117
|
+
}
|
|
118
|
+
if (subtitleLength > 95) {
|
|
119
|
+
throw invalidParameter('Pro2 NFT subtitle must contain at most 95 UTF-8 bytes.');
|
|
120
|
+
}
|
|
121
|
+
if (!Number.isSafeInteger(timestampMs) || timestampMs <= 0) {
|
|
122
|
+
throw invalidParameter('Parameter [timestampMs] must be a positive safe integer.');
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
const encodedImage = encodePro2Image({ ...image, alphaMode: 'black-background' }).data;
|
|
126
|
+
const encodedThumbnail = encodePro2Image({
|
|
127
|
+
...thumbnail,
|
|
128
|
+
alphaMode: 'black-background',
|
|
129
|
+
}).data;
|
|
130
|
+
const metadata = new TextEncoder().encode(JSON.stringify({ title, subtitle }));
|
|
131
|
+
if (metadata.byteLength === 0 || metadata.byteLength > 512) {
|
|
132
|
+
throw invalidParameter('Pro2 NFT metadata must contain 1 to 512 UTF-8 bytes.');
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
const hash8 = bytesToHex(blake2s(encodedImage)).slice(0, 8);
|
|
136
|
+
return {
|
|
137
|
+
basename: `nft-${hash8}-${timestampMs}`,
|
|
138
|
+
image: encodedImage,
|
|
139
|
+
thumbnail: encodedThumbnail,
|
|
140
|
+
metadata,
|
|
141
|
+
};
|
|
142
|
+
}
|
|
@@ -8,6 +8,8 @@ export const PRO2_WALLPAPER_HEIGHT = 1024;
|
|
|
8
8
|
|
|
9
9
|
export type Pro2WallpaperColorFormat = 'RGB565' | 'RGB565A8';
|
|
10
10
|
|
|
11
|
+
export type Pro2ImageAlphaMode = 'preserve' | 'black-background';
|
|
12
|
+
|
|
11
13
|
const COLOR_FORMAT_RGB565 = 0x12;
|
|
12
14
|
const COLOR_FORMAT_RGB565A8 = 0x14;
|
|
13
15
|
|
|
@@ -36,10 +38,11 @@ function align(value: number, boundary: number): number {
|
|
|
36
38
|
return Math.ceil(value / boundary) * boundary;
|
|
37
39
|
}
|
|
38
40
|
|
|
39
|
-
export function
|
|
41
|
+
export function encodePro2Image(options: {
|
|
40
42
|
width: number;
|
|
41
43
|
height: number;
|
|
42
44
|
rgba: Uint8Array | ArrayBuffer;
|
|
45
|
+
alphaMode?: Pro2ImageAlphaMode;
|
|
43
46
|
}): { data: Uint8Array; colorFormat: Pro2WallpaperColorFormat } {
|
|
44
47
|
const { width, height } = options;
|
|
45
48
|
if (!Number.isInteger(width) || width <= 0 || width > 0xffff) {
|
|
@@ -57,11 +60,14 @@ export function encodePro2Wallpaper(options: {
|
|
|
57
60
|
);
|
|
58
61
|
}
|
|
59
62
|
|
|
63
|
+
const alphaMode = options.alphaMode ?? 'preserve';
|
|
60
64
|
let hasTransparency = false;
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
+
if (alphaMode === 'preserve') {
|
|
66
|
+
for (let index = 3; index < rgba.length; index += 4) {
|
|
67
|
+
if (rgba[index] !== 0xff) {
|
|
68
|
+
hasTransparency = true;
|
|
69
|
+
break;
|
|
70
|
+
}
|
|
65
71
|
}
|
|
66
72
|
}
|
|
67
73
|
|
|
@@ -85,9 +91,22 @@ export function encodePro2Wallpaper(options: {
|
|
|
85
91
|
for (let x = 0; x < width; x += 1) {
|
|
86
92
|
const sourceOffset = (y * width + x) * 4;
|
|
87
93
|
const thresholdIndex = ((y & 7) << 3) + (x & 7);
|
|
88
|
-
const
|
|
89
|
-
const
|
|
90
|
-
|
|
94
|
+
const alpha = rgba[sourceOffset + 3];
|
|
95
|
+
const redChannel =
|
|
96
|
+
alphaMode === 'black-background'
|
|
97
|
+
? Math.round((rgba[sourceOffset] * alpha) / 0xff)
|
|
98
|
+
: rgba[sourceOffset];
|
|
99
|
+
const greenChannel =
|
|
100
|
+
alphaMode === 'black-background'
|
|
101
|
+
? Math.round((rgba[sourceOffset + 1] * alpha) / 0xff)
|
|
102
|
+
: rgba[sourceOffset + 1];
|
|
103
|
+
const blueChannel =
|
|
104
|
+
alphaMode === 'black-background'
|
|
105
|
+
? Math.round((rgba[sourceOffset + 2] * alpha) / 0xff)
|
|
106
|
+
: rgba[sourceOffset + 2];
|
|
107
|
+
const red = Math.min(redChannel + RED_THRESHOLD[thresholdIndex], 0xff) & 0xf8;
|
|
108
|
+
const green = Math.min(greenChannel + GREEN_THRESHOLD[thresholdIndex], 0xff) & 0xfc;
|
|
109
|
+
const blue = Math.min(blueChannel + BLUE_THRESHOLD[thresholdIndex], 0xff) & 0xf8;
|
|
91
110
|
const rgb565 = ((red >> 3) << 11) | ((green >> 2) << 5) | (blue >> 3);
|
|
92
111
|
const rgbOffset = 12 + y * stride + x * 2;
|
|
93
112
|
data[rgbOffset] = rgb565 & 0xff;
|
|
@@ -101,3 +120,11 @@ export function encodePro2Wallpaper(options: {
|
|
|
101
120
|
|
|
102
121
|
return { data, colorFormat };
|
|
103
122
|
}
|
|
123
|
+
|
|
124
|
+
export function encodePro2Wallpaper(options: {
|
|
125
|
+
width: number;
|
|
126
|
+
height: number;
|
|
127
|
+
rgba: Uint8Array | ArrayBuffer;
|
|
128
|
+
}): { data: Uint8Array; colorFormat: Pro2WallpaperColorFormat } {
|
|
129
|
+
return encodePro2Image(options);
|
|
130
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { UI_EVENT, UI_REQUEST } from '../events/ui-request';
|
|
2
|
+
|
|
3
|
+
import type { CoreMessage } from '../events';
|
|
4
|
+
|
|
5
|
+
const DEFAULT_UI_PROGRESS_INTERVAL_MS = 250;
|
|
6
|
+
|
|
7
|
+
type UiProgressThrottleState = {
|
|
8
|
+
lastEmittedAt: number;
|
|
9
|
+
lastProgress?: number;
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
const normalizeProgress = (progress: unknown) => {
|
|
13
|
+
if (typeof progress !== 'number' || !Number.isFinite(progress)) {
|
|
14
|
+
return undefined;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
return Math.max(0, Math.min(100, Math.floor(progress)));
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export const createUiProgressMessageFilter = (
|
|
21
|
+
intervalMs = DEFAULT_UI_PROGRESS_INTERVAL_MS,
|
|
22
|
+
now = Date.now
|
|
23
|
+
) => {
|
|
24
|
+
const stateByType = new Map<string, UiProgressThrottleState>();
|
|
25
|
+
|
|
26
|
+
return (message: CoreMessage) => {
|
|
27
|
+
if (
|
|
28
|
+
!('event' in message) ||
|
|
29
|
+
message.event !== UI_EVENT ||
|
|
30
|
+
(message.type !== UI_REQUEST.DEVICE_PROGRESS && message.type !== UI_REQUEST.FIRMWARE_PROGRESS)
|
|
31
|
+
) {
|
|
32
|
+
return true;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const key =
|
|
36
|
+
message.type === UI_REQUEST.FIRMWARE_PROGRESS
|
|
37
|
+
? `${message.type}:${message.payload.progressType}`
|
|
38
|
+
: message.type;
|
|
39
|
+
const progress = normalizeProgress(message.payload.progress);
|
|
40
|
+
const currentTime = now();
|
|
41
|
+
const state = stateByType.get(key);
|
|
42
|
+
|
|
43
|
+
if (!state) {
|
|
44
|
+
stateByType.set(key, { lastEmittedAt: currentTime, lastProgress: progress });
|
|
45
|
+
return true;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const isBoundary = progress === 0 || progress === 100;
|
|
49
|
+
if (isBoundary && progress === state.lastProgress) {
|
|
50
|
+
return false;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const startsNewPhase =
|
|
54
|
+
progress !== undefined && state.lastProgress !== undefined && progress < state.lastProgress;
|
|
55
|
+
|
|
56
|
+
if (!isBoundary && !startsNewPhase && currentTime - state.lastEmittedAt < intervalMs) {
|
|
57
|
+
return false;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
stateByType.set(key, { lastEmittedAt: currentTime, lastProgress: progress });
|
|
61
|
+
return true;
|
|
62
|
+
};
|
|
63
|
+
};
|
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
import { Device } from '../src/device/Device';
|
|
2
|
-
import TransportManager from '../src/data-manager/TransportManager';
|
|
3
|
-
|
|
4
|
-
jest.mock('../src/data/config', () => ({
|
|
5
|
-
getSDKVersion: jest.fn(() => '1.0.0'),
|
|
6
|
-
DEFAULT_DOMAIN: 'https://jssdk.onekey.so/1.0.0/',
|
|
7
|
-
}));
|
|
8
|
-
|
|
9
|
-
function buildV1Device() {
|
|
10
|
-
const device = Object.create(Device.prototype) as Device;
|
|
11
|
-
const typedCall = jest.fn(() => Promise.resolve({ message: { device_id: 'device' } }));
|
|
12
|
-
Object.assign(device, {
|
|
13
|
-
commands: { typedCall },
|
|
14
|
-
stateStore: { getState: () => undefined },
|
|
15
|
-
isProtocolV2: () => false,
|
|
16
|
-
_updateFeatures: jest.fn(),
|
|
17
|
-
getInternalState: jest.fn(() => undefined),
|
|
18
|
-
});
|
|
19
|
-
return { device, typedCall };
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
describe('Device.initialize Protocol V1 timeout', () => {
|
|
23
|
-
beforeEach(() => {
|
|
24
|
-
jest.spyOn(TransportManager, 'reconfigure').mockResolvedValue(undefined);
|
|
25
|
-
});
|
|
26
|
-
|
|
27
|
-
afterEach(() => {
|
|
28
|
-
jest.restoreAllMocks();
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
test('passes a custom Initialize timeout through to typedCall', async () => {
|
|
32
|
-
const { device, typedCall } = buildV1Device();
|
|
33
|
-
|
|
34
|
-
await device.initialize({ timeoutMs: 2500 });
|
|
35
|
-
|
|
36
|
-
expect(typedCall).toHaveBeenCalledWith(
|
|
37
|
-
'Initialize',
|
|
38
|
-
'Features',
|
|
39
|
-
expect.objectContaining({ is_contains_attach: true }),
|
|
40
|
-
{ timeoutMs: 2500 }
|
|
41
|
-
);
|
|
42
|
-
});
|
|
43
|
-
|
|
44
|
-
test('keeps the 25s Initialize timeout by default', async () => {
|
|
45
|
-
const { device, typedCall } = buildV1Device();
|
|
46
|
-
|
|
47
|
-
await device.initialize();
|
|
48
|
-
|
|
49
|
-
expect(typedCall).toHaveBeenCalledWith(
|
|
50
|
-
'Initialize',
|
|
51
|
-
'Features',
|
|
52
|
-
expect.objectContaining({ is_contains_attach: true }),
|
|
53
|
-
{ timeoutMs: 25 * 1000 }
|
|
54
|
-
);
|
|
55
|
-
});
|
|
56
|
-
});
|
|
@@ -1,175 +0,0 @@
|
|
|
1
|
-
import { EDeviceType, EFirmwareType, ERRORS, HardwareErrorCode } from '@onekeyfe/hd-shared';
|
|
2
|
-
|
|
3
|
-
import CheckAllFirmwareRelease from '../../src/api/CheckAllFirmwareRelease';
|
|
4
|
-
import { buildFirmwareUpdatePlan } from '../../src/api/firmware/FirmwareUpdatePlan';
|
|
5
|
-
import {
|
|
6
|
-
getBleFirmwareReleaseInfo,
|
|
7
|
-
getBootloaderReleaseInfo,
|
|
8
|
-
getFirmwareReleaseInfo,
|
|
9
|
-
} from '../../src/api/firmware/releaseHelper';
|
|
10
|
-
|
|
11
|
-
jest.mock('../../src/data/config', () => ({
|
|
12
|
-
getSDKVersion: jest.fn(() => '1.0.0'),
|
|
13
|
-
DEFAULT_DOMAIN: 'https://jssdk.onekey.so/1.0.0/',
|
|
14
|
-
}));
|
|
15
|
-
|
|
16
|
-
jest.mock('../../src/api/firmware/FirmwareUpdatePlan', () => ({
|
|
17
|
-
buildFirmwareUpdatePlan: jest.fn(),
|
|
18
|
-
validateFirmwareUpdatePlanForceTargets: jest.fn(value => value ?? []),
|
|
19
|
-
}));
|
|
20
|
-
|
|
21
|
-
jest.mock('../../src/api/firmware/releaseHelper', () => ({
|
|
22
|
-
getBleFirmwareReleaseInfo: jest.fn(),
|
|
23
|
-
getBootloaderReleaseInfo: jest.fn(),
|
|
24
|
-
getFirmwareReleaseInfo: jest.fn(),
|
|
25
|
-
}));
|
|
26
|
-
|
|
27
|
-
const mockBuildFirmwareUpdatePlan = buildFirmwareUpdatePlan as jest.MockedFunction<
|
|
28
|
-
typeof buildFirmwareUpdatePlan
|
|
29
|
-
>;
|
|
30
|
-
const mockGetBleFirmwareReleaseInfo = getBleFirmwareReleaseInfo as jest.MockedFunction<
|
|
31
|
-
typeof getBleFirmwareReleaseInfo
|
|
32
|
-
>;
|
|
33
|
-
const mockGetBootloaderReleaseInfo = getBootloaderReleaseInfo as jest.MockedFunction<
|
|
34
|
-
typeof getBootloaderReleaseInfo
|
|
35
|
-
>;
|
|
36
|
-
const mockGetFirmwareReleaseInfo = getFirmwareReleaseInfo as jest.MockedFunction<
|
|
37
|
-
typeof getFirmwareReleaseInfo
|
|
38
|
-
>;
|
|
39
|
-
|
|
40
|
-
const noUpdate = {
|
|
41
|
-
status: 'valid' as const,
|
|
42
|
-
release: undefined,
|
|
43
|
-
};
|
|
44
|
-
|
|
45
|
-
const createMethod = (serialNo = 'device-id') => {
|
|
46
|
-
const method = new CheckAllFirmwareRelease({
|
|
47
|
-
id: 1,
|
|
48
|
-
payload: {
|
|
49
|
-
method: 'checkAllFirmwareRelease',
|
|
50
|
-
platform: 'native',
|
|
51
|
-
},
|
|
52
|
-
});
|
|
53
|
-
method.init();
|
|
54
|
-
method.device = {
|
|
55
|
-
isProtocolV2: jest.fn(() => false),
|
|
56
|
-
features: {
|
|
57
|
-
deviceType: EDeviceType.Classic1s,
|
|
58
|
-
serialNo,
|
|
59
|
-
firmwareType: EFirmwareType.Universal,
|
|
60
|
-
firmwareVersion: '1.0.0',
|
|
61
|
-
bootloaderVersion: '1.0.0',
|
|
62
|
-
},
|
|
63
|
-
} as typeof method.device;
|
|
64
|
-
return method;
|
|
65
|
-
};
|
|
66
|
-
|
|
67
|
-
const createMethodWithForceTargets = () => {
|
|
68
|
-
const method = createMethod();
|
|
69
|
-
method.payload = {
|
|
70
|
-
...method.payload,
|
|
71
|
-
forceUpdateTargets: ['firmware', 'resource'],
|
|
72
|
-
};
|
|
73
|
-
return method;
|
|
74
|
-
};
|
|
75
|
-
|
|
76
|
-
describe('CheckAllFirmwareRelease', () => {
|
|
77
|
-
beforeEach(() => {
|
|
78
|
-
jest.clearAllMocks();
|
|
79
|
-
mockGetFirmwareReleaseInfo.mockReturnValue(noUpdate);
|
|
80
|
-
mockGetBootloaderReleaseInfo.mockReturnValue(noUpdate);
|
|
81
|
-
mockGetBleFirmwareReleaseInfo.mockReturnValue(noUpdate);
|
|
82
|
-
});
|
|
83
|
-
|
|
84
|
-
test('keeps release information available when an optional Plan cannot be built', async () => {
|
|
85
|
-
const firmware = {
|
|
86
|
-
status: 'outdated' as const,
|
|
87
|
-
release: {
|
|
88
|
-
url: 'https://firmware.onekey.so/classic/firmware.bin',
|
|
89
|
-
version: [3, 0, 0],
|
|
90
|
-
},
|
|
91
|
-
};
|
|
92
|
-
mockGetFirmwareReleaseInfo.mockReturnValue(firmware);
|
|
93
|
-
mockBuildFirmwareUpdatePlan.mockImplementation(() => {
|
|
94
|
-
throw ERRORS.TypedError(HardwareErrorCode.RuntimeError, 'Plan cannot be built', {
|
|
95
|
-
firmwareUpdateCode: 'FirmwarePlanInvalid',
|
|
96
|
-
});
|
|
97
|
-
});
|
|
98
|
-
|
|
99
|
-
await expect(createMethod('').run()).resolves.toEqual(
|
|
100
|
-
expect.objectContaining({
|
|
101
|
-
firmware,
|
|
102
|
-
bootloader: noUpdate,
|
|
103
|
-
ble: noUpdate,
|
|
104
|
-
firmwareUpdatePlan: undefined,
|
|
105
|
-
})
|
|
106
|
-
);
|
|
107
|
-
});
|
|
108
|
-
|
|
109
|
-
test('returns an optional Plan when the builder succeeds', async () => {
|
|
110
|
-
const plan = {
|
|
111
|
-
schemaVersion: 2 as const,
|
|
112
|
-
planDigest: 'a'.repeat(64),
|
|
113
|
-
executor: 'v3' as const,
|
|
114
|
-
deviceIdentity: 'device-id',
|
|
115
|
-
deviceModel: EDeviceType.Classic1s,
|
|
116
|
-
firmwareType: EFirmwareType.Universal,
|
|
117
|
-
platform: 'native' as const,
|
|
118
|
-
artifacts: [],
|
|
119
|
-
targetsToUpdate: [],
|
|
120
|
-
};
|
|
121
|
-
mockBuildFirmwareUpdatePlan.mockReturnValue(plan);
|
|
122
|
-
|
|
123
|
-
await expect(createMethod().run()).resolves.toEqual(
|
|
124
|
-
expect.objectContaining({
|
|
125
|
-
firmwareUpdatePlan: plan,
|
|
126
|
-
})
|
|
127
|
-
);
|
|
128
|
-
});
|
|
129
|
-
|
|
130
|
-
test('passes host-selected update targets to the Plan builder', async () => {
|
|
131
|
-
mockBuildFirmwareUpdatePlan.mockReturnValue({
|
|
132
|
-
schemaVersion: 2,
|
|
133
|
-
planDigest: 'a'.repeat(64),
|
|
134
|
-
executor: 'v2',
|
|
135
|
-
deviceIdentity: 'device-id',
|
|
136
|
-
deviceModel: EDeviceType.Classic1s,
|
|
137
|
-
firmwareType: EFirmwareType.Universal,
|
|
138
|
-
platform: 'native',
|
|
139
|
-
artifacts: [],
|
|
140
|
-
targetsToUpdate: [],
|
|
141
|
-
});
|
|
142
|
-
|
|
143
|
-
await createMethodWithForceTargets().run();
|
|
144
|
-
|
|
145
|
-
expect(mockBuildFirmwareUpdatePlan).toHaveBeenCalledWith(
|
|
146
|
-
expect.objectContaining({
|
|
147
|
-
forceUpdateTargets: ['firmware', 'resource'],
|
|
148
|
-
})
|
|
149
|
-
);
|
|
150
|
-
});
|
|
151
|
-
|
|
152
|
-
test('does not hide a Plan failure for an explicitly forced target', async () => {
|
|
153
|
-
const planError = ERRORS.TypedError(
|
|
154
|
-
HardwareErrorCode.RuntimeError,
|
|
155
|
-
'Forced firmware target is unavailable',
|
|
156
|
-
{
|
|
157
|
-
firmwareUpdateCode: 'FirmwarePlanInvalid',
|
|
158
|
-
}
|
|
159
|
-
);
|
|
160
|
-
mockBuildFirmwareUpdatePlan.mockImplementation(() => {
|
|
161
|
-
throw planError;
|
|
162
|
-
});
|
|
163
|
-
|
|
164
|
-
await expect(createMethodWithForceTargets().run()).rejects.toBe(planError);
|
|
165
|
-
});
|
|
166
|
-
|
|
167
|
-
test('does not hide unexpected Plan builder failures', async () => {
|
|
168
|
-
const unexpectedError = new Error('unexpected builder failure');
|
|
169
|
-
mockBuildFirmwareUpdatePlan.mockImplementation(() => {
|
|
170
|
-
throw unexpectedError;
|
|
171
|
-
});
|
|
172
|
-
|
|
173
|
-
await expect(createMethod().run()).rejects.toBe(unexpectedError);
|
|
174
|
-
});
|
|
175
|
-
});
|
|
@@ -1,87 +0,0 @@
|
|
|
1
|
-
import { EDeviceType, EFirmwareType, ERRORS, HardwareErrorCode } from '@onekeyfe/hd-shared';
|
|
2
|
-
|
|
3
|
-
import DeviceUpdateBootloader from '../../src/api/device/DeviceUpdateBootloader';
|
|
4
|
-
import {
|
|
5
|
-
registerFirmwareUpdateHostBinding,
|
|
6
|
-
unregisterFirmwareUpdateHostBinding,
|
|
7
|
-
} from '../../src/api/firmware/FirmwareHostBinding';
|
|
8
|
-
|
|
9
|
-
jest.mock('../../src/api/firmware/FirmwareUpdatePreparedPlan', () => ({
|
|
10
|
-
assertFirmwareUpdatePreparedPlanBinding: jest.fn(),
|
|
11
|
-
assertFirmwareUpdatePreparedPlanDeviceIdentity: jest.fn(),
|
|
12
|
-
}));
|
|
13
|
-
|
|
14
|
-
jest.mock('../../src/data-manager', () => ({
|
|
15
|
-
DataManager: {
|
|
16
|
-
getSettings: jest.fn(),
|
|
17
|
-
isBleConnect: jest.fn(),
|
|
18
|
-
},
|
|
19
|
-
}));
|
|
20
|
-
|
|
21
|
-
jest.mock('../../src/device/DevicePool', () => ({
|
|
22
|
-
DevicePool: {},
|
|
23
|
-
}));
|
|
24
|
-
|
|
25
|
-
const artifact = {
|
|
26
|
-
artifactRef: `fw:${'a'.repeat(64)}`,
|
|
27
|
-
size: 4,
|
|
28
|
-
sha256: 'a'.repeat(64),
|
|
29
|
-
};
|
|
30
|
-
|
|
31
|
-
const createMethod = () => {
|
|
32
|
-
const closeError = new Error('artifact reader close failed');
|
|
33
|
-
const close = jest.fn().mockRejectedValue(closeError);
|
|
34
|
-
const artifactReader = {
|
|
35
|
-
open: jest.fn().mockResolvedValue({ readerId: 'reader-1', size: artifact.size }),
|
|
36
|
-
read: jest.fn(),
|
|
37
|
-
close,
|
|
38
|
-
};
|
|
39
|
-
const hostBindingGeneration = registerFirmwareUpdateHostBinding({ artifactReader });
|
|
40
|
-
const method = new DeviceUpdateBootloader({
|
|
41
|
-
id: 1,
|
|
42
|
-
payload: {
|
|
43
|
-
method: 'deviceUpdateBootloader',
|
|
44
|
-
artifact,
|
|
45
|
-
hostBindingGeneration,
|
|
46
|
-
preparedPlan: {},
|
|
47
|
-
},
|
|
48
|
-
});
|
|
49
|
-
(method as any).device = {
|
|
50
|
-
features: {
|
|
51
|
-
deviceType: EDeviceType.Touch,
|
|
52
|
-
serialNo: 'touch-device-id',
|
|
53
|
-
},
|
|
54
|
-
getCurrentDeviceType: () => EDeviceType.Touch,
|
|
55
|
-
getCurrentFirmwareType: () => EFirmwareType.Universal,
|
|
56
|
-
};
|
|
57
|
-
return { close, closeError, method };
|
|
58
|
-
};
|
|
59
|
-
|
|
60
|
-
describe('DeviceUpdateBootloader artifact source cleanup', () => {
|
|
61
|
-
afterEach(() => {
|
|
62
|
-
unregisterFirmwareUpdateHostBinding();
|
|
63
|
-
jest.restoreAllMocks();
|
|
64
|
-
});
|
|
65
|
-
|
|
66
|
-
test('does not replace a successful update result when source close fails', async () => {
|
|
67
|
-
const { close, method } = createMethod();
|
|
68
|
-
jest.spyOn(method, 'updateTouchBootloader').mockResolvedValue(true);
|
|
69
|
-
|
|
70
|
-
await expect(method.run()).resolves.toBe(true);
|
|
71
|
-
|
|
72
|
-
expect(close).toHaveBeenCalledWith({ readerId: 'reader-1' });
|
|
73
|
-
});
|
|
74
|
-
|
|
75
|
-
test('does not replace the original hardware error when source close fails', async () => {
|
|
76
|
-
const { close, method } = createMethod();
|
|
77
|
-
const hardwareError = ERRORS.TypedError(
|
|
78
|
-
HardwareErrorCode.FirmwareError,
|
|
79
|
-
'original bootloader hardware error'
|
|
80
|
-
);
|
|
81
|
-
jest.spyOn(method, 'updateTouchBootloader').mockRejectedValue(hardwareError);
|
|
82
|
-
|
|
83
|
-
await expect(method.run()).rejects.toBe(hardwareError);
|
|
84
|
-
|
|
85
|
-
expect(close).toHaveBeenCalledWith({ readerId: 'reader-1' });
|
|
86
|
-
});
|
|
87
|
-
});
|