diff --git a/app/components/UI/WalletAccount/WalletAccount.test.tsx b/app/components/UI/WalletAccount/WalletAccount.test.tsx index 7cda83eb387..909c8d8dc94 100644 --- a/app/components/UI/WalletAccount/WalletAccount.test.tsx +++ b/app/components/UI/WalletAccount/WalletAccount.test.tsx @@ -10,6 +10,8 @@ import { createAccountSelectorNavDetails } from '../../../components/Views/Accou // Internal dependencies import WalletAccount from './WalletAccount'; import initialBackgroundState from '../../../util/test/initial-background-state.json'; +import { Account } from '../../hooks/useAccounts'; +import { KeyringTypes } from '@metamask/keyring-controller'; jest.mock('../../../core/Engine', () => ({ context: { @@ -25,6 +27,14 @@ jest.mock('../../../core/Engine', () => ({ }, })); +const mockAccount: Account = { + name: 'Test account 1', + address: '0xC4955C0d639D99699Bfd7Ec54d9FaFEe40e4D272', + type: KeyringTypes.hd, + yOffset: 0, + isSelected: true, +}; + const mockInitialState = { settings: { useBlockieIcon: false, @@ -32,12 +42,6 @@ const mockInitialState = { engine: { backgroundState: { ...initialBackgroundState, - PreferencesController: { - selectedAddress: '0xC4955C0d639D99699Bfd7Ec54d9FaFEe40e4D272', - identities: { - '0xC4955C0d639D99699Bfd7Ec54d9FaFEe40e4D272': { name: 'Account 1' }, - }, - }, }, }, }; @@ -69,36 +73,81 @@ jest.mock('react-redux', () => ({ describe('WalletAccount', () => { it('renders correctly', () => { - const { toJSON } = renderWithProvider(, { - state: mockInitialState, - }); + const { toJSON } = renderWithProvider( + , + { + state: mockInitialState, + }, + ); expect(toJSON()).toMatchSnapshot(); }); it('shows the account address', () => { - const { getByTestId } = renderWithProvider(, { - state: mockInitialState, - }); + const { getByTestId } = renderWithProvider( + , + { + state: mockInitialState, + }, + ); expect(getByTestId('wallet-account-address')).toBeDefined(); }); it('copies the account address to the clipboard when the copy button is pressed', async () => { - const { getByTestId } = renderWithProvider(, { - state: mockInitialState, - }); + const { getByTestId } = renderWithProvider( + , + { + state: mockInitialState, + }, + ); fireEvent.press(getByTestId('wallet-account-copy-button')); expect(ClipboardManager.setString).toHaveBeenCalledTimes(1); }); it('should navigate to the account selector screen on account press', () => { - const { getByTestId } = renderWithProvider(, { - state: mockInitialState, - }); + const { getByTestId } = renderWithProvider( + , + { + state: mockInitialState, + }, + ); fireEvent.press(getByTestId('account-picker')); expect(mockNavigate).toHaveBeenCalledWith( ...createAccountSelectorNavDetails({}), ); }); + it('displays the correct account name', () => { + const { getByText } = renderWithProvider( + , + { + state: mockInitialState, + }, + ); + expect(getByText(mockAccount.name)).toBeDefined(); + }); + it('displays custom account name when ENS is defined but account name is not the default', () => { + const ensName = 'test.eth'; + const { getByText } = renderWithProvider( + , + { + state: mockInitialState, + }, + ); + expect(getByText(mockAccount.name)).toBeDefined(); + }); + it('displays ENS name when defined and account name is the default', () => { + const ensName = 'test.eth'; + const mockAccountWithDefaultName: Account = { + ...mockAccount, + name: 'Account 1', + }; + const { getByText } = renderWithProvider( + , + { + state: mockInitialState, + }, + ); + expect(getByText(ensName)).toBeDefined(); + }); }); diff --git a/app/components/UI/WalletAccount/WalletAccount.tsx b/app/components/UI/WalletAccount/WalletAccount.tsx index 3a28a4cd27f..22e438ef866 100644 --- a/app/components/UI/WalletAccount/WalletAccount.tsx +++ b/app/components/UI/WalletAccount/WalletAccount.tsx @@ -1,12 +1,5 @@ // Third parties dependencies -import React, { - forwardRef, - useCallback, - useEffect, - useImperativeHandle, - useRef, - useState, -} from 'react'; +import React, { forwardRef, useImperativeHandle, useRef } from 'react'; import { useSelector } from 'react-redux'; import { useNavigation } from '@react-navigation/native'; import { Platform, View } from 'react-native'; @@ -18,15 +11,7 @@ import { createAccountSelectorNavDetails } from '../../../components/Views/Accou import { useStyles } from '../../../component-library/hooks'; import generateTestId from '../../../../wdio/utils/generateTestId'; import AddressCopy from '../AddressCopy'; -import { - doENSReverseLookup, - isDefaultAccountName, -} from '../../../util/ENSUtils'; -import { selectChainId } from '../../../selectors/networkController'; -import { - selectIdentities, - selectSelectedAddress, -} from '../../../selectors/preferencesController'; +import { isDefaultAccountName } from '../../../util/ENSUtils'; import ButtonIcon from '../../../component-library/components/Buttons/ButtonIcon/ButtonIcon'; import { ButtonIconSizes } from '../../../component-library/components/Buttons/ButtonIcon'; import Routes from '../../../constants/navigation/Routes'; @@ -40,12 +25,13 @@ import { } from '../../../../wdio/screen-objects/testIDs/Screens/WalletView.testIds'; import { getLabelTextByAddress } from '../../../util/address'; -const WalletAccount = ({ style }: WalletAccountProps, ref: React.Ref) => { +const WalletAccount = ( + { style, account, ens }: WalletAccountProps, + ref: React.Ref, +) => { const { styles } = useStyles(styleSheet, { style }); const { navigate } = useNavigation(); - const [ens, setEns] = useState(); - const yourAccountRef = useRef(null); const accountActionsRef = useRef(null); @@ -53,40 +39,12 @@ const WalletAccount = ({ style }: WalletAccountProps, ref: React.Ref) => { yourAccountRef, accountActionsRef, })); - /** - * A string that represents the selected address - */ - const selectedAddress = useSelector(selectSelectedAddress); - - /** - * An object containing each identity in the format address => account - */ - const identities = useSelector(selectIdentities); - - const chainId = useSelector(selectChainId); const accountAvatarType = useSelector((state: any) => state.settings.useBlockieIcon ? AvatarAccountType.Blockies : AvatarAccountType.JazzIcon, ); - const account = { - ...identities[selectedAddress], - address: selectedAddress, - }; - - const lookupEns = useCallback(async () => { - try { - const accountEns = await doENSReverseLookup(account.address, chainId); - - setEns(accountEns); - // eslint-disable-next-line no-empty - } catch {} - }, [account.address, chainId]); - - useEffect(() => { - lookupEns(); - }, [lookupEns]); const onNavigateToAccountActions = () => { navigate(Routes.MODAL.ROOT_MODAL_FLOW, { diff --git a/app/components/UI/WalletAccount/WalletAccount.types.ts b/app/components/UI/WalletAccount/WalletAccount.types.ts index 99f03f59845..22a09fe9ad9 100644 --- a/app/components/UI/WalletAccount/WalletAccount.types.ts +++ b/app/components/UI/WalletAccount/WalletAccount.types.ts @@ -1,7 +1,10 @@ import { ViewStyle } from 'react-native'; +import { Account } from '../../hooks/useAccounts'; export interface WalletAccountProps { style?: ViewStyle; + account: Account; + ens?: string; } /** diff --git a/app/components/UI/WalletAccount/__snapshots__/WalletAccount.test.tsx.snap b/app/components/UI/WalletAccount/__snapshots__/WalletAccount.test.tsx.snap index fbceeb4339a..9ce7f36026f 100644 --- a/app/components/UI/WalletAccount/__snapshots__/WalletAccount.test.tsx.snap +++ b/app/components/UI/WalletAccount/__snapshots__/WalletAccount.test.tsx.snap @@ -177,7 +177,7 @@ exports[`WalletAccount renders correctly 1`] = ` } testID="account-label" > - Account 1 + Test account 1 @@ -278,9 +278,7 @@ exports[`WalletAccount renders correctly 1`] = ` } } testID="wallet-account-address" - > - 0xC495...D272 - + /> StyleSheet.create({ @@ -789,8 +790,7 @@ class ChoosePassword extends PureComponent { ChoosePassword.contextType = ThemeContext; const mapStateToProps = (state) => ({ - selectedAddress: - state.engine.backgroundState.PreferencesController?.selectedAddress, + selectedAddress: selectSelectedAddress(state), }); const mapDispatchToProps = (dispatch) => ({ diff --git a/app/components/Views/Wallet/index.test.tsx b/app/components/Views/Wallet/index.test.tsx index e870de2c6fa..a7e471d1527 100644 --- a/app/components/Views/Wallet/index.test.tsx +++ b/app/components/Views/Wallet/index.test.tsx @@ -38,6 +38,15 @@ jest.mock('../../../core/Engine', () => ({ AccountTrackerController: { refresh: jest.fn(), }, + KeyringController: { + state: { + keyrings: [ + { + accounts: ['0xC4955C0d639D99699Bfd7Ec54d9FaFEe40e4D272'], + }, + ], + }, + }, }, })); diff --git a/app/components/Views/Wallet/index.tsx b/app/components/Views/Wallet/index.tsx index 2fe135ac1aa..3321ff0eb88 100644 --- a/app/components/Views/Wallet/index.tsx +++ b/app/components/Views/Wallet/index.tsx @@ -44,6 +44,7 @@ import { import { selectAccountsByChainId } from '../../../selectors/accountTrackerController'; import { selectSelectedAddress } from '../../../selectors/preferencesController'; import { useMetrics } from '../../../components/hooks/useMetrics'; +import { useAccounts } from '../../hooks/useAccounts'; const createStyles = ({ colors, typography }: Theme) => StyleSheet.create({ @@ -124,6 +125,32 @@ const Wallet = ({ navigation }: any) => { */ const providerConfig = useSelector(selectProviderConfig); + /** + * A list of all the user accounts and a mapping of ENS name to account address if they exist + */ + const { accounts, ensByAccountAddress } = useAccounts(); + + /** + * An object representing the currently selected account. + */ + const selectedAccount = useMemo(() => { + if (accounts.length > 0) { + return accounts.find((account) => account.isSelected); + } + return undefined; + }, [accounts]); + + /** + * ENS name for the currently selected account. + * This value may be undefined if there is no corresponding ENS name for the account. + */ + const ensForSelectedAccount = useMemo(() => { + if (ensByAccountAddress && selectedAccount) { + return ensByAccountAddress[selectedAccount.address]; + } + return undefined; + }, [ensByAccountAddress, selectedAccount]); + const networkName = useMemo( () => getNetworkNameFromProviderConfig(providerConfig), [providerConfig], @@ -274,8 +301,14 @@ const Wallet = ({ navigation }: any) => { } return ( - - + {selectedAccount ? ( + + ) : null} { ); }, [ + tokens, + accountsByChainId, + providerConfig.chainId, + selectedAddress, + styles.wrapper, + styles.walletAccount, + selectedAccount, + ensForSelectedAccount, renderTabBar, - conversionRate, - currentCurrency, - navigation, onChangeTab, - selectedAddress, + navigation, ticker, - tokens, - styles, - providerConfig.chainId, - accountsByChainId, + conversionRate, + currentCurrency, ]); const renderLoader = useCallback( () => ( diff --git a/app/components/Views/confirmations/components/SignatureRequest/index.js b/app/components/Views/confirmations/components/SignatureRequest/index.js index a52c26d179b..1bfccc8e6d1 100644 --- a/app/components/Views/confirmations/components/SignatureRequest/index.js +++ b/app/components/Views/confirmations/components/SignatureRequest/index.js @@ -23,6 +23,7 @@ import withQRHardwareAwareness from '../../../../UI/QRHardware/withQRHardwareAwa import WebsiteIcon from '../../../../UI/WebsiteIcon'; import { ResultType } from '../BlockaidBanner/BlockaidBanner.types'; import { withMetricsAwareness } from '../../../../../components/hooks/useMetrics'; +import { selectSelectedAddress } from '../../../../../selectors/preferencesController'; const createStyles = (colors) => StyleSheet.create({ @@ -417,8 +418,7 @@ class SignatureRequest extends PureComponent { } const mapStateToProps = (state) => ({ - selectedAddress: - state.engine.backgroundState.PreferencesController.selectedAddress, + selectedAddress: selectSelectedAddress(state), networkType: selectProviderType(state), securityAlertResponse: state.signatureRequest.securityAlertResponse, }); diff --git a/app/components/hooks/useAccounts/useAccounts.ts b/app/components/hooks/useAccounts/useAccounts.ts index 7d0988f1d6c..d0f04583608 100644 --- a/app/components/hooks/useAccounts/useAccounts.ts +++ b/app/components/hooks/useAccounts/useAccounts.ts @@ -36,7 +36,7 @@ import { /** * Hook that returns both wallet accounts and ens name information. * - * @returns Object that contins both wallet accounts and ens name information. + * @returns Object that contains both wallet accounts and ens name information. */ const useAccounts = ({ checkBalanceError, @@ -93,7 +93,7 @@ const useAccounts = ({ }; } } catch (e) { - // ENS either doesn't exists or failed to fetch. + // ENS either doesn't exist or failed to fetch. } };