import React, { Component } from 'react'; import PropTypes from 'prop-types'; import SendRowWrapper from '../send-row-wrapper'; import Identicon from '../../../../components/ui/identicon'; import TokenBalance from '../../../../components/ui/token-balance'; import TokenListDisplay from '../../../../components/app/token-list-display'; import UserPreferencedCurrencyDisplay from '../../../../components/app/user-preferenced-currency-display'; import { PRIMARY } from '../../../../helpers/constants/common'; import { isEqualCaseInsensitive } from '../../../../../shared/modules/string-utils'; import { MetaMetricsEventCategory } from '../../../../../shared/constants/metametrics'; import { AssetType, TokenStandard, } from '../../../../../shared/constants/transaction'; import { Text } from '../../../../components/component-library'; import { TextVariant } from '../../../../helpers/constants/design-system'; export default class SendAssetRow extends Component { static propTypes = { tokens: PropTypes.arrayOf( PropTypes.shape({ address: PropTypes.string, decimals: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), symbol: PropTypes.string, image: PropTypes.string, }), ).isRequired, accounts: PropTypes.object.isRequired, selectedAddress: PropTypes.string.isRequired, sendAsset: PropTypes.object, updateSendAsset: PropTypes.func.isRequired, nativeCurrency: PropTypes.string, nativeCurrencyImage: PropTypes.string, nfts: PropTypes.arrayOf( PropTypes.shape({ address: PropTypes.string.isRequired, tokenId: PropTypes.string.isRequired, name: PropTypes.string, description: PropTypes.string, image: PropTypes.string, standard: PropTypes.string, imageThumbnail: PropTypes.string, imagePreview: PropTypes.string, creator: PropTypes.shape({ address: PropTypes.string, config: PropTypes.string, profile_img_url: PropTypes.string, }), }), ), collections: PropTypes.arrayOf( PropTypes.shape({ address: PropTypes.string.isRequired, name: PropTypes.string, }), ), }; static contextTypes = { t: PropTypes.func, trackEvent: PropTypes.func, }; state = { isShowingDropdown: false, sendableTokens: [], sendableNfts: [], }; async componentDidMount() { const sendableTokens = this.props.tokens.filter((token) => !token.isERC721); const sendableNfts = this.props.nfts.filter( (nft) => nft.isCurrentlyOwned && nft.standard === TokenStandard.ERC721, ); this.setState({ sendableTokens, sendableNfts }); } openDropdown = () => this.setState({ isShowingDropdown: true }); closeDropdown = () => this.setState({ isShowingDropdown: false }); getAssetSelected = (type, token) => { switch (type) { case AssetType.native: return this.props.nativeCurrency; case AssetType.token: return TokenStandard.ERC20; case AssetType.NFT: return token?.standard; default: return null; } }; selectToken = (type, token) => { this.setState( { isShowingDropdown: false, }, () => { this.context.trackEvent({ category: MetaMetricsEventCategory.Transactions, event: 'User clicks "Assets" dropdown', properties: { action: 'Send Screen', legacy_event: true, assetSelected: this.getAssetSelected(type, token), }, }); this.props.updateSendAsset({ type, details: type === AssetType.native ? null : token, }); }, ); }; render() { const { t } = this.context; return (
{this.renderSendAsset()}
{[...this.state.sendableTokens, ...this.state.sendableNfts].length > 0 ? this.renderAssetDropdown() : null}
); } renderSendAsset() { const { sendAsset: { details, type }, tokens, nfts, } = this.props; if (type === AssetType.token) { const token = tokens.find(({ address }) => isEqualCaseInsensitive(address, details.address), ); if (token) { return this.renderToken(token); } return this.renderToken(details); } else if (type === AssetType.NFT) { const nft = nfts.find( ({ address, tokenId }) => isEqualCaseInsensitive(address, details.address) && tokenId === details.tokenId, ); if (nft || details) { return this.renderNft(nft ?? details); } } return this.renderNativeCurrency(); } renderAssetDropdown() { return ( this.state.isShowingDropdown && (
{this.renderNativeCurrency(true)} this.selectToken(AssetType.token, token)} /> {this.state.sendableNfts.map((nft) => this.renderNft(nft, true))}
) ); } renderNativeCurrency(insideDropdown = false) { const { t } = this.context; const { accounts, selectedAddress, nativeCurrency, nativeCurrencyImage } = this.props; const { sendableTokens, sendableNfts } = this.state; const balanceValue = accounts[selectedAddress] ? accounts[selectedAddress].balance : ''; const sendableAssets = [...sendableTokens, ...sendableNfts]; return (
0 ? 'send-v2__asset-dropdown__asset' : 'send-v2__asset-dropdown__single-asset' } onClick={() => this.selectToken(AssetType.native)} >
{nativeCurrency}
{`${t('balance')}:`}
{!insideDropdown && sendableAssets.length > 0 && ( )}
); } renderToken(token, insideDropdown = false) { const { address, symbol, image } = token; const { t } = this.context; return (
this.selectToken(AssetType.token, token)} >
{symbol}
{`${t('balance')}:`}
{!insideDropdown && ( )}
); } renderNft(nft, insideDropdown = false) { const { address, name, image, tokenId } = nft; const { t } = this.context; const nftCollection = this.props.collections.find( (collection) => collection.address === address, ); const label = nftCollection?.name || name; return (
this.selectToken(AssetType.NFT, nft)} >
{label}
{`${t('tokenId')}: ${tokenId}`}
{!insideDropdown && ( )}
); } }