From 40bcc25a7636710ab4200d558d5826e6e61a77f0 Mon Sep 17 00:00:00 2001 From: Victor Baranov Date: Mon, 15 Jun 2020 15:45:29 +0300 Subject: [PATCH] Send all option for tokens send --- .../amount-max-button.utils.js | 13 +---- old-ui/app/components/send/send-token.js | 58 ++++++++++++++----- old-ui/app/components/send/send.js | 12 ++-- ui/app/actions.js | 13 ++++- ui/app/reducers/metamask.js | 29 ++++++++++ ui/app/selectors.js | 13 +++++ 6 files changed, 104 insertions(+), 34 deletions(-) diff --git a/old-ui/app/components/send/amount-max-button/amount-max-button.utils.js b/old-ui/app/components/send/amount-max-button/amount-max-button.utils.js index 0f1572d82..0dd76db68 100644 --- a/old-ui/app/components/send/amount-max-button/amount-max-button.utils.js +++ b/old-ui/app/components/send/amount-max-button/amount-max-button.utils.js @@ -1,4 +1,4 @@ -import { multiplyCurrencies, subtractCurrencies, BIG_NUMBER_WEI_MULTIPLIER } from '../../../../../ui/app/conversion-util' +import { subtractCurrencies, BIG_NUMBER_WEI_MULTIPLIER } from '../../../../../ui/app/conversion-util' import ethUtil from 'ethereumjs-util' import BigNumber from 'bignumber.js' @@ -6,17 +6,10 @@ export function calcMaxAmount ({ balance, gasTotal, sendToken, tokenBalance }) { const { decimals } = sendToken || {} const multiplier = Math.pow(10, Number(decimals || 0)) - let maxBalance if (sendToken) { - maxBalance = multiplyCurrencies( - tokenBalance, - multiplier, - { - toNumericBase: 'hex', - multiplicandBase: 16, - }, - ) + const tokenBalanceBN = new BigNumber(tokenBalance.toString()) + maxBalance = tokenBalanceBN.div(multiplier).toString() } else { const maxBalanceInWei = subtractCurrencies( diff --git a/old-ui/app/components/send/send-token.js b/old-ui/app/components/send/send-token.js index 347434896..1dc5d10b3 100644 --- a/old-ui/app/components/send/send-token.js +++ b/old-ui/app/components/send/send-token.js @@ -18,7 +18,8 @@ import log from 'loglevel' import SendProfile from './send-profile' import SendHeader from './send-header' import ErrorComponent from '../error' -import { getMetaMaskAccounts } from '../../../../ui/app/selectors' +import { getMetaMaskAccounts, getSendToken, getSendTo, getTokenBalance, getSendTokenContract } from '../../../../ui/app/selectors' +import AmountMaxButton from './amount-max-button' class SendTransactionScreen extends PersistentForm { constructor (props) { @@ -30,13 +31,12 @@ class SendTransactionScreen extends PersistentForm { balance: 0, decimals: 0, }, - amount: '', isLoading: true, } PersistentForm.call(this) } render () { - const { isLoading, token, amount } = this.state + const { isLoading, token } = this.state if (isLoading) { return ( @@ -50,6 +50,7 @@ class SendTransactionScreen extends PersistentForm { identities, addressBook, error, + updateSendTo, } = props const nextDisabled = token.balance <= 0 @@ -67,18 +68,20 @@ class SendTransactionScreen extends PersistentForm { network={network} identities={identities} addressBook={addressBook} + updateSendTo={updateSendTo} />
this.amountDidChange(e.target.value)} placeholder="Amount" type="number" style={{ marginRight: '6px', }} + disabled={!!this.props.maxModeOn} />
+
) } componentDidMount () { this.getTokensMetadata() - .then(() => { + .then((token) => { + this.props.updateSendToken(token) + + const { + sendToken, + tokenContract, + address, + } = this.props + this.props.updateSendTokenBalance({sendToken, tokenContract, address}) this.createFreshTokenTracker() }) } @@ -102,16 +114,17 @@ class SendTransactionScreen extends PersistentForm { this.tokenInfoGetter = tokenInfoGetter() const { tokenAddress, network } = this.props const { symbol = '', decimals = 0 } = await this.tokenInfoGetter(tokenAddress) + const token = { + address: tokenAddress, + network, + symbol, + decimals, + } this.setState({ - token: { - address: tokenAddress, - network, - symbol, - decimals, - }, + token, }) - return Promise.resolve() + return Promise.resolve(token) } componentWillUnmount () { @@ -120,6 +133,9 @@ class SendTransactionScreen extends PersistentForm { this.tracker.stop() this.tracker.removeListener('update', this.balanceUpdater) this.tracker.removeListener('error', this.showError) + this.props.updateSendAmount(null) + this.props.setMaxModeTo(false) + this.props.updateSendTo('') } createFreshTokenTracker () { @@ -176,14 +192,13 @@ class SendTransactionScreen extends PersistentForm { } amountDidChange (amount) { - this.setState({ - amount, - }) + this.props.updateSendAmount(amount) } async onSubmit () { const state = this.state || {} - const { token, amount } = state + const { token } = state + const { amount } = this.props let recipient = state.recipient || document.querySelector('input[name="address"]').value.replace(/^[.\s]+|[.\s]+$/g, '') let nickname = state.nickname || ' ' if (typeof recipient === 'object') { @@ -284,6 +299,12 @@ const mapStateToProps = (state) => { network: state.metamask.network, addressBook: state.metamask.addressBook, tokenAddress: state.appState.currentView.tokenAddress, + to: getSendTo(state), + sendToken: getSendToken(state), + amount: state.metamask.send.amount, + maxModeOn: state.metamask.send.maxModeOn, + tokenBalance: getTokenBalance(state), + tokenContract: getSendTokenContract(state), } result.error = result.warning && result.warning.split('.')[0] @@ -307,6 +328,11 @@ const mapDispatchToProps = dispatch => { txParams, confTxScreenParams, ) => dispatch(actions.signTokenTx(tokenAddress, toAddress, tokensValueWithDec, txParams, confTxScreenParams)), + updateSendTokenBalance: props => dispatch(actions.updateSendTokenBalance(props)), + setMaxModeTo: maxMode => dispatch(actions.setMaxModeTo(maxMode)), + updateSendAmount: amount => dispatch(actions.updateSendAmount(amount)), + updateSendTo: (to, nickname) => dispatch(actions.updateSendTo(to, nickname)), + updateSendToken: token => dispatch(actions.updateSendToken(token)), } } diff --git a/old-ui/app/components/send/send.js b/old-ui/app/components/send/send.js index 00a0c5bc8..40b83e8a9 100644 --- a/old-ui/app/components/send/send.js +++ b/old-ui/app/components/send/send.js @@ -289,14 +289,14 @@ function mapDispatchToProps (dispatch) { return { addToAddressBook: (recipient, nickname) => dispatch(actions.addToAddressBook(recipient, nickname)), showAccountsPage: () => dispatch(actions.showAccountsPage()), - displayWarning: (msg) => dispatch(actions.displayWarning(msg)), + displayWarning: msg => dispatch(actions.displayWarning(msg)), hideWarning: () => dispatch(actions.hideWarning()), - getPendingNonce: (address) => dispatch(actions.getPendingNonce(address)), - signTx: (txParams) => dispatch(actions.signTx(txParams)), - updateSendAmount: (amount) => dispatch(actions.updateSendAmount(amount)), - setMaxModeTo: (maxMode) => dispatch(actions.setMaxModeTo(maxMode)), + getPendingNonce: address => dispatch(actions.getPendingNonce(address)), + signTx: txParams => dispatch(actions.signTx(txParams)), + updateSendAmount: amount => dispatch(actions.updateSendAmount(amount)), + setMaxModeTo: maxMode => dispatch(actions.setMaxModeTo(maxMode)), updateSendTo: (to, nickname) => dispatch(actions.updateSendTo(to, nickname)), - updateSendHexData: (txData) => dispatch(actions.updateSendHexData(txData)), + updateSendHexData: txData => dispatch(actions.updateSendHexData(txData)), } } diff --git a/ui/app/actions.js b/ui/app/actions.js index 23f5e92bb..50fa34d95 100644 --- a/ui/app/actions.js +++ b/ui/app/actions.js @@ -212,6 +212,7 @@ const actions = { UPDATE_SEND_ERRORS: 'UPDATE_SEND_ERRORS', UPDATE_MAX_MODE: 'UPDATE_MAX_MODE', UPDATE_SEND: 'UPDATE_SEND', + UPDATE_SEND_TOKEN: 'UPDATE_SEND_TOKEN', CLEAR_SEND: 'CLEAR_SEND', OPEN_FROM_DROPDOWN: 'OPEN_FROM_DROPDOWN', CLOSE_FROM_DROPDOWN: 'CLOSE_FROM_DROPDOWN', @@ -230,6 +231,7 @@ const actions = { updateSendMemo, setMaxModeTo, updateSend, + updateSendToken, updateSendErrors, clearSend, setSelectedAddress, @@ -1133,7 +1135,7 @@ function showChooseContractExecutorPage ({methodSelected, methodABI, inputValues } function updateSendTokenBalance ({ - selectedToken, + sendToken, tokenContract, address, }) { @@ -1144,7 +1146,7 @@ function updateSendTokenBalance ({ return tokenBalancePromise .then(usersToken => { if (usersToken) { - const newTokenBalance = calcTokenBalance({ selectedToken, usersToken }) + const newTokenBalance = calcTokenBalance({ sendToken, usersToken }) dispatch(setSendTokenBalance(newTokenBalance.toString(10))) } }) @@ -1218,6 +1220,13 @@ function updateSend (newSend) { } } +function updateSendToken (token) { + return { + type: actions.UPDATE_SEND_TOKEN, + value: token, + } +} + function clearSend () { return { type: actions.CLEAR_SEND, diff --git a/ui/app/reducers/metamask.js b/ui/app/reducers/metamask.js index f54ad7b1b..2e3565ee8 100644 --- a/ui/app/reducers/metamask.js +++ b/ui/app/reducers/metamask.js @@ -283,6 +283,35 @@ function reduceMetamask (state, action) { }, }) + case actions.UPDATE_SEND_TOKEN: + const newSend = { + ...metamaskState.send, + token: action.value, + } + // erase token-related state when switching back to native currency + if (newSend.editingTransactionId && !newSend.token) { + const unapprovedTx = newSend?.unapprovedTxs?.[newSend.editingTransactionId] || {} + const txParams = unapprovedTx.txParams || {} + Object.assign(newSend, { + tokenBalance: null, + balance: '0', + from: unapprovedTx.from || '', + unapprovedTxs: { + ...newSend.unapprovedTxs, + [newSend.editingTransactionId]: { + ...unapprovedTx, + txParams: { + ...txParams, + data: '', + }, + }, + }, + }) + } + return Object.assign(metamaskState, { + send: newSend, + }) + case actions.CLEAR_SEND: return extend(metamaskState, { send: { diff --git a/ui/app/selectors.js b/ui/app/selectors.js index 1a3436a95..85b3de25e 100644 --- a/ui/app/selectors.js +++ b/ui/app/selectors.js @@ -46,6 +46,8 @@ const selectors = { priceEstimateToWei, getCurrentEthBalance, getSendToken, + getSendTokenAddress, + getSendTokenContract, getTokenBalance, getSendFromBalance, getSendFromObject, @@ -269,6 +271,17 @@ function getSendToken (state) { return state.metamask.send.token } +function getSendTokenAddress (state) { + return getSendToken(state)?.address +} + +function getSendTokenContract (state) { + const sendTokenAddress = getSendTokenAddress(state) + return sendTokenAddress + ? global.eth.contract(abi).at(sendTokenAddress) + : null +} + function getTokenBalance (state) { return state.metamask.send.tokenBalance }