1
0
mirror of https://github.com/kremalicious/metamask-extension.git synced 2024-11-24 02:58:09 +01:00
metamask-extension/ui/app/hooks/useTokensToSearch.js
Dan J Miller a9d156e611
Fix and simplify account switching in Swaps (#9549)
* Ensure rendered swap from token balance updates when token balance changes

* Disable account switching on all swaps routes other than build quote
2020-10-12 14:21:01 -02:30

121 lines
4.5 KiB
JavaScript

import { useMemo } from 'react'
import { useSelector } from 'react-redux'
import contractMap from 'eth-contract-metadata'
import BigNumber from 'bignumber.js'
import { isEqual, shuffle } from 'lodash'
import { checksumAddress } from '../helpers/utils/util'
import { getTokenFiatAmount } from '../helpers/utils/token-util'
import { getTokenExchangeRates, getConversionRate, getCurrentCurrency } from '../selectors'
import { getSwapsTokens } from '../ducks/swaps/swaps'
import { useSwapsEthToken } from './useSwapsEthToken'
import { useEqualityCheck } from './useEqualityCheck'
const tokenList = shuffle(Object.entries(contractMap)
.map(([address, tokenData]) => ({ ...tokenData, address: address.toLowerCase() }))
.filter((tokenData) => Boolean(tokenData.erc20)))
export function getRenderableTokenData (token, contractExchangeRates, conversionRate, currentCurrency) {
const { symbol, name, address, iconUrl, string, balance, decimals } = token
const formattedFiat = getTokenFiatAmount(
symbol === 'ETH' ? 1 : contractExchangeRates[address],
conversionRate,
currentCurrency,
string,
symbol,
true,
) || ''
const rawFiat = getTokenFiatAmount(
symbol === 'ETH' ? 1 : contractExchangeRates[address],
conversionRate,
currentCurrency,
string,
symbol,
false,
) || ''
const usedIconUrl = iconUrl || (contractMap[checksumAddress(address)] && `images/contract/${contractMap[checksumAddress(address)].logo}`)
return {
...token,
primaryLabel: symbol,
secondaryLabel: name || contractMap[checksumAddress(address)]?.name,
rightPrimaryLabel: string && `${(new BigNumber(string)).round(6).toString()} ${symbol}`,
rightSecondaryLabel: formattedFiat,
iconUrl: usedIconUrl,
identiconAddress: usedIconUrl ? null : address,
balance,
decimals,
name: name || contractMap[checksumAddress(address)]?.name,
rawFiat,
}
}
export function useTokensToSearch ({
providedTokens,
usersTokens = [],
topTokens = {},
onlyEth,
singleToken,
}) {
const tokenConversionRates = useSelector(getTokenExchangeRates, isEqual)
const conversionRate = useSelector(getConversionRate)
const currentCurrency = useSelector(getCurrentCurrency)
const memoizedTopTokens = useEqualityCheck(topTokens)
const memoizedUsersToken = useEqualityCheck(usersTokens)
const swapsEthToken = useSwapsEthToken()
const ethToken = getRenderableTokenData(
swapsEthToken,
tokenConversionRates,
conversionRate,
currentCurrency,
)
const memoizedEthToken = useEqualityCheck(ethToken)
const swapsTokens = useSelector(getSwapsTokens) || []
let tokensToSearch
if (onlyEth) {
tokensToSearch = [memoizedEthToken]
} else if (singleToken) {
tokensToSearch = providedTokens
} else if (providedTokens) {
tokensToSearch = [memoizedEthToken, ...providedTokens]
} else if (swapsTokens.length) {
tokensToSearch = [memoizedEthToken, ...swapsTokens]
} else {
tokensToSearch = [memoizedEthToken, ...tokenList]
}
const memoizedTokensToSearch = useEqualityCheck(tokensToSearch)
return useMemo(() => {
const usersTokensAddressMap = memoizedUsersToken.reduce((acc, token) => ({ ...acc, [token.address]: token }), {})
const tokensToSearchBuckets = {
owned: singleToken ? [] : [memoizedEthToken],
top: [],
others: [],
}
memoizedTokensToSearch.forEach((token) => {
const renderableDataToken = getRenderableTokenData({ ...usersTokensAddressMap[token.address], ...token }, tokenConversionRates, conversionRate, currentCurrency)
if (usersTokensAddressMap[token.address] && ((renderableDataToken.symbol === 'ETH') || Number(renderableDataToken.balance ?? 0) !== 0)) {
tokensToSearchBuckets.owned.push(renderableDataToken)
} else if (memoizedTopTokens[token.address]) {
tokensToSearchBuckets.top[memoizedTopTokens[token.address].index] = renderableDataToken
} else {
tokensToSearchBuckets.others.push(renderableDataToken)
}
})
tokensToSearchBuckets.owned = tokensToSearchBuckets.owned.sort(({ rawFiat }, { rawFiat: secondRawFiat }) => {
return ((new BigNumber(rawFiat || 0)).gt(secondRawFiat || 0) ? -1 : 1)
})
tokensToSearchBuckets.top = tokensToSearchBuckets.top.filter((token) => token)
return [
...tokensToSearchBuckets.owned,
...tokensToSearchBuckets.top,
...tokensToSearchBuckets.others,
]
}, [memoizedTokensToSearch, memoizedUsersToken, tokenConversionRates, conversionRate, currentCurrency, memoizedTopTokens, memoizedEthToken, singleToken])
}