aboutsummaryrefslogtreecommitdiffstats
path: root/ui
diff options
context:
space:
mode:
authorAlexander Tseung <alextsg@gmail.com>2018-04-03 16:03:31 +0800
committerAlexander Tseung <alextsg@gmail.com>2018-04-03 16:03:31 +0800
commit35875863d2feafc1f653e17e0f58efc2f18ddc46 (patch)
tree5d40581a08201b3f37c7b31fe2aab4675d827f6b /ui
parent516c1869b0f366a42282a66e14185ce630f883dd (diff)
parentc14ec4191741c444dcf5b7c3e177c17a10374c16 (diff)
downloadtangerine-wallet-browser-35875863d2feafc1f653e17e0f58efc2f18ddc46.tar.gz
tangerine-wallet-browser-35875863d2feafc1f653e17e0f58efc2f18ddc46.tar.zst
tangerine-wallet-browser-35875863d2feafc1f653e17e0f58efc2f18ddc46.zip
Fix merge conflicts. Modify send workflow
Diffstat (limited to 'ui')
-rw-r--r--ui/app/actions.js5
-rw-r--r--ui/app/app.js5
-rw-r--r--ui/app/components/customize-gas-modal/index.js3
-rw-r--r--ui/app/components/dropdowns/network-dropdown.js8
-rw-r--r--ui/app/components/identicon.js5
-rw-r--r--ui/app/components/pages/home.js29
-rw-r--r--ui/app/components/pending-tx/confirm-send-ether.js110
-rw-r--r--ui/app/components/pending-tx/confirm-send-token.js107
-rw-r--r--ui/app/components/send/send-utils.js12
-rw-r--r--ui/app/components/tx-list-item.js21
-rw-r--r--ui/app/components/tx-list.js5
-rw-r--r--ui/app/conf-tx.js25
-rw-r--r--ui/app/css/itcss/components/confirm.scss36
-rw-r--r--ui/app/send-v2.js17
-rw-r--r--ui/index.js10
15 files changed, 331 insertions, 67 deletions
diff --git a/ui/app/actions.js b/ui/app/actions.js
index 08df31e1f..0748a5bea 100644
--- a/ui/app/actions.js
+++ b/ui/app/actions.js
@@ -1374,7 +1374,7 @@ function retryTransaction (txId) {
function setProviderType (type) {
return (dispatch) => {
- log.debug(`background.setProviderType`)
+ log.debug(`background.setProviderType`, type)
background.setProviderType(type, (err, result) => {
if (err) {
log.error(err)
@@ -1395,13 +1395,14 @@ function updateProviderType (type) {
}
function setRpcTarget (newRpc) {
- log.debug(`background.setRpcTarget: ${newRpc}`)
return (dispatch) => {
+ log.debug(`background.setRpcTarget: ${newRpc}`)
background.setCustomRpc(newRpc, (err, result) => {
if (err) {
log.error(err)
return dispatch(self.displayWarning('Had a problem changing networks!'))
}
+ dispatch(actions.setSelectedToken())
})
}
}
diff --git a/ui/app/app.js b/ui/app/app.js
index 52e5e00a8..82871d970 100644
--- a/ui/app/app.js
+++ b/ui/app/app.js
@@ -77,7 +77,6 @@ class App extends Component {
component: RevealSeedPage,
mascaraComponent: MascaraSeedScreen,
}),
- // h(Initialized, { path: CONFIRM_SEED_ROUTE, exact, component: MascaraConfirmSeedScreen }),
h(Initialized, { path: UNLOCK_ROUTE, exact, component: UnlockPage }),
h(Initialized, { path: SETTINGS_ROUTE, component: Settings }),
h(Initialized, { path: RESTORE_VAULT_ROUTE, exact, component: RestoreVaultPage }),
@@ -214,7 +213,6 @@ class App extends Component {
networkDropdownOpen,
showNetworkDropdown,
hideNetworkDropdown,
- currentView,
isInitialized,
welcomeScreenSeen,
isPopup,
@@ -276,7 +274,7 @@ class App extends Component {
h(NetworkIndicator, {
network,
provider,
- disabled: currentView.name === 'confTx',
+ disabled: this.props.location.pathname === CONFIRM_TRANSACTION_ROUTE,
onClick: (event) => {
event.preventDefault()
event.stopPropagation()
@@ -395,6 +393,7 @@ App.propTypes = {
showNetworkDropdown: PropTypes.func,
hideNetworkDropdown: PropTypes.func,
history: PropTypes.object,
+ location: PropTypes.object,
dispatch: PropTypes.func,
toggleAccountMenu: PropTypes.func,
selectedAddress: PropTypes.string,
diff --git a/ui/app/components/customize-gas-modal/index.js b/ui/app/components/customize-gas-modal/index.js
index 825366cb2..4c693d1c3 100644
--- a/ui/app/components/customize-gas-modal/index.js
+++ b/ui/app/components/customize-gas-modal/index.js
@@ -65,6 +65,7 @@ function mapDispatchToProps (dispatch) {
updateGasLimit: newGasLimit => dispatch(actions.updateGasLimit(newGasLimit)),
updateGasTotal: newGasTotal => dispatch(actions.updateGasTotal(newGasTotal)),
updateSendAmount: newAmount => dispatch(actions.updateSendAmount(newAmount)),
+ updateSendErrors: error => dispatch(actions.updateSendErrors(error)),
}
}
@@ -112,6 +113,7 @@ CustomizeGasModal.prototype.save = function (gasPrice, gasLimit, gasTotal) {
selectedToken,
balance,
updateSendAmount,
+ updateSendErrors,
} = this.props
if (maxModeOn && !selectedToken) {
@@ -126,6 +128,7 @@ CustomizeGasModal.prototype.save = function (gasPrice, gasLimit, gasTotal) {
updateGasPrice(ethUtil.addHexPrefix(gasPrice))
updateGasLimit(ethUtil.addHexPrefix(gasLimit))
updateGasTotal(ethUtil.addHexPrefix(gasTotal))
+ updateSendErrors({ insufficientFunds: false })
hideModal()
}
diff --git a/ui/app/components/dropdowns/network-dropdown.js b/ui/app/components/dropdowns/network-dropdown.js
index 94e5d967b..9e47f38ef 100644
--- a/ui/app/components/dropdowns/network-dropdown.js
+++ b/ui/app/components/dropdowns/network-dropdown.js
@@ -203,18 +203,18 @@ NetworkDropdown.prototype.render = function () {
{
key: 'default',
closeMenu: () => this.props.hideNetworkDropdown(),
- onClick: () => props.setRpcTarget('http://localhost:8545'),
+ onClick: () => props.setProviderType('localhost'),
style: dropdownMenuItemStyle,
},
[
- activeNetwork === 'http://localhost:8545' ? h('i.fa.fa-check') : h('.network-check__transparent', '✓'),
+ providerType === 'localhost' ? h('i.fa.fa-check') : h('.network-check__transparent', '✓'),
h(NetworkDropdownIcon, {
- isSelected: activeNetwork === 'http://localhost:8545',
+ isSelected: providerType === 'localhost',
innerBorder: '1px solid #9b9b9b',
}),
h('span.network-name-item', {
style: {
- color: activeNetwork === 'http://localhost:8545' ? '#ffffff' : '#9b9b9b',
+ color: providerType === 'localhost' ? '#ffffff' : '#9b9b9b',
},
}, this.context.t('localhost')),
]
diff --git a/ui/app/components/identicon.js b/ui/app/components/identicon.js
index 7cc5a4de0..dce9b0449 100644
--- a/ui/app/components/identicon.js
+++ b/ui/app/components/identicon.js
@@ -105,9 +105,8 @@ IdenticonComponent.prototype.componentDidUpdate = function () {
function _generateBlockie (container, address, diameter) {
const img = new Image()
img.src = toDataUrl(address)
- const dia = !diameter || diameter < 50 ? 50 : diameter
- img.height = dia * 1.25
- img.width = dia * 1.25
+ img.height = diameter
+ img.width = diameter
container.appendChild(img)
}
diff --git a/ui/app/components/pages/home.js b/ui/app/components/pages/home.js
index ffe35a2a8..177d9b4e7 100644
--- a/ui/app/components/pages/home.js
+++ b/ui/app/components/pages/home.js
@@ -27,21 +27,6 @@ const {
} = require('../../routes')
class Home extends Component {
- componentDidMount () {
- const {
- unapprovedTxs = {},
- unapprovedMsgCount = 0,
- unapprovedPersonalMsgCount = 0,
- unapprovedTypedMessagesCount = 0,
- } = this.props
-
- // unapprovedTxs and unapproved messages
- if (Object.keys(unapprovedTxs).length ||
- unapprovedTypedMessagesCount + unapprovedMsgCount + unapprovedPersonalMsgCount > 0) {
- this.props.history.push(CONFIRM_TRANSACTION_ROUTE)
- }
- }
-
render () {
log.debug('rendering primary')
const {
@@ -51,6 +36,10 @@ class Home extends Component {
currentView,
activeAddress,
seedWords,
+ unapprovedTxs = {},
+ unapprovedMsgCount = 0,
+ unapprovedPersonalMsgCount = 0,
+ unapprovedTypedMessagesCount = 0,
} = this.props
// notices
@@ -81,6 +70,16 @@ class Home extends Component {
})
}
+ // unapprovedTxs and unapproved messages
+ if (Object.keys(unapprovedTxs).length ||
+ unapprovedTypedMessagesCount + unapprovedMsgCount + unapprovedPersonalMsgCount > 0) {
+ return h(Redirect, {
+ to: {
+ pathname: CONFIRM_TRANSACTION_ROUTE,
+ },
+ })
+ }
+
// if (!props.noActiveNotices) {
// log.debug('rendering notice screen for unread notices.')
// return h(NoticeScreen, {
diff --git a/ui/app/components/pending-tx/confirm-send-ether.js b/ui/app/components/pending-tx/confirm-send-ether.js
index 3576d4405..4e2f763fc 100644
--- a/ui/app/components/pending-tx/confirm-send-ether.js
+++ b/ui/app/components/pending-tx/confirm-send-ether.js
@@ -10,11 +10,16 @@ const clone = require('clone')
const ethUtil = require('ethereumjs-util')
const BN = ethUtil.BN
const hexToBn = require('../../../../app/scripts/lib/hex-to-bn')
+const classnames = require('classnames')
const {
conversionUtil,
addCurrencies,
multiplyCurrencies,
} = require('../../conversion-util')
+const {
+ getGasTotal,
+ isBalanceSufficient,
+} = require('../send/send-utils')
const GasFeeDisplay = require('../send/gas-fee-display-v2')
const SenderToRecipient = require('../sender-to-recipient')
const NetworkDisplay = require('../network-display')
@@ -41,12 +46,14 @@ function mapStateToProps (state) {
} = state.metamask
const accounts = state.metamask.accounts
const selectedAddress = state.metamask.selectedAddress || Object.keys(accounts)[0]
+ const { balance } = accounts[selectedAddress]
return {
conversionRate,
identities,
selectedAddress,
currentCurrency,
send,
+ balance,
}
}
@@ -96,6 +103,7 @@ function mapDispatchToProps (dispatch) {
}))
dispatch(actions.showModal({ name: 'CUSTOMIZE_GAS' }))
},
+ updateSendErrors: error => dispatch(actions.updateSendErrors(error)),
}
}
@@ -106,6 +114,52 @@ function ConfirmSendEther () {
this.onSubmit = this.onSubmit.bind(this)
}
+ConfirmSendEther.prototype.updateComponentSendErrors = function (prevProps) {
+ const {
+ balance: oldBalance,
+ conversionRate: oldConversionRate,
+ } = prevProps
+ const {
+ updateSendErrors,
+ balance,
+ conversionRate,
+ send: {
+ errors: {
+ simulationFails,
+ },
+ },
+ } = this.props
+ const txMeta = this.gatherTxMeta()
+
+ const shouldUpdateBalanceSendErrors = balance && [
+ balance !== oldBalance,
+ conversionRate !== oldConversionRate,
+ ].some(x => Boolean(x))
+
+ if (shouldUpdateBalanceSendErrors) {
+ const balanceIsSufficient = this.isBalanceSufficient(txMeta)
+ updateSendErrors({
+ insufficientFunds: balanceIsSufficient ? false : this.context.t('insufficientFunds'),
+ })
+ }
+
+ const shouldUpdateSimulationSendError = Boolean(txMeta.simulationFails) !== Boolean(simulationFails)
+
+ if (shouldUpdateSimulationSendError) {
+ updateSendErrors({
+ simulationFails: !txMeta.simulationFails ? false : this.context.t('transactionError'),
+ })
+ }
+}
+
+ConfirmSendEther.prototype.componentWillMount = function () {
+ this.updateComponentSendErrors({})
+}
+
+ConfirmSendEther.prototype.componentDidUpdate = function (prevProps) {
+ this.updateComponentSendErrors(prevProps)
+}
+
ConfirmSendEther.prototype.getAmount = function () {
const { conversionRate, currentCurrency } = this.props
const txMeta = this.gatherTxMeta()
@@ -234,7 +288,12 @@ ConfirmSendEther.prototype.render = function () {
conversionRate,
currentCurrency: convertedCurrency,
showCustomizeGasModal,
- send: { gasTotal, gasLimit: sendGasLimit, gasPrice: sendGasPrice },
+ send: {
+ gasTotal,
+ gasLimit: sendGasLimit,
+ gasPrice: sendGasPrice,
+ errors,
+ },
} = this.props
const txMeta = this.gatherTxMeta()
const txParams = txMeta.txParams || {}
@@ -342,7 +401,12 @@ ConfirmSendEther.prototype.render = function () {
]),
h('section.flex-row.flex-center.confirm-screen-row.confirm-screen-total-box ', [
- h('div.confirm-screen-section-column', [
+ h('div', {
+ className: classnames({
+ 'confirm-screen-section-column--with-error': errors['insufficientFunds'],
+ 'confirm-screen-section-column': !errors['insufficientFunds'],
+ }),
+ }, [
h('span.confirm-screen-label', [ this.context.t('total') + ' ' ]),
h('div.confirm-screen-total-box__subtitle', [ this.context.t('amountPlusGas') ]),
]),
@@ -351,6 +415,8 @@ ConfirmSendEther.prototype.render = function () {
h('div.confirm-screen-row-info', `${totalInFIAT} ${currentCurrency.toUpperCase()}`),
h('div.confirm-screen-row-detail', `${totalInETH} ETH`),
]),
+
+ this.renderErrorMessage('insufficientFunds'),
]),
]),
@@ -436,8 +502,10 @@ ConfirmSendEther.prototype.render = function () {
]),
h('form#pending-tx-form', {
+ className: 'confirm-screen-form',
onSubmit: this.onSubmit,
}, [
+ this.renderErrorMessage('simulationFails'),
h('.page-container__footer', [
// Cancel Button
h('button.btn-cancel.page-container__footer-button.allcaps', {
@@ -455,16 +523,28 @@ ConfirmSendEther.prototype.render = function () {
)
}
+ConfirmSendEther.prototype.renderErrorMessage = function (message) {
+ const { send: { errors } } = this.props
+
+ return errors[message]
+ ? h('div.confirm-screen-error', [ errors[message] ])
+ : null
+}
+
ConfirmSendEther.prototype.onSubmit = function (event) {
event.preventDefault()
+ const { updateSendErrors } = this.props
const txMeta = this.gatherTxMeta()
const valid = this.checkValidity()
+ const balanceIsSufficient = this.isBalanceSufficient(txMeta)
this.setState({ valid, submitting: true })
- if (valid && this.verifyGasParams()) {
+ if (valid && this.verifyGasParams() && balanceIsSufficient) {
this.props.sendTransaction(txMeta, event)
+ } else if (!balanceIsSufficient) {
+ updateSendErrors({ insufficientFunds: this.context.t('insufficientFunds') })
} else {
- this.props.dispatch(actions.displayWarning(this.context.t('invalidGasParams')))
+ updateSendErrors({ invalidGasParams: this.context.t('invalidGasParams') })
this.setState({ submitting: false })
}
}
@@ -477,6 +557,28 @@ ConfirmSendEther.prototype.cancel = function (event, txMeta) {
.then(() => this.props.history.push(DEFAULT_ROUTE))
}
+ConfirmSendEther.prototype.isBalanceSufficient = function (txMeta) {
+ const {
+ balance,
+ conversionRate,
+ } = this.props
+ const {
+ txParams: {
+ gas,
+ gasPrice,
+ value: amount,
+ },
+ } = txMeta
+ const gasTotal = getGasTotal(gas, gasPrice)
+
+ return isBalanceSufficient({
+ amount,
+ gasTotal,
+ balance,
+ conversionRate,
+ })
+}
+
ConfirmSendEther.prototype.checkValidity = function () {
const form = this.getFormEl()
const valid = form.checkValidity()
diff --git a/ui/app/components/pending-tx/confirm-send-token.js b/ui/app/components/pending-tx/confirm-send-token.js
index 9f978b848..5e6d0747d 100644
--- a/ui/app/components/pending-tx/confirm-send-token.js
+++ b/ui/app/components/pending-tx/confirm-send-token.js
@@ -20,8 +20,13 @@ const {
addCurrencies,
} = require('../../conversion-util')
const {
+ getGasTotal,
+ isBalanceSufficient,
+} = require('../send/send-utils')
+const {
calcTokenAmount,
} = require('../../token-util')
+const classnames = require('classnames')
const { MIN_GAS_PRICE_HEX } = require('../send/send-constants')
@@ -52,9 +57,10 @@ function mapStateToProps (state, ownProps) {
identities,
currentCurrency,
} = state.metamask
+ const accounts = state.metamask.accounts
const selectedAddress = getSelectedAddress(state)
const tokenExchangeRate = getTokenExchangeRate(state, symbol)
-
+ const { balance } = accounts[selectedAddress]
return {
conversionRate,
identities,
@@ -64,6 +70,7 @@ function mapStateToProps (state, ownProps) {
currentCurrency: currentCurrency.toUpperCase(),
send: state.metamask.send,
tokenContract: getSelectedTokenContract(state),
+ balance,
}
}
@@ -135,6 +142,7 @@ function mapDispatchToProps (dispatch, ownProps) {
}))
dispatch(actions.showModal({ name: 'CUSTOMIZE_GAS' }))
},
+ updateSendErrors: error => dispatch(actions.updateSendErrors(error)),
}
}
@@ -151,6 +159,44 @@ ConfirmSendToken.prototype.editTransaction = function (txMeta) {
history.push(SEND_ROUTE)
}
+ConfirmSendToken.prototype.updateComponentSendErrors = function (prevProps) {
+ const {
+ balance: oldBalance,
+ conversionRate: oldConversionRate,
+ } = prevProps
+ const {
+ updateSendErrors,
+ balance,
+ conversionRate,
+ send: {
+ errors: {
+ simulationFails,
+ },
+ },
+ } = this.props
+ const txMeta = this.gatherTxMeta()
+
+ const shouldUpdateBalanceSendErrors = balance && [
+ balance !== oldBalance,
+ conversionRate !== oldConversionRate,
+ ].some(x => Boolean(x))
+
+ if (shouldUpdateBalanceSendErrors) {
+ const balanceIsSufficient = this.isBalanceSufficient(txMeta)
+ updateSendErrors({
+ insufficientFunds: balanceIsSufficient ? false : this.context.t('insufficientFunds'),
+ })
+ }
+
+ const shouldUpdateSimulationSendError = Boolean(txMeta.simulationFails) !== Boolean(simulationFails)
+
+ if (shouldUpdateSimulationSendError) {
+ updateSendErrors({
+ simulationFails: !txMeta.simulationFails ? false : this.context.t('transactionError'),
+ })
+ }
+}
+
ConfirmSendToken.prototype.componentWillMount = function () {
const { tokenContract, selectedAddress } = this.props
tokenContract && tokenContract
@@ -158,6 +204,11 @@ ConfirmSendToken.prototype.componentWillMount = function () {
.then(usersToken => {
})
this.props.updateTokenExchangeRate()
+ this.updateComponentSendErrors({})
+}
+
+ConfirmSendToken.prototype.componentDidUpdate = function (prevProps) {
+ this.updateComponentSendErrors(prevProps)
}
ConfirmSendToken.prototype.getAmount = function () {
@@ -318,7 +369,7 @@ ConfirmSendToken.prototype.renderGasFee = function () {
}
ConfirmSendToken.prototype.renderTotalPlusGas = function () {
- const { token: { symbol }, currentCurrency } = this.props
+ const { token: { symbol }, currentCurrency, send: { errors } } = this.props
const { fiat: fiatAmount, token: tokenAmount } = this.getAmount()
const { fiat: fiatGas, token: tokenGas } = this.getGasFee()
@@ -338,7 +389,12 @@ ConfirmSendToken.prototype.renderTotalPlusGas = function () {
)
: (
h('section.flex-row.flex-center.confirm-screen-row.confirm-screen-total-box ', [
- h('div.confirm-screen-section-column', [
+ h('div', {
+ className: classnames({
+ 'confirm-screen-section-column--with-error': errors['insufficientFunds'],
+ 'confirm-screen-section-column': !errors['insufficientFunds'],
+ }),
+ }, [
h('span.confirm-screen-label', [ this.context.t('total') + ' ' ]),
h('div.confirm-screen-total-box__subtitle', [ this.context.t('amountPlusGas') ]),
]),
@@ -347,12 +403,21 @@ ConfirmSendToken.prototype.renderTotalPlusGas = function () {
h('div.confirm-screen-row-info', `${tokenAmount} ${symbol}`),
h('div.confirm-screen-row-detail', `+ ${fiatGas} ${currentCurrency} ${this.context.t('gas')}`),
]),
+
+ this.renderErrorMessage('insufficientFunds'),
])
)
}
+ConfirmSendToken.prototype.renderErrorMessage = function (message) {
+ const { send: { errors } } = this.props
+
+ return errors[message]
+ ? h('div.confirm-screen-error', [ errors[message] ])
+ : null
+}
+
ConfirmSendToken.prototype.render = function () {
- const { editTransaction } = this.props
const txMeta = this.gatherTxMeta()
const {
from: {
@@ -379,7 +444,7 @@ ConfirmSendToken.prototype.render = function () {
h('div.page-container', [
h('div.page-container__header', [
!txMeta.lastGasPrice && h('button.confirm-screen-back-button', {
- onClick: () => editTransaction(txMeta),
+ onClick: () => this.editTransaction(txMeta),
}, this.context.t('edit')),
h('div.page-container__title', title),
h('div.page-container__subtitle', subtitle),
@@ -448,8 +513,10 @@ ConfirmSendToken.prototype.render = function () {
]),
h('form#pending-tx-form', {
+ className: 'confirm-screen-form',
onSubmit: this.onSubmit,
}, [
+ this.renderErrorMessage('simulationFails'),
h('.page-container__footer', [
// Cancel Button
h('button.btn-cancel.page-container__footer-button.allcaps', {
@@ -467,18 +534,44 @@ ConfirmSendToken.prototype.render = function () {
ConfirmSendToken.prototype.onSubmit = function (event) {
event.preventDefault()
+ const { updateSendErrors } = this.props
const txMeta = this.gatherTxMeta()
const valid = this.checkValidity()
+ const balanceIsSufficient = this.isBalanceSufficient(txMeta)
this.setState({ valid, submitting: true })
- if (valid && this.verifyGasParams()) {
+ if (valid && this.verifyGasParams() && balanceIsSufficient) {
this.props.sendTransaction(txMeta, event)
+ } else if (!balanceIsSufficient) {
+ updateSendErrors({ insufficientFunds: this.context.t('insufficientFunds') })
} else {
- this.props.dispatch(actions.displayWarning(this.context.t('invalidGasParams')))
+ updateSendErrors({ invalidGasParams: this.context.t('invalidGasParams') })
this.setState({ submitting: false })
}
}
+ConfirmSendToken.prototype.isBalanceSufficient = function (txMeta) {
+ const {
+ balance,
+ conversionRate,
+ } = this.props
+ const {
+ txParams: {
+ gas,
+ gasPrice,
+ },
+ } = txMeta
+ const gasTotal = getGasTotal(gas, gasPrice)
+
+ return isBalanceSufficient({
+ amount: '0',
+ gasTotal,
+ balance,
+ conversionRate,
+ })
+}
+
+
ConfirmSendToken.prototype.cancel = function (event, txMeta) {
event.preventDefault()
const { cancelTransaction } = this.props
diff --git a/ui/app/components/send/send-utils.js b/ui/app/components/send/send-utils.js
index d8211930d..71bfb2668 100644
--- a/ui/app/components/send/send-utils.js
+++ b/ui/app/components/send/send-utils.js
@@ -2,6 +2,7 @@ const {
addCurrencies,
conversionUtil,
conversionGTE,
+ multiplyCurrencies,
} = require('../../conversion-util')
const {
calcTokenAmount,
@@ -31,7 +32,7 @@ function isBalanceSufficient ({
{
value: totalAmount,
fromNumericBase: 'hex',
- conversionRate: amountConversionRate,
+ conversionRate: amountConversionRate || conversionRate,
fromCurrency: primaryCurrency,
},
)
@@ -62,7 +63,16 @@ function isTokenBalanceSufficient ({
return tokenBalanceIsSufficient
}
+function getGasTotal (gasLimit, gasPrice) {
+ return multiplyCurrencies(gasLimit, gasPrice, {
+ toNumericBase: 'hex',
+ multiplicandBase: 16,
+ multiplierBase: 16,
+ })
+}
+
module.exports = {
+ getGasTotal,
isBalanceSufficient,
isTokenBalanceSufficient,
}
diff --git a/ui/app/components/tx-list-item.js b/ui/app/components/tx-list-item.js
index 622664786..42c008798 100644
--- a/ui/app/components/tx-list-item.js
+++ b/ui/app/components/tx-list-item.js
@@ -68,20 +68,24 @@ TxListItem.prototype.getAddressText = function () {
const {
address,
txParams = {},
+ isMsg,
} = this.props
const decodedData = txParams.data && abiDecoder.decodeMethod(txParams.data)
const { name: txDataName, params = [] } = decodedData || {}
const { value } = params[0] || {}
- switch (txDataName) {
- case 'transfer':
- return `${value.slice(0, 10)}...${value.slice(-4)}`
- default:
- return address
- ? `${address.slice(0, 10)}...${address.slice(-4)}`
- : this.context.t('contractDeployment')
+ let addressText
+ if (txDataName === 'transfer' || address) {
+ const addressToRender = txDataName === 'transfer' ? value : address
+ addressText = `${addressToRender.slice(0, 10)}...${addressToRender.slice(-4)}`
+ } else if (isMsg) {
+ addressText = this.context.t('sigRequest')
+ } else {
+ addressText = this.context.t('contractDeployment')
}
+
+ return addressText
}
TxListItem.prototype.getSendEtherTotal = function () {
@@ -191,6 +195,9 @@ TxListItem.prototype.showRetryButton = function () {
transactionId,
txParams,
} = this.props
+ if (!txParams) {
+ return false
+ }
const currentNonce = txParams.nonce
const currentNonceTxs = selectedAddressTxList.filter(tx => tx.txParams.nonce === currentNonce)
const currentNonceSubmittedTxs = currentNonceTxs.filter(tx => tx.status === 'submitted')
diff --git a/ui/app/components/tx-list.js b/ui/app/components/tx-list.js
index 70643aa36..554febcff 100644
--- a/ui/app/components/tx-list.js
+++ b/ui/app/components/tx-list.js
@@ -82,9 +82,9 @@ TxList.prototype.renderTransactionListItem = function (transaction, conversionRa
const props = {
dateString: formatDate(transaction.time),
- address: transaction.txParams.to,
+ address: transaction.txParams && transaction.txParams.to,
transactionStatus: transaction.status,
- transactionAmount: transaction.txParams.value,
+ transactionAmount: transaction.txParams && transaction.txParams.value,
transactionId: transaction.id,
transactionHash: transaction.hash,
transactionNetworkId: transaction.metamaskNetworkId,
@@ -106,6 +106,7 @@ TxList.prototype.renderTransactionListItem = function (transaction, conversionRa
const opts = {
key: transactionId || transactionHash,
txParams: transaction.txParams,
+ isMsg: Boolean(transaction.msgParams),
transactionStatus,
transactionId,
dateString,
diff --git a/ui/app/conf-tx.js b/ui/app/conf-tx.js
index 3134cf331..886d98be7 100644
--- a/ui/app/conf-tx.js
+++ b/ui/app/conf-tx.js
@@ -55,11 +55,25 @@ function ConfirmTxScreen () {
Component.call(this)
}
+ConfirmTxScreen.prototype.componentDidMount = function () {
+ const {
+ unapprovedTxs = {},
+ network,
+ send,
+ } = this.props
+ const unconfTxList = txHelper(unapprovedTxs, {}, {}, {}, network)
+
+ if (unconfTxList.length === 0 && !send.to) {
+ this.props.history.push(DEFAULT_ROUTE)
+ }
+}
+
ConfirmTxScreen.prototype.componentDidUpdate = function (prevProps) {
const {
- unapprovedTxs,
+ unapprovedTxs = {},
network,
selectedAddressTxList,
+ send,
} = this.props
const { index: prevIndex, unapprovedTxs: prevUnapprovedTxs } = prevProps
const prevUnconfTxList = txHelper(prevUnapprovedTxs, {}, {}, {}, network)
@@ -67,7 +81,7 @@ ConfirmTxScreen.prototype.componentDidUpdate = function (prevProps) {
const prevTx = selectedAddressTxList.find(({ id }) => id === prevTxData.id) || {}
const unconfTxList = txHelper(unapprovedTxs, {}, {}, {}, network)
- if (prevTx.status === 'dropped' && unconfTxList.length === 0) {
+ if (unconfTxList.length === 0 && (prevTx.status === 'dropped' || !send.to)) {
this.props.history.push(DEFAULT_ROUTE)
}
}
@@ -109,13 +123,6 @@ ConfirmTxScreen.prototype.render = function () {
*/
log.info(`rendering a combined ${unconfTxList.length} unconf msg & txs`)
- if (unconfTxList.length === 0) {
- return h(Redirect, {
- to: {
- pathname: DEFAULT_ROUTE,
- },
- })
- }
return currentTxView({
// Properties
diff --git a/ui/app/css/itcss/components/confirm.scss b/ui/app/css/itcss/components/confirm.scss
index abe138f54..47762e8de 100644
--- a/ui/app/css/itcss/components/confirm.scss
+++ b/ui/app/css/itcss/components/confirm.scss
@@ -266,6 +266,7 @@ section .confirm-screen-account-number,
.confirm-screen-total-box {
background-color: $wild-sand;
+ position: relative;
.confirm-screen-label {
line-height: 21px;
@@ -287,6 +288,41 @@ section .confirm-screen-account-number,
}
}
+.confirm-screen-error {
+ font-size: 12px;
+ line-height: 12px;
+ color: #f00;
+ position: absolute;
+ right: 12px;
+ width: 80px;
+ text-align: right;
+}
+
+.confirm-screen-row.confirm-screen-total-box {
+ .confirm-screen-section-column--with-error {
+ flex: 0.6;
+ }
+}
+
+@media screen and (max-width: 379px) {
+ .confirm-screen-row.confirm-screen-total-box {
+ .confirm-screen-section-column--with-error {
+ flex: 0.4;
+ }
+ }
+}
+
+.confirm-screen-form {
+ position: relative;
+
+ .confirm-screen-error {
+ right: 0;
+ width: 100%;
+ margin-top: 7px;
+ text-align: center;
+ }
+}
+
.confirm-screen-confirm-button {
height: 50px;
border-radius: 4px;
diff --git a/ui/app/send-v2.js b/ui/app/send-v2.js
index abbb97643..b4d38495d 100644
--- a/ui/app/send-v2.js
+++ b/ui/app/send-v2.js
@@ -27,6 +27,7 @@ const {
const {
isBalanceSufficient,
isTokenBalanceSufficient,
+ getGasTotal,
} = require('./components/send/send-utils')
const { isValidAddress } = require('./util')
const { CONFIRM_TRANSACTION_ROUTE, DEFAULT_ROUTE } = require('./routes')
@@ -133,7 +134,7 @@ SendTransactionScreen.prototype.updateGas = function () {
estimateGas(estimateGasParams),
])
.then(([gasPrice, gas]) => {
- const newGasTotal = this.getGasTotal(gas, gasPrice)
+ const newGasTotal = getGasTotal(gas, gasPrice)
updateGasTotal(newGasTotal)
this.setState({ gasLoadingError: false })
})
@@ -141,19 +142,11 @@ SendTransactionScreen.prototype.updateGas = function () {
this.setState({ gasLoadingError: true })
})
} else {
- const newGasTotal = this.getGasTotal(gasLimit, gasPrice)
+ const newGasTotal = getGasTotal(gasLimit, gasPrice)
updateGasTotal(newGasTotal)
}
}
-SendTransactionScreen.prototype.getGasTotal = function (gasLimit, gasPrice) {
- return multiplyCurrencies(gasLimit, gasPrice, {
- toNumericBase: 'hex',
- multiplicandBase: 16,
- multiplierBase: 16,
- })
-}
-
SendTransactionScreen.prototype.componentDidUpdate = function (prevProps) {
const {
from: { balance },
@@ -642,6 +635,10 @@ SendTransactionScreen.prototype.onSubmit = function (event) {
txParams.to = to
}
+ Object.keys(txParams).forEach(key => {
+ txParams[key] = ethUtil.addHexPrefix(txParams[key])
+ })
+
selectedToken
? signTokenTx(selectedToken.address, to, amount, txParams)
: signTx(txParams)
diff --git a/ui/index.js b/ui/index.js
index 1e0e9f1cc..746e28eab 100644
--- a/ui/index.js
+++ b/ui/index.js
@@ -69,6 +69,16 @@ async function startApp (metamaskState, accountManager, opts) {
store.dispatch(actions.updateMetamaskState(metamaskState))
})
+ // global metamask api - used by tooling
+ global.metamask = {
+ updateCurrentLocale: (code) => {
+ store.dispatch(actions.updateCurrentLocale(code))
+ },
+ setProviderType: (type) => {
+ store.dispatch(actions.setProviderType(type))
+ },
+ }
+
// start app
render(
h(Root, {