aboutsummaryrefslogtreecommitdiffstats
path: root/ui/app/components/pages/add-token
diff options
context:
space:
mode:
Diffstat (limited to 'ui/app/components/pages/add-token')
-rw-r--r--ui/app/components/pages/add-token/add-token.component.js335
-rw-r--r--ui/app/components/pages/add-token/add-token.container.js22
-rw-r--r--ui/app/components/pages/add-token/index.js2
-rw-r--r--ui/app/components/pages/add-token/index.scss45
-rw-r--r--ui/app/components/pages/add-token/token-list/index.js2
-rw-r--r--ui/app/components/pages/add-token/token-list/index.scss65
-rw-r--r--ui/app/components/pages/add-token/token-list/token-list-placeholder/index.js2
-rw-r--r--ui/app/components/pages/add-token/token-list/token-list-placeholder/index.scss23
-rw-r--r--ui/app/components/pages/add-token/token-list/token-list-placeholder/token-list-placeholder.component.js27
-rw-r--r--ui/app/components/pages/add-token/token-list/token-list.component.js60
-rw-r--r--ui/app/components/pages/add-token/token-list/token-list.container.js11
-rw-r--r--ui/app/components/pages/add-token/token-search/index.js2
-rw-r--r--ui/app/components/pages/add-token/token-search/token-search.component.js85
-rw-r--r--ui/app/components/pages/add-token/util.js13
14 files changed, 0 insertions, 694 deletions
diff --git a/ui/app/components/pages/add-token/add-token.component.js b/ui/app/components/pages/add-token/add-token.component.js
deleted file mode 100644
index 198889cf2..000000000
--- a/ui/app/components/pages/add-token/add-token.component.js
+++ /dev/null
@@ -1,335 +0,0 @@
-import React, { Component } from 'react'
-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 TextField from '../../text-field'
-import TokenList from './token-list'
-import TokenSearch from './token-search'
-import PageContainer from '../../page-container'
-import { Tabs, Tab } from '../../tabs'
-
-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,
- forceEditSymbol: false,
- }
- }
-
- 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 >= 12) {
- customSymbolError = this.context.t('symbolBetweenZeroTwelve')
- }
-
- 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,
- forceEditSymbol,
- } = this.state
-
- return (
- <div className="add-token__custom-token-form">
- <TextField
- id="custom-address"
- label={this.context.t('tokenContractAddress')}
- type="text"
- value={customAddress}
- onChange={e => this.handleCustomAddressChange(e.target.value)}
- error={customAddressError}
- fullWidth
- margin="normal"
- />
- <TextField
- id="custom-symbol"
- label={(
- <div className="add-token__custom-symbol__label-wrapper">
- <span className="add-token__custom-symbol__label">
- {this.context.t('tokenSymbol')}
- </span>
- {(autoFilled && !forceEditSymbol) && (
- <div
- className="add-token__custom-symbol__edit"
- onClick={() => this.setState({ forceEditSymbol: true })}
- >
- {this.context.t('edit')}
- </div>
- )}
- </div>
- )}
- type="text"
- value={customSymbol}
- onChange={e => this.handleCustomSymbolChange(e.target.value)}
- error={customSymbolError}
- fullWidth
- margin="normal"
- disabled={autoFilled && !forceEditSymbol}
- />
- <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>
- )
- }
-
- renderTabs () {
- return (
- <Tabs>
- <Tab name={this.context.t('search')}>
- { this.renderSearchToken() }
- </Tab>
- <Tab name={this.context.t('customToken')}>
- { this.renderCustomTokenForm() }
- </Tab>
- </Tabs>
- )
- }
-
- render () {
- const { history, clearPendingTokens } = this.props
-
- return (
- <PageContainer
- title={this.context.t('addTokens')}
- tabsComponent={this.renderTabs()}
- onSubmit={() => this.handleNext()}
- disabled={this.hasError() || !this.hasSelected()}
- onCancel={() => {
- clearPendingTokens()
- history.push(DEFAULT_ROUTE)
- }}
- />
- )
- }
-}
-
-export default AddToken
diff --git a/ui/app/components/pages/add-token/add-token.container.js b/ui/app/components/pages/add-token/add-token.container.js
deleted file mode 100644
index 87671b156..000000000
--- a/ui/app/components/pages/add-token/add-token.container.js
+++ /dev/null
@@ -1,22 +0,0 @@
-import { connect } from 'react-redux'
-import AddToken from './add-token.component'
-
-const { setPendingTokens, clearPendingTokens } = 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()),
- }
-}
-
-export default connect(mapStateToProps, mapDispatchToProps)(AddToken)
diff --git a/ui/app/components/pages/add-token/index.js b/ui/app/components/pages/add-token/index.js
deleted file mode 100644
index 3666cae82..000000000
--- a/ui/app/components/pages/add-token/index.js
+++ /dev/null
@@ -1,2 +0,0 @@
-import AddToken from './add-token.container'
-module.exports = AddToken
diff --git a/ui/app/components/pages/add-token/index.scss b/ui/app/components/pages/add-token/index.scss
deleted file mode 100644
index 1690c7654..000000000
--- a/ui/app/components/pages/add-token/index.scss
+++ /dev/null
@@ -1,45 +0,0 @@
-@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;
- }
-
- &__custom-symbol {
-
- &__label-wrapper {
- display: flex;
- flex-flow: row nowrap;
- }
-
- &__label {
- flex: 0 0 auto;
- }
-
- &__edit {
- flex: 1 1 auto;
- text-align: right;
- color: $curious-blue;
- padding-right: 4px;
- cursor: pointer;
- }
- }
-}
diff --git a/ui/app/components/pages/add-token/token-list/index.js b/ui/app/components/pages/add-token/token-list/index.js
deleted file mode 100644
index 21dd5ac72..000000000
--- a/ui/app/components/pages/add-token/token-list/index.js
+++ /dev/null
@@ -1,2 +0,0 @@
-import TokenList from './token-list.container'
-module.exports = TokenList
diff --git a/ui/app/components/pages/add-token/token-list/index.scss b/ui/app/components/pages/add-token/token-list/index.scss
deleted file mode 100644
index e32739d59..000000000
--- a/ui/app/components/pages/add-token/token-list/index.scss
+++ /dev/null
@@ -1,65 +0,0 @@
-@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;
- }
-}
diff --git a/ui/app/components/pages/add-token/token-list/token-list-placeholder/index.js b/ui/app/components/pages/add-token/token-list/token-list-placeholder/index.js
deleted file mode 100644
index b82f45e93..000000000
--- a/ui/app/components/pages/add-token/token-list/token-list-placeholder/index.js
+++ /dev/null
@@ -1,2 +0,0 @@
-import TokenListPlaceholder from './token-list-placeholder.component'
-module.exports = TokenListPlaceholder
diff --git a/ui/app/components/pages/add-token/token-list/token-list-placeholder/index.scss b/ui/app/components/pages/add-token/token-list/token-list-placeholder/index.scss
deleted file mode 100644
index cc495dfb0..000000000
--- a/ui/app/components/pages/add-token/token-list/token-list-placeholder/index.scss
+++ /dev/null
@@ -1,23 +0,0 @@
-.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;
- }
-}
diff --git a/ui/app/components/pages/add-token/token-list/token-list-placeholder/token-list-placeholder.component.js b/ui/app/components/pages/add-token/token-list/token-list-placeholder/token-list-placeholder.component.js
deleted file mode 100644
index 20f550927..000000000
--- a/ui/app/components/pages/add-token/token-list/token-list-placeholder/token-list-placeholder.component.js
+++ /dev/null
@@ -1,27 +0,0 @@
-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">
- { this.context.t('addAcquiredTokens') }
- </div>
- <a
- className="token-list-placeholder__link"
- href="https://metamask.zendesk.com/hc/en-us/articles/360015489031"
- target="_blank"
- rel="noopener noreferrer"
- >
- { this.context.t('learnMore') }
- </a>
- </div>
- )
- }
-}
diff --git a/ui/app/components/pages/add-token/token-list/token-list.component.js b/ui/app/components/pages/add-token/token-list/token-list.component.js
deleted file mode 100644
index 724a68d6e..000000000
--- a/ui/app/components/pages/add-token/token-list/token-list.component.js
+++ /dev/null
@@ -1,60 +0,0 @@
-import React, { Component } from 'react'
-import PropTypes from 'prop-types'
-import classnames from 'classnames'
-import { checkExistingAddresses } from '../util'
-import TokenListPlaceholder from './token-list-placeholder'
-
-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">
- { 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)
-
- return Boolean(logo || symbol || name) && (
- <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>
- )
- })
- }
- </div>
- </div>
- )
- }
-}
diff --git a/ui/app/components/pages/add-token/token-list/token-list.container.js b/ui/app/components/pages/add-token/token-list/token-list.container.js
deleted file mode 100644
index cd7b07a37..000000000
--- a/ui/app/components/pages/add-token/token-list/token-list.container.js
+++ /dev/null
@@ -1,11 +0,0 @@
-import { connect } from 'react-redux'
-import TokenList from './token-list.component'
-
-const mapStateToProps = ({ metamask }) => {
- const { tokens } = metamask
- return {
- tokens,
- }
-}
-
-export default connect(mapStateToProps)(TokenList)
diff --git a/ui/app/components/pages/add-token/token-search/index.js b/ui/app/components/pages/add-token/token-search/index.js
deleted file mode 100644
index acaa6b084..000000000
--- a/ui/app/components/pages/add-token/token-search/index.js
+++ /dev/null
@@ -1,2 +0,0 @@
-import TokenSearch from './token-search.component'
-module.exports = TokenSearch
diff --git a/ui/app/components/pages/add-token/token-search/token-search.component.js b/ui/app/components/pages/add-token/token-search/token-search.component.js
deleted file mode 100644
index 036b2db1e..000000000
--- a/ui/app/components/pages/add-token/token-search/token-search.component.js
+++ /dev/null
@@ -1,85 +0,0 @@
-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={this.context.t('searchTokens')}
- type="text"
- value={searchQuery}
- onChange={e => this.handleSearch(e.target.value)}
- error={error}
- fullWidth
- startAdornment={this.renderAdornment()}
- />
- )
- }
-}
diff --git a/ui/app/components/pages/add-token/util.js b/ui/app/components/pages/add-token/util.js
deleted file mode 100644
index 579c56cc0..000000000
--- a/ui/app/components/pages/add-token/util.js
+++ /dev/null
@@ -1,13 +0,0 @@
-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)
-}