diff options
Diffstat (limited to 'ui/app/components/pending-tx/confirm-send-ether.js')
-rw-r--r-- | ui/app/components/pending-tx/confirm-send-ether.js | 409 |
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 } |