Add owners list to load Safe review page

This commit is contained in:
Germán Martínez 2019-05-20 14:49:26 +02:00
parent 853427c1b2
commit 6634286030
2 changed files with 134 additions and 69 deletions

View File

@ -71,7 +71,7 @@ export const safeFieldsValidation = async (values: Object) => {
)
const safeMaster = await getSafeMasterContract()
const masterCopy = safeMaster.address
const sameMasterCopy = checksummedProxyAddress === masterCopy
if (!sameMasterCopy) {
errors[FIELD_LOAD_ADDRESS] = SAFE_MASTERCOPY_ERROR

View File

@ -1,19 +1,25 @@
// @flow
import * as React from 'react'
import classNames from 'classnames'
import Block from '~/components/layout/Block'
import { withStyles } from '@material-ui/core/styles'
import OpenInNew from '@material-ui/icons/OpenInNew'
import Identicon from '~/components/Identicon'
import OpenPaper from '~/components/Stepper/OpenPaper'
import Col from '~/components/layout/Col'
import Row from '~/components/layout/Row'
import Link from '~/components/layout/Link'
import Paragraph from '~/components/layout/Paragraph'
import Hairline from '~/components/layout/Hairline'
import {
xs, sm, lg, border, secondary,
xs, sm, md, lg, border, secondary,
} from '~/theme/variables'
import { shortVersionOf, sameAddress } from '~/logic/wallets/ethAddresses'
import { getNamesFrom, getAccountsFrom } from '~/routes/open/utils/safeDataExtractor'
import { getOwnerNameBy, getOwnerAddressBy, getNumOwnersFrom } from '~/routes/open/components/fields'
import { getEtherScanLink, getWeb3 } from '~/logic/wallets/getWeb3'
import { FIELD_LOAD_NAME, FIELD_LOAD_ADDRESS } from '~/routes/load/components/fields'
import { sameAddress } from '~/logic/wallets/ethAddresses'
import { FIELD_LOAD_NAME, FIELD_LOAD_ADDRESS, THRESHOLD } from '~/routes/load/components/fields'
import { getGnosisSafeContract } from '~/logic/contracts/safeContracts'
const openIconStyle = {
@ -22,13 +28,38 @@ const openIconStyle = {
}
const styles = () => ({
root: {
minHeight: '300px',
},
details: {
padding: lg,
borderRight: `solid 1px ${border}`,
height: '100%',
},
owners: {
padding: lg,
},
name: {
letterSpacing: '-0.6px',
textOverflow: 'ellipsis',
overflow: 'hidden',
},
userName: {
whiteSpace: 'nowrap',
},
owner: {
padding: sm,
paddingLeft: lg,
alignItems: 'center',
},
user: {
justifyContent: 'left',
},
open: {
paddingLeft: sm,
width: 'auto',
'&:hover': {
cursor: 'pointer',
},
},
container: {
marginTop: xs,
@ -60,77 +91,111 @@ type State = {
isOwner: boolean,
}
const checkUserAddressOwner = (values: Object, userAddress: string): boolean => {
let isOwner: boolean = false
for (let i = 0; i < getNumOwnersFrom(values); i += 1) {
if (values[getOwnerAddressBy(i)] === userAddress) {
isOwner = true
break
}
}
return isOwner
}
class ReviewComponent extends React.PureComponent<Props, State> {
state = {
isOwner: false,
}
mounted = false
componentDidMount = async () => {
this.mounted = true
const { values, userAddress } = this.props
const safeAddress = values[FIELD_LOAD_ADDRESS]
const web3 = getWeb3()
const GnosisSafe = getGnosisSafeContract(web3)
const gnosisSafe = await GnosisSafe.at(safeAddress)
const owners = await gnosisSafe.getOwners()
if (!owners) {
return
}
const isOwner = owners.find((owner: string) => sameAddress(owner, userAddress)) !== undefined
if (this.mounted) {
this.setState(() => ({ isOwner }))
}
}
componentWillUnmount() {
this.mounted = false
}
render() {
const { values, classes, network } = this.props
const { isOwner } = this.state
const { values, classes, network, userAddress } = this.props
const isOwner = checkUserAddressOwner(values, userAddress)
const owners = getAccountsFrom(values)
const safeAddress = values[FIELD_LOAD_ADDRESS]
return (
<React.Fragment>
<Block className={classes.details}>
<Block margin="lg">
<Paragraph size="sm" color="disabled" noMargin>
Name of the Safe
</Paragraph>
<Paragraph size="lg" color="primary" noMargin weight="bolder" className={classes.name}>
{values[FIELD_LOAD_NAME]}
</Paragraph>
</Block>
<Block margin="lg">
<Paragraph size="sm" color="disabled" noMargin>
Safe address
</Paragraph>
<Row className={classes.container}>
<Identicon address={safeAddress} diameter={32} />
<Paragraph size="md" color="disabled" noMargin className={classes.address}>
{safeAddress}
<Row className={classes.root}>
<Col xs={4} layout="column">
<Block className={classes.details}>
<Block margin="lg">
<Paragraph size="lg" color="primary" noMargin>
Review details
</Paragraph>
</Block>
<Block margin="lg">
<Paragraph size="sm" color="disabled" noMargin>
Name of the Safe
</Paragraph>
<Paragraph size="lg" color="primary" noMargin weight="bolder" className={classes.name}>
{values[FIELD_LOAD_NAME]}
</Paragraph>
</Block>
<Block margin="lg">
<Paragraph size="sm" color="disabled" noMargin>
Safe address
</Paragraph>
<Row className={classes.container}>
<Identicon address={safeAddress} diameter={32} />
<Paragraph size="md" color="disabled" noMargin className={classes.address}>
{shortVersionOf(safeAddress, 4)}
</Paragraph>
<Link className={classes.open} to={getEtherScanLink(safeAddress, network)} target="_blank">
<OpenInNew style={openIconStyle} />
</Link>
</Row>
</Block>
<Block margin="lg">
<Paragraph size="sm" color="disabled" noMargin>
Connected wallet client is owner?
</Paragraph>
<Paragraph size="lg" color="primary" noMargin weight="bolder" className={classes.name}>
{isOwner ? 'Yes' : 'No (read-only)'}
</Paragraph>
</Block>
<Block margin="lg">
<Paragraph size="sm" color="disabled" noMargin>
Any transaction requires the confirmation of:
</Paragraph>
<Paragraph size="lg" color="primary" noMargin weight="bolder" className={classes.name}>
{`${values[THRESHOLD]} out of ${getNumOwnersFrom(values)} owners`}
</Paragraph>
</Block>
</Block>
</Col>
<Col xs={8} layout="column">
<Block className={classes.owners}>
<Paragraph size="lg" color="primary" noMargin>
{`${getNumOwnersFrom(values)} Safe owners`}
</Paragraph>
<Link className={classes.open} to={getEtherScanLink(safeAddress, network)} target="_blank">
<OpenInNew style={openIconStyle} />
</Link>
</Row>
</Block>
<Block margin="lg">
<Paragraph size="sm" color="disabled" noMargin>
Connected wallet client is owner?
</Paragraph>
<Paragraph size="lg" color="primary" noMargin weight="bolder" className={classes.name}>
{isOwner ? 'Yes' : 'No (read-only)'}
</Paragraph>
</Block>
</Block>
</Block>
<Hairline />
{owners.map((x, index) => (
<React.Fragment key={`name${index}`}>
<Row className={classes.owner}>
<Col xs={1} align="center">
<Identicon address={owners[index]} diameter={32} />
</Col>
<Col xs={11}>
<Block className={classNames(classes.name, classes.userName)}>
<Paragraph size="lg" noMargin>
{values[getOwnerNameBy(index)]}
</Paragraph>
<Block align="center" className={classes.user}>
<Paragraph size="md" color="disabled" noMargin>
{owners[index]}
</Paragraph>
<Link className={classes.open} to={getEtherScanLink(owners[index], network)} target="_blank">
<OpenInNew style={openIconStyle} />
</Link>
</Block>
</Block>
</Col>
</Row>
<Hairline />
</React.Fragment>
))}
</Col>
</Row>
</React.Fragment>
)
}