mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-12-23 09:52:26 +01:00
Add token selection to the send screen (#6445)
* Move send to pages/ * Fix unit tests * Finish UI * Integrate asset dropdown to send actions * Remove console.log * Hide asset change during edit * Enable switch from send token to seand eth * Enable switching from token to eth when editing * Fix linter * Fixing test * Fix unit tests * Fix linter * Fix react warning; remove console.log * fix flat test * Add metrics * Address code review comments * Consistent spacing between send screen form rows. * Reduce height of gas buttons on send screen. * Make send screen gas button height dependent on size of contents.
This commit is contained in:
parent
a844eb20da
commit
931aaeb700
@ -139,6 +139,9 @@
|
||||
"approved": {
|
||||
"message": "Approved"
|
||||
},
|
||||
"asset": {
|
||||
"message": "Asset"
|
||||
},
|
||||
"attemptingConnect": {
|
||||
"message": "Attempting to connect to blockchain."
|
||||
},
|
||||
@ -1351,6 +1354,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.*"
|
||||
},
|
||||
|
@ -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')
|
||||
@ -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')
|
||||
|
@ -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,
|
||||
@ -47,7 +47,7 @@ const {
|
||||
const {
|
||||
getGasPrice,
|
||||
getGasLimit,
|
||||
} = require('../send/send.selectors')
|
||||
} = require('../../../pages/send/send.selectors')
|
||||
|
||||
function mapStateToProps (state) {
|
||||
const selectedToken = getSelectedToken(state)
|
||||
|
@ -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')
|
||||
|
||||
|
@ -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'
|
||||
|
||||
|
@ -99,15 +99,13 @@
|
||||
}
|
||||
|
||||
&__loading-container {
|
||||
height: 78px;
|
||||
height: 54px;
|
||||
}
|
||||
|
||||
.button-group__button, .button-group__button--active {
|
||||
height: 78px;
|
||||
background: white;
|
||||
color: $scorpion;
|
||||
padding-top: 9px;
|
||||
padding-left: 8.5px;
|
||||
padding: 2px 8.5px 4px 8.5px;
|
||||
|
||||
@media screen and (max-width: $break-small) {
|
||||
padding-left: 4px;
|
||||
|
@ -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 {
|
||||
|
@ -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
|
||||
|
@ -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 = {
|
||||
|
@ -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', () => {
|
||||
|
@ -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
|
||||
|
@ -549,7 +549,7 @@
|
||||
}
|
||||
|
||||
&__form-row {
|
||||
margin: 14.5px 18px 0px;
|
||||
margin: 8px 18px 0px;
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-flow: row;
|
||||
@ -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;
|
||||
@ -628,6 +628,104 @@
|
||||
}
|
||||
}
|
||||
|
||||
&__from-dropdown {
|
||||
height: 73px;
|
||||
}
|
||||
|
||||
&__asset-dropdown {
|
||||
height: 62px;
|
||||
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;
|
||||
|
||||
|
@ -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) {
|
||||
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
|
||||
|
@ -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,
|
||||
|
@ -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'
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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
|
||||
|
@ -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 {
|
||||
|
@ -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)
|
@ -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
|
||||
|
||||
|
@ -15,7 +15,7 @@ proxyquire('../account-list-item.container.js', {
|
||||
getCurrentCurrency: () => `mockCurrentCurrency`,
|
||||
getNativeCurrency: () => `mockNativeCurrency`,
|
||||
},
|
||||
'../../../../selectors/selectors': {
|
||||
'../../../selectors/selectors': {
|
||||
isBalanceCached: () => `mockBalanceIsCached`,
|
||||
preferencesSelector: ({ showFiatInTestnets }) => ({
|
||||
showFiatInTestnets,
|
@ -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)
|
||||
|
@ -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 }) {
|
@ -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', () => {
|
@ -2,8 +2,8 @@ import React, { Component } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import SendRowWrapper from '../send-row-wrapper'
|
||||
import AmountMaxButton from './amount-max-button'
|
||||
import UserPreferencedCurrencyInput from '../../../user-preferenced-currency-input'
|
||||
import UserPreferencedTokenInput from '../../../user-preferenced-token-input'
|
||||
import UserPreferencedCurrencyInput from '../../../../components/app/user-preferenced-currency-input'
|
||||
import UserPreferencedTokenInput from '../../../../components/app/user-preferenced-token-input'
|
||||
|
||||
export default class SendAmountRow extends Component {
|
||||
|
@ -17,10 +17,10 @@ import { getAmountErrorObject, getGasFeeErrorObject } from '../../send.utils'
|
||||
import {
|
||||
setMaxModeTo,
|
||||
updateSendAmount,
|
||||
} from '../../../../../store/actions'
|
||||
} from '../../../../store/actions'
|
||||
import {
|
||||
updateSendErrors,
|
||||
} from '../../../../../ducks/send/send.duck'
|
||||
} from '../../../../ducks/send/send.duck'
|
||||
import SendAmountRow from './send-amount-row.component'
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(SendAmountRow)
|
@ -6,7 +6,7 @@ import SendAmountRow from '../send-amount-row.component.js'
|
||||
|
||||
import SendRowWrapper from '../../send-row-wrapper/send-row-wrapper.component'
|
||||
import AmountMaxButton from '../amount-max-button/amount-max-button.container'
|
||||
import UserPreferencedTokenInput from '../../../../user-preferenced-token-input'
|
||||
import UserPreferencedTokenInput from '../../../../../components/app/user-preferenced-token-input'
|
||||
|
||||
const propsMethodSpies = {
|
||||
setMaxModeTo: sinon.spy(),
|
@ -37,8 +37,8 @@ proxyquire('../send-amount-row.container.js', {
|
||||
getAmountErrorObject: (mockDataObject) => ({ ...mockDataObject, mockChange: true }),
|
||||
getGasFeeErrorObject: (mockDataObject) => ({ ...mockDataObject, mockGasFeeErrorChange: true }),
|
||||
},
|
||||
'../../../../../store/actions': actionSpies,
|
||||
'../../../../../ducks/send/send.duck': duckActionSpies,
|
||||
'../../../../store/actions': actionSpies,
|
||||
'../../../../ducks/send/send.duck': duckActionSpies,
|
||||
})
|
||||
|
||||
describe('send-amount-row container', () => {
|
1
ui/app/pages/send/send-content/send-asset-row/index.js
Normal file
1
ui/app/pages/send/send-content/send-asset-row/index.js
Normal file
@ -0,0 +1 @@
|
||||
export { default } from './send-asset-row.container'
|
@ -0,0 +1,152 @@
|
||||
import React, { Component } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import SendRowWrapper from '../send-row-wrapper'
|
||||
import Identicon from '../../../../components/ui/identicon/identicon.component'
|
||||
import TokenBalance from '../../../../components/ui/token-balance'
|
||||
import UserPreferencedCurrencyDisplay from '../../../../components/app/user-preferenced-currency-display'
|
||||
import {PRIMARY} from '../../../../helpers/constants/common'
|
||||
|
||||
export default class SendAssetRow extends Component {
|
||||
static propTypes = {
|
||||
tokens: PropTypes.arrayOf(
|
||||
PropTypes.shape({
|
||||
address: PropTypes.string,
|
||||
decimals: PropTypes.string,
|
||||
symbol: PropTypes.string,
|
||||
})
|
||||
).isRequired,
|
||||
accounts: PropTypes.object.isRequired,
|
||||
selectedAddress: PropTypes.string.isRequired,
|
||||
selectedTokenAddress: PropTypes.string,
|
||||
setSelectedToken: PropTypes.func.isRequired,
|
||||
}
|
||||
|
||||
static contextTypes = {
|
||||
t: PropTypes.func,
|
||||
metricsEvent: PropTypes.func,
|
||||
}
|
||||
|
||||
state = {
|
||||
isShowingDropdown: false,
|
||||
}
|
||||
|
||||
openDropdown = () => this.setState({ isShowingDropdown: true })
|
||||
|
||||
closeDropdown = () => this.setState({ isShowingDropdown: false })
|
||||
|
||||
selectToken = address => {
|
||||
this.setState({
|
||||
isShowingDropdown: false,
|
||||
}, () => {
|
||||
this.context.metricsEvent({
|
||||
eventOpts: {
|
||||
category: 'Transactions',
|
||||
action: 'Send Screen',
|
||||
name: 'User clicks "Assets" dropdown',
|
||||
},
|
||||
customVariables: {
|
||||
assetSelected: address ? 'ERC20' : 'ETH',
|
||||
},
|
||||
})
|
||||
this.props.setSelectedToken(address)
|
||||
})
|
||||
}
|
||||
|
||||
render () {
|
||||
const { t } = this.context
|
||||
|
||||
return (
|
||||
<SendRowWrapper label={`${t('asset')}:`}>
|
||||
<div className="send-v2__asset-dropdown">
|
||||
{ this.renderSelectedToken() }
|
||||
{ this.renderAssetDropdown() }
|
||||
</div>
|
||||
</SendRowWrapper>
|
||||
)
|
||||
}
|
||||
|
||||
renderSelectedToken () {
|
||||
const { selectedTokenAddress } = this.props
|
||||
const token = this.props.tokens.find(({ address }) => address === selectedTokenAddress)
|
||||
return (
|
||||
<div
|
||||
className="send-v2__asset-dropdown__input-wrapper"
|
||||
onClick={this.openDropdown}
|
||||
>
|
||||
{ token ? this.renderAsset(token) : this.renderEth() }
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
renderAssetDropdown () {
|
||||
return this.state.isShowingDropdown && (
|
||||
<div>
|
||||
<div
|
||||
className="send-v2__asset-dropdown__close-area"
|
||||
onClick={this.closeDropdown}
|
||||
/>
|
||||
<div className="send-v2__asset-dropdown__list">
|
||||
{ this.renderEth() }
|
||||
{ this.props.tokens.map(token => this.renderAsset(token)) }
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
renderEth () {
|
||||
const { t } = this.context
|
||||
const { accounts, selectedAddress } = this.props
|
||||
|
||||
const balanceValue = accounts[selectedAddress] ? accounts[selectedAddress].balance : ''
|
||||
|
||||
return (
|
||||
<div
|
||||
className="send-v2__asset-dropdown__asset"
|
||||
onClick={() => this.selectToken()}
|
||||
>
|
||||
<div className="send-v2__asset-dropdown__asset-icon">
|
||||
<Identicon diameter={36} />
|
||||
</div>
|
||||
<div className="send-v2__asset-dropdown__asset-data">
|
||||
<div className="send-v2__asset-dropdown__symbol">ETH</div>
|
||||
<div className="send-v2__asset-dropdown__name">
|
||||
<span className="send-v2__asset-dropdown__name__label">{`${t('balance')}:`}</span>
|
||||
<UserPreferencedCurrencyDisplay
|
||||
value={balanceValue}
|
||||
type={PRIMARY}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
renderAsset (token) {
|
||||
const { address, symbol } = token
|
||||
const { t } = this.context
|
||||
|
||||
return (
|
||||
<div
|
||||
key={address} className="send-v2__asset-dropdown__asset"
|
||||
onClick={() => this.selectToken(address)}
|
||||
>
|
||||
<div className="send-v2__asset-dropdown__asset-icon">
|
||||
<Identicon address={address} diameter={36} />
|
||||
</div>
|
||||
<div className="send-v2__asset-dropdown__asset-data">
|
||||
<div className="send-v2__asset-dropdown__symbol">
|
||||
{ symbol }
|
||||
</div>
|
||||
<div className="send-v2__asset-dropdown__name">
|
||||
<span className="send-v2__asset-dropdown__name__label">{`${t('balance')}:`}</span>
|
||||
<TokenBalance
|
||||
token={token}
|
||||
withSymbol
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
import { connect } from 'react-redux'
|
||||
import SendAssetRow from './send-asset-row.component'
|
||||
import {getMetaMaskAccounts} from '../../../../selectors/selectors'
|
||||
import { setSelectedToken } from '../../../../store/actions'
|
||||
|
||||
function mapStateToProps (state) {
|
||||
return {
|
||||
tokens: state.metamask.tokens,
|
||||
selectedAddress: state.metamask.selectedAddress,
|
||||
selectedTokenAddress: state.metamask.selectedTokenAddress,
|
||||
accounts: getMetaMaskAccounts(state),
|
||||
}
|
||||
}
|
||||
|
||||
function mapDispatchToProps (dispatch) {
|
||||
return {
|
||||
setSelectedToken: address => dispatch(setSelectedToken(address)),
|
||||
}
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(SendAssetRow)
|
@ -1,11 +1,12 @@
|
||||
import React, { Component } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import PageContainerContent from '../../../ui/page-container/page-container-content.component'
|
||||
import PageContainerContent from '../../../components/ui/page-container/page-container-content.component'
|
||||
import SendAmountRow from './send-amount-row'
|
||||
import SendFromRow from './send-from-row'
|
||||
import SendGasRow from './send-gas-row'
|
||||
import SendHexDataRow from './send-hex-data-row'
|
||||
import SendToRow from './send-to-row'
|
||||
import SendAssetRow from './send-asset-row'
|
||||
|
||||
export default class SendContent extends Component {
|
||||
|
||||
@ -26,6 +27,7 @@ export default class SendContent extends Component {
|
||||
updateGas={this.updateGas}
|
||||
scanQrCode={ _ => this.props.scanQrCode()}
|
||||
/>
|
||||
<SendAssetRow />
|
||||
<SendAmountRow updateGas={this.updateGas} />
|
||||
<SendGasRow />
|
||||
{(this.props.showHexData && (
|
@ -1,7 +1,7 @@
|
||||
import React, {Component} from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import UserPreferencedCurrencyDisplay from '../../../../user-preferenced-currency-display'
|
||||
import { PRIMARY, SECONDARY } from '../../../../../../helpers/constants/common'
|
||||
import UserPreferencedCurrencyDisplay from '../../../../../components/app/user-preferenced-currency-display'
|
||||
import { PRIMARY, SECONDARY } from '../../../../../helpers/constants/common'
|
||||
|
||||
export default class GasFeeDisplay extends Component {
|
||||
|
@ -2,7 +2,7 @@ import React from 'react'
|
||||
import assert from 'assert'
|
||||
import {shallow} from 'enzyme'
|
||||
import GasFeeDisplay from '../gas-fee-display.component'
|
||||
import UserPreferencedCurrencyDisplay from '../../../../../user-preferenced-currency-display'
|
||||
import UserPreferencedCurrencyDisplay from '../../../../../../components/app/user-preferenced-currency-display'
|
||||
import sinon from 'sinon'
|
||||
|
||||
|
@ -2,8 +2,8 @@ import React, { Component } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import SendRowWrapper from '../send-row-wrapper'
|
||||
import GasFeeDisplay from './gas-fee-display/gas-fee-display.component'
|
||||
import GasPriceButtonGroup from '../../../gas-customization/gas-price-button-group'
|
||||
import AdvancedGasInputs from '../../../gas-customization/advanced-gas-inputs'
|
||||
import GasPriceButtonGroup from '../../../../components/app/gas-customization/gas-price-button-group'
|
||||
import AdvancedGasInputs from '../../../../components/app/gas-customization/advanced-gas-inputs'
|
||||
|
||||
export default class SendGasRow extends Component {
|
||||
|
||||
@ -20,8 +20,8 @@ export default class SendGasRow extends Component {
|
||||
gasButtonGroupShown: PropTypes.bool,
|
||||
advancedInlineGasShown: PropTypes.bool,
|
||||
resetGasButtons: PropTypes.func,
|
||||
gasPrice: PropTypes.number,
|
||||
gasLimit: PropTypes.number,
|
||||
gasPrice: PropTypes.string,
|
||||
gasLimit: PropTypes.string,
|
||||
insufficientBalance: PropTypes.bool,
|
||||
}
|
||||
|
@ -15,18 +15,18 @@ import {
|
||||
getBasicGasEstimateLoadingStatus,
|
||||
getRenderableEstimateDataForSmallButtonsFromGWEI,
|
||||
getDefaultActiveButtonIndex,
|
||||
} from '../../../../../selectors/custom-gas'
|
||||
} from '../../../../selectors/custom-gas'
|
||||
import {
|
||||
showGasButtonGroup,
|
||||
} from '../../../../../ducks/send/send.duck'
|
||||
} from '../../../../ducks/send/send.duck'
|
||||
import {
|
||||
resetCustomData,
|
||||
setCustomGasPrice,
|
||||
setCustomGasLimit,
|
||||
} from '../../../../../ducks/gas/gas.duck'
|
||||
} from '../../../../ducks/gas/gas.duck'
|
||||
import { getGasLoadingError, gasFeeIsInError, getGasButtonGroupShown } from './send-gas-row.selectors.js'
|
||||
import { showModal, setGasPrice, setGasLimit, setGasTotal } from '../../../../../store/actions'
|
||||
import { getAdvancedInlineGasShown, getCurrentEthBalance, getSelectedToken } from '../../../../../selectors/selectors'
|
||||
import { showModal, setGasPrice, setGasLimit, setGasTotal } from '../../../../store/actions'
|
||||
import { getAdvancedInlineGasShown, getCurrentEthBalance, getSelectedToken } from '../../../../selectors/selectors'
|
||||
import SendGasRow from './send-gas-row.component'
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps, mergeProps)(SendGasRow)
|
@ -6,7 +6,7 @@ import SendGasRow from '../send-gas-row.component.js'
|
||||
|
||||
import SendRowWrapper from '../../send-row-wrapper/send-row-wrapper.component'
|
||||
import GasFeeDisplay from '../gas-fee-display/gas-fee-display.component'
|
||||
import GasPriceButtonGroup from '../../../../gas-customization/gas-price-button-group'
|
||||
import GasPriceButtonGroup from '../../../../../components/app/gas-customization/gas-price-button-group'
|
||||
|
||||
const propsMethodSpies = {
|
||||
showCustomizeGasModal: sinon.spy(),
|
@ -32,7 +32,7 @@ proxyquire('../send-gas-row.container.js', {
|
||||
return () => ({})
|
||||
},
|
||||
},
|
||||
'../../../../../selectors/selectors': {
|
||||
'../../../../selectors/selectors': {
|
||||
getCurrentEthBalance: (s) => `mockCurrentEthBalance:${s}`,
|
||||
getAdvancedInlineGasShown: (s) => `mockAdvancedInlineGasShown:${s}`,
|
||||
getSelectedToken: () => false,
|
||||
@ -59,14 +59,14 @@ proxyquire('../send-gas-row.container.js', {
|
||||
gasFeeIsInError: (s) => `mockGasFeeError:${s}`,
|
||||
getGasButtonGroupShown: (s) => `mockGetGasButtonGroupShown:${s}`,
|
||||
},
|
||||
'../../../../../store/actions': actionSpies,
|
||||
'../../../../../selectors/custom-gas': {
|
||||
'../../../../store/actions': actionSpies,
|
||||
'../../../../selectors/custom-gas': {
|
||||
getBasicGasEstimateLoadingStatus: (s) => `mockBasicGasEstimateLoadingStatus:${s}`,
|
||||
getRenderableEstimateDataForSmallButtonsFromGWEI: (s) => `mockGasButtonInfo:${s}`,
|
||||
getDefaultActiveButtonIndex: (gasButtonInfo, gasPrice) => gasButtonInfo.length + gasPrice.length,
|
||||
},
|
||||
'../../../../../ducks/send/send.duck': sendDuckSpies,
|
||||
'../../../../../ducks/gas/gas.duck': gasDuckSpies,
|
||||
'../../../../ducks/send/send.duck': sendDuckSpies,
|
||||
'../../../../ducks/gas/gas.duck': gasDuckSpies,
|
||||
})
|
||||
|
||||
describe('send-gas-row container', () => {
|
@ -1,7 +1,7 @@
|
||||
import { connect } from 'react-redux'
|
||||
import {
|
||||
updateSendHexData,
|
||||
} from '../../../../../store/actions'
|
||||
} from '../../../../store/actions'
|
||||
import SendHexDataRow from './send-hex-data-row.component'
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(SendHexDataRow)
|
@ -1,7 +1,7 @@
|
||||
import React, { Component } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import SendRowWrapper from '../send-row-wrapper'
|
||||
import EnsInput from '../../../ens-input'
|
||||
import EnsInput from '../../../../components/app/ens-input'
|
||||
import { getToErrorObject, getToWarningObject } from './send-to-row.utils.js'
|
||||
|
||||
export default class SendToRow extends Component {
|
@ -14,13 +14,13 @@ import {
|
||||
} from './send-to-row.selectors.js'
|
||||
import {
|
||||
updateSendTo,
|
||||
} from '../../../../../store/actions'
|
||||
} from '../../../../store/actions'
|
||||
import {
|
||||
updateSendErrors,
|
||||
updateSendWarnings,
|
||||
openToDropdown,
|
||||
closeToDropdown,
|
||||
} from '../../../../../ducks/send/send.duck'
|
||||
} from '../../../../ducks/send/send.duck'
|
||||
import SendToRow from './send-to-row.component'
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(SendToRow)
|
@ -4,8 +4,8 @@ const {
|
||||
KNOWN_RECIPIENT_ADDRESS_ERROR,
|
||||
INVALID_RECIPIENT_ADDRESS_NOT_ETH_NETWORK_ERROR,
|
||||
} = require('../../send.constants')
|
||||
const { isValidAddress, isEthNetwork } = require('../../../../../helpers/utils/util')
|
||||
import { checkExistingAddresses } from '../../../../../pages/add-token/util'
|
||||
const { isValidAddress, isEthNetwork } = require('../../../../helpers/utils/util')
|
||||
import { checkExistingAddresses } from '../../../add-token/util'
|
||||
|
||||
const ethUtil = require('ethereumjs-util')
|
||||
const contractMap = require('eth-contract-metadata')
|
@ -16,7 +16,7 @@ const SendToRow = proxyquire('../send-to-row.component.js', {
|
||||
}).default
|
||||
|
||||
import SendRowWrapper from '../../send-row-wrapper/send-row-wrapper.component'
|
||||
import EnsInput from '../../../../ens-input'
|
||||
import EnsInput from '../../../../../components/app/ens-input'
|
||||
|
||||
const propsMethodSpies = {
|
||||
closeToDropdown: sinon.spy(),
|
@ -36,8 +36,8 @@ proxyquire('../send-to-row.container.js', {
|
||||
sendToIsInWarning: (s) => `mockInWarning:${s}`,
|
||||
getTokens: (s) => `mockTokens:${s}`,
|
||||
},
|
||||
'../../../../../store/actions': actionSpies,
|
||||
'../../../../../ducks/send/send.duck': duckActionSpies,
|
||||
'../../../../store/actions': actionSpies,
|
||||
'../../../../ducks/send/send.duck': duckActionSpies,
|
||||
})
|
||||
|
||||
describe('send-to-row container', () => {
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user