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

Commit

Permalink
Merge pull request #233 from gnosis/development
Browse files Browse the repository at this point in the history
Development to master
  • Loading branch information
mmv08 authored Oct 24, 2019
2 parents bf6d1bf + 74f9956 commit 625e414
Show file tree
Hide file tree
Showing 66 changed files with 1,416 additions and 854 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@ build_webpack/
build_storybook/
.DS_Store
build/
yarn-error.log
yarn-error.log
.env.*
42 changes: 21 additions & 21 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,14 @@
"dependencies": {
"@gnosis.pm/safe-contracts": "^1.0.0",
"@gnosis.pm/util-contracts": "2.0.4",
"@material-ui/core": "4.5.0",
"@material-ui/icons": "4.4.3",
"@testing-library/jest-dom": "4.1.0",
"@welldone-software/why-did-you-render": "3.3.5",
"@material-ui/core": "4.5.1",
"@material-ui/icons": "4.5.1",
"@testing-library/jest-dom": "4.1.2",
"@welldone-software/why-did-you-render": "3.3.8",
"axios": "0.19.0",
"bignumber.js": "9.0.0",
"connected-react-router": "6.5.2",
"date-fns": "2.4.1",
"date-fns": "2.5.0",
"ethereum-ens": "0.7.8",
"final-form": "4.18.5",
"history": "4.10.1",
Expand All @@ -54,7 +54,7 @@
"react-dom": "16.10.2",
"react-final-form": "6.3.0",
"react-final-form-listeners": "^1.0.2",
"react-hot-loader": "4.12.14",
"react-hot-loader": "4.12.15",
"react-infinite-scroll-component": "4.5.3",
"react-qr-reader": "^2.2.1",
"react-redux": "7.1.1",
Expand All @@ -68,8 +68,8 @@
"web3": "1.2.1"
},
"devDependencies": {
"@babel/cli": "7.6.2",
"@babel/core": "7.6.2",
"@babel/cli": "7.6.4",
"@babel/core": "7.6.4",
"@babel/plugin-proposal-class-properties": "7.5.5",
"@babel/plugin-proposal-decorators": "7.6.0",
"@babel/plugin-proposal-do-expressions": "7.6.0",
Expand All @@ -89,16 +89,16 @@
"@babel/plugin-transform-member-expression-literals": "^7.2.0",
"@babel/plugin-transform-property-literals": "^7.2.0",
"@babel/polyfill": "7.6.0",
"@babel/preset-env": "7.6.2",
"@babel/preset-env": "7.6.3",
"@babel/preset-flow": "^7.0.0",
"@babel/preset-react": "^7.0.0",
"@babel/preset-react": "7.6.3",
"@sambego/storybook-state": "^1.3.6",
"@storybook/addon-actions": "5.2.1",
"@storybook/addon-knobs": "5.2.1",
"@storybook/addon-links": "5.2.1",
"@storybook/react": "5.2.1",
"@storybook/addon-actions": "5.2.4",
"@storybook/addon-knobs": "5.2.4",
"@storybook/addon-links": "5.2.4",
"@storybook/react": "5.2.4",
"@testing-library/react": "9.3.0",
"autoprefixer": "9.6.1",
"autoprefixer": "9.6.5",
"babel-core": "^7.0.0-bridge.0",
"babel-eslint": "10.0.3",
"babel-jest": "24.9.0",
Expand All @@ -113,9 +113,9 @@
"eslint-config-airbnb": "18.0.1",
"eslint-plugin-flowtype": "4.3.0",
"eslint-plugin-import": "2.18.2",
"eslint-plugin-jest": "22.17.0",
"eslint-plugin-jest": "22.19.0",
"eslint-plugin-jsx-a11y": "6.2.3",
"eslint-plugin-react": "7.15.0",
"eslint-plugin-react": "7.16.0",
"ethereumjs-abi": "0.6.8",
"extract-text-webpack-plugin": "^4.0.0-beta.0",
"file-loader": "4.2.0",
Expand All @@ -136,13 +136,13 @@
"storybook-host": "5.1.0",
"storybook-router": "^0.3.4",
"style-loader": "1.0.0",
"truffle": "5.0.39",
"truffle": "5.0.40",
"truffle-contract": "4.0.31",
"truffle-solidity-loader": "0.1.32",
"uglifyjs-webpack-plugin": "2.2.0",
"url-loader": "^2.1.0",
"webpack": "4.41.0",
"webpack-bundle-analyzer": "3.5.2",
"url-loader": "2.2.0",
"webpack": "4.41.2",
"webpack-bundle-analyzer": "3.6.0",
"webpack-cli": "3.3.9",
"webpack-dev-server": "3.8.2",
"webpack-manifest-plugin": "2.2.0"
Expand Down
16 changes: 11 additions & 5 deletions src/components/Notifier/index.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,20 @@
// @flow
import React, { Component } from 'react'
import { Component } from 'react'
import { List } from 'immutable'
import { connect } from 'react-redux'
import { withSnackbar } from 'notistack'
import actions from './actions'
import { type Notification } from '~/logic/notifications/store/models/notification'
import actions, { type Actions } from './actions'
import selector from './selector'

class Notifier extends Component {
type Props = Actions & {
notifications: List<Notification>,
}

class Notifier extends Component<Props> {
displayed = []

shouldComponentUpdate({ notifications: newSnacks = [] }) {
shouldComponentUpdate({ notifications: newSnacks = List() }) {
const { notifications: currentSnacks, closeSnackbar, removeSnackbar } = this.props

if (!newSnacks.size) {
Expand All @@ -27,7 +33,7 @@ class Notifier extends Component {
if (notExists) {
continue
}
notExists = notExists || !currentSnacks.filter(({ key }) => newSnack.key === key).length
notExists = notExists || !currentSnacks.filter(({ key }) => newSnack.key === key).size
}
return notExists
}
Expand Down
4 changes: 2 additions & 2 deletions src/components/forms/validator.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,8 @@ export const minValue = (min: number) => (value: string) => {
return `Should be at least ${min}`
}

export const maxValue = (max: number) => (value: string) => {
if (Number.isNaN(Number(value)) || Number.parseInt(value, 10) <= Number(max)) {
export const maxValue = (max: number | string) => (value: string) => {
if (Number.isNaN(Number(value)) || parseFloat(value, 10) <= parseFloat(max, 10)) {
return undefined
}

Expand Down
2 changes: 1 addition & 1 deletion src/components/layout/Col/index.jsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// @flow
import * as React from 'react'
import classNames from 'classnames/bind'
import React from 'react'
import { capitalize } from '~/utils/css'
import styles from './index.scss'

Expand Down
25 changes: 25 additions & 0 deletions src/logic/contracts/safeContracts.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import contract from 'truffle-contract'
import ProxyFactorySol from '@gnosis.pm/safe-contracts/build/contracts/ProxyFactory.json'
import GnosisSafeSol from '@gnosis.pm/safe-contracts/build/contracts/GnosisSafe.json'
import SafeProxy from '@gnosis.pm/safe-contracts/build/contracts/Proxy.json'
import { ensureOnce } from '~/utils/singleton'
import { getWeb3 } from '~/logic/wallets/getWeb3'
import { calculateGasOf, calculateGasPrice } from '~/logic/wallets/ethTransactions'
Expand Down Expand Up @@ -99,3 +100,27 @@ export const getGnosisSafeInstanceAt = async (safeAddress: string) => {

return gnosisSafe
}

const cleanByteCodeMetadata = (bytecode: string): string => {
const metaData = 'a165'
return bytecode.substring(0, bytecode.lastIndexOf(metaData))
}

export const validateProxy = async (safeAddress: string): boolean => {
// https://solidity.readthedocs.io/en/latest/metadata.html#usage-for-source-code-verification
const web3 = getWeb3()
const code = await web3.eth.getCode(safeAddress)
const codeWithoutMetadata = cleanByteCodeMetadata(code)
const supportedProxies = [SafeProxy]
for (let i = 0; i < supportedProxies.length; i += 1) {
const proxy = supportedProxies[i]
const proxyCode = proxy.deployedBytecode
const proxyCodeWithoutMetadata = cleanByteCodeMetadata(proxyCode)
if (codeWithoutMetadata === proxyCodeWithoutMetadata) {
return true
}
}
// Old PayingProxyCode
const oldProxyCode = '0x60806040526004361061004c576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680634555d5c91461008b5780635c60da1b146100b6575b73ffffffffffffffffffffffffffffffffffffffff600054163660008037600080366000845af43d6000803e6000811415610086573d6000fd5b3d6000f35b34801561009757600080fd5b506100a061010d565b6040518082815260200191505060405180910390f35b3480156100c257600080fd5b506100cb610116565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b60006002905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050905600'
return codeWithoutMetadata === oldProxyCode
}
4 changes: 2 additions & 2 deletions src/logic/notifications/notificationBuilder.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { Close as IconClose } from '@material-ui/icons'
import { TX_NOTIFICATION_TYPES } from '~/logic/safe/transactions'
import { type Notification, NOTIFICATIONS } from './notificationTypes'

type NotificationsQueue = {
export type NotificationsQueue = {
beforeExecution: Notification,
pendingExecution: {
noMoreConfirmationsNeeded: Notification,
Expand Down Expand Up @@ -104,7 +104,7 @@ const defaultNotificationsQueue: NotificationsQueue = {
afterExecutionError: NOTIFICATIONS.TX_FAILED_MSG,
}

export const getNofiticationsFromTxType = (txType: string) => {
export const getNotificationsFromTxType = (txType: string) => {
let notificationsQueue: NotificationsQueue

switch (txType) {
Expand Down
3 changes: 1 addition & 2 deletions src/logic/notifications/store/actions/enqueueSnackbar.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// @flow
import { createAction } from 'redux-actions'
import type { Dispatch as ReduxDispatch, GetState } from 'redux'
import type { Dispatch as ReduxDispatch } from 'redux'
import { type GlobalState } from '~/store'
import { type NotificationProps } from '~/logic/notifications/store/models/notification'

Expand All @@ -10,7 +10,6 @@ const addSnackbar = createAction<string, *>(ENQUEUE_SNACKBAR)

const enqueueSnackbar = (notification: NotificationProps) => (
dispatch: ReduxDispatch<GlobalState>,
getState: GetState<GlobalState>,
) => {
const newNotification = {
...notification,
Expand Down
4 changes: 1 addition & 3 deletions src/logic/notifications/store/reducer/notifications.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,5 @@ export default handleActions<NotificationReducerState, *>(
return state.delete(key)
},
},
Map({
notifications: Map(),
}),
Map(),
)
2 changes: 1 addition & 1 deletion src/logic/notifications/store/selectors/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { type GlobalState } from '~/store'
import { NOTIFICATIONS_REDUCER_ID } from '~/logic/notifications/store/reducer/notifications'
import { type Notification } from '~/logic/notifications/store/models/notification'

export const notificationsMapSelector = (
const notificationsMapSelector = (
state: GlobalState,
): Map<string, Notification> => state[NOTIFICATIONS_REDUCER_ID]

Expand Down
57 changes: 57 additions & 0 deletions src/logic/safe/transactions/gasNew.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
// @flow
import GnosisSafeSol from '@gnosis.pm/safe-contracts/build/contracts/GnosisSafe.json'
import { type Transaction } from '~/routes/safe/store/models/transaction'
import { getWeb3, getAccountFrom } from '~/logic/wallets/getWeb3'
import { generateSignaturesFromTxConfirmations } from '~/routes/safe/store/actions/processTransaction'
import { calculateGasOf, calculateGasPrice } from '~/logic/wallets/ethTransactions'
import { ZERO_ADDRESS } from '~/logic/wallets/ethAddresses'
import { CALL } from '.'

export const estimateTxGasCosts = async (
safeAddress: string,
to: string,
data: string,
tx?: Transaction,
preApprovingOwner?: string,
): Promise<number> => {
try {
const web3 = getWeb3()
const from = await getAccountFrom(web3)
const safeInstance = new web3.eth.Contract(GnosisSafeSol.abi, safeAddress)
const nonce = await safeInstance.methods.nonce().call()
const threshold = await safeInstance.methods.getThreshold().call()

const isExecution = (tx && tx.confirmations.size === threshold) || !!preApprovingOwner || threshold === '1'

let txData
if (isExecution) {
// https://gnosis-safe.readthedocs.io/en/latest/contracts/signatures.html#pre-validated-signatures
const signatures = tx && tx.confirmations
? generateSignaturesFromTxConfirmations(tx.confirmations, preApprovingOwner)
: `0x000000000000000000000000${from.replace(
'0x',
'',
)}000000000000000000000000000000000000000000000000000000000000000001`
txData = await safeInstance.methods
.execTransaction(to, tx ? tx.value : 0, data, CALL, 0, 0, 0, ZERO_ADDRESS, ZERO_ADDRESS, signatures)
.encodeABI()
} else {
const txHash = await safeInstance.methods
.getTransactionHash(to, tx ? tx.value : 0, data, CALL, 0, 0, 0, ZERO_ADDRESS, ZERO_ADDRESS, nonce)
.call({
from,
})
txData = await safeInstance.methods.approveHash(txHash).encodeABI()
}

const gas = await calculateGasOf(txData, from, safeAddress)
const gasPrice = await calculateGasPrice()

return gas * parseInt(gasPrice, 10)
} catch (err) {
console.error('Error while estimating transaction execution gas costs:')
console.error(err)

return 10000
}
}
47 changes: 47 additions & 0 deletions src/logic/tokens/utils/alternativeAbi.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// @flow
// https://github.com/ethers-io/ethers.js/issues/527

export const ALTERNATIVE_TOKEN_ABI = [
{
constant: true,
inputs: [],
name: 'name',
outputs: [
{
name: '',
type: 'bytes32',
},
],
payable: false,
stateMutability: 'view',
type: 'function',
},
{
constant: true,
inputs: [],
name: 'symbol',
outputs: [
{
name: '',
type: 'bytes32',
},
],
payable: false,
stateMutability: 'view',
type: 'function',
},
{
constant: true,
inputs: [],
name: 'decimals',
outputs: [
{
name: '',
type: 'uint8',
},
],
payable: false,
stateMutability: 'view',
type: 'function',
},
]
6 changes: 5 additions & 1 deletion src/logic/tokens/utils/formatAmount.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,11 @@ const lt1000tFormatter = new Intl.NumberFormat([], { maximumFractionDigits: 3, n
export const formatAmount = (number: string | number) => {
let numberFloat = parseFloat(number)

if (numberFloat < 1000) {
if (numberFloat === 0) {
numberFloat = '0.000'
} else if (numberFloat < 0.001) {
numberFloat = '< 0.001'
} else if (numberFloat < 1000) {
numberFloat = lt1kFormatter.format(numberFloat)
} else if (numberFloat < 10000) {
numberFloat = lt10kFormatter.format(numberFloat)
Expand Down
2 changes: 1 addition & 1 deletion src/logic/wallets/ethTransactions.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,6 @@ export const calculateGasOf = async (data: Object, from: string, to: string) =>

return gas * 2
} catch (err) {
return Promise.reject(new Error(err))
return Promise.reject(err)
}
}
2 changes: 1 addition & 1 deletion src/logic/wallets/getWeb3.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ const getProviderName: Function = (web3Provider): string => {
return name
}

const getAccountFrom: Function = async (web3Provider): Promise<string | null> => {
export const getAccountFrom: Function = async (web3Provider): Promise<string | null> => {
const accounts = await web3Provider.eth.getAccounts()

if (process.env.NODE_ENV === 'test' && window.testAccountIndex) {
Expand Down
2 changes: 1 addition & 1 deletion src/routes/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ const Routes = ({ defaultSafe, location }: RoutesProps) => {
/>
<Route exact path={WELCOME_ADDRESS} component={Welcome} />
<Route exact path={OPEN_ADDRESS} component={Open} />
<Route exact path={SAFE_ADDRESS} component={Safe} />
<Route path={SAFE_ADDRESS} component={Safe} />
<Route exact path={OPENING_ADDRESS} component={Opening} />
<Route exact path={LOAD_ADDRESS} component={Load} />
<Redirect to="/" />
Expand Down
Loading

0 comments on commit 625e414

Please sign in to comment.