From 8b919758e51e16536b6edaf33d4978d551363249 Mon Sep 17 00:00:00 2001 From: Chi Kei Chan Date: Thu, 7 Sep 2017 04:24:03 -0700 Subject: Send Token screen partial UI --- ui/app/components/send-token/index.js | 213 ++++++++++++++++++++++++++++++++++ 1 file changed, 213 insertions(+) create mode 100644 ui/app/components/send-token/index.js (limited to 'ui/app/components/send-token/index.js') diff --git a/ui/app/components/send-token/index.js b/ui/app/components/send-token/index.js new file mode 100644 index 000000000..a49e559dc --- /dev/null +++ b/ui/app/components/send-token/index.js @@ -0,0 +1,213 @@ +const Component = require('react').Component +const connect = require('react-redux').connect +const h = require('react-hyperscript') +const ethUtil = require('ethereumjs-util') +const inherits = require('util').inherits +const actions = require('../../actions') +const selectors = require('../../selectors') + +// const BalanceComponent = require('./balance-component') +const Identicon = require('../identicon') +const TokenBalance = require('../token-balance') +const CurrencyToggle = require('../send/currency-toggle') +const GasTooltip = require('../send/gas-tooltip') +const GasFeeDisplay = require('../send/gas-fee-display') + + +module.exports = connect(mapStateToProps, mapDispatchToProps)(SendTokenScreen) + +function mapStateToProps (state) { + // const sidebarOpen = state.appState.sidebarOpen + + const identities = state.metamask.identities + const addressBook = state.metamask.addressBook + const conversionRate = state.metamask.conversionRate + const currentBlockGasLimit = state.metamask.currentBlockGasLimit + // const accounts = state.metamask.accounts + // const network = state.metamask.network + const selectedTokenAddress = state.metamask.selectedTokenAddress + // const selectedAddress = state.metamask.selectedAddress || Object.keys(accounts)[0] + // const checksumAddress = selectedAddress && ethUtil.toChecksumAddress(selectedAddress) + // const identity = identities[selectedAddress] + + return { + // sidebarOpen, + // selectedAddress, + // checksumAddress, + selectedTokenAddress, + identities, + addressBook, + conversionRate, + currentBlockGasLimit, + selectedToken: selectors.getSelectedToken(state), + // selectedToken: selectors.getSelectedToken(state), + // identity, + // network, + } +} + +function mapDispatchToProps (dispatch) { + return { + // showSidebar: () => { dispatch(actions.showSidebar()) }, + // hideSidebar: () => { dispatch(actions.hideSidebar()) }, + // showModal: (payload) => { dispatch(actions.showModal(payload)) }, + // showSendPage: () => { dispatch(actions.showSendPage()) }, + // showSendTokenPage: () => { dispatch(actions.showSendTokenPage()) }, + } +} + +inherits(SendTokenScreen, Component) +function SendTokenScreen () { + Component.call(this) + this.state = { + to: '', + selectedCurrency: 'USD', + isGasTooltipOpen: false, + gasPrice: '0x5d21dba00', + gasLimit: '0x7b0d', + } +} + +SendTokenScreen.prototype.renderToAddressInput = function () { + const { + identities, + addressBook, + } = this.props + + const { + to, + } = this.state + + return h('div.send-screen-input-wrapper', {}, [ + h('div', ['To:']), + h('input.large-input.send-screen-input', { + name: 'address', + list: 'addresses', + placeholder: 'Address', + value: to, + onChange: e => this.setState({ to: e.target.value }), + }), + h('datalist#addresses', [ + // Corresponds to the addresses owned. + Object.entries(identities).map(([key, { address, name }]) => { + return h('option', { + value: address, + label: name, + key: address, + }) + }), + addressBook.map(({ address, name }) => { + return h('option', { + value: address, + label: name, + key: address, + }) + }), + ]), + ]) +} + +SendTokenScreen.prototype.renderAmountInput = function () { + const { + selectedCurrency, + } = this.state + + const { + selectedToken: {symbol}, + } = this.props + + return h('div.send-screen-input-wrapper', {}, [ + h('div.send-screen-amount-labels', [ + h('span', ['Amount']), + h(CurrencyToggle, { + selectedCurrency, + onClick: currency => this.setState({ selectedCurrency: currency }), + }), + ]), + h('input.large-input.send-screen-input', { + placeholder: `0 ${symbol}`, + type: 'number', + onChange: e => this.setState({ amount: e.target.value }), + }), + ]) +} + +SendTokenScreen.prototype.renderGasInput = function () { + const { + isGasTooltipOpen, + gasPrice, + gasLimit, + selectedCurrency, + } = this.state + + const { + conversionRate, + currentBlockGasLimit, + } = this.props + + return h('div.send-screen-input-wrapper', [ + isGasTooltipOpen && h(GasTooltip, { + className: 'send-tooltip', + gasPrice, + gasLimit, + onClose: () => this.setState({ isGasTooltipOpen: false }), + onFeeChange: ({ gasLimit, gasPrice }) => { + this.setState({ gasLimit, gasPrice }) + }, + }), + + h('div.send-screen-gas-labels', {}, [ + h('span', [ h('i.fa.fa-bolt'), 'Gas fee:']), + h('span', ['What\'s this?']), + ]), + h('div.large-input.send-screen-gas-input', [ + h(GasFeeDisplay, { + conversionRate, + gasPrice, + currentCurrency: selectedCurrency, + gas: gasLimit, + blockGasLimit: currentBlockGasLimit, + }), + h( + 'div.send-screen-gas-input-customize', + { onClick: () => this.setState({ isGasTooltipOpen: !isGasTooltipOpen }) }, + ['Customize'] + ), + ]), + ]) +} + +SendTokenScreen.prototype.renderMemoInput = function () { + return h('div.send-screen-input-wrapper', {}, [ + h('div', {}, ['Transaction memo (optional)']), + h( + 'input.large-input.send-screen-input', + { onChange: e => this.setState({ memo: e.target.value }) } + ), + ]) +} + +SendTokenScreen.prototype.render = function () { + const { + selectedTokenAddress, + selectedToken, + } = this.props + + return h('div.send-token', [ + h(Identicon, { + diameter: 75, + address: selectedTokenAddress, + }), + h('div.send-token__title', ['Send Tokens']), + h('div.send-token__description', ['Send Tokens to anyone with an Ethereum account']), + h('div.send-token__balance-text', ['Your Token Balance is:']), + h('div.send-token__token-balance', [ + h(TokenBalance, { token: selectedToken, balanceOnly: true }), + ]), + h('div.send-token__token-symbol', [selectedToken.symbol]), + this.renderToAddressInput(), + this.renderAmountInput(), + this.renderGasInput(), + this.renderMemoInput(), + ]) +} -- cgit v1.2.3 From 062e67bff83fd79647231be6e2448d35b5f312f9 Mon Sep 17 00:00:00 2001 From: Chi Kei Chan Date: Mon, 11 Sep 2017 22:14:09 -0700 Subject: Add buttons; handle back; add yarn.lock --- ui/app/components/send-token/index.js | 54 +++++++++++++++++++++++------------ 1 file changed, 36 insertions(+), 18 deletions(-) (limited to 'ui/app/components/send-token/index.js') diff --git a/ui/app/components/send-token/index.js b/ui/app/components/send-token/index.js index a49e559dc..985116409 100644 --- a/ui/app/components/send-token/index.js +++ b/ui/app/components/send-token/index.js @@ -23,16 +23,16 @@ function mapStateToProps (state) { const addressBook = state.metamask.addressBook const conversionRate = state.metamask.conversionRate const currentBlockGasLimit = state.metamask.currentBlockGasLimit - // const accounts = state.metamask.accounts + const accounts = state.metamask.accounts // const network = state.metamask.network const selectedTokenAddress = state.metamask.selectedTokenAddress - // const selectedAddress = state.metamask.selectedAddress || Object.keys(accounts)[0] + const selectedAddress = state.metamask.selectedAddress || Object.keys(accounts)[0] // const checksumAddress = selectedAddress && ethUtil.toChecksumAddress(selectedAddress) // const identity = identities[selectedAddress] return { // sidebarOpen, - // selectedAddress, + selectedAddress, // checksumAddress, selectedTokenAddress, identities, @@ -48,6 +48,7 @@ function mapStateToProps (state) { function mapDispatchToProps (dispatch) { return { + backToAccountDetail: address => dispatch(actions.backToAccountDetail(address)), // showSidebar: () => { dispatch(actions.showSidebar()) }, // hideSidebar: () => { dispatch(actions.hideSidebar()) }, // showModal: (payload) => { dispatch(actions.showModal(payload)) }, @@ -121,6 +122,7 @@ SendTokenScreen.prototype.renderAmountInput = function () { h('span', ['Amount']), h(CurrencyToggle, { selectedCurrency, + currencies: [ symbol, 'USD' ], onClick: currency => this.setState({ selectedCurrency: currency }), }), ]), @@ -178,7 +180,7 @@ SendTokenScreen.prototype.renderGasInput = function () { } SendTokenScreen.prototype.renderMemoInput = function () { - return h('div.send-screen-input-wrapper', {}, [ + return h('div.send-screen-input-wrapper', [ h('div', {}, ['Transaction memo (optional)']), h( 'input.large-input.send-screen-input', @@ -187,6 +189,19 @@ SendTokenScreen.prototype.renderMemoInput = function () { ]) } +SendTokenScreen.prototype.renderButtons = function () { + const { selectedAddress, backToAccountDetail } = this.props + + return h('div.send-token__button-group', [ + h('button.send-token__button-next.btn-secondary', { + + }, ['Next']), + h('button.send-token__button-cancel.btn-tertiary', { + onClick: () => backToAccountDetail(selectedAddress), + }, ['Cancel']), + ]) +} + SendTokenScreen.prototype.render = function () { const { selectedTokenAddress, @@ -194,20 +209,23 @@ SendTokenScreen.prototype.render = function () { } = this.props return h('div.send-token', [ - h(Identicon, { - diameter: 75, - address: selectedTokenAddress, - }), - h('div.send-token__title', ['Send Tokens']), - h('div.send-token__description', ['Send Tokens to anyone with an Ethereum account']), - h('div.send-token__balance-text', ['Your Token Balance is:']), - h('div.send-token__token-balance', [ - h(TokenBalance, { token: selectedToken, balanceOnly: true }), + h('div.send-token__content', [ + h(Identicon, { + diameter: 75, + address: selectedTokenAddress, + }), + h('div.send-token__title', ['Send Tokens']), + h('div.send-token__description', ['Send Tokens to anyone with an Ethereum account']), + h('div.send-token__balance-text', ['Your Token Balance is:']), + h('div.send-token__token-balance', [ + h(TokenBalance, { token: selectedToken, balanceOnly: true }), + ]), + h('div.send-token__token-symbol', [selectedToken.symbol]), + this.renderToAddressInput(), + this.renderAmountInput(), + this.renderGasInput(), + this.renderMemoInput(), ]), - h('div.send-token__token-symbol', [selectedToken.symbol]), - this.renderToAddressInput(), - this.renderAmountInput(), - this.renderGasInput(), - this.renderMemoInput(), + this.renderButtons(), ]) } -- cgit v1.2.3 From 836bf2e1a38bb6917f1b7fe9db0604c8143c7adf Mon Sep 17 00:00:00 2001 From: Chi Kei Chan Date: Mon, 11 Sep 2017 23:18:54 -0700 Subject: Add frontend validation to send-token --- ui/app/components/send-token/index.js | 98 ++++++++++++++++++++++++++++++++--- 1 file changed, 90 insertions(+), 8 deletions(-) (limited to 'ui/app/components/send-token/index.js') diff --git a/ui/app/components/send-token/index.js b/ui/app/components/send-token/index.js index 985116409..439ea45b7 100644 --- a/ui/app/components/send-token/index.js +++ b/ui/app/components/send-token/index.js @@ -2,6 +2,7 @@ const Component = require('react').Component const connect = require('react-redux').connect const h = require('react-hyperscript') const ethUtil = require('ethereumjs-util') +const classnames = require('classnames') const inherits = require('util').inherits const actions = require('../../actions') const selectors = require('../../selectors') @@ -62,10 +63,60 @@ function SendTokenScreen () { Component.call(this) this.state = { to: '', + amount: null, selectedCurrency: 'USD', isGasTooltipOpen: false, gasPrice: '0x5d21dba00', gasLimit: '0x7b0d', + errors: {}, + } +} + +SendTokenScreen.prototype.validate = function () { + const { + to, + amount, + gasPrice: hexGasPrice, + gasLimit: hexGasLimit, + } = this.state + + const gasPrice = parseInt(hexGasPrice, 16) + const gasLimit = parseInt(hexGasLimit, 16) / 1000000000 + + if (to && amount && gasPrice && gasLimit) { + return { + isValid: true, + errors: {}, + } + } + + const errors = { + to: !to ? 'Required' : null, + amount: !Number(amount) ? 'Required' : null, + gasPrice: !gasPrice ? 'Gas Price Required' : null, + gasLimit: !gasLimit ? 'Gas Limit Required' : null, + } + + return { + isValid: false, + errors, + } +} + +SendTokenScreen.prototype.submit = function () { + // const { + // to, + // amount, + // selectedCurrency, + // isGasTooltipOpen, + // gasPrice, + // gasLimit, + // } = this.state + + const { isValid, errors } = this.validate() + + if (!isValid) { + return this.setState({ errors }) } } @@ -77,16 +128,24 @@ SendTokenScreen.prototype.renderToAddressInput = function () { const { to, + errors: { to: errorMessage }, } = this.state - return h('div.send-screen-input-wrapper', {}, [ + return h('div', { + className: classnames('send-screen-input-wrapper', { + 'send-screen-input-wrapper--error': errorMessage, + }), + }, [ h('div', ['To:']), h('input.large-input.send-screen-input', { name: 'address', list: 'addresses', placeholder: 'Address', value: to, - onChange: e => this.setState({ to: e.target.value }), + onChange: e => this.setState({ + to: e.target.value, + errors: {}, + }), }), h('datalist#addresses', [ // Corresponds to the addresses owned. @@ -105,23 +164,30 @@ SendTokenScreen.prototype.renderToAddressInput = function () { }) }), ]), + h('div.send-screen-input-wrapper__error-message', [ errorMessage ]), ]) } SendTokenScreen.prototype.renderAmountInput = function () { const { selectedCurrency, + amount, + errors: { amount: errorMessage }, } = this.state const { selectedToken: {symbol}, } = this.props - return h('div.send-screen-input-wrapper', {}, [ + return h('div.send-screen-input-wrapper', { + className: classnames('send-screen-input-wrapper', { + 'send-screen-input-wrapper--error': errorMessage, + }), + }, [ h('div.send-screen-amount-labels', [ h('span', ['Amount']), h(CurrencyToggle, { - selectedCurrency, + currentCurrency: selectedCurrency, currencies: [ symbol, 'USD' ], onClick: currency => this.setState({ selectedCurrency: currency }), }), @@ -129,8 +195,13 @@ SendTokenScreen.prototype.renderAmountInput = function () { h('input.large-input.send-screen-input', { placeholder: `0 ${symbol}`, type: 'number', - onChange: e => this.setState({ amount: e.target.value }), + value: amount, + onChange: e => this.setState({ + amount: e.target.value, + errors: {}, + }), }), + h('div.send-screen-input-wrapper__error-message', [ errorMessage ]), ]) } @@ -140,6 +211,10 @@ SendTokenScreen.prototype.renderGasInput = function () { gasPrice, gasLimit, selectedCurrency, + errors: { + gasPrice: gasPriceErrorMessage, + gasLimit: gasLimitErrorMessage, + }, } = this.state const { @@ -147,14 +222,18 @@ SendTokenScreen.prototype.renderGasInput = function () { currentBlockGasLimit, } = this.props - return h('div.send-screen-input-wrapper', [ + return h('div.send-screen-input-wrapper', { + className: classnames('send-screen-input-wrapper', { + 'send-screen-input-wrapper--error': gasPriceErrorMessage || gasLimitErrorMessage, + }), + }, [ isGasTooltipOpen && h(GasTooltip, { className: 'send-tooltip', gasPrice, gasLimit, onClose: () => this.setState({ isGasTooltipOpen: false }), onFeeChange: ({ gasLimit, gasPrice }) => { - this.setState({ gasLimit, gasPrice }) + this.setState({ gasLimit, gasPrice, errors: {} }) }, }), @@ -176,6 +255,9 @@ SendTokenScreen.prototype.renderGasInput = function () { ['Customize'] ), ]), + h('div.send-screen-input-wrapper__error-message', [ + gasPriceErrorMessage || gasLimitErrorMessage, + ]), ]) } @@ -194,7 +276,7 @@ SendTokenScreen.prototype.renderButtons = function () { return h('div.send-token__button-group', [ h('button.send-token__button-next.btn-secondary', { - + onClick: () => this.submit(), }, ['Next']), h('button.send-token__button-cancel.btn-tertiary', { onClick: () => backToAccountDetail(selectedAddress), -- cgit v1.2.3 From 7eb6dae4185d083ebb967256fdd09203b5092480 Mon Sep 17 00:00:00 2001 From: Chi Kei Chan Date: Tue, 12 Sep 2017 02:22:23 -0700 Subject: Added signTokenTx; Adding token confirmation screen --- ui/app/components/send-token/index.js | 52 +++++++++++++++++++++++++++-------- 1 file changed, 41 insertions(+), 11 deletions(-) (limited to 'ui/app/components/send-token/index.js') diff --git a/ui/app/components/send-token/index.js b/ui/app/components/send-token/index.js index 439ea45b7..8c02ec45d 100644 --- a/ui/app/components/send-token/index.js +++ b/ui/app/components/send-token/index.js @@ -1,7 +1,7 @@ const Component = require('react').Component const connect = require('react-redux').connect const h = require('react-hyperscript') -const ethUtil = require('ethereumjs-util') +const { addHexPrefix } = require('ethereumjs-util') const classnames = require('classnames') const inherits = require('util').inherits const actions = require('../../actions') @@ -50,6 +50,14 @@ function mapStateToProps (state) { function mapDispatchToProps (dispatch) { return { backToAccountDetail: address => dispatch(actions.backToAccountDetail(address)), + hideWarning: () => dispatch(actions.hideWarning()), + addToAddressBook: (recipient, nickname) => dispatch( + actions.addToAddressBook(recipient, nickname) + ), + signTx: txParams => dispatch(actions.signTx(txParams)), + signTokenTx: (tokenAddress, toAddress, amount, txData) => ( + dispatch(actions.signTokenTx(tokenAddress, toAddress, amount, txData)) + ), // showSidebar: () => { dispatch(actions.showSidebar()) }, // hideSidebar: () => { dispatch(actions.hideSidebar()) }, // showModal: (payload) => { dispatch(actions.showModal(payload)) }, @@ -75,13 +83,14 @@ function SendTokenScreen () { SendTokenScreen.prototype.validate = function () { const { to, - amount, + amount: stringAmount, gasPrice: hexGasPrice, gasLimit: hexGasLimit, } = this.state const gasPrice = parseInt(hexGasPrice, 16) const gasLimit = parseInt(hexGasLimit, 16) / 1000000000 + const amount = Number(stringAmount) if (to && amount && gasPrice && gasLimit) { return { @@ -92,7 +101,7 @@ SendTokenScreen.prototype.validate = function () { const errors = { to: !to ? 'Required' : null, - amount: !Number(amount) ? 'Required' : null, + amount: !amount ? 'Required' : null, gasPrice: !gasPrice ? 'Gas Price Required' : null, gasLimit: !gasLimit ? 'Gas Limit Required' : null, } @@ -104,20 +113,41 @@ SendTokenScreen.prototype.validate = function () { } SendTokenScreen.prototype.submit = function () { - // const { - // to, - // amount, - // selectedCurrency, - // isGasTooltipOpen, - // gasPrice, - // gasLimit, - // } = this.state + const { + to, + amount, + gasPrice, + gasLimit, + } = this.state + + const { + identities, + selectedAddress, + selectedTokenAddress, + hideWarning, + addToAddressBook, + signTokenTx, + } = this.props + + const { nickname = ' ' } = identities[to] || {} const { isValid, errors } = this.validate() if (!isValid) { return this.setState({ errors }) } + + hideWarning() + addToAddressBook(to, nickname) + + const txParams = { + from: selectedAddress, + value: '0', + gas: gasLimit, + gasPrice: gasPrice, + } + + signTokenTx(selectedTokenAddress, to, Number(amount).toString(16), txParams) } SendTokenScreen.prototype.renderToAddressInput = function () { -- cgit v1.2.3 From 8f31b05ac5b7d8383c720b8b0c9f7f3cecc937f5 Mon Sep 17 00:00:00 2001 From: Chi Kei Chan Date: Wed, 13 Sep 2017 01:25:39 -0700 Subject: Add token exchange rates --- ui/app/components/send-token/index.js | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) (limited to 'ui/app/components/send-token/index.js') diff --git a/ui/app/components/send-token/index.js b/ui/app/components/send-token/index.js index 8c02ec45d..851d463eb 100644 --- a/ui/app/components/send-token/index.js +++ b/ui/app/components/send-token/index.js @@ -28,9 +28,12 @@ function mapStateToProps (state) { // const network = state.metamask.network const selectedTokenAddress = state.metamask.selectedTokenAddress const selectedAddress = state.metamask.selectedAddress || Object.keys(accounts)[0] + const selectedToken = selectors.getSelectedToken(state) + const tokenExchangeRates = state.metamask.tokenExchangeRates + const pair = `${selectedToken.symbol.toLowerCase()}_eth` + const { rate: tokenExchangeRate = 0 } = tokenExchangeRates[pair] || {} // const checksumAddress = selectedAddress && ethUtil.toChecksumAddress(selectedAddress) // const identity = identities[selectedAddress] - return { // sidebarOpen, selectedAddress, @@ -39,8 +42,9 @@ function mapStateToProps (state) { identities, addressBook, conversionRate, + tokenExchangeRate, currentBlockGasLimit, - selectedToken: selectors.getSelectedToken(state), + selectedToken, // selectedToken: selectors.getSelectedToken(state), // identity, // network, @@ -58,6 +62,7 @@ function mapDispatchToProps (dispatch) { signTokenTx: (tokenAddress, toAddress, amount, txData) => ( dispatch(actions.signTokenTx(tokenAddress, toAddress, amount, txData)) ), + updateTokenExchangeRate: token => dispatch(actions.updateTokenExchangeRate(token)), // showSidebar: () => { dispatch(actions.showSidebar()) }, // hideSidebar: () => { dispatch(actions.hideSidebar()) }, // showModal: (payload) => { dispatch(actions.showModal(payload)) }, @@ -71,7 +76,7 @@ function SendTokenScreen () { Component.call(this) this.state = { to: '', - amount: null, + amount: '', selectedCurrency: 'USD', isGasTooltipOpen: false, gasPrice: '0x5d21dba00', @@ -80,6 +85,15 @@ function SendTokenScreen () { } } +SendTokenScreen.prototype.componentWillMount = function () { + const { + updateTokenExchangeRate, + selectedToken: { symbol }, + } = this.props + + updateTokenExchangeRate(symbol) +} + SendTokenScreen.prototype.validate = function () { const { to, @@ -206,6 +220,7 @@ SendTokenScreen.prototype.renderAmountInput = function () { } = this.state const { + tokenExchangeRate, selectedToken: {symbol}, } = this.props @@ -217,8 +232,8 @@ SendTokenScreen.prototype.renderAmountInput = function () { h('div.send-screen-amount-labels', [ h('span', ['Amount']), h(CurrencyToggle, { - currentCurrency: selectedCurrency, - currencies: [ symbol, 'USD' ], + currentCurrency: tokenExchangeRate ? selectedCurrency : 'USD', + currencies: tokenExchangeRate ? [ symbol, 'USD' ] : [], onClick: currency => this.setState({ selectedCurrency: currency }), }), ]), @@ -249,6 +264,7 @@ SendTokenScreen.prototype.renderGasInput = function () { const { conversionRate, + tokenExchangeRate, currentBlockGasLimit, } = this.props @@ -274,6 +290,7 @@ SendTokenScreen.prototype.renderGasInput = function () { h('div.large-input.send-screen-gas-input', [ h(GasFeeDisplay, { conversionRate, + tokenExchangeRate, gasPrice, currentCurrency: selectedCurrency, gas: gasLimit, -- cgit v1.2.3 From d722c1045f70954cb1a97de52cae5084a6f14815 Mon Sep 17 00:00:00 2001 From: Chi Kei Chan Date: Wed, 13 Sep 2017 19:57:33 -0700 Subject: Update yarn.lock; Fix tx-list-item overflow; Fix gas exchange rate --- ui/app/components/send-token/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'ui/app/components/send-token/index.js') diff --git a/ui/app/components/send-token/index.js b/ui/app/components/send-token/index.js index 851d463eb..a3332ca9e 100644 --- a/ui/app/components/send-token/index.js +++ b/ui/app/components/send-token/index.js @@ -292,7 +292,7 @@ SendTokenScreen.prototype.renderGasInput = function () { conversionRate, tokenExchangeRate, gasPrice, - currentCurrency: selectedCurrency, + activeCurrency: selectedCurrency, gas: gasLimit, blockGasLimit: currentBlockGasLimit, }), -- cgit v1.2.3 From 93a1089e085cb70ddbd58721a140ab8d3b6b79eb Mon Sep 17 00:00:00 2001 From: Chi Kei Chan Date: Thu, 14 Sep 2017 01:09:57 -0700 Subject: Show token tx properly --- ui/app/components/send-token/index.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'ui/app/components/send-token/index.js') diff --git a/ui/app/components/send-token/index.js b/ui/app/components/send-token/index.js index a3332ca9e..72fb593be 100644 --- a/ui/app/components/send-token/index.js +++ b/ui/app/components/send-token/index.js @@ -141,6 +141,7 @@ SendTokenScreen.prototype.submit = function () { hideWarning, addToAddressBook, signTokenTx, + selectedToken, } = this.props const { nickname = ' ' } = identities[to] || {} @@ -161,7 +162,11 @@ SendTokenScreen.prototype.submit = function () { gasPrice: gasPrice, } - signTokenTx(selectedTokenAddress, to, Number(amount).toString(16), txParams) + const { decimals } = selectedToken || {} + const multiplier = Math.pow(10, Number(decimals || 0)) + const sendAmount = Number(amount * multiplier).toString(16) + + signTokenTx(selectedTokenAddress, to, sendAmount, txParams) } SendTokenScreen.prototype.renderToAddressInput = function () { -- cgit v1.2.3 From 97810acb5355be575914a2e1e57a1cacd9fbccfa Mon Sep 17 00:00:00 2001 From: Dan Date: Wed, 20 Sep 2017 20:34:03 -0230 Subject: Handles errors with to field and renders warnings from backend in send token. --- ui/app/components/send-token/index.js | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) (limited to 'ui/app/components/send-token/index.js') diff --git a/ui/app/components/send-token/index.js b/ui/app/components/send-token/index.js index 72fb593be..7adbf48dc 100644 --- a/ui/app/components/send-token/index.js +++ b/ui/app/components/send-token/index.js @@ -6,6 +6,7 @@ const classnames = require('classnames') const inherits = require('util').inherits const actions = require('../../actions') const selectors = require('../../selectors') +const { isValidAddress } = require('../../util') // const BalanceComponent = require('./balance-component') const Identicon = require('../identicon') @@ -14,12 +15,12 @@ const CurrencyToggle = require('../send/currency-toggle') const GasTooltip = require('../send/gas-tooltip') const GasFeeDisplay = require('../send/gas-fee-display') - module.exports = connect(mapStateToProps, mapDispatchToProps)(SendTokenScreen) function mapStateToProps (state) { // const sidebarOpen = state.appState.sidebarOpen + const { warning } = state.appState const identities = state.metamask.identities const addressBook = state.metamask.addressBook const conversionRate = state.metamask.conversionRate @@ -34,6 +35,7 @@ function mapStateToProps (state) { const { rate: tokenExchangeRate = 0 } = tokenExchangeRates[pair] || {} // const checksumAddress = selectedAddress && ethUtil.toChecksumAddress(selectedAddress) // const identity = identities[selectedAddress] + return { // sidebarOpen, selectedAddress, @@ -45,6 +47,7 @@ function mapStateToProps (state) { tokenExchangeRate, currentBlockGasLimit, selectedToken, + warning, // selectedToken: selectors.getSelectedToken(state), // identity, // network, @@ -106,13 +109,6 @@ SendTokenScreen.prototype.validate = function () { const gasLimit = parseInt(hexGasLimit, 16) / 1000000000 const amount = Number(stringAmount) - if (to && amount && gasPrice && gasLimit) { - return { - isValid: true, - errors: {}, - } - } - const errors = { to: !to ? 'Required' : null, amount: !amount ? 'Required' : null, @@ -120,9 +116,14 @@ SendTokenScreen.prototype.validate = function () { gasLimit: !gasLimit ? 'Gas Limit Required' : null, } + if(to && !isValidAddress(to)) { + errors.to = 'Invalid address' + } + + const isValid = Object.entries(errors).every(([key, value]) => value === null) return { - isValid: false, - errors, + isValid, + errors: isValid ? {} : errors, } } @@ -145,7 +146,6 @@ SendTokenScreen.prototype.submit = function () { } = this.props const { nickname = ' ' } = identities[to] || {} - const { isValid, errors } = this.validate() if (!isValid) { @@ -340,6 +340,7 @@ SendTokenScreen.prototype.render = function () { const { selectedTokenAddress, selectedToken, + warning, } = this.props return h('div.send-token', [ @@ -359,6 +360,11 @@ SendTokenScreen.prototype.render = function () { this.renderAmountInput(), this.renderGasInput(), this.renderMemoInput(), + warning && h('div.send-screen-input-wrapper--error', {}, + h('div.send-screen-input-wrapper__error-message', [ + warning, + ]) + ), ]), this.renderButtons(), ]) -- cgit v1.2.3 From e1077836ce916e2bd788451e3f365324024a1c0c Mon Sep 17 00:00:00 2001 From: Chi Kei Chan Date: Fri, 22 Sep 2017 14:34:56 -0700 Subject: Add Confirm Send token screen --- ui/app/components/send-token/index.js | 18 ++---------------- 1 file changed, 2 insertions(+), 16 deletions(-) (limited to 'ui/app/components/send-token/index.js') diff --git a/ui/app/components/send-token/index.js b/ui/app/components/send-token/index.js index 7adbf48dc..dd8ca6b9d 100644 --- a/ui/app/components/send-token/index.js +++ b/ui/app/components/send-token/index.js @@ -1,7 +1,6 @@ const Component = require('react').Component const connect = require('react-redux').connect const h = require('react-hyperscript') -const { addHexPrefix } = require('ethereumjs-util') const classnames = require('classnames') const inherits = require('util').inherits const actions = require('../../actions') @@ -26,20 +25,15 @@ function mapStateToProps (state) { const conversionRate = state.metamask.conversionRate const currentBlockGasLimit = state.metamask.currentBlockGasLimit const accounts = state.metamask.accounts - // const network = state.metamask.network const selectedTokenAddress = state.metamask.selectedTokenAddress const selectedAddress = state.metamask.selectedAddress || Object.keys(accounts)[0] const selectedToken = selectors.getSelectedToken(state) const tokenExchangeRates = state.metamask.tokenExchangeRates const pair = `${selectedToken.symbol.toLowerCase()}_eth` const { rate: tokenExchangeRate = 0 } = tokenExchangeRates[pair] || {} - // const checksumAddress = selectedAddress && ethUtil.toChecksumAddress(selectedAddress) - // const identity = identities[selectedAddress] return { - // sidebarOpen, selectedAddress, - // checksumAddress, selectedTokenAddress, identities, addressBook, @@ -48,9 +42,6 @@ function mapStateToProps (state) { currentBlockGasLimit, selectedToken, warning, - // selectedToken: selectors.getSelectedToken(state), - // identity, - // network, } } @@ -66,11 +57,6 @@ function mapDispatchToProps (dispatch) { dispatch(actions.signTokenTx(tokenAddress, toAddress, amount, txData)) ), updateTokenExchangeRate: token => dispatch(actions.updateTokenExchangeRate(token)), - // showSidebar: () => { dispatch(actions.showSidebar()) }, - // hideSidebar: () => { dispatch(actions.hideSidebar()) }, - // showModal: (payload) => { dispatch(actions.showModal(payload)) }, - // showSendPage: () => { dispatch(actions.showSendPage()) }, - // showSendTokenPage: () => { dispatch(actions.showSendTokenPage()) }, } } @@ -116,7 +102,7 @@ SendTokenScreen.prototype.validate = function () { gasLimit: !gasLimit ? 'Gas Limit Required' : null, } - if(to && !isValidAddress(to)) { + if (to && !isValidAddress(to)) { errors.to = 'Invalid address' } @@ -360,7 +346,7 @@ SendTokenScreen.prototype.render = function () { this.renderAmountInput(), this.renderGasInput(), this.renderMemoInput(), - warning && h('div.send-screen-input-wrapper--error', {}, + warning && h('div.send-screen-input-wrapper--error', h('div.send-screen-input-wrapper__error-message', [ warning, ]) -- cgit v1.2.3 From 171d38c8dbbe78c206e57c5d838ab672ef61f23b Mon Sep 17 00:00:00 2001 From: Dan Date: Wed, 20 Sep 2017 20:34:03 -0230 Subject: Handles errors with to field and renders warnings from backend in send token. --- ui/app/components/send-token/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'ui/app/components/send-token/index.js') diff --git a/ui/app/components/send-token/index.js b/ui/app/components/send-token/index.js index dd8ca6b9d..8dd277f1d 100644 --- a/ui/app/components/send-token/index.js +++ b/ui/app/components/send-token/index.js @@ -346,7 +346,7 @@ SendTokenScreen.prototype.render = function () { this.renderAmountInput(), this.renderGasInput(), this.renderMemoInput(), - warning && h('div.send-screen-input-wrapper--error', + warning && h('div.send-screen-input-wrapper--error', {}, h('div.send-screen-input-wrapper__error-message', [ warning, ]) -- cgit v1.2.3 From a1d87b821b7e0a444257065d284b13f98e4d3173 Mon Sep 17 00:00:00 2001 From: Dan Date: Mon, 25 Sep 2017 21:45:51 -0230 Subject: Update send token to handle errors onBlur events and prevent clicking send until all errors handled --- ui/app/components/send-token/index.js | 71 +++++++++++++++++++++++++++++------ 1 file changed, 59 insertions(+), 12 deletions(-) (limited to 'ui/app/components/send-token/index.js') diff --git a/ui/app/components/send-token/index.js b/ui/app/components/send-token/index.js index 8dd277f1d..166088898 100644 --- a/ui/app/components/send-token/index.js +++ b/ui/app/components/send-token/index.js @@ -5,7 +5,7 @@ const classnames = require('classnames') const inherits = require('util').inherits const actions = require('../../actions') const selectors = require('../../selectors') -const { isValidAddress } = require('../../util') +const { isValidAddress, allNull } = require('../../util') // const BalanceComponent = require('./balance-component') const Identicon = require('../identicon') @@ -65,7 +65,8 @@ function SendTokenScreen () { Component.call(this) this.state = { to: '', - amount: '', + amount: '0x0', + amountToSend: '0x0', selectedCurrency: 'USD', isGasTooltipOpen: false, gasPrice: '0x5d21dba00', @@ -113,6 +114,46 @@ SendTokenScreen.prototype.validate = function () { } } +SendTokenScreen.prototype.setErrorsFor = function (field) { + const { balance, selectedToken } = this.props + const { errors: previousErrors } = this.state + + const { + isValid, + errors: newErrors + } = this.validate() + + const nextErrors = Object.assign({}, previousErrors, { + [field]: newErrors[field] || null + }) + + if (!isValid) { + this.setState({ + errors: nextErrors, + isValid, + }) + } +} + +SendTokenScreen.prototype.clearErrorsFor = function (field) { + const { errors: previousErrors } = this.state + const nextErrors = Object.assign({}, previousErrors, { + [field]: null + }) + + this.setState({ + errors: nextErrors, + isValid: allNull(nextErrors), + }) +} + +SendTokenScreen.prototype.getAmountToSend = function (amount, selectedToken) { + const { decimals } = selectedToken || {} + const multiplier = Math.pow(10, Number(decimals || 0)) + const sendAmount = Number(amount * multiplier).toString(16) + return sendAmount +} + SendTokenScreen.prototype.submit = function () { const { to, @@ -132,11 +173,6 @@ SendTokenScreen.prototype.submit = function () { } = this.props const { nickname = ' ' } = identities[to] || {} - const { isValid, errors } = this.validate() - - if (!isValid) { - return this.setState({ errors }) - } hideWarning() addToAddressBook(to, nickname) @@ -148,9 +184,7 @@ SendTokenScreen.prototype.submit = function () { gasPrice: gasPrice, } - const { decimals } = selectedToken || {} - const multiplier = Math.pow(10, Number(decimals || 0)) - const sendAmount = Number(amount * multiplier).toString(16) + const sendAmount = this.getAmountToSend(amount, selectedToken) signTokenTx(selectedTokenAddress, to, sendAmount, txParams) } @@ -181,6 +215,8 @@ SendTokenScreen.prototype.renderToAddressInput = function () { to: e.target.value, errors: {}, }), + onBlur: () => this.setErrorsFor('to'), + onFocus: () => this.clearErrorsFor('to'), }), h('datalist#addresses', [ // Corresponds to the addresses owned. @@ -234,8 +270,9 @@ SendTokenScreen.prototype.renderAmountInput = function () { value: amount, onChange: e => this.setState({ amount: e.target.value, - errors: {}, }), + onBlur: () => this.setErrorsFor('amount'), + onFocus: () => this.clearErrorsFor('amount'), }), h('div.send-screen-input-wrapper__error-message', [ errorMessage ]), ]) @@ -272,6 +309,14 @@ SendTokenScreen.prototype.renderGasInput = function () { onFeeChange: ({ gasLimit, gasPrice }) => { this.setState({ gasLimit, gasPrice, errors: {} }) }, + onBlur: () => { + this.setErrorsFor('gasLimit') + this.setErrorsFor('gasPrice') + }, + onFocus: () => { + this.clearErrorsFor('gasLimit') + this.clearErrorsFor('gasPrice') + }, }), h('div.send-screen-gas-labels', {}, [ @@ -311,10 +356,12 @@ SendTokenScreen.prototype.renderMemoInput = function () { SendTokenScreen.prototype.renderButtons = function () { const { selectedAddress, backToAccountDetail } = this.props + const { isValid } = this.validate() return h('div.send-token__button-group', [ h('button.send-token__button-next.btn-secondary', { - onClick: () => this.submit(), + className: !isValid && 'send-screen__send-button__disabled', + onClick: () => isValid && this.submit(), }, ['Next']), h('button.send-token__button-cancel.btn-tertiary', { onClick: () => backToAccountDetail(selectedAddress), -- cgit v1.2.3 From fc3e071ad699f6c3586a20f12e06e6f456b0eea3 Mon Sep 17 00:00:00 2001 From: Dan Date: Mon, 25 Sep 2017 22:09:10 -0230 Subject: Send token now estimates gas and price. --- ui/app/components/send-token/index.js | 45 ++++++++++++++++++++++++++++------- 1 file changed, 37 insertions(+), 8 deletions(-) (limited to 'ui/app/components/send-token/index.js') diff --git a/ui/app/components/send-token/index.js b/ui/app/components/send-token/index.js index 166088898..e4f13a874 100644 --- a/ui/app/components/send-token/index.js +++ b/ui/app/components/send-token/index.js @@ -57,6 +57,9 @@ function mapDispatchToProps (dispatch) { dispatch(actions.signTokenTx(tokenAddress, toAddress, amount, txData)) ), updateTokenExchangeRate: token => dispatch(actions.updateTokenExchangeRate(token)), + estimateGas: ({ to, amount }) => dispatch(actions.estimateGas({ to, amount })), + getGasPrice: () => dispatch(actions.getGasPrice()), + } } @@ -69,8 +72,8 @@ function SendTokenScreen () { amountToSend: '0x0', selectedCurrency: 'USD', isGasTooltipOpen: false, - gasPrice: '0x5d21dba00', - gasLimit: '0x7b0d', + gasPrice: null, + gasLimit: null, errors: {}, } } @@ -84,6 +87,24 @@ SendTokenScreen.prototype.componentWillMount = function () { updateTokenExchangeRate(symbol) } +SendTokenScreen.prototype.estimateGasAndPrice = function () { + const { selectedToken } = this.props + const { errors, amount, to } = this.state + + if (!errors.to && !errors.amount && amount > 0) { + Promise.all([ + this.props.getGasPrice(), + this.props.estimateGas({ to, amount: this.getAmountToSend(amount, selectedToken) }), + ]) + .then(([blockGasPrice, estimatedGas]) => { + this.setState({ + blockGasPrice, + estimatedGas, + }) + }) + } +} + SendTokenScreen.prototype.validate = function () { const { to, @@ -215,7 +236,10 @@ SendTokenScreen.prototype.renderToAddressInput = function () { to: e.target.value, errors: {}, }), - onBlur: () => this.setErrorsFor('to'), + onBlur: () => { + this.setErrorsFor('to') + this.estimateGasAndPrice() + }, onFocus: () => this.clearErrorsFor('to'), }), h('datalist#addresses', [ @@ -271,7 +295,10 @@ SendTokenScreen.prototype.renderAmountInput = function () { onChange: e => this.setState({ amount: e.target.value, }), - onBlur: () => this.setErrorsFor('amount'), + onBlur: () => { + this.setErrorsFor('amount') + this.estimateGasAndPrice() + }, onFocus: () => this.clearErrorsFor('amount'), }), h('div.send-screen-input-wrapper__error-message', [ errorMessage ]), @@ -283,6 +310,8 @@ SendTokenScreen.prototype.renderGasInput = function () { isGasTooltipOpen, gasPrice, gasLimit, + blockGasPrice, + estimatedGas, selectedCurrency, errors: { gasPrice: gasPriceErrorMessage, @@ -303,8 +332,8 @@ SendTokenScreen.prototype.renderGasInput = function () { }, [ isGasTooltipOpen && h(GasTooltip, { className: 'send-tooltip', - gasPrice, - gasLimit, + gasPrice: gasPrice || blockGasPrice || '0x0', + gasLimit: gasLimit || estimatedGas || '0x0', onClose: () => this.setState({ isGasTooltipOpen: false }), onFeeChange: ({ gasLimit, gasPrice }) => { this.setState({ gasLimit, gasPrice, errors: {} }) @@ -327,9 +356,9 @@ SendTokenScreen.prototype.renderGasInput = function () { h(GasFeeDisplay, { conversionRate, tokenExchangeRate, - gasPrice, + gasPrice: gasPrice || blockGasPrice || '0x0', activeCurrency: selectedCurrency, - gas: gasLimit, + gas: gasLimit || estimatedGas || '0x0', blockGasLimit: currentBlockGasLimit, }), h( -- cgit v1.2.3 From eae40e054418c195310224194d9435ccfbf14e46 Mon Sep 17 00:00:00 2001 From: Dan Date: Fri, 22 Sep 2017 05:58:43 -0230 Subject: Able to change selections in to and from fields of send and send token. --- ui/app/components/send-token/index.js | 1 + 1 file changed, 1 insertion(+) (limited to 'ui/app/components/send-token/index.js') diff --git a/ui/app/components/send-token/index.js b/ui/app/components/send-token/index.js index dd8ca6b9d..cc77c2699 100644 --- a/ui/app/components/send-token/index.js +++ b/ui/app/components/send-token/index.js @@ -181,6 +181,7 @@ SendTokenScreen.prototype.renderToAddressInput = function () { to: e.target.value, errors: {}, }), + onFocus: () => to && this.setState({ to: '' }), }), h('datalist#addresses', [ // Corresponds to the addresses owned. -- cgit v1.2.3 From 56697ea9a4399ecaccf33ae3ae1a42283bdc9dc7 Mon Sep 17 00:00:00 2001 From: Dan Date: Fri, 22 Sep 2017 18:47:05 -0230 Subject: Select all in to and from of send screens, instead of clearing on focus. --- ui/app/components/send-token/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'ui/app/components/send-token/index.js') diff --git a/ui/app/components/send-token/index.js b/ui/app/components/send-token/index.js index cc77c2699..60fe2ac8b 100644 --- a/ui/app/components/send-token/index.js +++ b/ui/app/components/send-token/index.js @@ -181,7 +181,7 @@ SendTokenScreen.prototype.renderToAddressInput = function () { to: e.target.value, errors: {}, }), - onFocus: () => to && this.setState({ to: '' }), + onFocus: event => to && event.target.select(), }), h('datalist#addresses', [ // Corresponds to the addresses owned. -- cgit v1.2.3 From 541b69dda9a5ddbb0ea4e4c0df805e886f53645c Mon Sep 17 00:00:00 2001 From: Dan Date: Tue, 26 Sep 2017 21:51:45 -0230 Subject: Gets gas and price estimates when send components mount. --- ui/app/components/send-token/index.js | 32 ++++++++++++-------------------- 1 file changed, 12 insertions(+), 20 deletions(-) (limited to 'ui/app/components/send-token/index.js') diff --git a/ui/app/components/send-token/index.js b/ui/app/components/send-token/index.js index 379f63883..02423a348 100644 --- a/ui/app/components/send-token/index.js +++ b/ui/app/components/send-token/index.js @@ -57,9 +57,8 @@ function mapDispatchToProps (dispatch) { dispatch(actions.signTokenTx(tokenAddress, toAddress, amount, txData)) ), updateTokenExchangeRate: token => dispatch(actions.updateTokenExchangeRate(token)), - estimateGas: ({ to, amount }) => dispatch(actions.estimateGas({ to, amount })), + estimateGas: () => dispatch(actions.estimateGas()), getGasPrice: () => dispatch(actions.getGasPrice()), - } } @@ -82,27 +81,22 @@ SendTokenScreen.prototype.componentWillMount = function () { const { updateTokenExchangeRate, selectedToken: { symbol }, + getGasPrice, + estimateGas, } = this.props updateTokenExchangeRate(symbol) -} -SendTokenScreen.prototype.estimateGasAndPrice = function () { - const { selectedToken } = this.props - const { errors, amount, to } = this.state - - if (!errors.to && !errors.amount && amount > 0) { - Promise.all([ - this.props.getGasPrice(), - this.props.estimateGas({ to, amount: this.getAmountToSend(amount, selectedToken) }), - ]) - .then(([blockGasPrice, estimatedGas]) => { - this.setState({ - blockGasPrice, - estimatedGas, - }) + Promise.all([ + getGasPrice(), + estimateGas(), + ]) + .then(([blockGasPrice, estimatedGas]) => { + this.setState({ + blockGasPrice, + estimatedGas, }) - } + }) } SendTokenScreen.prototype.validate = function () { @@ -238,7 +232,6 @@ SendTokenScreen.prototype.renderToAddressInput = function () { }), onBlur: () => { this.setErrorsFor('to') - this.estimateGasAndPrice() }, onFocus: event => { if (to) event.target.select() @@ -300,7 +293,6 @@ SendTokenScreen.prototype.renderAmountInput = function () { }), onBlur: () => { this.setErrorsFor('amount') - this.estimateGasAndPrice() }, onFocus: () => this.clearErrorsFor('amount'), }), -- cgit v1.2.3 From 39365f2cc419ee824988e6dad4e8a75e650ad1cc Mon Sep 17 00:00:00 2001 From: Dan Date: Tue, 26 Sep 2017 23:03:03 -0230 Subject: Update the correct values in state when estimates are received. --- ui/app/components/send-token/index.js | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) (limited to 'ui/app/components/send-token/index.js') diff --git a/ui/app/components/send-token/index.js b/ui/app/components/send-token/index.js index 02423a348..8a827e951 100644 --- a/ui/app/components/send-token/index.js +++ b/ui/app/components/send-token/index.js @@ -93,8 +93,8 @@ SendTokenScreen.prototype.componentWillMount = function () { ]) .then(([blockGasPrice, estimatedGas]) => { this.setState({ - blockGasPrice, - estimatedGas, + gasPrice: blockGasPrice, + gasLimit: estimatedGas, }) }) } @@ -305,8 +305,6 @@ SendTokenScreen.prototype.renderGasInput = function () { isGasTooltipOpen, gasPrice, gasLimit, - blockGasPrice, - estimatedGas, selectedCurrency, errors: { gasPrice: gasPriceErrorMessage, @@ -327,8 +325,8 @@ SendTokenScreen.prototype.renderGasInput = function () { }, [ isGasTooltipOpen && h(GasTooltip, { className: 'send-tooltip', - gasPrice: gasPrice || blockGasPrice || '0x0', - gasLimit: gasLimit || estimatedGas || '0x0', + gasPrice: gasPrice || '0x0', + gasLimit: gasLimit || '0x0', onClose: () => this.setState({ isGasTooltipOpen: false }), onFeeChange: ({ gasLimit, gasPrice }) => { this.setState({ gasLimit, gasPrice, errors: {} }) @@ -351,9 +349,9 @@ SendTokenScreen.prototype.renderGasInput = function () { h(GasFeeDisplay, { conversionRate, tokenExchangeRate, - gasPrice: gasPrice || blockGasPrice || '0x0', + gasPrice: gasPrice || '0x0', activeCurrency: selectedCurrency, - gas: gasLimit || estimatedGas || '0x0', + gas: gasLimit || '0x0', blockGasLimit: currentBlockGasLimit, }), h( -- cgit v1.2.3 From 66ed4dfaa31be826f0d5a4a34410e34eca34d007 Mon Sep 17 00:00:00 2001 From: Dan Date: Thu, 28 Sep 2017 12:18:25 -0230 Subject: Ensure sent token value is recognized as hex. --- ui/app/components/send-token/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'ui/app/components/send-token/index.js') diff --git a/ui/app/components/send-token/index.js b/ui/app/components/send-token/index.js index 8a827e951..6e4c909be 100644 --- a/ui/app/components/send-token/index.js +++ b/ui/app/components/send-token/index.js @@ -165,7 +165,7 @@ SendTokenScreen.prototype.clearErrorsFor = function (field) { SendTokenScreen.prototype.getAmountToSend = function (amount, selectedToken) { const { decimals } = selectedToken || {} const multiplier = Math.pow(10, Number(decimals || 0)) - const sendAmount = Number(amount * multiplier).toString(16) + const sendAmount = '0x' + Number(amount * multiplier).toString(16) return sendAmount } -- cgit v1.2.3 From 67ee5b21e6f64ac22e65f2712ae13dd8c09ed113 Mon Sep 17 00:00:00 2001 From: Chi Kei Chan Date: Thu, 28 Sep 2017 17:39:53 -0700 Subject: Query for gas estimates --- ui/app/components/send-token/index.js | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) (limited to 'ui/app/components/send-token/index.js') diff --git a/ui/app/components/send-token/index.js b/ui/app/components/send-token/index.js index 6e4c909be..a95a0a6d8 100644 --- a/ui/app/components/send-token/index.js +++ b/ui/app/components/send-token/index.js @@ -2,6 +2,7 @@ const Component = require('react').Component const connect = require('react-redux').connect const h = require('react-hyperscript') const classnames = require('classnames') +const abi = require('ethereumjs-abi') const inherits = require('util').inherits const actions = require('../../actions') const selectors = require('../../selectors') @@ -57,7 +58,7 @@ function mapDispatchToProps (dispatch) { dispatch(actions.signTokenTx(tokenAddress, toAddress, amount, txData)) ), updateTokenExchangeRate: token => dispatch(actions.updateTokenExchangeRate(token)), - estimateGas: () => dispatch(actions.estimateGas()), + estimateGas: params => dispatch(actions.estimateGas(params)), getGasPrice: () => dispatch(actions.getGasPrice()), } } @@ -83,15 +84,28 @@ SendTokenScreen.prototype.componentWillMount = function () { selectedToken: { symbol }, getGasPrice, estimateGas, + selectedAddress, } = this.props updateTokenExchangeRate(symbol) + const data = Array.prototype.map.call( + abi.rawEncode(['address', 'uint256'], [selectedAddress, '0x0']), + x => ('00' + x.toString(16)).slice(-2) + ).join('') + + console.log(data) Promise.all([ getGasPrice(), - estimateGas(), + estimateGas({ + from: selectedAddress, + value: '0x0', + gas: '746a528800', + data, + }), ]) .then(([blockGasPrice, estimatedGas]) => { + console.log({ blockGasPrice, estimatedGas}) this.setState({ gasPrice: blockGasPrice, gasLimit: estimatedGas, -- cgit v1.2.3 From 5a94775b3fa22517a71232ebe229ee83e9debcf1 Mon Sep 17 00:00:00 2001 From: Dan Date: Thu, 2 Nov 2017 00:00:33 -0230 Subject: Lint fixes for NewUI-flat. --- ui/app/components/send-token/index.js | 1 - 1 file changed, 1 deletion(-) (limited to 'ui/app/components/send-token/index.js') diff --git a/ui/app/components/send-token/index.js b/ui/app/components/send-token/index.js index a95a0a6d8..c5c7a0b46 100644 --- a/ui/app/components/send-token/index.js +++ b/ui/app/components/send-token/index.js @@ -144,7 +144,6 @@ SendTokenScreen.prototype.validate = function () { } SendTokenScreen.prototype.setErrorsFor = function (field) { - const { balance, selectedToken } = this.props const { errors: previousErrors } = this.state const { -- cgit v1.2.3 From 56e9f98bd05de8ae26f653d15eec4304f0c72155 Mon Sep 17 00:00:00 2001 From: Dan Date: Thu, 2 Nov 2017 09:45:59 -0230 Subject: More lint fixes --- ui/app/components/send-token/index.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'ui/app/components/send-token/index.js') diff --git a/ui/app/components/send-token/index.js b/ui/app/components/send-token/index.js index c5c7a0b46..99d078251 100644 --- a/ui/app/components/send-token/index.js +++ b/ui/app/components/send-token/index.js @@ -148,11 +148,11 @@ SendTokenScreen.prototype.setErrorsFor = function (field) { const { isValid, - errors: newErrors + errors: newErrors, } = this.validate() const nextErrors = Object.assign({}, previousErrors, { - [field]: newErrors[field] || null + [field]: newErrors[field] || null, }) if (!isValid) { @@ -166,7 +166,7 @@ SendTokenScreen.prototype.setErrorsFor = function (field) { SendTokenScreen.prototype.clearErrorsFor = function (field) { const { errors: previousErrors } = this.state const nextErrors = Object.assign({}, previousErrors, { - [field]: null + [field]: null, }) this.setState({ @@ -428,7 +428,7 @@ SendTokenScreen.prototype.render = function () { this.renderAmountInput(), this.renderGasInput(), this.renderMemoInput(), - warning && h('div.send-screen-input-wrapper--error', {}, + warning && h('div.send-screen-input-wrapper--error', {}, h('div.send-screen-input-wrapper__error-message', [ warning, ]) -- cgit v1.2.3