diff --git a/app/component-library/components-temp/Price/AggregatedPercentage/AggregatedPercentage.constants.ts b/app/component-library/components-temp/Price/AggregatedPercentage/AggregatedPercentage.constants.ts
new file mode 100644
index 00000000000..52b0b69960a
--- /dev/null
+++ b/app/component-library/components-temp/Price/AggregatedPercentage/AggregatedPercentage.constants.ts
@@ -0,0 +1,2 @@
+export const FORMATTED_VALUE_PRICE_TEST_ID = 'formatted-value-price-test-id';
+export const FORMATTED_PERCENTAGE_TEST_ID = 'formatted-percentage-test-id';
diff --git a/app/component-library/components-temp/Price/AggregatedPercentage/AggregatedPercentage.test.tsx b/app/component-library/components-temp/Price/AggregatedPercentage/AggregatedPercentage.test.tsx
index affec361321..ac0bdb30a2e 100644
--- a/app/component-library/components-temp/Price/AggregatedPercentage/AggregatedPercentage.test.tsx
+++ b/app/component-library/components-temp/Price/AggregatedPercentage/AggregatedPercentage.test.tsx
@@ -4,6 +4,10 @@ import AggregatedPercentage from './AggregatedPercentage';
import { mockTheme } from '../../../../util/theme';
import { useSelector } from 'react-redux';
import { selectCurrentCurrency } from '../../../../selectors/currencyRateController';
+import {
+ FORMATTED_VALUE_PRICE_TEST_ID,
+ FORMATTED_PERCENTAGE_TEST_ID,
+} from './AggregatedPercentage.constants';
jest.mock('react-redux', () => ({
...jest.requireActual('react-redux'),
@@ -65,4 +69,22 @@ describe('AggregatedPercentage', () => {
color: mockTheme.colors.error.default,
});
});
+
+ it('renders correctly with privacy mode on', () => {
+ const { getByTestId } = render(
+ ,
+ );
+
+ const formattedPercentage = getByTestId(FORMATTED_PERCENTAGE_TEST_ID);
+ const formattedValuePrice = getByTestId(FORMATTED_VALUE_PRICE_TEST_ID);
+
+ expect(formattedPercentage.props.children).toBe('••••••••••');
+ expect(formattedValuePrice.props.children).toBe('••••••••••');
+ });
});
diff --git a/app/component-library/components-temp/Price/AggregatedPercentage/AggregatedPercentage.tsx b/app/component-library/components-temp/Price/AggregatedPercentage/AggregatedPercentage.tsx
index c2a94c1bc1a..715587f6ddc 100644
--- a/app/component-library/components-temp/Price/AggregatedPercentage/AggregatedPercentage.tsx
+++ b/app/component-library/components-temp/Price/AggregatedPercentage/AggregatedPercentage.tsx
@@ -1,14 +1,19 @@
import React from 'react';
-import Text, {
+import {
TextColor,
TextVariant,
} from '../../../../component-library/components/Texts/Text';
+import SensitiveText from '../../../../component-library/components/Texts/SensitiveText';
import { View } from 'react-native';
import { renderFiat } from '../../../../util/number';
import { useSelector } from 'react-redux';
import { selectCurrentCurrency } from '../../../../selectors/currencyRateController';
import styleSheet from './AggregatedPercentage.styles';
import { useStyles } from '../../../hooks';
+import {
+ FORMATTED_VALUE_PRICE_TEST_ID,
+ FORMATTED_PERCENTAGE_TEST_ID,
+} from './AggregatedPercentage.constants';
export interface AggregatedPercentageProps {
ethFiat: number;
@@ -25,11 +30,13 @@ const AggregatedPercentage = ({
tokenFiat,
tokenFiat1dAgo,
ethFiat1dAgo,
+ privacyMode = false,
}: {
ethFiat: number;
tokenFiat: number;
tokenFiat1dAgo: number;
ethFiat1dAgo: number;
+ privacyMode?: boolean;
}) => {
const { styles } = useStyles(styleSheet, {});
@@ -46,12 +53,16 @@ const AggregatedPercentage = ({
let percentageTextColor = TextColor.Default;
- if (percentageChange === 0) {
- percentageTextColor = TextColor.Default;
- } else if (percentageChange > 0) {
- percentageTextColor = TextColor.Success;
+ if (!privacyMode) {
+ if (percentageChange === 0) {
+ percentageTextColor = TextColor.Default;
+ } else if (percentageChange > 0) {
+ percentageTextColor = TextColor.Success;
+ } else {
+ percentageTextColor = TextColor.Error;
+ }
} else {
- percentageTextColor = TextColor.Error;
+ percentageTextColor = TextColor.Alternative;
}
const formattedPercentage = isValidAmount(percentageChange)
@@ -70,12 +81,24 @@ const AggregatedPercentage = ({
return (
-
+
{formattedValuePrice}
-
-
+
+
{formattedPercentage}
-
+
);
};
diff --git a/app/component-library/components-temp/Price/AggregatedPercentage/__snapshots__/AggregatedPercentage.test.tsx.snap b/app/component-library/components-temp/Price/AggregatedPercentage/__snapshots__/AggregatedPercentage.test.tsx.snap
index 16b825b0e5d..1066d19a41b 100644
--- a/app/component-library/components-temp/Price/AggregatedPercentage/__snapshots__/AggregatedPercentage.test.tsx.snap
+++ b/app/component-library/components-temp/Price/AggregatedPercentage/__snapshots__/AggregatedPercentage.test.tsx.snap
@@ -21,6 +21,7 @@ exports[`AggregatedPercentage should render correctly 1`] = `
"lineHeight": 22,
}
}
+ testID="formatted-value-price-test-id"
>
+20 USD
@@ -36,6 +37,7 @@ exports[`AggregatedPercentage should render correctly 1`] = `
"lineHeight": 22,
}
}
+ testID="formatted-percentage-test-id"
>
(+11.11%)
diff --git a/app/component-library/components/Texts/SensitiveText/SensitiveText.types.ts b/app/component-library/components/Texts/SensitiveText/SensitiveText.types.ts
index 1c6f4688b78..927acd91279 100644
--- a/app/component-library/components/Texts/SensitiveText/SensitiveText.types.ts
+++ b/app/component-library/components/Texts/SensitiveText/SensitiveText.types.ts
@@ -1,4 +1,5 @@
// External dependencies.
+import React from 'react';
import { TextProps } from '../Text/Text.types';
/**
@@ -42,5 +43,5 @@ export interface SensitiveTextProps extends TextProps {
/**
* The text content to be displayed or hidden.
*/
- children: string;
+ children: React.ReactNode;
}
diff --git a/app/components/UI/AccountSelectorList/AccountSelectorList.styles.ts b/app/components/UI/AccountSelectorList/AccountSelectorList.styles.ts
index 90c0ffedf6d..a1103280571 100644
--- a/app/components/UI/AccountSelectorList/AccountSelectorList.styles.ts
+++ b/app/components/UI/AccountSelectorList/AccountSelectorList.styles.ts
@@ -13,6 +13,7 @@ const styleSheet = () =>
StyleSheet.create({
balancesContainer: {
alignItems: 'flex-end',
+ flexDirection: 'column',
},
balanceLabel: { textAlign: 'right' },
});
diff --git a/app/components/UI/AccountSelectorList/AccountSelectorList.tsx b/app/components/UI/AccountSelectorList/AccountSelectorList.tsx
index 53e2bef5f2e..f8212feda79 100644
--- a/app/components/UI/AccountSelectorList/AccountSelectorList.tsx
+++ b/app/components/UI/AccountSelectorList/AccountSelectorList.tsx
@@ -11,7 +11,11 @@ import Cell, {
CellVariant,
} from '../../../component-library/components/Cells/Cell';
import { useStyles } from '../../../component-library/hooks';
-import Text from '../../../component-library/components/Texts/Text';
+import { selectPrivacyMode } from '../../../selectors/preferencesController';
+import { TextColor } from '../../../component-library/components/Texts/Text';
+import SensitiveText, {
+ SensitiveTextLength,
+} from '../../../component-library/components/Texts/SensitiveText';
import AvatarGroup from '../../../component-library/components/Avatars/AvatarGroup';
import {
formatAddress,
@@ -60,27 +64,46 @@ const AccountSelectorList = ({
? AvatarAccountType.Blockies
: AvatarAccountType.JazzIcon,
);
-
+ const privacyMode = useSelector(selectPrivacyMode);
const getKeyExtractor = ({ address }: Account) => address;
const renderAccountBalances = useCallback(
- ({ fiatBalance, tokens }: Assets, address: string) => (
-
- {fiatBalance}
- {tokens && (
- ({
- ...tokenObj,
- variant: AvatarVariant.Token,
- }))}
- />
- )}
-
- ),
- [styles.balancesContainer, styles.balanceLabel],
+ ({ fiatBalance, tokens }: Assets, address: string) => {
+ const fiatBalanceStrSplit = fiatBalance.split('\n');
+ const fiatBalanceAmount = fiatBalanceStrSplit[0] || '';
+ const tokenTicker = fiatBalanceStrSplit[1] || '';
+ return (
+
+
+ {fiatBalanceAmount}
+
+
+ {tokenTicker}
+
+ {tokens && (
+ ({
+ ...tokenObj,
+ variant: AvatarVariant.Token,
+ }))}
+ />
+ )}
+
+ );
+ },
+ [styles.balancesContainer, styles.balanceLabel, privacyMode],
);
const onLongPress = useCallback(
diff --git a/app/components/UI/AccountSelectorList/__snapshots__/AccountSelector.test.tsx.snap b/app/components/UI/AccountSelectorList/__snapshots__/AccountSelector.test.tsx.snap
index 49c9d6e96b1..036a2be8d53 100644
--- a/app/components/UI/AccountSelectorList/__snapshots__/AccountSelector.test.tsx.snap
+++ b/app/components/UI/AccountSelectorList/__snapshots__/AccountSelector.test.tsx.snap
@@ -290,6 +290,7 @@ exports[`AccountSelectorList renders all accounts with balances 1`] = `
style={
{
"alignItems": "flex-end",
+ "flexDirection": "column",
}
}
testID="account-balance-by-address-0xC4955C0d639D99699Bfd7Ec54d9FaFEe40e4D272"
@@ -309,7 +310,22 @@ exports[`AccountSelectorList renders all accounts with balances 1`] = `
}
>
$3200.00
-1 ETH
+
+
+ 1 ETH
@@ -583,6 +599,7 @@ exports[`AccountSelectorList renders all accounts with balances 1`] = `
style={
{
"alignItems": "flex-end",
+ "flexDirection": "column",
}
}
testID="account-balance-by-address-0xd018538C87232FF95acbCe4870629b75640a78E7"
@@ -602,7 +619,22 @@ exports[`AccountSelectorList renders all accounts with balances 1`] = `
}
>
$6400.00
-2 ETH
+
+
+ 2 ETH
@@ -1453,6 +1485,7 @@ exports[`AccountSelectorList renders correctly 1`] = `
style={
{
"alignItems": "flex-end",
+ "flexDirection": "column",
}
}
testID="account-balance-by-address-0xC4955C0d639D99699Bfd7Ec54d9FaFEe40e4D272"
@@ -1472,7 +1505,22 @@ exports[`AccountSelectorList renders correctly 1`] = `
}
>
$3200.00
-1 ETH
+
+
+ 1 ETH
@@ -1746,6 +1794,7 @@ exports[`AccountSelectorList renders correctly 1`] = `
style={
{
"alignItems": "flex-end",
+ "flexDirection": "column",
}
}
testID="account-balance-by-address-0xd018538C87232FF95acbCe4870629b75640a78E7"
@@ -1765,7 +1814,22 @@ exports[`AccountSelectorList renders correctly 1`] = `
}
>
$6400.00
-2 ETH
+
+
+ 2 ETH
@@ -1949,6 +2013,7 @@ exports[`AccountSelectorList should render all accounts but only the balance for
style={
{
"alignItems": "flex-end",
+ "flexDirection": "column",
}
}
testID="account-balance-by-address-0xC4955C0d639D99699Bfd7Ec54d9FaFEe40e4D272"
@@ -1968,7 +2033,22 @@ exports[`AccountSelectorList should render all accounts but only the balance for
}
>
$3200.00
-1 ETH
+
+
+ 1 ETH
diff --git a/app/components/UI/AssetElement/index.constants.ts b/app/components/UI/AssetElement/index.constants.ts
new file mode 100644
index 00000000000..1b14c68f51c
--- /dev/null
+++ b/app/components/UI/AssetElement/index.constants.ts
@@ -0,0 +1,2 @@
+export const FIAT_BALANCE_TEST_ID = 'fiat-balance-test-id';
+export const MAIN_BALANCE_TEST_ID = 'main-balance-test-id';
diff --git a/app/components/UI/AssetElement/index.test.tsx b/app/components/UI/AssetElement/index.test.tsx
index 1d178a7f4c3..e664027b309 100644
--- a/app/components/UI/AssetElement/index.test.tsx
+++ b/app/components/UI/AssetElement/index.test.tsx
@@ -3,6 +3,7 @@ import { shallow } from 'enzyme';
import { render, fireEvent } from '@testing-library/react-native';
import AssetElement from './';
import { getAssetTestId } from '../../../../wdio/screen-objects/testIDs/Screens/WalletView.testIds';
+import { FIAT_BALANCE_TEST_ID, MAIN_BALANCE_TEST_ID } from './index.constants';
describe('AssetElement', () => {
const onPressMock = jest.fn();
@@ -54,4 +55,34 @@ describe('AssetElement', () => {
expect(onLongPressMock).toHaveBeenCalledWith(erc20Token);
});
+
+ it('renders the fiat and token balance', () => {
+ const { getByTestId } = render(
+ ,
+ );
+
+ expect(getByTestId(FIAT_BALANCE_TEST_ID)).toBeDefined();
+ expect(getByTestId(MAIN_BALANCE_TEST_ID)).toBeDefined();
+ });
+
+ it('renders the fiat balance with privacy mode', () => {
+ const { getByTestId } = render(
+ ,
+ );
+
+ const fiatBalance = getByTestId(FIAT_BALANCE_TEST_ID);
+ const mainBalance = getByTestId(MAIN_BALANCE_TEST_ID);
+
+ expect(fiatBalance.props.children).toBe('•••••••••');
+ expect(mainBalance.props.children).toBe('••••••');
+ });
});
diff --git a/app/components/UI/AssetElement/index.tsx b/app/components/UI/AssetElement/index.tsx
index a2810c48db0..ff39a4eac1a 100644
--- a/app/components/UI/AssetElement/index.tsx
+++ b/app/components/UI/AssetElement/index.tsx
@@ -1,9 +1,7 @@
/* eslint-disable react/prop-types */
import React from 'react';
import { TouchableOpacity, StyleSheet, Platform, View } from 'react-native';
-import Text, {
- TextVariant,
-} from '../../../component-library/components/Texts/Text';
+import { TextVariant } from '../../../component-library/components/Texts/Text';
import SkeletonText from '../Ramp/components/SkeletonText';
import { TokenI } from '../Tokens/types';
import generateTestId from '../../../../wdio/utils/generateTestId';
@@ -15,6 +13,10 @@ import {
import { Colors } from '../../../util/theme/models';
import { fontStyles } from '../../../styles/common';
import { useTheme } from '../../../util/theme';
+import SensitiveText, {
+ SensitiveTextLength,
+} from '../../../component-library/components/Texts/SensitiveText';
+import { FIAT_BALANCE_TEST_ID, MAIN_BALANCE_TEST_ID } from './index.constants';
interface AssetElementProps {
children?: React.ReactNode;
@@ -23,6 +25,7 @@ interface AssetElementProps {
onLongPress?: ((asset: TokenI) => void) | null;
balance?: string;
mainBalance?: string | null;
+ privacyMode?: boolean;
}
const createStyles = (colors: Colors) =>
@@ -63,6 +66,7 @@ const AssetElement: React.FC = ({
mainBalance = null,
onPress,
onLongPress,
+ privacyMode = false,
}) => {
const { colors } = useTheme();
const styles = createStyles(colors);
@@ -75,6 +79,8 @@ const AssetElement: React.FC = ({
onLongPress?.(asset);
};
+ // TODO: Use the SensitiveText component when it's available
+ // when privacyMode is true, we should hide the balance and the fiat
return (
= ({
{balance && (
-
{balance === TOKEN_BALANCE_LOADING ? (
) : (
balance
)}
-
+
)}
{mainBalance ? (
-
+
{mainBalance === TOKEN_BALANCE_LOADING ? (
) : (
mainBalance
)}
-
+
) : null}
diff --git a/app/components/UI/AssetOverview/Balance/__snapshots__/index.test.tsx.snap b/app/components/UI/AssetOverview/Balance/__snapshots__/index.test.tsx.snap
index d233e8e44fd..0a66cea0de2 100644
--- a/app/components/UI/AssetOverview/Balance/__snapshots__/index.test.tsx.snap
+++ b/app/components/UI/AssetOverview/Balance/__snapshots__/index.test.tsx.snap
@@ -203,6 +203,7 @@ exports[`Balance should render correctly with a fiat balance 1`] = `
"lineHeight": 24,
}
}
+ testID="fiat-balance-test-id"
>
456
@@ -220,6 +221,7 @@ exports[`Balance should render correctly with a fiat balance 1`] = `
"textTransform": "uppercase",
}
}
+ testID="main-balance-test-id"
>
123
@@ -433,6 +435,7 @@ exports[`Balance should render correctly without a fiat balance 1`] = `
"textTransform": "uppercase",
}
}
+ testID="main-balance-test-id"
>
123
diff --git a/app/components/UI/AssetOverview/__snapshots__/AssetOverview.test.tsx.snap b/app/components/UI/AssetOverview/__snapshots__/AssetOverview.test.tsx.snap
index 5ec60e73b6f..40327fba228 100644
--- a/app/components/UI/AssetOverview/__snapshots__/AssetOverview.test.tsx.snap
+++ b/app/components/UI/AssetOverview/__snapshots__/AssetOverview.test.tsx.snap
@@ -1060,6 +1060,7 @@ exports[`AssetOverview should render correctly 1`] = `
"textTransform": "uppercase",
}
}
+ testID="main-balance-test-id"
>
0 ETH
diff --git a/app/components/UI/Tokens/TokenList/PortfolioBalance/index.constants.ts b/app/components/UI/Tokens/TokenList/PortfolioBalance/index.constants.ts
new file mode 100644
index 00000000000..16f1ef78e5c
--- /dev/null
+++ b/app/components/UI/Tokens/TokenList/PortfolioBalance/index.constants.ts
@@ -0,0 +1,2 @@
+export const EYE_SLASH_ICON_TEST_ID = 'eye-slash-icon';
+export const EYE_ICON_TEST_ID = 'eye-icon';
diff --git a/app/components/UI/Tokens/TokenList/PortfolioBalance/index.test.tsx b/app/components/UI/Tokens/TokenList/PortfolioBalance/index.test.tsx
index e1e1f694376..31c2beee9cf 100644
--- a/app/components/UI/Tokens/TokenList/PortfolioBalance/index.test.tsx
+++ b/app/components/UI/Tokens/TokenList/PortfolioBalance/index.test.tsx
@@ -7,6 +7,10 @@ import AppConstants from '../../../../../../app/core/AppConstants';
import Routes from '../../../../../../app/constants/navigation/Routes';
import { WalletViewSelectorsIDs } from '../../../../../../e2e/selectors/wallet/WalletView.selectors';
import { PortfolioBalance } from '.';
+import Engine from '../../../../../core/Engine';
+import { EYE_SLASH_ICON_TEST_ID, EYE_ICON_TEST_ID } from './index.constants';
+
+const { PreferencesController } = Engine.context;
jest.mock('../../../../../core/Engine', () => ({
getTotalFiatAccountBalance: jest.fn(),
@@ -14,6 +18,9 @@ jest.mock('../../../../../core/Engine', () => ({
TokensController: {
ignoreTokens: jest.fn(() => Promise.resolve()),
},
+ PreferencesController: {
+ setPrivacyMode: jest.fn(),
+ },
},
}));
@@ -138,4 +145,95 @@ describe('PortfolioBalance', () => {
screen: Routes.BROWSER.VIEW,
});
});
+
+ it('renders sensitive text when privacy mode is off', () => {
+ const { getByTestId } = renderPortfolioBalance({
+ ...initialState,
+ engine: {
+ backgroundState: {
+ ...initialState.engine.backgroundState,
+ PreferencesController: {
+ privacyMode: false,
+ },
+ },
+ },
+ });
+ const sensitiveText = getByTestId(
+ WalletViewSelectorsIDs.TOTAL_BALANCE_TEXT,
+ );
+ expect(sensitiveText.props.isHidden).toBeFalsy();
+ });
+
+ it('hides sensitive text when privacy mode is on', () => {
+ const { getByTestId } = renderPortfolioBalance({
+ ...initialState,
+ engine: {
+ backgroundState: {
+ ...initialState.engine.backgroundState,
+ PreferencesController: {
+ privacyMode: true,
+ },
+ },
+ },
+ });
+ const sensitiveText = getByTestId(
+ WalletViewSelectorsIDs.TOTAL_BALANCE_TEXT,
+ );
+ expect(sensitiveText.props.children).toEqual('••••••••••••');
+ });
+
+ it('toggles privacy mode when eye icon is pressed', () => {
+ const { getByTestId } = renderPortfolioBalance({
+ ...initialState,
+ engine: {
+ backgroundState: {
+ ...initialState.engine.backgroundState,
+ PreferencesController: {
+ privacyMode: false,
+ },
+ },
+ },
+ });
+
+ const balanceContainer = getByTestId('balance-container');
+ fireEvent.press(balanceContainer);
+
+ expect(PreferencesController.setPrivacyMode).toHaveBeenCalledWith(true);
+ });
+
+ it('renders eye icon when privacy mode is off', () => {
+ const { getByTestId } = renderPortfolioBalance({
+ ...initialState,
+ engine: {
+ backgroundState: {
+ ...initialState.engine.backgroundState,
+ PreferencesController: {
+ privacyMode: false,
+ },
+ },
+ },
+ });
+
+ const eyeIcon = getByTestId(EYE_ICON_TEST_ID);
+ expect(eyeIcon).toBeDefined();
+ expect(eyeIcon.props.name).toBe('Eye');
+ });
+
+ it('renders eye-slash icon when privacy mode is on', () => {
+ const { getByTestId } = renderPortfolioBalance({
+ ...initialState,
+ engine: {
+ backgroundState: {
+ ...initialState.engine.backgroundState,
+ PreferencesController: {
+ privacyMode: true,
+ },
+ },
+ },
+ });
+
+ const eyeSlashIcon = getByTestId(EYE_SLASH_ICON_TEST_ID);
+ expect(eyeSlashIcon).toBeDefined();
+ expect(eyeSlashIcon.props.name).toBe('EyeSlash');
+ });
});
diff --git a/app/components/UI/Tokens/TokenList/PortfolioBalance/index.tsx b/app/components/UI/Tokens/TokenList/PortfolioBalance/index.tsx
index 06729279ac3..5da53e48066 100644
--- a/app/components/UI/Tokens/TokenList/PortfolioBalance/index.tsx
+++ b/app/components/UI/Tokens/TokenList/PortfolioBalance/index.tsx
@@ -1,5 +1,5 @@
import React from 'react';
-import { View } from 'react-native';
+import { View, TouchableOpacity } from 'react-native';
import { useNavigation } from '@react-navigation/native';
import { useSelector } from 'react-redux';
import useIsOriginalNativeTokenSymbol from '../../../../hooks/useIsOriginalNativeTokenSymbol/useIsOriginalNativeTokenSymbol';
@@ -15,6 +15,7 @@ import {
selectTicker,
} from '../../../../../selectors/networkController';
import { selectCurrentCurrency } from '../../../../../selectors/currencyRateController';
+import { selectPrivacyMode } from '../../../../../selectors/preferencesController';
import { RootState } from '../../../../../reducers';
import { renderFiat } from '../../../../../util/number';
import { isTestNet } from '../../../../../util/networks';
@@ -25,16 +26,22 @@ import Button, {
ButtonSize,
ButtonWidthTypes,
} from '../../../../../component-library/components/Buttons/Button';
-import Text, {
- TextVariant,
-} from '../../../../../component-library/components/Texts/Text';
+import { TextVariant } from '../../../../../component-library/components/Texts/Text';
+import SensitiveText, {
+ SensitiveTextLength,
+} from '../../../../../component-library/components/Texts/SensitiveText';
import AggregatedPercentage from '../../../../../component-library/components-temp/Price/AggregatedPercentage';
-import { IconName } from '../../../../../component-library/components/Icons/Icon';
+import Icon, {
+ IconSize,
+ IconName,
+} from '../../../../../component-library/components/Icons/Icon';
import { BrowserTab } from '../../types';
import { WalletViewSelectorsIDs } from '../../../../../../e2e/selectors/wallet/WalletView.selectors';
import { strings } from '../../../../../../locales/i18n';
+import { EYE_SLASH_ICON_TEST_ID, EYE_ICON_TEST_ID } from './index.constants';
export const PortfolioBalance = () => {
+ const { PreferencesController } = Engine.context;
const { colors } = useTheme();
const styles = createStyles(colors);
const balance = Engine.getTotalFiatAccountBalance();
@@ -49,6 +56,7 @@ export const PortfolioBalance = () => {
);
const currentCurrency = useSelector(selectCurrentCurrency);
const browserTabs = useSelector((state: RootState) => state.browser.tabs);
+ const privacyMode = useSelector(selectPrivacyMode);
const isOriginalNativeTokenSymbol = useIsOriginalNativeTokenSymbol(
chainId,
@@ -108,35 +116,68 @@ export const PortfolioBalance = () => {
});
};
+ const renderAggregatedPercentage = () => {
+ if (isTestNet(chainId)) {
+ return null;
+ }
+
+ return (
+
+ );
+ };
+
+ const toggleIsBalanceAndAssetsHidden = (value: boolean) => {
+ PreferencesController.setPrivacyMode(value);
+ };
+
return (
-
- {fiatBalance}
-
+
+
+
+ {fiatBalance}
+
+ toggleIsBalanceAndAssetsHidden(!privacyMode)}
+ testID="balance-container"
+ >
+
+
+
- {!isTestNet(chainId) ? (
-
- ) : null}
+ {renderAggregatedPercentage()}
+
+
+
+
-
);
};
diff --git a/app/components/UI/Tokens/TokenList/TokenListItem/index.tsx b/app/components/UI/Tokens/TokenList/TokenListItem/index.tsx
index 46f5322c377..651bebf7f7f 100644
--- a/app/components/UI/Tokens/TokenList/TokenListItem/index.tsx
+++ b/app/components/UI/Tokens/TokenList/TokenListItem/index.tsx
@@ -55,6 +55,7 @@ interface TokenListItemProps {
showScamWarningModal: boolean;
showRemoveMenu: (arg: TokenI) => void;
setShowScamWarningModal: (arg: boolean) => void;
+ privacyMode: boolean;
}
export const TokenListItem = ({
@@ -62,6 +63,7 @@ export const TokenListItem = ({
showScamWarningModal,
showRemoveMenu,
setShowScamWarningModal,
+ privacyMode,
}: TokenListItemProps) => {
const navigation = useNavigation();
const { colors } = useTheme();
@@ -182,6 +184,7 @@ export const TokenListItem = ({
asset={asset}
balance={secondaryBalance}
mainBalance={mainBalance}
+ privacyMode={privacyMode}
>
)}
keyExtractor={(_, index) => index.toString()}
diff --git a/app/components/UI/Tokens/__snapshots__/index.test.tsx.snap b/app/components/UI/Tokens/__snapshots__/index.test.tsx.snap
index 05f8d2ad9b5..e9e7f0f4b15 100644
--- a/app/components/UI/Tokens/__snapshots__/index.test.tsx.snap
+++ b/app/components/UI/Tokens/__snapshots__/index.test.tsx.snap
@@ -865,6 +865,7 @@ exports[`Tokens should hide zero balance tokens when setting is on 1`] = `
"lineHeight": 24,
}
}
+ testID="fiat-balance-test-id"
>
ETH
@@ -882,6 +883,7 @@ exports[`Tokens should hide zero balance tokens when setting is on 1`] = `
"textTransform": "uppercase",
}
}
+ testID="main-balance-test-id"
>
< $0.01
@@ -1129,6 +1131,7 @@ exports[`Tokens should hide zero balance tokens when setting is on 1`] = `
"lineHeight": 24,
}
}
+ testID="fiat-balance-test-id"
>
< 0.00001 BAT
@@ -1146,6 +1149,7 @@ exports[`Tokens should hide zero balance tokens when setting is on 1`] = `
"textTransform": "uppercase",
}
}
+ testID="main-balance-test-id"
>
< $0.01
@@ -2107,6 +2111,7 @@ exports[`Tokens should render correctly 1`] = `
"lineHeight": 24,
}
}
+ testID="fiat-balance-test-id"
>
ETH
@@ -2124,6 +2129,7 @@ exports[`Tokens should render correctly 1`] = `
"textTransform": "uppercase",
}
}
+ testID="main-balance-test-id"
>
< $0.01
@@ -2371,6 +2377,7 @@ exports[`Tokens should render correctly 1`] = `
"lineHeight": 24,
}
}
+ testID="fiat-balance-test-id"
>
< 0.00001 BAT
@@ -2388,6 +2395,7 @@ exports[`Tokens should render correctly 1`] = `
"textTransform": "uppercase",
}
}
+ testID="main-balance-test-id"
>
< $0.01
@@ -3367,6 +3375,7 @@ exports[`Tokens should show all balance tokens when hideZeroBalanceTokens settin
"lineHeight": 24,
}
}
+ testID="fiat-balance-test-id"
>
ETH
@@ -3384,6 +3393,7 @@ exports[`Tokens should show all balance tokens when hideZeroBalanceTokens settin
"textTransform": "uppercase",
}
}
+ testID="main-balance-test-id"
>
< $0.01
@@ -3631,6 +3641,7 @@ exports[`Tokens should show all balance tokens when hideZeroBalanceTokens settin
"lineHeight": 24,
}
}
+ testID="fiat-balance-test-id"
>
< 0.00001 BAT
@@ -3648,6 +3659,7 @@ exports[`Tokens should show all balance tokens when hideZeroBalanceTokens settin
"textTransform": "uppercase",
}
}
+ testID="main-balance-test-id"
>
< $0.01
@@ -3895,6 +3907,7 @@ exports[`Tokens should show all balance tokens when hideZeroBalanceTokens settin
"lineHeight": 24,
}
}
+ testID="fiat-balance-test-id"
>
0 LINK
@@ -3912,6 +3925,7 @@ exports[`Tokens should show all balance tokens when hideZeroBalanceTokens settin
"textTransform": "uppercase",
}
}
+ testID="main-balance-test-id"
>
< $0.01
diff --git a/app/components/UI/Tokens/styles.ts b/app/components/UI/Tokens/styles.ts
index c5e907b102d..b0d18658d5d 100644
--- a/app/components/UI/Tokens/styles.ts
+++ b/app/components/UI/Tokens/styles.ts
@@ -164,6 +164,16 @@ const createStyles = (colors: Colors) =>
borderStyle: 'solid',
borderWidth: 1,
},
+ balanceContainer: {
+ flexDirection: 'row',
+ alignItems: 'center',
+ },
+ privacyIcon: {
+ marginLeft: 8,
+ },
+ portfolioButtonContainer: {
+ alignItems: 'center',
+ },
});
export default createStyles;
diff --git a/app/selectors/preferencesController.ts b/app/selectors/preferencesController.ts
index 3f46e968dfa..2d7ae6b4a8e 100644
--- a/app/selectors/preferencesController.ts
+++ b/app/selectors/preferencesController.ts
@@ -114,3 +114,9 @@ export const selectUseTransactionSimulations = createSelector(
}
).useTransactionSimulations,
);
+
+export const selectPrivacyMode = createSelector(
+ selectPreferencesControllerState,
+ (preferencesControllerState: PreferencesState) =>
+ preferencesControllerState.privacyMode,
+);
diff --git a/app/util/test/initial-background-state.json b/app/util/test/initial-background-state.json
index 86ac80cef68..93bcf8fd60a 100644
--- a/app/util/test/initial-background-state.json
+++ b/app/util/test/initial-background-state.json
@@ -199,7 +199,8 @@
"key": "tokenFiatAmount",
"order": "dsc",
"sortCallback": "stringNumeric"
- }
+ },
+ "privacyMode": false
},
"TokenBalancesController": {
"contractBalances": {}
diff --git a/bitrise.yml b/bitrise.yml
index 2c85f6e5e38..67dd1873222 100644
--- a/bitrise.yml
+++ b/bitrise.yml
@@ -1576,7 +1576,7 @@ app:
meta:
bitrise.io:
stack: osx-xcode-15.0.x
- machine_type_id: g2-m1-max.5core
+ machine_type_id: g2.mac.large
trigger_map:
- push_branch: release/*
pipeline: pr_regression_e2e_pipeline
diff --git a/patches/@metamask+preferences-controller+11.0.0.patch b/patches/@metamask+preferences-controller+11.0.0.patch
index 16c14a2b5e9..6e711d24199 100644
--- a/patches/@metamask+preferences-controller+11.0.0.patch
+++ b/patches/@metamask+preferences-controller+11.0.0.patch
@@ -1,8 +1,8 @@
diff --git a/node_modules/@metamask/preferences-controller/dist/chunk-FSWGV6H6.js b/node_modules/@metamask/preferences-controller/dist/chunk-FSWGV6H6.js
-index 30e985c..ec9db71 100644
+index 30e985c..8dabed3 100644
--- a/node_modules/@metamask/preferences-controller/dist/chunk-FSWGV6H6.js
+++ b/node_modules/@metamask/preferences-controller/dist/chunk-FSWGV6H6.js
-@@ -17,13 +17,18 @@ var metadata = {
+@@ -17,13 +17,19 @@ var metadata = {
isIpfsGatewayEnabled: { persist: true, anonymous: true },
isMultiAccountBalancesEnabled: { persist: true, anonymous: true },
lostIdentities: { persist: true, anonymous: false },
@@ -19,11 +19,12 @@ index 30e985c..ec9db71 100644
+ smartTransactionsOptInStatus: { persist: true, anonymous: true },
+ useTransactionSimulations: { persist: true, anonymous: true },
+ showMultiRpcModal: { persist: false, anonymous: false },
-+ tokenSortConfig: { persist: true, anonymous: false }
++ tokenSortConfig: { persist: true, anonymous: false },
++ privacyMode: { persist: true, anonymous: true },
};
var name = "PreferencesController";
function getDefaultPreferencesState() {
-@@ -37,7 +42,7 @@ function getDefaultPreferencesState() {
+@@ -37,7 +43,7 @@ function getDefaultPreferencesState() {
isIpfsGatewayEnabled: true,
isMultiAccountBalancesEnabled: true,
lostIdentities: {},
@@ -32,7 +33,7 @@ index 30e985c..ec9db71 100644
securityAlertsEnabled: false,
selectedAddress: "",
showIncomingTransactions: {
-@@ -64,7 +69,16 @@ function getDefaultPreferencesState() {
+@@ -64,7 +70,17 @@ function getDefaultPreferencesState() {
},
showTestNetworks: false,
useNftDetection: false,
@@ -43,14 +44,15 @@ index 30e985c..ec9db71 100644
+ useTransactionSimulations: true,
+ showMultiRpcModal: false,
+ tokenSortConfig: {
-+ key: "tokenFiatBalance",
-+ order: 'dsc',
-+ sortCallback: 'stringNumeric',
-+ }
++ key: "tokenFiatBalance",
++ order: 'dsc',
++ sortCallback: 'stringNumeric',
++ },
++ privacyMode: false,
};
}
var _syncIdentities, syncIdentities_fn;
-@@ -213,9 +227,9 @@ var PreferencesController = class extends _basecontroller.BaseController {
+@@ -213,9 +229,9 @@ var PreferencesController = class extends _basecontroller.BaseController {
* @param useNftDetection - Boolean indicating user preference on NFT detection.
*/
setUseNftDetection(useNftDetection) {
@@ -62,7 +64,7 @@ index 30e985c..ec9db71 100644
);
}
this.update((state) => {
-@@ -223,18 +237,33 @@ var PreferencesController = class extends _basecontroller.BaseController {
+@@ -223,18 +239,33 @@ var PreferencesController = class extends _basecontroller.BaseController {
});
}
/**
@@ -101,7 +103,7 @@ index 30e985c..ec9db71 100644
/**
* Toggle the security alert enabled setting.
*
-@@ -245,6 +274,43 @@ var PreferencesController = class extends _basecontroller.BaseController {
+@@ -245,6 +276,43 @@ var PreferencesController = class extends _basecontroller.BaseController {
state.securityAlertsEnabled = securityAlertsEnabled;
});
}
@@ -145,10 +147,11 @@ index 30e985c..ec9db71 100644
/**
* A setter for the user preferences to enable/disable rpc methods.
*
-@@ -307,6 +373,16 @@ var PreferencesController = class extends _basecontroller.BaseController {
+@@ -307,6 +375,26 @@ var PreferencesController = class extends _basecontroller.BaseController {
});
}
}
++
+ /**
+ * Set the token sort configuration setting.
+ *
@@ -158,12 +161,21 @@ index 30e985c..ec9db71 100644
+ this.update((state) => {
+ state.tokenSortConfig = tokenSortConfig;
+ });
++ }
++
++ /**
++ * A setter for the user hide balance and assets
++ *
++ * @param privacyMode - true to hide balance and assets
++ */
++ setPrivacyMode(privacyMode) {
++ this.update((state) => { state.privacyMode = privacyMode; });
+ }
};
_syncIdentities = new WeakSet();
syncIdentities_fn = function(addresses) {
diff --git a/node_modules/@metamask/preferences-controller/dist/types/PreferencesController.d.ts b/node_modules/@metamask/preferences-controller/dist/types/PreferencesController.d.ts
-index 7e3ba15..552580d 100644
+index 7e3ba15..dda7eb7 100644
--- a/node_modules/@metamask/preferences-controller/dist/types/PreferencesController.d.ts
+++ b/node_modules/@metamask/preferences-controller/dist/types/PreferencesController.d.ts
@@ -69,9 +69,10 @@ export type PreferencesState = {
@@ -179,7 +191,7 @@ index 7e3ba15..552580d 100644
/**
* Controls whether "security alerts" are enabled
*/
-@@ -98,6 +99,22 @@ export type PreferencesState = {
+@@ -98,6 +99,26 @@ export type PreferencesState = {
* Controls whether token detection is enabled
*/
useTokenDetection: boolean;
@@ -196,13 +208,17 @@ index 7e3ba15..552580d 100644
+ */
+ showMultiRpcModal: boolean;
+ /**
-+ * Controls whether Multi rpc modal is displayed or not
++ * Controls the token sort configuration
+ */
+ tokenSortConfig: Record;
++ /**
++ * Controls whether balance and assets are hidden or not
++ */
++ privacyMode: boolean;
};
declare const name = "PreferencesController";
export type PreferencesControllerGetStateAction = ControllerGetStateAction;
-@@ -121,7 +138,7 @@ export declare function getDefaultPreferencesState(): {
+@@ -121,7 +142,7 @@ export declare function getDefaultPreferencesState(): {
isIpfsGatewayEnabled: boolean;
isMultiAccountBalancesEnabled: boolean;
lostIdentities: {};
@@ -211,18 +227,19 @@ index 7e3ba15..552580d 100644
securityAlertsEnabled: boolean;
selectedAddress: string;
showIncomingTransactions: {
-@@ -149,6 +166,10 @@ export declare function getDefaultPreferencesState(): {
+@@ -149,6 +170,11 @@ export declare function getDefaultPreferencesState(): {
showTestNetworks: boolean;
useNftDetection: boolean;
useTokenDetection: boolean;
+ smartTransactionsOptInStatus: boolean;
+ useTransactionSimulations: boolean;
+ showMultiRpcModal: boolean;
-+ tokenSortConfig: Record
++ tokenSortConfig: Record;
++ privacyMode: boolean;
};
/**
* Controller that stores shared settings and exposes convenience methods
-@@ -217,11 +238,16 @@ export declare class PreferencesController extends BaseController): void
++ setTokenSortConfig(tokenSortConfig: Record): void;
++ /**
++ * Toggle the balance and assets hidden setting.
++ *
++ * @param privacyMode - Boolean indicating user preference on hiding balance and assets.
++ */
++ setPrivacyMode(privacyMode: boolean): void;
}
export default PreferencesController;
//# sourceMappingURL=PreferencesController.d.ts.map