mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-12-23 09:52:26 +01:00
Further refactors; includes refactor of send-v2.js and associated container
This commit is contained in:
parent
33c16d1bf6
commit
26f965bcce
@ -2,7 +2,8 @@ const fs = require('fs')
|
|||||||
const path = require('path')
|
const path = require('path')
|
||||||
const pump = require('pump')
|
const pump = require('pump')
|
||||||
const browserify = require('browserify')
|
const browserify = require('browserify')
|
||||||
const tests = fs.readdirSync(path.join(__dirname, 'lib'))
|
let tests = fs.readdirSync(path.join(__dirname, 'lib'))
|
||||||
|
tests = tests.filter(fln => fln.match(/send/))
|
||||||
const bundlePath = path.join(__dirname, 'bundle.js')
|
const bundlePath = path.join(__dirname, 'bundle.js')
|
||||||
|
|
||||||
const b = browserify()
|
const b = browserify()
|
||||||
|
@ -1,6 +1,11 @@
|
|||||||
const abi = require('human-standard-token-abi')
|
const abi = require('human-standard-token-abi')
|
||||||
const getBuyEthUrl = require('../../app/scripts/lib/buy-eth-url')
|
const getBuyEthUrl = require('../../app/scripts/lib/buy-eth-url')
|
||||||
const { getTokenAddressFromTokenObject } = require('./util')
|
const { getTokenAddressFromTokenObject } = require('./util')
|
||||||
|
const {
|
||||||
|
calcGasTotal,
|
||||||
|
getParamsForGasEstimate,
|
||||||
|
calcTokenBalance,
|
||||||
|
} = require('./components/send_/send.utils')
|
||||||
const ethUtil = require('ethereumjs-util')
|
const ethUtil = require('ethereumjs-util')
|
||||||
const { fetchLocale } = require('../i18n-helper')
|
const { fetchLocale } = require('../i18n-helper')
|
||||||
const log = require('loglevel')
|
const log = require('loglevel')
|
||||||
@ -173,14 +178,16 @@ var actions = {
|
|||||||
updateGasLimit,
|
updateGasLimit,
|
||||||
updateGasPrice,
|
updateGasPrice,
|
||||||
updateGasTotal,
|
updateGasTotal,
|
||||||
|
setGasTotal,
|
||||||
|
setSendTokenBalance,
|
||||||
updateSendTokenBalance,
|
updateSendTokenBalance,
|
||||||
updateSendFrom,
|
updateSendFrom,
|
||||||
updateSendTo,
|
updateSendTo,
|
||||||
updateSendAmount,
|
updateSendAmount,
|
||||||
updateSendMemo,
|
updateSendMemo,
|
||||||
updateSendErrors,
|
|
||||||
setMaxModeTo,
|
setMaxModeTo,
|
||||||
updateSend,
|
updateSend,
|
||||||
|
updateSendErrors,
|
||||||
clearSend,
|
clearSend,
|
||||||
setSelectedAddress,
|
setSelectedAddress,
|
||||||
// app messages
|
// app messages
|
||||||
@ -716,14 +723,64 @@ function updateGasPrice (gasPrice) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateGasTotal (gasTotal) {
|
function setGasTotal (gasTotal) {
|
||||||
return {
|
return {
|
||||||
type: actions.UPDATE_GAS_TOTAL,
|
type: actions.UPDATE_GAS_TOTAL,
|
||||||
value: gasTotal,
|
value: gasTotal,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateSendTokenBalance (tokenBalance) {
|
function updateGasTotal ({ selectedAddress, selectedToken, data }) {
|
||||||
|
return (dispatch) => {
|
||||||
|
const { symbol } = selectedToken || {}
|
||||||
|
const estimateGasParams = getParamsForGasEstimate(selectedAddress, symbol, data)
|
||||||
|
return Promise.all([
|
||||||
|
dispatch(actions.getGasPrice()),
|
||||||
|
dispatch(actions.estimateGas(estimateGasParams)),
|
||||||
|
])
|
||||||
|
.then(([gasPrice, gas]) => {
|
||||||
|
const newGasTotal = calcGasTotal(gas, gasPrice)
|
||||||
|
dispatch(actions.setGasTotal(newGasTotal))
|
||||||
|
dispatch(updateSendErrors({ gasLoadingError: null }))
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
log.error(err)
|
||||||
|
dispatch(updateSendErrors({ gasLoadingError: 'gasLoadingError' }))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateSendTokenBalance ({
|
||||||
|
selectedToken,
|
||||||
|
tokenContract,
|
||||||
|
address,
|
||||||
|
}) {
|
||||||
|
return (dispatch) => {
|
||||||
|
const tokenBalancePromise = tokenContract
|
||||||
|
? tokenContract.balanceOf(address)
|
||||||
|
: Promise.resolve()
|
||||||
|
return tokenBalancePromise
|
||||||
|
.then(usersToken => {
|
||||||
|
if (usersToken) {
|
||||||
|
const newTokenBalance = calcTokenBalance({ selectedToken, usersToken })
|
||||||
|
dispatch(setSendTokenBalance(newTokenBalance))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
log.error(err)
|
||||||
|
updateSendErrors({ tokenBalance: 'tokenBalanceError' })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateSendErrors (errorObject) {
|
||||||
|
return {
|
||||||
|
type: actions.UPDATE_SEND_ERRORS,
|
||||||
|
value: errorObject,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function setSendTokenBalance (tokenBalance) {
|
||||||
return {
|
return {
|
||||||
type: actions.UPDATE_SEND_TOKEN_BALANCE,
|
type: actions.UPDATE_SEND_TOKEN_BALANCE,
|
||||||
value: tokenBalance,
|
value: tokenBalance,
|
||||||
@ -758,13 +815,6 @@ function updateSendMemo (memo) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateSendErrors (error) {
|
|
||||||
return {
|
|
||||||
type: actions.UPDATE_SEND_ERRORS,
|
|
||||||
value: error,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function setMaxModeTo (bool) {
|
function setMaxModeTo (bool) {
|
||||||
return {
|
return {
|
||||||
type: actions.UPDATE_MAX_MODE,
|
type: actions.UPDATE_MAX_MODE,
|
||||||
|
@ -11,7 +11,7 @@ const log = require('loglevel')
|
|||||||
// init
|
// init
|
||||||
const InitializeScreen = require('../../mascara/src/app/first-time').default
|
const InitializeScreen = require('../../mascara/src/app/first-time').default
|
||||||
// accounts
|
// accounts
|
||||||
const SendTransactionScreen2 = require('./components/send/send-v2-container')
|
const SendTransactionScreen = require('./components/send_/send.container')
|
||||||
const ConfirmTxScreen = require('./conf-tx')
|
const ConfirmTxScreen = require('./conf-tx')
|
||||||
|
|
||||||
// slideout menu
|
// slideout menu
|
||||||
@ -84,7 +84,7 @@ class App extends Component {
|
|||||||
h(Initialized, { path: RESTORE_VAULT_ROUTE, exact, component: RestoreVaultPage }),
|
h(Initialized, { path: RESTORE_VAULT_ROUTE, exact, component: RestoreVaultPage }),
|
||||||
h(Initialized, { path: NOTICE_ROUTE, exact, component: NoticeScreen }),
|
h(Initialized, { path: NOTICE_ROUTE, exact, component: NoticeScreen }),
|
||||||
h(Authenticated, { path: CONFIRM_TRANSACTION_ROUTE, component: ConfirmTxScreen }),
|
h(Authenticated, { path: CONFIRM_TRANSACTION_ROUTE, component: ConfirmTxScreen }),
|
||||||
h(Authenticated, { path: SEND_ROUTE, exact, component: SendTransactionScreen2 }),
|
h(Authenticated, { path: SEND_ROUTE, exact, component: SendTransactionScreen }),
|
||||||
h(Authenticated, { path: ADD_TOKEN_ROUTE, exact, component: AddTokenPage }),
|
h(Authenticated, { path: ADD_TOKEN_ROUTE, exact, component: AddTokenPage }),
|
||||||
h(Authenticated, { path: NEW_ACCOUNT_ROUTE, component: CreateAccountPage }),
|
h(Authenticated, { path: NEW_ACCOUNT_ROUTE, component: CreateAccountPage }),
|
||||||
h(Authenticated, { path: DEFAULT_ROUTE, exact, component: Home }),
|
h(Authenticated, { path: DEFAULT_ROUTE, exact, component: Home }),
|
||||||
|
@ -8,6 +8,10 @@ const GasModalCard = require('./gas-modal-card')
|
|||||||
|
|
||||||
const ethUtil = require('ethereumjs-util')
|
const ethUtil = require('ethereumjs-util')
|
||||||
|
|
||||||
|
import {
|
||||||
|
updateSendErrors,
|
||||||
|
} from '../../ducks/send'
|
||||||
|
|
||||||
const {
|
const {
|
||||||
MIN_GAS_PRICE_DEC,
|
MIN_GAS_PRICE_DEC,
|
||||||
MIN_GAS_LIMIT_DEC,
|
MIN_GAS_LIMIT_DEC,
|
||||||
@ -63,9 +67,9 @@ function mapDispatchToProps (dispatch) {
|
|||||||
hideModal: () => dispatch(actions.hideModal()),
|
hideModal: () => dispatch(actions.hideModal()),
|
||||||
updateGasPrice: newGasPrice => dispatch(actions.updateGasPrice(newGasPrice)),
|
updateGasPrice: newGasPrice => dispatch(actions.updateGasPrice(newGasPrice)),
|
||||||
updateGasLimit: newGasLimit => dispatch(actions.updateGasLimit(newGasLimit)),
|
updateGasLimit: newGasLimit => dispatch(actions.updateGasLimit(newGasLimit)),
|
||||||
updateGasTotal: newGasTotal => dispatch(actions.updateGasTotal(newGasTotal)),
|
updateGasTotal: newGasTotal => dispatch(actions.setGasTotal(newGasTotal)),
|
||||||
updateSendAmount: newAmount => dispatch(actions.updateSendAmount(newAmount)),
|
updateSendAmount: newAmount => dispatch(actions.updateSendAmount(newAmount)),
|
||||||
updateSendErrors: error => dispatch(actions.updateSendErrors(error)),
|
updateSendErrors: error => dispatch(updateSendErrors(error)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,6 +29,10 @@ const currencies = require('currency-formatter/currencies')
|
|||||||
const { MIN_GAS_PRICE_HEX } = require('../send/send-constants')
|
const { MIN_GAS_PRICE_HEX } = require('../send/send-constants')
|
||||||
const { SEND_ROUTE, DEFAULT_ROUTE } = require('../../routes')
|
const { SEND_ROUTE, DEFAULT_ROUTE } = require('../../routes')
|
||||||
|
|
||||||
|
import {
|
||||||
|
updateSendErrors,
|
||||||
|
} from '../../ducks/send'
|
||||||
|
|
||||||
ConfirmSendEther.contextTypes = {
|
ConfirmSendEther.contextTypes = {
|
||||||
t: PropTypes.func,
|
t: PropTypes.func,
|
||||||
}
|
}
|
||||||
@ -105,7 +109,7 @@ function mapDispatchToProps (dispatch) {
|
|||||||
}))
|
}))
|
||||||
dispatch(actions.showModal({ name: 'CUSTOMIZE_GAS' }))
|
dispatch(actions.showModal({ name: 'CUSTOMIZE_GAS' }))
|
||||||
},
|
},
|
||||||
updateSendErrors: error => dispatch(actions.updateSendErrors(error)),
|
updateSendErrors: error => dispatch(updateSendErrors(error)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,6 +39,10 @@ const {
|
|||||||
} = require('../../selectors')
|
} = require('../../selectors')
|
||||||
const { SEND_ROUTE, DEFAULT_ROUTE } = require('../../routes')
|
const { SEND_ROUTE, DEFAULT_ROUTE } = require('../../routes')
|
||||||
|
|
||||||
|
import {
|
||||||
|
updateSendErrors,
|
||||||
|
} from '../../ducks/send'
|
||||||
|
|
||||||
ConfirmSendToken.contextTypes = {
|
ConfirmSendToken.contextTypes = {
|
||||||
t: PropTypes.func,
|
t: PropTypes.func,
|
||||||
}
|
}
|
||||||
@ -141,7 +145,7 @@ function mapDispatchToProps (dispatch, ownProps) {
|
|||||||
}))
|
}))
|
||||||
dispatch(actions.showModal({ name: 'CUSTOMIZE_GAS' }))
|
dispatch(actions.showModal({ name: 'CUSTOMIZE_GAS' }))
|
||||||
},
|
},
|
||||||
updateSendErrors: error => dispatch(actions.updateSendErrors(error)),
|
updateSendErrors: error => dispatch(updateSendErrors(error)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,6 +18,10 @@ const {
|
|||||||
getSelectedTokenContract,
|
getSelectedTokenContract,
|
||||||
} = require('../../selectors')
|
} = require('../../selectors')
|
||||||
|
|
||||||
|
import {
|
||||||
|
updateSendErrors,
|
||||||
|
} from '../../ducks/send'
|
||||||
|
|
||||||
module.exports = compose(
|
module.exports = compose(
|
||||||
withRouter,
|
withRouter,
|
||||||
connect(mapStateToProps, mapDispatchToProps)
|
connect(mapStateToProps, mapDispatchToProps)
|
||||||
@ -74,7 +78,8 @@ function mapDispatchToProps (dispatch) {
|
|||||||
updateTx: txData => dispatch(actions.updateTransaction(txData)),
|
updateTx: txData => dispatch(actions.updateTransaction(txData)),
|
||||||
setSelectedAddress: address => dispatch(actions.setSelectedAddress(address)),
|
setSelectedAddress: address => dispatch(actions.setSelectedAddress(address)),
|
||||||
addToAddressBook: (address, nickname) => dispatch(actions.addToAddressBook(address, nickname)),
|
addToAddressBook: (address, nickname) => dispatch(actions.addToAddressBook(address, nickname)),
|
||||||
updateGasTotal: newTotal => dispatch(actions.updateGasTotal(newTotal)),
|
setGasTotal: newTotal => dispatch(actions.setGasTotal(newTotal)),
|
||||||
|
updateGasTotal: () => dispatch(actions.updateGasTotal()),
|
||||||
updateGasPrice: newGasPrice => dispatch(actions.updateGasPrice(newGasPrice)),
|
updateGasPrice: newGasPrice => dispatch(actions.updateGasPrice(newGasPrice)),
|
||||||
updateGasLimit: newGasLimit => dispatch(actions.updateGasLimit(newGasLimit)),
|
updateGasLimit: newGasLimit => dispatch(actions.updateGasLimit(newGasLimit)),
|
||||||
updateSendTokenBalance: tokenBalance => dispatch(actions.updateSendTokenBalance(tokenBalance)),
|
updateSendTokenBalance: tokenBalance => dispatch(actions.updateSendTokenBalance(tokenBalance)),
|
||||||
@ -82,7 +87,7 @@ function mapDispatchToProps (dispatch) {
|
|||||||
updateSendTo: (newTo, nickname) => dispatch(actions.updateSendTo(newTo, nickname)),
|
updateSendTo: (newTo, nickname) => dispatch(actions.updateSendTo(newTo, nickname)),
|
||||||
updateSendAmount: newAmount => dispatch(actions.updateSendAmount(newAmount)),
|
updateSendAmount: newAmount => dispatch(actions.updateSendAmount(newAmount)),
|
||||||
updateSendMemo: newMemo => dispatch(actions.updateSendMemo(newMemo)),
|
updateSendMemo: newMemo => dispatch(actions.updateSendMemo(newMemo)),
|
||||||
updateSendErrors: newError => dispatch(actions.updateSendErrors(newError)),
|
updateSendErrors: newError => dispatch(updateSendErrors(newError)),
|
||||||
clearSend: () => dispatch(actions.clearSend()),
|
clearSend: () => dispatch(actions.clearSend()),
|
||||||
setMaxModeTo: bool => dispatch(actions.setMaxModeTo(bool)),
|
setMaxModeTo: bool => dispatch(actions.setMaxModeTo(bool)),
|
||||||
}
|
}
|
||||||
|
@ -12,4 +12,4 @@ function mapStateToProps (state) {
|
|||||||
conversionRate: getConversionRate(state),
|
conversionRate: getConversionRate(state),
|
||||||
currentCurrency: getConvertedCurrency(state),
|
currentCurrency: getConvertedCurrency(state),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,10 +9,12 @@ import { getMaxModeOn } from '../send-amount-row.selectors.js'
|
|||||||
import { calcMaxAmount } from './amount-max-button.utils.js'
|
import { calcMaxAmount } from './amount-max-button.utils.js'
|
||||||
import {
|
import {
|
||||||
updateSendAmount,
|
updateSendAmount,
|
||||||
updateSendErrors,
|
|
||||||
setMaxModeTo,
|
setMaxModeTo,
|
||||||
} from '../../../actions'
|
} from '../../../../../actions'
|
||||||
import AmountMaxButton from './amount-max-button.component'
|
import AmountMaxButton from './amount-max-button.component'
|
||||||
|
import {
|
||||||
|
updateSendErrors,
|
||||||
|
} from '../../../../../ducks/send'
|
||||||
|
|
||||||
export default connect(mapStateToProps, mapDispatchToProps)(AmountMaxButton)
|
export default connect(mapStateToProps, mapDispatchToProps)(AmountMaxButton)
|
||||||
|
|
||||||
|
@ -8,7 +8,10 @@ export default class SendAmountRow extends Component {
|
|||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
amount: PropTypes.string,
|
amount: PropTypes.string,
|
||||||
amountConversionRate: PropTypes.number,
|
amountConversionRate: PropTypes.oneOfType([
|
||||||
|
PropTypes.string,
|
||||||
|
PropTypes.number,
|
||||||
|
]),
|
||||||
balance: PropTypes.string,
|
balance: PropTypes.string,
|
||||||
conversionRate: PropTypes.number,
|
conversionRate: PropTypes.number,
|
||||||
convertedCurrency: PropTypes.string,
|
convertedCurrency: PropTypes.string,
|
||||||
|
@ -1,24 +1,26 @@
|
|||||||
import { connect } from 'react-redux'
|
import { connect } from 'react-redux'
|
||||||
import {
|
import {
|
||||||
|
getAmountConversionRate,
|
||||||
getConversionRate,
|
getConversionRate,
|
||||||
getConvertedCurrency,
|
getConvertedCurrency,
|
||||||
getGasTotal,
|
getGasTotal,
|
||||||
|
getPrimaryCurrency,
|
||||||
getSelectedToken,
|
getSelectedToken,
|
||||||
getSendAmount,
|
getSendAmount,
|
||||||
getSendFromBalance,
|
getSendFromBalance,
|
||||||
getTokenBalance,
|
getTokenBalance,
|
||||||
} from '../../send.selectors.js'
|
} from '../../send.selectors'
|
||||||
import {
|
import {
|
||||||
getAmountConversionRate,
|
|
||||||
getPrimaryCurrency,
|
|
||||||
sendAmountIsInError,
|
sendAmountIsInError,
|
||||||
} from './send-amount-row.selectors.js'
|
} from './send-amount-row.selectors'
|
||||||
import { getAmountErrorObject } from './send-amount-row.utils.js'
|
import { getAmountErrorObject } from '../../send.utils'
|
||||||
import {
|
import {
|
||||||
setMaxModeTo,
|
setMaxModeTo,
|
||||||
updateSendAmount,
|
updateSendAmount,
|
||||||
updateSendErrors,
|
|
||||||
} from '../../../../actions'
|
} from '../../../../actions'
|
||||||
|
import {
|
||||||
|
updateSendErrors,
|
||||||
|
} from '../../../../ducks/send'
|
||||||
import SendAmountRow from './send-amount-row.component'
|
import SendAmountRow from './send-amount-row.component'
|
||||||
|
|
||||||
export default connect(mapStateToProps, mapDispatchToProps)(SendAmountRow)
|
export default connect(mapStateToProps, mapDispatchToProps)(SendAmountRow)
|
||||||
|
@ -1,13 +1,5 @@
|
|||||||
import {
|
|
||||||
getSelectedToken,
|
|
||||||
getSelectedTokenToFiatRate,
|
|
||||||
getConversionRate,
|
|
||||||
} from '../../send.selectors.js'
|
|
||||||
|
|
||||||
const selectors = {
|
const selectors = {
|
||||||
getAmountConversionRate,
|
|
||||||
getMaxModeOn,
|
getMaxModeOn,
|
||||||
getPrimaryCurrency,
|
|
||||||
sendAmountIsInError,
|
sendAmountIsInError,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -18,16 +10,5 @@ function getMaxModeOn (state) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function sendAmountIsInError (state) {
|
function sendAmountIsInError (state) {
|
||||||
return Boolean(state.metamask.send.errors.amount)
|
return Boolean(state.send.errors.amount)
|
||||||
}
|
|
||||||
|
|
||||||
function getPrimaryCurrency (state) {
|
|
||||||
const selectedToken = getSelectedToken(state)
|
|
||||||
return selectedToken && selectedToken.symbol
|
|
||||||
}
|
|
||||||
|
|
||||||
function getAmountConversionRate (state) {
|
|
||||||
return getSelectedToken(state)
|
|
||||||
? getSelectedTokenToFiatRate(state)
|
|
||||||
: getConversionRate(state)
|
|
||||||
}
|
}
|
||||||
|
@ -1,61 +0,0 @@
|
|||||||
const {
|
|
||||||
conversionGreaterThan,
|
|
||||||
} = require('../../../../conversion-util')
|
|
||||||
const {
|
|
||||||
isBalanceSufficient,
|
|
||||||
isTokenBalanceSufficient,
|
|
||||||
} = require('../../send.utils')
|
|
||||||
|
|
||||||
function getAmountErrorObject ({
|
|
||||||
amount,
|
|
||||||
amountConversionRate,
|
|
||||||
balance,
|
|
||||||
conversionRate,
|
|
||||||
gasTotal,
|
|
||||||
primaryCurrency,
|
|
||||||
selectedToken,
|
|
||||||
tokenBalance,
|
|
||||||
}) {
|
|
||||||
let insufficientFunds = false
|
|
||||||
if (gasTotal && conversionRate) {
|
|
||||||
insufficientFunds = !isBalanceSufficient({
|
|
||||||
amount: selectedToken ? '0x0' : amount,
|
|
||||||
amountConversionRate,
|
|
||||||
balance,
|
|
||||||
conversionRate,
|
|
||||||
gasTotal,
|
|
||||||
primaryCurrency,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
let inSufficientTokens = false
|
|
||||||
if (selectedToken && tokenBalance !== null) {
|
|
||||||
const { decimals } = selectedToken
|
|
||||||
inSufficientTokens = !isTokenBalanceSufficient({
|
|
||||||
tokenBalance,
|
|
||||||
amount,
|
|
||||||
decimals,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const amountLessThanZero = conversionGreaterThan(
|
|
||||||
{ value: 0, fromNumericBase: 'dec' },
|
|
||||||
{ value: amount, fromNumericBase: 'hex' },
|
|
||||||
)
|
|
||||||
|
|
||||||
let amountError = null
|
|
||||||
|
|
||||||
if (insufficientFunds) {
|
|
||||||
amountError = 'insufficientFunds'
|
|
||||||
} else if (inSufficientTokens) {
|
|
||||||
amountError = 'insufficientTokens'
|
|
||||||
} else if (amountLessThanZero) {
|
|
||||||
amountError = 'negativeETH'
|
|
||||||
}
|
|
||||||
|
|
||||||
return { amount: amountError }
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
getAmountErrorObject,
|
|
||||||
}
|
|
@ -14,19 +14,19 @@ export default class SendFromRow extends Component {
|
|||||||
openFromDropdown: PropTypes.func,
|
openFromDropdown: PropTypes.func,
|
||||||
tokenContract: PropTypes.object,
|
tokenContract: PropTypes.object,
|
||||||
updateSendFrom: PropTypes.func,
|
updateSendFrom: PropTypes.func,
|
||||||
updateSendTokenBalance: PropTypes.func,
|
setSendTokenBalance: PropTypes.func,
|
||||||
};
|
};
|
||||||
|
|
||||||
async handleFromChange (newFrom) {
|
async handleFromChange (newFrom) {
|
||||||
const {
|
const {
|
||||||
updateSendFrom,
|
updateSendFrom,
|
||||||
tokenContract,
|
tokenContract,
|
||||||
updateSendTokenBalance,
|
setSendTokenBalance,
|
||||||
} = this.props
|
} = this.props
|
||||||
|
|
||||||
if (tokenContract) {
|
if (tokenContract) {
|
||||||
const usersToken = await tokenContract.balanceOf(newFrom.address)
|
const usersToken = await tokenContract.balanceOf(newFrom.address)
|
||||||
updateSendTokenBalance(usersToken)
|
setSendTokenBalance(usersToken)
|
||||||
}
|
}
|
||||||
updateSendFrom(newFrom)
|
updateSendFrom(newFrom)
|
||||||
}
|
}
|
||||||
|
@ -11,7 +11,7 @@ import {
|
|||||||
import { calcTokenUpdateAmount } from './send-from-row.utils.js'
|
import { calcTokenUpdateAmount } from './send-from-row.utils.js'
|
||||||
import {
|
import {
|
||||||
updateSendFrom,
|
updateSendFrom,
|
||||||
updateSendTokenBalance,
|
setSendTokenBalance,
|
||||||
} from '../../../../actions'
|
} from '../../../../actions'
|
||||||
import {
|
import {
|
||||||
closeFromDropdown,
|
closeFromDropdown,
|
||||||
@ -36,11 +36,11 @@ function mapDispatchToProps (dispatch) {
|
|||||||
closeFromDropdown: () => dispatch(closeFromDropdown()),
|
closeFromDropdown: () => dispatch(closeFromDropdown()),
|
||||||
openFromDropdown: () => dispatch(openFromDropdown()),
|
openFromDropdown: () => dispatch(openFromDropdown()),
|
||||||
updateSendFrom: newFrom => dispatch(updateSendFrom(newFrom)),
|
updateSendFrom: newFrom => dispatch(updateSendFrom(newFrom)),
|
||||||
updateSendTokenBalance: (usersToken, selectedToken) => {
|
setSendTokenBalance: (usersToken, selectedToken) => {
|
||||||
if (!usersToken) return
|
if (!usersToken) return
|
||||||
|
|
||||||
const tokenBalance = calcTokenUpdateAmount(selectedToken, selectedToken)
|
const tokenBalance = calcTokenUpdateAmount(selectedToken, selectedToken)
|
||||||
dispatch(updateSendTokenBalance(tokenBalance))
|
dispatch(setSendTokenBalance(tokenBalance))
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,23 +18,8 @@ export default class SendGasRow extends Component {
|
|||||||
showCustomizeGasModal: PropTypes.func,
|
showCustomizeGasModal: PropTypes.func,
|
||||||
tokenContract: PropTypes.object,
|
tokenContract: PropTypes.object,
|
||||||
updateSendFrom: PropTypes.func,
|
updateSendFrom: PropTypes.func,
|
||||||
updateSendTokenBalance: PropTypes.func,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
async handleFromChange (newFrom) {
|
|
||||||
const {
|
|
||||||
tokenContract,
|
|
||||||
updateSendFrom,
|
|
||||||
updateSendTokenBalance,
|
|
||||||
} = this.props
|
|
||||||
|
|
||||||
if (tokenContract) {
|
|
||||||
const usersToken = await tokenContract.balanceOf(newFrom.address)
|
|
||||||
updateSendTokenBalance(usersToken)
|
|
||||||
}
|
|
||||||
updateSendFrom(newFrom)
|
|
||||||
}
|
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const {
|
const {
|
||||||
conversionRate,
|
conversionRate,
|
||||||
|
@ -10,6 +10,7 @@ export default class SendRowErrorMessage extends Component {
|
|||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { errors, errorType } = this.props
|
const { errors, errorType } = this.props
|
||||||
|
|
||||||
const errorMessage = errors[errorType]
|
const errorMessage = errors[errorType]
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -10,12 +10,12 @@ import {
|
|||||||
} from './send-to-row.selectors.js'
|
} from './send-to-row.selectors.js'
|
||||||
import { getToErrorObject } from './send-to-row.utils.js'
|
import { getToErrorObject } from './send-to-row.utils.js'
|
||||||
import {
|
import {
|
||||||
updateSendErrors,
|
|
||||||
updateSendTo,
|
updateSendTo,
|
||||||
} from '../../../../actions'
|
} from '../../../../actions'
|
||||||
import {
|
import {
|
||||||
openToDropdown,
|
updateSendErrors,
|
||||||
closeToDropdown,
|
openToDropdown,
|
||||||
|
closeToDropdown,
|
||||||
} from '../../../../ducks/send'
|
} from '../../../../ducks/send'
|
||||||
import SendToRow from './send-to-row.component'
|
import SendToRow from './send-to-row.component'
|
||||||
|
|
||||||
|
@ -0,0 +1,143 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import PropTypes from 'prop-types'
|
||||||
|
import PersistentForm from '../../../lib/persistent-form'
|
||||||
|
import {
|
||||||
|
getAmountErrorObject,
|
||||||
|
doesAmountErrorRequireUpdate,
|
||||||
|
} from './send.utils'
|
||||||
|
|
||||||
|
import PageContainer from '..//page-container/page-container.component'
|
||||||
|
import SendHeader from './send-header/send-header.container'
|
||||||
|
import SendContent from './send-content/send-content.component'
|
||||||
|
import SendFooter from './send-footer/send-footer.container'
|
||||||
|
|
||||||
|
export default class SendTransactionScreen extends PersistentForm {
|
||||||
|
|
||||||
|
static propTypes = {
|
||||||
|
amount: PropTypes.string,
|
||||||
|
amountConversionRate: PropTypes.oneOfType([
|
||||||
|
PropTypes.string,
|
||||||
|
PropTypes.number,
|
||||||
|
]),
|
||||||
|
conversionRate: PropTypes.number,
|
||||||
|
data: PropTypes.string,
|
||||||
|
editingTransactionId: PropTypes.string,
|
||||||
|
from: PropTypes.object,
|
||||||
|
gasLimit: PropTypes.string,
|
||||||
|
gasPrice: PropTypes.string,
|
||||||
|
gasTotal: PropTypes.string,
|
||||||
|
history: PropTypes.object,
|
||||||
|
network: PropTypes.string,
|
||||||
|
primaryCurrency: PropTypes.string,
|
||||||
|
selectedAddress: PropTypes.string,
|
||||||
|
selectedToken: PropTypes.object,
|
||||||
|
tokenBalance: PropTypes.string,
|
||||||
|
tokenContract: PropTypes.object,
|
||||||
|
updateAndSetGasTotal: PropTypes.func,
|
||||||
|
updateSendErrors: PropTypes.func,
|
||||||
|
updateSendTokenBalance: PropTypes.func,
|
||||||
|
};
|
||||||
|
|
||||||
|
updateGas () {
|
||||||
|
const {
|
||||||
|
data,
|
||||||
|
editingTransactionId,
|
||||||
|
gasLimit,
|
||||||
|
gasPrice,
|
||||||
|
selectedAddress,
|
||||||
|
selectedToken = {},
|
||||||
|
updateAndSetGasTotal,
|
||||||
|
} = this.props
|
||||||
|
|
||||||
|
updateAndSetGasTotal({
|
||||||
|
data,
|
||||||
|
editingTransactionId,
|
||||||
|
gasLimit,
|
||||||
|
gasPrice,
|
||||||
|
selectedAddress,
|
||||||
|
selectedToken,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidUpdate (prevProps) {
|
||||||
|
const {
|
||||||
|
amount,
|
||||||
|
amountConversionRate,
|
||||||
|
conversionRate,
|
||||||
|
from: { address, balance },
|
||||||
|
gasTotal,
|
||||||
|
network,
|
||||||
|
primaryCurrency,
|
||||||
|
selectedToken,
|
||||||
|
tokenBalance,
|
||||||
|
updateSendErrors,
|
||||||
|
updateSendTokenBalance,
|
||||||
|
tokenContract,
|
||||||
|
} = this.props
|
||||||
|
|
||||||
|
const {
|
||||||
|
from: { balance: prevBalance },
|
||||||
|
gasTotal: prevGasTotal,
|
||||||
|
tokenBalance: prevTokenBalance,
|
||||||
|
network: prevNetwork,
|
||||||
|
} = prevProps
|
||||||
|
|
||||||
|
const uninitialized = [prevBalance, prevGasTotal].every(n => n === null)
|
||||||
|
|
||||||
|
if (!uninitialized) {
|
||||||
|
const amountErrorRequiresUpdate = doesAmountErrorRequireUpdate({
|
||||||
|
balance,
|
||||||
|
gasTotal,
|
||||||
|
prevBalance,
|
||||||
|
prevGasTotal,
|
||||||
|
prevTokenBalance,
|
||||||
|
selectedToken,
|
||||||
|
tokenBalance,
|
||||||
|
})
|
||||||
|
|
||||||
|
if (amountErrorRequiresUpdate) {
|
||||||
|
const amountErrorObject = getAmountErrorObject({
|
||||||
|
amount,
|
||||||
|
amountConversionRate,
|
||||||
|
balance,
|
||||||
|
conversionRate,
|
||||||
|
gasTotal,
|
||||||
|
primaryCurrency,
|
||||||
|
selectedToken,
|
||||||
|
tokenBalance,
|
||||||
|
})
|
||||||
|
updateSendErrors(amountErrorObject)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (network !== prevNetwork && network !== 'loading') {
|
||||||
|
updateSendTokenBalance({
|
||||||
|
selectedToken,
|
||||||
|
tokenContract,
|
||||||
|
address,
|
||||||
|
})
|
||||||
|
this.updateGas()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillMount () {
|
||||||
|
this.updateGas()
|
||||||
|
}
|
||||||
|
|
||||||
|
render () {
|
||||||
|
const { history } = this.props
|
||||||
|
|
||||||
|
return (
|
||||||
|
<PageContainer>
|
||||||
|
<SendHeader/>
|
||||||
|
<SendContent/>
|
||||||
|
<SendFooter history={history}/>
|
||||||
|
</PageContainer>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
SendTransactionScreen.contextTypes = {
|
||||||
|
t: PropTypes.func,
|
||||||
|
}
|
@ -0,0 +1,88 @@
|
|||||||
|
import { connect } from 'react-redux'
|
||||||
|
import abi from 'ethereumjs-abi'
|
||||||
|
import SendEther from './send.component'
|
||||||
|
import { withRouter } from 'react-router-dom'
|
||||||
|
import { compose } from 'recompose'
|
||||||
|
import {
|
||||||
|
getAmountConversionRate,
|
||||||
|
getConversionRate,
|
||||||
|
getCurrentNetwork,
|
||||||
|
getGasLimit,
|
||||||
|
getGasPrice,
|
||||||
|
getGasTotal,
|
||||||
|
getPrimaryCurrency,
|
||||||
|
getSelectedAddress,
|
||||||
|
getSelectedToken,
|
||||||
|
getSelectedTokenContract,
|
||||||
|
getSelectedTokenToFiatRate,
|
||||||
|
getSendAmount,
|
||||||
|
getSendEditingTransactionId,
|
||||||
|
getSendFromObject,
|
||||||
|
getTokenBalance,
|
||||||
|
} from './send.selectors'
|
||||||
|
import {
|
||||||
|
updateSendTokenBalance,
|
||||||
|
updateGasTotal,
|
||||||
|
setGasTotal,
|
||||||
|
} from '../../actions'
|
||||||
|
import {
|
||||||
|
updateSendErrors,
|
||||||
|
} from '../../ducks/send'
|
||||||
|
import {
|
||||||
|
calcGasTotal,
|
||||||
|
generateTokenTransferData,
|
||||||
|
} from './send.utils.js'
|
||||||
|
|
||||||
|
module.exports = compose(
|
||||||
|
withRouter,
|
||||||
|
connect(mapStateToProps, mapDispatchToProps)
|
||||||
|
)(SendEther)
|
||||||
|
|
||||||
|
function mapStateToProps (state) {
|
||||||
|
const selectedAddress = getSelectedAddress(state)
|
||||||
|
const selectedToken = getSelectedToken(state)
|
||||||
|
|
||||||
|
return {
|
||||||
|
amount: getSendAmount(state),
|
||||||
|
amountConversionRate: getAmountConversionRate(state),
|
||||||
|
conversionRate: getConversionRate(state),
|
||||||
|
data: generateTokenTransferData(abi, selectedAddress, selectedToken),
|
||||||
|
editingTransactionId: getSendEditingTransactionId(state),
|
||||||
|
from: getSendFromObject(state),
|
||||||
|
gasLimit: getGasLimit(state),
|
||||||
|
gasPrice: getGasPrice(state),
|
||||||
|
gasTotal: getGasTotal(state),
|
||||||
|
network: getCurrentNetwork(state),
|
||||||
|
primaryCurrency: getPrimaryCurrency(state),
|
||||||
|
selectedAddress: getSelectedAddress(state),
|
||||||
|
selectedToken: getSelectedToken(state),
|
||||||
|
tokenBalance: getTokenBalance(state),
|
||||||
|
tokenContract: getSelectedTokenContract(state),
|
||||||
|
tokenToFiatRate: getSelectedTokenToFiatRate(state),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function mapDispatchToProps (dispatch) {
|
||||||
|
return {
|
||||||
|
updateAndSetGasTotal: ({
|
||||||
|
data,
|
||||||
|
editingTransactionId,
|
||||||
|
gasLimit,
|
||||||
|
gasPrice,
|
||||||
|
selectedAddress,
|
||||||
|
selectedToken,
|
||||||
|
}) => {
|
||||||
|
!editingTransactionId
|
||||||
|
? dispatch(updateGasTotal({ selectedAddress, selectedToken, data }))
|
||||||
|
: dispatch(setGasTotal(calcGasTotal(gasLimit, gasPrice)))
|
||||||
|
},
|
||||||
|
updateSendTokenBalance: ({ selectedToken, tokenContract, address }) => {
|
||||||
|
dispatch(updateSendTokenBalance({
|
||||||
|
selectedToken,
|
||||||
|
tokenContract,
|
||||||
|
address,
|
||||||
|
}))
|
||||||
|
},
|
||||||
|
updateSendErrors: newError => dispatch(updateSendErrors(newError)),
|
||||||
|
}
|
||||||
|
}
|
@ -8,6 +8,7 @@ const selectors = {
|
|||||||
accountsWithSendEtherInfoSelector,
|
accountsWithSendEtherInfoSelector,
|
||||||
autoAddToBetaUI,
|
autoAddToBetaUI,
|
||||||
getAddressBook,
|
getAddressBook,
|
||||||
|
getAmountConversionRate,
|
||||||
getConversionRate,
|
getConversionRate,
|
||||||
getConvertedCurrency,
|
getConvertedCurrency,
|
||||||
getCurrentAccountWithSendEtherInfo,
|
getCurrentAccountWithSendEtherInfo,
|
||||||
@ -18,6 +19,7 @@ const selectors = {
|
|||||||
getGasLimit,
|
getGasLimit,
|
||||||
getGasPrice,
|
getGasPrice,
|
||||||
getGasTotal,
|
getGasTotal,
|
||||||
|
getPrimaryCurrency,
|
||||||
getSelectedAccount,
|
getSelectedAccount,
|
||||||
getSelectedAddress,
|
getSelectedAddress,
|
||||||
getSelectedIdentity,
|
getSelectedIdentity,
|
||||||
@ -77,6 +79,12 @@ function getAddressBook (state) {
|
|||||||
return state.metamask.addressBook
|
return state.metamask.addressBook
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getAmountConversionRate (state) {
|
||||||
|
return getSelectedToken(state)
|
||||||
|
? getSelectedTokenToFiatRate(state)
|
||||||
|
: getConversionRate(state)
|
||||||
|
}
|
||||||
|
|
||||||
function getConversionRate (state) {
|
function getConversionRate (state) {
|
||||||
return state.metamask.conversionRate
|
return state.metamask.conversionRate
|
||||||
}
|
}
|
||||||
@ -121,6 +129,11 @@ function getGasTotal (state) {
|
|||||||
return state.metamask.send.gasTotal
|
return state.metamask.send.gasTotal
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getPrimaryCurrency (state) {
|
||||||
|
const selectedToken = getSelectedToken(state)
|
||||||
|
return selectedToken && selectedToken.symbol
|
||||||
|
}
|
||||||
|
|
||||||
function getSelectedAccount (state) {
|
function getSelectedAccount (state) {
|
||||||
const accounts = state.metamask.accounts
|
const accounts = state.metamask.accounts
|
||||||
const selectedAddress = getSelectedAddress(state)
|
const selectedAddress = getSelectedAddress(state)
|
||||||
@ -161,9 +174,8 @@ function getSelectedTokenExchangeRate (state) {
|
|||||||
const tokenExchangeRates = state.metamask.tokenExchangeRates
|
const tokenExchangeRates = state.metamask.tokenExchangeRates
|
||||||
const selectedToken = getSelectedToken(state) || {}
|
const selectedToken = getSelectedToken(state) || {}
|
||||||
const { symbol = '' } = selectedToken
|
const { symbol = '' } = selectedToken
|
||||||
|
|
||||||
const pair = `${symbol.toLowerCase()}_eth`
|
const pair = `${symbol.toLowerCase()}_eth`
|
||||||
const { rate: tokenExchangeRate = 0 } = tokenExchangeRates[pair] || {}
|
const { rate: tokenExchangeRate = 0 } = tokenExchangeRates && tokenExchangeRates[pair] || {}
|
||||||
|
|
||||||
return tokenExchangeRate
|
return tokenExchangeRate
|
||||||
}
|
}
|
||||||
@ -190,7 +202,7 @@ function getSendEditingTransactionId (state) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function getSendErrors (state) {
|
function getSendErrors (state) {
|
||||||
return state.metamask.send.errors
|
return state.send.errors
|
||||||
}
|
}
|
||||||
|
|
||||||
function getSendFrom (state) {
|
function getSendFrom (state) {
|
||||||
|
@ -7,8 +7,22 @@ const {
|
|||||||
const {
|
const {
|
||||||
calcTokenAmount,
|
calcTokenAmount,
|
||||||
} = require('../../token-util')
|
} = require('../../token-util')
|
||||||
|
const {
|
||||||
|
conversionGreaterThan,
|
||||||
|
} = require('../../conversion-util')
|
||||||
|
|
||||||
function getGasTotal (gasLimit, gasPrice) {
|
module.exports = {
|
||||||
|
calcGasTotal,
|
||||||
|
doesAmountErrorRequireUpdate,
|
||||||
|
generateTokenTransferData,
|
||||||
|
getAmountErrorObject,
|
||||||
|
getParamsForGasEstimate,
|
||||||
|
calcTokenBalance,
|
||||||
|
isBalanceSufficient,
|
||||||
|
isTokenBalanceSufficient,
|
||||||
|
}
|
||||||
|
|
||||||
|
function calcGasTotal (gasLimit, gasPrice) {
|
||||||
return multiplyCurrencies(gasLimit, gasPrice, {
|
return multiplyCurrencies(gasLimit, gasPrice, {
|
||||||
toNumericBase: 'hex',
|
toNumericBase: 'hex',
|
||||||
multiplicandBase: 16,
|
multiplicandBase: 16,
|
||||||
@ -71,8 +85,99 @@ function isTokenBalanceSufficient ({
|
|||||||
return tokenBalanceIsSufficient
|
return tokenBalanceIsSufficient
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = {
|
function getAmountErrorObject ({
|
||||||
getGasTotal,
|
amount,
|
||||||
isBalanceSufficient,
|
amountConversionRate,
|
||||||
isTokenBalanceSufficient,
|
balance,
|
||||||
|
conversionRate,
|
||||||
|
gasTotal,
|
||||||
|
primaryCurrency,
|
||||||
|
selectedToken,
|
||||||
|
tokenBalance,
|
||||||
|
}) {
|
||||||
|
let insufficientFunds = false
|
||||||
|
if (gasTotal && conversionRate) {
|
||||||
|
insufficientFunds = !isBalanceSufficient({
|
||||||
|
amount: selectedToken ? '0x0' : amount,
|
||||||
|
amountConversionRate,
|
||||||
|
balance,
|
||||||
|
conversionRate,
|
||||||
|
gasTotal,
|
||||||
|
primaryCurrency,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
let inSufficientTokens = false
|
||||||
|
if (selectedToken && tokenBalance !== null) {
|
||||||
|
const { decimals } = selectedToken
|
||||||
|
inSufficientTokens = !isTokenBalanceSufficient({
|
||||||
|
tokenBalance,
|
||||||
|
amount,
|
||||||
|
decimals,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const amountLessThanZero = conversionGreaterThan(
|
||||||
|
{ value: 0, fromNumericBase: 'dec' },
|
||||||
|
{ value: amount, fromNumericBase: 'hex' },
|
||||||
|
)
|
||||||
|
|
||||||
|
let amountError = null
|
||||||
|
|
||||||
|
if (insufficientFunds) {
|
||||||
|
amountError = 'insufficientFunds'
|
||||||
|
} else if (inSufficientTokens) {
|
||||||
|
amountError = 'insufficientTokens'
|
||||||
|
} else if (amountLessThanZero) {
|
||||||
|
amountError = 'negativeETH'
|
||||||
|
}
|
||||||
|
|
||||||
|
return { amount: amountError }
|
||||||
|
}
|
||||||
|
|
||||||
|
function getParamsForGasEstimate (selectedAddress, symbol, data) {
|
||||||
|
const estimatedGasParams = {
|
||||||
|
from: selectedAddress,
|
||||||
|
gas: '746a528800',
|
||||||
|
}
|
||||||
|
|
||||||
|
if (symbol) {
|
||||||
|
Object.assign(estimatedGasParams, { value: '0x0' })
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data) {
|
||||||
|
Object.assign(estimatedGasParams, { data })
|
||||||
|
}
|
||||||
|
|
||||||
|
return estimatedGasParams
|
||||||
|
}
|
||||||
|
|
||||||
|
function calcTokenBalance ({ selectedToken, usersToken }) {
|
||||||
|
const { decimals } = selectedToken || {}
|
||||||
|
return calcTokenAmount(usersToken.balance.toString(), decimals)
|
||||||
|
}
|
||||||
|
|
||||||
|
function doesAmountErrorRequireUpdate ({
|
||||||
|
balance,
|
||||||
|
gasTotal,
|
||||||
|
prevBalance,
|
||||||
|
prevGasTotal,
|
||||||
|
prevTokenBalance,
|
||||||
|
selectedToken,
|
||||||
|
tokenBalance,
|
||||||
|
}) {
|
||||||
|
const balanceHasChanged = balance !== prevBalance
|
||||||
|
const gasTotalHasChange = gasTotal !== prevGasTotal
|
||||||
|
const tokenBalanceHasChanged = selectedToken && tokenBalance !== prevTokenBalance
|
||||||
|
const amountErrorRequiresUpdate = balanceHasChanged || gasTotalHasChange || tokenBalanceHasChanged
|
||||||
|
|
||||||
|
return amountErrorRequiresUpdate
|
||||||
|
}
|
||||||
|
|
||||||
|
function generateTokenTransferData (abi, selectedAddress, selectedToken) {
|
||||||
|
if (!selectedToken) return
|
||||||
|
return Array.prototype.map.call(
|
||||||
|
abi.rawEncode(['address', 'uint256'], [selectedAddress, '0x0']),
|
||||||
|
x => ('00' + x.toString(16)).slice(-2)
|
||||||
|
).join('')
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@ const OPEN_FROM_DROPDOWN = 'metamask/send/OPEN_FROM_DROPDOWN'
|
|||||||
const CLOSE_FROM_DROPDOWN = 'metamask/send/CLOSE_FROM_DROPDOWN'
|
const CLOSE_FROM_DROPDOWN = 'metamask/send/CLOSE_FROM_DROPDOWN'
|
||||||
const OPEN_TO_DROPDOWN = 'metamask/send/OPEN_TO_DROPDOWN'
|
const OPEN_TO_DROPDOWN = 'metamask/send/OPEN_TO_DROPDOWN'
|
||||||
const CLOSE_TO_DROPDOWN = 'metamask/send/CLOSE_TO_DROPDOWN'
|
const CLOSE_TO_DROPDOWN = 'metamask/send/CLOSE_TO_DROPDOWN'
|
||||||
|
const UPDATE_SEND_ERRORS = 'metamask/send/UPDATE_SEND_ERRORS'
|
||||||
|
|
||||||
// TODO: determine if this approach to initState is consistent with conventional ducks pattern
|
// TODO: determine if this approach to initState is consistent with conventional ducks pattern
|
||||||
const initState = {
|
const initState = {
|
||||||
@ -32,6 +33,13 @@ export default function reducer ({ send: sendState = initState }, action = {}) {
|
|||||||
return extend(sendState, {
|
return extend(sendState, {
|
||||||
toDropdownOpen: false,
|
toDropdownOpen: false,
|
||||||
})
|
})
|
||||||
|
case UPDATE_SEND_ERRORS:
|
||||||
|
return extend(sendState, {
|
||||||
|
errors: {
|
||||||
|
...sendState.errors,
|
||||||
|
...action.value,
|
||||||
|
},
|
||||||
|
})
|
||||||
default:
|
default:
|
||||||
return sendState
|
return sendState
|
||||||
}
|
}
|
||||||
@ -53,3 +61,10 @@ export function openToDropdown () {
|
|||||||
export function closeToDropdown () {
|
export function closeToDropdown () {
|
||||||
return { type: CLOSE_TO_DROPDOWN }
|
return { type: CLOSE_TO_DROPDOWN }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function updateSendErrors (errorObject) {
|
||||||
|
return {
|
||||||
|
type: UPDATE_SEND_ERRORS,
|
||||||
|
value: errorObject,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -254,17 +254,6 @@ function reduceMetamask (state, action) {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
case actions.UPDATE_SEND_ERRORS:
|
|
||||||
return extend(metamaskState, {
|
|
||||||
send: {
|
|
||||||
...metamaskState.send,
|
|
||||||
errors: {
|
|
||||||
...metamaskState.send.errors,
|
|
||||||
...action.value,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
||||||
case actions.UPDATE_MAX_MODE:
|
case actions.UPDATE_MAX_MODE:
|
||||||
return extend(metamaskState, {
|
return extend(metamaskState, {
|
||||||
send: {
|
send: {
|
||||||
|
@ -84,7 +84,7 @@ SendTransactionScreen.prototype.updateGas = function () {
|
|||||||
estimateGas,
|
estimateGas,
|
||||||
selectedAddress,
|
selectedAddress,
|
||||||
data,
|
data,
|
||||||
updateGasTotal,
|
setGasTotal,
|
||||||
from,
|
from,
|
||||||
tokenContract,
|
tokenContract,
|
||||||
editingTransactionId,
|
editingTransactionId,
|
||||||
@ -110,7 +110,7 @@ SendTransactionScreen.prototype.updateGas = function () {
|
|||||||
])
|
])
|
||||||
.then(([gasPrice, gas]) => {
|
.then(([gasPrice, gas]) => {
|
||||||
const newGasTotal = getGasTotal(gas, gasPrice)
|
const newGasTotal = getGasTotal(gas, gasPrice)
|
||||||
updateGasTotal(newGasTotal)
|
setGasTotal(newGasTotal)
|
||||||
this.setState({ gasLoadingError: false })
|
this.setState({ gasLoadingError: false })
|
||||||
})
|
})
|
||||||
.catch(err => {
|
.catch(err => {
|
||||||
@ -118,7 +118,7 @@ SendTransactionScreen.prototype.updateGas = function () {
|
|||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
const newGasTotal = getGasTotal(gasLimit, gasPrice)
|
const newGasTotal = getGasTotal(gasLimit, gasPrice)
|
||||||
updateGasTotal(newGasTotal)
|
setGasTotal(newGasTotal)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user