diff --git a/src/app/actions.ts b/src/app/actions.ts
index 0edef57820d..b84e78250b0 100644
--- a/src/app/actions.ts
+++ b/src/app/actions.ts
@@ -38,7 +38,7 @@ export enum Actions {
PUSH_NOTIFICATIONS_PERMISSION_CHANGED = 'APP/PUSH_NOTIFICATIONS_PERMISSION_CHANGED',
IN_APP_REVIEW_REQUESTED = 'APP/IN_APP_REVIEW_REQUESTED',
NOTIFICATION_SPOTLIGHT_SEEN = 'APP/NOTIFICATION_SPOTLIGHT_SEEN',
- TOGGLE_HIDE_BALANCES = 'APP/TOGGLE_HIDE_BALANCES',
+ TOGGLE_HIDE_HOME_BALANCES = 'APP/TOGGLE_HIDE_HOME_BALANCES',
}
export interface SetAppState {
@@ -170,8 +170,8 @@ export interface NotificationSpotlightSeen {
type: Actions.NOTIFICATION_SPOTLIGHT_SEEN
}
-interface ToggleHideBalances {
- type: Actions.TOGGLE_HIDE_BALANCES
+interface ToggleHideHomeBalances {
+ type: Actions.TOGGLE_HIDE_HOME_BALANCES
}
export type ActionTypes =
@@ -201,7 +201,7 @@ export type ActionTypes =
| PushNotificationsPermissionChanged
| inAppReviewRequested
| NotificationSpotlightSeen
- | ToggleHideBalances
+ | ToggleHideHomeBalances
export const setAppState = (state: string): SetAppState => ({
type: Actions.SET_APP_STATE,
@@ -369,8 +369,8 @@ export const notificationSpotlightSeen = (): NotificationSpotlightSeen => {
}
}
-export const toggleHideBalances = (): ToggleHideBalances => {
+export const toggleHideHomeBalances = (): ToggleHideHomeBalances => {
return {
- type: Actions.TOGGLE_HIDE_BALANCES,
+ type: Actions.TOGGLE_HIDE_HOME_BALANCES,
}
}
diff --git a/src/app/reducers.ts b/src/app/reducers.ts
index 47843d3ee9f..d994b4672eb 100644
--- a/src/app/reducers.ts
+++ b/src/app/reducers.ts
@@ -268,7 +268,7 @@ export const appReducer = (
...state,
inAppReviewLastInteractionTimestamp: action.inAppReviewLastInteractionTimestamp,
}
- case Actions.TOGGLE_HIDE_BALANCES:
+ case Actions.TOGGLE_HIDE_HOME_BALANCES:
return {
...state,
hideHomeBalances: !state.hideHomeBalances,
diff --git a/src/components/TokenBalance.test.tsx b/src/components/TokenBalance.test.tsx
index 7baded406a6..409009461ab 100644
--- a/src/components/TokenBalance.test.tsx
+++ b/src/components/TokenBalance.test.tsx
@@ -681,6 +681,48 @@ describe('FiatExchangeTokenBalance and HomeTokenBalance', () => {
expect(tree.getByTestId('EyeIcon')).toBeTruthy()
})
+ it('renders correctly when feature flag is off, hideBalance is false', async () => {
+ jest
+ .mocked(getFeatureGate)
+ .mockImplementation(
+ (featureGate) =>
+ featureGate !== StatsigFeatureGates.SHOW_ASSET_DETAILS_SCREEN &&
+ featureGate !== StatsigFeatureGates.SHOW_HIDE_HOME_BALANCES_TOGGLE
+ )
+ const store = createMockStore(defaultStore)
+
+ const tree = render(
+
+
+
+ )
+
+ expect(getElementText(tree.getByTestId('TotalTokenBalance'))).toEqual('$8.41')
+ expect(tree.queryByTestId('EyeIcon')).toBeFalsy()
+ expect(tree.queryByTestId('HiddenEyeIcon')).toBeFalsy()
+ })
+
+ it('renders correctly when feature flag is off, hideBalance is true', async () => {
+ jest
+ .mocked(getFeatureGate)
+ .mockImplementation(
+ (featureGate) =>
+ featureGate !== StatsigFeatureGates.SHOW_ASSET_DETAILS_SCREEN &&
+ featureGate !== StatsigFeatureGates.SHOW_HIDE_HOME_BALANCES_TOGGLE
+ )
+ const store = createMockStore({ ...defaultStore, app: { hideHomeBalances: true } })
+
+ const tree = render(
+
+
+
+ )
+
+ expect(getElementText(tree.getByTestId('TotalTokenBalance'))).toEqual('$8.41')
+ expect(tree.queryByTestId('EyeIcon')).toBeFalsy()
+ expect(tree.queryByTestId('HiddenEyeIcon')).toBeFalsy()
+ })
+
it('tracks analytics event when eye icon is pressed', async () => {
const store = createMockStore(defaultStore)
diff --git a/src/components/TokenBalance.tsx b/src/components/TokenBalance.tsx
index 71975fe81af..db97e24ec4c 100644
--- a/src/components/TokenBalance.tsx
+++ b/src/components/TokenBalance.tsx
@@ -17,7 +17,7 @@ import { useDispatch, useSelector } from 'react-redux'
import { hideAlert, showToast } from 'src/alert/actions'
import { AssetsEvents, FiatExchangeEvents, HomeEvents } from 'src/analytics/Events'
import ValoraAnalytics from 'src/analytics/ValoraAnalytics'
-import { toggleHideBalances } from 'src/app/actions'
+import { toggleHideHomeBalances } from 'src/app/actions'
import { hideHomeBalancesSelector } from 'src/app/selectors'
import Dialog from 'src/components/Dialog'
import { formatValueToDisplay } from 'src/components/TokenDisplay'
@@ -55,11 +55,11 @@ import { getSupportedNetworkIdsForTokenBalances } from 'src/tokens/utils'
function TokenBalance({
style = styles.balance,
singleTokenViewEnabled = true,
- hideBalance = false,
+ showHideHomeBalancesToggle = false,
}: {
style?: StyleProp
singleTokenViewEnabled?: boolean
- hideBalance?: boolean
+ showHideHomeBalancesToggle?: boolean
}) {
const supportedNetworkIds = getSupportedNetworkIdsForTokenBalances()
const tokensWithUsdValue = useTokensWithUsdValue(supportedNetworkIds)
@@ -77,16 +77,25 @@ function TokenBalance({
: undefined
const { decimalSeparator } = getNumberFormatSettings()
+ const hideHomeBalanceState = useSelector(hideHomeBalancesSelector)
+ const hideBalance = showHideHomeBalancesToggle && hideHomeBalanceState
const balanceDisplay = hideBalance ? `XX${decimalSeparator}XX` : totalBalanceLocal?.toFormat(2)
- if (tokenFetchError || tokenFetchLoading || tokensAreStale) {
- // Show '-' if we haven't fetched the tokens yet or prices are stale
+ const TotalTokenBalance = ({ balanceDisplay }: { balanceDisplay: string }) => {
return (
-
- {localCurrencySymbol}
- {'-'}
-
+
+
+ {!hideBalance && localCurrencySymbol}
+ {balanceDisplay}
+
+ {showHideHomeBalancesToggle && }
+
)
+ }
+
+ if (tokenFetchError || tokenFetchLoading || tokensAreStale) {
+ // Show '-' if we haven't fetched the tokens yet or prices are stale
+ return
} else if (
singleTokenViewEnabled &&
tokensWithUsdValue.length === 1 &&
@@ -97,10 +106,7 @@ function TokenBalance({
-
- {!hideBalance && localCurrencySymbol}
- {balanceDisplay ?? '-'}
-
+
{!hideBalance && (
{formatValueToDisplay(tokenBalance)} {tokensWithUsdValue[0].symbol}
@@ -110,13 +116,21 @@ function TokenBalance({
)
} else {
- return (
-
- {!hideBalance && localCurrencySymbol}
- {balanceDisplay ?? new BigNumber(0).toFormat(2)}
-
- )
+ return
+ }
+}
+
+function HideBalanceButton({ hideBalance }: { hideBalance: boolean }) {
+ const dispatch = useDispatch()
+ const eyeIconOnPress = () => {
+ ValoraAnalytics.track(hideBalance ? HomeEvents.show_balances : HomeEvents.hide_balances)
+ dispatch(toggleHideHomeBalances())
}
+ return (
+
+ {hideBalance ? : }
+
+ )
}
function useErrorMessageWithRefresh() {
@@ -218,7 +232,6 @@ export function AssetsTokenBalance({ showInfo }: { showInfo: boolean }) {
export function HomeTokenBalance() {
const { t } = useTranslation()
- const dispatch = useDispatch()
const totalBalance = useTotalTokenBalance()
const tokenBalances = useTokensWithTokenBalance()
@@ -242,13 +255,6 @@ export function HomeTokenBalance() {
const [infoVisible, setInfoVisible] = useState(false)
- const hideBalance = useSelector(hideHomeBalancesSelector)
-
- const eyeIconOnPress = () => {
- ValoraAnalytics.track(hideBalance ? HomeEvents.show_balances : HomeEvents.hide_balances)
- dispatch(toggleHideBalances())
- }
-
return (
@@ -278,19 +284,16 @@ export function HomeTokenBalance() {
)}
-
-
-
- {hideBalance ? : }
-
-
+
)
}
diff --git a/src/statsig/constants.ts b/src/statsig/constants.ts
index c398b99bd2a..3cd5bb2fc98 100644
--- a/src/statsig/constants.ts
+++ b/src/statsig/constants.ts
@@ -42,6 +42,7 @@ export const FeatureGates = {
[StatsigFeatureGates.USE_VIEM_FOR_WALLETCONNECT_TRANSACTIONS]: false,
[StatsigFeatureGates.USE_NEW_RECIPIENT_SCREEN]: false,
[StatsigFeatureGates.USE_NEW_SEND_FLOW]: false,
+ [StatsigFeatureGates.SHOW_HIDE_HOME_BALANCES_TOGGLE]: false,
}
export const ExperimentConfigs = {
diff --git a/src/statsig/types.ts b/src/statsig/types.ts
index faf35002111..3f64bb6b55c 100644
--- a/src/statsig/types.ts
+++ b/src/statsig/types.ts
@@ -40,6 +40,7 @@ export enum StatsigFeatureGates {
USE_VIEM_FOR_WALLETCONNECT_TRANSACTIONS = 'use_viem_for_walletconnect_transactions',
USE_NEW_RECIPIENT_SCREEN = 'use_new_recipient_screen',
USE_NEW_SEND_FLOW = 'use_new_send_flow',
+ SHOW_HIDE_HOME_BALANCES_TOGGLE = 'show_hide_home_balances_toggle',
}
export enum StatsigExperiments {
diff --git a/src/transactions/feed/SwapFeedItem.test.tsx b/src/transactions/feed/SwapFeedItem.test.tsx
index c0fd0ad62dd..9468d1c30fe 100644
--- a/src/transactions/feed/SwapFeedItem.test.tsx
+++ b/src/transactions/feed/SwapFeedItem.test.tsx
@@ -2,6 +2,7 @@ import { render } from '@testing-library/react-native'
import React from 'react'
import { Provider } from 'react-redux'
import { RootState } from 'src/redux/reducers'
+import { getFeatureGate } from 'src/statsig'
import SwapFeedItem from 'src/transactions/feed/SwapFeedItem'
import {
Fee,
@@ -16,6 +17,8 @@ import { mockCeurTokenId, mockCusdTokenId } from 'test/values'
const MOCK_TX_HASH = '0x006b866d20452a24d1d90c7514422188cc7c5d873e2f1ed661ec3f810ad5331c'
+jest.mock('src/statsig')
+
jest.mock('src/web3/networkConfig', () => {
const originalModule = jest.requireActual('src/web3/networkConfig')
return {
@@ -33,6 +36,10 @@ jest.mock('src/web3/networkConfig', () => {
})
describe('SwapFeedItem', () => {
+ beforeEach(() => {
+ jest.clearAllMocks()
+ jest.mocked(getFeatureGate).mockReturnValue(true)
+ })
function renderScreen({
storeOverrides = {},
inAmount,
@@ -117,7 +124,28 @@ describe('SwapFeedItem', () => {
expect(getElementText(getByTestId('SwapFeedItem/outgoingAmount'))).toEqual('-17.54 cEUR')
})
- it('hides balance when flag is set', async () => {
+ it('still shows balances when feature gate false, hide balances root state true', async () => {
+ jest.mocked(getFeatureGate).mockReturnValue(false)
+ const { getByTestId } = renderScreen({
+ inAmount: {
+ tokenId: mockCeurTokenId,
+ value: 2.93,
+ },
+ outAmount: {
+ tokenId: mockCusdTokenId,
+ value: 2.87,
+ },
+ })
+
+ expect(getElementText(getByTestId('SwapFeedItem/title'))).toEqual('swapScreen.title')
+ expect(getElementText(getByTestId('SwapFeedItem/subtitle'))).toEqual(
+ 'feedItemSwapPath, {"token1":"cUSD","token2":"cEUR"}'
+ )
+ expect(getElementText(getByTestId('SwapFeedItem/incomingAmount'))).toEqual('+2.93 cEUR')
+ expect(getElementText(getByTestId('SwapFeedItem/outgoingAmount'))).toEqual('-2.87 cUSD')
+ })
+
+ it('hides balance when feature gate true, root state hide home balances flag is set', async () => {
const { queryByTestId } = renderScreen({
inAmount: {
tokenId: mockCeurTokenId,
diff --git a/src/transactions/feed/SwapFeedItem.tsx b/src/transactions/feed/SwapFeedItem.tsx
index eed17c6a2aa..9a5a1bba36c 100644
--- a/src/transactions/feed/SwapFeedItem.tsx
+++ b/src/transactions/feed/SwapFeedItem.tsx
@@ -9,6 +9,8 @@ import TokenDisplay from 'src/components/TokenDisplay'
import Touchable from 'src/components/Touchable'
import { navigate } from 'src/navigator/NavigationService'
import { Screens } from 'src/navigator/Screens'
+import { getFeatureGate } from 'src/statsig'
+import { StatsigFeatureGates } from 'src/statsig/types'
import colors from 'src/styles/colors'
import fontStyles from 'src/styles/fonts'
import variables from 'src/styles/variables'
@@ -29,7 +31,10 @@ function SwapFeedItem({ exchange }: Props) {
navigate(Screens.TransactionDetailsScreen, { transaction: exchange })
ValoraAnalytics.track(HomeEvents.transaction_feed_item_select)
}
- const hideBalance = useSelector(hideHomeBalancesSelector)
+
+ const hideHomeBalanceState = useSelector(hideHomeBalancesSelector)
+ const hideBalance =
+ getFeatureGate(StatsigFeatureGates.SHOW_HIDE_HOME_BALANCES_TOGGLE) && hideHomeBalanceState
return (
diff --git a/src/transactions/feed/TransferFeedItem.test.tsx b/src/transactions/feed/TransferFeedItem.test.tsx
index 919798878c1..5db8d548223 100644
--- a/src/transactions/feed/TransferFeedItem.test.tsx
+++ b/src/transactions/feed/TransferFeedItem.test.tsx
@@ -9,6 +9,7 @@ import FiatConnectQuote from 'src/fiatExchanges/quotes/FiatConnectQuote'
import { CICOFlow } from 'src/fiatExchanges/utils'
import { LocalCurrencyCode } from 'src/localCurrency/consts'
import { RootState } from 'src/redux/reducers'
+import { getFeatureGate } from 'src/statsig'
import TransferFeedItem from 'src/transactions/feed/TransferFeedItem'
import {
Fee,
@@ -41,6 +42,8 @@ const MOCK_CONTACT = {
address: MOCK_ADDRESS,
}
+jest.mock('src/statsig')
+
jest.mock('src/web3/networkConfig', () => {
const originalModule = jest.requireActual('src/web3/networkConfig')
return {
@@ -58,6 +61,10 @@ jest.mock('src/web3/networkConfig', () => {
})
describe('TransferFeedItem', () => {
+ beforeEach(() => {
+ jest.clearAllMocks()
+ jest.mocked(getFeatureGate).mockReturnValue(true)
+ })
function renderScreen({
storeOverrides = {},
type = TokenTransactionTypeV2.Sent,
@@ -618,7 +625,14 @@ describe('TransferFeedItem', () => {
})
})
- it('hides balance when flag is set', async () => {
+ it('shows balance when feature gate false, root state hide home balances flag is set', async () => {
+ jest.mocked(getFeatureGate).mockReturnValue(false)
+ const { getByTestId } = renderScreen({ storeOverrides: { app: { hideHomeBalances: true } } })
+ expect(getByTestId('TransferFeedItem/amount')).toBeTruthy()
+ expect(getByTestId('TransferFeedItem/tokenAmount')).toBeTruthy()
+ })
+
+ it('hides balance when feature gate true, root state hide home balances flag is set', async () => {
const { queryByTestId } = renderScreen({ storeOverrides: { app: { hideHomeBalances: true } } })
expect(queryByTestId('TransferFeedItem/amount')).toBeNull()
expect(queryByTestId('TransferFeedItem/tokenAmount')).toBeNull()
diff --git a/src/transactions/feed/TransferFeedItem.tsx b/src/transactions/feed/TransferFeedItem.tsx
index a33854fda75..83a51dda1e9 100644
--- a/src/transactions/feed/TransferFeedItem.tsx
+++ b/src/transactions/feed/TransferFeedItem.tsx
@@ -9,6 +9,8 @@ import TokenDisplay from 'src/components/TokenDisplay'
import Touchable from 'src/components/Touchable'
import { navigate } from 'src/navigator/NavigationService'
import { Screens } from 'src/navigator/Screens'
+import { getFeatureGate } from 'src/statsig'
+import { StatsigFeatureGates } from 'src/statsig/types'
import colors from 'src/styles/colors'
import fontStyles from 'src/styles/fonts'
import variables from 'src/styles/variables'
@@ -38,7 +40,9 @@ function TransferFeedItem({ transfer }: Props) {
const colorStyle = new BigNumber(amount.value).isPositive() ? { color: colors.greenUI } : {}
- const hideBalance = useSelector(hideHomeBalancesSelector)
+ const hideHomeBalanceState = useSelector(hideHomeBalancesSelector)
+ const hideBalance =
+ getFeatureGate(StatsigFeatureGates.SHOW_HIDE_HOME_BALANCES_TOGGLE) && hideHomeBalanceState
return (