[Address Book v2] - Refactor addressBook selectors (#2372)
This commit is contained in:
parent
b9b239e0e3
commit
cd9182cf4e
|
@ -4,20 +4,32 @@ import { getNetworkId } from 'src/config'
|
||||||
import { ADDRESS_BOOK_DEFAULT_NAME, AddressBookEntry } from 'src/logic/addressBook/model/addressBook'
|
import { ADDRESS_BOOK_DEFAULT_NAME, AddressBookEntry } from 'src/logic/addressBook/model/addressBook'
|
||||||
import { AppReduxState } from 'src/store'
|
import { AppReduxState } from 'src/store'
|
||||||
import { Overwrite } from 'src/types/helpers'
|
import { Overwrite } from 'src/types/helpers'
|
||||||
|
import { checksumAddress } from 'src/utils/checksumAddress'
|
||||||
|
import { isValidAddress } from 'src/utils/isValidAddress'
|
||||||
|
|
||||||
const networkId = getNetworkId()
|
const networkId = getNetworkId()
|
||||||
|
|
||||||
export const addressBookSelector = (state: AppReduxState): AppReduxState['addressBook'] => state['addressBook']
|
export const addressBookFromQueryParams = (state: AppReduxState): string | undefined => {
|
||||||
|
return state.router.location?.query?.entryAddress
|
||||||
type AddressBookMap = {
|
|
||||||
[chainId: number]: {
|
|
||||||
[address: string]: AddressBookEntry
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const addressBookMapSelector = createSelector(
|
export const addressBookState = (state: AppReduxState): AppReduxState['addressBook'] => state['addressBook']
|
||||||
[addressBookSelector],
|
|
||||||
(addressBook): AddressBookMap => {
|
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 = {}
|
const addressBookMap = {}
|
||||||
|
|
||||||
addressBook.forEach((entry) => {
|
addressBook.forEach((entry) => {
|
||||||
|
@ -33,33 +45,45 @@ export const addressBookMapSelector = createSelector(
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
export const addressBookAddressesListSelector = createSelector([addressBookSelector], (addressBook): string[] =>
|
type GetNameParams = Overwrite<Partial<AddressBookEntry>, { address: string }>
|
||||||
addressBook.map(({ address }) => address),
|
|
||||||
)
|
|
||||||
|
|
||||||
type GetNameParams = Overwrite<
|
export const addressBookEntryName = createSelector(
|
||||||
AddressBookEntry,
|
|
||||||
{ chainId?: AddressBookEntry['chainId']; name?: AddressBookEntry['name'] }
|
|
||||||
>
|
|
||||||
|
|
||||||
type GetNameReturnObject = Overwrite<GetNameParams, { chainId: AddressBookEntry['chainId'] }>
|
|
||||||
|
|
||||||
export const getNameFromAddressBookSelector = createSelector(
|
|
||||||
[
|
[
|
||||||
addressBookMapSelector,
|
addressBookAsMap,
|
||||||
(_, { address, chainId = networkId }: GetNameParams): GetNameReturnObject => ({
|
(_, { address, chainId = networkId }: GetNameParams): { address: string; chainId: number } => ({
|
||||||
address,
|
address,
|
||||||
chainId,
|
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) {
|
export const currentNetworkAddressBook = createSelector(
|
||||||
const { entryAddress } = location.query
|
[addressBookState],
|
||||||
return entryAddress
|
(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
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
|
@ -1,32 +1,4 @@
|
||||||
import {
|
import { isValidAddressBookName } from 'src/logic/addressBook/utils'
|
||||||
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)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
describe('isValidAddressBookName', () => {
|
describe('isValidAddressBookName', () => {
|
||||||
it('It should return false if given a blacklisted name like UNKNOWN', () => {
|
it('It should return false if given a blacklisted name like UNKNOWN', () => {
|
||||||
|
@ -78,51 +50,3 @@ describe('isValidAddressBookName', () => {
|
||||||
expect(result).toEqual(expectedResult)
|
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)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
import { mustBeEthereumContractAddress } from 'src/components/forms/validator'
|
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 { AddressBookEntry, AddressBookState } from 'src/logic/addressBook/model/addressBook'
|
||||||
import { sameAddress } from 'src/logic/wallets/ethAddresses'
|
import { sameAddress } from 'src/logic/wallets/ethAddresses'
|
||||||
import { AppReduxState } from 'src/store'
|
import { AppReduxState } from 'src/store'
|
||||||
|
@ -17,22 +16,6 @@ export type OldAddressBookType = {
|
||||||
|
|
||||||
export const ADDRESS_BOOK_INVALID_NAMES = ['UNKNOWN', 'OWNER #', 'MY WALLET']
|
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 => {
|
export const isValidAddressBookName = (addressBookName: string): boolean => {
|
||||||
const hasInvalidName = ADDRESS_BOOK_INVALID_NAMES.find((invalidName) =>
|
const hasInvalidName = ADDRESS_BOOK_INVALID_NAMES.find((invalidName) =>
|
||||||
addressBookName?.toUpperCase().includes(invalidName),
|
addressBookName?.toUpperCase().includes(invalidName),
|
||||||
|
@ -40,50 +23,6 @@ export const isValidAddressBookName = (addressBookName: string): boolean => {
|
||||||
return !hasInvalidName
|
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
|
* Returns a filtered list of AddressBookEntries whose addresses are contracts
|
||||||
* @param {Array<AddressBookEntry>} addressBook
|
* @param {Array<AddressBookEntry>} addressBook
|
||||||
|
|
|
@ -2,9 +2,8 @@ import { List } from 'immutable'
|
||||||
import { matchPath } from 'react-router-dom'
|
import { matchPath } from 'react-router-dom'
|
||||||
import { createSelector } from 'reselect'
|
import { createSelector } from 'reselect'
|
||||||
|
|
||||||
import { getNetworkId } from 'src/config'
|
|
||||||
import { AddressBookEntry, makeAddressBookEntry } from 'src/logic/addressBook/model/addressBook'
|
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 makeSafe, { SafeRecord, SafeRecordProps } from 'src/logic/safe/store/models/safe'
|
||||||
import { SAFE_REDUCER_ID } from 'src/logic/safe/store/reducer/safe'
|
import { SAFE_REDUCER_ID } from 'src/logic/safe/store/reducer/safe'
|
||||||
import { SAFELIST_ADDRESS } from 'src/routes/routes'
|
import { SAFELIST_ADDRESS } from 'src/routes/routes'
|
||||||
|
@ -72,23 +71,20 @@ export const currentSafeTotalFiatBalance = createSelector(currentSafe, safeField
|
||||||
/*************************/
|
/*************************/
|
||||||
/* With AddressBook Data */
|
/* With AddressBook Data */
|
||||||
/*************************/
|
/*************************/
|
||||||
const chainId = getNetworkId()
|
|
||||||
const baseSafeWithName = { ...baseSafe.toJS(), name: '' }
|
const baseSafeWithName = { ...baseSafe.toJS(), name: '' }
|
||||||
|
|
||||||
export type SafeRecordWithNames = Overwrite<SafeRecordProps, { owners: AddressBookEntry[] }> & { name: string }
|
export type SafeRecordWithNames = Overwrite<SafeRecordProps, { owners: AddressBookEntry[] }> & { name: string }
|
||||||
|
|
||||||
export const safesWithNamesAsList = createSelector(
|
export const safesWithNamesAsList = createSelector(
|
||||||
[safesAsList, addressBookMapSelector],
|
[safesAsList, currentNetworkAddressBookAsMap],
|
||||||
(safesList, addressBookMap): SafeRecordWithNames[] => {
|
(safesList, addressBookMap): SafeRecordWithNames[] => {
|
||||||
const addressBook = addressBookMap?.[chainId]
|
|
||||||
|
|
||||||
return safesList
|
return safesList
|
||||||
.map((safeRecord) => {
|
.map((safeRecord) => {
|
||||||
const safe = safeRecord.toObject()
|
const safe = safeRecord.toObject()
|
||||||
const name = addressBook?.[safe.address]?.name ?? ''
|
const name = addressBookMap?.[safe.address]?.name ?? ''
|
||||||
|
|
||||||
const owners = safe.owners.map((ownerAddress) => {
|
const owners = safe.owners.map((ownerAddress) => {
|
||||||
return addressBook?.[ownerAddress] ?? makeAddressBookEntry({ address: ownerAddress, name: '' })
|
return addressBookMap?.[ownerAddress] ?? makeAddressBookEntry({ address: ownerAddress, name: '' })
|
||||||
})
|
})
|
||||||
|
|
||||||
return { ...safe, name, owners }
|
return { ...safe, name, owners }
|
||||||
|
|
|
@ -14,10 +14,9 @@ import Hairline from 'src/components/layout/Hairline'
|
||||||
import Paragraph from 'src/components/layout/Paragraph'
|
import Paragraph from 'src/components/layout/Paragraph'
|
||||||
import Row from 'src/components/layout/Row'
|
import Row from 'src/components/layout/Row'
|
||||||
import OpenPaper from 'src/components/Stepper/OpenPaper'
|
import OpenPaper from 'src/components/Stepper/OpenPaper'
|
||||||
import { AddressBookEntry } from 'src/logic/addressBook/model/addressBook'
|
import { AddressBookEntry, makeAddressBookEntry } from 'src/logic/addressBook/model/addressBook'
|
||||||
import { addressBookSelector } from 'src/logic/addressBook/store/selectors'
|
import { currentNetworkAddressBookAsMap } from 'src/logic/addressBook/store/selectors'
|
||||||
|
|
||||||
import { formatAddressListToAddressBookNames } from 'src/logic/addressBook/utils'
|
|
||||||
import { getGnosisSafeInstanceAt } from 'src/logic/contracts/safeContracts'
|
import { getGnosisSafeInstanceAt } from 'src/logic/contracts/safeContracts'
|
||||||
import { FIELD_LOAD_ADDRESS, THRESHOLD } from 'src/routes/load/components/fields'
|
import { FIELD_LOAD_ADDRESS, THRESHOLD } from 'src/routes/load/components/fields'
|
||||||
import { getOwnerAddressBy, getOwnerNameBy } from 'src/routes/open/components/fields'
|
import { getOwnerAddressBy, getOwnerNameBy } from 'src/routes/open/components/fields'
|
||||||
|
@ -33,12 +32,6 @@ const calculateSafeValues = (owners, threshold, values) => {
|
||||||
return initialValues
|
return initialValues
|
||||||
}
|
}
|
||||||
|
|
||||||
const useAddressBookForOwnersNames = (ownersList: string[]): AddressBookEntry[] => {
|
|
||||||
const addressBook = useSelector(addressBookSelector)
|
|
||||||
|
|
||||||
return formatAddressListToAddressBookNames(addressBook, ownersList)
|
|
||||||
}
|
|
||||||
|
|
||||||
const useStyles = makeStyles(styles)
|
const useStyles = makeStyles(styles)
|
||||||
|
|
||||||
interface OwnerListComponentProps {
|
interface OwnerListComponentProps {
|
||||||
|
@ -49,8 +42,19 @@ interface OwnerListComponentProps {
|
||||||
const OwnerListComponent = ({ values, updateInitialProps }: OwnerListComponentProps): ReactElement => {
|
const OwnerListComponent = ({ values, updateInitialProps }: OwnerListComponentProps): ReactElement => {
|
||||||
const [owners, setOwners] = useState<string[]>([])
|
const [owners, setOwners] = useState<string[]>([])
|
||||||
const classes = useStyles()
|
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(() => {
|
useEffect(() => {
|
||||||
let isCurrent = true
|
let isCurrent = true
|
||||||
|
@ -91,7 +95,7 @@ const OwnerListComponent = ({ values, updateInitialProps }: OwnerListComponentPr
|
||||||
</Row>
|
</Row>
|
||||||
<Hairline />
|
<Hairline />
|
||||||
<Block margin="md" padding="md">
|
<Block margin="md" padding="md">
|
||||||
{ownersWithNames.map(({ address, name }, index) => {
|
{ownersWithName.map(({ address, name }, index) => {
|
||||||
return (
|
return (
|
||||||
<Row className={classes.owner} key={address} data-testid="owner-row">
|
<Row className={classes.owner} key={address} data-testid="owner-row">
|
||||||
<Col className={classes.ownerName} xs={4}>
|
<Col className={classes.ownerName} xs={4}>
|
||||||
|
|
|
@ -17,14 +17,15 @@ import {
|
||||||
getOwnerAddressBy,
|
getOwnerAddressBy,
|
||||||
getOwnerNameBy,
|
getOwnerNameBy,
|
||||||
} from 'src/routes/open/components/fields'
|
} 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 { history } from 'src/store'
|
||||||
import { secondary, sm } from 'src/theme/variables'
|
import { secondary, sm } from 'src/theme/variables'
|
||||||
import { providerNameSelector, userAccountSelector } from 'src/logic/wallets/store/selectors'
|
import { providerNameSelector, userAccountSelector } from 'src/logic/wallets/store/selectors'
|
||||||
import { useSelector } from 'react-redux'
|
import { useSelector } from 'react-redux'
|
||||||
import { addressBookSelector } from 'src/logic/addressBook/store/selectors'
|
import { addressBookEntryName } from 'src/logic/addressBook/store/selectors'
|
||||||
import { getNameFromAddressBook } from 'src/logic/addressBook/utils'
|
|
||||||
import { SafeProps } from 'src/routes/open/container/Open'
|
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
|
const { useEffect } = React
|
||||||
|
|
||||||
|
@ -39,12 +40,11 @@ export type InitialValuesForm = {
|
||||||
}
|
}
|
||||||
|
|
||||||
const useInitialValuesFrom = (userAccount: string, safeProps?: SafeProps): InitialValuesForm => {
|
const useInitialValuesFrom = (userAccount: string, safeProps?: SafeProps): InitialValuesForm => {
|
||||||
const addressBook = useSelector(addressBookSelector)
|
const ownerName = useSelector((state) => addressBookEntryName(state, { address: userAccount }))
|
||||||
const ownerName = getNameFromAddressBook(addressBook, userAccount, { filterOnlyValidName: true })
|
|
||||||
|
|
||||||
if (!safeProps) {
|
if (!safeProps) {
|
||||||
return {
|
return {
|
||||||
[getOwnerNameBy(0)]: ownerName || 'My Wallet',
|
[getOwnerNameBy(0)]: sameString(ownerName, ADDRESS_BOOK_DEFAULT_NAME) ? 'My Wallet' : ownerName,
|
||||||
[getOwnerAddressBy(0)]: userAccount,
|
[getOwnerAddressBy(0)]: userAccount,
|
||||||
[FIELD_CONFIRMATIONS]: '1',
|
[FIELD_CONFIRMATIONS]: '1',
|
||||||
[FIELD_CREATION_PROXY_SALT]: Date.now(),
|
[FIELD_CREATION_PROXY_SALT]: Date.now(),
|
||||||
|
|
|
@ -38,8 +38,7 @@ import {
|
||||||
} from 'src/routes/open/components/fields'
|
} from 'src/routes/open/components/fields'
|
||||||
import { getAccountsFrom } from 'src/routes/open/utils/safeDataExtractor'
|
import { getAccountsFrom } from 'src/routes/open/utils/safeDataExtractor'
|
||||||
import { useSelector } from 'react-redux'
|
import { useSelector } from 'react-redux'
|
||||||
import { addressBookSelector } from 'src/logic/addressBook/store/selectors'
|
import { currentNetworkAddressBook } from 'src/logic/addressBook/store/selectors'
|
||||||
import { getNameFromAddressBook } from 'src/logic/addressBook/utils'
|
|
||||||
|
|
||||||
const { useState } = React
|
const { useState } = React
|
||||||
|
|
||||||
|
@ -116,7 +115,7 @@ const SafeOwnersForm = (props): React.ReactElement => {
|
||||||
const classes = useStyles()
|
const classes = useStyles()
|
||||||
|
|
||||||
const validOwners = getNumOwnersFrom(values)
|
const validOwners = getNumOwnersFrom(values)
|
||||||
const addressBook = useSelector(addressBookSelector)
|
const addressBook = useSelector(currentNetworkAddressBook)
|
||||||
|
|
||||||
const [numOwners, setNumOwners] = useState(validOwners)
|
const [numOwners, setNumOwners] = useState(validOwners)
|
||||||
const [qrModalOpen, setQrModalOpen] = useState(false)
|
const [qrModalOpen, setQrModalOpen] = useState(false)
|
||||||
|
@ -206,9 +205,7 @@ const SafeOwnersForm = (props): React.ReactElement => {
|
||||||
<Col className={classes.ownerAddress} xs={7}>
|
<Col className={classes.ownerAddress} xs={7}>
|
||||||
<StyledAddressInput
|
<StyledAddressInput
|
||||||
fieldMutator={(newOwnerAddress) => {
|
fieldMutator={(newOwnerAddress) => {
|
||||||
const newOwnerName = getNameFromAddressBook(addressBook, newOwnerAddress, {
|
const newOwnerName = addressBook[newOwnerAddress]?.name
|
||||||
filterOnlyValidName: true,
|
|
||||||
})
|
|
||||||
form.mutators.setValue(addressName, newOwnerAddress)
|
form.mutators.setValue(addressName, newOwnerAddress)
|
||||||
if (newOwnerName) {
|
if (newOwnerName) {
|
||||||
form.mutators.setValue(ownerName, newOwnerName)
|
form.mutators.setValue(ownerName, newOwnerName)
|
||||||
|
|
|
@ -13,7 +13,7 @@ import { composeValidators, required, uniqueAddress, validAddressBookName } from
|
||||||
import Block from 'src/components/layout/Block'
|
import Block from 'src/components/layout/Block'
|
||||||
import Col from 'src/components/layout/Col'
|
import Col from 'src/components/layout/Col'
|
||||||
import Row from 'src/components/layout/Row'
|
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 { AddressBookEntry } from 'src/logic/addressBook/model/addressBook'
|
||||||
import { Entry } from 'src/routes/safe/components/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)
|
const isUniqueAddress = uniqueAddress(storedAddresses)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -9,7 +9,7 @@ import { useDispatch, useSelector } from 'react-redux'
|
||||||
|
|
||||||
import { sameString } from 'src/utils/strings'
|
import { sameString } from 'src/utils/strings'
|
||||||
import { ADDRESS_BOOK_DEFAULT_NAME } from 'src/logic/addressBook/model/addressBook'
|
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 { SAFELIST_ADDRESS } from 'src/routes/routes'
|
||||||
import { safeAddressFromUrl } from 'src/logic/safe/store/selectors'
|
import { safeAddressFromUrl } from 'src/logic/safe/store/selectors'
|
||||||
import { xs } from 'src/theme/variables'
|
import { xs } from 'src/theme/variables'
|
||||||
|
@ -52,7 +52,7 @@ export const EllipsisTransactionDetails = ({
|
||||||
const currentSafeAddress = useSelector(safeAddressFromUrl)
|
const currentSafeAddress = useSelector(safeAddressFromUrl)
|
||||||
const isOwnerConnected = useSelector(grantedSelector)
|
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
|
// We have to check that the name returned is not UNKNOWN
|
||||||
const isStoredInAddressBook = !sameString(recipientName, ADDRESS_BOOK_DEFAULT_NAME)
|
const isStoredInAddressBook = !sameString(recipientName, ADDRESS_BOOK_DEFAULT_NAME)
|
||||||
|
|
||||||
|
|
|
@ -9,8 +9,7 @@ import { enhanceSnackbarForAction, getNotificationsFromTxType } from 'src/logic/
|
||||||
import enqueueSnackbar from 'src/logic/notifications/store/actions/enqueueSnackbar'
|
import enqueueSnackbar from 'src/logic/notifications/store/actions/enqueueSnackbar'
|
||||||
import { TX_NOTIFICATION_TYPES } from 'src/logic/safe/transactions'
|
import { TX_NOTIFICATION_TYPES } from 'src/logic/safe/transactions'
|
||||||
|
|
||||||
import { addressBookSelector } from 'src/logic/addressBook/store/selectors'
|
import { addressBookState } from 'src/logic/addressBook/store/selectors'
|
||||||
import { AddressBookState } from 'src/logic/addressBook/model/addressBook'
|
|
||||||
|
|
||||||
import { lg, md, background } from 'src/theme/variables'
|
import { lg, md, background } from 'src/theme/variables'
|
||||||
|
|
||||||
|
@ -57,7 +56,7 @@ const StyledCSVLink = styled(CSVDownloader)`
|
||||||
|
|
||||||
export const ExportEntriesModal = ({ isOpen, onClose }: ExportEntriesModalProps): ReactElement => {
|
export const ExportEntriesModal = ({ isOpen, onClose }: ExportEntriesModalProps): ReactElement => {
|
||||||
const dispatch = useDispatch()
|
const dispatch = useDispatch()
|
||||||
const addressBook: AddressBookState = useSelector(addressBookSelector)
|
const addressBook = useSelector(addressBookState)
|
||||||
const [loading, setLoading] = useState<boolean>(true)
|
const [loading, setLoading] = useState<boolean>(true)
|
||||||
const [error, setError] = useState<string | undefined>('')
|
const [error, setError] = useState<string | undefined>('')
|
||||||
const [csvData, setCsvData] = useState<string>('')
|
const [csvData, setCsvData] = useState<string>('')
|
||||||
|
|
|
@ -19,7 +19,7 @@ import Col from 'src/components/layout/Col'
|
||||||
import Row from 'src/components/layout/Row'
|
import Row from 'src/components/layout/Row'
|
||||||
import { AddressBookEntry, makeAddressBookEntry } from 'src/logic/addressBook/model/addressBook'
|
import { AddressBookEntry, makeAddressBookEntry } from 'src/logic/addressBook/model/addressBook'
|
||||||
import { addressBookAddOrUpdate, addressBookImport, addressBookRemove } from 'src/logic/addressBook/store/actions'
|
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 { isUserAnOwnerOfAnySafe, sameAddress } from 'src/logic/wallets/ethAddresses'
|
||||||
import { CreateEditEntryModal } from 'src/routes/safe/components/AddressBook/CreateEditEntryModal'
|
import { CreateEditEntryModal } from 'src/routes/safe/components/AddressBook/CreateEditEntryModal'
|
||||||
import { ExportEntriesModal } from 'src/routes/safe/components/AddressBook/ExportEntriesModal'
|
import { ExportEntriesModal } from 'src/routes/safe/components/AddressBook/ExportEntriesModal'
|
||||||
|
@ -72,8 +72,8 @@ const AddressBookTable = (): ReactElement => {
|
||||||
const autoColumns = columns.filter(({ custom }) => !custom)
|
const autoColumns = columns.filter(({ custom }) => !custom)
|
||||||
const dispatch = useDispatch()
|
const dispatch = useDispatch()
|
||||||
const safesList = useSelector(safesAsList)
|
const safesList = useSelector(safesAsList)
|
||||||
const entryAddressToEditOrCreateNew = useSelector(addressBookQueryParamsSelector)
|
const entryAddressToEditOrCreateNew = useSelector(addressBookFromQueryParams)
|
||||||
const addressBook = useSelector(addressBookSelector)
|
const addressBook = useSelector(currentNetworkAddressBook)
|
||||||
const granted = useSelector(grantedSelector)
|
const granted = useSelector(grantedSelector)
|
||||||
const [selectedEntry, setSelectedEntry] = useState<Entry>(initialEntryState)
|
const [selectedEntry, setSelectedEntry] = useState<Entry>(initialEntryState)
|
||||||
const [editCreateEntryModalOpen, setEditCreateEntryModalOpen] = useState(false)
|
const [editCreateEntryModalOpen, setEditCreateEntryModalOpen] = useState(false)
|
||||||
|
|
|
@ -8,7 +8,7 @@ import { mustBeEthereumAddress, mustBeEthereumContractAddress } from 'src/compon
|
||||||
import { getNetworkId, isFeatureEnabled } from 'src/config'
|
import { getNetworkId, isFeatureEnabled } from 'src/config'
|
||||||
import { FEATURES } from 'src/config/networks/network.d'
|
import { FEATURES } from 'src/config/networks/network.d'
|
||||||
import { AddressBookEntry } from 'src/logic/addressBook/model/addressBook'
|
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 { filterContractAddressBookEntries, filterAddressEntries } from 'src/logic/addressBook/utils'
|
||||||
import { isValidEnsName, isValidCryptoDomainName } from 'src/logic/wallets/ethAddresses'
|
import { isValidEnsName, isValidCryptoDomainName } from 'src/logic/wallets/ethAddresses'
|
||||||
import { getAddressFromDomain } from 'src/logic/wallets/getWeb3'
|
import { getAddressFromDomain } from 'src/logic/wallets/getWeb3'
|
||||||
|
@ -172,7 +172,7 @@ const BaseAddressBookInput = ({
|
||||||
}
|
}
|
||||||
|
|
||||||
export const AddressBookInput = (props: AddressBookProps): ReactElement => {
|
export const AddressBookInput = (props: AddressBookProps): ReactElement => {
|
||||||
const addressBookEntries = useSelector(addressBookSelector)
|
const addressBookEntries = useSelector(currentNetworkAddressBook)
|
||||||
const [validationText, setValidationText] = useState<string>('')
|
const [validationText, setValidationText] = useState<string>('')
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
@ -196,7 +196,7 @@ export const ContractsAddressBookInput = ({
|
||||||
setSelectedEntry,
|
setSelectedEntry,
|
||||||
...props
|
...props
|
||||||
}: AddressBookProps): ReactElement => {
|
}: AddressBookProps): ReactElement => {
|
||||||
const addressBookEntries = useSelector(addressBookSelector)
|
const addressBookEntries = useSelector(currentNetworkAddressBook)
|
||||||
const [filteredEntries, setFilteredEntries] = useState<AddressBookEntry[]>([])
|
const [filteredEntries, setFilteredEntries] = useState<AddressBookEntry[]>([])
|
||||||
const [validationText, setValidationText] = useState<string>('')
|
const [validationText, setValidationText] = useState<string>('')
|
||||||
|
|
||||||
|
|
|
@ -27,7 +27,7 @@ import {
|
||||||
getValueFromTxInputs,
|
getValueFromTxInputs,
|
||||||
} from 'src/routes/safe/components/Balances/SendModal/screens/ContractInteraction/utils'
|
} from 'src/routes/safe/components/Balances/SendModal/screens/ContractInteraction/utils'
|
||||||
import { useEstimateTransactionGas, EstimationStatus } from 'src/logic/hooks/useEstimateTransactionGas'
|
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 { useEstimationStatus } from 'src/logic/hooks/useEstimationStatus'
|
||||||
import { ButtonStatus, Modal } from 'src/components/Modal'
|
import { ButtonStatus, Modal } from 'src/components/Modal'
|
||||||
import { TransactionFees } from 'src/components/TransactionsFees'
|
import { TransactionFees } from 'src/components/TransactionsFees'
|
||||||
|
@ -61,9 +61,7 @@ const ContractInteractionReview = ({ onClose, onPrev, tx }: Props): React.ReactE
|
||||||
const [manualSafeTxGas, setManualSafeTxGas] = useState(0)
|
const [manualSafeTxGas, setManualSafeTxGas] = useState(0)
|
||||||
const [manualGasPrice, setManualGasPrice] = useState<string | undefined>()
|
const [manualGasPrice, setManualGasPrice] = useState<string | undefined>()
|
||||||
const [manualGasLimit, setManualGasLimit] = useState<string | undefined>()
|
const [manualGasLimit, setManualGasLimit] = useState<string | undefined>()
|
||||||
const addressName = useSelector((state) =>
|
const addressName = useSelector((state) => addressBookEntryName(state, { address: tx.contractAddress as string }))
|
||||||
getNameFromAddressBookSelector(state, { address: tx.contractAddress as string }),
|
|
||||||
)
|
|
||||||
|
|
||||||
const [txInfo, setTxInfo] = useState<{
|
const [txInfo, setTxInfo] = useState<{
|
||||||
txRecipient: string
|
txRecipient: string
|
||||||
|
|
|
@ -15,8 +15,7 @@ import Row from 'src/components/layout/Row'
|
||||||
import { ScanQRWrapper } from 'src/components/ScanQRModal/ScanQRWrapper'
|
import { ScanQRWrapper } from 'src/components/ScanQRModal/ScanQRWrapper'
|
||||||
import { Modal } from 'src/components/Modal'
|
import { Modal } from 'src/components/Modal'
|
||||||
import WhenFieldChanges from 'src/components/WhenFieldChanges'
|
import WhenFieldChanges from 'src/components/WhenFieldChanges'
|
||||||
import { addressBookSelector } from 'src/logic/addressBook/store/selectors'
|
import { currentNetworkAddressBook } from 'src/logic/addressBook/store/selectors'
|
||||||
import { getNameFromAddressBook } from 'src/logic/addressBook/utils'
|
|
||||||
import { nftAssetsSelector, nftTokensSelector } from 'src/logic/collectibles/store/selectors'
|
import { nftAssetsSelector, nftTokensSelector } from 'src/logic/collectibles/store/selectors'
|
||||||
import { Erc721Transfer } from 'src/logic/safe/store/models/types/gateway'
|
import { Erc721Transfer } from 'src/logic/safe/store/models/types/gateway'
|
||||||
import SafeInfo from 'src/routes/safe/components/Balances/SendModal/SafeInfo'
|
import SafeInfo from 'src/routes/safe/components/Balances/SendModal/SafeInfo'
|
||||||
|
@ -70,7 +69,7 @@ const SendCollectible = ({
|
||||||
const classes = useStyles()
|
const classes = useStyles()
|
||||||
const nftAssets = useSelector(nftAssetsSelector)
|
const nftAssets = useSelector(nftAssetsSelector)
|
||||||
const nftTokens = useSelector(nftTokensSelector)
|
const nftTokens = useSelector(nftTokensSelector)
|
||||||
const addressBook = useSelector(addressBookSelector)
|
const addressBook = useSelector(currentNetworkAddressBook)
|
||||||
const [selectedEntry, setSelectedEntry] = useState<{ address: string; name: string } | null>(() => {
|
const [selectedEntry, setSelectedEntry] = useState<{ address: string; name: string } | null>(() => {
|
||||||
const defaultEntry = { address: recipientAddress || '', name: '' }
|
const defaultEntry = { address: recipientAddress || '', name: '' }
|
||||||
|
|
||||||
|
@ -138,7 +137,7 @@ const SendCollectible = ({
|
||||||
if (scannedAddress.startsWith('ethereum:')) {
|
if (scannedAddress.startsWith('ethereum:')) {
|
||||||
scannedAddress = scannedAddress.replace('ethereum:', '')
|
scannedAddress = scannedAddress.replace('ethereum:', '')
|
||||||
}
|
}
|
||||||
const scannedName = addressBook ? getNameFromAddressBook(addressBook, scannedAddress) : ''
|
const scannedName = addressBook[scannedAddress]?.name ?? ''
|
||||||
mutators.setRecipient(scannedAddress)
|
mutators.setRecipient(scannedAddress)
|
||||||
setSelectedEntry({
|
setSelectedEntry({
|
||||||
name: scannedName ?? '',
|
name: scannedName ?? '',
|
||||||
|
|
|
@ -26,8 +26,7 @@ import Hairline from 'src/components/layout/Hairline'
|
||||||
import Paragraph from 'src/components/layout/Paragraph'
|
import Paragraph from 'src/components/layout/Paragraph'
|
||||||
import Row from 'src/components/layout/Row'
|
import Row from 'src/components/layout/Row'
|
||||||
import { ScanQRWrapper } from 'src/components/ScanQRModal/ScanQRWrapper'
|
import { ScanQRWrapper } from 'src/components/ScanQRModal/ScanQRWrapper'
|
||||||
import { addressBookSelector } from 'src/logic/addressBook/store/selectors'
|
import { currentNetworkAddressBook } from 'src/logic/addressBook/store/selectors'
|
||||||
import { getNameFromAddressBook } from 'src/logic/addressBook/utils'
|
|
||||||
import { sameAddress } from 'src/logic/wallets/ethAddresses'
|
import { sameAddress } from 'src/logic/wallets/ethAddresses'
|
||||||
import { SpendingLimit } from 'src/logic/safe/store/models/safe'
|
import { SpendingLimit } from 'src/logic/safe/store/models/safe'
|
||||||
import { userAccountSelector } from 'src/logic/wallets/store/selectors'
|
import { userAccountSelector } from 'src/logic/wallets/store/selectors'
|
||||||
|
@ -98,7 +97,7 @@ const SendFunds = ({
|
||||||
}: SendFundsProps): ReactElement => {
|
}: SendFundsProps): ReactElement => {
|
||||||
const classes = useStyles()
|
const classes = useStyles()
|
||||||
const tokens = useSelector(extendedSafeTokensSelector)
|
const tokens = useSelector(extendedSafeTokensSelector)
|
||||||
const addressBook = useSelector(addressBookSelector)
|
const addressBook = useSelector(currentNetworkAddressBook)
|
||||||
const { nativeCoin } = getNetworkInfo()
|
const { nativeCoin } = getNetworkInfo()
|
||||||
const [selectedEntry, setSelectedEntry] = useState<{ address: string; name: string } | null>(() => {
|
const [selectedEntry, setSelectedEntry] = useState<{ address: string; name: string } | null>(() => {
|
||||||
const defaultEntry = { address: recipientAddress || '', name: '' }
|
const defaultEntry = { address: recipientAddress || '', name: '' }
|
||||||
|
@ -212,7 +211,7 @@ const SendFunds = ({
|
||||||
if (scannedAddress.startsWith('ethereum:')) {
|
if (scannedAddress.startsWith('ethereum:')) {
|
||||||
scannedAddress = scannedAddress.replace('ethereum:', '')
|
scannedAddress = scannedAddress.replace('ethereum:', '')
|
||||||
}
|
}
|
||||||
const scannedName = addressBook ? getNameFromAddressBook(addressBook, scannedAddress) : ''
|
const scannedName = addressBook[scannedAddress]?.name ?? ''
|
||||||
const addressErrorMessage = mustBeEthereumAddress(scannedAddress)
|
const addressErrorMessage = mustBeEthereumAddress(scannedAddress)
|
||||||
if (!addressErrorMessage) {
|
if (!addressErrorMessage) {
|
||||||
mutators.setRecipient(scannedAddress)
|
mutators.setRecipient(scannedAddress)
|
||||||
|
|
|
@ -8,7 +8,6 @@ import { OnChange } from 'react-final-form-listeners'
|
||||||
|
|
||||||
import { styles } from './style'
|
import { styles } from './style'
|
||||||
|
|
||||||
import { getNetworkId } from 'src/config'
|
|
||||||
import { ScanQRWrapper } from 'src/components/ScanQRModal/ScanQRWrapper'
|
import { ScanQRWrapper } from 'src/components/ScanQRModal/ScanQRWrapper'
|
||||||
import AddressInput from 'src/components/forms/AddressInput'
|
import AddressInput from 'src/components/forms/AddressInput'
|
||||||
import Field from 'src/components/forms/Field'
|
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 Hairline from 'src/components/layout/Hairline'
|
||||||
import Paragraph from 'src/components/layout/Paragraph'
|
import Paragraph from 'src/components/layout/Paragraph'
|
||||||
import Row from 'src/components/layout/Row'
|
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 { currentSafe } from 'src/logic/safe/store/selectors'
|
||||||
import { isValidAddress } from 'src/utils/isValidAddress'
|
import { isValidAddress } from 'src/utils/isValidAddress'
|
||||||
|
|
||||||
|
@ -51,8 +50,6 @@ const formMutators: Record<
|
||||||
|
|
||||||
const useStyles = makeStyles(styles)
|
const useStyles = makeStyles(styles)
|
||||||
|
|
||||||
const chainId = getNetworkId()
|
|
||||||
|
|
||||||
type OwnerFormProps = {
|
type OwnerFormProps = {
|
||||||
onClose: () => void
|
onClose: () => void
|
||||||
onSubmit: (values) => void
|
onSubmit: (values) => void
|
||||||
|
@ -64,7 +61,7 @@ export const OwnerForm = ({ onClose, onSubmit, initialValues }: OwnerFormProps):
|
||||||
const handleSubmit = (values) => {
|
const handleSubmit = (values) => {
|
||||||
onSubmit(values)
|
onSubmit(values)
|
||||||
}
|
}
|
||||||
const addressBookMap = useSelector(addressBookMapSelector)
|
const addressBookMap = useSelector(currentNetworkAddressBookAsMap)
|
||||||
const { address: safeAddress = '', owners = [] } = useSelector(currentSafe) ?? {}
|
const { address: safeAddress = '', owners = [] } = useSelector(currentSafe) ?? {}
|
||||||
const ownerDoesntExist = uniqueAddress(owners)
|
const ownerDoesntExist = uniqueAddress(owners)
|
||||||
const ownerAddressIsNotSafeAddress = addressIsNotCurrentSafe(safeAddress)
|
const ownerAddressIsNotSafeAddress = addressIsNotCurrentSafe(safeAddress)
|
||||||
|
@ -122,7 +119,7 @@ export const OwnerForm = ({ onClose, onSubmit, initialValues }: OwnerFormProps):
|
||||||
<OnChange name="ownerAddress">
|
<OnChange name="ownerAddress">
|
||||||
{async (address: string) => {
|
{async (address: string) => {
|
||||||
if (isValidAddress(address)) {
|
if (isValidAddress(address)) {
|
||||||
const { name: ownerName } = addressBookMap[chainId][address]
|
const ownerName = addressBookMap[address]?.name
|
||||||
if (ownerName) {
|
if (ownerName) {
|
||||||
mutators.setOwnerName(ownerName)
|
mutators.setOwnerName(ownerName)
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,12 +24,12 @@ import Row from 'src/components/layout/Row'
|
||||||
import { ScanQRWrapper } from 'src/components/ScanQRModal/ScanQRWrapper'
|
import { ScanQRWrapper } from 'src/components/ScanQRModal/ScanQRWrapper'
|
||||||
import { Modal } from 'src/components/Modal'
|
import { Modal } from 'src/components/Modal'
|
||||||
import { currentSafe } from 'src/logic/safe/store/selectors'
|
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 { OwnerData } from 'src/routes/safe/components/Settings/ManageOwners/dataFetcher'
|
||||||
import { isValidAddress } from 'src/utils/isValidAddress'
|
import { isValidAddress } from 'src/utils/isValidAddress'
|
||||||
|
|
||||||
import { useStyles } from './style'
|
import { useStyles } from './style'
|
||||||
import { getExplorerInfo, getNetworkId } from 'src/config'
|
import { getExplorerInfo } from 'src/config'
|
||||||
import { EthHashInfo } from '@gnosis.pm/safe-react-components'
|
import { EthHashInfo } from '@gnosis.pm/safe-react-components'
|
||||||
|
|
||||||
export const REPLACE_OWNER_NAME_INPUT_TEST_ID = 'replace-owner-name-input'
|
export const REPLACE_OWNER_NAME_INPUT_TEST_ID = 'replace-owner-name-input'
|
||||||
|
@ -50,8 +50,6 @@ const formMutators: Record<
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
const chainId = getNetworkId()
|
|
||||||
|
|
||||||
type NewOwnerProps = {
|
type NewOwnerProps = {
|
||||||
ownerAddress: string
|
ownerAddress: string
|
||||||
ownerName: string
|
ownerName: string
|
||||||
|
@ -70,7 +68,7 @@ export const OwnerForm = ({ onClose, onSubmit, owner, initialValues }: OwnerForm
|
||||||
const handleSubmit = (values: NewOwnerProps) => {
|
const handleSubmit = (values: NewOwnerProps) => {
|
||||||
onSubmit(values)
|
onSubmit(values)
|
||||||
}
|
}
|
||||||
const addressBookMap = useSelector(addressBookMapSelector)
|
const addressBookMap = useSelector(currentNetworkAddressBookAsMap)
|
||||||
const { address: safeAddress = '', owners } = useSelector(currentSafe) ?? {}
|
const { address: safeAddress = '', owners } = useSelector(currentSafe) ?? {}
|
||||||
const ownerDoesntExist = uniqueAddress(owners)
|
const ownerDoesntExist = uniqueAddress(owners)
|
||||||
const ownerAddressIsNotSafeAddress = addressIsNotCurrentSafe(safeAddress)
|
const ownerAddressIsNotSafeAddress = addressIsNotCurrentSafe(safeAddress)
|
||||||
|
@ -149,7 +147,7 @@ export const OwnerForm = ({ onClose, onSubmit, owner, initialValues }: OwnerForm
|
||||||
<OnChange name="ownerAddress">
|
<OnChange name="ownerAddress">
|
||||||
{async (address: string) => {
|
{async (address: string) => {
|
||||||
if (isValidAddress(address)) {
|
if (isValidAddress(address)) {
|
||||||
const ownerName = addressBookMap?.[chainId]?.[address]?.name
|
const ownerName = addressBookMap[address]?.name
|
||||||
if (ownerName) {
|
if (ownerName) {
|
||||||
mutators.setOwnerName(ownerName)
|
mutators.setOwnerName(ownerName)
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,8 +6,7 @@ import styled from 'styled-components'
|
||||||
|
|
||||||
import { ScanQRWrapper } from 'src/components/ScanQRModal/ScanQRWrapper'
|
import { ScanQRWrapper } from 'src/components/ScanQRModal/ScanQRWrapper'
|
||||||
import { getExplorerInfo } from 'src/config'
|
import { getExplorerInfo } from 'src/config'
|
||||||
import { addressBookSelector } from 'src/logic/addressBook/store/selectors'
|
import { currentNetworkAddressBook } from 'src/logic/addressBook/store/selectors'
|
||||||
import { getNameFromAddressBook } from 'src/logic/addressBook/utils'
|
|
||||||
import { AddressBookInput } from 'src/routes/safe/components/Balances/SendModal/screens/AddressBookInput'
|
import { AddressBookInput } from 'src/routes/safe/components/Balances/SendModal/screens/AddressBookInput'
|
||||||
import { sameString } from 'src/utils/strings'
|
import { sameString } from 'src/utils/strings'
|
||||||
|
|
||||||
|
@ -40,13 +39,11 @@ const Beneficiary = (): ReactElement => {
|
||||||
}
|
}
|
||||||
}, [mutators, pristine, selectedEntry])
|
}, [mutators, pristine, selectedEntry])
|
||||||
|
|
||||||
const addressBook = useSelector(addressBookSelector)
|
const addressBook = useSelector(currentNetworkAddressBook)
|
||||||
|
|
||||||
const handleScan = (value, closeQrModal) => {
|
const handleScan = (value, closeQrModal) => {
|
||||||
const scannedAddress = value.startsWith('ethereum:') ? value.replace('ethereum:', '') : value
|
const scannedAddress = value.startsWith('ethereum:') ? value.replace('ethereum:', '') : value
|
||||||
const scannedName = addressBook
|
const scannedName = addressBook[scannedAddress]?.name ?? ''
|
||||||
? getNameFromAddressBook(addressBook, scannedAddress, { filterOnlyValidName: true }) ?? ''
|
|
||||||
: ''
|
|
||||||
|
|
||||||
mutators?.setBeneficiary?.(scannedAddress)
|
mutators?.setBeneficiary?.(scannedAddress)
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@ import React, { ReactElement } from 'react'
|
||||||
import { useSelector } from 'react-redux'
|
import { useSelector } from 'react-redux'
|
||||||
|
|
||||||
import { getExplorerInfo } from 'src/config'
|
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 { ADDRESS_BOOK_DEFAULT_NAME } from 'src/logic/addressBook/model/addressBook'
|
||||||
import { sameString } from 'src/utils/strings'
|
import { sameString } from 'src/utils/strings'
|
||||||
|
|
||||||
|
@ -15,7 +15,7 @@ interface AddressInfoProps {
|
||||||
}
|
}
|
||||||
|
|
||||||
const AddressInfo = ({ address, title }: AddressInfoProps): ReactElement => {
|
const AddressInfo = ({ address, title }: AddressInfoProps): ReactElement => {
|
||||||
const name = useSelector((state) => getNameFromAddressBookSelector(state, { address }))
|
const name = useSelector((state) => addressBookEntryName(state, { address }))
|
||||||
const explorerUrl = getExplorerInfo(address)
|
const explorerUrl = getExplorerInfo(address)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -3,12 +3,12 @@ import React, { ReactElement } from 'react'
|
||||||
import { useSelector } from 'react-redux'
|
import { useSelector } from 'react-redux'
|
||||||
|
|
||||||
import { getExplorerInfo } from 'src/config'
|
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 { ADDRESS_BOOK_DEFAULT_NAME } from 'src/logic/addressBook/model/addressBook'
|
||||||
import { sameString } from 'src/utils/strings'
|
import { sameString } from 'src/utils/strings'
|
||||||
|
|
||||||
export const OwnerRow = ({ address }: { address: string }): ReactElement => {
|
export const OwnerRow = ({ address }: { address: string }): ReactElement => {
|
||||||
const ownerName = useSelector((state) => getNameFromAddressBookSelector(state, { address }))
|
const ownerName = useSelector((state) => addressBookEntryName(state, { address }))
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<EthHashInfo
|
<EthHashInfo
|
||||||
|
|
|
@ -2,14 +2,14 @@ import { useSelector } from 'react-redux'
|
||||||
|
|
||||||
import { sameString } from 'src/utils/strings'
|
import { sameString } from 'src/utils/strings'
|
||||||
import { ADDRESS_BOOK_DEFAULT_NAME } from 'src/logic/addressBook/model/addressBook'
|
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 AddressInfo = { name: string | undefined; image: string | undefined }
|
||||||
|
|
||||||
type UseKnownAddressResponse = AddressInfo & { isAddressBook: boolean }
|
type UseKnownAddressResponse = AddressInfo & { isAddressBook: boolean }
|
||||||
|
|
||||||
export const useKnownAddress = (address: string, addressInfo: AddressInfo): UseKnownAddressResponse => {
|
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
|
// We have to check that the name returned is not UNKNOWN
|
||||||
const isInAddressBook = !sameString(recipientName, ADDRESS_BOOK_DEFAULT_NAME)
|
const isInAddressBook = !sameString(recipientName, ADDRESS_BOOK_DEFAULT_NAME)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue