Skip to content
This repository has been archived by the owner on Nov 10, 2023. It is now read-only.

Commit

Permalink
v1.7.3 (#611)
Browse files Browse the repository at this point in the history
* Fix #597: USD value not load (#609)

* Converts all the addresses to checksum values

* Fix for empty address

* fix the order of transactions, change updateSafe to upgradeSafe to avoid naming confusion with the updateSafe action (#610)

* Fix #596: Notification when safe is already updated (#599)

* Fix notification of update if the safe is already updated

* Makes the notification clickable
Displays the notification for owners only

* Identify upgrade tx

* Add red badge to Settings tab

* Fixs Padding
Removes the red dot if the user is not an owner

Co-authored-by: Fernando <fernando.greco@gmail.com>

Co-authored-by: Fernando <fernando.greco@gmail.com>
Co-authored-by: Agustin Pane <agustin.pane@gmail.com>
  • Loading branch information
3 people authored Feb 26, 2020
1 parent 5bd173b commit 8f0f28b
Show file tree
Hide file tree
Showing 18 changed files with 162 additions and 44 deletions.
2 changes: 1 addition & 1 deletion src/logic/notifications/notificationTypes.js
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,7 @@ export const NOTIFICATIONS: Notifications = {

// Safe Version
SAFE_NEW_VERSION_AVAILABLE: {
message: 'There is a new version available for this Safe',
message: 'There is a new version available for this Safe. Update now!',
options: { variant: WARNING, persist: false, preventDuplicate: true },
},
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import type { MultiSendTransactionInstanceType } from '~/logic/contracts/safeCon
import { DELEGATE_CALL } from '~/logic/safe/transactions'
import { getWeb3 } from '~/logic/wallets/getWeb3'

export const upgradeSafeToLastVersion = async (safeAddress: string, createTransaction: Function) => {
export const upgradeSafeToLatestVersion = async (safeAddress: string, createTransaction: Function) => {
const sendTransactions = async (txs: Array<MultiSendTransactionInstanceType>) => {
const web3 = getWeb3()
const encodeMultiSendCallData = getEncodedMultiSendCallData(txs, web3)
Expand All @@ -35,13 +35,13 @@ export const upgradeSafeToLastVersion = async (safeAddress: string, createTransa
operation: 0,
to: safeAddress,
value: 0,
data: fallbackHandlerTxData,
data: updateSafeTxData,
},
{
operation: 0,
to: safeAddress,
value: 0,
data: updateSafeTxData,
data: fallbackHandlerTxData,
},
]
return sendTransactions(txs)
Expand Down
8 changes: 8 additions & 0 deletions src/logic/tokens/utils/tokenHelpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,3 +53,11 @@ export const isAddressAToken = async (tokenAddress: string) => {

export const isTokenTransfer = (data: string, value: number): boolean =>
!!data && data.substring(0, 10) === '0xa9059cbb' && value === 0

export const isMultisendTransaction = (data: string, value: number): boolean =>
!!data && data.substring(0, 10) === '0x8d80ff0a' && value === 0

// f08a0323 - setFallbackHandler (308, 8)
// 7de7edef - changeMasterCopy (550, 8)
export const isUpgradeTransaction = (data: string) =>
!!data && data.substr(308, 8) === 'f08a0323' && data.substr(550, 8) === '7de7edef'
31 changes: 29 additions & 2 deletions src/routes/safe/components/Layout.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import classNames from 'classnames/bind'
import { Switch, Redirect, Route, withRouter } from 'react-router-dom'
import Tabs from '@material-ui/core/Tabs'
import Tab from '@material-ui/core/Tab'
import Badge from '@material-ui/core/Badge'
import CallMade from '@material-ui/icons/CallMade'
import CallReceived from '@material-ui/icons/CallReceived'
import { withStyles } from '@material-ui/core/styles'
Expand Down Expand Up @@ -35,6 +36,7 @@ import { AddressBookIcon } from './assets/AddressBookIcon'
import { TransactionsIcon } from './assets/TransactionsIcon'
import { BalancesIcon } from './assets/BalancesIcon'
import { AppsIcon } from './assets/AppsIcon'
import { getSafeVersion } from '~/logic/safe/utils/safeVersion'

export const BALANCES_TAB_BTN_TEST_ID = 'balances-tab-btn'
export const SETTINGS_TAB_BTN_TEST_ID = 'settings-tab-btn'
Expand Down Expand Up @@ -102,6 +104,23 @@ const Layout = (props: Props) => {
onClose: null,
})

const [needUpdate, setNeedUpdate] = useState(false)

React.useEffect(() => {
const checkUpdateRequirement = async () => {
let safeVersion = {}

try {
safeVersion = await getSafeVersion(safe.address)
} catch (e) {
console.error('failed to check version', e)
}
setNeedUpdate(safeVersion.needUpdate)
}

checkUpdateRequirement()
}, [safe && safe.address])

const handleCallToRouter = (_, value) => {
const { history } = props

Expand Down Expand Up @@ -147,11 +166,19 @@ const Layout = (props: Props) => {
Apps
</>
)

const labelSettings = (
<>
<SettingsIcon />
Settings
<Badge
badgeContent=""
variant="dot"
invisible={!needUpdate || !granted}
color="error"
style={{ paddingRight: '10px' }}
>
Settings
</Badge>
</>
)
const labelBalances = (
Expand Down
4 changes: 2 additions & 2 deletions src/routes/safe/components/Settings/UpdateSafeModal/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import GnoForm from '~/components/forms/GnoForm'
import Block from '~/components/layout/Block'
import Button from '~/components/layout/Button'
import { styles } from './style'
import { upgradeSafeToLastVersion } from '~/logic/safe/utils/updateSafe'
import { upgradeSafeToLatestVersion } from '~/logic/safe/utils/upgradeSafe'

type Props = {
onClose: Function,
Expand All @@ -22,7 +22,7 @@ type Props = {
const UpdateSafeModal = ({ onClose, classes, safeAddress, createTransaction }: Props) => {
const handleSubmit = async () => {
// Call the update safe method
await upgradeSafeToLastVersion(safeAddress, createTransaction)
await upgradeSafeToLatestVersion(safeAddress, createTransaction)
onClose()
}

Expand Down
23 changes: 22 additions & 1 deletion src/routes/safe/components/Settings/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import * as React from 'react'
import cn from 'classnames'
import { List } from 'immutable'
import { connect } from 'react-redux'
import Badge from '@material-ui/core/Badge'
import { withStyles } from '@material-ui/core/styles'
import Paragraph from '~/components/layout/Paragraph'
import { OwnersIcon } from './assets/icons/OwnersIcon'
Expand All @@ -25,12 +26,14 @@ import { styles } from './style'
import RemoveSafeIcon from './assets/icons/bin.svg'
import type { Safe } from '~/routes/safe/store/models/safe'
import type { AddressBook } from '~/logic/addressBook/model/addressBook'
import { getSafeVersion } from '~/logic/safe/utils/safeVersion'

export const OWNERS_SETTINGS_TAB_TEST_ID = 'owner-settings-tab'

type State = {
showRemoveSafe: boolean,
menuOptionIndex: number,
needUpdate: boolean,
}

type Props = Actions & {
Expand Down Expand Up @@ -63,9 +66,25 @@ class Settings extends React.Component<Props, State> {
this.state = {
showRemoveSafe: false,
menuOptionIndex: 1,
needUpdate: false,
}
}

componentDidMount(): void {
const checkUpdateRequirement = async () => {
let safeVersion = {}

try {
safeVersion = await getSafeVersion(this.props.safe.address)
} catch (e) {
console.error('failed to check version', e)
}
this.setState({ needUpdate: safeVersion.needUpdate })
}

checkUpdateRequirement()
}

handleChange = menuOptionIndex => () => {
this.setState({ menuOptionIndex })
}
Expand Down Expand Up @@ -124,7 +143,9 @@ class Settings extends React.Component<Props, State> {
onClick={this.handleChange(1)}
>
<SafeDetailsIcon />
Safe details
<Badge badgeContent=" " variant="dot" invisible={!this.state.needUpdate || !granted} color="error" style={{paddingRight: '10px'}}>
Safe details
</Badge>
</Row>
<Hairline className={classes.hairline} />
<Row
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,7 @@ const TxDescription = ({ tx, classes }: Props) => {
cancellationTx,
customTx,
creationTx,
upgradeTx,
data,
} = getTxData(tx)
const amount = getTxAmount(tx)
Expand All @@ -179,8 +180,11 @@ const TxDescription = ({ tx, classes }: Props) => {
{modifySettingsTx && (
<SettingsDescription removedOwner={removedOwner} newThreshold={newThreshold} addedOwner={addedOwner} />
)}
{customTx && <CustomDescription data={data} amount={amount} recipient={recipient} classes={classes} />}
{!cancellationTx && !modifySettingsTx && !customTx && !creationTx && (
{!upgradeTx && customTx && (
<CustomDescription data={data} amount={amount} recipient={recipient} classes={classes} />
)}
{upgradeTx && <div>{data}</div>}
{!cancellationTx && !modifySettingsTx && !customTx && !creationTx && !upgradeTx && (
<TransferDescription amount={amount} recipient={recipient} />
)}
</Block>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,16 @@ type DecodedTxData = {
data: string,
}

const getSafeVersion = (data: string) => {
const contractAddress = data.substr(582, 40).toLowerCase()

return (
{
'34cfac646f301356faa8b21e94227e3583fe3f5f': '1.1.1',
}[contractAddress] || 'X.x.x'
)
}

export const getTxData = (tx: Transaction): DecodedTxData => {
const web3 = getWeb3()
const { toBN, fromWei } = web3.utils
Expand Down Expand Up @@ -57,6 +67,9 @@ export const getTxData = (tx: Transaction): DecodedTxData => {
txData.cancellationTx = true
} else if (tx.creationTx) {
txData.creationTx = true
} else if (tx.upgradeTx) {
txData.upgradeTx = true
txData.data = `The contract of this Safe is upgraded to Version ${getSafeVersion(tx.data)}`
} else {
txData.recipient = tx.recipient
txData.value = 0
Expand Down
29 changes: 18 additions & 11 deletions src/routes/safe/components/Transactions/TxsTable/TxType/index.jsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// @flow
import * as React from 'react'
import { withStyles } from '@material-ui/core/styles'
import { makeStyles } from '@material-ui/core/styles'
import Block from '~/components/layout/Block'
import Paragraph from '~/components/layout/Paragraph/'
import Img from '~/components/layout/Img'
Expand All @@ -12,7 +12,6 @@ import SettingsTxIcon from './assets/settings.svg'
import { styles } from './style'

type Props = {
classes: Object,
txType: TransactionType,
}

Expand All @@ -23,6 +22,7 @@ const typeToIcon = {
settings: SettingsTxIcon,
creation: SettingsTxIcon,
cancellation: SettingsTxIcon,
upgrade: SettingsTxIcon,
}

const typeToLabel = {
Expand All @@ -32,15 +32,22 @@ const typeToLabel = {
settings: 'Modify settings',
creation: 'Safe created',
cancellation: 'Cancellation transaction',
upgrade: 'Contract Upgrade',
}

const TxType = ({ classes, txType }: Props) => (
<Block className={classes.container}>
<Img src={typeToIcon[txType]} alt={typeToLabel[txType]} className={classes.img} />
<Paragraph className={classes.type} noMargin>
{typeToLabel[txType]}
</Paragraph>
</Block>
)
const useStyles = makeStyles(styles)

export default withStyles(styles)(TxType)
const TxType = ({ txType }: Props) => {
const classes = useStyles()

return (
<Block className={classes.container}>
<Img src={typeToIcon[txType]} alt={typeToLabel[txType]} className={classes.img} />
<Paragraph className={classes.type} noMargin>
{typeToLabel[txType]}
</Paragraph>
</Block>
)
}

export default TxType
2 changes: 2 additions & 0 deletions src/routes/safe/components/Transactions/TxsTable/columns.js
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@ const getTransactionTableData = (tx: Transaction, cancelTx: ?Transaction): Trans
txType = 'custom'
} else if (tx.creationTx) {
txType = 'creation'
} else if (tx.upgradeTx) {
txType = 'upgrade'
}

return {
Expand Down
11 changes: 7 additions & 4 deletions src/routes/safe/store/actions/fetchSafe.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import type { SafeProps } from '~/routes/safe/store/models/safe'
import addSafe from '~/routes/safe/store/actions/addSafe'
import { getSafeName, getLocalSafe } from '~/logic/safe/utils'
import { getGnosisSafeInstanceAt } from '~/logic/contracts/safeContracts'
import { getBalanceInEtherOf } from '~/logic/wallets/getWeb3'
import { getBalanceInEtherOf, getWeb3 } from '~/logic/wallets/getWeb3'
import { sameAddress } from '~/logic/wallets/ethAddresses'
import removeSafeOwner from '~/routes/safe/store/actions/removeSafeOwner'
import addSafeOwner from '~/routes/safe/store/actions/addSafeOwner'
Expand All @@ -33,7 +33,8 @@ const buildOwnersFrom = (
})
})

export const buildSafe = async (safeAddress: string, safeName: string) => {
export const buildSafe = async (safeAdd: string, safeName: string) => {
const safeAddress = getWeb3().utils.toChecksumAddress(safeAdd)
const gnosisSafe = await getGnosisSafeInstanceAt(safeAddress)
const ethBalance = await getBalanceInEtherOf(safeAddress)

Expand All @@ -53,7 +54,8 @@ export const buildSafe = async (safeAddress: string, safeName: string) => {
return safe
}

export const checkAndUpdateSafe = (safeAddress: string) => async (dispatch: ReduxDispatch<*>) => {
export const checkAndUpdateSafe = (safeAdd: string) => async (dispatch: ReduxDispatch<*>) => {
const safeAddress = getWeb3().utils.toChecksumAddress(safeAdd)
// Check if the owner's safe did change and update them
const [gnosisSafe, localSafe] = await Promise.all([getGnosisSafeInstanceAt(safeAddress), getLocalSafe(safeAddress)])

Expand Down Expand Up @@ -90,8 +92,9 @@ export const checkAndUpdateSafe = (safeAddress: string) => async (dispatch: Redu
}

// eslint-disable-next-line consistent-return
export default (safeAddress: string) => async (dispatch: ReduxDispatch<GlobalState>) => {
export default (safeAdd: string) => async (dispatch: ReduxDispatch<GlobalState>) => {
try {
const safeAddress = getWeb3().utils.toChecksumAddress(safeAdd)
const safeName = (await getSafeName(safeAddress)) || 'LOADED SAFE'
const safeProps: SafeProps = await buildSafe(safeAddress, safeName)

Expand Down
8 changes: 6 additions & 2 deletions src/routes/safe/store/actions/fetchTransactions.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import { getLocalSafe } from '~/logic/safe/utils'
import { addTransactions } from './addTransactions'
import { addIncomingTransactions } from './addIncomingTransactions'
import { getHumanFriendlyToken } from '~/logic/tokens/store/actions/fetchTokens'
import { isTokenTransfer } from '~/logic/tokens/utils/tokenHelpers'
import { isMultisendTransaction, isTokenTransfer, isUpgradeTransaction } from '~/logic/tokens/utils/tokenHelpers'
import { decodeParamsFromSafeMethod } from '~/logic/contracts/methodIds'
import { ALTERNATIVE_TOKEN_ABI } from '~/logic/tokens/utils/alternativeAbi'
import type { TransactionProps } from '~/routes/safe/store/models/transaction'
Expand Down Expand Up @@ -89,7 +89,9 @@ export const buildTransactionFrom = async (safeAddress: string, tx: TxServiceMod
const modifySettingsTx = sameAddress(tx.to, safeAddress) && Number(tx.value) === 0 && !!tx.data
const cancellationTx = sameAddress(tx.to, safeAddress) && Number(tx.value) === 0 && !tx.data
const isSendTokenTx = isTokenTransfer(tx.data, Number(tx.value))
const customTx = !sameAddress(tx.to, safeAddress) && !!tx.data && !isSendTokenTx
const isMultiSendTx = isMultisendTransaction(tx.data, Number(tx.value))
const customTx = !sameAddress(tx.to, safeAddress) && !!tx.data && !isSendTokenTx && !isMultiSendTx
const isUpgradeTx = isMultiSendTx && isUpgradeTransaction(tx.data)

let refundParams = null
if (tx.gasPrice > 0) {
Expand Down Expand Up @@ -165,6 +167,8 @@ export const buildTransactionFrom = async (safeAddress: string, tx: TxServiceMod
executionTxHash: tx.transactionHash,
safeTxHash: tx.safeTxHash,
isTokenTransfer: isSendTokenTx,
multiSendTx: isMultiSendTx,
upgradeTx: isUpgradeTx,
decodedParams,
modifySettingsTx,
customTx,
Expand Down
6 changes: 4 additions & 2 deletions src/routes/safe/store/actions/loadDefaultSafe.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@ import type { Dispatch as ReduxDispatch } from 'redux'
import { type GlobalState } from '~/store/index'
import { getDefaultSafe } from '~/logic/safe/utils'
import setDefaultSafe from './setDefaultSafe'
import { getWeb3 } from '~/logic/wallets/getWeb3'

const loadDefaultSafe = () => async (dispatch: ReduxDispatch<GlobalState>) => {
try {
const defaultSafe: string = await getDefaultSafe()

dispatch(setDefaultSafe(defaultSafe))
const checksumed =
defaultSafe && defaultSafe.length > 0 ? getWeb3().utils.toChecksumAddress(defaultSafe) : defaultSafe
dispatch(setDefaultSafe(checksumed))
} catch (err) {
// eslint-disable-next-line
console.error('Error while getting default Safe from storage:', err)
Expand Down
Loading

0 comments on commit 8f0f28b

Please sign in to comment.