Merge pull request #1174 from gnosis/issue-1144

Fix: Display abbreviated addresses consistently
This commit is contained in:
nicolas 2020-08-11 14:58:45 -03:00 committed by GitHub
commit f11981357f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 189 additions and 145 deletions

View File

@ -44,7 +44,8 @@
},
"husky": {
"hooks": {
"pre-commit": "lint-staged --allow-empty"
"pre-commit": "lint-staged --allow-empty",
"pre-push": "tsc"
}
},
"lint-staged": {
@ -161,8 +162,8 @@
]
},
"dependencies": {
"@gnosis.pm/safe-contracts": "1.1.1-dev.2",
"@gnosis.pm/safe-react-components": "https://github.com/gnosis/safe-react-components.git#7bb55de",
"@gnosis.pm/safe-contracts": "1.1.1-dev.2",
"@gnosis.pm/safe-react-components": "https://github.com/gnosis/safe-react-components.git#45c746a",
"@gnosis.pm/util-contracts": "2.0.6",
"@ledgerhq/hw-transport-node-hid": "5.19.1",
"@material-ui/core": "4.11.0",

View File

@ -2,11 +2,10 @@ import { withStyles } from '@material-ui/core/styles'
import Dot from '@material-ui/icons/FiberManualRecord'
import classNames from 'classnames'
import * as React from 'react'
import { Identicon } from '@gnosis.pm/safe-react-components'
import { EthHashInfo } from '@gnosis.pm/safe-react-components'
import CopyBtn from 'src/components/CopyBtn'
import EtherscanBtn from 'src/components/EtherscanBtn'
import CircleDot from 'src/components/Header/components/CircleDot'
import Identicon from 'src/components/Identicon'
import Spacer from 'src/components/Spacer'
import Block from 'src/components/layout/Block'
import Button from 'src/components/layout/Button'
@ -14,7 +13,6 @@ import Hairline from 'src/components/layout/Hairline'
import Img from 'src/components/layout/Img'
import Paragraph from 'src/components/layout/Paragraph'
import Row from 'src/components/layout/Row'
import { shortVersionOf } from 'src/logic/wallets/ethAddresses'
import { background, connected as connectedBg, lg, md, sm, warning, xs } from 'src/theme/variables'
import { upperFirst } from 'src/utils/css'
@ -93,8 +91,6 @@ const styles = () => ({
const UserDetails = ({ classes, connected, network, onDisconnect, openDashboard, provider, userAddress }) => {
const status = connected ? 'Connected' : 'Connection error'
const address = userAddress ? shortVersionOf(userAddress, 4) : 'Address not available'
const identiconAddress = userAddress || 'random'
const color = connected ? 'primary' : 'warning'
return (
@ -102,20 +98,16 @@ const UserDetails = ({ classes, connected, network, onDisconnect, openDashboard,
<Block className={classes.container}>
<Row align="center" className={classes.identicon} margin="md">
{connected ? (
<Identicon address={identiconAddress} diameter={60} />
<Identicon address={userAddress || 'random'} size="lg" />
) : (
<CircleDot circleSize={75} dotRight={25} dotSize={25} dotTop={50} hideDot keySize={30} mode="warning" />
)}
</Row>
<Block className={classes.user} justify="center">
<Paragraph className={classes.address} noMargin size="sm">
{address}
</Paragraph>
{userAddress && (
<>
<CopyBtn content={userAddress} increaseZindex />
<EtherscanBtn increaseZindex type="address" value={userAddress} />
</>
{userAddress ? (
<EthHashInfo hash={userAddress} showCopyBtn showEtherscanBtn shortenHash={4} network={network} />
) : (
'Address not available'
)}
</Block>
</Block>

View File

@ -1,12 +1,11 @@
import { makeStyles } from '@material-ui/core/styles'
import * as React from 'react'
import { EthHashInfo, Text } from '@gnosis.pm/safe-react-components'
import NetworkLabel from '../NetworkLabel'
import CircleDot from 'src/components/Header/components/CircleDot'
import Identicon from 'src/components/Identicon'
import Col from 'src/components/layout/Col'
import Paragraph from 'src/components/layout/Paragraph'
import { shortVersionOf } from 'src/logic/wallets/ethAddresses'
import WalletIcon from '../WalletIcon'
import { connected as connectedBg, screenSm, sm } from 'src/theme/variables'
@ -69,10 +68,7 @@ interface ProviderInfoProps {
const ProviderInfo = ({ connected, provider, userAddress, network }: ProviderInfoProps): React.ReactElement => {
const classes = useStyles()
const cutAddress = connected ? shortVersionOf(userAddress, 4) : 'Connection Error'
const color = connected ? 'primary' : 'warning'
const identiconAddress = userAddress || 'random'
const addressColor = connected ? 'text' : 'warning'
return (
<>
{!connected && <CircleDot circleSize={35} dotRight={11} dotSize={16} dotTop={24} keySize={14} mode="warning" />}
@ -89,10 +85,25 @@ const ProviderInfo = ({ connected, provider, userAddress, network }: ProviderInf
{provider}
</Paragraph>
<div className={classes.providerContainer}>
{connected && <Identicon address={identiconAddress} className={classes.identicon} diameter={10} />}
<Paragraph className={classes.address} color={color} noMargin size="xs">
{connected ? (
<EthHashInfo
hash={userAddress}
shortenHash={4}
showIdenticon
identiconSize="xs"
textColor={addressColor}
textSize="sm"
network={network}
/>
) : (
<Text size="md" color={addressColor}>
Connection Error
</Text>
)}
{/* <Paragraph className={classes.address} color={color} noMargin size="xs">
{cutAddress}
</Paragraph>
</Paragraph> */}
</div>
</Col>
<Col className={classes.networkLabel} layout="column" start="sm">

View File

@ -1,34 +1,64 @@
import MuiList from '@material-ui/core/List'
import ListItem from '@material-ui/core/ListItem'
import ListItemIcon from '@material-ui/core/ListItemIcon'
import ListItemText from '@material-ui/core/ListItemText'
import { makeStyles } from '@material-ui/core/styles'
import { EthHashInfo, Icon, Text, ButtonLink } from '@gnosis.pm/safe-react-components'
import * as React from 'react'
import styled from 'styled-components'
import { SafeRecord } from 'src/routes/safe/store/models/safe'
import { DefaultSafe } from 'src/routes/safe/store/reducer/types/safe'
import { SetDefaultSafe } from 'src/routes/safe/store/actions/setDefaultSafe'
import { getNetwork } from 'src/config'
import DefaultBadge from './DefaultBadge'
import check from 'src/assets/icons/check.svg'
import Identicon from 'src/components/Identicon'
import ButtonLink from 'src/components/layout/ButtonLink'
import Hairline from 'src/components/layout/Hairline'
import Img from 'src/components/layout/Img'
import Link from 'src/components/layout/Link'
import Paragraph from 'src/components/layout/Paragraph'
import { formatAmount } from 'src/logic/tokens/utils/formatAmount'
import { sameAddress, shortVersionOf } from 'src/logic/wallets/ethAddresses'
import { sameAddress } from 'src/logic/wallets/ethAddresses'
import { SAFELIST_ADDRESS } from 'src/routes/routes'
import { disabled, md, mediumFontSize, primary, sm } from 'src/theme/variables'
export const SIDEBAR_SAFELIST_ROW_TESTID = 'SIDEBAR_SAFELIST_ROW_TESTID'
const StyledIcon = styled(Icon)`
margin-right: 4px;
`
const AddressWrapper = styled.div`
display: flex;
padding: 5px 0;
width: 100%;
justify-content: space-between;
> nth-child(2) {
display: flex;
align-items: center;
}
`
const StyledButtonLink = styled(ButtonLink)`
visibility: hidden;
white-space: nowrap;
`
const AddressDetails = styled.div`
display: flex;
align-items: center;
justify-content: space-between;
width: 175px;
div {
margin-left: 0px;
padding: 5px 20px;
img {
margin-right: 5px;
}
p {
margin-top: 3px;
}
}
`
const useStyles = makeStyles({
icon: {
marginRight: sm,
},
checkIcon: {
marginRight: '10px',
},
list: {
height: '100%',
overflowX: 'hidden',
@ -38,33 +68,28 @@ const useStyles = makeStyles({
listItemRoot: {
paddingTop: 0,
paddingBottom: 0,
'&:hover $makeDefaultBtn': {
'&:hover .safeListMakeDefaultButton': {
visibility: 'initial',
},
'&:focus $makeDefaultBtn': {
'&:focus .safeListMakeDefaultButton': {
visibility: 'initial',
},
},
safeName: {
color: primary,
overflowWrap: 'break-word',
},
safeAddress: {
color: disabled,
fontSize: mediumFontSize,
},
makeDefaultBtn: {
padding: 0,
marginLeft: md,
visibility: 'hidden',
},
noIcon: {
visibility: 'hidden',
width: '28px',
},
})
const SafeList = ({ currentSafe, defaultSafe, onSafeClick, safes, setDefaultSafe }) => {
type Props = {
currentSafe: string | null
defaultSafe: DefaultSafe
safes: SafeRecord[]
onSafeClick: () => void
setDefaultSafe: SetDefaultSafe
}
const SafeList = ({ currentSafe, defaultSafe, onSafeClick, safes, setDefaultSafe }: Props): React.ReactElement => {
const classes = useStyles()
return (
@ -78,42 +103,38 @@ const SafeList = ({ currentSafe, defaultSafe, onSafeClick, safes, setDefaultSafe
>
<ListItem classes={{ root: classes.listItemRoot }}>
{sameAddress(currentSafe, safe.address) ? (
<ListItemIcon>
<Img alt="check" className={classes.checkIcon} src={check} />
</ListItemIcon>
<StyledIcon type="check" size="md" color="primary" />
) : (
<div className={classes.noIcon}>placeholder</div>
)}
<ListItemIcon>
<Identicon address={safe.address} className={classes.icon} diameter={32} />
</ListItemIcon>
<ListItemText
classes={{
primary: classes.safeName,
secondary: classes.safeAddress,
}}
primary={safe.name}
secondary={shortVersionOf(safe.address, 4)}
/>
<Paragraph color="primary" size="lg">
{`${formatAmount(safe.ethBalance)} ETH`}
</Paragraph>
{sameAddress(defaultSafe, safe.address) ? (
<DefaultBadge />
) : (
<ButtonLink
className={classes.makeDefaultBtn}
onClick={(e) => {
e.preventDefault()
e.stopPropagation()
setDefaultSafe(safe.address)
}}
size="sm"
>
Make default
</ButtonLink>
)}
<AddressWrapper>
<EthHashInfo
hash={safe.address}
name={safe.name}
showIdenticon
shortenHash={4}
network={getNetwork()}
/>
<AddressDetails>
<Text size="xl">{`${formatAmount(safe.ethBalance)} ETH`}</Text>
{sameAddress(defaultSafe, safe.address) ? (
<DefaultBadge />
) : (
<StyledButtonLink
className="safeListMakeDefaultButton"
textSize="sm"
onClick={() => {
setDefaultSafe(safe.address)
}}
color="primary"
>
Make default
</StyledButtonLink>
)}
</AddressDetails>
</AddressWrapper>
</ListItem>
</Link>
<Hairline />

View File

@ -1,4 +1,4 @@
//
//
import { getAccountsFrom, getNamesFrom, getThresholdFrom } from './safeDataExtractor'
describe('Test JS', () => {

View File

@ -23,6 +23,9 @@ import {
} from 'src/routes/safe/store/selectors'
import { isSameHref } from 'src/utils/url'
const StyledCard = styled(Card)`
margin-bottom: 24px;
`
const StyledIframe = styled.iframe`
padding: 15px;
box-sizing: border-box;
@ -271,11 +274,11 @@ function Apps({ closeModal, closeSnackbar, enqueueSnackbar, openModal }) {
<LCL.Content>{getContent()}</LCL.Content>
</LCL.Wrapper>
) : (
<Card style={{ marginBottom: '24px' }}>
<StyledCard>
<Centered>
<Title size="xs">No Apps Enabled</Title>
</Centered>
</Card>
</StyledCard>
)}
<CenteredMT>
<IconText

View File

@ -1,10 +1,12 @@
import { makeStyles } from '@material-ui/core/styles'
import React from 'react'
import { EthHashInfo } from '@gnosis.pm/safe-react-components'
import { getNetwork } from 'src/config'
import { Transaction } from 'src/routes/safe/store/models/types/transaction'
import { formatDate } from 'src/routes/safe/components/Transactions/TxsTable/columns'
import Bold from 'src/components/layout/Bold'
import Paragraph from 'src/components/layout/Paragraph'
import EtherscanLink from 'src/components/EtherscanLink'
import Block from 'src/components/layout/Block'
import { TransactionTypes } from 'src/routes/safe/store/models/types/transaction'
@ -22,7 +24,11 @@ const useStyles = makeStyles({
},
})
export const CreationTx = ({ tx }) => {
type Props = {
tx: Transaction
}
export const CreationTx = ({ tx }: Props): React.ReactElement => {
const classes = useStyles()
if (!tx) {
@ -39,15 +45,27 @@ export const CreationTx = ({ tx }) => {
</Paragraph>
<Block align="left" className={classes.txData}>
<Bold className={classes.txHash}>Creator:</Bold>
{tx.creator ? <EtherscanLink cut={8} type="address" value={tx.creator} /> : 'n/a'}
{tx.creator ? (
<EthHashInfo hash={tx.creator} shortenHash={4} showCopyBtn showEtherscanBtn network={getNetwork()} />
) : (
'n/a'
)}
</Block>
<Block align="left" className={classes.txData}>
<Bold className={classes.txHash}>Factory:</Bold>
{tx.factoryAddress ? <EtherscanLink cut={8} type="address" value={tx.factoryAddress} /> : 'n/a'}
{tx.factoryAddress ? (
<EthHashInfo hash={tx.factoryAddress} shortenHash={4} showCopyBtn showEtherscanBtn network={getNetwork()} />
) : (
'n/a'
)}
</Block>
<Block align="left" className={classes.txData}>
<Bold className={classes.txHash}>Mastercopy:</Bold>
{tx.masterCopy ? <EtherscanLink cut={8} type="address" value={tx.masterCopy} /> : 'n/a'}
{tx.masterCopy ? (
<EthHashInfo hash={tx.masterCopy} shortenHash={4} showCopyBtn showEtherscanBtn network={getNetwork()} />
) : (
'n/a'
)}
</Block>
</>
) : null

View File

@ -2,6 +2,8 @@ import { makeStyles } from '@material-ui/core/styles'
import cn from 'classnames'
import React from 'react'
import { useSelector } from 'react-redux'
import { EthHashInfo } from '@gnosis.pm/safe-react-components'
import { getNetwork } from 'src/config'
import CancelSmallFilledCircle from './assets/cancel-small-filled.svg'
import ConfirmSmallFilledCircle from './assets/confirm-small-filled.svg'
@ -11,12 +13,9 @@ import ConfirmSmallRedCircle from './assets/confirm-small-red.svg'
import PendingSmallYellowCircle from './assets/confirm-small-yellow.svg'
import { styles } from './style'
import EtherscanLink from 'src/components/EtherscanLink'
import Identicon from 'src/components/Identicon'
import Block from 'src/components/layout/Block'
import Button from 'src/components/layout/Button'
import Img from 'src/components/layout/Img'
import Paragraph from 'src/components/layout/Paragraph'
import { getNameFromAddressBook } from 'src/logic/addressBook/store/selectors'
import { OwnersWithoutConfirmations } from './index'
@ -177,13 +176,15 @@ const OwnerComponent = (props: OwnerComponentProps): React.ReactElement => {
<div className={classes.circleState}>
<Img alt="" src={imgCircle} />
</div>
<Identicon address={owner} className={classes.icon} diameter={32} />
<Block>
<Paragraph className={nameInAdbk === 'UNKNOWN' ? null : classes.name} noMargin>
{!nameInAdbk || nameInAdbk === 'UNKNOWN' ? null : nameInAdbk}
</Paragraph>
<EtherscanLink className={classes.address} cut={4} type="address" value={owner} />
</Block>
<EthHashInfo
hash={owner}
name={!nameInAdbk || nameInAdbk === 'UNKNOWN' ? null : nameInAdbk}
shortenHash={4}
showIdenticon
showCopyBtn
showEtherscanBtn
network={getNetwork()}
/>
<Block className={classes.spacer} />
{owner === userAddress && <Block>{isCancelTx ? rejectButton() : confirmButton()}</Block>}
{owner === executor && <Block className={classes.executor}>Executor</Block>}

View File

@ -2,6 +2,7 @@ import { makeStyles } from '@material-ui/core/styles'
import cn from 'classnames'
import React, { useState } from 'react'
import { useSelector } from 'react-redux'
import { EthHashInfo } from '@gnosis.pm/safe-react-components'
import ApproveTxModal from './ApproveTxModal'
import OwnersColumn from './OwnersColumn'
@ -12,7 +13,7 @@ import { CreationTx } from './CreationTx'
import { OutgoingTx } from './OutgoingTx'
import { styles } from './style'
import EtherScanLink from 'src/components/EtherscanLink'
import { getNetwork } from 'src/config'
import Block from 'src/components/layout/Block'
import Bold from 'src/components/layout/Bold'
import Col from 'src/components/layout/Col'
@ -61,10 +62,20 @@ const ExpandedTx = ({ cancelTx, tx }: ExpandedTxProps): React.ReactElement => {
<Row>
<Col layout="column" xs={6}>
<Block className={cn(classes.txDataContainer, (isIncomingTx || isCreationTx) && classes.incomingTxBlock)}>
<Block align="left" className={classes.txData}>
<div style={{ display: 'flex' }}>
<Bold className={classes.txHash}>Hash:</Bold>
{tx.executionTxHash ? <EtherScanLink cut={8} type="tx" value={tx.executionTxHash} /> : 'n/a'}
</Block>
{tx.executionTxHash ? (
<EthHashInfo
hash={tx.executionTxHash}
shortenHash={4}
showCopyBtn
showEtherscanBtn
network={getNetwork()}
/>
) : (
'n/a'
)}
</div>
{!isIncomingTx && !isCreationTx && (
<Paragraph noMargin>
<Bold>Nonce: </Bold>

View File

@ -1,32 +1,12 @@
import { border, connected, disabled, error, lg, md } from 'src/theme/variables'
import { border, lg, md } from 'src/theme/variables'
export const styles = () => ({
const cssStyles = {
expandedTxBlock: {
borderBottom: `2px solid ${border}`,
},
txDataContainer: {
padding: `${lg} ${md}`,
},
txData: {
alignItems: 'center',
display: 'flex',
lineHeight: '1.6',
},
awaiting_your_confirmation: {
color: disabled,
},
awaiting_confirmations: {
color: disabled,
},
awaiting_execution: {
color: disabled,
},
success: {
color: connected,
},
cancelled: {
color: error,
},
txHash: {
paddingRight: '3px',
},
@ -39,4 +19,6 @@ export const styles = () => ({
paddingBottom: md,
borderRight: '2px solid rgb(232, 231, 230)',
},
})
}
export const styles = (): typeof cssStyles => cssStyles

View File

@ -2,6 +2,8 @@ import { createAction } from 'redux-actions'
export const SET_DEFAULT_SAFE = 'SET_DEFAULT_SAFE'
const setDefaultSafe = createAction(SET_DEFAULT_SAFE)
export type SetDefaultSafe = (safe: string) => void
const setDefaultSafe: SetDefaultSafe = createAction(SET_DEFAULT_SAFE)
export default setDefaultSafe

View File

@ -13,7 +13,7 @@ export const makeTransaction = Record<TransactionProps>({
blockNumber: 0,
cancelled: false,
confirmations: List([]),
created: false,
created: '',
creator: '',
creationTx: false,
customTx: false,
@ -25,6 +25,7 @@ export const makeTransaction = Record<TransactionProps>({
executionTxHash: undefined,
executor: '',
factoryAddress: '',
fee: null,
gasPrice: '0',
gasToken: ZERO_ADDRESS,
isCancellationTx: false,

View File

@ -38,7 +38,7 @@ export type TransactionProps = {
blockNumber?: number | null
cancelled?: boolean
confirmations: List<Confirmation>
created: boolean
created: string
creator: string
creationTx: boolean
customTx: boolean
@ -50,7 +50,7 @@ export type TransactionProps = {
executionTxHash?: string | null
executor: string
factoryAddress: string
fee?: string
fee?: string // It will be replace with the new TXs types.
gasPrice: string
gasToken: string
isCancellationTx: boolean

View File

@ -3,8 +3,10 @@ import { Map } from 'immutable'
export type SafesMap = Map<string, SafeRecord>
export type DefaultSafe = 'NOT_ASKED' | string | undefined
export interface SafeReducerState {
defaultSafe: 'NOT_ASKED' | string | undefined
defaultSafe: DefaultSafe
safes: SafesMap
latestMasterContractVersion: string
}

View File

@ -1337,9 +1337,9 @@
solc "0.5.14"
truffle "^5.1.21"
"@gnosis.pm/safe-react-components@https://github.com/gnosis/safe-react-components.git#7bb55de":
"@gnosis.pm/safe-react-components@https://github.com/gnosis/safe-react-components.git#45c746a":
version "0.2.0"
resolved "https://github.com/gnosis/safe-react-components.git#7bb55de2d8a2b6f192466043dc643387fb42dbf6"
resolved "https://github.com/gnosis/safe-react-components.git#45c746a12661b9c38e839e76022b6a0a92285db7"
dependencies:
classnames "^2.2.6"
polished "3.6.5"
@ -18784,7 +18784,6 @@ websocket@^1.0.31:
dependencies:
debug "^2.2.0"
es5-ext "^0.10.50"
gulp "^4.0.2"
nan "^2.14.0"
typedarray-to-buffer "^3.1.5"
yaeti "^0.0.6"