@onekeyfe/hd-core 1.2.0-alpha.64 → 1.2.0-alpha.66
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 +198 -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-resources.test.ts +340 -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 +1506 -1097
- package/__tests__/protocolV2FileWrite.test.ts +152 -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 +2 -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 -11
- 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 +13 -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 -248
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3051 -3774
- 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 -71
- 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 +59 -60
- package/src/api/DetectDeviceConnectProtocol.ts +18 -0
- package/src/api/FirmwareUpdate.ts +7 -15
- package/src/api/FirmwareUpdateV2.ts +126 -316
- package/src/api/FirmwareUpdateV3.ts +63 -265
- package/src/api/FirmwareUpdateV4.ts +597 -1005
- 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 +202 -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 +390 -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 -79
- 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 +60 -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/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 -213
- 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
|
@@ -5,6 +5,7 @@ import CheckAllFirmwareRelease, {
|
|
|
5
5
|
} from '../src/api/CheckAllFirmwareRelease';
|
|
6
6
|
import { DataManager } from '../src/data-manager';
|
|
7
7
|
import { createCoreApi } from '../src/inject';
|
|
8
|
+
import { PROTOCOL_V2_RESOURCE_DEVICE_PATHS } from '../src/protocols/protocol-v2/resources';
|
|
8
9
|
|
|
9
10
|
import type { CoreApi } from '../src/types/api';
|
|
10
11
|
import type { DeviceStateVersions, IFirmwareReleaseInfo } from '../src/types';
|
|
@@ -72,7 +73,74 @@ const release: IFirmwareReleaseInfo = {
|
|
|
72
73
|
],
|
|
73
74
|
};
|
|
74
75
|
|
|
76
|
+
const stableResources = ['images', 'animation', 'wallpaper', 'translations', 'roobert', 'noto'].map(
|
|
77
|
+
(type, index) => ({
|
|
78
|
+
type,
|
|
79
|
+
url: `https://example.com/${type}.okpkg`,
|
|
80
|
+
size: 0x52a0 + index + 1,
|
|
81
|
+
fileHash: 'a'.repeat(64),
|
|
82
|
+
headerHash: index.toString(16).padStart(128, '0'),
|
|
83
|
+
})
|
|
84
|
+
);
|
|
85
|
+
|
|
86
|
+
const createFilesystemTypedCall = (missingAll = false) => {
|
|
87
|
+
const resourceByPath = new Map(
|
|
88
|
+
stableResources.map(resource => [
|
|
89
|
+
PROTOCOL_V2_RESOURCE_DEVICE_PATHS[
|
|
90
|
+
resource.type as keyof typeof PROTOCOL_V2_RESOURCE_DEVICE_PATHS
|
|
91
|
+
],
|
|
92
|
+
resource,
|
|
93
|
+
])
|
|
94
|
+
);
|
|
95
|
+
return jest.fn((requestType: string, _responseType: string, payload: Record<string, any>) => {
|
|
96
|
+
if (requestType === 'ResourceInventoryGet') {
|
|
97
|
+
throw new Error('ResourceInventoryGet is unavailable on released firmware');
|
|
98
|
+
}
|
|
99
|
+
if (requestType === 'FilesystemPathInfoQuery') {
|
|
100
|
+
const resource = resourceByPath.get(payload.path);
|
|
101
|
+
return {
|
|
102
|
+
message: {
|
|
103
|
+
exist: Boolean(resource) && !missingAll,
|
|
104
|
+
directory: false,
|
|
105
|
+
size: missingAll ? 0 : resource?.size,
|
|
106
|
+
},
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
if (requestType === 'FilesystemFileRead') {
|
|
110
|
+
const resource = resourceByPath.get(payload.file.path);
|
|
111
|
+
if (!resource || missingAll) throw new Error('missing resource');
|
|
112
|
+
const header = new Uint8Array(0x52a0);
|
|
113
|
+
const view = new DataView(header.buffer);
|
|
114
|
+
'OKPP'.split('').forEach((char, index) => {
|
|
115
|
+
header[index] = char.charCodeAt(0);
|
|
116
|
+
});
|
|
117
|
+
'RESC'.split('').forEach((char, index) => {
|
|
118
|
+
header[0x08 + index] = char.charCodeAt(0);
|
|
119
|
+
});
|
|
120
|
+
view.setUint32(0x0c, header.byteLength, true);
|
|
121
|
+
for (let index = 0; index < resource.headerHash.length / 2; index++) {
|
|
122
|
+
header[0x240 + index] = Number.parseInt(
|
|
123
|
+
resource.headerHash.slice(index * 2, index * 2 + 2),
|
|
124
|
+
16
|
|
125
|
+
);
|
|
126
|
+
}
|
|
127
|
+
const offset = Number(payload.file.offset);
|
|
128
|
+
const chunkLength = Number(payload.chunk_len);
|
|
129
|
+
return {
|
|
130
|
+
message: {
|
|
131
|
+
data: header.slice(offset, offset + chunkLength),
|
|
132
|
+
},
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
throw new Error(`Unexpected request: ${requestType}`);
|
|
136
|
+
});
|
|
137
|
+
};
|
|
138
|
+
|
|
75
139
|
describe('checkAllFirmwareRelease Protocol V2 support', () => {
|
|
140
|
+
afterEach(() => {
|
|
141
|
+
jest.restoreAllMocks();
|
|
142
|
+
});
|
|
143
|
+
|
|
76
144
|
test('builds ordered firmwareUpdateV4 targets from recommended component versions', () => {
|
|
77
145
|
const result = buildProtocolV2FirmwareRelease({
|
|
78
146
|
currentVersions,
|
|
@@ -84,7 +152,7 @@ describe('checkAllFirmwareRelease Protocol V2 support', () => {
|
|
|
84
152
|
status: 'required',
|
|
85
153
|
hasUpgrade: true,
|
|
86
154
|
required: true,
|
|
87
|
-
targetsToUpdate: ['boot', 'app_v1'
|
|
155
|
+
targetsToUpdate: ['boot', 'app_v1'],
|
|
88
156
|
components: [
|
|
89
157
|
{ configKey: 'bootloader', status: 'outdated', updateTarget: 'boot' },
|
|
90
158
|
{ configKey: 'applicationP1', status: 'outdated', updateTarget: 'app_v1' },
|
|
@@ -142,6 +210,7 @@ describe('checkAllFirmwareRelease Protocol V2 support', () => {
|
|
|
142
210
|
applicationP1Hash: 'aa'.repeat(32),
|
|
143
211
|
applicationP2Hash: 'bb'.repeat(32),
|
|
144
212
|
},
|
|
213
|
+
checkFirmwareHash: true,
|
|
145
214
|
remotePayloadHashes: {
|
|
146
215
|
applicationP1: 'aa'.repeat(64),
|
|
147
216
|
applicationP2: 'cc'.repeat(64),
|
|
@@ -160,6 +229,37 @@ describe('checkAllFirmwareRelease Protocol V2 support', () => {
|
|
|
160
229
|
});
|
|
161
230
|
});
|
|
162
231
|
|
|
232
|
+
test('uses version-only comparison for same-version packages by default', () => {
|
|
233
|
+
const packageSet: IFirmwareReleaseInfo = {
|
|
234
|
+
...release,
|
|
235
|
+
required: false,
|
|
236
|
+
resourceBundles: undefined,
|
|
237
|
+
installOrder: ['applicationP1'],
|
|
238
|
+
components: {
|
|
239
|
+
applicationP1: {
|
|
240
|
+
target: 'APPLICATION_P1',
|
|
241
|
+
version: [1, 0, 0],
|
|
242
|
+
url: 'https://example.com/application-p1.okpkg',
|
|
243
|
+
payloadHash: 'cc'.repeat(64),
|
|
244
|
+
},
|
|
245
|
+
},
|
|
246
|
+
};
|
|
247
|
+
|
|
248
|
+
expect(
|
|
249
|
+
buildProtocolV2FirmwareRelease({
|
|
250
|
+
currentVersions: { ...currentVersions, applicationP1: '1.0.0' },
|
|
251
|
+
currentVerification: { applicationP1Hash: 'aa'.repeat(32) },
|
|
252
|
+
firmwareType: EFirmwareType.Universal,
|
|
253
|
+
release: packageSet,
|
|
254
|
+
})
|
|
255
|
+
).toMatchObject({
|
|
256
|
+
status: 'valid',
|
|
257
|
+
hasUpgrade: false,
|
|
258
|
+
targetsToUpdate: [],
|
|
259
|
+
components: [{ configKey: 'applicationP1', status: 'valid' }],
|
|
260
|
+
});
|
|
261
|
+
});
|
|
262
|
+
|
|
163
263
|
test('keeps same-version hash-aware components unknown without metadata payloadHash', () => {
|
|
164
264
|
const packageSet: IFirmwareReleaseInfo = {
|
|
165
265
|
...release,
|
|
@@ -180,6 +280,7 @@ describe('checkAllFirmwareRelease Protocol V2 support', () => {
|
|
|
180
280
|
buildProtocolV2FirmwareRelease({
|
|
181
281
|
currentVersions: { ...currentVersions, applicationP1: '1.0.0' },
|
|
182
282
|
currentVerification: { applicationP1Hash: 'aa'.repeat(32) },
|
|
283
|
+
checkFirmwareHash: true,
|
|
183
284
|
firmwareType: EFirmwareType.Universal,
|
|
184
285
|
release: packageSet,
|
|
185
286
|
})
|
|
@@ -215,6 +316,7 @@ describe('checkAllFirmwareRelease Protocol V2 support', () => {
|
|
|
215
316
|
const result = buildProtocolV2FirmwareRelease({
|
|
216
317
|
currentVersions,
|
|
217
318
|
currentVerification: { applicationP1Hash: 'aa'.repeat(32) },
|
|
319
|
+
checkFirmwareHash: true,
|
|
218
320
|
remotePayloadHashes: { applicationP1: 'cc'.repeat(64) },
|
|
219
321
|
firmwareType: EFirmwareType.Universal,
|
|
220
322
|
release: packageSet,
|
|
@@ -223,7 +325,7 @@ describe('checkAllFirmwareRelease Protocol V2 support', () => {
|
|
|
223
325
|
expect(result.targetsToUpdate).toEqual(['app_v1', 'app_v2']);
|
|
224
326
|
});
|
|
225
327
|
|
|
226
|
-
test('
|
|
328
|
+
test('does not read vol0 resource inventory while Protocol V2 is in Application mode', async () => {
|
|
227
329
|
const method = new CheckAllFirmwareRelease({
|
|
228
330
|
id: 1,
|
|
229
331
|
payload: {
|
|
@@ -240,6 +342,7 @@ describe('checkAllFirmwareRelease Protocol V2 support', () => {
|
|
|
240
342
|
status: { mode: 'normal' },
|
|
241
343
|
versions: currentVersions,
|
|
242
344
|
});
|
|
345
|
+
const typedCall = createFilesystemTypedCall(true);
|
|
243
346
|
method.device = {
|
|
244
347
|
isProtocolV2: () => true,
|
|
245
348
|
features: {
|
|
@@ -247,32 +350,124 @@ describe('checkAllFirmwareRelease Protocol V2 support', () => {
|
|
|
247
350
|
firmwareVersion: '1.0.0',
|
|
248
351
|
},
|
|
249
352
|
getDeviceState,
|
|
353
|
+
getCommands: () => ({ typedCall }),
|
|
250
354
|
} as unknown as CheckAllFirmwareRelease['device'];
|
|
251
355
|
jest.spyOn(DataManager, 'getFirmwareLatestRelease').mockReturnValue(release);
|
|
356
|
+
jest.spyOn(DataManager, 'getProtocolV2Resources').mockReturnValue(stableResources as any);
|
|
252
357
|
|
|
253
358
|
await expect(method.run()).resolves.toMatchObject({
|
|
254
359
|
protocol: 'V2',
|
|
255
360
|
deviceType: 'pro2',
|
|
256
361
|
status: 'required',
|
|
257
|
-
|
|
362
|
+
resourceStatus: 'unknown',
|
|
363
|
+
targetsToUpdate: ['boot', 'app_v1'],
|
|
258
364
|
firmware: {
|
|
259
365
|
status: 'required',
|
|
260
366
|
},
|
|
261
367
|
});
|
|
368
|
+
expect(typedCall).not.toHaveBeenCalled();
|
|
369
|
+
expect(getDeviceState).toHaveBeenCalledWith({
|
|
370
|
+
refreshSections: ['identity', 'versions'],
|
|
371
|
+
});
|
|
262
372
|
expect(method.getSupportedProtocols()).toEqual(['V1', 'V2']);
|
|
263
373
|
});
|
|
264
374
|
|
|
375
|
+
test('requests and compares firmware hashes only when explicitly enabled', async () => {
|
|
376
|
+
const packageSet: IFirmwareReleaseInfo = {
|
|
377
|
+
...release,
|
|
378
|
+
required: false,
|
|
379
|
+
resourceBundles: undefined,
|
|
380
|
+
installOrder: ['applicationP1'],
|
|
381
|
+
components: {
|
|
382
|
+
applicationP1: {
|
|
383
|
+
target: 'APPLICATION_P1',
|
|
384
|
+
version: [1, 0, 0],
|
|
385
|
+
url: 'https://example.com/application-p1.okpkg',
|
|
386
|
+
payloadHash: 'cc'.repeat(64),
|
|
387
|
+
},
|
|
388
|
+
},
|
|
389
|
+
};
|
|
390
|
+
const method = new CheckAllFirmwareRelease({
|
|
391
|
+
id: 1,
|
|
392
|
+
payload: {
|
|
393
|
+
method: 'checkAllFirmwareRelease',
|
|
394
|
+
firmwareType: EFirmwareType.Universal,
|
|
395
|
+
checkFirmwareHash: true,
|
|
396
|
+
},
|
|
397
|
+
});
|
|
398
|
+
method.init();
|
|
399
|
+
const getDeviceState = jest.fn().mockResolvedValue({
|
|
400
|
+
identity: { deviceType: 'pro2', firmwareType: EFirmwareType.Universal },
|
|
401
|
+
status: { mode: 'normal' },
|
|
402
|
+
versions: { ...currentVersions, applicationP1: '1.0.0' },
|
|
403
|
+
verification: { applicationP1Hash: 'aa'.repeat(32) },
|
|
404
|
+
});
|
|
405
|
+
method.device = {
|
|
406
|
+
isProtocolV2: () => true,
|
|
407
|
+
features: { deviceType: 'pro2', firmwareVersion: '1.0.0' },
|
|
408
|
+
getDeviceState,
|
|
409
|
+
getCommands: () => ({ typedCall: jest.fn() }),
|
|
410
|
+
} as unknown as CheckAllFirmwareRelease['device'];
|
|
411
|
+
jest.spyOn(DataManager, 'getFirmwareLatestRelease').mockReturnValue(packageSet);
|
|
412
|
+
jest.spyOn(DataManager, 'getProtocolV2Resources').mockReturnValue(undefined);
|
|
413
|
+
|
|
414
|
+
await expect(method.run()).resolves.toMatchObject({
|
|
415
|
+
status: 'outdated',
|
|
416
|
+
targetsToUpdate: ['app_v1'],
|
|
417
|
+
});
|
|
418
|
+
expect(getDeviceState).toHaveBeenCalledWith({
|
|
419
|
+
refreshSections: ['identity', 'versions', 'verification'],
|
|
420
|
+
});
|
|
421
|
+
});
|
|
422
|
+
|
|
423
|
+
test.each(['bootloader', 'romloader'] as const)(
|
|
424
|
+
'uses filesystem inventory in %s mode instead of forcing all resources',
|
|
425
|
+
async mode => {
|
|
426
|
+
const method = new CheckAllFirmwareRelease({
|
|
427
|
+
id: 1,
|
|
428
|
+
payload: {
|
|
429
|
+
method: 'checkAllFirmwareRelease',
|
|
430
|
+
firmwareType: EFirmwareType.Universal,
|
|
431
|
+
},
|
|
432
|
+
});
|
|
433
|
+
method.init();
|
|
434
|
+
const typedCall = createFilesystemTypedCall();
|
|
435
|
+
method.device = {
|
|
436
|
+
isProtocolV2: () => true,
|
|
437
|
+
features: { deviceType: 'pro2', firmwareVersion: '1.0.0' },
|
|
438
|
+
getDeviceState: jest.fn().mockResolvedValue({
|
|
439
|
+
identity: { deviceType: 'pro2', firmwareType: EFirmwareType.Universal },
|
|
440
|
+
status: { mode },
|
|
441
|
+
versions: currentVersions,
|
|
442
|
+
}),
|
|
443
|
+
getCommands: () => ({ typedCall }),
|
|
444
|
+
} as unknown as CheckAllFirmwareRelease['device'];
|
|
445
|
+
jest.spyOn(DataManager, 'getFirmwareLatestRelease').mockReturnValue(release);
|
|
446
|
+
jest.spyOn(DataManager, 'getProtocolV2Resources').mockReturnValue(stableResources as any);
|
|
447
|
+
|
|
448
|
+
await expect(method.run()).resolves.toMatchObject({
|
|
449
|
+
protocol: 'V2',
|
|
450
|
+
resourceStatus: 'valid',
|
|
451
|
+
targetsToUpdate: ['boot', 'app_v1'],
|
|
452
|
+
});
|
|
453
|
+
expect(typedCall.mock.calls.some(call => call[0] === 'ResourceInventoryGet')).toBe(false);
|
|
454
|
+
expect(typedCall.mock.calls.some(call => call[0] === 'FilesystemFileRead')).toBe(true);
|
|
455
|
+
}
|
|
456
|
+
);
|
|
457
|
+
|
|
265
458
|
test('continues forwarding the existing public method', async () => {
|
|
266
459
|
const call = jest.fn().mockResolvedValue({ success: true, payload: {} });
|
|
267
460
|
const api = createCoreApi(call as CoreApi['call']) as CoreApi;
|
|
268
461
|
|
|
269
462
|
await api.checkAllFirmwareRelease('pro2-connect-id', {
|
|
463
|
+
checkFirmwareHash: true,
|
|
270
464
|
firmwareType: EFirmwareType.Universal,
|
|
271
465
|
retryCount: 0,
|
|
272
466
|
});
|
|
273
467
|
|
|
274
468
|
expect(call).toHaveBeenCalledWith({
|
|
275
469
|
connectId: 'pro2-connect-id',
|
|
470
|
+
checkFirmwareHash: true,
|
|
276
471
|
firmwareType: EFirmwareType.Universal,
|
|
277
472
|
retryCount: 0,
|
|
278
473
|
method: 'checkAllFirmwareRelease',
|
|
@@ -1,61 +1,19 @@
|
|
|
1
|
-
import DataManager from '../src/data-manager/DataManager';
|
|
2
1
|
import { parseConnectSettings } from '../src/data-manager/connectSettings';
|
|
3
2
|
|
|
4
|
-
import type { RemoteConfigResponse } from '../src/types';
|
|
5
|
-
|
|
6
|
-
jest.mock('axios', () => ({
|
|
7
|
-
get: jest.fn(),
|
|
8
|
-
}));
|
|
9
|
-
|
|
10
3
|
jest.mock('../src/data/config', () => ({
|
|
11
4
|
getSDKVersion: jest.fn(() => '1.0.0'),
|
|
12
5
|
DEFAULT_DOMAIN: 'https://jssdk.onekey.so/1.0.0/',
|
|
13
6
|
}));
|
|
14
7
|
|
|
15
|
-
const mockAxiosGet: jest.Mock = jest.requireMock('axios').get;
|
|
16
|
-
|
|
17
8
|
describe('parseConnectSettings', () => {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
classic: { firmware: [], ble: [] },
|
|
21
|
-
classic1s: { firmware: [], ble: [] },
|
|
22
|
-
classicpure: { firmware: [], ble: [] },
|
|
23
|
-
mini: { firmware: [], ble: [] },
|
|
24
|
-
touch: { firmware: [], ble: [] },
|
|
25
|
-
pro: { firmware: [], ble: [] },
|
|
26
|
-
pro2: { firmware: [], ble: [] },
|
|
27
|
-
} as unknown as RemoteConfigResponse;
|
|
28
|
-
|
|
29
|
-
it('keeps a serializable preloaded config in parsed settings', () => {
|
|
30
|
-
const settings = parseConnectSettings({
|
|
31
|
-
firmwareManifestMode: 'sdk-managed',
|
|
32
|
-
preloadedConfig,
|
|
33
|
-
});
|
|
34
|
-
|
|
35
|
-
expect(settings.firmwareManifestMode).toBe('sdk-managed');
|
|
36
|
-
expect(settings.preloadedConfig).toBe(preloadedConfig);
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
it('uses the preloaded config before the SDK network client', async () => {
|
|
40
|
-
const settings = parseConnectSettings({
|
|
41
|
-
firmwareManifestMode: 'sdk-managed',
|
|
42
|
-
preloadedConfig,
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
await DataManager.load(settings);
|
|
46
|
-
|
|
47
|
-
expect(mockAxiosGet).not.toHaveBeenCalled();
|
|
48
|
-
expect(DataManager.deviceMap.classic).toEqual({ firmware: [], ble: [] });
|
|
49
|
-
});
|
|
9
|
+
it('keeps custom configFetcher in parsed settings', () => {
|
|
10
|
+
const configFetcher = jest.fn();
|
|
50
11
|
|
|
51
|
-
it('fails closed without a preloaded config in external-only mode', async () => {
|
|
52
12
|
const settings = parseConnectSettings({
|
|
53
|
-
|
|
13
|
+
fetchConfig: true,
|
|
14
|
+
configFetcher,
|
|
54
15
|
});
|
|
55
16
|
|
|
56
|
-
|
|
57
|
-
'External firmware config snapshot is required'
|
|
58
|
-
);
|
|
59
|
-
expect(mockAxiosGet).not.toHaveBeenCalled();
|
|
17
|
+
expect(settings.configFetcher).toBe(configFetcher);
|
|
60
18
|
});
|
|
61
19
|
});
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { DataManager } from '../src/data-manager';
|
|
2
|
+
import { init } from '../src/core';
|
|
3
|
+
|
|
4
|
+
import type { ConnectSettings } from '../src/types';
|
|
5
|
+
|
|
6
|
+
jest.mock('../src/data/config', () => ({
|
|
7
|
+
getSDKVersion: jest.fn(() => '1.0.0-test'),
|
|
8
|
+
DEFAULT_DOMAIN: 'https://jssdk.onekey.so/1.0.0-test/',
|
|
9
|
+
}));
|
|
10
|
+
|
|
11
|
+
describe('Core initialization', () => {
|
|
12
|
+
afterEach(() => {
|
|
13
|
+
jest.restoreAllMocks();
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
it('does not create a partially initialized core when settings loading fails', async () => {
|
|
17
|
+
jest.spyOn(DataManager, 'load').mockRejectedValue(new Error('settings load failed'));
|
|
18
|
+
|
|
19
|
+
await expect(init({} as ConnectSettings, class TestTransport {})).rejects.toThrow(
|
|
20
|
+
'settings load failed'
|
|
21
|
+
);
|
|
22
|
+
});
|
|
23
|
+
});
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { HardwareErrorCode } from '@onekeyfe/hd-shared';
|
|
2
|
+
|
|
3
|
+
import DeviceConnector from '../src/device/DeviceConnector';
|
|
4
|
+
|
|
5
|
+
jest.mock('../src/data-manager/TransportManager', () => ({
|
|
6
|
+
__esModule: true,
|
|
7
|
+
default: {
|
|
8
|
+
load: jest.fn(),
|
|
9
|
+
getTransport: jest.fn(),
|
|
10
|
+
},
|
|
11
|
+
}));
|
|
12
|
+
|
|
13
|
+
jest.mock('../src/data-manager', () => ({
|
|
14
|
+
DataManager: {
|
|
15
|
+
getSettings: jest.fn(() => 'desktop-web-ble'),
|
|
16
|
+
isBleConnect: jest.fn(() => true),
|
|
17
|
+
},
|
|
18
|
+
}));
|
|
19
|
+
|
|
20
|
+
jest.mock('../src/device/DevicePool', () => ({
|
|
21
|
+
DevicePool: {
|
|
22
|
+
setConnector: jest.fn(),
|
|
23
|
+
},
|
|
24
|
+
}));
|
|
25
|
+
|
|
26
|
+
const transportManagerMock: {
|
|
27
|
+
default: {
|
|
28
|
+
getTransport: jest.Mock;
|
|
29
|
+
};
|
|
30
|
+
} = jest.requireMock('../src/data-manager/TransportManager');
|
|
31
|
+
|
|
32
|
+
describe('DeviceConnector protocol validation', () => {
|
|
33
|
+
beforeEach(() => {
|
|
34
|
+
jest.clearAllMocks();
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
it('reports an explicit transport error when connector initialization ran too early', async () => {
|
|
38
|
+
transportManagerMock.default.getTransport.mockReturnValue(undefined);
|
|
39
|
+
const connector = new DeviceConnector();
|
|
40
|
+
|
|
41
|
+
await expect(connector.enumerate()).rejects.toMatchObject({
|
|
42
|
+
errorCode: HardwareErrorCode.TransportNotConfigured,
|
|
43
|
+
});
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
it('uses the actively probed protocol returned by acquire when the cache was cleared', async () => {
|
|
47
|
+
const acquire = jest.fn().mockResolvedValue({
|
|
48
|
+
id: 'pro2-id',
|
|
49
|
+
path: 'pro2-id',
|
|
50
|
+
protocolType: 'V2',
|
|
51
|
+
});
|
|
52
|
+
transportManagerMock.default.getTransport.mockReturnValue({
|
|
53
|
+
acquire,
|
|
54
|
+
getProtocolType: jest.fn(() => undefined),
|
|
55
|
+
});
|
|
56
|
+
const connector = new DeviceConnector();
|
|
57
|
+
|
|
58
|
+
await expect(connector.acquire('pro2-id', undefined, undefined, 'V2')).resolves.toEqual(
|
|
59
|
+
expect.objectContaining({ protocolType: 'V2' })
|
|
60
|
+
);
|
|
61
|
+
expect(acquire).toHaveBeenCalledWith(
|
|
62
|
+
expect.objectContaining({ uuid: 'pro2-id', expectedProtocol: 'V2' })
|
|
63
|
+
);
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
it('still rejects a real mismatch reported by the active protocol probe', async () => {
|
|
67
|
+
transportManagerMock.default.getTransport.mockReturnValue({
|
|
68
|
+
acquire: jest.fn().mockResolvedValue({
|
|
69
|
+
id: 'classic-id',
|
|
70
|
+
path: 'classic-id',
|
|
71
|
+
protocolType: 'V1',
|
|
72
|
+
}),
|
|
73
|
+
getProtocolType: jest.fn(() => 'V1'),
|
|
74
|
+
});
|
|
75
|
+
const connector = new DeviceConnector();
|
|
76
|
+
|
|
77
|
+
await expect(connector.acquire('classic-id', undefined, undefined, 'V2')).rejects.toThrow(
|
|
78
|
+
'Device protocol mismatch: expected V2, detected V1'
|
|
79
|
+
);
|
|
80
|
+
});
|
|
81
|
+
});
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { HardwareErrorCode } from '@onekeyfe/hd-shared';
|
|
1
2
|
import { TRANSPORT_EVENT } from '@onekeyfe/hd-transport';
|
|
2
3
|
|
|
3
4
|
import { initConnector, initCore } from '../src/core';
|
|
@@ -95,7 +96,7 @@ describe('public device lifecycle events', () => {
|
|
|
95
96
|
expect(messages.filter(message => message.type === DEVICE.DISCONNECT)).toHaveLength(1);
|
|
96
97
|
});
|
|
97
98
|
|
|
98
|
-
test('uses a cached protocol as a
|
|
99
|
+
test('uses a verified cached protocol as a strict expected protocol', async () => {
|
|
99
100
|
jest.spyOn(DataManager, 'getSettings').mockReturnValue('react-native' as never);
|
|
100
101
|
const device = Device.fromDescriptor({
|
|
101
102
|
id: 'ble-id',
|
|
@@ -103,16 +104,117 @@ describe('public device lifecycle events', () => {
|
|
|
103
104
|
commType: 'ble',
|
|
104
105
|
protocolType: 'V1',
|
|
105
106
|
} as never);
|
|
106
|
-
const acquire = jest.fn().mockResolvedValue({ uuid: 'ble-id', protocolType: '
|
|
107
|
+
const acquire = jest.fn().mockResolvedValue({ uuid: 'ble-id', protocolType: 'V1' });
|
|
107
108
|
device.deviceConnector = { acquire } as never;
|
|
108
109
|
|
|
109
110
|
await device.acquire();
|
|
110
111
|
|
|
111
|
-
expect(acquire).toHaveBeenCalledWith('ble-id', undefined, true,
|
|
112
|
+
expect(acquire).toHaveBeenCalledWith('ble-id', undefined, true, 'V1', undefined);
|
|
113
|
+
expect(device.getProtocol()).toBe('V1');
|
|
114
|
+
expect(device.originalDescriptor.protocolType).toBe('V1');
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
test('bypasses a cached protocol only for explicit active detection', async () => {
|
|
118
|
+
jest.spyOn(DataManager, 'getSettings').mockReturnValue('react-native' as never);
|
|
119
|
+
const device = Device.fromDescriptor({
|
|
120
|
+
id: 'ble-id',
|
|
121
|
+
path: 'ble-id',
|
|
122
|
+
commType: 'ble',
|
|
123
|
+
protocolType: 'V1',
|
|
124
|
+
} as never);
|
|
125
|
+
const acquire = jest.fn().mockResolvedValue({ uuid: 'ble-id', protocolType: 'V2' });
|
|
126
|
+
device.deviceConnector = { acquire } as never;
|
|
127
|
+
|
|
128
|
+
await device.acquire(undefined, { forceProtocolDetection: true });
|
|
129
|
+
|
|
130
|
+
expect(acquire).toHaveBeenCalledWith('ble-id', undefined, true, undefined, undefined);
|
|
112
131
|
expect(device.getProtocol()).toBe('V2');
|
|
113
132
|
expect(device.originalDescriptor.protocolType).toBe('V2');
|
|
114
133
|
});
|
|
115
134
|
|
|
135
|
+
test('does not reuse a stale protocol when active detection returns no protocol', async () => {
|
|
136
|
+
jest.spyOn(DataManager, 'getSettings').mockReturnValue('react-native' as never);
|
|
137
|
+
const device = Device.fromDescriptor({
|
|
138
|
+
id: 'ble-id',
|
|
139
|
+
path: 'ble-id',
|
|
140
|
+
commType: 'ble',
|
|
141
|
+
protocolType: 'V1',
|
|
142
|
+
} as never);
|
|
143
|
+
const acquire = jest.fn().mockResolvedValue({ uuid: 'ble-id' });
|
|
144
|
+
const release = jest.fn().mockResolvedValue(undefined);
|
|
145
|
+
device.deviceConnector = { acquire, release } as never;
|
|
146
|
+
await expect(
|
|
147
|
+
device.acquire(undefined, {
|
|
148
|
+
forceProtocolDetection: true,
|
|
149
|
+
throwOnRunPromiseError: true,
|
|
150
|
+
})
|
|
151
|
+
).rejects.toMatchObject({ errorCode: HardwareErrorCode.RuntimeError });
|
|
152
|
+
expect(device.originalDescriptor.protocolType).toBe('V1');
|
|
153
|
+
expect(device.hasDeviceAcquire()).toBe(false);
|
|
154
|
+
expect(release).toHaveBeenCalledWith('ble-id', false);
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
test('actively reacquires an already connected device without initializing it', async () => {
|
|
158
|
+
jest.spyOn(DataManager, 'getSettings').mockReturnValue('webusb' as never);
|
|
159
|
+
const device = Device.fromDescriptor({
|
|
160
|
+
id: 'usb-device',
|
|
161
|
+
path: 'usb-device',
|
|
162
|
+
session: 'old-session',
|
|
163
|
+
protocolType: 'V1',
|
|
164
|
+
} as never);
|
|
165
|
+
device.mainId = 'old-session';
|
|
166
|
+
device.commands = { disposed: false } as never;
|
|
167
|
+
const release = jest.spyOn(device, 'release').mockImplementation(() => {
|
|
168
|
+
device.mainId = null;
|
|
169
|
+
device.originalDescriptor.session = null;
|
|
170
|
+
device.commands.disposed = true;
|
|
171
|
+
return Promise.resolve();
|
|
172
|
+
});
|
|
173
|
+
const acquire = jest.spyOn(device, 'acquire').mockImplementation(() => {
|
|
174
|
+
device.mainId = 'new-session';
|
|
175
|
+
device.originalDescriptor.session = 'new-session';
|
|
176
|
+
device.originalDescriptor.protocolType = 'V2';
|
|
177
|
+
device.commands.disposed = false;
|
|
178
|
+
return Promise.resolve();
|
|
179
|
+
});
|
|
180
|
+
const initialize = jest.spyOn(device, 'initialize').mockResolvedValue(undefined);
|
|
181
|
+
|
|
182
|
+
await device.run(() => Promise.resolve(undefined), {
|
|
183
|
+
forceProtocolDetection: true,
|
|
184
|
+
skipInitialize: true,
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
expect(release).toHaveBeenCalled();
|
|
188
|
+
expect(acquire).toHaveBeenCalledWith(undefined, {
|
|
189
|
+
forceProtocolDetection: true,
|
|
190
|
+
});
|
|
191
|
+
expect(initialize).not.toHaveBeenCalled();
|
|
192
|
+
expect(device.getProtocol()).toBe('V2');
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
test('keeps the freshly probed React Native BLE session until the call completes', async () => {
|
|
196
|
+
jest.spyOn(DataManager, 'getSettings').mockReturnValue('react-native' as never);
|
|
197
|
+
const device = Device.fromDescriptor({
|
|
198
|
+
id: 'ble-device',
|
|
199
|
+
path: 'ble-device',
|
|
200
|
+
commType: 'ble',
|
|
201
|
+
protocolType: 'V1',
|
|
202
|
+
} as never);
|
|
203
|
+
device.mainId = 'ble-device';
|
|
204
|
+
device.commands = { disposed: false } as never;
|
|
205
|
+
(device as unknown as { deviceAcquired: boolean }).deviceAcquired = true;
|
|
206
|
+
const release = jest.spyOn(device, 'release').mockResolvedValue(undefined);
|
|
207
|
+
const run = jest.fn().mockResolvedValue(undefined);
|
|
208
|
+
|
|
209
|
+
await device.run(run, {
|
|
210
|
+
forceProtocolDetection: true,
|
|
211
|
+
skipInitialize: true,
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
expect(run).toHaveBeenCalledTimes(1);
|
|
215
|
+
expect(release).toHaveBeenCalledTimes(1);
|
|
216
|
+
});
|
|
217
|
+
|
|
116
218
|
test('keeps an explicit connectProtocol as a strict expected protocol', async () => {
|
|
117
219
|
jest.spyOn(DataManager, 'getSettings').mockReturnValue('react-native' as never);
|
|
118
220
|
const device = Device.fromDescriptor({
|
|
@@ -38,6 +38,28 @@ describe('DevicePool state lifecycle', () => {
|
|
|
38
38
|
expect(getDeviceState).toHaveBeenNthCalledWith(2, { refreshSections: ['settings'] });
|
|
39
39
|
});
|
|
40
40
|
|
|
41
|
+
test('actively re-detects a cached device when protocol detection is forced', async () => {
|
|
42
|
+
const descriptor = { path: 'cached-path', protocolType: 'V1' } as any;
|
|
43
|
+
const device = Device.fromDescriptor(descriptor);
|
|
44
|
+
const acquire = jest.spyOn(device, 'acquire').mockImplementation(() => {
|
|
45
|
+
device.originalDescriptor.protocolType = 'V2';
|
|
46
|
+
return Promise.resolve(true);
|
|
47
|
+
});
|
|
48
|
+
const initialize = jest.spyOn(device, 'initialize').mockResolvedValue(undefined);
|
|
49
|
+
const release = jest.spyOn(device, 'release').mockResolvedValue(undefined);
|
|
50
|
+
DevicePool.devicesCache = { 'cached-id': device };
|
|
51
|
+
|
|
52
|
+
const result = await DevicePool.getDevices([descriptor], 'cached-id', {
|
|
53
|
+
forceProtocolDetection: true,
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
expect(acquire).toHaveBeenCalledWith(undefined, { forceProtocolDetection: true });
|
|
57
|
+
expect(initialize).toHaveBeenCalledWith({ forceProtocolDetection: true });
|
|
58
|
+
expect(release).toHaveBeenCalledTimes(1);
|
|
59
|
+
expect(device.originalDescriptor.protocolType).toBe('V2');
|
|
60
|
+
expect(result.deviceList).toEqual([device]);
|
|
61
|
+
});
|
|
62
|
+
|
|
41
63
|
test('keeps a discovered device when its Protocol V2 label cannot be read', async () => {
|
|
42
64
|
const labelError = new Error('settings unavailable');
|
|
43
65
|
const getDeviceState = jest
|