diff --git a/packages/suite/src/components/suite/Preloader/Preloader.tsx b/packages/suite/src/components/suite/Preloader/Preloader.tsx
index 20489e1a8eb..86d61a1a38e 100644
--- a/packages/suite/src/components/suite/Preloader/Preloader.tsx
+++ b/packages/suite/src/components/suite/Preloader/Preloader.tsx
@@ -1,8 +1,6 @@
import { FC, PropsWithChildren, useEffect } from 'react';
-import { Feature, selectIsFeatureDisabled } from '@suite-common/message-system';
import {
- selectIsEntropyCheckFailed,
selectIsFirmwareAuthenticityCheckDismissed,
selectSelectedDevice,
} from '@suite-common/wallet-core';
@@ -12,7 +10,7 @@ import { useGuideKeyboard } from 'src/hooks/guide';
import { useDispatch, useSelector } from 'src/hooks/suite';
import { useWindowVisibility } from 'src/hooks/suite/useWindowVisibility';
import {
- selectIsEntropyCheckEnabled,
+ selectIsEntropyCheckEnabledAndFailed,
selectIsFirmwareAuthenticityCheckEnabledAndHardFailed,
selectIsLoggedOut,
selectIsTransportInitialized,
@@ -63,18 +61,14 @@ export const Preloader = ({ children }: PropsWithChildren) => {
const isLoggedOut = useSelector(selectIsLoggedOut);
const selectedDevice = useSelector(selectSelectedDevice);
const { initialRun, viewOnlyPromoClosed } = useSelector(selectSuiteFlags);
- const isFirmwareCheckFailed = useSelector(
+ const isFirmwareCheckEnabledAndFailed = useSelector(
selectIsFirmwareAuthenticityCheckEnabledAndHardFailed,
);
const isFirmwareAuthenticityCheckDismissed = useSelector(
selectIsFirmwareAuthenticityCheckDismissed,
);
- const isEntropyCheckEnabled = useSelector(selectIsEntropyCheckEnabled);
- // Entropy check won't be performed if disabled but we also have to check it here to avoid showing the UI when the failed state is stored in database.
- const isEntropyCheckDisabledByMessageSystem = useSelector(state =>
- selectIsFeatureDisabled(state, Feature.entropyCheck),
- );
- const isEntropyCheckFailed = useSelector(selectIsEntropyCheckFailed);
+ // Entropy check won't be performed if disabled but we must also check it here to avoid showing the UI when the failed state is stored in database.
+ const isEntropyCheckEnabledAndFailed = useSelector(selectIsEntropyCheckEnabledAndFailed);
// report firmware authenticity failures even when the UI is disabled
useReportDeviceCompromised();
@@ -102,16 +96,13 @@ export const Preloader = ({ children }: PropsWithChildren) => {
return ;
}
- const isEntropyCheckEnabledAndFailed =
- isEntropyCheckEnabled && !isEntropyCheckDisabledByMessageSystem && isEntropyCheckFailed;
-
if (
(router.route?.app === undefined ||
!ROUTES_TO_SKIP_FIRMWARE_CHECK.includes(router.route?.app)) &&
- ((!isFirmwareAuthenticityCheckDismissed && isFirmwareCheckFailed) ||
+ ((!isFirmwareAuthenticityCheckDismissed && isFirmwareCheckEnabledAndFailed) ||
isEntropyCheckEnabledAndFailed)
) {
- return ;
+ return ;
}
if (
diff --git a/packages/suite/src/components/suite/SecurityCheck/DeviceCompromised.tsx b/packages/suite/src/components/suite/SecurityCheck/DeviceCompromised.tsx
index ed0a4ea9582..c2e4a968489 100644
--- a/packages/suite/src/components/suite/SecurityCheck/DeviceCompromised.tsx
+++ b/packages/suite/src/components/suite/SecurityCheck/DeviceCompromised.tsx
@@ -7,22 +7,34 @@ import { useDevice, useDispatch, useSelector } from 'src/hooks/suite';
import {
selectFirmwareHashCheckErrorIfEnabled,
selectFirmwareRevisionCheckErrorIfEnabled,
+ selectIsEntropyCheckEnabledAndFailed,
} from 'src/reducers/suite/suiteReducer';
import { SecurityCheckFail, SecurityCheckFailProps } from './SecurityCheckFail';
import { hardFailureChecklistItems, softFailureChecklistItems } from './checklistItems';
-const useSecurityCheckFailProps = (
- isEntropyCheckFailed: boolean,
-): Partial => {
+const useSecurityCheckFailProps = (): SecurityCheckFailProps => {
+ const { device } = useDevice();
const revisionCheckError = useSelector(selectFirmwareRevisionCheckErrorIfEnabled);
const hashCheckError = useSelector(selectFirmwareHashCheckErrorIfEnabled);
+ const isEntropyCheckFailed = useSelector(selectIsEntropyCheckEnabledAndFailed);
+ const dispatch = useDispatch();
+
+ // Let user access the wallet if it may have been initiated before so that they can access the funds and send them to safety.
+ const goToSuite = () => {
+ // Condition to satisfy TypeScript, device.id is always defined at this point.
+ if (device?.id) {
+ dispatch(deviceActions.dismissFirmwareAuthenticityCheck(device.id));
+ }
+ };
if (isEntropyCheckFailed) {
return {
heading: 'TR_DEVICE_COMPROMISED_HEADING',
text: 'TR_DEVICE_COMPROMISED_ENTROPY_CHECK_TEXT',
checklistItems: hardFailureChecklistItems,
+ goBack: undefined,
+ supportUrl: TREZOR_SUPPORT_URL, // TODO: add specific URL when it is created
};
}
// revision check has precedence over hash check, because it does not have the ambiguous other-error state
@@ -31,6 +43,8 @@ const useSecurityCheckFailProps = (
heading: 'TR_DEVICE_COMPROMISED_HEADING',
text: 'TR_DEVICE_COMPROMISED_FW_REVISION_CHECK_TEXT',
checklistItems: hardFailureChecklistItems,
+ goBack: goToSuite,
+ supportUrl: TREZOR_SUPPORT_FW_REVISION_CHECK_FAILED_URL,
};
}
// hash check other-error shall display softer wording than standard hash check errors
@@ -40,6 +54,8 @@ const useSecurityCheckFailProps = (
text: 'TR_FAILED_VERIFY_DEVICE_TEXT',
checklistItems: softFailureChecklistItems,
supportButtonVariant: 'warning',
+ goBack: goToSuite,
+ supportUrl: TREZOR_SUPPORT_FW_REVISION_CHECK_FAILED_URL,
};
}
if (hashCheckError !== null) {
@@ -47,43 +63,22 @@ const useSecurityCheckFailProps = (
heading: 'TR_DEVICE_COMPROMISED_HEADING',
text: 'TR_DEVICE_COMPROMISED_FW_HASH_CHECK_TEXT',
checklistItems: hardFailureChecklistItems,
+ goBack: goToSuite,
+ supportUrl: TREZOR_SUPPORT_FW_REVISION_CHECK_FAILED_URL,
};
}
// should not happen, but default props will be used with no problem
- return {};
-};
-
-type DeviceCompromisedProps = {
- isEntropyCheckFailed: boolean;
+ return { supportUrl: TREZOR_SUPPORT_FW_REVISION_CHECK_FAILED_URL };
};
-export const DeviceCompromised = ({ isEntropyCheckFailed }: DeviceCompromisedProps) => {
- const dispatch = useDispatch();
- const { device } = useDevice();
-
- const securityCheckFailProps = useSecurityCheckFailProps(isEntropyCheckFailed);
-
- const goToSuite = () => {
- // Condition to satisfy TypeScript, device.id is always defined at this point.
- if (device?.id) {
- dispatch(deviceActions.dismissFirmwareAuthenticityCheck(device.id));
- }
- };
+export const DeviceCompromised = () => {
+ const securityCheckFailProps = useSecurityCheckFailProps();
return (
-
+
);
diff --git a/packages/suite/src/reducers/suite/suiteReducer.ts b/packages/suite/src/reducers/suite/suiteReducer.ts
index 50293f3609d..6715eb71b57 100644
--- a/packages/suite/src/reducers/suite/suiteReducer.ts
+++ b/packages/suite/src/reducers/suite/suiteReducer.ts
@@ -4,7 +4,12 @@ import { Feature, selectIsFeatureDisabled } from '@suite-common/message-system';
import { isDeviceAcquired } from '@suite-common/suite-utils';
import type { InvityServerEnvironment } from '@suite-common/trading';
import { NetworkSymbol } from '@suite-common/wallet-config';
-import { DeviceRootState, discoveryActions, selectSelectedDevice } from '@suite-common/wallet-core';
+import {
+ DeviceRootState,
+ discoveryActions,
+ selectIsEntropyCheckFailed,
+ selectSelectedDevice,
+} from '@suite-common/wallet-core';
import { AddressDisplayOptions, WalletType } from '@suite-common/wallet-types';
import { ConnectSettings, InstallerInfo, TRANSPORT, TransportInfo } from '@trezor/connect';
import { isWeb } from '@trezor/env-utils';
@@ -577,4 +582,18 @@ export const selectIsFirmwareAuthenticityCheckEnabledAndHardFailed = (state: App
return isRevisionHardError || isHashHardError;
};
+/**
+ * Return true if entropy check has failed and is not disabled via settings nor message system.
+ */
+export const selectIsEntropyCheckEnabledAndFailed = (state: AppState) => {
+ const isEntropyCheckEnabled = selectIsEntropyCheckEnabled(state);
+ const isEntropyCheckDisabledByMessageSystem = selectIsFeatureDisabled(
+ state,
+ Feature.entropyCheck,
+ );
+ const isEntropyCheckFailed = selectIsEntropyCheckFailed(state);
+
+ return isEntropyCheckEnabled && !isEntropyCheckDisabledByMessageSystem && isEntropyCheckFailed;
+};
+
export default suiteReducer;