Consistently render known address with Address Book priority (#2195)

* update SRC

* fix known address to take priority from adress book

* rename useGetTxTo to getTxTo

* Liliya feedback

* Liliya feedback

* fix eslint warning

* Fix customIcon for TX-collapsed if address is in AB

Co-authored-by: katspaugh <katspaugh@users.noreply.github.com>
This commit is contained in:
nicolas 2021-05-12 07:53:02 -03:00 committed by GitHub
parent 28e1bd3e77
commit ac2987d999
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 92 additions and 41 deletions

View File

@ -161,7 +161,7 @@
"@gnosis.pm/safe-apps-sdk": "1.0.3", "@gnosis.pm/safe-apps-sdk": "1.0.3",
"@gnosis.pm/safe-apps-sdk-v1": "npm:@gnosis.pm/safe-apps-sdk@0.4.2", "@gnosis.pm/safe-apps-sdk-v1": "npm:@gnosis.pm/safe-apps-sdk@0.4.2",
"@gnosis.pm/safe-contracts": "1.1.1-dev.2", "@gnosis.pm/safe-contracts": "1.1.1-dev.2",
"@gnosis.pm/safe-react-components": "https://github.com/gnosis/safe-react-components.git#b281238", "@gnosis.pm/safe-react-components": "https://github.com/gnosis/safe-react-components.git#4864ebb",
"@gnosis.pm/util-contracts": "2.0.6", "@gnosis.pm/util-contracts": "2.0.6",
"@ledgerhq/hw-transport-node-hid-singleton": "5.49.0", "@ledgerhq/hw-transport-node-hid-singleton": "5.49.0",
"@material-ui/core": "^4.11.0", "@material-ui/core": "^4.11.0",

View File

@ -1,22 +1,22 @@
import { Text } from '@gnosis.pm/safe-react-components' import { EthHashInfo } from '@gnosis.pm/safe-react-components'
import React, { ReactElement } from 'react' import React, { ReactElement } from 'react'
import styled from 'styled-components'
const Wrapper = styled.div` type Props = {
display: flex; address: string
align-items: center; iconUrl?: string
` iconUrlFallback?: string
const Icon = styled.img` text?: string
max-width: 15px; }
max-height: 15px;
margin-right: 9px;
`
type Props = { iconUrl: string | null | undefined; text?: string } export const CustomIconText = ({ address, iconUrl, text, iconUrlFallback }: Props): ReactElement => (
<EthHashInfo
export const CustomIconText = ({ iconUrl, text }: Props): ReactElement => ( hash={address}
<Wrapper> showHash={false}
{iconUrl && <Icon alt={text} src={iconUrl} />} avatarSize="sm"
{text && <Text size="xl">{text}</Text>} showAvatar
</Wrapper> customAvatar={iconUrl || undefined}
customAvatarFallback={iconUrlFallback}
name={text}
textSize="xl"
/>
) )

View File

@ -136,7 +136,7 @@ type BaseCustom = {
toInfo?: AddressInfo toInfo?: AddressInfo
} }
type Custom = BaseCustom & { export type Custom = BaseCustom & {
methodName: string | null methodName: string | null
} }

View File

@ -1,9 +1,8 @@
import { EthHashInfo } from '@gnosis.pm/safe-react-components' import { EthHashInfo } from '@gnosis.pm/safe-react-components'
import React, { ReactElement } from 'react' import React, { ReactElement } from 'react'
import { useSelector } from 'react-redux'
import { getExplorerInfo } from 'src/config'
import { getNameFromAddressBookSelector } from 'src/logic/addressBook/store/selectors' import { getExplorerInfo } from 'src/config'
import { useKnownAddress } from './hooks/useKnownAddress'
type Props = { type Props = {
address: string address: string
@ -12,7 +11,7 @@ type Props = {
} }
export const AddressInfo = ({ address, name, avatarUrl }: Props): ReactElement | null => { export const AddressInfo = ({ address, name, avatarUrl }: Props): ReactElement | null => {
const recipientName = useSelector((state) => getNameFromAddressBookSelector(state, address)) const toInfo = useKnownAddress(address, { name, image: avatarUrl })
if (address === '') { if (address === '') {
return null return null
@ -21,9 +20,9 @@ export const AddressInfo = ({ address, name, avatarUrl }: Props): ReactElement |
return ( return (
<EthHashInfo <EthHashInfo
hash={address} hash={address}
name={recipientName === 'UNKNOWN' ? name : recipientName} name={toInfo.name}
showAvatar showAvatar
customAvatar={avatarUrl} customAvatar={toInfo.image}
showCopyBtn showCopyBtn
explorerUrl={getExplorerInfo(address)} explorerUrl={getExplorerInfo(address)}
/> />

View File

@ -23,7 +23,7 @@ import { TokenTransferAmount } from './TokenTransferAmount'
import { TxsInfiniteScrollContext } from './TxsInfiniteScroll' import { TxsInfiniteScrollContext } from './TxsInfiniteScroll'
import { TxLocationContext } from './TxLocationProvider' import { TxLocationContext } from './TxLocationProvider'
import { CalculatedVotes } from './TxQueueCollapsed' import { CalculatedVotes } from './TxQueueCollapsed'
import { isCancelTxDetails } from './utils' import { getTxTo, isCancelTxDetails } from './utils'
const TxInfo = ({ info }: { info: AssetInfo }) => { const TxInfo = ({ info }: { info: AssetInfo }) => {
if (isTokenTransferAsset(info)) { if (isTokenTransferAsset(info)) {
@ -114,6 +114,7 @@ export const TxCollapsed = ({
}: TxCollapsedProps): ReactElement => { }: TxCollapsedProps): ReactElement => {
const { txLocation } = useContext(TxLocationContext) const { txLocation } = useContext(TxLocationContext)
const { ref, lastItemId } = useContext(TxsInfiniteScrollContext) const { ref, lastItemId } = useContext(TxsInfiniteScrollContext)
const toAddress = getTxTo(transaction)
const willBeReplaced = transaction?.txStatus === 'WILL_BE_REPLACED' ? ' will-be-replaced' : '' const willBeReplaced = transaction?.txStatus === 'WILL_BE_REPLACED' ? ' will-be-replaced' : ''
const onChainRejection = const onChainRejection =
@ -127,7 +128,12 @@ export const TxCollapsed = ({
const txCollapsedType = ( const txCollapsedType = (
<div className={'tx-type' + willBeReplaced + onChainRejection}> <div className={'tx-type' + willBeReplaced + onChainRejection}>
<CustomIconText iconUrl={type.icon} text={type.text} /> <CustomIconText
address={toAddress || '0x'}
iconUrl={type.icon}
iconUrlFallback={type.fallbackIcon}
text={type.text}
/>
</div> </div>
) )

View File

@ -0,0 +1,21 @@
import { useSelector } from 'react-redux'
import { getNameFromAddressBookSelector } 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 isInAddressBook = recipientName !== 'UNKNOWN'
return isInAddressBook
? {
name: recipientName,
image: undefined,
isAddressBook: true,
}
: { ...addressInfo, isAddressBook: false }
}

View File

@ -1,22 +1,31 @@
import { useEffect, useState } from 'react' import { useEffect, useState } from 'react'
import { useSelector } from 'react-redux' import { useSelector } from 'react-redux'
import { Transaction } from 'src/logic/safe/store/models/types/gateway.d' import { Transaction, Custom } from 'src/logic/safe/store/models/types/gateway.d'
import { safeParamAddressFromStateSelector } from 'src/logic/safe/store/selectors' import { safeParamAddressFromStateSelector } from 'src/logic/safe/store/selectors'
import CustomTxIcon from 'src/routes/safe/components/Transactions/TxList/assets/custom.svg' import CustomTxIcon from 'src/routes/safe/components/Transactions/TxList/assets/custom.svg'
import CircleCrossRed from 'src/routes/safe/components/Transactions/TxList/assets/circle-cross-red.svg' import CircleCrossRed from 'src/routes/safe/components/Transactions/TxList/assets/circle-cross-red.svg'
import IncomingTxIcon from 'src/routes/safe/components/Transactions/TxList/assets/incoming.svg' import IncomingTxIcon from 'src/routes/safe/components/Transactions/TxList/assets/incoming.svg'
import OutgoingTxIcon from 'src/routes/safe/components/Transactions/TxList/assets/outgoing.svg' import OutgoingTxIcon from 'src/routes/safe/components/Transactions/TxList/assets/outgoing.svg'
import SettingsTxIcon from 'src/routes/safe/components/Transactions/TxList/assets/settings.svg' import SettingsTxIcon from 'src/routes/safe/components/Transactions/TxList/assets/settings.svg'
import { getTxTo } from 'src/routes/safe/components/Transactions/TxList/utils'
import { useKnownAddress } from './useKnownAddress'
export type TxTypeProps = { export type TxTypeProps = {
icon: string | null icon?: string
text: string fallbackIcon?: string
text?: string
} }
export const useTransactionType = (tx: Transaction): TxTypeProps => { export const useTransactionType = (tx: Transaction): TxTypeProps => {
const [type, setType] = useState<TxTypeProps>({ icon: CustomTxIcon, text: 'Contract interaction' }) const [type, setType] = useState<TxTypeProps>({ icon: CustomTxIcon, text: 'Contract interaction' })
const safeAddress = useSelector(safeParamAddressFromStateSelector) const safeAddress = useSelector(safeParamAddressFromStateSelector)
const toAddress = getTxTo(tx)
// Fixed casting because known address only works for Custom tx
const knownAddress = useKnownAddress(toAddress || '0x', {
name: (tx.txInfo as Custom)?.toInfo?.name,
image: (tx.txInfo as Custom)?.toInfo?.logoUri || undefined,
})
useEffect(() => { useEffect(() => {
switch (tx.txInfo.type) { switch (tx.txInfo.type) {
@ -51,16 +60,15 @@ export const useTransactionType = (tx: Transaction): TxTypeProps => {
} }
const toInfo = tx.txInfo.toInfo const toInfo = tx.txInfo.toInfo
if (toInfo) { setType({
setType({ icon: toInfo.logoUri, text: toInfo.name }) icon: knownAddress.isAddressBook ? CustomTxIcon : knownAddress.image || CustomTxIcon,
break fallbackIcon: knownAddress.isAddressBook ? undefined : CustomTxIcon,
} text: toInfo ? knownAddress.name : 'Contract interaction',
})
setType({ icon: CustomTxIcon, text: 'Contract interaction' })
break break
} }
} }
}, [tx, safeAddress]) }, [tx, safeAddress, knownAddress.name, knownAddress.image, knownAddress.isAddressBook])
return type return type
} }

View File

@ -96,3 +96,20 @@ export const isCancelTxDetails = (txInfo: Transaction['txInfo']): boolean =>
export const addressInList = (list: string[] = []) => (address: string): boolean => export const addressInList = (list: string[] = []) => (address: string): boolean =>
list.some((ownerAddress) => sameAddress(ownerAddress, address)) list.some((ownerAddress) => sameAddress(ownerAddress, address))
export const getTxTo = (tx: Transaction): string | undefined => {
switch (tx.txInfo.type) {
case 'Transfer': {
return tx.txInfo.recipient
}
case 'SettingsChange': {
return undefined
}
case 'Custom': {
return tx.txInfo.to
}
case 'Creation': {
return tx.txInfo.factory || undefined
}
}
}

View File

@ -1637,9 +1637,9 @@
solc "0.5.14" solc "0.5.14"
truffle "^5.1.21" truffle "^5.1.21"
"@gnosis.pm/safe-react-components@https://github.com/gnosis/safe-react-components.git#b281238": "@gnosis.pm/safe-react-components@https://github.com/gnosis/safe-react-components.git#4864ebb":
version "0.5.0" version "0.6.0"
resolved "https://github.com/gnosis/safe-react-components.git#b2812381a265e9b0a17abbc11392986e6c1c74b8" resolved "https://github.com/gnosis/safe-react-components.git#4864ebb57f1c0b39963c7a5a5acc4a8bf90448ea"
dependencies: dependencies:
classnames "^2.2.6" classnames "^2.2.6"
react-media "^1.10.0" react-media "^1.10.0"