aboutsummaryrefslogtreecommitdiffstats
path: root/ui/app/components/pending-tx/confirm-send-ether.js
diff options
context:
space:
mode:
Diffstat (limited to 'ui/app/components/pending-tx/confirm-send-ether.js')
-rw-r--r--ui/app/components/pending-tx/confirm-send-ether.js409
1 files changed, 240 insertions, 169 deletions
diff --git a/ui/app/components/pending-tx/confirm-send-ether.js b/ui/app/components/pending-tx/confirm-send-ether.js
index 3f8d9c28f..f36def9d5 100644
--- a/ui/app/components/pending-tx/confirm-send-ether.js
+++ b/ui/app/components/pending-tx/confirm-send-ether.js
@@ -8,7 +8,13 @@ const Identicon = require('../identicon')
const ethUtil = require('ethereumjs-util')
const BN = ethUtil.BN
const hexToBn = require('../../../../app/scripts/lib/hex-to-bn')
-const { conversionUtil, addCurrencies } = require('../../conversion-util')
+const {
+ conversionUtil,
+ addCurrencies,
+ multiplyCurrencies,
+} = require('../../conversion-util')
+const GasFeeDisplay = require('../send/gas-fee-display-v2')
+const t = require('../../../i18n')
const { MIN_GAS_PRICE_HEX } = require('../send/send-constants')
@@ -43,6 +49,7 @@ function mapDispatchToProps (dispatch) {
to,
value: amount,
} = txParams
+
dispatch(actions.updateSend({
gasLimit,
gasPrice,
@@ -55,6 +62,29 @@ function mapDispatchToProps (dispatch) {
dispatch(actions.showSendPage())
},
cancelTransaction: ({ id }) => dispatch(actions.cancelTx({ id })),
+ showCustomizeGasModal: (txMeta, sendGasLimit, sendGasPrice, sendGasTotal) => {
+ const { id, txParams, lastGasPrice } = txMeta
+ const { gas: txGasLimit, gasPrice: txGasPrice } = txParams
+
+ let forceGasMin
+ if (lastGasPrice) {
+ forceGasMin = ethUtil.addHexPrefix(multiplyCurrencies(lastGasPrice, 1.1, {
+ multiplicandBase: 16,
+ multiplierBase: 10,
+ toNumericBase: 'hex',
+ fromDenomination: 'WEI',
+ }))
+ }
+
+ dispatch(actions.updateSend({
+ gasLimit: sendGasLimit || txGasLimit,
+ gasPrice: sendGasPrice || txGasPrice,
+ editingTransactionId: id,
+ gasTotal: sendGasTotal,
+ forceGasMin,
+ }))
+ dispatch(actions.showModal({ name: 'CUSTOMIZE_GAS' }))
+ },
}
}
@@ -139,6 +169,7 @@ ConfirmSendEther.prototype.getGasFee = function () {
return {
FIAT,
ETH,
+ gasFeeInHex: txFeeBn.toString(16),
}
}
@@ -146,7 +177,7 @@ ConfirmSendEther.prototype.getData = function () {
const { identities } = this.props
const txMeta = this.gatherTxMeta()
const txParams = txMeta.txParams || {}
- const { FIAT: gasFeeInFIAT, ETH: gasFeeInETH } = this.getGasFee()
+ const { FIAT: gasFeeInFIAT, ETH: gasFeeInETH, gasFeeInHex } = this.getGasFee()
const { FIAT: amountInFIAT, ETH: amountInETH } = this.getAmount()
const totalInFIAT = addCurrencies(gasFeeInFIAT, amountInFIAT, {
@@ -165,7 +196,7 @@ ConfirmSendEther.prototype.getData = function () {
},
to: {
address: txParams.to,
- name: identities[txParams.to] ? identities[txParams.to].name : 'New Recipient',
+ name: identities[txParams.to] ? identities[txParams.to].name : t('newRecipient'),
},
memo: txParams.memo || '',
gasFeeInFIAT,
@@ -174,11 +205,20 @@ ConfirmSendEther.prototype.getData = function () {
amountInETH,
totalInFIAT,
totalInETH,
+ gasFeeInHex,
}
}
ConfirmSendEther.prototype.render = function () {
- const { editTransaction, currentCurrency, clearSend } = this.props
+ const {
+ editTransaction,
+ currentCurrency,
+ clearSend,
+ conversionRate,
+ currentCurrency: convertedCurrency,
+ showCustomizeGasModal,
+ send: { gasTotal, gasLimit: sendGasLimit, gasPrice: sendGasPrice },
+ } = this.props
const txMeta = this.gatherTxMeta()
const txParams = txMeta.txParams || {}
@@ -192,13 +232,17 @@ ConfirmSendEther.prototype.render = function () {
name: toName,
},
memo,
- gasFeeInFIAT,
- gasFeeInETH,
+ gasFeeInHex,
amountInFIAT,
totalInFIAT,
totalInETH,
} = this.getData()
+ const title = txMeta.lastGasPrice ? 'Reprice Transaction' : 'Confirm'
+ const subtitle = txMeta.lastGasPrice
+ ? 'Increase your gas fee to attempt to overwrite and speed up your transaction'
+ : 'Please review your transaction.'
+
// This is from the latest master
// It handles some of the errors that we are not currently handling
// Leaving as comments fo reference
@@ -217,187 +261,193 @@ ConfirmSendEther.prototype.render = function () {
// Main Send token Card
h('div.page-container', [
h('div.page-container__header', [
- h('button.confirm-screen-back-button', {
+ !txMeta.lastGasPrice && h('button.confirm-screen-back-button', {
onClick: () => editTransaction(txMeta),
}, 'Edit'),
- h('div.page-container__title', 'Confirm'),
- h('div.page-container__subtitle', `Please review your transaction.`),
+ h('div.page-container__title', title),
+ h('div.page-container__subtitle', subtitle),
]),
- h('div.flex-row.flex-center.confirm-screen-identicons', [
- h('div.confirm-screen-account-wrapper', [
- h(
- Identicon,
- {
- address: fromAddress,
- diameter: 60,
- },
- ),
- h('span.confirm-screen-account-name', fromName),
- // h('span.confirm-screen-account-number', fromAddress.slice(fromAddress.length - 4)),
+ h('.page-container__content', [
+ h('div.flex-row.flex-center.confirm-screen-identicons', [
+ h('div.confirm-screen-account-wrapper', [
+ h(
+ Identicon,
+ {
+ address: fromAddress,
+ diameter: 60,
+ },
+ ),
+ h('span.confirm-screen-account-name', fromName),
+ // h('span.confirm-screen-account-number', fromAddress.slice(fromAddress.length - 4)),
+ ]),
+ h('i.fa.fa-arrow-right.fa-lg'),
+ h('div.confirm-screen-account-wrapper', [
+ h(
+ Identicon,
+ {
+ address: txParams.to,
+ diameter: 60,
+ },
+ ),
+ h('span.confirm-screen-account-name', toName),
+ // h('span.confirm-screen-account-number', toAddress.slice(toAddress.length - 4)),
+ ]),
]),
- h('i.fa.fa-arrow-right.fa-lg'),
- h('div.confirm-screen-account-wrapper', [
- h(
- Identicon,
- {
- address: txParams.to,
- diameter: 60,
- },
- ),
- h('span.confirm-screen-account-name', toName),
- // h('span.confirm-screen-account-number', toAddress.slice(toAddress.length - 4)),
+
+ // h('h3.flex-center.confirm-screen-sending-to-message', {
+ // style: {
+ // textAlign: 'center',
+ // fontSize: '16px',
+ // },
+ // }, [
+ // `You're sending to Recipient ...${toAddress.slice(toAddress.length - 4)}`,
+ // ]),
+
+ h('h3.flex-center.confirm-screen-send-amount', [`${amountInFIAT}`]),
+ h('h3.flex-center.confirm-screen-send-amount-currency', [ currentCurrency.toUpperCase() ]),
+ h('div.flex-center.confirm-memo-wrapper', [
+ h('h3.confirm-screen-send-memo', [ memo ? `"${memo}"` : '' ]),
]),
- ]),
- // h('h3.flex-center.confirm-screen-sending-to-message', {
- // style: {
- // textAlign: 'center',
- // fontSize: '16px',
- // },
- // }, [
- // `You're sending to Recipient ...${toAddress.slice(toAddress.length - 4)}`,
- // ]),
-
- h('h3.flex-center.confirm-screen-send-amount', [`${amountInFIAT}`]),
- h('h3.flex-center.confirm-screen-send-amount-currency', [ currentCurrency.toUpperCase() ]),
- h('div.flex-center.confirm-memo-wrapper', [
- h('h3.confirm-screen-send-memo', [ memo ? `"${memo}"` : '' ]),
- ]),
+ h('div.confirm-screen-rows', [
+ h('section.flex-row.flex-center.confirm-screen-row', [
+ h('span.confirm-screen-label.confirm-screen-section-column', [ t('from') ]),
+ h('div.confirm-screen-section-column', [
+ h('div.confirm-screen-row-info', fromName),
+ h('div.confirm-screen-row-detail', `...${fromAddress.slice(fromAddress.length - 4)}`),
+ ]),
+ ]),
- h('div.confirm-screen-rows', [
- h('section.flex-row.flex-center.confirm-screen-row', [
- h('span.confirm-screen-label.confirm-screen-section-column', [ 'From' ]),
- h('div.confirm-screen-section-column', [
- h('div.confirm-screen-row-info', fromName),
- h('div.confirm-screen-row-detail', `...${fromAddress.slice(fromAddress.length - 4)}`),
+ h('section.flex-row.flex-center.confirm-screen-row', [
+ h('span.confirm-screen-label.confirm-screen-section-column', [ t('to') ]),
+ h('div.confirm-screen-section-column', [
+ h('div.confirm-screen-row-info', toName),
+ h('div.confirm-screen-row-detail', `...${toAddress.slice(toAddress.length - 4)}`),
+ ]),
]),
- ]),
- h('section.flex-row.flex-center.confirm-screen-row', [
- h('span.confirm-screen-label.confirm-screen-section-column', [ 'To' ]),
- h('div.confirm-screen-section-column', [
- h('div.confirm-screen-row-info', toName),
- h('div.confirm-screen-row-detail', `...${toAddress.slice(toAddress.length - 4)}`),
+ h('section.flex-row.flex-center.confirm-screen-row', [
+ h('span.confirm-screen-label.confirm-screen-section-column', [ t('gasFee') ]),
+ h('div.confirm-screen-section-column', [
+ h(GasFeeDisplay, {
+ gasTotal: gasTotal || gasFeeInHex,
+ conversionRate,
+ convertedCurrency,
+ onClick: () => showCustomizeGasModal(txMeta, sendGasLimit, sendGasPrice, gasTotal),
+ }),
+ ]),
]),
- ]),
- h('section.flex-row.flex-center.confirm-screen-row', [
- h('span.confirm-screen-label.confirm-screen-section-column', [ 'Gas Fee' ]),
- h('div.confirm-screen-section-column', [
- h('div.confirm-screen-row-info', `${gasFeeInFIAT} ${currentCurrency.toUpperCase()}`),
+ h('section.flex-row.flex-center.confirm-screen-row.confirm-screen-total-box ', [
+ h('div.confirm-screen-section-column', [
+ h('span.confirm-screen-label', [ t('total') + ' ' ]),
+ h('div.confirm-screen-total-box__subtitle', [ t('amountPlusGas') ]),
+ ]),
- h('div.confirm-screen-row-detail', `${gasFeeInETH} ETH`),
+ h('div.confirm-screen-section-column', [
+ h('div.confirm-screen-row-info', `${totalInFIAT} ${currentCurrency.toUpperCase()}`),
+ h('div.confirm-screen-row-detail', `${totalInETH} ETH`),
+ ]),
]),
]),
+ // These are latest errors handling from master
+ // Leaving as comments as reference when we start implementing error handling
+ // h('style', `
+ // .conf-buttons button {
+ // margin-left: 10px;
+ // text-transform: uppercase;
+ // }
+ // `),
+
+ // txMeta.simulationFails ?
+ // h('.error', {
+ // style: {
+ // marginLeft: 50,
+ // fontSize: '0.9em',
+ // },
+ // }, 'Transaction Error. Exception thrown in contract code.')
+ // : null,
+
+ // !isValidAddress ?
+ // h('.error', {
+ // style: {
+ // marginLeft: 50,
+ // fontSize: '0.9em',
+ // },
+ // }, 'Recipient address is invalid. Sending this transaction will result in a loss of ETH.')
+ // : null,
+
+ // insufficientBalance ?
+ // h('span.error', {
+ // style: {
+ // marginLeft: 50,
+ // fontSize: '0.9em',
+ // },
+ // }, 'Insufficient balance for transaction')
+ // : null,
+
+ // // send + cancel
+ // h('.flex-row.flex-space-around.conf-buttons', {
+ // style: {
+ // display: 'flex',
+ // justifyContent: 'flex-end',
+ // margin: '14px 25px',
+ // },
+ // }, [
+ // h('button', {
+ // onClick: (event) => {
+ // this.resetGasFields()
+ // event.preventDefault()
+ // },
+ // }, 'Reset'),
+
+ // // Accept Button or Buy Button
+ // insufficientBalance ? h('button.btn-green', { onClick: props.buyEth }, 'Buy Ether') :
+ // h('input.confirm.btn-green', {
+ // type: 'submit',
+ // value: 'SUBMIT',
+ // style: { marginLeft: '10px' },
+ // disabled: buyDisabled,
+ // }),
+
+ // h('button.cancel.btn-red', {
+ // onClick: props.cancelTransaction,
+ // }, 'Reject'),
+ // ]),
+ // showRejectAll ? h('.flex-row.flex-space-around.conf-buttons', {
+ // style: {
+ // display: 'flex',
+ // justifyContent: 'flex-end',
+ // margin: '14px 25px',
+ // },
+ // }, [
+ // h('button.cancel.btn-red', {
+ // onClick: props.cancelAllTransactions,
+ // }, 'Reject All'),
+ // ]) : null,
+ // ]),
+ // ])
+ // )
+ // }
+ ]),
- h('section.flex-row.flex-center.confirm-screen-total-box ', [
- h('div.confirm-screen-section-column', [
- h('span.confirm-screen-label', [ 'Total ' ]),
- h('div.confirm-screen-total-box__subtitle', [ 'Amount + Gas' ]),
- ]),
+ h('form#pending-tx-form', {
+ onSubmit: this.onSubmit,
+ }, [
+ h('.page-container__footer', [
+ // Cancel Button
+ h('button.btn-cancel.page-container__footer-button.allcaps', {
+ onClick: (event) => {
+ clearSend()
+ this.cancel(event, txMeta)
+ },
+ }, t('cancel')),
- h('div.confirm-screen-section-column', [
- h('div.confirm-screen-row-info', `${totalInFIAT} ${currentCurrency.toUpperCase()}`),
- h('div.confirm-screen-row-detail', `${totalInETH} ETH`),
- ]),
+ // Accept Button
+ h('button.btn-confirm.page-container__footer-button.allcaps', [t('confirm')]),
]),
]),
-
-// These are latest errors handling from master
-// Leaving as comments as reference when we start implementing error handling
-// h('style', `
-// .conf-buttons button {
-// margin-left: 10px;
-// text-transform: uppercase;
-// }
-// `),
-
-// txMeta.simulationFails ?
-// h('.error', {
-// style: {
-// marginLeft: 50,
-// fontSize: '0.9em',
-// },
-// }, 'Transaction Error. Exception thrown in contract code.')
-// : null,
-
-// !isValidAddress ?
-// h('.error', {
-// style: {
-// marginLeft: 50,
-// fontSize: '0.9em',
-// },
-// }, 'Recipient address is invalid. Sending this transaction will result in a loss of ETH.')
-// : null,
-
-// insufficientBalance ?
-// h('span.error', {
-// style: {
-// marginLeft: 50,
-// fontSize: '0.9em',
-// },
-// }, 'Insufficient balance for transaction')
-// : null,
-
-// // send + cancel
-// h('.flex-row.flex-space-around.conf-buttons', {
-// style: {
-// display: 'flex',
-// justifyContent: 'flex-end',
-// margin: '14px 25px',
-// },
-// }, [
-// h('button', {
-// onClick: (event) => {
-// this.resetGasFields()
-// event.preventDefault()
-// },
-// }, 'Reset'),
-
-// // Accept Button or Buy Button
-// insufficientBalance ? h('button.btn-green', { onClick: props.buyEth }, 'Buy Ether') :
-// h('input.confirm.btn-green', {
-// type: 'submit',
-// value: 'SUBMIT',
-// style: { marginLeft: '10px' },
-// disabled: buyDisabled,
-// }),
-
-// h('button.cancel.btn-red', {
-// onClick: props.cancelTransaction,
-// }, 'Reject'),
-// ]),
-// showRejectAll ? h('.flex-row.flex-space-around.conf-buttons', {
-// style: {
-// display: 'flex',
-// justifyContent: 'flex-end',
-// margin: '14px 25px',
-// },
-// }, [
-// h('button.cancel.btn-red', {
-// onClick: props.cancelAllTransactions,
-// }, 'Reject All'),
-// ]) : null,
-// ]),
-// ])
-// )
-// }
- ]),
-
- h('form#pending-tx-form', {
- onSubmit: this.onSubmit,
- }, [
- // Cancel Button
- h('div.cancel.btn-light.confirm-screen-cancel-button', {
- onClick: (event) => {
- clearSend()
- this.cancel(event, txMeta)
- },
- }, 'CANCEL'),
-
- // Accept Button
- h('button.confirm-screen-confirm-button', ['CONFIRM']),
]),
])
)
@@ -412,7 +462,7 @@ ConfirmSendEther.prototype.onSubmit = function (event) {
if (valid && this.verifyGasParams()) {
this.props.sendTransaction(txMeta, event)
} else {
- this.props.dispatch(actions.displayWarning('Invalid Gas Parameters'))
+ this.props.dispatch(actions.displayWarning(t('invalidGasParams')))
this.setState({ submitting: false })
}
}
@@ -445,6 +495,27 @@ ConfirmSendEther.prototype.gatherTxMeta = function () {
const state = this.state
const txData = clone(state.txData) || clone(props.txData)
+ const { gasPrice: sendGasPrice, gas: sendGasLimit } = props.send
+ const {
+ lastGasPrice,
+ txParams: {
+ gasPrice: txGasPrice,
+ gas: txGasLimit,
+ },
+ } = txData
+
+ let forceGasMin
+ if (lastGasPrice) {
+ forceGasMin = ethUtil.addHexPrefix(multiplyCurrencies(lastGasPrice, 1.1, {
+ multiplicandBase: 16,
+ multiplierBase: 10,
+ toNumericBase: 'hex',
+ }))
+ }
+
+ txData.txParams.gasPrice = sendGasPrice || forceGasMin || txGasPrice
+ txData.txParams.gas = sendGasLimit || txGasLimit
+
// log.debug(`UI has defaulted to tx meta ${JSON.stringify(txData)}`)
return txData
}