From dc92b56f184100a24aaf53c3e93619514159f938 Mon Sep 17 00:00:00 2001 From: Dan Date: Tue, 20 Mar 2018 09:07:23 -0230 Subject: Identify token transactions by method names token data, and not just whether they've been add via metamask. --- ui/app/components/pending-tx/confirm-send-token.js | 1 + ui/app/components/pending-tx/index.js | 14 ++++++++++---- 2 files changed, 11 insertions(+), 4 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/pending-tx/confirm-send-token.js b/ui/app/components/pending-tx/confirm-send-token.js index 0a4182014..c347dd21e 100644 --- a/ui/app/components/pending-tx/confirm-send-token.js +++ b/ui/app/components/pending-tx/confirm-send-token.js @@ -86,6 +86,7 @@ function mapDispatchToProps (dispatch, ownProps) { amount: tokenAmountInHex, errors: { to: null, amount: null }, editingTransactionId: id, + token: ownProps.token, })) dispatch(actions.showSendTokenPage()) }, diff --git a/ui/app/components/pending-tx/index.js b/ui/app/components/pending-tx/index.js index f4f6afb8f..9676e9c86 100644 --- a/ui/app/components/pending-tx/index.js +++ b/ui/app/components/pending-tx/index.js @@ -63,14 +63,17 @@ PendingTx.prototype.componentWillMount = async function () { isFetching: false, }) } + const tokenData = txParams && abiDecoder.decodeMethod(txParams.data) + const { name: tokenMethodName } = tokenData || {} + const isTokenTransaction = ['transfer', 'approve', 'transferFrom'] + .find(possibleName => tokenMethodName === possibleName) - try { + if (isTokenTransaction) { const token = util.getContractAtAddress(txParams.to) const results = await Promise.all([ token.symbol(), token.decimals(), ]) - const [ symbol, decimals ] = results if (symbol[0] && decimals[0]) { @@ -83,11 +86,14 @@ PendingTx.prototype.componentWillMount = async function () { }) } else { this.setState({ - transactionType: TX_TYPES.SEND_ETHER, + transactionType: TX_TYPES.SEND_TOKEN, + tokenAddress: txParams.to, + tokenSymbol: null, + tokenDecimals: null, isFetching: false, }) } - } catch (e) { + } else { this.setState({ transactionType: TX_TYPES.SEND_ETHER, isFetching: false, -- cgit v1.2.3 From 3c1248c8169a1cb96a0ee2bc0f523fb9c765569e Mon Sep 17 00:00:00 2001 From: Alexander Tseung Date: Mon, 19 Mar 2018 16:12:09 -0700 Subject: Update confirm transaction screen --- ui/app/components/network-display.js | 51 ++++ .../pending-tx/confirm-deploy-contract.js | 10 +- ui/app/components/pending-tx/confirm-send-ether.js | 336 ++++++++++----------- ui/app/components/sender-to-recipient.js | 29 +- 4 files changed, 244 insertions(+), 182 deletions(-) create mode 100644 ui/app/components/network-display.js (limited to 'ui/app/components') diff --git a/ui/app/components/network-display.js b/ui/app/components/network-display.js new file mode 100644 index 000000000..9dc31b5c7 --- /dev/null +++ b/ui/app/components/network-display.js @@ -0,0 +1,51 @@ +const { Component } = require('react') +const h = require('react-hyperscript') +const PropTypes = require('prop-types') +const { connect } = require('react-redux') +const NetworkDropdownIcon = require('./dropdowns/components/network-dropdown-icon') +const t = require('../../i18n') + +const networkToColorHash = { + 1: '#038789', + 3: '#e91550', + 42: '#690496', + 4: '#ebb33f', +} + +class NetworkDisplay extends Component { + renderNetworkIcon () { + const { network } = this.props + const networkColor = networkToColorHash[network] + + return networkColor + ? h(NetworkDropdownIcon, { backgroundColor: networkColor }) + : h('i.fa.fa-question-circle.fa-med', { + style: { + margin: '0 4px', + color: 'rgb(125, 128, 130)', + }, + }) + } + + render () { + const { provider: { type } } = this.props + return h('.network-display__container', [ + this.renderNetworkIcon(), + h('.network-name', t(type)), + ]) + } +} + +NetworkDisplay.propTypes = { + network: PropTypes.string, + provider: PropTypes.object, +} + +const mapStateToProps = ({ metamask: { network, provider } }) => { + return { + network, + provider, + } +} + +module.exports = connect(mapStateToProps)(NetworkDisplay) diff --git a/ui/app/components/pending-tx/confirm-deploy-contract.js b/ui/app/components/pending-tx/confirm-deploy-contract.js index 4810bb515..b75f3a964 100644 --- a/ui/app/components/pending-tx/confirm-deploy-contract.js +++ b/ui/app/components/pending-tx/confirm-deploy-contract.js @@ -10,6 +10,7 @@ const hexToBn = require('../../../../app/scripts/lib/hex-to-bn') const { conversionUtil } = require('../../conversion-util') const t = require('../../../i18n') const SenderToRecipient = require('../sender-to-recipient') +const NetworkDisplay = require('../network-display') const { MIN_GAS_PRICE_HEX } = require('../send/send-constants') @@ -244,9 +245,12 @@ class ConfirmDeployContract extends Component { return ( h('.page-container', [ h('.page-container__header', [ - h('.page-container__back-button', { - onClick: () => backToAccountDetail(selectedAddress), - }, t('back')), + h('.page-container__header-row', [ + h('span.page-container__back-button', { + onClick: () => backToAccountDetail(selectedAddress), + }, t('back')), + window.METAMASK_UI_TYPE === 'notification' && h(NetworkDisplay), + ]), h('.page-container__title', t('confirmContract')), h('.page-container__subtitle', t('pleaseReviewTransaction')), ]), diff --git a/ui/app/components/pending-tx/confirm-send-ether.js b/ui/app/components/pending-tx/confirm-send-ether.js index f36def9d5..d1ce25cbf 100644 --- a/ui/app/components/pending-tx/confirm-send-ether.js +++ b/ui/app/components/pending-tx/confirm-send-ether.js @@ -4,7 +4,6 @@ const h = require('react-hyperscript') const inherits = require('util').inherits const actions = require('../../actions') const clone = require('clone') -const Identicon = require('../identicon') const ethUtil = require('ethereumjs-util') const BN = ethUtil.BN const hexToBn = require('../../../../app/scripts/lib/hex-to-bn') @@ -15,6 +14,8 @@ const { } = require('../../conversion-util') const GasFeeDisplay = require('../send/gas-fee-display-v2') const t = require('../../../i18n') +const SenderToRecipient = require('../sender-to-recipient') +const NetworkDisplay = require('../network-display') const { MIN_GAS_PRICE_HEX } = require('../send/send-constants') @@ -257,196 +258,181 @@ ConfirmSendEther.prototype.render = function () { this.inputs = [] return ( - h('div.confirm-screen-container.confirm-send-ether', [ - // Main Send token Card - h('div.page-container', [ - h('div.page-container__header', [ - !txMeta.lastGasPrice && h('button.confirm-screen-back-button', { + // Main Send token Card + h('.page-container', [ + h('.page-container__header', [ + h('.page-container__header-row', [ + h('span.page-container__back-button', { onClick: () => editTransaction(txMeta), + style: { + visibility: !txMeta.lastGasPrice ? 'initial' : 'hidden', + }, }, 'Edit'), - h('div.page-container__title', title), - h('div.page-container__subtitle', subtitle), + window.METAMASK_UI_TYPE === 'notification' && h(NetworkDisplay), + ]), + h('.page-container__title', title), + h('.page-container__subtitle', subtitle), + ]), + h('.page-container__content', [ + h(SenderToRecipient, { + senderName: fromName, + senderAddress: fromAddress, + recipientName: toName, + recipientAddress: txParams.to, + }), + + // 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('.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('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', [ 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('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', [ 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', [ 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', [ 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.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('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-section-column', [ - h('div.confirm-screen-row-info', `${totalInFIAT} ${currentCurrency.toUpperCase()}`), - h('div.confirm-screen-row-detail', `${totalInETH} 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('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')), - - // 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, + }, [ + h('.page-container__footer', [ + // Cancel Button + h('button.btn-cancel.page-container__footer-button.allcaps', { + onClick: (event) => { + clearSend() + this.cancel(event, txMeta) + }, + }, t('cancel')), + + // Accept Button + h('button.btn-confirm.page-container__footer-button.allcaps', [t('confirm')]), ]), ]), ]) diff --git a/ui/app/components/sender-to-recipient.js b/ui/app/components/sender-to-recipient.js index 25b9c7d6b..f35c353ad 100644 --- a/ui/app/components/sender-to-recipient.js +++ b/ui/app/components/sender-to-recipient.js @@ -5,6 +5,28 @@ const t = require('../../i18n') const Identicon = require('./identicon') class SenderToRecipient extends Component { + renderRecipientIcon () { + const { recipientAddress } = this.props + return ( + recipientAddress + ? h(Identicon, { address: recipientAddress, diameter: 20 }) + : h('i.fa.fa-file-text-o') + ) + } + + renderRecipient () { + const { recipientName } = this.props + return ( + h('.sender-to-recipient__recipient', [ + this.renderRecipientIcon(), + h( + '.sender-to-recipient__name.sender-to-recipient__recipient-name', + recipientName || t('newContract') + ), + ]) + ) + } + render () { const { senderName, senderAddress } = this.props @@ -28,10 +50,7 @@ class SenderToRecipient extends Component { }), ]), ]), - h('.sender-to-recipient__recipient', [ - h('i.fa.fa-file-text-o'), - h('.sender-to-recipient__name.sender-to-recipient__recipient-name', t('newContract')), - ]), + this.renderRecipient(), ]) ) } @@ -40,6 +59,8 @@ class SenderToRecipient extends Component { SenderToRecipient.propTypes = { senderName: PropTypes.string, senderAddress: PropTypes.string, + recipientName: PropTypes.string, + recipientAddress: PropTypes.string, } module.exports = SenderToRecipient -- cgit v1.2.3 From a69480d78d3a97310c7f39792133003b9bc058cb Mon Sep 17 00:00:00 2001 From: Dan J Miller Date: Tue, 20 Mar 2018 20:20:30 -0230 Subject: Gas inputs can be changed by up and down arrows (#3598) * Up and down arrows can control gas inputs. * input-number.js just uses number type. --- ui/app/components/currency-input.js | 2 ++ ui/app/components/input-number.js | 1 + 2 files changed, 3 insertions(+) (limited to 'ui/app/components') diff --git a/ui/app/components/currency-input.js b/ui/app/components/currency-input.js index 940238fa5..ece3eb43d 100644 --- a/ui/app/components/currency-input.js +++ b/ui/app/components/currency-input.js @@ -91,6 +91,7 @@ CurrencyInput.prototype.render = function () { placeholder, readOnly, inputRef, + type, } = this.props const { emptyState, focused } = this.state @@ -99,6 +100,7 @@ CurrencyInput.prototype.render = function () { const valueToRender = this.getValueToRender() return h('input', { className, + type, value: emptyState ? '' : valueToRender, placeholder: focused ? '' : placeholder, size: valueToRender.length * inputSizeMultiplier, diff --git a/ui/app/components/input-number.js b/ui/app/components/input-number.js index fd8c5c309..5600e35ee 100644 --- a/ui/app/components/input-number.js +++ b/ui/app/components/input-number.js @@ -55,6 +55,7 @@ InputNumber.prototype.render = function () { className: 'customize-gas-input', value, placeholder, + type: 'number', onInputChange: newValue => { this.setValue(newValue) }, -- cgit v1.2.3 From 3e79941658e58f5ef74cd9545c2b69136362ec76 Mon Sep 17 00:00:00 2001 From: kumavis Date: Wed, 21 Mar 2018 13:12:59 -0700 Subject: ui - tx conf - only show special token tx conf screen for token send --- ui/app/components/pending-tx/index.js | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'ui/app/components') diff --git a/ui/app/components/pending-tx/index.js b/ui/app/components/pending-tx/index.js index 9676e9c86..9c0453a3b 100644 --- a/ui/app/components/pending-tx/index.js +++ b/ui/app/components/pending-tx/index.js @@ -63,10 +63,14 @@ PendingTx.prototype.componentWillMount = async function () { isFetching: false, }) } - const tokenData = txParams && abiDecoder.decodeMethod(txParams.data) - const { name: tokenMethodName } = tokenData || {} - const isTokenTransaction = ['transfer', 'approve', 'transferFrom'] - .find(possibleName => tokenMethodName === possibleName) + + // inspect tx data for supported special confirmation screens + let isTokenTransaction = false + if (txParams.data) { + const tokenData = abiDecoder.decodeMethod(txParams.data) + const { name: tokenMethodName } = tokenData || {} + isTokenTransaction = (tokenMethodName === 'transfer') + } if (isTokenTransaction) { const token = util.getContractAtAddress(txParams.to) -- cgit v1.2.3