From c3bac3d447f8aff54f9257002aca62aaab9a2153 Mon Sep 17 00:00:00 2001 From: gomes <17035424+gomesalexandre@users.noreply.github.com> Date: Mon, 29 Jul 2024 02:18:20 +0300 Subject: [PATCH 1/2] fix: fallback icon for custom token import step (#7429) * chore: zerion market data wip * chore: wire up token price on import * chore: filter by alchemy supported chainIds * chore: hide fiat on input when not available * chore: handle no fiat data in quote tag * chore: more missing fiat handling * chore: even more missing fiat handling * feat: handle custom asset view * fix: asset selection * fix: market data selector * feat: handle JIT market data fetching * chore: first pass address review feedback * chore: first pass kevs review feedback * chore: 2nd pass kevs review feedback * fix: build lint * chore: remove JIT market data logic * chore: remove custom asset prop * chore: lint * fix: ratio calc without market data * feat: improve `` types * fix: derp * fix: more derp * fix: more more derp * fix: derpy derp derp * fix: last derp? * fix: actually last derp fix * feat: pre-rebase mergefixes --------- Co-authored-by: Apotheosis <97164662+0xApotheosis@users.noreply.github.com> Co-authored-by: Apotheosis <0xapotheosis@gmail.com> --- src/components/AssetIcon.tsx | 93 ++++++++++++------- .../components/AssetMenuButton.tsx | 9 +- src/components/ChainMenu.tsx | 4 +- .../components/AssetSummaryStep.tsx | 4 +- .../TradeAssetSearch/Chains/ChainCard.tsx | 1 + .../components/CustomAssetAcknowledgement.tsx | 2 +- .../components/GroupedAssetRow.tsx | 5 +- .../TransactionDetails/TransferColumn.tsx | 2 +- .../components/AssetTransfer.tsx | 2 +- .../components/AssetsTransfers.tsx | 6 +- .../Overview/ThorchainSaversEmpty.tsx | 12 ++- .../ReusableLpStatus/TransactionRow.tsx | 6 +- 12 files changed, 86 insertions(+), 60 deletions(-) diff --git a/src/components/AssetIcon.tsx b/src/components/AssetIcon.tsx index 6c1559c3f3a..d529ca95ece 100644 --- a/src/components/AssetIcon.tsx +++ b/src/components/AssetIcon.tsx @@ -2,6 +2,7 @@ import type { AvatarProps } from '@chakra-ui/react' import { Avatar, Center, Flex, useColorModeValue } from '@chakra-ui/react' import type { AssetId } from '@shapeshiftoss/caip' import { fromAssetId } from '@shapeshiftoss/caip' +import type { Asset } from '@shapeshiftoss/types' import { memo, useMemo } from 'react' import { getChainAdapterManager } from 'context/PluginProvider/chainAdapterSingleton' import { selectAssetById, selectFeeAssetById } from 'state/slices/selectors' @@ -23,34 +24,58 @@ export const sansNotchBottom = 'polygon( 29.875% 95.781%,29.875% 95.781%,32.106% 96.7%,34.39% 97.513%,36.724% 98.218%,39.105% 98.81%,41.529% 99.287%,43.995% 99.646%,46.498% 99.882%,49.036% 99.994%,51.605% 99.977%,54.203% 99.828%,54.203% 99.828%,61.486% 98.674%,68.384% 96.495%,74.816% 93.377%,80.7% 89.403%,85.955% 84.66%,90.5% 79.232%,94.254% 73.203%,97.135% 66.658%,99.062% 59.682%,99.953% 52.359%,99.953% 52.359%,100.006% 49.623%,99.913% 46.921%,99.679% 44.257%,99.307% 41.634%,98.801% 39.057%,98.164% 36.528%,97.401% 34.053%,96.516% 31.635%,95.511% 29.277%,94.391% 26.984%,94.391% 26.984%,94.286% 26.814%,94.163% 26.66%,94.022% 26.523%,93.867% 26.405%,93.699% 26.307%,93.521% 26.23%,93.335% 26.175%,93.143% 26.143%,92.947% 26.137%,92.75% 26.156%,92.75% 26.156%,82.77% 28.407%,73.334% 31.927%,64.536% 36.619%,56.474% 42.387%,49.244% 49.135%,42.943% 56.766%,37.667% 65.185%,33.512% 74.295%,30.575% 84%,28.953% 94.203%,28.953% 94.203%,28.947% 94.403%,28.967% 94.6%,29.01% 94.791%,29.076% 94.973%,29.164% 95.146%,29.273% 95.308%,29.401% 95.456%,29.547% 95.588%,29.711% 95.702%,29.891% 95.797%,29.875% 95.781% );' type AssetIconProps = { - assetId?: AssetId // Show the network icon instead of the asset icon e.g OP icon instead of ETH for Optimism native asset showNetworkIcon?: boolean -} & AvatarProps +} & ( + | { + assetId: AssetId + asset?: undefined + src?: undefined + icon?: undefined + } + | { + asset: Asset + assetId?: undefined + src?: undefined + icon?: undefined + } + | { + src: string | undefined + assetId?: undefined + asset?: undefined + icon?: undefined + } + | { + icon: JSX.Element + src?: undefined + assetId?: undefined + asset?: undefined + } +) & + AvatarProps // @TODO: this will be replaced with whatever we do for icons later // The icon prop is used as the placeholder while the icon loads, or if it fails to load. // Either src or assetId can be passed, if both are passed src takes precedence type AssetWithNetworkProps = { - assetId: AssetId + asset: Asset showNetworkIcon?: boolean } & AvatarProps const AssetWithNetwork: React.FC = ({ - assetId, + asset, icon, src, showNetworkIcon = true, size, ...rest }) => { - const asset = useAppSelector(state => selectAssetById(state, assetId ?? '')) - const feeAsset = useAppSelector(state => selectFeeAssetById(state, assetId)) - const showNetwork = feeAsset?.networkIcon || asset?.assetId !== feeAsset?.assetId - const iconSrc = src ?? asset?.icon + const feeAsset = useAppSelector(state => selectFeeAssetById(state, asset.assetId)) + const showNetwork = feeAsset?.networkIcon || asset.assetId !== feeAsset?.assetId + const iconSrc = src ?? asset.icon // We should only show the fallback if the asset doesn't have an icon/icons // Failure to check this means we would lose loading FOX icon functionality - const showFallback = !asset?.icon && !asset?.icons?.length + const showFallback = !asset.icon && !asset.icons?.length return (
@@ -70,7 +95,7 @@ const AssetWithNetwork: React.FC = ({ )} = ({ ) } -export const AssetIcon = memo(({ assetId, showNetworkIcon, src, ...rest }: AssetIconProps) => { - const asset = useAppSelector(state => selectAssetById(state, assetId ?? '')) - const assetIconBg = useColorModeValue('gray.200', 'gray.700') - const assetIconColor = useColorModeValue('text.subtle', 'text.subtle') +export const AssetIcon = memo( + ({ assetId: _assetId, asset: _asset, showNetworkIcon, src, ...rest }: AssetIconProps) => { + const asset = useAppSelector(state => + _asset ? _asset : selectAssetById(state, _assetId ?? ''), + ) + const assetId = _assetId ?? asset?.assetId + const assetIconBg = useColorModeValue('gray.200', 'gray.700') + const assetIconColor = useColorModeValue('text.subtle', 'text.subtle') - const chainAdapterManager = getChainAdapterManager() - const chainId = assetId && fromAssetId(assetId).chainId - const nativeAssetId = chainAdapterManager.get(chainId ?? '')?.getFeeAssetId() - const foxIcon = useMemo(() => , [assetIconColor]) + const chainAdapterManager = getChainAdapterManager() + const chainId = assetId && fromAssetId(assetId).chainId + const nativeAssetId = chainAdapterManager.get(chainId ?? '')?.getFeeAssetId() + const foxIcon = useMemo( + () => , + [assetIconColor], + ) - if (assetId === nativeAssetId && asset?.networkIcon && showNetworkIcon) { - return - } + if (!asset) return - if (assetId) { - if (asset?.icons?.length) { + if (assetId === nativeAssetId && asset.networkIcon && showNetworkIcon) { + return + } + + if (asset.icons?.length) { return ( {asset.icons.map((iconSrc, i) => ( @@ -108,15 +141,7 @@ export const AssetIcon = memo(({ assetId, showNetworkIcon, src, ...rest }: Asset } return ( - + ) - } - - return -}) + }, +) diff --git a/src/components/AssetSelection/components/AssetMenuButton.tsx b/src/components/AssetSelection/components/AssetMenuButton.tsx index 7f530bf5969..cf9bc7db55b 100644 --- a/src/components/AssetSelection/components/AssetMenuButton.tsx +++ b/src/components/AssetSelection/components/AssetMenuButton.tsx @@ -30,11 +30,10 @@ export const AssetMenuButton = ({ const asset = useAppSelector(state => selectAssetById(state, assetId ?? '')) const icon = useMemo(() => { - return asset?.icons ? ( - - ) : ( - - ) + if (asset?.icons) + return + if (assetId) return + return null }, [asset?.icons, assetId, showNetworkIcon]) const handleAssetClick = useCallback(() => { diff --git a/src/components/ChainMenu.tsx b/src/components/ChainMenu.tsx index 08f273b85eb..b189353a000 100644 --- a/src/components/ChainMenu.tsx +++ b/src/components/ChainMenu.tsx @@ -29,7 +29,7 @@ export type ChainMenuProps = { onMenuOptionClick: (chainId: T) => void } -export const ChainIcon = (props: { chainId: ChainId } & AvatarProps) => { +export const ChainIcon = (props: { chainId: ChainId } & Omit) => { const { chainId, avatarProps } = useMemo(() => { const { chainId, ...avatarProps } = props return { chainId, avatarProps } @@ -43,6 +43,8 @@ export const ChainIcon = (props: { chainId: ChainId } & AvatarProps) => { return feeAssetId }, [chainId]) + if (!feeAssetId) return null + return } diff --git a/src/components/MultiHopTrade/components/MultiHopTradeConfirm/components/AssetSummaryStep.tsx b/src/components/MultiHopTrade/components/MultiHopTradeConfirm/components/AssetSummaryStep.tsx index c77721be519..23a08753f1d 100644 --- a/src/components/MultiHopTrade/components/MultiHopTradeConfirm/components/AssetSummaryStep.tsx +++ b/src/components/MultiHopTrade/components/MultiHopTradeConfirm/components/AssetSummaryStep.tsx @@ -56,8 +56,8 @@ export const AssetSummaryStep = ({ }, [asset.chainId]) const assetIcon = useMemo(() => { - return - }, [asset.icon]) + return + }, [asset.assetId]) return ( = memo(({ chainId, isActive, onClick }) => { const feeAssetId = chainIdToFeeAssetId(chainId) + if (!feeAssetId) throw new Error(`feeAssetId not found for chainId ${chainId}`) const feeAsset = useAppSelector(state => selectAssetById(state, feeAssetId ?? '')) if (!feeAsset) throw new Error(`Fee asset not found for AssetId ${feeAssetId}`) diff --git a/src/components/TradeAssetSearch/components/CustomAssetAcknowledgement.tsx b/src/components/TradeAssetSearch/components/CustomAssetAcknowledgement.tsx index 697ed9618a5..754160ad162 100644 --- a/src/components/TradeAssetSearch/components/CustomAssetAcknowledgement.tsx +++ b/src/components/TradeAssetSearch/components/CustomAssetAcknowledgement.tsx @@ -102,7 +102,7 @@ export const CustomAssetAcknowledgement: React.FC - + - + - + { /> - + = ({ index, compactMode direction={index === 0 ? 'row' : 'row-reverse'} textAlign={index === 0 ? 'left' : 'right'} > - + = ({ > {singleAsset ? ( <> - + { + if (!asset) return + return ( {bnOrZero(cryptoBalance).eq(0) && assetSupportsBuy} - +