Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add token selection to the send screen #6445

Merged
merged 19 commits into from
Apr 17, 2019
Merged
Show file tree
Hide file tree
Changes from 16 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions app/_locales/en/messages.json
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,9 @@
"approved": {
"message": "Approved"
},
"asset": {
"message": "Asset"
},
"attemptingConnect": {
"message": "Attempting to connect to blockchain."
},
Expand Down Expand Up @@ -1342,6 +1345,9 @@
"selectAnAccountHelp": {
"message": "Select the account to view in MetaMask"
},
"selectAnAsset": {
"message": "Select an Asset"
},
"selectAHigherGasFee": {
"message": "Select a higher gas fee to accelerate the processing of your transaction.*"
},
Expand Down
4 changes: 2 additions & 2 deletions test/integration/lib/send-new-ui.js
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ async function runSendFlowTest (assert, done) {
const sendToAccountAddress = sendToFieldInput.val()
assert.equal(sendToAccountAddress, '0x2f8D4a878cFA04A6E60D46362f5644DeAb66572D', 'send to dropdown selects the correct address')

const sendAmountField = await queryAsync($, '.send-v2__form-row:eq(2)')
const sendAmountField = await queryAsync($, '.send-v2__form-row:eq(3)')
sendAmountField.find('.unit-input')[0].click()

const sendAmountFieldInput = await findAsync(sendAmountField, '.unit-input__input')
Expand Down Expand Up @@ -115,7 +115,7 @@ async function runSendFlowTest (assert, done) {
sendToFieldInputInEdit[0].focus()
sendToFieldInputInEdit.val('0xd85a4b6a394794842887b8284293d69163007bbb')

const sendAmountFieldInEdit = await queryAsync($, '.send-v2__form-row:eq(2)')
const sendAmountFieldInEdit = await queryAsync($, '.send-v2__form-row:eq(3)')
sendAmountFieldInEdit.find('.unit-input')[0].click()

const sendAmountFieldInputInEdit = sendAmountFieldInEdit.find('.unit-input__input')
Expand Down
6 changes: 3 additions & 3 deletions ui/app/components/app/customize-gas-modal/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,11 @@ const {
MIN_GAS_PRICE_DEC,
MIN_GAS_LIMIT_DEC,
MIN_GAS_PRICE_GWEI,
} = require('../send/send.constants')
} = require('../../../pages/send/send.constants')

const {
isBalanceSufficient,
} = require('../send/send.utils')
} = require('../../../pages/send/send.utils')

const {
conversionUtil,
Expand All @@ -47,7 +47,7 @@ const {
const {
getGasPrice,
getGasLimit,
} = require('../send/send.selectors')
} = require('../../../pages/send/send.selectors')

function mapStateToProps (state) {
const selectedToken = getSelectedToken(state)
Expand Down
2 changes: 1 addition & 1 deletion ui/app/components/app/ens-input.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ const networkMap = require('ethjs-ens/lib/network-map.json')
const ensRE = /.+\..+$/
const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000'
const connect = require('react-redux').connect
const ToAutoComplete = require('./send/to-autocomplete').default
const ToAutoComplete = require('../../pages/send/to-autocomplete').default
const log = require('loglevel')
const { isValidENSAddress } = require('../../helpers/utils/util')

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ import {
import {
calcGasTotal,
isBalanceSufficient,
} from '../../send/send.utils'
} from '../../../../pages/send/send.utils'
import { addHexPrefix } from 'ethereumjs-util'
import { getAdjacentGasPrices, extrapolateY } from '../gas-price-chart/gas-price-chart.utils'

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React, { Component } from 'react'
import PropTypes from 'prop-types'
import BigNumber from 'bignumber.js'
import GasModalCard from '../../customize-gas-modal/gas-modal-card'
import { MIN_GAS_PRICE_GWEI } from '../../send/send.constants'
import { MIN_GAS_PRICE_GWEI } from '../../../../pages/send/send.constants'
import Button from '../../../ui/button'

import {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import {
setCustomGasLimit,
} from '../../../ducks/gas/gas.duck'
import { getIsMainnet, preferencesSelector, getSelectedAddress, conversionRateSelector } from '../../../selectors/selectors'
import { isBalanceSufficient } from '../send/send.utils'
import { isBalanceSufficient } from '../../../pages/send/send.utils'

const mapStateToProps = (state, ownProps) => {
const { metamask: { knownMethodData, accounts } } = state
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React, { PureComponent } from 'react'
import PropTypes from 'prop-types'
import AccountListItem from '../../app/send/account-list-item/account-list-item.component'
import AccountListItem from '../../../pages/send/account-list-item/account-list-item.component'

export default class AccountDropdownMini extends PureComponent {
static propTypes = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React from 'react'
import assert from 'assert'
import { shallow } from 'enzyme'
import AccountDropdownMini from '../account-dropdown-mini.component'
import AccountListItem from '../../../app/send/account-list-item/account-list-item.component'
import AccountListItem from '../../../../pages/send/account-list-item/account-list-item.component'

describe('AccountDropdownMini', () => {
it('should render an account with an icon', () => {
Expand Down
2 changes: 1 addition & 1 deletion ui/app/components/ui/unit-input/unit-input.component.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React, { PureComponent } from 'react'
import PropTypes from 'prop-types'
import classnames from 'classnames'
import { removeLeadingZeroes } from '../../app/send/send.utils'
import { removeLeadingZeroes } from '../../../pages/send/send.utils'

/**
* Component that attaches a suffix or unit of measurement trailing user input, ex. 'ETH'. Also
Expand Down
102 changes: 100 additions & 2 deletions ui/app/css/itcss/components/send.scss
Original file line number Diff line number Diff line change
Expand Up @@ -592,8 +592,8 @@
flex: 0 0 auto;
}

&__from-dropdown {
height: 73px;
&__from-dropdown,
&__asset-dropdown {
width: 100%;
border: 1px solid $alto;
border-radius: 4px;
Expand Down Expand Up @@ -628,6 +628,104 @@
}
}

&__from-dropdown {
height: 73px;
}

&__asset-dropdown {
height: 54px;
border: none;

&__asset {
display: flex;
flex-flow: row nowrap;
align-items: center;
padding: 10px 8px;
cursor: pointer;

&:hover {
background-color: rgba($alto, 0.2);
}
}

&__asset-icon {
.identicon {
border: 1px solid $alto;
}
}

&__asset-data {
display: flex;
flex-flow: column nowrap;
margin-left: 8px;
}

&__symbol {
font-size: 16px;
margin-bottom: 2px;
}

&__name {
display: flex;
flex-flow: row nowrap;
font-size: 12px;

&__label {
margin-right: .25rem;
}
}

&__close-area {
z-index: 2000;
}

&__list {
z-index: 2050;
position: absolute;
height: 220px;
width: 100%;
border: 1px solid $geyser;
border-radius: 4px;
background-color: $white;
box-shadow: 0 3px 6px 0 rgba(0 ,0 ,0 ,.11);
top: 55px;
left: 0;
box-sizing: content-box;
overflow-y: scroll;
}

&__input-wrapper {
border: 1px solid $alto;
border-radius: 4px;

&--opened {
position: relative;
z-index: 2050;
}

.send-v2__asset-dropdown__asset {
&:hover {
background-color: $white;
}
}
}

&__input {
z-index: 1025;
position: relative;
height: 54px;
width: 100%;
border: none;
border-radius: 4px;
background-color: $white;
color: $tundora;
padding: 10px;
font-family: Roboto;
font-size: 16px;
line-height: 21px;
}
}

&__to-autocomplete {
position: relative;

Expand Down
19 changes: 18 additions & 1 deletion ui/app/ducks/metamask/metamask.js
Original file line number Diff line number Diff line change
Expand Up @@ -154,9 +154,26 @@ function reduceMetamask (state, action) {
return newState

case actions.SET_SELECTED_TOKEN:
return extend(metamaskState, {
newState = extend(metamaskState, {
selectedTokenAddress: action.value,
})
const newSend = extend(metamaskState.send)

if (metamaskState.send.editingTransactionId && !action.value) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is meant to handle the specific case of when we are editing a transaction and ETH is selected, correct?

I see in send-asset-row.component that we pass an empty string when ETH is selected. Perhaps instead of just !action.value, we could explicitly check action.value === ''. That way the reader of the code here knows that the value passed to the action was intentionally an empty string, and not just defaulting to undefined.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

changed it to this.setSelectedToken() to invoke with no params, keeping it consistent with how it is call everywhere else in the app.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about the case when a user has ETH + two or more tokens in the dropdown. Do we need to modify unapprovedTxs in state if, while editing a token transaction, a user switches it to a different token?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This part is handled in ui/app/pages/send/send.component.js:L169. Would love a manual test from you to see if it works. I tested it with multiple tokens locally many times.

delete newSend.token
const unapprovedTx = newState.unapprovedTxs[newSend.editingTransactionId] || {}
const txParams = unapprovedTx.txParams || {}
newState.unapprovedTxs = extend(newState.unapprovedTxs, {
[newSend.editingTransactionId]: extend(unapprovedTx, {
txParams: extend(txParams, { data: '' }),
}),
})
newSend.tokenBalance = null
newSend.balance = '0'
}

newState.send = newSend
return newState

case actions.SET_ACCOUNT_LABEL:
const account = action.value.account
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import PropTypes from 'prop-types'
import { ENVIRONMENT_TYPE_NOTIFICATION } from '../../../../app/scripts/lib/enums'
import { getEnvironmentType } from '../../../../app/scripts/lib/util'
import ConfirmPageContainer, { ConfirmDetailRow } from '../../components/app/confirm-page-container'
import { isBalanceSufficient } from '../../components/app/send/send.utils'
import { isBalanceSufficient } from '../send/send.utils'
import { DEFAULT_ROUTE, CONFIRM_TRANSACTION_ROUTE } from '../../helpers/constants/routes'
import {
INSUFFICIENT_FUNDS_ERROR_KEY,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@ import {
GAS_LIMIT_TOO_LOW_ERROR_KEY,
} from '../../helpers/constants/error-keys'
import { getHexGasTotal } from '../../helpers/utils/confirm-tx.util'
import { isBalanceSufficient, calcGasTotal } from '../../components/app/send/send.utils'
import { isBalanceSufficient, calcGasTotal } from '../send/send.utils'
import { conversionGreaterThan } from '../../helpers/utils/conversion-util'
import { MIN_GAS_LIMIT_DEC } from '../../components/app/send/send.constants'
import { MIN_GAS_LIMIT_DEC } from '../send/send.constants'
import { checksumAddress, addressSlicer, valuesFor } from '../../helpers/utils/util'
import {getMetaMaskAccounts, getAdvancedInlineGasShown, preferencesSelector, getIsMainnet} from '../../selectors/selectors'

Expand Down
2 changes: 1 addition & 1 deletion ui/app/pages/home/home.container.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { compose } from 'recompose'
import { connect } from 'react-redux'
import { withRouter } from 'react-router-dom'
import { unconfirmedTransactionsCountSelector } from '../../selectors/confirm-transaction'

``
const mapStateToProps = state => {
const { metamask, appState } = state
const {
Expand Down
2 changes: 1 addition & 1 deletion ui/app/pages/routes/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { getMetaMaskAccounts, getNetworkIdentifier } from '../../selectors/selec
// init
import FirstTimeFlow from '../first-time-flow'
// accounts
const SendTransactionScreen = require('../../components/app/send/send.container')
const SendTransactionScreen = require('../send/send.container')
const ConfirmTransaction = require('../confirm-transaction')

// slideout menu
Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import classnames from 'classnames'
import { checksumAddress } from '../../../../helpers/utils/util'
import Identicon from '../../../ui/identicon'
import UserPreferencedCurrencyDisplay from '../../user-preferenced-currency-display'
import { PRIMARY, SECONDARY } from '../../../../helpers/constants/common'
import Tooltip from '../../../ui/tooltip-v2'
import { checksumAddress } from '../../../helpers/utils/util'
import Identicon from '../../../components/ui/identicon'
import UserPreferencedCurrencyDisplay from '../../../components/app/user-preferenced-currency-display'
import { PRIMARY, SECONDARY } from '../../../helpers/constants/common'
import Tooltip from '../../../components/ui/tooltip-v2'

export default class AccountListItem extends Component {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {
getIsMainnet,
isBalanceCached,
preferencesSelector,
} from '../../../../selectors/selectors'
} from '../../../selectors/selectors'
import AccountListItem from './account-list-item.component'

export default connect(mapStateToProps)(AccountListItem)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,15 @@ import assert from 'assert'
import { shallow } from 'enzyme'
import sinon from 'sinon'
import proxyquire from 'proxyquire'
import Identicon from '../../../../ui/identicon'
import UserPreferencedCurrencyDisplay from '../../../user-preferenced-currency-display'
import Identicon from '../../../../components/ui/identicon'
import UserPreferencedCurrencyDisplay from '../../../../components/app/user-preferenced-currency-display'

const utilsMethodStubs = {
checksumAddress: sinon.stub().returns('mockCheckSumAddress'),
}

const AccountListItem = proxyquire('../account-list-item.component.js', {
'../../../../helpers/utils/util': utilsMethodStubs,
'../../../helpers/utils/util': utilsMethodStubs,
}).default


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ proxyquire('../account-list-item.container.js', {
getCurrentCurrency: () => `mockCurrentCurrency`,
getNativeCurrency: () => `mockNativeCurrency`,
},
'../../../../selectors/selectors': {
'../../../selectors/selectors': {
isBalanceCached: () => `mockBalanceIsCached`,
preferencesSelector: ({ showFiatInTestnets }) => ({
showFiatInTestnets,
Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@ import { calcMaxAmount } from './amount-max-button.utils.js'
import {
updateSendAmount,
setMaxModeTo,
} from '../../../../../../store/actions'
} from '../../../../../store/actions'
import AmountMaxButton from './amount-max-button.component'
import {
updateSendErrors,
} from '../../../../../../ducks/send/send.duck'
} from '../../../../../ducks/send/send.duck'

export default connect(mapStateToProps, mapDispatchToProps)(AmountMaxButton)

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
const {
multiplyCurrencies,
subtractCurrencies,
} = require('../../../../../../helpers/utils/conversion-util')
} = require('../../../../../helpers/utils/conversion-util')
const ethUtil = require('ethereumjs-util')

function calcMaxAmount ({ balance, gasTotal, selectedToken, tokenBalance }) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ proxyquire('../amount-max-button.container.js', {
},
'./amount-max-button.selectors.js': { getMaxModeOn: (s) => `mockMaxModeOn:${s}` },
'./amount-max-button.utils.js': { calcMaxAmount: (mockObj) => mockObj.val + 1 },
'../../../../../../store/actions': actionSpies,
'../../../../../../ducks/send/send.duck': duckActionSpies,
'../../../../../store/actions': actionSpies,
'../../../../../ducks/send/send.duck': duckActionSpies,
})

describe('amount-max-button container', () => {
Expand Down
Loading