affected components to new files

This commit is contained in:
Victor Baranov 2018-09-18 14:21:32 +03:00
parent 2393f3691b
commit 984c4594e3
30 changed files with 991 additions and 59 deletions

View File

@ -21,9 +21,8 @@ const NoticeScreen = require('./components/notice')
const generateLostAccountsNotice = require('../lib/lost-accounts-notice')
// other views
const ConfigScreen = require('./config')
// const AddTokenScreen = require('../../ui/app/components/pages/add-token')
const AddTokenScreen = require('./add-token')
const ConfirmAddTokenScreen = require('../../ui/app/components/pages/confirm-add-token')
const AddTokenScreen = require('./components/add-token.js')
const ConfirmAddTokenScreen = require('./components/confirm-add-token')
const RemoveTokenScreen = require('./remove-token')
const Import = require('./accounts/import')
const InfoScreen = require('./info')

View File

@ -2,15 +2,15 @@ const React = require('react')
const { Component } = React
const h = require('react-hyperscript')
const connect = require('react-redux').connect
const actions = require('../../ui/app/actions')
const actions = require('../../../ui/app/actions')
const { setPendingTokens, clearPendingTokens, displayWarning, goHome, addToken } = actions
const Tooltip = require('./components/tooltip.js')
const TabBar = require('./components/tab-bar')
const Tooltip = require('./tooltip.js')
const TabBar = require('./tab-bar')
// const { CONFIRM_ADD_TOKEN_ROUTE } = require('../../ui/app/routes')
const { checkExistingAddresses } = require('../../ui/app/components/pages/add-token/util')
const TokenList = require('../../ui/app/components/pages/add-token/token-list')
const TokenSearch = require('../../ui/app/components/pages/add-token/token-search')
const { tokenInfoGetter } = require('../../ui/app/token-util')
const { checkExistingAddresses } = require('../../../ui/app/components/pages/add-token/util')
const TokenList = require('../../../ui/app/components/pages/add-token/token-list')
const TokenSearch = require('../../../ui/app/components/pages/add-token/token-search')
const { tokenInfoGetter } = require('../../../ui/app/token-util')
const ethUtil = require('ethereumjs-util')
const abi = require('human-standard-token-abi')
const Eth = require('ethjs-query')
@ -311,7 +311,7 @@ class AddTokenScreen extends Component {
goHome()
},
}, 'Cancel' /* this.context.t('cancel')*/),
h('button', {
h('button.btn-primary', {
onClick: () => this.handleNext(),
disabled: this.hasError() || !this.hasSelected(),
}, 'Next' /* this.context.t('next')*/),

View File

@ -0,0 +1,351 @@
import React, { Component } from 'react'
import classnames from 'classnames'
import PropTypes from 'prop-types'
import ethUtil from 'ethereumjs-util'
import { checkExistingAddresses } from './util'
import { tokenInfoGetter } from '../../../token-util'
import { DEFAULT_ROUTE, CONFIRM_ADD_TOKEN_ROUTE } from '../../../routes'
import Button from '../../button'
import TextField from '../../text-field'
import TokenList from './token-list'
import TokenSearch from './token-search'
const emptyAddr = '0x0000000000000000000000000000000000000000'
const SEARCH_TAB = 'SEARCH'
const CUSTOM_TOKEN_TAB = 'CUSTOM_TOKEN'
class AddToken extends Component {
static contextTypes = {
t: PropTypes.func,
}
static propTypes = {
history: PropTypes.object,
setPendingTokens: PropTypes.func,
pendingTokens: PropTypes.object,
clearPendingTokens: PropTypes.func,
tokens: PropTypes.array,
identities: PropTypes.object,
}
constructor (props) {
super(props)
this.state = {
customAddress: '',
customSymbol: '',
customDecimals: 0,
searchResults: [],
selectedTokens: {},
tokenSelectorError: null,
customAddressError: null,
customSymbolError: null,
customDecimalsError: null,
autoFilled: false,
displayedTab: SEARCH_TAB,
}
}
componentDidMount () {
this.tokenInfoGetter = tokenInfoGetter()
const { pendingTokens = {} } = this.props
const pendingTokenKeys = Object.keys(pendingTokens)
if (pendingTokenKeys.length > 0) {
let selectedTokens = {}
let customToken = {}
pendingTokenKeys.forEach(tokenAddress => {
const token = pendingTokens[tokenAddress]
const { isCustom } = token
if (isCustom) {
customToken = { ...token }
} else {
selectedTokens = { ...selectedTokens, [tokenAddress]: { ...token } }
}
})
const {
address: customAddress = '',
symbol: customSymbol = '',
decimals: customDecimals = 0,
} = customToken
const displayedTab = Object.keys(selectedTokens).length > 0 ? SEARCH_TAB : CUSTOM_TOKEN_TAB
this.setState({ selectedTokens, customAddress, customSymbol, customDecimals, displayedTab })
}
}
handleToggleToken (token) {
const { address } = token
const { selectedTokens = {} } = this.state
const selectedTokensCopy = { ...selectedTokens }
if (address in selectedTokensCopy) {
delete selectedTokensCopy[address]
} else {
selectedTokensCopy[address] = token
}
this.setState({
selectedTokens: selectedTokensCopy,
tokenSelectorError: null,
})
}
hasError () {
const {
tokenSelectorError,
customAddressError,
customSymbolError,
customDecimalsError,
} = this.state
return tokenSelectorError || customAddressError || customSymbolError || customDecimalsError
}
hasSelected () {
const { customAddress = '', selectedTokens = {} } = this.state
return customAddress || Object.keys(selectedTokens).length > 0
}
handleNext () {
if (this.hasError()) {
return
}
if (!this.hasSelected()) {
this.setState({ tokenSelectorError: this.context.t('mustSelectOne') })
return
}
const { setPendingTokens, history } = this.props
const {
customAddress: address,
customSymbol: symbol,
customDecimals: decimals,
selectedTokens,
} = this.state
const customToken = {
address,
symbol,
decimals,
}
setPendingTokens({ customToken, selectedTokens })
history.push(CONFIRM_ADD_TOKEN_ROUTE)
}
async attemptToAutoFillTokenParams (address) {
const { symbol = '', decimals = 0 } = await this.tokenInfoGetter(address)
const autoFilled = Boolean(symbol && decimals)
this.setState({ autoFilled })
this.handleCustomSymbolChange(symbol || '')
this.handleCustomDecimalsChange(decimals)
}
handleCustomAddressChange (value) {
const customAddress = value.trim()
this.setState({
customAddress,
customAddressError: null,
tokenSelectorError: null,
autoFilled: false,
})
const isValidAddress = ethUtil.isValidAddress(customAddress)
const standardAddress = ethUtil.addHexPrefix(customAddress).toLowerCase()
switch (true) {
case !isValidAddress:
this.setState({
customAddressError: this.context.t('invalidAddress'),
customSymbol: '',
customDecimals: 0,
customSymbolError: null,
customDecimalsError: null,
})
break
case Boolean(this.props.identities[standardAddress]):
this.setState({
customAddressError: this.context.t('personalAddressDetected'),
})
break
case checkExistingAddresses(customAddress, this.props.tokens):
this.setState({
customAddressError: this.context.t('tokenAlreadyAdded'),
})
break
default:
if (customAddress !== emptyAddr) {
this.attemptToAutoFillTokenParams(customAddress)
}
}
}
handleCustomSymbolChange (value) {
const customSymbol = value.trim()
const symbolLength = customSymbol.length
let customSymbolError = null
if (symbolLength <= 0 || symbolLength >= 10) {
customSymbolError = this.context.t('symbolBetweenZeroTen')
}
this.setState({ customSymbol, customSymbolError })
}
handleCustomDecimalsChange (value) {
const customDecimals = value.trim()
const validDecimals = customDecimals !== null &&
customDecimals !== '' &&
customDecimals >= 0 &&
customDecimals < 36
let customDecimalsError = null
if (!validDecimals) {
customDecimalsError = this.context.t('decimalsMustZerotoTen')
}
this.setState({ customDecimals, customDecimalsError })
}
renderCustomTokenForm () {
const {
customAddress,
customSymbol,
customDecimals,
customAddressError,
customSymbolError,
customDecimalsError,
autoFilled,
} = this.state
return (
<div className="add-token__custom-token-form">
<TextField
id="custom-address"
label={this.context.t('tokenAddress')}
type="text"
value={customAddress}
onChange={e => this.handleCustomAddressChange(e.target.value)}
error={customAddressError}
fullWidth
margin="normal"
/>
<TextField
id="custom-symbol"
label={this.context.t('tokenSymbol')}
type="text"
value={customSymbol}
onChange={e => this.handleCustomSymbolChange(e.target.value)}
error={customSymbolError}
fullWidth
margin="normal"
disabled={autoFilled}
/>
<TextField
id="custom-decimals"
label={this.context.t('decimal')}
type="number"
value={customDecimals}
onChange={e => this.handleCustomDecimalsChange(e.target.value)}
error={customDecimalsError}
fullWidth
margin="normal"
disabled={autoFilled}
/>
</div>
)
}
renderSearchToken () {
const { tokenSelectorError, selectedTokens, searchResults } = this.state
return (
<div className="add-token__search-token">
<TokenSearch
onSearch={({ results = [] }) => this.setState({ searchResults: results })}
error={tokenSelectorError}
/>
<div className="add-token__token-list">
<TokenList
results={searchResults}
selectedTokens={selectedTokens}
onToggleToken={token => this.handleToggleToken(token)}
/>
</div>
</div>
)
}
render () {
const { displayedTab } = this.state
const { history, clearPendingTokens } = this.props
return (
<div className="page-container">
<div className="page-container__header page-container__header--no-padding-bottom">
<div className="page-container__title">
{ this.context.t('addTokens') }
</div>
<div className="page-container__tabs">
<div
className={classnames('page-container__tab', {
'page-container__tab--selected': displayedTab === SEARCH_TAB,
})}
onClick={() => this.setState({ displayedTab: SEARCH_TAB })}
>
{ this.context.t('search') }
</div>
<div
className={classnames('page-container__tab', {
'page-container__tab--selected': displayedTab === CUSTOM_TOKEN_TAB,
})}
onClick={() => this.setState({ displayedTab: CUSTOM_TOKEN_TAB })}
>
{ this.context.t('customToken') }
</div>
</div>
</div>
<div className="page-container__content">
{
displayedTab === CUSTOM_TOKEN_TAB
? this.renderCustomTokenForm()
: this.renderSearchToken()
}
</div>
<div className="page-container__footer">
<Button
type="default"
large
className="page-container__footer-button"
onClick={() => {
clearPendingTokens()
history.push(DEFAULT_ROUTE)
}}
>
{ this.context.t('cancel') }
</Button>
<Button
type="primary"
large
className="page-container__footer-button"
onClick={() => this.handleNext()}
disabled={this.hasError() || !this.hasSelected()}
>
{ this.context.t('next') }
</Button>
</div>
</div>
)
}
}
export default AddToken

View File

@ -0,0 +1,23 @@
import { connect } from 'react-redux'
import AddToken from './add-token.component'
const { setPendingTokens, clearPendingTokens, showConfirmAddTokenPage } = require('../../../actions')
const mapStateToProps = ({ metamask }) => {
const { identities, tokens, pendingTokens } = metamask
return {
identities,
tokens,
pendingTokens,
}
}
const mapDispatchToProps = dispatch => {
return {
setPendingTokens: tokens => dispatch(setPendingTokens(tokens)),
clearPendingTokens: () => dispatch(clearPendingTokens()),
showConfirmAddTokenPage: () => dispatch(showConfirmAddTokenPage()),
}
}
export default connect(mapStateToProps, mapDispatchToProps)(AddToken)

View File

@ -0,0 +1,2 @@
import AddToken from './add-token.container'
module.exports = AddToken

View File

@ -0,0 +1,25 @@
@import './token-list/index';
.add-token {
&__custom-token-form {
padding: 8px 16px 16px;
input[type="number"]::-webkit-inner-spin-button {
-webkit-appearance: none;
display: none;
}
input[type="number"]:hover::-webkit-inner-spin-button {
-webkit-appearance: none;
display: none;
}
}
&__search-token {
padding: 16px;
}
&__token-list {
margin-top: 16px;
}
}

View File

@ -0,0 +1,2 @@
import TokenList from './token-list.container'
module.exports = TokenList

View File

@ -0,0 +1,65 @@
@import './token-list-placeholder/index';
.token-list {
&__title {
font-size: .75rem;
}
&__tokens-container {
display: flex;
flex-direction: column;
}
&__token {
transition: 200ms ease-in-out;
display: flex;
flex-flow: row nowrap;
align-items: center;
padding: 8px;
margin-top: 8px;
box-sizing: border-box;
border-radius: 10px;
cursor: pointer;
border: 2px solid transparent;
position: relative;
&:hover {
border: 2px solid rgba($malibu-blue, .5);
}
&--selected {
border: 2px solid $malibu-blue !important;
}
&--disabled {
opacity: .4;
pointer-events: none;
}
}
&__token-icon {
width: 48px;
height: 48px;
background-repeat: no-repeat;
background-size: contain;
background-position: center;
border-radius: 50%;
background-color: $white;
box-shadow: 0 2px 4px 0 rgba($black, .24);
margin-right: 12px;
flex: 0 0 auto;
}
&__token-data {
display: flex;
flex-direction: row;
align-items: center;
min-width: 0;
}
&__token-name {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
}

View File

@ -0,0 +1,2 @@
import TokenListPlaceholder from './token-list-placeholder.component'
module.exports = TokenListPlaceholder

View File

@ -0,0 +1,23 @@
.token-list-placeholder {
display: flex;
align-items: center;
padding-top: 36px;
flex-direction: column;
line-height: 22px;
opacity: .5;
&__text {
color: $silver-chalice;
width: 50%;
text-align: center;
margin-top: 8px;
@media screen and (max-width: 575px) {
width: 60%;
}
}
&__link {
color: $curious-blue;
}
}

View File

@ -0,0 +1,19 @@
import React, { Component } from 'react'
import PropTypes from 'prop-types'
export default class TokenListPlaceholder extends Component {
static contextTypes = {
t: PropTypes.func,
}
render () {
return (
<div className="token-list-placeholder">
<img src="images/tokensearch.svg" />
<div className="token-list-placeholder__text">
{`Add the tokens you've acquired using Nifty Wallet` /* this.context.t('addAcquiredTokens')*/}
</div>
</div>
)
}
}

View File

@ -0,0 +1,72 @@
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import classnames from 'classnames'
import { checkExistingAddresses } from '../util'
import TokenListPlaceholder from './token-list-placeholder'
import h from 'react-hyperscript'
import Tooltip from '../../tooltip.js'
export default class InfoBox extends Component {
static contextTypes = {
t: PropTypes.func,
}
static propTypes = {
tokens: PropTypes.array,
results: PropTypes.array,
selectedTokens: PropTypes.object,
onToggleToken: PropTypes.func,
}
render () {
const { results = [], selectedTokens = {}, onToggleToken, tokens = [] } = this.props
return results.length === 0
? <TokenListPlaceholder />
: (
<div className="token-list">
<div className="token-list__title">
{ 'searchResults' /* this.context.t('searchResults')*/ }
</div>
<div className="token-list__tokens-container">
{
Array(6).fill(undefined)
.map((_, i) => {
const { logo, symbol, name, address } = results[i] || {}
const tokenAlreadyAdded = checkExistingAddresses(address, tokens)
const title = `${name} (${symbol})`
const isLongTitle = title.length > 28
const tokenRow = (key) => h(`.${classnames('token-list__token', {
'token-list__token--selected': selectedTokens[address],
'token-list__token--disabled': tokenAlreadyAdded,
}).split(' ').join('.')}`, {
onClick: () => !tokenAlreadyAdded && onToggleToken(results[i]),
key: key || 'tokenRow',
}, [
h('.token-list__token-icon', {
style: {
backgroundImage: logo && `url(images/contract/${logo})`,
},
}),
h('.token-list__token-data', [
h('span.token-list__token-name', title),
]),
])
return Boolean(logo || symbol || name) && (
isLongTitle ? h(Tooltip, {
position: 'top',
title: title,
key: i,
}, [
tokenRow(),
]) : tokenRow(i)
)
})
}
</div>
</div>
)
}
}

View File

@ -0,0 +1,11 @@
import { connect } from 'react-redux'
import TokenList from './token-list.component'
const mapStateToProps = ({ metamask }) => {
const { tokens } = metamask
return {
tokens,
}
}
export default connect(mapStateToProps)(TokenList)

View File

@ -0,0 +1,2 @@
import TokenSearch from './token-search.component'
module.exports = TokenSearch

View File

@ -0,0 +1,85 @@
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import contractMap from 'eth-contract-metadata'
import Fuse from 'fuse.js'
import InputAdornment from '@material-ui/core/InputAdornment'
import TextField from '../../../text-field'
const contractList = Object.entries(contractMap)
.map(([ _, tokenData]) => tokenData)
.filter(tokenData => Boolean(tokenData.erc20))
const fuse = new Fuse(contractList, {
shouldSort: true,
threshold: 0.45,
location: 0,
distance: 100,
maxPatternLength: 32,
minMatchCharLength: 1,
keys: [
{ name: 'name', weight: 0.5 },
{ name: 'symbol', weight: 0.5 },
],
})
export default class TokenSearch extends Component {
static contextTypes = {
t: PropTypes.func,
}
static defaultProps = {
error: null,
}
static propTypes = {
onSearch: PropTypes.func,
error: PropTypes.string,
}
constructor (props) {
super(props)
this.state = {
searchQuery: '',
}
}
handleSearch (searchQuery) {
this.setState({ searchQuery })
const fuseSearchResult = fuse.search(searchQuery)
const addressSearchResult = contractList.filter(token => {
return token.address.toLowerCase() === searchQuery.toLowerCase()
})
const results = [...addressSearchResult, ...fuseSearchResult]
this.props.onSearch({ searchQuery, results })
}
renderAdornment () {
return (
<InputAdornment
position="start"
style={{ marginRight: '12px' }}
>
<img src="images/search.svg" />
</InputAdornment>
)
}
render () {
const { error } = this.props
const { searchQuery } = this.state
return (
<TextField
id="search-tokens"
placeholder={'Search Tokens' /* this.context.t('searchTokens')*/}
type="text"
value={searchQuery}
onChange={e => this.handleSearch(e.target.value)}
error={error}
fullWidth
startAdornment={this.renderAdornment()}
/>
)
}
}

View File

@ -0,0 +1,13 @@
import R from 'ramda'
export function checkExistingAddresses (address, tokenList = []) {
if (!address) {
return false
}
const matchesAddress = existingToken => {
return existingToken.address.toLowerCase() === address.toLowerCase()
}
return R.any(matchesAddress)(tokenList)
}

View File

@ -0,0 +1,118 @@
import React, { Component } from 'react'
import PropTypes from 'prop-types'
// import { DEFAULT_ROUTE, ADD_TOKEN_ROUTE } from '../../../routes'
import Button from '../../../../ui/app/components/button'
import Identicon from '../identicon'
import TokenBalance from './token-balance'
export default class ConfirmAddToken extends Component {
static contextTypes = {
t: PropTypes.func,
}
static propTypes = {
// history: PropTypes.object,
clearPendingTokens: PropTypes.func,
addTokens: PropTypes.func,
pendingTokens: PropTypes.object,
goHome: PropTypes.func,
}
componentDidMount () {
const { pendingTokens = {}, goHome /*, history*/ } = this.props
if (Object.keys(pendingTokens).length === 0) {
goHome()
// history.push(DEFAULT_ROUTE)
}
}
getTokenName (name, symbol) {
return typeof name === 'undefined'
? symbol
: `${name} (${symbol})`
}
render () {
const { /* history,*/ addTokens, clearPendingTokens, pendingTokens, goHome } = this.props
const areMultipleTokens = pendingTokens && Object.keys(pendingTokens).length > 1
return (
<div className="page-container">
<div className="page-container__header">
<h2 className="page-subtitle">
{ 'Add Tokens' /* this.context.t('addTokens')*/ }
</h2>
<p className="confirm-label">
{ areMultipleTokens ? 'Would you like to add these tokens?' : 'Would you like to add this token?' /* this.context.t('likeToAddTokens')*/ }
</p>
</div>
<div className="page-container__content">
<div className="confirm-add-token">
<div className="confirm-add-token__header">
<div className="confirm-add-token__token">
{ 'Token' /* this.context.t('token')*/ }
</div>
<div className="confirm-add-token__balance">
{ 'Balance' /* this.context.t('balance')*/ }
</div>
</div>
<div className="confirm-add-token__token-list">
{
pendingTokens && Object.entries(pendingTokens)
.map(([ address, token ]) => {
const { name, symbol } = token
return (
<div
className="confirm-add-token__token-list-item"
key={address}
>
<div className="confirm-add-token__token confirm-add-token__data">
<Identicon
className="confirm-add-token__token-icon"
diameter={48}
address={address}
/>
<div className="confirm-add-token__name">
{ this.getTokenName(name, symbol) }
</div>
</div>
<div className="confirm-add-token__balance">
<TokenBalance token={token} />
</div>
</div>
)
})
}
</div>
</div>
</div>
<div className="page-container__footer">
<div className="page-container__footer-container">
<Button
type="default"
className="btn-violet"
onClick={() => goHome()}// history.push(ADD_TOKEN_ROUTE)}
>
{ 'Cancel' /* this.context.t('back')*/ }
</Button>
<Button
type="primary"
onClick={() => {
addTokens(pendingTokens)
.then(() => {
clearPendingTokens()
goHome()
// history.push(DEFAULT_ROUTE)
})
}}
>
{ 'Add Tokens' /* this.context.t('addTokens')*/ }
</Button>
</div>
</div>
</div>
)
}
}

View File

@ -0,0 +1,21 @@
import { connect } from 'react-redux'
import ConfirmAddToken from './confirm-add-token.component'
const { addTokens, clearPendingTokens, goHome } = require('../../../../ui/app/actions')
const mapStateToProps = ({ metamask }) => {
const { pendingTokens } = metamask
return {
pendingTokens,
}
}
const mapDispatchToProps = dispatch => {
return {
addTokens: tokens => dispatch(addTokens(tokens)),
clearPendingTokens: () => dispatch(clearPendingTokens()),
goHome: () => dispatch(goHome()),
}
}
export default connect(mapStateToProps, mapDispatchToProps)(ConfirmAddToken)

View File

@ -0,0 +1,2 @@
import ConfirmAddToken from './confirm-add-token.container'
module.exports = ConfirmAddToken

View File

@ -0,0 +1,69 @@
.confirm-add-token {
padding: 16px;
&__header {
font-size: .75rem;
display: flex;
}
&__token {
flex: 1;
min-width: 0;
}
&__balance {
flex: 0 0 30%;
min-width: 0;
}
&__token-list {
display: flex;
flex-flow: column nowrap;
.token-balance {
display: flex;
flex-flow: row nowrap;
align-items: flex-start;
&__amount {
color: $scorpion;
font-size: 43px;
line-height: 43px;
margin-right: 8px;
}
&__symbol {
color: $scorpion;
font-size: 16px;
font-weight: 400;
line-height: 24px;
}
}
}
&__token-list-item {
display: flex;
flex-flow: row nowrap;
align-items: center;
margin-top: 8px;
box-sizing: border-box;
}
&__data {
display: flex;
align-items: center;
padding: 8px;
}
&__name {
min-width: 0;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
&__token-icon {
margin-right: 12px;
flex: 0 0 auto;
}
}

View File

@ -0,0 +1,2 @@
import TokenBalance from './token-balance.container'
module.exports = TokenBalance

View File

@ -0,0 +1,16 @@
import React, { Component } from 'react'
import PropTypes from 'prop-types'
export default class TokenBalance extends Component {
static propTypes = {
string: PropTypes.string,
symbol: PropTypes.string,
error: PropTypes.string,
}
render () {
return (
<div className="hide-text-overflow">{ this.props.string }</div>
)
}
}

View File

@ -0,0 +1,16 @@
import { connect } from 'react-redux'
import { compose } from 'recompose'
import withTokenTracker from '../../../../../ui/app/helpers/with-token-tracker'
import TokenBalance from './token-balance.component'
import selectors from '../../../../../ui/app/selectors'
const mapStateToProps = state => {
return {
userAddress: selectors.getSelectedAddress(state),
}
}
export default compose(
connect(mapStateToProps),
withTokenTracker
)(TokenBalance)

2
package-lock.json generated
View File

@ -8453,7 +8453,7 @@
}
},
"eth-contract-metadata": {
"version": "github:MetaMask/eth-contract-metadata#966a891dd9c79b873fd8968a0155b067ca630502",
"version": "github:MetaMask/eth-contract-metadata#bd23fa120512dcbb6fad31559297f96f17c3a8e0",
"from": "github:MetaMask/eth-contract-metadata#master"
},
"eth-ens-namehash": {

View File

@ -1,7 +1,7 @@
import { connect } from 'react-redux'
import AddToken from './add-token.component'
const { setPendingTokens, clearPendingTokens, showConfirmAddTokenPage } = require('../../../actions')
const { setPendingTokens, clearPendingTokens } = require('../../../actions')
const mapStateToProps = ({ metamask }) => {
const { identities, tokens, pendingTokens } = metamask
@ -16,8 +16,7 @@ const mapDispatchToProps = dispatch => {
return {
setPendingTokens: tokens => dispatch(setPendingTokens(tokens)),
clearPendingTokens: () => dispatch(clearPendingTokens()),
showConfirmAddTokenPage: () => dispatch(showConfirmAddTokenPage()),
}
}
export default connect(mapStateToProps, mapDispatchToProps)(AddToken)
export default connect(mapStateToProps, mapDispatchToProps)(AddToken)

View File

@ -11,9 +11,17 @@ export default class TokenListPlaceholder extends Component {
<div className="token-list-placeholder">
<img src="images/tokensearch.svg" />
<div className="token-list-placeholder__text">
{`Add the tokens you've acquired using Nifty Wallet` /* this.context.t('addAcquiredTokens')*/}
{ this.context.t('addAcquiredTokens') }
</div>
<a
className="token-list-placeholder__link"
href="https://consensys.zendesk.com/hc/en-us/articles/360004135092"
target="_blank"
rel="noopener noreferrer"
>
{ this.context.t('learnMore') }
</a>
</div>
)
}
}
}

View File

@ -3,8 +3,6 @@ import PropTypes from 'prop-types'
import classnames from 'classnames'
import { checkExistingAddresses } from '../util'
import TokenListPlaceholder from './token-list-placeholder'
import h from 'react-hyperscript'
import Tooltip from '../../../../../../old-ui/app/components/tooltip.js'
export default class InfoBox extends Component {
static contextTypes = {
@ -26,7 +24,7 @@ export default class InfoBox extends Component {
: (
<div className="token-list">
<div className="token-list__title">
{ 'searchResults' /* this.context.t('searchResults')*/ }
{ this.context.t('searchResults') }
</div>
<div className="token-list__tokens-container">
{
@ -34,34 +32,24 @@ export default class InfoBox extends Component {
.map((_, i) => {
const { logo, symbol, name, address } = results[i] || {}
const tokenAlreadyAdded = checkExistingAddresses(address, tokens)
const title = `${name} (${symbol})`
const isLongTitle = title.length > 28
const tokenRow = (key) => h(`.${classnames('token-list__token', {
'token-list__token--selected': selectedTokens[address],
'token-list__token--disabled': tokenAlreadyAdded,
}).split(' ').join('.')}`, {
onClick: () => !tokenAlreadyAdded && onToggleToken(results[i]),
key: key || 'tokenRow',
}, [
h('.token-list__token-icon', {
style: {
backgroundImage: logo && `url(images/contract/${logo})`,
},
}),
h('.token-list__token-data', [
h('span.token-list__token-name', title),
]),
])
return Boolean(logo || symbol || name) && (
isLongTitle ? h(Tooltip, {
position: 'top',
title: title,
key: i,
}, [
tokenRow(),
]) : tokenRow(i)
<div
className={classnames('token-list__token', {
'token-list__token--selected': selectedTokens[address],
'token-list__token--disabled': tokenAlreadyAdded,
})}
onClick={() => !tokenAlreadyAdded && onToggleToken(results[i])}
key={i}
>
<div
className="token-list__token-icon"
style={{ backgroundImage: logo && `url(images/contract/${logo})` }}>
</div>
<div className="token-list__token-data">
<span className="token-list__token-name">{ `${name} (${symbol})` }</span>
</div>
</div>
)
})
}
@ -69,4 +57,4 @@ export default class InfoBox extends Component {
</div>
)
}
}
}

View File

@ -72,7 +72,7 @@ export default class TokenSearch extends Component {
return (
<TextField
id="search-tokens"
placeholder={'Search Tokens' /* this.context.t('searchTokens')*/}
placeholder={this.context.t('searchTokens')}
type="text"
value={searchQuery}
onChange={e => this.handleSearch(e.target.value)}

View File

@ -1,6 +1,6 @@
import React, { Component } from 'react'
import PropTypes from 'prop-types'
// import { DEFAULT_ROUTE, ADD_TOKEN_ROUTE } from '../../../routes'
import { DEFAULT_ROUTE, ADD_TOKEN_ROUTE } from '../../../routes'
import Button from '../../button'
import Identicon from '../../../components/identicon'
import TokenBalance from './token-balance'
@ -11,7 +11,7 @@ export default class ConfirmAddToken extends Component {
}
static propTypes = {
// history: PropTypes.object,
history: PropTypes.object,
clearPendingTokens: PropTypes.func,
addTokens: PropTypes.func,
pendingTokens: PropTypes.object,
@ -19,11 +19,11 @@ export default class ConfirmAddToken extends Component {
}
componentDidMount () {
const { pendingTokens = {}, goHome /*, history*/ } = this.props
const { pendingTokens = {}, goHome , history } = this.props
if (Object.keys(pendingTokens).length === 0) {
goHome()
// history.push(DEFAULT_ROUTE)
history.push(DEFAULT_ROUTE)
}
}
@ -34,7 +34,7 @@ export default class ConfirmAddToken extends Component {
}
render () {
const { /* history,*/ addTokens, clearPendingTokens, pendingTokens, goHome } = this.props
const { history, addTokens, clearPendingTokens, pendingTokens, goHome } = this.props
const areMultipleTokens = pendingTokens && Object.keys(pendingTokens).length > 1
return (
@ -93,7 +93,7 @@ export default class ConfirmAddToken extends Component {
<Button
type="default"
className="btn-violet"
onClick={() => goHome()}// history.push(ADD_TOKEN_ROUTE)}
onClick={() => history.push(ADD_TOKEN_ROUTE)}
>
{ 'Cancel' /* this.context.t('back')*/ }
</Button>
@ -103,8 +103,8 @@ export default class ConfirmAddToken extends Component {
addTokens(pendingTokens)
.then(() => {
clearPendingTokens()
goHome()
// history.push(DEFAULT_ROUTE)
//goHome()
history.push(DEFAULT_ROUTE)
})
}}
>

View File

@ -1,7 +1,7 @@
import { connect } from 'react-redux'
import ConfirmAddToken from './confirm-add-token.component'
const { addTokens, clearPendingTokens, goHome } = require('../../../actions')
const { addTokens, clearPendingTokens } = require('../../../actions')
const mapStateToProps = ({ metamask }) => {
const { pendingTokens } = metamask
@ -14,8 +14,7 @@ const mapDispatchToProps = dispatch => {
return {
addTokens: tokens => dispatch(addTokens(tokens)),
clearPendingTokens: () => dispatch(clearPendingTokens()),
goHome: () => dispatch(goHome()),
}
}
export default connect(mapStateToProps, mapDispatchToProps)(ConfirmAddToken)
export default connect(mapStateToProps, mapDispatchToProps)(ConfirmAddToken)