From ea9d51e427b8e607e612a01629bebf153e516ad9 Mon Sep 17 00:00:00 2001 From: Alexander Tseung Date: Fri, 22 Jun 2018 23:52:45 -0700 Subject: Refactor and redesign confirm transaction views --- .../confirm-transaction-base.component.js | 382 +++++++++++++++++++++ 1 file changed, 382 insertions(+) create mode 100644 ui/app/components/pages/confirm-transaction-base/confirm-transaction-base.component.js (limited to 'ui/app/components/pages/confirm-transaction-base/confirm-transaction-base.component.js') diff --git a/ui/app/components/pages/confirm-transaction-base/confirm-transaction-base.component.js b/ui/app/components/pages/confirm-transaction-base/confirm-transaction-base.component.js new file mode 100644 index 000000000..3b60a5d5d --- /dev/null +++ b/ui/app/components/pages/confirm-transaction-base/confirm-transaction-base.component.js @@ -0,0 +1,382 @@ +import React, { Component } from 'react' +import PropTypes from 'prop-types' +import ConfirmPageContainer, { ConfirmDetailRow } from '../../confirm-page-container' +import { formatCurrency, getHexGasTotal } from '../../../helpers/confirm-transaction/util' +import { isBalanceSufficient } from '../../send_/send.utils' +import { DEFAULT_ROUTE } from '../../../routes' +import { conversionGreaterThan } from '../../../conversion-util' +import { MIN_GAS_LIMIT_DEC } from '../../send_/send.constants' + +export default class ConfirmTransactionBase extends Component { + static contextTypes = { + t: PropTypes.func, + } + + static propTypes = { + match: PropTypes.object, + history: PropTypes.object, + // Redux props + txData: PropTypes.object, + tokenData: PropTypes.object, + tokenProps: PropTypes.object, + isTxReprice: PropTypes.bool, + nonce: PropTypes.string, + fromName: PropTypes.string, + fromAddress: PropTypes.string, + toName: PropTypes.string, + toAddress: PropTypes.string, + transactionStatus: PropTypes.string, + ethTransactionAmount: PropTypes.string, + ethTransactionFee: PropTypes.string, + ethTransactionTotal: PropTypes.string, + fiatTransactionAmount: PropTypes.string, + fiatTransactionFee: PropTypes.string, + fiatTransactionTotal: PropTypes.string, + hexGasTotal: PropTypes.string, + balance: PropTypes.string, + currentCurrency: PropTypes.string, + conversionRate: PropTypes.number, + setTransactionToConfirm: PropTypes.func, + clearConfirmTransaction: PropTypes.func, + cancelTransaction: PropTypes.func, + clearSend: PropTypes.func, + sendTransaction: PropTypes.func, + editTransaction: PropTypes.func, + showCustomizeGasModal: PropTypes.func, + updateGasAndCalculate: PropTypes.func, + showTransactionConfirmedModal: PropTypes.func, + // Component props + action: PropTypes.string, + hideDetails: PropTypes.bool, + hideData: PropTypes.bool, + detailsComponent: PropTypes.node, + dataComponent: PropTypes.node, + summaryComponent: PropTypes.node, + contentComponent: PropTypes.node, + title: PropTypes.string, + subtitle: PropTypes.string, + hideSubtitle: PropTypes.bool, + valid: PropTypes.bool, + errorMessage: PropTypes.string, + warning: PropTypes.string, + identiconAddress: PropTypes.string, + onEdit: PropTypes.func, + onEditGas: PropTypes.func, + onCancel: PropTypes.func, + onSubmit: PropTypes.func, + } + + componentDidMount () { + const { match: { params: { id } = {} }, setTransactionToConfirm } = this.props + setTransactionToConfirm(id) + } + + componentDidUpdate (prevProps) { + const { + transactionStatus, + showTransactionConfirmedModal, + history, + clearConfirmTransaction, + match: { params: { id } = {} }, + setTransactionToConfirm, + txData, + } = this.props + + if (transactionStatus === 'dropped') { + showTransactionConfirmedModal({ + onHide: () => { + clearConfirmTransaction() + history.push(DEFAULT_ROUTE) + }, + }) + + return + } + + if (id && id !== txData.id + '') { + setTransactionToConfirm(id) + } + } + + getError () { + const INSUFFICIENT_FUNDS_ERROR = this.context.t('insufficientFunds') + const TRANSACTION_ERROR = this.context.t('transactionError') + const { + balance, + conversionRate, + hexGasTotal, + txData: { + simulationFails, + txParams: { + value: amount, + } = {}, + } = {}, + } = this.props + + const insufficientBalance = balance && !isBalanceSufficient({ + amount, + gasTotal: hexGasTotal || '0x0', + balance, + conversionRate, + }) + + if (insufficientBalance) { + return { + valid: false, + errorMessage: INSUFFICIENT_FUNDS_ERROR, + } + } + + if (simulationFails) { + return { + valid: false, + errorMessage: TRANSACTION_ERROR, + } + } + + return { + valid: true, + } + } + + validateEditGas ({ gasLimit, gasPrice }) { + const { t } = this.context + const { + balance, + conversionRate, + txData: { + txParams: { + value: amount, + } = {}, + } = {}, + } = this.props + + const INSUFFICIENT_FUNDS_ERROR = t('insufficientFunds') + const GAS_LIMIT_TOO_LOW_ERROR = t('gasLimitTooLow') + + const gasTotal = getHexGasTotal({ gasLimit, gasPrice }) + const hasSufficientBalance = isBalanceSufficient({ + amount, + gasTotal, + balance, + conversionRate, + }) + + if (!hasSufficientBalance) { + return { + valid: false, + errorMessage: INSUFFICIENT_FUNDS_ERROR, + } + } + + const gasLimitTooLow = gasLimit && conversionGreaterThan( + { + value: MIN_GAS_LIMIT_DEC, + fromNumericBase: 'dec', + conversionRate, + }, + { + value: gasLimit, + fromNumericBase: 'hex', + }, + ) + + if (gasLimitTooLow) { + return { + valid: false, + errorMessage: GAS_LIMIT_TOO_LOW_ERROR, + } + } + + return { + valid: true, + } + } + + handleEditGas () { + const { onEditGas, showCustomizeGasModal, txData, updateGasAndCalculate } = this.props + + if (onEditGas) { + onEditGas() + } else { + showCustomizeGasModal({ + txData, + onSubmit: txData => updateGasAndCalculate(txData), + validate: ({ gasLimit, gasPrice }) => this.validateEditGas({ gasLimit, gasPrice }), + }) + } + } + + renderDetails () { + const { + detailsComponent, + fiatTransactionFee, + ethTransactionFee, + currentCurrency, + fiatTransactionTotal, + ethTransactionTotal, + hideDetails, + } = this.props + + if (hideDetails) { + return null + } + + return ( + detailsComponent || ( +
+
+ this.handleEditGas()} + /> +
+
+ +
+
+ ) + ) + } + + renderData () { + const { t } = this.context + const { + txData: { + txParams: { + data, + } = {}, + } = {}, + tokenData: { + name, + params, + } = {}, + hideData, + dataComponent, + } = this.props + + if (hideData) { + return null + } + + return dataComponent || ( +
+
+ {`${t('functionType')}:`} + + { name } + +
+
+ { JSON.stringify(params, null, 2) } +
+
+ {`${t('hexData')}:`} +
+
+ { data } +
+
+ ) + } + + handleEdit () { + const { txData, tokenData, tokenProps, onEdit } = this.props + onEdit({ txData, tokenData, tokenProps }) + } + + handleCancel () { + const { onCancel, txData, cancelTransaction, history, clearConfirmTransaction } = this.props + + if (onCancel) { + onCancel(txData) + } else { + cancelTransaction(txData) + .then(() => { + clearConfirmTransaction() + history.push(DEFAULT_ROUTE) + }) + } + } + + handleSubmit () { + const { sendTransaction, clearConfirmTransaction, txData, history, onSubmit } = this.props + + if (onSubmit) { + onSubmit(txData) + } else { + sendTransaction(txData) + .then(() => { + clearConfirmTransaction() + history.push(DEFAULT_ROUTE) + }) + } + } + + render () { + const { + isTxReprice, + fromName, + fromAddress, + toName, + toAddress, + tokenData, + ethTransactionAmount, + fiatTransactionAmount, + valid: propsValid, + errorMessage: propsErrorMessage, + currentCurrency, + action, + title, + subtitle, + hideSubtitle, + identiconAddress, + summaryComponent, + contentComponent, + onEdit, + nonce, + warning, + } = this.props + + const { name } = tokenData + const fiatConvertedAmount = formatCurrency(fiatTransactionAmount, currentCurrency) + const { valid, errorMessage } = this.getError() + + return ( + this.handleEdit()} + onCancel={() => this.handleCancel()} + onSubmit={() => this.handleSubmit()} + /> + ) + } +} -- cgit From e89549846fd3bd520b99740c7845f48f368c3afa Mon Sep 17 00:00:00 2001 From: Alexander Tseung Date: Mon, 25 Jun 2018 12:06:57 -0700 Subject: Refactor data flow, signature request routing --- .../confirm-transaction-base.component.js | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) (limited to 'ui/app/components/pages/confirm-transaction-base/confirm-transaction-base.component.js') diff --git a/ui/app/components/pages/confirm-transaction-base/confirm-transaction-base.component.js b/ui/app/components/pages/confirm-transaction-base/confirm-transaction-base.component.js index 3b60a5d5d..dfbbd0177 100644 --- a/ui/app/components/pages/confirm-transaction-base/confirm-transaction-base.component.js +++ b/ui/app/components/pages/confirm-transaction-base/confirm-transaction-base.component.js @@ -36,7 +36,6 @@ export default class ConfirmTransactionBase extends Component { balance: PropTypes.string, currentCurrency: PropTypes.string, conversionRate: PropTypes.number, - setTransactionToConfirm: PropTypes.func, clearConfirmTransaction: PropTypes.func, cancelTransaction: PropTypes.func, clearSend: PropTypes.func, @@ -66,20 +65,12 @@ export default class ConfirmTransactionBase extends Component { onSubmit: PropTypes.func, } - componentDidMount () { - const { match: { params: { id } = {} }, setTransactionToConfirm } = this.props - setTransactionToConfirm(id) - } - - componentDidUpdate (prevProps) { + componentDidUpdate () { const { transactionStatus, showTransactionConfirmedModal, history, clearConfirmTransaction, - match: { params: { id } = {} }, - setTransactionToConfirm, - txData, } = this.props if (transactionStatus === 'dropped') { @@ -92,10 +83,6 @@ export default class ConfirmTransactionBase extends Component { return } - - if (id && id !== txData.id + '') { - setTransactionToConfirm(id) - } } getError () { -- cgit From 9cde5ab11b0670eed7baeb2f31486cb3e253bdcb Mon Sep 17 00:00:00 2001 From: Alexander Tseung Date: Thu, 28 Jun 2018 11:23:31 -0700 Subject: Use eth-method-registry to get method data --- .../confirm-transaction-base.component.js | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) (limited to 'ui/app/components/pages/confirm-transaction-base/confirm-transaction-base.component.js') diff --git a/ui/app/components/pages/confirm-transaction-base/confirm-transaction-base.component.js b/ui/app/components/pages/confirm-transaction-base/confirm-transaction-base.component.js index dfbbd0177..1a399a464 100644 --- a/ui/app/components/pages/confirm-transaction-base/confirm-transaction-base.component.js +++ b/ui/app/components/pages/confirm-transaction-base/confirm-transaction-base.component.js @@ -18,6 +18,7 @@ export default class ConfirmTransactionBase extends Component { // Redux props txData: PropTypes.object, tokenData: PropTypes.object, + methodData: PropTypes.object, tokenProps: PropTypes.object, isTxReprice: PropTypes.bool, nonce: PropTypes.string, @@ -245,7 +246,7 @@ export default class ConfirmTransactionBase extends Component { data, } = {}, } = {}, - tokenData: { + methodData: { name, params, } = {}, @@ -266,7 +267,12 @@ export default class ConfirmTransactionBase extends Component {
- { JSON.stringify(params, null, 2) } +
+ { `${t('parameters')}:` } +
+
+
{ JSON.stringify(params, null, 2) }
+
{`${t('hexData')}:`} @@ -318,7 +324,7 @@ export default class ConfirmTransactionBase extends Component { fromAddress, toName, toAddress, - tokenData, + methodData, ethTransactionAmount, fiatTransactionAmount, valid: propsValid, @@ -336,7 +342,7 @@ export default class ConfirmTransactionBase extends Component { warning, } = this.props - const { name } = tokenData + const { name } = methodData const fiatConvertedAmount = formatCurrency(fiatTransactionAmount, currentCurrency) const { valid, errorMessage } = this.getError() -- cgit From a2d9c43fba49680d7553409a4f5013d3febd80e9 Mon Sep 17 00:00:00 2001 From: Alexander Tseung Date: Fri, 6 Jul 2018 11:58:41 -0700 Subject: Various fixes from PR comments --- .../confirm-transaction-base.component.js | 147 +++++++-------------- 1 file changed, 46 insertions(+), 101 deletions(-) (limited to 'ui/app/components/pages/confirm-transaction-base/confirm-transaction-base.component.js') diff --git a/ui/app/components/pages/confirm-transaction-base/confirm-transaction-base.component.js b/ui/app/components/pages/confirm-transaction-base/confirm-transaction-base.component.js index 1a399a464..842b34d2e 100644 --- a/ui/app/components/pages/confirm-transaction-base/confirm-transaction-base.component.js +++ b/ui/app/components/pages/confirm-transaction-base/confirm-transaction-base.component.js @@ -1,11 +1,13 @@ import React, { Component } from 'react' import PropTypes from 'prop-types' import ConfirmPageContainer, { ConfirmDetailRow } from '../../confirm-page-container' -import { formatCurrency, getHexGasTotal } from '../../../helpers/confirm-transaction/util' +import { formatCurrency } from '../../../helpers/confirm-transaction/util' import { isBalanceSufficient } from '../../send_/send.utils' import { DEFAULT_ROUTE } from '../../../routes' -import { conversionGreaterThan } from '../../../conversion-util' -import { MIN_GAS_LIMIT_DEC } from '../../send_/send.constants' +import { + INSUFFICIENT_FUNDS_ERROR_KEY, + TRANSACTION_ERROR_KEY, +} from '../../../constants/error-keys' export default class ConfirmTransactionBase extends Component { static contextTypes = { @@ -13,57 +15,58 @@ export default class ConfirmTransactionBase extends Component { } static propTypes = { + // react-router props match: PropTypes.object, history: PropTypes.object, // Redux props - txData: PropTypes.object, - tokenData: PropTypes.object, - methodData: PropTypes.object, - tokenProps: PropTypes.object, - isTxReprice: PropTypes.bool, - nonce: PropTypes.string, - fromName: PropTypes.string, - fromAddress: PropTypes.string, - toName: PropTypes.string, - toAddress: PropTypes.string, - transactionStatus: PropTypes.string, + balance: PropTypes.string, + cancelTransaction: PropTypes.func, + clearConfirmTransaction: PropTypes.func, + clearSend: PropTypes.func, + conversionRate: PropTypes.number, + currentCurrency: PropTypes.string, + editTransaction: PropTypes.func, ethTransactionAmount: PropTypes.string, ethTransactionFee: PropTypes.string, ethTransactionTotal: PropTypes.string, fiatTransactionAmount: PropTypes.string, fiatTransactionFee: PropTypes.string, fiatTransactionTotal: PropTypes.string, + fromAddress: PropTypes.string, + fromName: PropTypes.string, hexGasTotal: PropTypes.string, - balance: PropTypes.string, - currentCurrency: PropTypes.string, - conversionRate: PropTypes.number, - clearConfirmTransaction: PropTypes.func, - cancelTransaction: PropTypes.func, - clearSend: PropTypes.func, + isTxReprice: PropTypes.bool, + methodData: PropTypes.object, + nonce: PropTypes.string, sendTransaction: PropTypes.func, - editTransaction: PropTypes.func, showCustomizeGasModal: PropTypes.func, - updateGasAndCalculate: PropTypes.func, showTransactionConfirmedModal: PropTypes.func, + toAddress: PropTypes.string, + tokenData: PropTypes.object, + tokenProps: PropTypes.object, + toName: PropTypes.string, + transactionStatus: PropTypes.string, + txData: PropTypes.object, // Component props action: PropTypes.string, - hideDetails: PropTypes.bool, - hideData: PropTypes.bool, - detailsComponent: PropTypes.node, - dataComponent: PropTypes.node, - summaryComponent: PropTypes.node, contentComponent: PropTypes.node, - title: PropTypes.string, - subtitle: PropTypes.string, - hideSubtitle: PropTypes.bool, - valid: PropTypes.bool, + dataComponent: PropTypes.node, + detailsComponent: PropTypes.node, + errorKey: PropTypes.string, errorMessage: PropTypes.string, - warning: PropTypes.string, + hideData: PropTypes.bool, + hideDetails: PropTypes.bool, + hideSubtitle: PropTypes.bool, identiconAddress: PropTypes.string, + onCancel: PropTypes.func, onEdit: PropTypes.func, onEditGas: PropTypes.func, - onCancel: PropTypes.func, onSubmit: PropTypes.func, + subtitle: PropTypes.string, + summaryComponent: PropTypes.node, + title: PropTypes.string, + valid: PropTypes.bool, + warning: PropTypes.string, } componentDidUpdate () { @@ -86,9 +89,7 @@ export default class ConfirmTransactionBase extends Component { } } - getError () { - const INSUFFICIENT_FUNDS_ERROR = this.context.t('insufficientFunds') - const TRANSACTION_ERROR = this.context.t('transactionError') + getErrorKey () { const { balance, conversionRate, @@ -111,68 +112,14 @@ export default class ConfirmTransactionBase extends Component { if (insufficientBalance) { return { valid: false, - errorMessage: INSUFFICIENT_FUNDS_ERROR, + errorKey: INSUFFICIENT_FUNDS_ERROR_KEY, } } if (simulationFails) { return { valid: false, - errorMessage: TRANSACTION_ERROR, - } - } - - return { - valid: true, - } - } - - validateEditGas ({ gasLimit, gasPrice }) { - const { t } = this.context - const { - balance, - conversionRate, - txData: { - txParams: { - value: amount, - } = {}, - } = {}, - } = this.props - - const INSUFFICIENT_FUNDS_ERROR = t('insufficientFunds') - const GAS_LIMIT_TOO_LOW_ERROR = t('gasLimitTooLow') - - const gasTotal = getHexGasTotal({ gasLimit, gasPrice }) - const hasSufficientBalance = isBalanceSufficient({ - amount, - gasTotal, - balance, - conversionRate, - }) - - if (!hasSufficientBalance) { - return { - valid: false, - errorMessage: INSUFFICIENT_FUNDS_ERROR, - } - } - - const gasLimitTooLow = gasLimit && conversionGreaterThan( - { - value: MIN_GAS_LIMIT_DEC, - fromNumericBase: 'dec', - conversionRate, - }, - { - value: gasLimit, - fromNumericBase: 'hex', - }, - ) - - if (gasLimitTooLow) { - return { - valid: false, - errorMessage: GAS_LIMIT_TOO_LOW_ERROR, + errorKey: TRANSACTION_ERROR_KEY, } } @@ -182,16 +129,12 @@ export default class ConfirmTransactionBase extends Component { } handleEditGas () { - const { onEditGas, showCustomizeGasModal, txData, updateGasAndCalculate } = this.props + const { onEditGas, showCustomizeGasModal } = this.props if (onEditGas) { onEditGas() } else { - showCustomizeGasModal({ - txData, - onSubmit: txData => updateGasAndCalculate(txData), - validate: ({ gasLimit, gasPrice }) => this.validateEditGas({ gasLimit, gasPrice }), - }) + showCustomizeGasModal() } } @@ -328,7 +271,8 @@ export default class ConfirmTransactionBase extends Component { ethTransactionAmount, fiatTransactionAmount, valid: propsValid, - errorMessage: propsErrorMessage, + errorMessage, + errorKey: propsErrorKey, currentCurrency, action, title, @@ -344,7 +288,7 @@ export default class ConfirmTransactionBase extends Component { const { name } = methodData const fiatConvertedAmount = formatCurrency(fiatTransactionAmount, currentCurrency) - const { valid, errorMessage } = this.getError() + const { valid, errorKey } = this.getErrorKey() return ( this.handleEdit()} -- cgit