aboutsummaryrefslogtreecommitdiffstats
path: root/ui/app/components/pages/add-token.js
diff options
context:
space:
mode:
Diffstat (limited to 'ui/app/components/pages/add-token.js')
-rw-r--r--ui/app/components/pages/add-token.js431
1 files changed, 0 insertions, 431 deletions
diff --git a/ui/app/components/pages/add-token.js b/ui/app/components/pages/add-token.js
deleted file mode 100644
index 8d52571d0..000000000
--- a/ui/app/components/pages/add-token.js
+++ /dev/null
@@ -1,431 +0,0 @@
-const inherits = require('util').inherits
-const Component = require('react').Component
-const classnames = require('classnames')
-const h = require('react-hyperscript')
-const PropTypes = require('prop-types')
-const connect = require('react-redux').connect
-const R = require('ramda')
-const Fuse = require('fuse.js')
-const contractMap = require('eth-contract-metadata')
-const TokenBalance = require('../../components/token-balance')
-const Identicon = require('../../components/identicon')
-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 },
- ],
-})
-const actions = require('../../actions')
-const ethUtil = require('ethereumjs-util')
-const { tokenInfoGetter } = require('../../token-util')
-const { DEFAULT_ROUTE } = require('../../routes')
-
-const emptyAddr = '0x0000000000000000000000000000000000000000'
-
-AddTokenScreen.contextTypes = {
- t: PropTypes.func,
-}
-
-module.exports = connect(mapStateToProps, mapDispatchToProps)(AddTokenScreen)
-
-
-function mapStateToProps (state) {
- const { identities, tokens } = state.metamask
- return {
- identities,
- tokens,
- }
-}
-
-function mapDispatchToProps (dispatch) {
- return {
- addTokens: tokens => dispatch(actions.addTokens(tokens)),
- }
-}
-
-inherits(AddTokenScreen, Component)
-function AddTokenScreen () {
- this.state = {
- isShowingConfirmation: false,
- isShowingInfoBox: true,
- customAddress: '',
- customSymbol: '',
- customDecimals: '',
- searchQuery: '',
- selectedTokens: {},
- errors: {},
- autoFilled: false,
- displayedTab: 'SEARCH',
- }
- this.tokenAddressDidChange = this.tokenAddressDidChange.bind(this)
- this.tokenSymbolDidChange = this.tokenSymbolDidChange.bind(this)
- this.tokenDecimalsDidChange = this.tokenDecimalsDidChange.bind(this)
- this.onNext = this.onNext.bind(this)
- Component.call(this)
-}
-
-AddTokenScreen.prototype.componentWillMount = function () {
- this.tokenInfoGetter = tokenInfoGetter()
-}
-
-AddTokenScreen.prototype.toggleToken = function (address, token) {
- const { selectedTokens = {}, errors } = this.state
- const selectedTokensCopy = { ...selectedTokens }
-
- if (address in selectedTokensCopy) {
- delete selectedTokensCopy[address]
- } else {
- selectedTokensCopy[address] = token
- }
-
- this.setState({
- selectedTokens: selectedTokensCopy,
- errors: {
- ...errors,
- tokenSelector: null,
- },
- })
-}
-
-AddTokenScreen.prototype.onNext = function () {
- const { isValid, errors } = this.validate()
-
- return !isValid
- ? this.setState({ errors })
- : this.setState({ isShowingConfirmation: true })
-}
-
-AddTokenScreen.prototype.tokenAddressDidChange = function (e) {
- const customAddress = e.target.value.trim()
- this.setState({ customAddress })
- if (ethUtil.isValidAddress(customAddress) && customAddress !== emptyAddr) {
- this.attemptToAutoFillTokenParams(customAddress)
- } else {
- this.setState({
- customSymbol: '',
- customDecimals: 0,
- })
- }
-}
-
-AddTokenScreen.prototype.tokenSymbolDidChange = function (e) {
- const customSymbol = e.target.value.trim()
- this.setState({ customSymbol })
-}
-
-AddTokenScreen.prototype.tokenDecimalsDidChange = function (e) {
- const customDecimals = e.target.value.trim()
- this.setState({ customDecimals })
-}
-
-AddTokenScreen.prototype.checkExistingAddresses = function (address) {
- if (!address) return false
- const tokensList = this.props.tokens
- const matchesAddress = existingToken => {
- return existingToken.address.toLowerCase() === address.toLowerCase()
- }
-
- return R.any(matchesAddress)(tokensList)
-}
-
-AddTokenScreen.prototype.validate = function () {
- const errors = {}
- const identitiesList = Object.keys(this.props.identities)
- const { customAddress, customSymbol, customDecimals, selectedTokens } = this.state
- const standardAddress = ethUtil.addHexPrefix(customAddress).toLowerCase()
-
- if (customAddress) {
- const validAddress = ethUtil.isValidAddress(customAddress)
- if (!validAddress) {
- errors.customAddress = this.context.t('invalidAddress')
- }
-
- const validDecimals = customDecimals !== null
- && customDecimals !== ''
- && customDecimals >= 0
- && customDecimals < 36
- if (!validDecimals) {
- errors.customDecimals = this.context.t('decimalsMustZerotoTen')
- }
-
- const symbolLen = customSymbol.trim().length
- const validSymbol = symbolLen > 0 && symbolLen < 10
- if (!validSymbol) {
- errors.customSymbol = this.context.t('symbolBetweenZeroTen')
- }
-
- const ownAddress = identitiesList.includes(standardAddress)
- if (ownAddress) {
- errors.customAddress = this.context.t('personalAddressDetected')
- }
-
- const tokenAlreadyAdded = this.checkExistingAddresses(customAddress)
- if (tokenAlreadyAdded) {
- errors.customAddress = this.context.t('tokenAlreadyAdded')
- }
- } else if (
- Object.entries(selectedTokens)
- .reduce((isEmpty, [ symbol, isSelected ]) => (
- isEmpty && !isSelected
- ), true)
- ) {
- errors.tokenSelector = this.context.t('mustSelectOne')
- }
-
- return {
- isValid: !Object.keys(errors).length,
- errors,
- }
-}
-
-AddTokenScreen.prototype.attemptToAutoFillTokenParams = async function (address) {
- const { symbol, decimals } = await this.tokenInfoGetter(address)
- if (symbol && decimals) {
- this.setState({
- customSymbol: symbol,
- customDecimals: decimals,
- autoFilled: true,
- })
- }
-}
-
-AddTokenScreen.prototype.renderCustomForm = function () {
- const { autoFilled, customAddress, customSymbol, customDecimals, errors } = this.state
-
- return (
- h('div.add-token__add-custom-form', [
- h('div', {
- className: classnames('add-token__add-custom-field', {
- 'add-token__add-custom-field--error': errors.customAddress,
- }),
- }, [
- h('div.add-token__add-custom-label', this.context.t('tokenAddress')),
- h('input.add-token__add-custom-input', {
- type: 'text',
- onChange: this.tokenAddressDidChange,
- value: customAddress,
- }),
- h('div.add-token__add-custom-error-message', errors.customAddress),
- ]),
- h('div', {
- className: classnames('add-token__add-custom-field', {
- 'add-token__add-custom-field--error': errors.customSymbol,
- }),
- }, [
- h('div.add-token__add-custom-label', this.context.t('tokenSymbol')),
- h('input.add-token__add-custom-input', {
- type: 'text',
- onChange: this.tokenSymbolDidChange,
- value: customSymbol,
- disabled: autoFilled,
- }),
- h('div.add-token__add-custom-error-message', errors.customSymbol),
- ]),
- h('div', {
- className: classnames('add-token__add-custom-field', {
- 'add-token__add-custom-field--error': errors.customDecimals,
- }),
- }, [
- h('div.add-token__add-custom-label', this.context.t('decimal')),
- h('input.add-token__add-custom-input', {
- type: 'number',
- onChange: this.tokenDecimalsDidChange,
- value: customDecimals,
- disabled: autoFilled,
- }),
- h('div.add-token__add-custom-error-message', errors.customDecimals),
- ]),
- ])
- )
-}
-
-AddTokenScreen.prototype.renderTokenList = function () {
- const { searchQuery = '', selectedTokens } = this.state
- const fuseSearchResult = fuse.search(searchQuery)
- const addressSearchResult = contractList.filter(token => {
- return token.address.toLowerCase() === searchQuery.toLowerCase()
- })
- const results = [...addressSearchResult, ...fuseSearchResult]
-
- return h('div', [
- results.length > 0 && h('div.add-token__token-icons-title', this.context.t('popularTokens')),
- h('div.add-token__token-icons-container', Array(6).fill(undefined)
- .map((_, i) => {
- const { logo, symbol, name, address } = results[i] || {}
- const tokenAlreadyAdded = this.checkExistingAddresses(address)
- return Boolean(logo || symbol || name) && (
- h('div.add-token__token-wrapper', {
- className: classnames({
- 'add-token__token-wrapper--selected': selectedTokens[address],
- 'add-token__token-wrapper--disabled': tokenAlreadyAdded,
- }),
- onClick: () => !tokenAlreadyAdded && this.toggleToken(address, results[i]),
- }, [
- h('div.add-token__token-icon', {
- style: {
- backgroundImage: logo && `url(images/contract/${logo})`,
- },
- }),
- h('div.add-token__token-data', [
- h('div.add-token__token-symbol', symbol),
- h('div.add-token__token-name', name),
- ]),
- // tokenAlreadyAdded && (
- // h('div.add-token__token-message', 'Already added')
- // ),
- ])
- )
- })),
- ])
-}
-
-AddTokenScreen.prototype.renderConfirmation = function () {
- const {
- customAddress: address,
- customSymbol: symbol,
- customDecimals: decimals,
- selectedTokens,
- } = this.state
-
- const { addTokens, history } = this.props
-
- const customToken = {
- address,
- symbol,
- decimals,
- }
-
- const tokens = address && symbol && decimals
- ? { ...selectedTokens, [address]: customToken }
- : selectedTokens
-
- return (
- h('div.add-token', [
- h('div.add-token__wrapper', [
- h('div.add-token__content-container.add-token__confirmation-content', [
- h('div.add-token__description.add-token__confirmation-description', this.context.t('balances')),
- h('div.add-token__confirmation-token-list',
- Object.entries(tokens)
- .map(([ address, token ]) => (
- h('span.add-token__confirmation-token-list-item', [
- h(Identicon, {
- className: 'add-token__confirmation-token-icon',
- diameter: 75,
- address,
- }),
- h(TokenBalance, { token }),
- ])
- ))
- ),
- ]),
- ]),
- h('div.add-token__buttons', [
- h('button.btn-secondary--lg.add-token__cancel-button', {
- onClick: () => this.setState({ isShowingConfirmation: false }),
- }, this.context.t('back')),
- h('button.btn-primary--lg', {
- onClick: () => addTokens(tokens).then(() => history.push(DEFAULT_ROUTE)),
- }, this.context.t('addTokens')),
- ]),
- ])
- )
-}
-
-AddTokenScreen.prototype.displayTab = function (selectedTab) {
- this.setState({ displayedTab: selectedTab })
-}
-
-AddTokenScreen.prototype.renderTabs = function () {
- const { isShowingInfoBox, displayedTab, errors } = this.state
-
- return displayedTab === 'CUSTOM_TOKEN'
- ? this.renderCustomForm()
- : h('div', [
- h('div.add-token__wrapper', [
- h('div.add-token__content-container', [
- isShowingInfoBox && h('div.add-token__info-box', [
- h('div.add-token__info-box__close', {
- onClick: () => this.setState({ isShowingInfoBox: false }),
- }),
- h('div.add-token__info-box__title', this.context.t('whatsThis')),
- h('div.add-token__info-box__copy', this.context.t('keepTrackTokens')),
- h('a.add-token__info-box__copy--blue', {
- href: 'http://metamask.helpscoutdocs.com/article/16-managing-erc20-tokens',
- target: '_blank',
- }, this.context.t('learnMore')),
- ]),
- h('div.add-token__input-container', [
- h('input.add-token__input', {
- type: 'text',
- placeholder: this.context.t('searchTokens'),
- onChange: e => this.setState({ searchQuery: e.target.value }),
- }),
- h('div.add-token__search-input-error-message', errors.tokenSelector),
- ]),
- this.renderTokenList(),
- ]),
- ]),
- ])
-}
-
-AddTokenScreen.prototype.render = function () {
- const {
- isShowingConfirmation,
- displayedTab,
- } = this.state
- const { history } = this.props
-
- return h('div.add-token', [
- h('div.add-token__header', [
- h('div.add-token__header__cancel', {
- onClick: () => history.push(DEFAULT_ROUTE),
- }, [
- h('i.fa.fa-angle-left.fa-lg'),
- h('span', this.context.t('cancel')),
- ]),
- h('div.add-token__header__title', this.context.t('addTokens')),
- isShowingConfirmation && h('div.add-token__header__subtitle', this.context.t('likeToAddTokens')),
- !isShowingConfirmation && h('div.add-token__header__tabs', [
-
- h('div.add-token__header__tabs__tab', {
- className: classnames('add-token__header__tabs__tab', {
- 'add-token__header__tabs__selected': displayedTab === 'SEARCH',
- 'add-token__header__tabs__unselected': displayedTab !== 'SEARCH',
- }),
- onClick: () => this.displayTab('SEARCH'),
- }, this.context.t('search')),
-
- h('div.add-token__header__tabs__tab', {
- className: classnames('add-token__header__tabs__tab', {
- 'add-token__header__tabs__selected': displayedTab === 'CUSTOM_TOKEN',
- 'add-token__header__tabs__unselected': displayedTab !== 'CUSTOM_TOKEN',
- }),
- onClick: () => this.displayTab('CUSTOM_TOKEN'),
- }, this.context.t('customToken')),
-
- ]),
- ]),
-
- isShowingConfirmation
- ? this.renderConfirmation()
- : this.renderTabs(),
-
- !isShowingConfirmation && h('div.add-token__buttons', [
- h('button.btn-secondary--lg.add-token__cancel-button', {
- onClick: () => history.push(DEFAULT_ROUTE),
- }, this.context.t('cancel')),
- h('button.btn-primary--lg.add-token__confirm-button', {
- onClick: this.onNext,
- }, this.context.t('next')),
- ]),
- ])
-}