gas calculations wip

This commit is contained in:
mmv 2019-05-21 19:04:52 +04:00
parent b0a7b649a1
commit 2eb09c6398
8 changed files with 91 additions and 20 deletions

View File

@ -10,7 +10,7 @@ const devConfig = {
[TX_SERVICE_HOST]: 'http://localhost:8000/api/v1/', [TX_SERVICE_HOST]: 'http://localhost:8000/api/v1/',
[ENABLED_TX_SERVICE_REMOVAL_SENDER]: false, [ENABLED_TX_SERVICE_REMOVAL_SENDER]: false,
[SIGNATURES_VIA_METAMASK]: false, [SIGNATURES_VIA_METAMASK]: false,
[RELAY_API_URL]: 'https://safe-relay.staging.gnosisdev.com/api/v1/', [RELAY_API_URL]: 'https://safe-relay.staging.gnosisdev.com/api/v1',
} }
export default devConfig export default devConfig

View File

@ -10,7 +10,7 @@ const prodConfig = {
[TX_SERVICE_HOST]: 'https://safe-transaction-history.dev.gnosisdev.com/api/v1/', [TX_SERVICE_HOST]: 'https://safe-transaction-history.dev.gnosisdev.com/api/v1/',
[ENABLED_TX_SERVICE_REMOVAL_SENDER]: false, [ENABLED_TX_SERVICE_REMOVAL_SENDER]: false,
[SIGNATURES_VIA_METAMASK]: false, [SIGNATURES_VIA_METAMASK]: false,
[RELAY_API_URL]: 'https://safe-relay.staging.gnosisdev.com/api/v1/', [RELAY_API_URL]: 'https://safe-relay.staging.gnosisdev.com/api/v1',
} }
export default prodConfig export default prodConfig

View File

@ -10,7 +10,7 @@ const testConfig = {
[TX_SERVICE_HOST]: 'http://localhost:8000/api/v1/', [TX_SERVICE_HOST]: 'http://localhost:8000/api/v1/',
[ENABLED_TX_SERVICE_REMOVAL_SENDER]: false, [ENABLED_TX_SERVICE_REMOVAL_SENDER]: false,
[SIGNATURES_VIA_METAMASK]: false, [SIGNATURES_VIA_METAMASK]: false,
[RELAY_API_URL]: 'https://safe-relay.staging.gnosisdev.com/api/v1/', [RELAY_API_URL]: 'https://safe-relay.staging.gnosisdev.com/api/v1',
} }
export default testConfig export default testConfig

View File

@ -0,0 +1,17 @@
// @flow
import axios from 'axios'
import { getRelayUrl } from '~/config/index'
export const estimateTxGas = (safeAddress: string, to: string, value: string, data, operation = 0) => {
const apiUrl = getRelayUrl()
const url = `${apiUrl}/safes/${safeAddress}/transactions/estimate/`
// const estimationValue = isTokenTransfer(tx.data) ? '0' : value.toString(10)
return axios.post(url, {
safe: safeAddress,
to,
data: '0x',
value,
operation,
})
}

View File

@ -0,0 +1,3 @@
// @flow
export * from './estimateTxGas'

View File

@ -3,6 +3,7 @@ import { getWeb3 } from '~/logic/wallets/getWeb3'
import { BigNumber } from 'bignumber.js' import { BigNumber } from 'bignumber.js'
import { EMPTY_DATA } from '~/logic/wallets/ethTransactions' import { EMPTY_DATA } from '~/logic/wallets/ethTransactions'
import { getSignaturesFrom } from '~/utils/storage/signatures' import { getSignaturesFrom } from '~/utils/storage/signatures'
import { getSafeEthereumInstance } from './safeFrontendOperations';
const estimateDataGasCosts = (data) => { const estimateDataGasCosts = (data) => {
const reducer = (accumulator, currentValue) => { const reducer = (accumulator, currentValue) => {
@ -63,7 +64,12 @@ export const generateTxGasEstimateFrom = async (
operation: number, operation: number,
) => { ) => {
try { try {
const estimateData = safe.contract.methods.requiredTxGas(to, valueInWei, data, operation).encodeABI() let safeInstance = safe
if (!safeInstance) {
safeInstance = await getSafeEthereumInstance(safeAddress)
}
const estimateData = safeInstance.contract.methods.requiredTxGas(to, valueInWei, data, operation).encodeABI()
const estimateResponse = await getWeb3().eth.call({ const estimateResponse = await getWeb3().eth.call({
to: safeAddress, to: safeAddress,
from: safeAddress, from: safeAddress,
@ -72,11 +78,11 @@ export const generateTxGasEstimateFrom = async (
const txGasEstimate = new BigNumber(estimateResponse.substring(138), 16) const txGasEstimate = new BigNumber(estimateResponse.substring(138), 16)
// Add 10k else we will fail in case of nested calls // Add 10k else we will fail in case of nested calls
return Promise.resolve(txGasEstimate.toNumber() + 10000) return txGasEstimate.toNumber() + 10000
} catch (error) { } catch (error) {
// eslint-disable-next-line // eslint-disable-next-line
console.log('Error calculating tx gas estimation ' + error) console.log('Error calculating tx gas estimation ' + error)
return Promise.resolve(0) return 0
} }
} }

View File

@ -1,7 +1,6 @@
// @flow // @flow
import React from 'react' import React from 'react'
import { List } from 'immutable' import { List } from 'immutable'
import { OnChange } from 'react-final-form-listeners'
import { withStyles } from '@material-ui/core/styles' import { withStyles } from '@material-ui/core/styles'
import MenuItem from '@material-ui/core/MenuItem' import MenuItem from '@material-ui/core/MenuItem'
import ListItemIcon from '@material-ui/core/ListItemIcon' import ListItemIcon from '@material-ui/core/ListItemIcon'
@ -18,7 +17,6 @@ import { selectedTokenStyles, selectStyles } from './style'
type SelectFieldProps = { type SelectFieldProps = {
tokens: List<Token>, tokens: List<Token>,
classes: Object, classes: Object,
onTokenChange: Function,
} }
type SelectedTokenProps = { type SelectedTokenProps = {
@ -49,7 +47,7 @@ const SelectedToken = ({ token, classes }: SelectedTokenProps) => (
const SelectedTokenStyled = withStyles(selectedTokenStyles)(SelectedToken) const SelectedTokenStyled = withStyles(selectedTokenStyles)(SelectedToken)
const TokenSelectField = ({ tokens, onTokenChange, classes }: SelectFieldProps) => ( const TokenSelectField = ({ tokens, classes }: SelectFieldProps) => (
<Field <Field
name="token" name="token"
component={SelectField} component={SelectField}
@ -67,11 +65,6 @@ const TokenSelectField = ({ tokens, onTokenChange, classes }: SelectFieldProps)
<ListItemText primary={token.name} secondary={`${token.balance} ${token.symbol}`} /> <ListItemText primary={token.name} secondary={`${token.balance} ${token.symbol}`} />
</MenuItem> </MenuItem>
))} ))}
<OnChange name="token">
{() => {
onTokenChange()
}}
</OnChange>
</Field> </Field>
) )

View File

@ -1,7 +1,9 @@
// @flow // @flow
import * as React from 'react' import React, { useState } from 'react'
import { List } from 'immutable' import { List } from 'immutable'
import { BigNumber } from 'bignumber.js'
import { withStyles } from '@material-ui/core/styles' import { withStyles } from '@material-ui/core/styles'
import { OnChange } from 'react-final-form-listeners'
import Close from '@material-ui/icons/Close' import Close from '@material-ui/icons/Close'
import InputAdornment from '@material-ui/core/InputAdornment' import InputAdornment from '@material-ui/core/InputAdornment'
import IconButton from '@material-ui/core/IconButton' import IconButton from '@material-ui/core/IconButton'
@ -13,11 +15,21 @@ import Block from '~/components/layout/Block'
import Hairline from '~/components/layout/Hairline' import Hairline from '~/components/layout/Hairline'
import ButtonLink from '~/components/layout/ButtonLink' import ButtonLink from '~/components/layout/ButtonLink'
import Field from '~/components/forms/Field' import Field from '~/components/forms/Field'
import Bold from '~/components/layout/Bold'
import TextField from '~/components/forms/TextField' import TextField from '~/components/forms/TextField'
import { getWeb3 } from '~/logic/wallets/getWeb3'
import { type Token } from '~/logic/tokens/store/model/token' import { type Token } from '~/logic/tokens/store/model/token'
import { composeValidators, required, mustBeEthereumAddress } from '~/components/forms/validator' import {
composeValidators,
required,
mustBeEthereumAddress,
mustBeFloat,
maxValue,
greaterThan,
} from '~/components/forms/validator'
import TokenSelectField from '~/routes/safe/components/Balances/SendModal/screens/SendFunds/TokenSelectField' import TokenSelectField from '~/routes/safe/components/Balances/SendModal/screens/SendFunds/TokenSelectField'
import SafeInfo from '~/routes/safe/components/Balances/SendModal/screens/SendFunds/SafeInfo' import SafeInfo from '~/routes/safe/components/Balances/SendModal/screens/SendFunds/SafeInfo'
import { generateTxGasEstimateFrom } from '~/logic/safe/safeTxSignerEIP712'
import ArrowDown from './assets/arrow-down.svg' import ArrowDown from './assets/arrow-down.svg'
import { styles } from './style' import { styles } from './style'
@ -31,9 +43,12 @@ type Props = {
tokens: List<Token>, tokens: List<Token>,
} }
const web3 = getWeb3()
const SendFunds = ({ const SendFunds = ({
classes, onClose, safeAddress, etherScanLink, safeName, ethBalance, tokens, classes, onClose, safeAddress, etherScanLink, safeName, ethBalance, tokens,
}: Props) => { }: Props) => {
const [txFee, setTxFee] = useState(0)
const handleSubmit = () => {} const handleSubmit = () => {}
const formMutators = { const formMutators = {
setMax: (args, state, utils) => { setMax: (args, state, utils) => {
@ -71,7 +86,13 @@ const SendFunds = ({
{(...args) => { {(...args) => {
const formState = args[2] const formState = args[2]
const mutators = args[3] const mutators = args[3]
const { token } = formState.values const { token, recipientAddress, amount } = formState.values
const estimateFee = async () => {
const valueInWei = web3.utils.toWei(amount, 'ether')
const fee = await generateTxGasEstimateFrom(null, safeAddress, '0x', recipientAddress, valueInWei, 0)
setTxFee(fee)
}
return ( return (
<React.Fragment> <React.Fragment>
@ -90,7 +111,7 @@ const SendFunds = ({
</Row> </Row>
<Row margin="sm"> <Row margin="sm">
<Col> <Col>
<TokenSelectField tokens={tokens} onTokenChange={mutators.onTokenChange} /> <TokenSelectField tokens={tokens} />
</Col> </Col>
</Row> </Row>
<Row margin="xs"> <Row margin="xs">
@ -103,13 +124,18 @@ const SendFunds = ({
</ButtonLink> </ButtonLink>
</Col> </Col>
</Row> </Row>
<Row> <Row margin="md">
<Col> <Col>
<Field <Field
name="amount" name="amount"
component={TextField} component={TextField}
type="text" type="text"
validate={composeValidators(required)} validate={composeValidators(
required,
mustBeFloat,
greaterThan(0),
maxValue(token && token.balance),
)}
placeholder="Amount*" placeholder="Amount*"
text="Amount*" text="Amount*"
className={classes.addressInput} className={classes.addressInput}
@ -119,6 +145,32 @@ const SendFunds = ({
} }
} }
/> />
<OnChange name="amount">
{() => {
estimateFee()
}}
</OnChange>
<OnChange name="token">
{() => {
mutators.onTokenChange()
}}
</OnChange>
</Col>
</Row>
<Row margin="xs">
<Col>
<Paragraph size="md" color="disabled" style={{ letterSpacing: '-0.5px' }} noMargin>
Fee
</Paragraph>
</Col>
</Row>
<Row>
<Col layout="column">
<Bold>
{web3.utils.fromWei(web3.utils.toBN(txFee), 'ether')}
{' '}
ETH
</Bold>
</Col> </Col>
</Row> </Row>
</React.Fragment> </React.Fragment>