import React, { Component } from 'react'; import PropTypes from 'prop-types'; import Button from '../../components/ui/button'; import Identicon from '../../components/ui/identicon'; import TokenBalance from '../../components/ui/token-balance'; import { getEnvironmentType } from '../../../../app/scripts/lib/util'; import { ENVIRONMENT_TYPE_NOTIFICATION } from '../../../../shared/constants/app'; export default class ConfirmAddSuggestedToken extends Component { static contextTypes = { t: PropTypes.func, trackEvent: PropTypes.func, }; static propTypes = { history: PropTypes.object, addToken: PropTypes.func, mostRecentOverviewPage: PropTypes.string.isRequired, pendingTokens: PropTypes.object, removeSuggestedTokens: PropTypes.func, tokens: PropTypes.array, }; componentDidMount() { this._checkPendingTokens(); } componentDidUpdate() { this._checkPendingTokens(); } _checkPendingTokens() { const { mostRecentOverviewPage, pendingTokens = {}, history } = this.props; if (Object.keys(pendingTokens).length > 0) { return; } if (getEnvironmentType() === ENVIRONMENT_TYPE_NOTIFICATION) { global.platform.closeCurrentWindow(); } else { history.push(mostRecentOverviewPage); } } getTokenName(name, symbol) { return typeof name === 'undefined' ? symbol : `${name} (${symbol})`; } render() { const { addToken, pendingTokens, tokens, removeSuggestedTokens, history, mostRecentOverviewPage, } = this.props; const pendingTokenKey = Object.keys(pendingTokens)[0]; const pendingToken = pendingTokens[pendingTokenKey]; const hasTokenDuplicates = this.checkTokenDuplicates(pendingTokens, tokens); const reusesName = this.checkNameReuse(pendingTokens, tokens); return (
{this.context.t('addSuggestedTokens')}
{this.context.t('likeToAddTokens')}
{hasTokenDuplicates ? (
{this.context.t('knownTokenWarning')}
) : null} {reusesName ? (
{this.context.t('reusedTokenNameWarning')}
) : null}
{this.context.t('token')}
{this.context.t('balance')}
{Object.entries(pendingTokens).map(([address, token]) => { const { name, symbol, image } = token; return (
{this.getTokenName(name, symbol)}
); })}
); } checkTokenDuplicates(pendingTokens, tokens) { const pending = Object.keys(pendingTokens); const existing = tokens.map((token) => token.address); const dupes = pending.filter((proposed) => { return existing.includes(proposed); }); return dupes.length > 0; } /** * Returns true if any pendingTokens both: * - Share a symbol with an existing `tokens` member. * - Does not share an address with that same `tokens` member. * This should be flagged as possibly deceptive or confusing. */ checkNameReuse(pendingTokens, tokens) { const duplicates = Object.keys(pendingTokens) .map((addr) => pendingTokens[addr]) .filter((token) => { const dupes = tokens .filter((old) => old.symbol === token.symbol) .filter((old) => old.address !== token.address); return dupes.length > 0; }); return duplicates.length > 0; } }