From cd9182cf4ef98a5eae56a4550d300fad2f25b032 Mon Sep 17 00:00:00 2001
From: Fernando <fernando.greco@gmail.com>
Date: Mon, 7 Jun 2021 15:47:16 -0300
Subject: [PATCH] [Address Book v2] - Refactor addressBook selectors (#2372)

---
 .../addressBook/store/selectors/index.ts      | 84 ++++++++++++-------
 .../utils/__tests__/addressBookUtils.test.ts  | 78 +----------------
 src/logic/addressBook/utils/index.ts          | 61 --------------
 src/logic/safe/store/selectors/index.ts       | 12 +--
 .../load/components/OwnerList/index.tsx       | 26 +++---
 src/routes/open/components/Layout.tsx         | 12 +--
 .../SafeOwnersConfirmationsForm/index.tsx     |  9 +-
 .../CreateEditEntryModal/index.tsx            |  4 +-
 .../EllipsisTransactionDetails/index.tsx      |  4 +-
 .../AddressBook/ExportEntriesModal/index.tsx  |  5 +-
 .../safe/components/AddressBook/index.tsx     |  6 +-
 .../screens/AddressBookInput/index.tsx        |  6 +-
 .../ContractInteraction/Review/index.tsx      |  6 +-
 .../screens/SendCollectible/index.tsx         |  7 +-
 .../SendModal/screens/SendFunds/index.tsx     |  7 +-
 .../AddOwnerModal/screens/OwnerForm/index.tsx |  9 +-
 .../screens/OwnerForm/index.tsx               | 10 +--
 .../SpendingLimit/FormFields/Beneficiary.tsx  |  9 +-
 .../SpendingLimit/InfoDisplay/AddressInfo.tsx |  4 +-
 .../Transactions/TxList/OwnerRow.tsx          |  4 +-
 .../TxList/hooks/useKnownAddress.ts           |  4 +-
 21 files changed, 119 insertions(+), 248 deletions(-)

diff --git a/src/logic/addressBook/store/selectors/index.ts b/src/logic/addressBook/store/selectors/index.ts
index f28d4d4c..e2fcb6e3 100644
--- a/src/logic/addressBook/store/selectors/index.ts
+++ b/src/logic/addressBook/store/selectors/index.ts
@@ -4,20 +4,32 @@ import { getNetworkId } from 'src/config'
 import { ADDRESS_BOOK_DEFAULT_NAME, AddressBookEntry } from 'src/logic/addressBook/model/addressBook'
 import { AppReduxState } from 'src/store'
 import { Overwrite } from 'src/types/helpers'
+import { checksumAddress } from 'src/utils/checksumAddress'
+import { isValidAddress } from 'src/utils/isValidAddress'
 
 const networkId = getNetworkId()
 
-export const addressBookSelector = (state: AppReduxState): AppReduxState['addressBook'] => state['addressBook']
-
-type AddressBookMap = {
-  [chainId: number]: {
-    [address: string]: AddressBookEntry
-  }
+export const addressBookFromQueryParams = (state: AppReduxState): string | undefined => {
+  return state.router.location?.query?.entryAddress
 }
 
-export const addressBookMapSelector = createSelector(
-  [addressBookSelector],
-  (addressBook): AddressBookMap => {
+export const addressBookState = (state: AppReduxState): AppReduxState['addressBook'] => state['addressBook']
+
+export const addressBookAddresses = createSelector([addressBookState], (addressBook): string[] => {
+  return addressBook.map(({ address }) => address)
+})
+
+type AddressBookMap = {
+  [address: string]: AddressBookEntry
+}
+
+type AddressBookMapByChain = {
+  [chainId: number]: AddressBookMap
+}
+
+export const addressBookAsMap = createSelector(
+  [addressBookState],
+  (addressBook): AddressBookMapByChain => {
     const addressBookMap = {}
 
     addressBook.forEach((entry) => {
@@ -33,33 +45,45 @@ export const addressBookMapSelector = createSelector(
   },
 )
 
-export const addressBookAddressesListSelector = createSelector([addressBookSelector], (addressBook): string[] =>
-  addressBook.map(({ address }) => address),
-)
+type GetNameParams = Overwrite<Partial<AddressBookEntry>, { address: string }>
 
-type GetNameParams = Overwrite<
-  AddressBookEntry,
-  { chainId?: AddressBookEntry['chainId']; name?: AddressBookEntry['name'] }
->
-
-type GetNameReturnObject = Overwrite<GetNameParams, { chainId: AddressBookEntry['chainId'] }>
-
-export const getNameFromAddressBookSelector = createSelector(
+export const addressBookEntryName = createSelector(
   [
-    addressBookMapSelector,
-    (_, { address, chainId = networkId }: GetNameParams): GetNameReturnObject => ({
+    addressBookAsMap,
+    (_, { address, chainId = networkId }: GetNameParams): { address: string; chainId: number } => ({
       address,
       chainId,
     }),
   ],
-  (addressBook, entry) => addressBook?.[entry.chainId]?.[entry.address]?.name ?? ADDRESS_BOOK_DEFAULT_NAME,
+  (addressBook, { address, chainId }) => {
+    if (isValidAddress(address)) {
+      return addressBook?.[chainId]?.[checksumAddress(address)]?.name ?? ADDRESS_BOOK_DEFAULT_NAME
+    }
+
+    return ADDRESS_BOOK_DEFAULT_NAME
+  },
 )
 
-export const addressBookQueryParamsSelector = (state: AppReduxState): string | undefined => {
-  const { location } = state.router
+/*********************/
+/* Connected Network */
+/*********************/
 
-  if (location?.query) {
-    const { entryAddress } = location.query
-    return entryAddress
-  }
-}
+export const currentNetworkAddressBook = createSelector(
+  [addressBookState],
+  (addressBook): AppReduxState['addressBook'] => {
+    return addressBook.filter(({ chainId }) => chainId === networkId)
+  },
+)
+
+export const currentNetworkAddressBookAsMap = createSelector(
+  [currentNetworkAddressBook],
+  (addressBook): AddressBookMap => {
+    const addressBookMap = {}
+
+    addressBook.forEach((entry) => {
+      addressBookMap[entry.address] = entry
+    })
+
+    return addressBookMap
+  },
+)
diff --git a/src/logic/addressBook/utils/__tests__/addressBookUtils.test.ts b/src/logic/addressBook/utils/__tests__/addressBookUtils.test.ts
index f7f006e0..d1495f36 100644
--- a/src/logic/addressBook/utils/__tests__/addressBookUtils.test.ts
+++ b/src/logic/addressBook/utils/__tests__/addressBookUtils.test.ts
@@ -1,32 +1,4 @@
-import {
-  checkIfEntryWasDeletedFromAddressBook,
-  getNameFromAddressBook,
-  isValidAddressBookName,
-} from 'src/logic/addressBook/utils'
-import { AddressBookEntry, AddressBookState, makeAddressBookEntry } from 'src/logic/addressBook/model/addressBook'
-
-const getMockAddressBookEntry = (address: string, name: string = 'test'): AddressBookEntry =>
-  makeAddressBookEntry({
-    address,
-    name,
-  })
-
-describe('getNameFromSafeAddressBook', () => {
-  const entry1 = getMockAddressBookEntry('123456', 'test1')
-  const entry2 = getMockAddressBookEntry('78910', 'test2')
-  const entry3 = getMockAddressBookEntry('4781321', 'test3')
-  it('It should returns the user name given a safeAddressBook and an user account', () => {
-    // given
-    const safeAddressBook = [entry1, entry2, entry3]
-    const expectedResult = entry2.name
-
-    // when
-    const result = getNameFromAddressBook(safeAddressBook, entry2.address)
-
-    // then
-    expect(result).toBe(expectedResult)
-  })
-})
+import { isValidAddressBookName } from 'src/logic/addressBook/utils'
 
 describe('isValidAddressBookName', () => {
   it('It should return false if given a blacklisted name like UNKNOWN', () => {
@@ -78,51 +50,3 @@ describe('isValidAddressBookName', () => {
     expect(result).toEqual(expectedResult)
   })
 })
-
-describe('checkIfEntryWasDeletedFromAddressBook', () => {
-  const mockAdd1 = '0x696fd93D725d84acfFf6c62a1fe8C94E1c9E934A'
-  const mockAdd2 = '0x2C7aC78b01Be0FC66AD29b684ffAb0C93B381D00'
-  const mockAdd3 = '0x537BD452c3505FC07bA242E437bD29D4E1DC9126'
-  const entry1 = getMockAddressBookEntry(mockAdd1, 'test1')
-  const entry2 = getMockAddressBookEntry(mockAdd2, 'test2')
-  const entry3 = getMockAddressBookEntry(mockAdd3, 'test3')
-  it('It should return true if a given entry was deleted from addressBook', () => {
-    // given
-    const addressBookEntry = entry1
-    const addressBook: AddressBookState = [entry2, entry3]
-    const safeAlreadyLoaded = true
-    const expectedResult = true
-
-    // when
-    const result = checkIfEntryWasDeletedFromAddressBook(addressBookEntry, addressBook, safeAlreadyLoaded)
-
-    // then
-    expect(result).toEqual(expectedResult)
-  })
-  it('It should return false if a given entry was not deleted from addressBook', () => {
-    // given
-    const addressBookEntry = entry1
-    const addressBook: AddressBookState = [entry1, entry2, entry3]
-    const safeAlreadyLoaded = true
-    const expectedResult = false
-
-    // when
-    const result = checkIfEntryWasDeletedFromAddressBook(addressBookEntry, addressBook, safeAlreadyLoaded)
-
-    // then
-    expect(result).toEqual(expectedResult)
-  })
-  it('It should return false if the safe was not already loaded', () => {
-    // given
-    const addressBookEntry = entry1
-    const addressBook: AddressBookState = [entry1, entry2, entry3]
-    const safeAlreadyLoaded = false
-    const expectedResult = false
-
-    // when
-    const result = checkIfEntryWasDeletedFromAddressBook(addressBookEntry, addressBook, safeAlreadyLoaded)
-
-    // then
-    expect(result).toEqual(expectedResult)
-  })
-})
diff --git a/src/logic/addressBook/utils/index.ts b/src/logic/addressBook/utils/index.ts
index c08e462c..8173d08c 100644
--- a/src/logic/addressBook/utils/index.ts
+++ b/src/logic/addressBook/utils/index.ts
@@ -1,5 +1,4 @@
 import { mustBeEthereumContractAddress } from 'src/components/forms/validator'
-import { ETHEREUM_NETWORK } from 'src/config/networks/network.d'
 import { AddressBookEntry, AddressBookState } from 'src/logic/addressBook/model/addressBook'
 import { sameAddress } from 'src/logic/wallets/ethAddresses'
 import { AppReduxState } from 'src/store'
@@ -17,22 +16,6 @@ export type OldAddressBookType = {
 
 export const ADDRESS_BOOK_INVALID_NAMES = ['UNKNOWN', 'OWNER #', 'MY WALLET']
 
-type GetNameFromAddressBookOptions = {
-  filterOnlyValidName: boolean
-}
-
-export const getNameFromAddressBook = (
-  addressBook: AddressBookState,
-  userAddress: string,
-  options?: GetNameFromAddressBookOptions,
-): string | null => {
-  const entry = addressBook.find((addressBookItem) => addressBookItem.address === userAddress)
-  if (entry) {
-    return options?.filterOnlyValidName ? getValidAddressBookName(entry.name) : entry.name
-  }
-  return null
-}
-
 export const isValidAddressBookName = (addressBookName: string): boolean => {
   const hasInvalidName = ADDRESS_BOOK_INVALID_NAMES.find((invalidName) =>
     addressBookName?.toUpperCase().includes(invalidName),
@@ -40,50 +23,6 @@ export const isValidAddressBookName = (addressBookName: string): boolean => {
   return !hasInvalidName
 }
 
-// TODO: is this really required?
-export const getValidAddressBookName = (addressBookName: string): string | null => {
-  return isValidAddressBookName(addressBookName) ? addressBookName : null
-}
-
-export const formatAddressListToAddressBookNames = (
-  addressBook: AddressBookState,
-  addresses: string[],
-): AddressBookEntry[] => {
-  if (!addresses.length) {
-    return []
-  }
-  return addresses.map((address) => {
-    const ownerName = getNameFromAddressBook(addressBook, address)
-    return {
-      address: address,
-      name: ownerName || '',
-      chainId: ETHEREUM_NETWORK.UNKNOWN,
-    }
-  })
-}
-
-/**
- * If the safe is not loaded, the owner wasn't deleted
- * If the safe is already loaded and the owner has a valid name, will return true if the address is not already on the addressBook
- * @param name
- * @param address
- * @param addressBook
- * @param safeAlreadyLoaded
- */
-export const checkIfEntryWasDeletedFromAddressBook = (
-  { name, address }: AddressBookEntry,
-  addressBook: AddressBookState,
-  safeAlreadyLoaded: boolean,
-): boolean => {
-  if (!safeAlreadyLoaded) {
-    return false
-  }
-
-  const addressShouldBeOnTheAddressBook = !!getValidAddressBookName(name)
-  const isAlreadyInAddressBook = !!addressBook.find((entry) => sameAddress(entry.address, address))
-  return addressShouldBeOnTheAddressBook && !isAlreadyInAddressBook
-}
-
 /**
  * Returns a filtered list of AddressBookEntries whose addresses are contracts
  * @param {Array<AddressBookEntry>} addressBook
diff --git a/src/logic/safe/store/selectors/index.ts b/src/logic/safe/store/selectors/index.ts
index a0ab3178..0cd6c7d4 100644
--- a/src/logic/safe/store/selectors/index.ts
+++ b/src/logic/safe/store/selectors/index.ts
@@ -2,9 +2,8 @@ import { List } from 'immutable'
 import { matchPath } from 'react-router-dom'
 import { createSelector } from 'reselect'
 
-import { getNetworkId } from 'src/config'
 import { AddressBookEntry, makeAddressBookEntry } from 'src/logic/addressBook/model/addressBook'
-import { addressBookMapSelector } from 'src/logic/addressBook/store/selectors'
+import { currentNetworkAddressBookAsMap } from 'src/logic/addressBook/store/selectors'
 import makeSafe, { SafeRecord, SafeRecordProps } from 'src/logic/safe/store/models/safe'
 import { SAFE_REDUCER_ID } from 'src/logic/safe/store/reducer/safe'
 import { SAFELIST_ADDRESS } from 'src/routes/routes'
@@ -72,23 +71,20 @@ export const currentSafeTotalFiatBalance = createSelector(currentSafe, safeField
 /*************************/
 /* With AddressBook Data */
 /*************************/
-const chainId = getNetworkId()
 const baseSafeWithName = { ...baseSafe.toJS(), name: '' }
 
 export type SafeRecordWithNames = Overwrite<SafeRecordProps, { owners: AddressBookEntry[] }> & { name: string }
 
 export const safesWithNamesAsList = createSelector(
-  [safesAsList, addressBookMapSelector],
+  [safesAsList, currentNetworkAddressBookAsMap],
   (safesList, addressBookMap): SafeRecordWithNames[] => {
-    const addressBook = addressBookMap?.[chainId]
-
     return safesList
       .map((safeRecord) => {
         const safe = safeRecord.toObject()
-        const name = addressBook?.[safe.address]?.name ?? ''
+        const name = addressBookMap?.[safe.address]?.name ?? ''
 
         const owners = safe.owners.map((ownerAddress) => {
-          return addressBook?.[ownerAddress] ?? makeAddressBookEntry({ address: ownerAddress, name: '' })
+          return addressBookMap?.[ownerAddress] ?? makeAddressBookEntry({ address: ownerAddress, name: '' })
         })
 
         return { ...safe, name, owners }
diff --git a/src/routes/load/components/OwnerList/index.tsx b/src/routes/load/components/OwnerList/index.tsx
index afea0b75..5514571f 100644
--- a/src/routes/load/components/OwnerList/index.tsx
+++ b/src/routes/load/components/OwnerList/index.tsx
@@ -14,10 +14,9 @@ import Hairline from 'src/components/layout/Hairline'
 import Paragraph from 'src/components/layout/Paragraph'
 import Row from 'src/components/layout/Row'
 import OpenPaper from 'src/components/Stepper/OpenPaper'
-import { AddressBookEntry } from 'src/logic/addressBook/model/addressBook'
-import { addressBookSelector } from 'src/logic/addressBook/store/selectors'
+import { AddressBookEntry, makeAddressBookEntry } from 'src/logic/addressBook/model/addressBook'
+import { currentNetworkAddressBookAsMap } from 'src/logic/addressBook/store/selectors'
 
-import { formatAddressListToAddressBookNames } from 'src/logic/addressBook/utils'
 import { getGnosisSafeInstanceAt } from 'src/logic/contracts/safeContracts'
 import { FIELD_LOAD_ADDRESS, THRESHOLD } from 'src/routes/load/components/fields'
 import { getOwnerAddressBy, getOwnerNameBy } from 'src/routes/open/components/fields'
@@ -33,12 +32,6 @@ const calculateSafeValues = (owners, threshold, values) => {
   return initialValues
 }
 
-const useAddressBookForOwnersNames = (ownersList: string[]): AddressBookEntry[] => {
-  const addressBook = useSelector(addressBookSelector)
-
-  return formatAddressListToAddressBookNames(addressBook, ownersList)
-}
-
 const useStyles = makeStyles(styles)
 
 interface OwnerListComponentProps {
@@ -49,8 +42,19 @@ interface OwnerListComponentProps {
 const OwnerListComponent = ({ values, updateInitialProps }: OwnerListComponentProps): ReactElement => {
   const [owners, setOwners] = useState<string[]>([])
   const classes = useStyles()
+  const addressBookMap = useSelector(currentNetworkAddressBookAsMap)
+  const [ownersWithName, setOwnersWithName] = useState<AddressBookEntry[]>([])
 
-  const ownersWithNames = useAddressBookForOwnersNames(owners)
+  useEffect(() => {
+    setOwnersWithName(
+      owners.map((address) =>
+        makeAddressBookEntry({
+          address,
+          name: addressBookMap[address]?.name ?? '',
+        }),
+      ),
+    )
+  }, [addressBookMap, owners, ownersWithName])
 
   useEffect(() => {
     let isCurrent = true
@@ -91,7 +95,7 @@ const OwnerListComponent = ({ values, updateInitialProps }: OwnerListComponentPr
         </Row>
         <Hairline />
         <Block margin="md" padding="md">
-          {ownersWithNames.map(({ address, name }, index) => {
+          {ownersWithName.map(({ address, name }, index) => {
             return (
               <Row className={classes.owner} key={address} data-testid="owner-row">
                 <Col className={classes.ownerName} xs={4}>
diff --git a/src/routes/open/components/Layout.tsx b/src/routes/open/components/Layout.tsx
index 9ae2b4e3..26f5f6b6 100644
--- a/src/routes/open/components/Layout.tsx
+++ b/src/routes/open/components/Layout.tsx
@@ -17,14 +17,15 @@ import {
   getOwnerAddressBy,
   getOwnerNameBy,
 } from 'src/routes/open/components/fields'
-import { WelcomeLayout } from 'src/routes/welcome/components/index'
+import { WelcomeLayout } from 'src/routes/welcome/components'
 import { history } from 'src/store'
 import { secondary, sm } from 'src/theme/variables'
 import { providerNameSelector, userAccountSelector } from 'src/logic/wallets/store/selectors'
 import { useSelector } from 'react-redux'
-import { addressBookSelector } from 'src/logic/addressBook/store/selectors'
-import { getNameFromAddressBook } from 'src/logic/addressBook/utils'
+import { addressBookEntryName } from 'src/logic/addressBook/store/selectors'
 import { SafeProps } from 'src/routes/open/container/Open'
+import { ADDRESS_BOOK_DEFAULT_NAME } from 'src/logic/addressBook/model/addressBook'
+import { sameString } from 'src/utils/strings'
 
 const { useEffect } = React
 
@@ -39,12 +40,11 @@ export type InitialValuesForm = {
 }
 
 const useInitialValuesFrom = (userAccount: string, safeProps?: SafeProps): InitialValuesForm => {
-  const addressBook = useSelector(addressBookSelector)
-  const ownerName = getNameFromAddressBook(addressBook, userAccount, { filterOnlyValidName: true })
+  const ownerName = useSelector((state) => addressBookEntryName(state, { address: userAccount }))
 
   if (!safeProps) {
     return {
-      [getOwnerNameBy(0)]: ownerName || 'My Wallet',
+      [getOwnerNameBy(0)]: sameString(ownerName, ADDRESS_BOOK_DEFAULT_NAME) ? 'My Wallet' : ownerName,
       [getOwnerAddressBy(0)]: userAccount,
       [FIELD_CONFIRMATIONS]: '1',
       [FIELD_CREATION_PROXY_SALT]: Date.now(),
diff --git a/src/routes/open/components/SafeOwnersConfirmationsForm/index.tsx b/src/routes/open/components/SafeOwnersConfirmationsForm/index.tsx
index 4b4a7704..a6b0aab0 100644
--- a/src/routes/open/components/SafeOwnersConfirmationsForm/index.tsx
+++ b/src/routes/open/components/SafeOwnersConfirmationsForm/index.tsx
@@ -38,8 +38,7 @@ import {
 } from 'src/routes/open/components/fields'
 import { getAccountsFrom } from 'src/routes/open/utils/safeDataExtractor'
 import { useSelector } from 'react-redux'
-import { addressBookSelector } from 'src/logic/addressBook/store/selectors'
-import { getNameFromAddressBook } from 'src/logic/addressBook/utils'
+import { currentNetworkAddressBook } from 'src/logic/addressBook/store/selectors'
 
 const { useState } = React
 
@@ -116,7 +115,7 @@ const SafeOwnersForm = (props): React.ReactElement => {
   const classes = useStyles()
 
   const validOwners = getNumOwnersFrom(values)
-  const addressBook = useSelector(addressBookSelector)
+  const addressBook = useSelector(currentNetworkAddressBook)
 
   const [numOwners, setNumOwners] = useState(validOwners)
   const [qrModalOpen, setQrModalOpen] = useState(false)
@@ -206,9 +205,7 @@ const SafeOwnersForm = (props): React.ReactElement => {
               <Col className={classes.ownerAddress} xs={7}>
                 <StyledAddressInput
                   fieldMutator={(newOwnerAddress) => {
-                    const newOwnerName = getNameFromAddressBook(addressBook, newOwnerAddress, {
-                      filterOnlyValidName: true,
-                    })
+                    const newOwnerName = addressBook[newOwnerAddress]?.name
                     form.mutators.setValue(addressName, newOwnerAddress)
                     if (newOwnerName) {
                       form.mutators.setValue(ownerName, newOwnerName)
diff --git a/src/routes/safe/components/AddressBook/CreateEditEntryModal/index.tsx b/src/routes/safe/components/AddressBook/CreateEditEntryModal/index.tsx
index fe3bc4dd..1d22f4ff 100644
--- a/src/routes/safe/components/AddressBook/CreateEditEntryModal/index.tsx
+++ b/src/routes/safe/components/AddressBook/CreateEditEntryModal/index.tsx
@@ -13,7 +13,7 @@ import { composeValidators, required, uniqueAddress, validAddressBookName } from
 import Block from 'src/components/layout/Block'
 import Col from 'src/components/layout/Col'
 import Row from 'src/components/layout/Row'
-import { addressBookAddressesListSelector } from 'src/logic/addressBook/store/selectors'
+import { addressBookAddresses } from 'src/logic/addressBook/store/selectors'
 import { AddressBookEntry } from 'src/logic/addressBook/model/addressBook'
 import { Entry } from 'src/routes/safe/components/AddressBook'
 
@@ -54,7 +54,7 @@ export const CreateEditEntryModal = ({
     }
   }
 
-  const storedAddresses = useSelector(addressBookAddressesListSelector)
+  const storedAddresses = useSelector(addressBookAddresses)
   const isUniqueAddress = uniqueAddress(storedAddresses)
 
   return (
diff --git a/src/routes/safe/components/AddressBook/EllipsisTransactionDetails/index.tsx b/src/routes/safe/components/AddressBook/EllipsisTransactionDetails/index.tsx
index 43eeff44..595c0391 100644
--- a/src/routes/safe/components/AddressBook/EllipsisTransactionDetails/index.tsx
+++ b/src/routes/safe/components/AddressBook/EllipsisTransactionDetails/index.tsx
@@ -9,7 +9,7 @@ import { useDispatch, useSelector } from 'react-redux'
 
 import { sameString } from 'src/utils/strings'
 import { ADDRESS_BOOK_DEFAULT_NAME } from 'src/logic/addressBook/model/addressBook'
-import { getNameFromAddressBookSelector } from 'src/logic/addressBook/store/selectors'
+import { addressBookEntryName } from 'src/logic/addressBook/store/selectors'
 import { SAFELIST_ADDRESS } from 'src/routes/routes'
 import { safeAddressFromUrl } from 'src/logic/safe/store/selectors'
 import { xs } from 'src/theme/variables'
@@ -52,7 +52,7 @@ export const EllipsisTransactionDetails = ({
   const currentSafeAddress = useSelector(safeAddressFromUrl)
   const isOwnerConnected = useSelector(grantedSelector)
 
-  const recipientName = useSelector((state) => getNameFromAddressBookSelector(state, { address }))
+  const recipientName = useSelector((state) => addressBookEntryName(state, { address }))
   // We have to check that the name returned is not UNKNOWN
   const isStoredInAddressBook = !sameString(recipientName, ADDRESS_BOOK_DEFAULT_NAME)
 
diff --git a/src/routes/safe/components/AddressBook/ExportEntriesModal/index.tsx b/src/routes/safe/components/AddressBook/ExportEntriesModal/index.tsx
index 7360e853..647c7e83 100644
--- a/src/routes/safe/components/AddressBook/ExportEntriesModal/index.tsx
+++ b/src/routes/safe/components/AddressBook/ExportEntriesModal/index.tsx
@@ -9,8 +9,7 @@ import { enhanceSnackbarForAction, getNotificationsFromTxType } from 'src/logic/
 import enqueueSnackbar from 'src/logic/notifications/store/actions/enqueueSnackbar'
 import { TX_NOTIFICATION_TYPES } from 'src/logic/safe/transactions'
 
-import { addressBookSelector } from 'src/logic/addressBook/store/selectors'
-import { AddressBookState } from 'src/logic/addressBook/model/addressBook'
+import { addressBookState } from 'src/logic/addressBook/store/selectors'
 
 import { lg, md, background } from 'src/theme/variables'
 
@@ -57,7 +56,7 @@ const StyledCSVLink = styled(CSVDownloader)`
 
 export const ExportEntriesModal = ({ isOpen, onClose }: ExportEntriesModalProps): ReactElement => {
   const dispatch = useDispatch()
-  const addressBook: AddressBookState = useSelector(addressBookSelector)
+  const addressBook = useSelector(addressBookState)
   const [loading, setLoading] = useState<boolean>(true)
   const [error, setError] = useState<string | undefined>('')
   const [csvData, setCsvData] = useState<string>('')
diff --git a/src/routes/safe/components/AddressBook/index.tsx b/src/routes/safe/components/AddressBook/index.tsx
index 79b7cf44..5f96809f 100644
--- a/src/routes/safe/components/AddressBook/index.tsx
+++ b/src/routes/safe/components/AddressBook/index.tsx
@@ -19,7 +19,7 @@ import Col from 'src/components/layout/Col'
 import Row from 'src/components/layout/Row'
 import { AddressBookEntry, makeAddressBookEntry } from 'src/logic/addressBook/model/addressBook'
 import { addressBookAddOrUpdate, addressBookImport, addressBookRemove } from 'src/logic/addressBook/store/actions'
-import { addressBookQueryParamsSelector, addressBookSelector } from 'src/logic/addressBook/store/selectors'
+import { addressBookFromQueryParams, currentNetworkAddressBook } from 'src/logic/addressBook/store/selectors'
 import { isUserAnOwnerOfAnySafe, sameAddress } from 'src/logic/wallets/ethAddresses'
 import { CreateEditEntryModal } from 'src/routes/safe/components/AddressBook/CreateEditEntryModal'
 import { ExportEntriesModal } from 'src/routes/safe/components/AddressBook/ExportEntriesModal'
@@ -72,8 +72,8 @@ const AddressBookTable = (): ReactElement => {
   const autoColumns = columns.filter(({ custom }) => !custom)
   const dispatch = useDispatch()
   const safesList = useSelector(safesAsList)
-  const entryAddressToEditOrCreateNew = useSelector(addressBookQueryParamsSelector)
-  const addressBook = useSelector(addressBookSelector)
+  const entryAddressToEditOrCreateNew = useSelector(addressBookFromQueryParams)
+  const addressBook = useSelector(currentNetworkAddressBook)
   const granted = useSelector(grantedSelector)
   const [selectedEntry, setSelectedEntry] = useState<Entry>(initialEntryState)
   const [editCreateEntryModalOpen, setEditCreateEntryModalOpen] = useState(false)
diff --git a/src/routes/safe/components/Balances/SendModal/screens/AddressBookInput/index.tsx b/src/routes/safe/components/Balances/SendModal/screens/AddressBookInput/index.tsx
index cbd1cd6a..cc46757d 100644
--- a/src/routes/safe/components/Balances/SendModal/screens/AddressBookInput/index.tsx
+++ b/src/routes/safe/components/Balances/SendModal/screens/AddressBookInput/index.tsx
@@ -8,7 +8,7 @@ import { mustBeEthereumAddress, mustBeEthereumContractAddress } from 'src/compon
 import { getNetworkId, isFeatureEnabled } from 'src/config'
 import { FEATURES } from 'src/config/networks/network.d'
 import { AddressBookEntry } from 'src/logic/addressBook/model/addressBook'
-import { addressBookSelector } from 'src/logic/addressBook/store/selectors'
+import { currentNetworkAddressBook } from 'src/logic/addressBook/store/selectors'
 import { filterContractAddressBookEntries, filterAddressEntries } from 'src/logic/addressBook/utils'
 import { isValidEnsName, isValidCryptoDomainName } from 'src/logic/wallets/ethAddresses'
 import { getAddressFromDomain } from 'src/logic/wallets/getWeb3'
@@ -172,7 +172,7 @@ const BaseAddressBookInput = ({
 }
 
 export const AddressBookInput = (props: AddressBookProps): ReactElement => {
-  const addressBookEntries = useSelector(addressBookSelector)
+  const addressBookEntries = useSelector(currentNetworkAddressBook)
   const [validationText, setValidationText] = useState<string>('')
 
   useEffect(() => {
@@ -196,7 +196,7 @@ export const ContractsAddressBookInput = ({
   setSelectedEntry,
   ...props
 }: AddressBookProps): ReactElement => {
-  const addressBookEntries = useSelector(addressBookSelector)
+  const addressBookEntries = useSelector(currentNetworkAddressBook)
   const [filteredEntries, setFilteredEntries] = useState<AddressBookEntry[]>([])
   const [validationText, setValidationText] = useState<string>('')
 
diff --git a/src/routes/safe/components/Balances/SendModal/screens/ContractInteraction/Review/index.tsx b/src/routes/safe/components/Balances/SendModal/screens/ContractInteraction/Review/index.tsx
index 53bb3999..4b0da32b 100644
--- a/src/routes/safe/components/Balances/SendModal/screens/ContractInteraction/Review/index.tsx
+++ b/src/routes/safe/components/Balances/SendModal/screens/ContractInteraction/Review/index.tsx
@@ -27,7 +27,7 @@ import {
   getValueFromTxInputs,
 } from 'src/routes/safe/components/Balances/SendModal/screens/ContractInteraction/utils'
 import { useEstimateTransactionGas, EstimationStatus } from 'src/logic/hooks/useEstimateTransactionGas'
-import { getNameFromAddressBookSelector } from 'src/logic/addressBook/store/selectors'
+import { addressBookEntryName } from 'src/logic/addressBook/store/selectors'
 import { useEstimationStatus } from 'src/logic/hooks/useEstimationStatus'
 import { ButtonStatus, Modal } from 'src/components/Modal'
 import { TransactionFees } from 'src/components/TransactionsFees'
@@ -61,9 +61,7 @@ const ContractInteractionReview = ({ onClose, onPrev, tx }: Props): React.ReactE
   const [manualSafeTxGas, setManualSafeTxGas] = useState(0)
   const [manualGasPrice, setManualGasPrice] = useState<string | undefined>()
   const [manualGasLimit, setManualGasLimit] = useState<string | undefined>()
-  const addressName = useSelector((state) =>
-    getNameFromAddressBookSelector(state, { address: tx.contractAddress as string }),
-  )
+  const addressName = useSelector((state) => addressBookEntryName(state, { address: tx.contractAddress as string }))
 
   const [txInfo, setTxInfo] = useState<{
     txRecipient: string
diff --git a/src/routes/safe/components/Balances/SendModal/screens/SendCollectible/index.tsx b/src/routes/safe/components/Balances/SendModal/screens/SendCollectible/index.tsx
index f904a903..820bec8c 100644
--- a/src/routes/safe/components/Balances/SendModal/screens/SendCollectible/index.tsx
+++ b/src/routes/safe/components/Balances/SendModal/screens/SendCollectible/index.tsx
@@ -15,8 +15,7 @@ import Row from 'src/components/layout/Row'
 import { ScanQRWrapper } from 'src/components/ScanQRModal/ScanQRWrapper'
 import { Modal } from 'src/components/Modal'
 import WhenFieldChanges from 'src/components/WhenFieldChanges'
-import { addressBookSelector } from 'src/logic/addressBook/store/selectors'
-import { getNameFromAddressBook } from 'src/logic/addressBook/utils'
+import { currentNetworkAddressBook } from 'src/logic/addressBook/store/selectors'
 import { nftAssetsSelector, nftTokensSelector } from 'src/logic/collectibles/store/selectors'
 import { Erc721Transfer } from 'src/logic/safe/store/models/types/gateway'
 import SafeInfo from 'src/routes/safe/components/Balances/SendModal/SafeInfo'
@@ -70,7 +69,7 @@ const SendCollectible = ({
   const classes = useStyles()
   const nftAssets = useSelector(nftAssetsSelector)
   const nftTokens = useSelector(nftTokensSelector)
-  const addressBook = useSelector(addressBookSelector)
+  const addressBook = useSelector(currentNetworkAddressBook)
   const [selectedEntry, setSelectedEntry] = useState<{ address: string; name: string } | null>(() => {
     const defaultEntry = { address: recipientAddress || '', name: '' }
 
@@ -138,7 +137,7 @@ const SendCollectible = ({
             if (scannedAddress.startsWith('ethereum:')) {
               scannedAddress = scannedAddress.replace('ethereum:', '')
             }
-            const scannedName = addressBook ? getNameFromAddressBook(addressBook, scannedAddress) : ''
+            const scannedName = addressBook[scannedAddress]?.name ?? ''
             mutators.setRecipient(scannedAddress)
             setSelectedEntry({
               name: scannedName ?? '',
diff --git a/src/routes/safe/components/Balances/SendModal/screens/SendFunds/index.tsx b/src/routes/safe/components/Balances/SendModal/screens/SendFunds/index.tsx
index e3f19a03..609f9603 100644
--- a/src/routes/safe/components/Balances/SendModal/screens/SendFunds/index.tsx
+++ b/src/routes/safe/components/Balances/SendModal/screens/SendFunds/index.tsx
@@ -26,8 +26,7 @@ import Hairline from 'src/components/layout/Hairline'
 import Paragraph from 'src/components/layout/Paragraph'
 import Row from 'src/components/layout/Row'
 import { ScanQRWrapper } from 'src/components/ScanQRModal/ScanQRWrapper'
-import { addressBookSelector } from 'src/logic/addressBook/store/selectors'
-import { getNameFromAddressBook } from 'src/logic/addressBook/utils'
+import { currentNetworkAddressBook } from 'src/logic/addressBook/store/selectors'
 import { sameAddress } from 'src/logic/wallets/ethAddresses'
 import { SpendingLimit } from 'src/logic/safe/store/models/safe'
 import { userAccountSelector } from 'src/logic/wallets/store/selectors'
@@ -98,7 +97,7 @@ const SendFunds = ({
 }: SendFundsProps): ReactElement => {
   const classes = useStyles()
   const tokens = useSelector(extendedSafeTokensSelector)
-  const addressBook = useSelector(addressBookSelector)
+  const addressBook = useSelector(currentNetworkAddressBook)
   const { nativeCoin } = getNetworkInfo()
   const [selectedEntry, setSelectedEntry] = useState<{ address: string; name: string } | null>(() => {
     const defaultEntry = { address: recipientAddress || '', name: '' }
@@ -212,7 +211,7 @@ const SendFunds = ({
             if (scannedAddress.startsWith('ethereum:')) {
               scannedAddress = scannedAddress.replace('ethereum:', '')
             }
-            const scannedName = addressBook ? getNameFromAddressBook(addressBook, scannedAddress) : ''
+            const scannedName = addressBook[scannedAddress]?.name ?? ''
             const addressErrorMessage = mustBeEthereumAddress(scannedAddress)
             if (!addressErrorMessage) {
               mutators.setRecipient(scannedAddress)
diff --git a/src/routes/safe/components/Settings/ManageOwners/AddOwnerModal/screens/OwnerForm/index.tsx b/src/routes/safe/components/Settings/ManageOwners/AddOwnerModal/screens/OwnerForm/index.tsx
index 5e3b3827..618f7d17 100644
--- a/src/routes/safe/components/Settings/ManageOwners/AddOwnerModal/screens/OwnerForm/index.tsx
+++ b/src/routes/safe/components/Settings/ManageOwners/AddOwnerModal/screens/OwnerForm/index.tsx
@@ -8,7 +8,6 @@ import { OnChange } from 'react-final-form-listeners'
 
 import { styles } from './style'
 
-import { getNetworkId } from 'src/config'
 import { ScanQRWrapper } from 'src/components/ScanQRModal/ScanQRWrapper'
 import AddressInput from 'src/components/forms/AddressInput'
 import Field from 'src/components/forms/Field'
@@ -26,7 +25,7 @@ import Col from 'src/components/layout/Col'
 import Hairline from 'src/components/layout/Hairline'
 import Paragraph from 'src/components/layout/Paragraph'
 import Row from 'src/components/layout/Row'
-import { addressBookMapSelector } from 'src/logic/addressBook/store/selectors'
+import { currentNetworkAddressBookAsMap } from 'src/logic/addressBook/store/selectors'
 import { currentSafe } from 'src/logic/safe/store/selectors'
 import { isValidAddress } from 'src/utils/isValidAddress'
 
@@ -51,8 +50,6 @@ const formMutators: Record<
 
 const useStyles = makeStyles(styles)
 
-const chainId = getNetworkId()
-
 type OwnerFormProps = {
   onClose: () => void
   onSubmit: (values) => void
@@ -64,7 +61,7 @@ export const OwnerForm = ({ onClose, onSubmit, initialValues }: OwnerFormProps):
   const handleSubmit = (values) => {
     onSubmit(values)
   }
-  const addressBookMap = useSelector(addressBookMapSelector)
+  const addressBookMap = useSelector(currentNetworkAddressBookAsMap)
   const { address: safeAddress = '', owners = [] } = useSelector(currentSafe) ?? {}
   const ownerDoesntExist = uniqueAddress(owners)
   const ownerAddressIsNotSafeAddress = addressIsNotCurrentSafe(safeAddress)
@@ -122,7 +119,7 @@ export const OwnerForm = ({ onClose, onSubmit, initialValues }: OwnerFormProps):
                     <OnChange name="ownerAddress">
                       {async (address: string) => {
                         if (isValidAddress(address)) {
-                          const { name: ownerName } = addressBookMap[chainId][address]
+                          const ownerName = addressBookMap[address]?.name
                           if (ownerName) {
                             mutators.setOwnerName(ownerName)
                           }
diff --git a/src/routes/safe/components/Settings/ManageOwners/ReplaceOwnerModal/screens/OwnerForm/index.tsx b/src/routes/safe/components/Settings/ManageOwners/ReplaceOwnerModal/screens/OwnerForm/index.tsx
index 72e1bd84..77b124ac 100644
--- a/src/routes/safe/components/Settings/ManageOwners/ReplaceOwnerModal/screens/OwnerForm/index.tsx
+++ b/src/routes/safe/components/Settings/ManageOwners/ReplaceOwnerModal/screens/OwnerForm/index.tsx
@@ -24,12 +24,12 @@ import Row from 'src/components/layout/Row'
 import { ScanQRWrapper } from 'src/components/ScanQRModal/ScanQRWrapper'
 import { Modal } from 'src/components/Modal'
 import { currentSafe } from 'src/logic/safe/store/selectors'
-import { addressBookMapSelector } from 'src/logic/addressBook/store/selectors'
+import { currentNetworkAddressBookAsMap } from 'src/logic/addressBook/store/selectors'
 import { OwnerData } from 'src/routes/safe/components/Settings/ManageOwners/dataFetcher'
 import { isValidAddress } from 'src/utils/isValidAddress'
 
 import { useStyles } from './style'
-import { getExplorerInfo, getNetworkId } from 'src/config'
+import { getExplorerInfo } from 'src/config'
 import { EthHashInfo } from '@gnosis.pm/safe-react-components'
 
 export const REPLACE_OWNER_NAME_INPUT_TEST_ID = 'replace-owner-name-input'
@@ -50,8 +50,6 @@ const formMutators: Record<
   },
 }
 
-const chainId = getNetworkId()
-
 type NewOwnerProps = {
   ownerAddress: string
   ownerName: string
@@ -70,7 +68,7 @@ export const OwnerForm = ({ onClose, onSubmit, owner, initialValues }: OwnerForm
   const handleSubmit = (values: NewOwnerProps) => {
     onSubmit(values)
   }
-  const addressBookMap = useSelector(addressBookMapSelector)
+  const addressBookMap = useSelector(currentNetworkAddressBookAsMap)
   const { address: safeAddress = '', owners } = useSelector(currentSafe) ?? {}
   const ownerDoesntExist = uniqueAddress(owners)
   const ownerAddressIsNotSafeAddress = addressIsNotCurrentSafe(safeAddress)
@@ -149,7 +147,7 @@ export const OwnerForm = ({ onClose, onSubmit, owner, initialValues }: OwnerForm
                     <OnChange name="ownerAddress">
                       {async (address: string) => {
                         if (isValidAddress(address)) {
-                          const ownerName = addressBookMap?.[chainId]?.[address]?.name
+                          const ownerName = addressBookMap[address]?.name
                           if (ownerName) {
                             mutators.setOwnerName(ownerName)
                           }
diff --git a/src/routes/safe/components/Settings/SpendingLimit/FormFields/Beneficiary.tsx b/src/routes/safe/components/Settings/SpendingLimit/FormFields/Beneficiary.tsx
index a3aa27bc..0c140520 100644
--- a/src/routes/safe/components/Settings/SpendingLimit/FormFields/Beneficiary.tsx
+++ b/src/routes/safe/components/Settings/SpendingLimit/FormFields/Beneficiary.tsx
@@ -6,8 +6,7 @@ import styled from 'styled-components'
 
 import { ScanQRWrapper } from 'src/components/ScanQRModal/ScanQRWrapper'
 import { getExplorerInfo } from 'src/config'
-import { addressBookSelector } from 'src/logic/addressBook/store/selectors'
-import { getNameFromAddressBook } from 'src/logic/addressBook/utils'
+import { currentNetworkAddressBook } from 'src/logic/addressBook/store/selectors'
 import { AddressBookInput } from 'src/routes/safe/components/Balances/SendModal/screens/AddressBookInput'
 import { sameString } from 'src/utils/strings'
 
@@ -40,13 +39,11 @@ const Beneficiary = (): ReactElement => {
     }
   }, [mutators, pristine, selectedEntry])
 
-  const addressBook = useSelector(addressBookSelector)
+  const addressBook = useSelector(currentNetworkAddressBook)
 
   const handleScan = (value, closeQrModal) => {
     const scannedAddress = value.startsWith('ethereum:') ? value.replace('ethereum:', '') : value
-    const scannedName = addressBook
-      ? getNameFromAddressBook(addressBook, scannedAddress, { filterOnlyValidName: true }) ?? ''
-      : ''
+    const scannedName = addressBook[scannedAddress]?.name ?? ''
 
     mutators?.setBeneficiary?.(scannedAddress)
 
diff --git a/src/routes/safe/components/Settings/SpendingLimit/InfoDisplay/AddressInfo.tsx b/src/routes/safe/components/Settings/SpendingLimit/InfoDisplay/AddressInfo.tsx
index b2cb638f..4e2ab775 100644
--- a/src/routes/safe/components/Settings/SpendingLimit/InfoDisplay/AddressInfo.tsx
+++ b/src/routes/safe/components/Settings/SpendingLimit/InfoDisplay/AddressInfo.tsx
@@ -3,7 +3,7 @@ import React, { ReactElement } from 'react'
 import { useSelector } from 'react-redux'
 
 import { getExplorerInfo } from 'src/config'
-import { getNameFromAddressBookSelector } from 'src/logic/addressBook/store/selectors'
+import { addressBookEntryName } from 'src/logic/addressBook/store/selectors'
 import { ADDRESS_BOOK_DEFAULT_NAME } from 'src/logic/addressBook/model/addressBook'
 import { sameString } from 'src/utils/strings'
 
@@ -15,7 +15,7 @@ interface AddressInfoProps {
 }
 
 const AddressInfo = ({ address, title }: AddressInfoProps): ReactElement => {
-  const name = useSelector((state) => getNameFromAddressBookSelector(state, { address }))
+  const name = useSelector((state) => addressBookEntryName(state, { address }))
   const explorerUrl = getExplorerInfo(address)
 
   return (
diff --git a/src/routes/safe/components/Transactions/TxList/OwnerRow.tsx b/src/routes/safe/components/Transactions/TxList/OwnerRow.tsx
index b60fae86..6cc3b07e 100644
--- a/src/routes/safe/components/Transactions/TxList/OwnerRow.tsx
+++ b/src/routes/safe/components/Transactions/TxList/OwnerRow.tsx
@@ -3,12 +3,12 @@ import React, { ReactElement } from 'react'
 import { useSelector } from 'react-redux'
 
 import { getExplorerInfo } from 'src/config'
-import { getNameFromAddressBookSelector } from 'src/logic/addressBook/store/selectors'
+import { addressBookEntryName } from 'src/logic/addressBook/store/selectors'
 import { ADDRESS_BOOK_DEFAULT_NAME } from 'src/logic/addressBook/model/addressBook'
 import { sameString } from 'src/utils/strings'
 
 export const OwnerRow = ({ address }: { address: string }): ReactElement => {
-  const ownerName = useSelector((state) => getNameFromAddressBookSelector(state, { address }))
+  const ownerName = useSelector((state) => addressBookEntryName(state, { address }))
 
   return (
     <EthHashInfo
diff --git a/src/routes/safe/components/Transactions/TxList/hooks/useKnownAddress.ts b/src/routes/safe/components/Transactions/TxList/hooks/useKnownAddress.ts
index 1a08832b..2c2ecd7f 100644
--- a/src/routes/safe/components/Transactions/TxList/hooks/useKnownAddress.ts
+++ b/src/routes/safe/components/Transactions/TxList/hooks/useKnownAddress.ts
@@ -2,14 +2,14 @@ import { useSelector } from 'react-redux'
 
 import { sameString } from 'src/utils/strings'
 import { ADDRESS_BOOK_DEFAULT_NAME } from 'src/logic/addressBook/model/addressBook'
-import { getNameFromAddressBookSelector } from 'src/logic/addressBook/store/selectors'
+import { addressBookEntryName } from 'src/logic/addressBook/store/selectors'
 
 type AddressInfo = { name: string | undefined; image: string | undefined }
 
 type UseKnownAddressResponse = AddressInfo & { isAddressBook: boolean }
 
 export const useKnownAddress = (address: string, addressInfo: AddressInfo): UseKnownAddressResponse => {
-  const recipientName = useSelector((state) => getNameFromAddressBookSelector(state, { address }))
+  const recipientName = useSelector((state) => addressBookEntryName(state, { address }))
   // We have to check that the name returned is not UNKNOWN
   const isInAddressBook = !sameString(recipientName, ADDRESS_BOOK_DEFAULT_NAME)