From 638dd952d0171057ab48fec505309b6752ddb0a6 Mon Sep 17 00:00:00 2001 From: XiaoYhun Date: Mon, 18 Sep 2023 22:05:10 +0700 Subject: [PATCH 01/15] update assetId and hooks to use new params --- src/components/KyberAITokenBanner/index.tsx | 8 +- src/pages/App.tsx | 2 +- src/pages/ProAmmPools/KyberAIModalInPool.tsx | 6 +- src/pages/TrueSightV2/components/CexRekt.tsx | 13 +- .../components/DisplaySettings.tsx | 4 +- .../components/KyberAIShareModal.tsx | 4 +- .../TrueSightV2/components/KyberAIWidget.tsx | 9 +- .../components/SearchWithDropDown.tsx | 20 ++- .../components/TimeFrameLegend.tsx | 4 +- .../TrueSightV2/components/TokenOverview.tsx | 4 +- .../TrueSightV2/components/chart/datafeed.tsx | 4 +- .../TrueSightV2/components/chart/index.tsx | 49 +++---- src/pages/TrueSightV2/components/index.tsx | 4 +- .../shareContent/ExploreTopShareContent.tsx | 4 +- .../shareContent/KyberScoreShareContent.tsx | 4 +- .../TrueSightV2/components/table/index.tsx | 136 +++++++----------- .../hooks/useIsReachMaxLimitWatchedToken.tsx | 16 +-- .../hooks/useKyberAIAssetOverview.tsx | 22 +++ .../TrueSightV2/hooks/useKyberAIData.tsx | 27 ++-- .../hooks/useKyberAITokenOverview.tsx | 13 -- src/pages/TrueSightV2/pages/SingleToken.tsx | 100 ++++++------- .../TrueSightV2/pages/TechnicalAnalysis.tsx | 27 ++-- .../TrueSightV2/pages/TokenAnalysisList.tsx | 105 +++----------- src/pages/TrueSightV2/types/index.tsx | 8 +- 24 files changed, 247 insertions(+), 346 deletions(-) create mode 100644 src/pages/TrueSightV2/hooks/useKyberAIAssetOverview.tsx delete mode 100644 src/pages/TrueSightV2/hooks/useKyberAITokenOverview.tsx diff --git a/src/components/KyberAITokenBanner/index.tsx b/src/components/KyberAITokenBanner/index.tsx index 5ee3825895..84893a8175 100644 --- a/src/components/KyberAITokenBanner/index.tsx +++ b/src/components/KyberAITokenBanner/index.tsx @@ -22,7 +22,7 @@ import useTheme from 'hooks/useTheme' import KyberScoreMeter from 'pages/TrueSightV2/components/KyberScoreMeter' import { NETWORK_TO_CHAINID } from 'pages/TrueSightV2/constants' import { SUPPORTED_NETWORK_KYBERAI } from 'pages/TrueSightV2/constants/index' -import { useTokenDetailQuery } from 'pages/TrueSightV2/hooks/useKyberAIData' +import { useTokenOverviewQuery } from 'pages/TrueSightV2/hooks/useKyberAIData' import { calculateValueToColor } from 'pages/TrueSightV2/utils' import { useIsWhiteListKyberAI } from 'state/user/hooks' import { MEDIA_WIDTHS } from 'theme' @@ -47,17 +47,17 @@ const KyberAITokenBanner = ({ const { isStableCoin } = useStableCoins(chainId) - const { data: tokenInputOverview } = useTokenDetailQuery( + const { data: tokenInputOverview } = useTokenOverviewQuery( { address: token0?.address, chain }, { skip: !token0?.address || !account || !isWhiteList || !chain, refetchOnMountOrArgChange: true }, ) - const { data: tokenOutputOverview } = useTokenDetailQuery( + const { data: tokenOutputOverview } = useTokenOverviewQuery( { address: token1?.address, chain }, { skip: !token1?.address || !account || !isWhiteList || !chain, refetchOnMountOrArgChange: true }, ) - const { data: tokenNativeOverview } = useTokenDetailQuery( + const { data: tokenNativeOverview } = useTokenOverviewQuery( { address: NativeCurrencies[chainId].wrapped.address, chain }, { skip: !account || !isWhiteList || !chain, refetchOnMountOrArgChange: true }, ) diff --git a/src/pages/App.tsx b/src/pages/App.tsx index 0d636745c7..e7584ae04c 100644 --- a/src/pages/App.tsx +++ b/src/pages/App.tsx @@ -390,7 +390,7 @@ export default function App() { } /> diff --git a/src/pages/ProAmmPools/KyberAIModalInPool.tsx b/src/pages/ProAmmPools/KyberAIModalInPool.tsx index a2bfdee408..3360fc1521 100644 --- a/src/pages/ProAmmPools/KyberAIModalInPool.tsx +++ b/src/pages/ProAmmPools/KyberAIModalInPool.tsx @@ -19,7 +19,7 @@ import useTheme from 'hooks/useTheme' import KyberScoreMeter from 'pages/TrueSightV2/components/KyberScoreMeter' import SimpleTooltip from 'pages/TrueSightV2/components/SimpleTooltip' import { SUPPORTED_NETWORK_KYBERAI } from 'pages/TrueSightV2/constants/index' -import { useTokenDetailQuery } from 'pages/TrueSightV2/hooks/useKyberAIData' +import { useTokenOverviewQuery } from 'pages/TrueSightV2/hooks/useKyberAIData' import { calculateValueToColor, formatTokenPrice, navigateToSwapPage } from 'pages/TrueSightV2/utils' import { useIsWhiteListKyberAI } from 'state/user/hooks' @@ -99,11 +99,11 @@ const KyberAIModalInPool = ({ currency0, currency1 }: { currency0?: Currency; cu const [tab, setTab] = useState(TokenTabType.First) const [openTruesightModal, setOpenTruesightModal] = useState(false) - const { data: token0Overview } = useTokenDetailQuery( + const { data: token0Overview } = useTokenOverviewQuery( { address: currency0?.wrapped?.address, chain: SUPPORTED_NETWORK_KYBERAI[chainId] }, { skip: !currency0?.wrapped?.address && !isWhiteList, refetchOnMountOrArgChange: true }, ) - const { data: token1Overview } = useTokenDetailQuery( + const { data: token1Overview } = useTokenOverviewQuery( { address: currency1?.wrapped?.address, chain: SUPPORTED_NETWORK_KYBERAI[chainId] }, { skip: !currency1?.wrapped?.address && !isWhiteList, refetchOnMountOrArgChange: true }, ) diff --git a/src/pages/TrueSightV2/components/CexRekt.tsx b/src/pages/TrueSightV2/components/CexRekt.tsx index aa13785b55..c8b6703139 100644 --- a/src/pages/TrueSightV2/components/CexRekt.tsx +++ b/src/pages/TrueSightV2/components/CexRekt.tsx @@ -27,11 +27,14 @@ const Card = styled.div` export default function CexRekt() { const above768 = useMedia(`(min-width:${MEDIA_WIDTHS.upToSmall}px)`) const { address, chain } = useParams() - const { data } = useCexesLiquidationQuery({ - tokenAddress: address, - chartSize: '1m', - chain, - }) + const { data } = useCexesLiquidationQuery( + { + tokenAddress: address, + chartSize: '1m', + chain, + }, + { skip: !chain || !address }, + ) return ( <> diff --git a/src/pages/TrueSightV2/components/DisplaySettings.tsx b/src/pages/TrueSightV2/components/DisplaySettings.tsx index a538e47723..1f1f66ebda 100644 --- a/src/pages/TrueSightV2/components/DisplaySettings.tsx +++ b/src/pages/TrueSightV2/components/DisplaySettings.tsx @@ -19,7 +19,7 @@ import { ApplicationModal } from 'state/application/actions' import { useToggleModal } from 'state/application/hooks' import { useTokenAnalysisSettings, useUpdateTokenAnalysisSettings } from 'state/user/hooks' -import useKyberAITokenOverview from '../hooks/useKyberAITokenOverview' +import useKyberAIAssetOverview from '../hooks/useKyberAIAssetOverview' import { HeaderButton } from '../pages/SingleToken' import { DiscoverTokenTab } from '../types' @@ -112,7 +112,7 @@ export default function DisplaySettings({ currentTab }: { currentTab: DiscoverTo const storedTokenAnalysisSettings = useTokenAnalysisSettings() const updateTokenAnalysisSettings = useUpdateTokenAnalysisSettings() const toggleTutorial = useToggleModal(ApplicationModal.KYBERAI_TUTORIAL) - const { data: token } = useKyberAITokenOverview() + const { data: token } = useKyberAIAssetOverview() const { chain } = useParams() const ref = useRef(null) useOnClickOutside(ref, () => { diff --git a/src/pages/TrueSightV2/components/KyberAIShareModal.tsx b/src/pages/TrueSightV2/components/KyberAIShareModal.tsx index 153f06d6c5..b808b1b9e5 100644 --- a/src/pages/TrueSightV2/components/KyberAIShareModal.tsx +++ b/src/pages/TrueSightV2/components/KyberAIShareModal.tsx @@ -24,7 +24,7 @@ import { downloadImage } from 'utils/index' import { getProxyTokenLogo } from 'utils/tokenInfo' import { NETWORK_IMAGE_URL } from '../constants' -import useKyberAITokenOverview from '../hooks/useKyberAITokenOverview' +import useKyberAIAssetOverview from '../hooks/useKyberAIAssetOverview' import KyberSwapShareLogo from './KyberSwapShareLogo' import LoadingTextAnimation from './LoadingTextAnimation' import { InfoWrapper, LegendWrapper } from './chart' @@ -208,7 +208,7 @@ export default function KyberAIShareModal({ }) { const theme = useTheme() const { chain } = useParams() - const { data: tokenOverview } = useKyberAITokenOverview() + const { data: tokenOverview } = useKyberAIAssetOverview() const ref = useRef(null) const refMobile = useRef(null) diff --git a/src/pages/TrueSightV2/components/KyberAIWidget.tsx b/src/pages/TrueSightV2/components/KyberAIWidget.tsx index 37e77c908b..c908d5ebfb 100644 --- a/src/pages/TrueSightV2/components/KyberAIWidget.tsx +++ b/src/pages/TrueSightV2/components/KyberAIWidget.tsx @@ -353,7 +353,6 @@ export default function Widget() { isLoading={isFetching} isError={isError} onRowClick={() => setShowExpanded(false)} - activeTab={activeTab} /> )} @@ -471,13 +470,7 @@ const KyberAIWidgetMobileContent = ({
- +
diff --git a/src/pages/TrueSightV2/components/SearchWithDropDown.tsx b/src/pages/TrueSightV2/components/SearchWithDropDown.tsx index a543996385..3df6a4f1d9 100644 --- a/src/pages/TrueSightV2/components/SearchWithDropDown.tsx +++ b/src/pages/TrueSightV2/components/SearchWithDropDown.tsx @@ -18,19 +18,17 @@ import { useOnClickOutside } from 'hooks/useOnClickOutside' import useTheme from 'hooks/useTheme' import { MEDIA_WIDTHS } from 'theme' -import { KYBERAI_LISTYPE_TO_MIXPANEL, NETWORK_IMAGE_URL } from '../constants' +import { KYBERAI_LISTYPE_TO_MIXPANEL } from '../constants' import { useLazySearchTokenQuery, useSearchTokenQuery, useTokenListQuery } from '../hooks/useKyberAIData' import { ITokenList, ITokenSearchResult, KyberAIListType } from '../types' import { formatTokenPrice } from '../utils' const formatTokenType = (token: ITokenList): ITokenSearchResult => { - const token0 = token.tokens[0] return { - address: token0.address, + assetId: token.asset_id, name: token.name, symbol: token.symbol, - logo: token0.logo, - chain: token0.chain, + logo: token.tokens[0].logo, price: token.price, priceChange24h: token.percent_change_24h, kyberScore: { @@ -206,7 +204,7 @@ const TokenItem = ({ token, onClick }: { token: ITokenSearchResult; onClick?: () { onClick?.() - navigate(`${APP_PATHS.KYBERAI_EXPLORE}/${token.chain}/${token.address}`) + navigate(`${APP_PATHS.KYBERAI_EXPLORE}/${token.assetId}`) }} > @@ -231,13 +229,13 @@ const TokenItem = ({ token, onClick }: { token: ITokenSearchResult; onClick?: () backgroundColor: theme.tableHeader, }} > - eth + /> */} @@ -322,7 +320,7 @@ const SearchWithDropdown = () => { ) const [history, setHistory] = useLocalStorage>('kyberai-search-history') const saveToHistory = (token: ITokenSearchResult) => { - if (!(history && history.findIndex(t => t.address === token.address && t.chain === token.chain) >= 0)) { + if (!(history && history.findIndex(t => t.assetId === token.assetId) >= 0)) { setHistory([token, ...(history || [])].slice(0, 3)) } } @@ -333,7 +331,7 @@ const SearchWithDropdown = () => { const fetchHistoryTokenInfo = async () => { const results = await Promise.all( history.map(t => { - return getTokenData({ q: t.address, size: 1 }, true).unwrap() + return getTokenData({ q: t.assetId, size: 1 }, true).unwrap() }), ) setHistory(results.map(res => res[0])) @@ -407,7 +405,7 @@ const SearchWithDropdown = () => { {searchResult.map(item => ( { setExpanded(false) diff --git a/src/pages/TrueSightV2/components/TimeFrameLegend.tsx b/src/pages/TrueSightV2/components/TimeFrameLegend.tsx index f1b9df1bc0..9bb47749a9 100644 --- a/src/pages/TrueSightV2/components/TimeFrameLegend.tsx +++ b/src/pages/TrueSightV2/components/TimeFrameLegend.tsx @@ -3,7 +3,7 @@ import styled, { css } from 'styled-components' import { MIXPANEL_TYPE, useMixpanelKyberAI } from 'hooks/useMixpanel' -import useKyberAITokenOverview from '../hooks/useKyberAITokenOverview' +import useKyberAIAssetOverview from '../hooks/useKyberAIAssetOverview' import { KyberAITimeframe } from '../types' const TimeFrameWrapper = styled.div` @@ -72,7 +72,7 @@ const TimeFrameLegend = ({ const ref = useRef(null) const [left, setLeft] = useState(0) const [width, setWidth] = useState(0) - const { data: token } = useKyberAITokenOverview() + const { data: token } = useKyberAIAssetOverview() const handleSelect = (t: KyberAITimeframe) => { const wrapperEl = ref.current?.closest('section-wrapper') diff --git a/src/pages/TrueSightV2/components/TokenOverview.tsx b/src/pages/TrueSightV2/components/TokenOverview.tsx index 27324dc590..cfe195c72f 100644 --- a/src/pages/TrueSightV2/components/TokenOverview.tsx +++ b/src/pages/TrueSightV2/components/TokenOverview.tsx @@ -21,7 +21,7 @@ import { getEtherscanLink, shortenAddress } from 'utils' import { ShareButton } from '.' import { MIXPANEL_KYBERAI_TAG, NETWORK_IMAGE_URL, NETWORK_TO_CHAINID } from '../constants' -import { ITokenOverview } from '../types' +import { IAssetOverview } from '../types' import { calculateValueToColor, formatLocaleStringNum, formatTokenPrice } from '../utils' import ChevronIcon from './ChevronIcon' import KyberAIShareModal from './KyberAIShareModal' @@ -143,7 +143,7 @@ const ExternalLink = ({ href, className, children }: { href: string; className?: ) } -export const TokenOverview = ({ data, isLoading }: { data?: ITokenOverview; isLoading?: boolean }) => { +export const TokenOverview = ({ data, isLoading }: { data?: IAssetOverview; isLoading?: boolean }) => { const theme = useTheme() const { chain } = useParams() const mixpanelHandler = useMixpanelKyberAI() diff --git a/src/pages/TrueSightV2/components/chart/datafeed.tsx b/src/pages/TrueSightV2/components/chart/datafeed.tsx index 1157417494..bccef89c3a 100644 --- a/src/pages/TrueSightV2/components/chart/datafeed.tsx +++ b/src/pages/TrueSightV2/components/chart/datafeed.tsx @@ -13,13 +13,13 @@ import { import { getTradingViewTimeZone } from 'components/TradingViewChart/utils' import { useLazyChartingDataQuery } from 'pages/TrueSightV2/hooks/useKyberAIData' import { defaultExplorePageToken } from 'pages/TrueSightV2/pages/SingleToken' -import { ITokenOverview, OHLCData } from 'pages/TrueSightV2/types' +import { IAssetOverview, OHLCData } from 'pages/TrueSightV2/types' const configurationData = { supported_resolutions: ['1H', '4H', '1D', '4D'], } -export const useDatafeed = (isBTC: boolean, token?: ITokenOverview) => { +export const useDatafeed = (isBTC: boolean, token?: IAssetOverview) => { const intervalRef = useRef() const { chain, address } = useParams() const [getChartingData, { isLoading }] = useLazyChartingDataQuery() diff --git a/src/pages/TrueSightV2/components/chart/index.tsx b/src/pages/TrueSightV2/components/chart/index.tsx index 16fa66b24a..88099fc5d3 100644 --- a/src/pages/TrueSightV2/components/chart/index.tsx +++ b/src/pages/TrueSightV2/components/chart/index.tsx @@ -4,7 +4,6 @@ import { rgba } from 'polished' import React, { ReactNode, useCallback, useContext, useEffect, useLayoutEffect, useMemo, useRef, useState } from 'react' import { isMobile } from 'react-device-detect' import { Info } from 'react-feather' -import { useParams } from 'react-router-dom' import { useMedia } from 'react-use' import { Text } from 'rebass' import { @@ -41,6 +40,7 @@ import { useActiveWeb3React } from 'hooks' import useTheme from 'hooks/useTheme' import { KYBERAI_CHART_ID, NETWORK_TO_CHAINID } from 'pages/TrueSightV2/constants' import { CHART_STATES_ACTION_TYPE, useChartStatesContext } from 'pages/TrueSightV2/hooks/useChartStatesReducer' +import useKyberAIAssetOverview from 'pages/TrueSightV2/hooks/useKyberAIAssetOverview' import { useCexesLiquidationQuery, useHolderListQuery, @@ -50,7 +50,6 @@ import { useTradingVolumeQuery, useTransferInformationQuery, } from 'pages/TrueSightV2/hooks/useKyberAIData' -import useKyberAITokenOverview from 'pages/TrueSightV2/hooks/useKyberAITokenOverview' import { defaultExplorePageToken } from 'pages/TrueSightV2/pages/SingleToken' import { TechnicalAnalysisContext } from 'pages/TrueSightV2/pages/TechnicalAnalysis' import { @@ -297,7 +296,7 @@ const roundNumberUp = (number: number) => { export const NumberofTradesChart = ({ noAnimation }: { noAnimation?: boolean }) => { const theme = useTheme() - const { chain, address } = useParams() + const { chain, address } = useKyberAIAssetOverview() const { state, dispatch } = useChartStatesContext(KYBERAI_CHART_ID.NUMBER_OF_TRADES, { timeframe: KyberAITimeframe.ONE_MONTH, showOptions: ['showSell', 'showBuy', 'showTotalTrade'], @@ -328,11 +327,14 @@ export const NumberofTradesChart = ({ noAnimation }: { noAnimation?: boolean }) }[timeframe as string] || 604800) return [from, now, timerange] }, [timeframe]) - const { data, isLoading } = useTradingVolumeQuery({ - chain: chain || defaultExplorePageToken.chain, - address: address || defaultExplorePageToken.address, - params: { from, to }, - }) + const { data, isLoading } = useTradingVolumeQuery( + { + chain: chain, + address: address, + params: { from, to }, + }, + { skip: !address || !chain }, + ) const dataRange = useMemo(() => { if (!data) return undefined @@ -615,7 +617,7 @@ export const NumberofTradesChart = ({ noAnimation }: { noAnimation?: boolean }) export const TradingVolumeChart = ({ noAnimation }: { noAnimation?: boolean }) => { const theme = useTheme() - const { chain, address } = useParams() + const { chain, address } = useKyberAIAssetOverview() const { state, dispatch } = useChartStatesContext(KYBERAI_CHART_ID.TRADING_VOLUME, { timeframe: KyberAITimeframe.ONE_MONTH, showOptions: ['showSell', 'showBuy', 'showTotalVolume'], @@ -938,7 +940,7 @@ export const TradingVolumeChart = ({ noAnimation }: { noAnimation?: boolean }) = export const NetflowToWhaleWallets = ({ tab, noAnimation }: { tab?: ChartTab; noAnimation?: boolean }) => { const theme = useTheme() - const { chain, address } = useParams() + const { chain, address } = useKyberAIAssetOverview() const { state, dispatch } = useChartStatesContext(KYBERAI_CHART_ID.NETFLOW_TO_WHALE_WALLET, { timeframe: KyberAITimeframe.ONE_WEEK, showOptions: ['showInflow', 'showOutflow', 'showNetflow'], @@ -1381,7 +1383,7 @@ export const NetflowToWhaleWallets = ({ tab, noAnimation }: { tab?: ChartTab; no export const NetflowToCentralizedExchanges = ({ tab, noAnimation }: { tab?: ChartTab; noAnimation?: boolean }) => { const theme = useTheme() - const { chain, address } = useParams() + const { chain, address } = useKyberAIAssetOverview() const { state, dispatch } = useChartStatesContext(KYBERAI_CHART_ID.NETFLOW_TO_CEX, { timeframe: KyberAITimeframe.ONE_WEEK, showOptions: ['showInflow', 'showOutflow', 'showNetflow'], @@ -1773,7 +1775,7 @@ export const NetflowToCentralizedExchanges = ({ tab, noAnimation }: { tab?: Char export const NumberofTransfers = ({ tab }: { tab: ChartTab }) => { const theme = useTheme() - const { chain, address } = useParams() + const { chain, address } = useKyberAIAssetOverview() const { state, dispatch } = useChartStatesContext(KYBERAI_CHART_ID.NUMBER_OF_TRANSFERS, { timeframe: KyberAITimeframe.ONE_MONTH, noData: true, @@ -1962,7 +1964,7 @@ export const NumberofTransfers = ({ tab }: { tab: ChartTab }) => { export const NumberofHolders = () => { const theme = useTheme() - const { chain, address } = useParams() + const { chain, address } = useKyberAIAssetOverview() const { state, dispatch } = useChartStatesContext(KYBERAI_CHART_ID.NUMBER_OF_HOLDERS, { timeframe: KyberAITimeframe.ONE_MONTH, noData: true, @@ -2138,7 +2140,7 @@ export const NumberofHolders = () => { const COLORS = ['#00a2f7', '#31CB9E', '#FFBB28', '#F3841E', '#FF537B', '#27AE60', '#78d5ff', '#8088E5'] const CustomLabel = ({ x, y, cx, cy, name, address, percentage, sumPercentage }: any) => { let customY = y - const { chain } = useParams() + const { chain } = useKyberAIAssetOverview() if (Math.abs(cx - x) < 30) { customY = cy - y > 0 ? y - 8 : y + 8 } @@ -2177,22 +2179,11 @@ const CustomLabelLine = (props: any) => { )} ) - // if (percentage > 0.01) { - // return ( - // - // ) - // } else { - // return - // } } export const HoldersChartWrapper = ({ noAnimation }: { noAnimation?: boolean }) => { const theme = useTheme() const above768 = useMedia(`(min-width:${MEDIA_WIDTHS.upToSmall}px)`) - const { chain, address } = useParams() + const { chain, address } = useKyberAIAssetOverview() const { dispatch } = useChartStatesContext(KYBERAI_CHART_ID.HOLDER_PIE_CHART, { noData: true, }) @@ -2268,7 +2259,7 @@ export const HoldersChartWrapper = ({ noAnimation }: { noAnimation?: boolean }) export const LiquidOnCentralizedExchanges = ({ noAnimation }: { noAnimation?: boolean }) => { const theme = useTheme() const { account } = useActiveWeb3React() - const { chain, address } = useParams() + const { chain, address } = useKyberAIAssetOverview() const { state, dispatch } = useChartStatesContext(KYBERAI_CHART_ID.LIQUID_ON_CEX, { timeframe: KyberAITimeframe.ONE_MONTH, noData: true, @@ -2303,7 +2294,7 @@ export const LiquidOnCentralizedExchanges = ({ noAnimation }: { noAnimation?: bo }, { skip: !address || !chain }, ) - const { data: tokenOverview } = useKyberAITokenOverview() + const { data: tokenOverview } = useKyberAIAssetOverview() const [showLong, setShowLong] = useState(true) const [showShort, setShowShort] = useState(true) const [showPrice, setShowPrice] = useState(true) @@ -2655,7 +2646,7 @@ export const Prochart = ({ const [fullscreen, setFullscreen] = useState(false) const [loading, setLoading] = useState(false) const userLocale = useUserLocale() - const { data } = useKyberAITokenOverview() + const { data } = useKyberAIAssetOverview() const datafeed = useDatafeed(isBTC || false, data) const { SRLevels, currentPrice, resolution, setResolution, showSRLevels } = useContext(TechnicalAnalysisContext) diff --git a/src/pages/TrueSightV2/components/index.tsx b/src/pages/TrueSightV2/components/index.tsx index 9433823bba..b7745c44d1 100644 --- a/src/pages/TrueSightV2/components/index.tsx +++ b/src/pages/TrueSightV2/components/index.tsx @@ -18,7 +18,7 @@ import { CloseIcon, MEDIA_WIDTHS } from 'theme' import { openFullscreen } from 'utils/index' import { MIXPANEL_KYBERAI_TAG } from '../constants' -import useKyberAITokenOverview from '../hooks/useKyberAITokenOverview' +import useKyberAIAssetOverview from '../hooks/useKyberAIAssetOverview' import { ChartTab } from '../types' import KyberAIShareModal from './KyberAIShareModal' @@ -144,7 +144,7 @@ export const SectionWrapper = ({ const theme = useTheme() const mixpanelHandler = useMixpanelKyberAI() const { chain } = useParams() - const { data: token } = useKyberAITokenOverview() + const { data: token } = useKyberAIAssetOverview() const ref = useRef(null) const above768 = useMedia(`(min-width:${MEDIA_WIDTHS.upToSmall}px)`) const [showText, setShowText] = useState(above768 ? true : false) diff --git a/src/pages/TrueSightV2/components/shareContent/ExploreTopShareContent.tsx b/src/pages/TrueSightV2/components/shareContent/ExploreTopShareContent.tsx index 1cf0e72697..c66e11bac1 100644 --- a/src/pages/TrueSightV2/components/shareContent/ExploreTopShareContent.tsx +++ b/src/pages/TrueSightV2/components/shareContent/ExploreTopShareContent.tsx @@ -9,7 +9,7 @@ import Column from 'components/Column' import Divider from 'components/Divider' import Row, { RowFit } from 'components/Row' import { useTokenListQuery } from 'pages/TrueSightV2/hooks/useKyberAIData' -import { ITokenOverview, KyberAIListType } from 'pages/TrueSightV2/types' +import { IAssetOverview, KyberAIListType } from 'pages/TrueSightV2/types' import { calculateValueToColor, formatTokenPrice } from 'pages/TrueSightV2/utils' import ChevronIcon from '../ChevronIcon' @@ -72,7 +72,7 @@ const PriceChart7Days = ({ ) } -export default function ExploreShareContent({ token, mobileMode }: { token?: ITokenOverview; mobileMode?: boolean }) { +export default function ExploreShareContent({ token, mobileMode }: { token?: IAssetOverview; mobileMode?: boolean }) { const theme = useTheme() const { data } = useTokenListQuery( { type: KyberAIListType.ALL, page: 1, pageSize: 5, keywords: token?.address }, diff --git a/src/pages/TrueSightV2/components/shareContent/KyberScoreShareContent.tsx b/src/pages/TrueSightV2/components/shareContent/KyberScoreShareContent.tsx index d921e784f1..fcd4e2d202 100644 --- a/src/pages/TrueSightV2/components/shareContent/KyberScoreShareContent.tsx +++ b/src/pages/TrueSightV2/components/shareContent/KyberScoreShareContent.tsx @@ -5,7 +5,7 @@ import { Text } from 'rebass' import Column from 'components/Column' import Row from 'components/Row' import useTheme from 'hooks/useTheme' -import { ITokenOverview } from 'pages/TrueSightV2/types' +import { IAssetOverview } from 'pages/TrueSightV2/types' import { calculateValueToColor, formatTokenPrice } from 'pages/TrueSightV2/utils' import KyberScoreMeter from '../KyberScoreMeter' @@ -15,7 +15,7 @@ export default function KyberScoreShareContent({ token, mobileMode, }: { - token?: ITokenOverview + token?: IAssetOverview mobileMode?: boolean }) { const theme = useTheme() diff --git a/src/pages/TrueSightV2/components/table/index.tsx b/src/pages/TrueSightV2/components/table/index.tsx index e3bc1fdc7c..e236e650e0 100644 --- a/src/pages/TrueSightV2/components/table/index.tsx +++ b/src/pages/TrueSightV2/components/table/index.tsx @@ -6,7 +6,7 @@ import { ReactNode, useCallback, useContext, useEffect, useMemo, useRef, useStat import { isMobile } from 'react-device-detect' import { Info } from 'react-feather' import Skeleton, { SkeletonTheme } from 'react-loading-skeleton' -import { useNavigate, useParams } from 'react-router-dom' +import { useNavigate } from 'react-router-dom' import { Text } from 'rebass' import styled, { DefaultTheme, css } from 'styled-components' @@ -19,20 +19,12 @@ import AnimatedLoader from 'components/Loader/AnimatedLoader' import Pagination from 'components/Pagination' import Row, { RowFit } from 'components/Row' import { APP_PATHS } from 'constants/index' -import { useActiveWeb3React } from 'hooks' -import { MIXPANEL_TYPE, useMixpanelKyberAI } from 'hooks/useMixpanel' import { useOnClickOutside } from 'hooks/useOnClickOutside' import useTheme from 'hooks/useTheme' import { NETWORK_IMAGE_URL, NETWORK_TO_CHAINID } from 'pages/TrueSightV2/constants' import useIsReachMaxLimitWatchedToken from 'pages/TrueSightV2/hooks/useIsReachMaxLimitWatchedToken' -import { - useAddToWatchlistMutation, - useFundingRateQuery, - useHolderListQuery, - useLiveDexTradesQuery, - useRemoveFromWatchlistMutation, -} from 'pages/TrueSightV2/hooks/useKyberAIData' -import useKyberAITokenOverview from 'pages/TrueSightV2/hooks/useKyberAITokenOverview' +import useKyberAIAssetOverview from 'pages/TrueSightV2/hooks/useKyberAIAssetOverview' +import { useFundingRateQuery, useHolderListQuery, useLiveDexTradesQuery } from 'pages/TrueSightV2/hooks/useKyberAIData' import { TechnicalAnalysisContext } from 'pages/TrueSightV2/pages/TechnicalAnalysis' import { IHolderList, IKyberScoreChart, ILiveTrade, ITokenList, KyberAITimeframe } from 'pages/TrueSightV2/types' import { @@ -46,7 +38,6 @@ import { getEtherscanLink, shortenAddress } from 'utils' import { getProxyTokenLogo } from 'utils/tokenInfo' import ChevronIcon from '../ChevronIcon' -import { WidgetTab } from '../KyberAIWidget' import MultipleChainDropdown from '../MultipleChainDropdown' import SimpleTooltip from '../SimpleTooltip' import SmallKyberScoreMeter from '../SmallKyberScoreMeter' @@ -172,9 +163,8 @@ const LoadingHandleWrapper = ({ export const Top10HoldersTable = () => { const theme = useTheme() - const { chain, address } = useParams() - const { data, isLoading } = useHolderListQuery({ address, chain }) - const { data: tokenOverview } = useKyberAITokenOverview() + const { data: tokenOverview, chain, address } = useKyberAIAssetOverview() + const { data, isLoading } = useHolderListQuery({ address, chain }, { skip: !chain || !address }) return ( 0} height="400px"> @@ -373,8 +363,8 @@ function colorRateText(value: number, theme: DefaultTheme) { export const FundingRateTable = ({ mobileMode }: { mobileMode?: boolean }) => { const theme = useTheme() - const { chain, address } = useParams() - const { data, isLoading } = useFundingRateQuery({ address, chain }) + const { chain, address } = useKyberAIAssetOverview() + const { data, isLoading } = useFundingRateQuery({ address, chain }, { skip: !chain || !address }) if (mobileMode) { return ( @@ -458,15 +448,15 @@ export const FundingRateTable = ({ mobileMode }: { mobileMode?: boolean }) => { export const LiveDEXTrades = () => { const theme = useTheme() const [currentPage, setCurrentPage] = useState(1) - const { chain, address } = useParams() + const { data: tokenOverview, chain, address } = useKyberAIAssetOverview() + const { data, isLoading } = useLiveDexTradesQuery( { chain, address, }, - { pollingInterval: 10000 }, + { pollingInterval: 10000, skip: !chain || !address }, ) - const { data: tokenOverview } = useKyberAITokenOverview() return ( <> @@ -577,22 +567,11 @@ const WidgetTableWrapper = styled(Table)` } ` -const WidgetTokenRow = ({ - token, - onClick, - activeTab, - index, -}: { - token: ITokenList - onClick?: () => void - activeTab: WidgetTab - index: number -}) => { +const WidgetTokenRow = ({ token, onClick }: { token: ITokenList; onClick?: () => void }) => { const theme = useTheme() const navigate = useNavigate() - const { account } = useActiveWeb3React() - const mixpanelHandler = useMixpanelKyberAI() - const reachedMaxLimit = useIsReachMaxLimitWatchedToken(token?.tokens.length) + + const reachedMaxLimit = useIsReachMaxLimitWatchedToken() const latestKyberScore: IKyberScoreChart | undefined = token?.ks_3d?.[token.ks_3d.length - 1] const hasMutipleChain = token?.tokens?.length > 1 @@ -600,9 +579,6 @@ const WidgetTokenRow = ({ const [showSwapMenu, setShowSwapMenu] = useState(false) const [menuLeft, setMenuLeft] = useState(undefined) const [isWatched, setIsWatched] = useState(!!token.isWatched) - const [loadingStar, setLoadingStar] = useState(false) - const [addToWatchlist] = useAddToWatchlistMutation() - const [removeFromWatchlist] = useRemoveFromWatchlistMutation() const rowRef = useRef(null) const menuRef = useRef(null) @@ -643,36 +619,36 @@ const WidgetTokenRow = ({ navigateToSwapPage({ address, chain }) } - const handleWatchlistClick = (e: any) => { - e.stopPropagation() - if (!account) return - setLoadingStar(true) - if (isWatched) { - mixpanelHandler(MIXPANEL_TYPE.KYBERAI_ADD_TOKEN_TO_WATCHLIST, { - token_name: token.symbol?.toUpperCase(), - source: activeTab, - ranking_order: index, - option: 'remove', - }) - Promise.all(token.tokens.map(t => removeFromWatchlist({ tokenAddress: t.address, chain: t.chain }))).then(() => { - setIsWatched(false) - setLoadingStar(false) - }) - } else { - if (!isWatched) { - mixpanelHandler(MIXPANEL_TYPE.KYBERAI_ADD_TOKEN_TO_WATCHLIST, { - token_name: token.symbol?.toUpperCase(), - source: activeTab, - ranking_order: index, - option: 'add', - }) - Promise.all(token.tokens.map(t => addToWatchlist({ tokenAddress: t.address, chain: t.chain }))).then(() => { - setIsWatched(true) - setLoadingStar(false) - }) - } - } - } + // const handleWatchlistClick = (e: any) => { + // e.stopPropagation() + // if (!account) return + // setLoadingStar(true) + // if (isWatched) { + // mixpanelHandler(MIXPANEL_TYPE.KYBERAI_ADD_TOKEN_TO_WATCHLIST, { + // token_name: token.symbol?.toUpperCase(), + // source: activeTab, + // ranking_order: index, + // option: 'remove', + // }) + // Promise.all(token.tokens.map(t => removeFromWatchlist({ tokenAddress: t.address, chain: t.chain }))).then(() => { + // setIsWatched(false) + // setLoadingStar(false) + // }) + // } else { + // if (!isWatched) { + // mixpanelHandler(MIXPANEL_TYPE.KYBERAI_ADD_TOKEN_TO_WATCHLIST, { + // token_name: token.symbol?.toUpperCase(), + // source: activeTab, + // ranking_order: index, + // option: 'add', + // }) + // Promise.all(token.tokens.map(t => addToWatchlist({ tokenAddress: t.address, chain: t.chain }))).then(() => { + // setIsWatched(true) + // setLoadingStar(false) + // }) + // } + // } + // } useEffect(() => { setIsWatched(token.isWatched) @@ -685,12 +661,7 @@ const WidgetTokenRow = ({ - + tokenInList - + void - activeTab: WidgetTab }) => { const theme = useTheme() return ( @@ -919,7 +883,7 @@ export const WidgetTable = ({ ) : ( {data?.map((token, i) => { - return + return })} )} @@ -932,13 +896,11 @@ export const WidgetMobileTable = ({ isLoading, isError, onRowClick, - activeTab, }: { data?: ITokenList[] isLoading: boolean isError: boolean onRowClick?: () => void - activeTab: WidgetTab }) => { const theme = useTheme() return ( @@ -993,7 +955,7 @@ export const WidgetMobileTable = ({ ) : ( {data?.map((token, i) => { - return + return })} )} @@ -1024,7 +986,7 @@ export const Top10HoldersShareModalTable = ({ startIndex?: number }) => { const theme = useTheme() - const { data: tokenOverview } = useKyberAITokenOverview() + const { data: tokenOverview } = useKyberAIAssetOverview() return ( @@ -1091,7 +1053,7 @@ export const LiveTradesInShareModalTable = ({ mobileMode?: boolean }) => { const theme = useTheme() - const { data: tokenOverview } = useKyberAITokenOverview() + const { data: tokenOverview } = useKyberAIAssetOverview() return ( diff --git a/src/pages/TrueSightV2/hooks/useIsReachMaxLimitWatchedToken.tsx b/src/pages/TrueSightV2/hooks/useIsReachMaxLimitWatchedToken.tsx index 9a06730b1f..2ce593c52b 100644 --- a/src/pages/TrueSightV2/hooks/useIsReachMaxLimitWatchedToken.tsx +++ b/src/pages/TrueSightV2/hooks/useIsReachMaxLimitWatchedToken.tsx @@ -1,10 +1,8 @@ -import { useMemo } from 'react' - -import { ITokenList, KyberAIListType } from '../types' +import { KyberAIListType } from '../types' import { useTokenListQuery } from './useKyberAIData' const MAX_LIMIT_WATCHED_TOKEN = 30 -export default function useIsReachMaxLimitWatchedToken(tokenCount?: number) { +export default function useIsReachMaxLimitWatchedToken() { const { data } = useTokenListQuery({ type: KyberAIListType.ALL, chain: 'all', @@ -13,13 +11,7 @@ export default function useIsReachMaxLimitWatchedToken(tokenCount?: number) { watchlist: true, }) - const watchedCount = useMemo(() => { - let count = 0 - data?.data.forEach((t: ITokenList) => { - count += t.tokens.length - }) - return count - }, [data]) + const watchedCount = data?.totalItems || 0 - return watchedCount + (tokenCount || 1) > MAX_LIMIT_WATCHED_TOKEN + return watchedCount + 1 > MAX_LIMIT_WATCHED_TOKEN } diff --git a/src/pages/TrueSightV2/hooks/useKyberAIAssetOverview.tsx b/src/pages/TrueSightV2/hooks/useKyberAIAssetOverview.tsx new file mode 100644 index 0000000000..557d492a6d --- /dev/null +++ b/src/pages/TrueSightV2/hooks/useKyberAIAssetOverview.tsx @@ -0,0 +1,22 @@ +import { useParams } from 'react-router' +import { useSearchParams } from 'react-router-dom' + +import { useIsWhiteListKyberAI } from 'state/user/hooks' + +import { useAssetOverviewQuery } from './useKyberAIData' + +export default function useKyberAIAssetOverview() { + const { isWhiteList } = useIsWhiteListKyberAI() + const { assetId } = useParams() + + const [searchParams] = useSearchParams() + + const result = useAssetOverviewQuery({ assetId }, { skip: !assetId || !isWhiteList }) + + return { + data: result.data, + isLoading: result.isLoading, + address: searchParams.get('address') || undefined, + chain: searchParams.get('chain') || undefined, + } +} diff --git a/src/pages/TrueSightV2/hooks/useKyberAIData.tsx b/src/pages/TrueSightV2/hooks/useKyberAIData.tsx index b3a1a74b62..d57b590b1b 100644 --- a/src/pages/TrueSightV2/hooks/useKyberAIData.tsx +++ b/src/pages/TrueSightV2/hooks/useKyberAIData.tsx @@ -4,6 +4,7 @@ import baseQueryOauth from 'services/baseQueryOauth' import { BFF_API } from 'constants/env' import { + IAssetOverview, ILiquidCEX, ILiveTrade, INetflowToCEX, @@ -12,7 +13,6 @@ import { INumberOfTrades, INumberOfTransfers, ITokenList, - ITokenOverview, ITokenSearchResult, ITradingVolume, KyberAIListType, @@ -57,7 +57,7 @@ const kyberAIApi = createApi({ }, providesTags: (result, error, arg) => (arg.watchlist === true ? ['myWatchList', 'tokenList'] : ['tokenList']), }), - //2. + //2. TODO addToWatchlist: builder.mutation({ query: (params: { tokenAddress: string; chain: string }) => ({ url: `/watchlist`, @@ -66,7 +66,7 @@ const kyberAIApi = createApi({ }), invalidatesTags: (res, err, params) => [{ type: 'tokenOverview', id: params.tokenAddress }, 'myWatchList'], }), - //3. + //3. TODO removeFromWatchlist: builder.mutation({ query: (params: { tokenAddress: string; chain: string }) => ({ url: `/watchlist`, @@ -79,9 +79,20 @@ const kyberAIApi = createApi({ 'tokenList', ], }), - + assetOverview: builder.query({ + query: ({ assetId }: { assetId?: string }) => ({ + url: `/assets/${assetId}`, + }), + transformResponse: (res: any) => { + // If token is stablecoin remove its kyberscore value + if (res.data && res.data.tags?.includes('stablecoin')) { + return { ...res.data, kyberScore: { ks3d: null, label: '', score: 0 } } + } + return res.data + }, + }), //4. - tokenDetail: builder.query({ + tokenOverview: builder.query({ query: ({ chain, address }: { chain?: string; address?: string }) => ({ url: `/overview/${chain}/${address}`, }), @@ -92,7 +103,6 @@ const kyberAIApi = createApi({ } return res.data }, - providesTags: result => [{ type: 'tokenOverview', id: result?.address }], }), //5. numberOfTrades: builder.query({ @@ -172,7 +182,7 @@ const kyberAIApi = createApi({ //11. chartingData: builder.query< OHLCData[], - { chain: string; address: string; from: number; to: number; candleSize: string; currency: string } + { chain?: string; address?: string; from: number; to: number; candleSize: string; currency: string } >({ query: ({ chain, address, from, to, candleSize, currency }) => ({ url: `/ohlcv/${chain}/${address}`, @@ -259,7 +269,8 @@ const kyberAIApi = createApi({ }) export const { - useTokenDetailQuery, + useAssetOverviewQuery, + useTokenOverviewQuery, useNumberOfTradesQuery, useTradingVolumeQuery, useNetflowToWhaleWalletsQuery, diff --git a/src/pages/TrueSightV2/hooks/useKyberAITokenOverview.tsx b/src/pages/TrueSightV2/hooks/useKyberAITokenOverview.tsx deleted file mode 100644 index 5548573a65..0000000000 --- a/src/pages/TrueSightV2/hooks/useKyberAITokenOverview.tsx +++ /dev/null @@ -1,13 +0,0 @@ -import { useParams } from 'react-router' - -import { useIsWhiteListKyberAI } from 'state/user/hooks' - -import { useTokenDetailQuery } from './useKyberAIData' - -export default function useKyberAITokenOverview() { - const { isWhiteList } = useIsWhiteListKyberAI() - const { chain, address } = useParams() - const result = useTokenDetailQuery({ chain, address }, { skip: !chain || !address || !isWhiteList }) - - return result -} diff --git a/src/pages/TrueSightV2/pages/SingleToken.tsx b/src/pages/TrueSightV2/pages/SingleToken.tsx index f47f5cfbe5..f6b7532809 100644 --- a/src/pages/TrueSightV2/pages/SingleToken.tsx +++ b/src/pages/TrueSightV2/pages/SingleToken.tsx @@ -3,7 +3,7 @@ import { rgba } from 'polished' import { stringify } from 'querystring' import { ReactNode, useEffect, useLayoutEffect, useRef, useState } from 'react' import { ChevronLeft } from 'react-feather' -import { useLocation, useNavigate, useParams } from 'react-router-dom' +import { useLocation, useNavigate, useParams, useSearchParams } from 'react-router-dom' import { useMedia } from 'react-use' import { Text } from 'rebass' import styled, { css } from 'styled-components' @@ -13,7 +13,6 @@ import Icon from 'components/Icons/Icon' import { DotsLoader } from 'components/Loader/DotsLoader' import Row, { RowBetween, RowFit } from 'components/Row' import { APP_PATHS } from 'constants/index' -import { useActiveWeb3React } from 'hooks' import { MIXPANEL_TYPE, useMixpanelKyberAI } from 'hooks/useMixpanel' import useTheme from 'hooks/useTheme' import { PROFILE_MANAGE_ROUTES } from 'pages/NotificationCenter/const' @@ -26,12 +25,11 @@ import SimpleTooltip from '../components/SimpleTooltip' import { TokenOverview } from '../components/TokenOverview' import { StarWithAnimation } from '../components/WatchlistStar' import ExploreShareContent from '../components/shareContent/ExploreTopShareContent' -import { MIXPANEL_KYBERAI_TAG, NETWORK_IMAGE_URL, NETWORK_TO_CHAINID } from '../constants' +import { MIXPANEL_KYBERAI_TAG, NETWORK_IMAGE_URL } from '../constants' import useChartStatesReducer, { ChartStatesContext } from '../hooks/useChartStatesReducer' import useIsReachMaxLimitWatchedToken from '../hooks/useIsReachMaxLimitWatchedToken' -import { useAddToWatchlistMutation, useRemoveFromWatchlistMutation } from '../hooks/useKyberAIData' -import useKyberAITokenOverview from '../hooks/useKyberAITokenOverview' -import { DiscoverTokenTab, ITokenOverview } from '../types' +import useKyberAIAssetOverview from '../hooks/useKyberAIAssetOverview' +import { DiscoverTokenTab, IAssetOverview } from '../types' import { navigateToSwapPage } from '../utils' import OnChainAnalysis from './OnChainAnalysis' import TechnicalAnalysis from './TechnicalAnalysis' @@ -153,7 +151,8 @@ const TabButton = styled.div<{ active?: boolean }>` export const defaultExplorePageToken = { chain: 'ethereum', - address: '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2', + address: '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2', //TODO: remove + assetId: 1, } const StyledTokenDescription = styled.div<{ show?: boolean }>` @@ -235,43 +234,41 @@ const TokenDescription = ({ description }: { description: string }) => { ) } -const TokenNameGroup = ({ token, isLoading }: { token?: ITokenOverview; isLoading?: boolean }) => { - const { account } = useActiveWeb3React() +const TokenNameGroup = ({ token, isLoading }: { token?: IAssetOverview; isLoading?: boolean }) => { const theme = useTheme() - const mixpanelHandler = useMixpanelKyberAI() const navigate = useNavigate() const location = useLocation() const above768 = useMedia(`(min-width:${MEDIA_WIDTHS.upToSmall}px)`) const { chain } = useParams() const reachedMaxLimit = useIsReachMaxLimitWatchedToken() - const [addToWatchlist, { isLoading: loadingAddtoWatchlist }] = useAddToWatchlistMutation() - const [removeFromWatchlist, { isLoading: loadingRemovefromWatchlist }] = useRemoveFromWatchlistMutation() + // const [addToWatchlist, { isLoading: loadingAddtoWatchlist }] = useAddToWatchlistMutation() + // const [removeFromWatchlist, { isLoading: loadingRemovefromWatchlist }] = useRemoveFromWatchlistMutation() const [isWatched, setIsWatched] = useState(false) - const handleStarClick = () => { - if (!token || !chain || !account) return - if (isWatched) { - mixpanelHandler(MIXPANEL_TYPE.KYBERAI_ADD_TOKEN_TO_WATCHLIST, { - token_name: token.symbol?.toUpperCase(), - source: 'explore', - option: 'remove', - }) + // const handleStarClick = () => { + // if (!token || !chain || !account) return + // if (isWatched) { + // mixpanelHandler(MIXPANEL_TYPE.KYBERAI_ADD_TOKEN_TO_WATCHLIST, { + // token_name: token.symbol?.toUpperCase(), + // source: 'explore', + // option: 'remove', + // }) - removeFromWatchlist({ - tokenAddress: token?.address, - chain, - }).then(() => setIsWatched(false)) - } else { - if (!reachedMaxLimit) { - mixpanelHandler(MIXPANEL_TYPE.KYBERAI_ADD_TOKEN_TO_WATCHLIST, { - token_name: token.symbol?.toUpperCase(), - source: 'explore', - option: 'add', - }) - addToWatchlist({ tokenAddress: token?.address, chain }).then(() => setIsWatched(true)) - } - } - } + // removeFromWatchlist({ + // tokenAddress: token?.address, + // chain, + // }).then(() => setIsWatched(false)) + // } else { + // if (!reachedMaxLimit) { + // mixpanelHandler(MIXPANEL_TYPE.KYBERAI_ADD_TOKEN_TO_WATCHLIST, { + // token_name: token.symbol?.toUpperCase(), + // source: 'explore', + // option: 'add', + // }) + // addToWatchlist({ tokenAddress: token?.address, chain }).then(() => setIsWatched(true)) + // } + // } + // } const handleGoBackClick = () => { if (!!location?.state?.from) { navigate(location.state.from) @@ -297,10 +294,9 @@ const TokenNameGroup = ({ token, isLoading }: { token?: ITokenOverview; isLoadin > ) } -const SettingButtons = ({ token, onShareClick }: { token?: ITokenOverview; onShareClick: () => void }) => { +const SettingButtons = ({ token, onShareClick }: { token?: IAssetOverview; onShareClick: () => void }) => { const theme = useTheme() const navigate = useNavigate() - const { chain } = useParams() return ( <> @@ -365,7 +360,7 @@ const SettingButtons = ({ token, onShareClick }: { token?: ITokenOverview; onSha navigate( `${APP_PATHS.PROFILE_MANAGE}${PROFILE_MANAGE_ROUTES.CREATE_ALERT}?${stringify({ inputCurrency: token?.address ?? '', - chainId: chain ? NETWORK_TO_CHAINID[chain] : '', + chainId: 1, //TODO })}`, ) } @@ -441,7 +436,7 @@ const TokenHeader = ({ isLoading, onShareClick, }: { - token?: ITokenOverview + token?: IAssetOverview isLoading?: boolean onShareClick: () => void }) => { @@ -510,19 +505,20 @@ export default function SingleToken() { const theme = useTheme() const navigate = useNavigate() const mixpanelHandler = useMixpanelKyberAI() + const [, setSearchParams] = useSearchParams() const [state, dispatch] = useChartStatesReducer() const [showShare, setShowShare] = useState(false) const above768 = useMedia(`(min-width:${MEDIA_WIDTHS.upToSmall}px)`) - const { chain, address } = useParams() + const { assetId } = useParams() const [currentTab, setCurrentTab] = useState(DiscoverTokenTab.TechnicalAnalysis) - const { data: token, isLoading } = useKyberAITokenOverview() + const { data: token, isLoading } = useKyberAIAssetOverview() const [viewAllTag, setViewAllTag] = useState(false) useEffect(() => { - if (!chain || !address) { - navigate(APP_PATHS.KYBERAI_EXPLORE + `/${defaultExplorePageToken.chain}/${defaultExplorePageToken.address}`) + if (!assetId) { + navigate(APP_PATHS.KYBERAI_EXPLORE + `/${defaultExplorePageToken.assetId}`) setTimeout(() => { const element = document.querySelector('#kyberai-search') as HTMLInputElement element?.focus({ @@ -530,11 +526,17 @@ export default function SingleToken() { }) }, 750) } - }, [chain, address, navigate]) + }, [assetId, navigate]) useEffect(() => { window.scrollTo(0, 0) }, []) + useEffect(() => { + if (token?.addresses && token.addresses[0].address && token.addresses[0].chain) { + setSearchParams({ chain: token.addresses[0].chain, address: token.addresses[0].address }) + } + }, [token?.addresses, setSearchParams]) + return ( @@ -553,7 +555,7 @@ export default function SingleToken() { onClick={() => { mixpanelHandler(MIXPANEL_TYPE.KYBERAI_EXPLORING_VIEW_ALL_CLICK, { token_name: token?.symbol?.toUpperCase(), - network: chain, + network: 1, //TODO }) setViewAllTag(true) }} @@ -575,7 +577,7 @@ export default function SingleToken() { onClick={() => { mixpanelHandler(MIXPANEL_TYPE.KYBERAI_EXPLORING_ANALYSIS_TYPE_CLICK, { token_name: token?.symbol?.toUpperCase(), - network: chain, + network: 1, //TODO option: tab === DiscoverTokenTab.OnChainAnalysis ? 'onchain_analysis' : 'technical_analysis', }) setCurrentTab(tab) @@ -609,7 +611,7 @@ export default function SingleToken() { onShareClick={social => mixpanelHandler(MIXPANEL_TYPE.KYBERAI_SHARE_TOKEN_CLICK, { token_name: token?.symbol?.toUpperCase(), - network: chain, + network: 1, //TODO source: MIXPANEL_KYBERAI_TAG.EXPLORE_SHARE_THIS_TOKEN, share_via: social, }) diff --git a/src/pages/TrueSightV2/pages/TechnicalAnalysis.tsx b/src/pages/TrueSightV2/pages/TechnicalAnalysis.tsx index 2393bf5cf1..5be2aa2547 100644 --- a/src/pages/TrueSightV2/pages/TechnicalAnalysis.tsx +++ b/src/pages/TrueSightV2/pages/TechnicalAnalysis.tsx @@ -1,6 +1,5 @@ import { Trans, t } from '@lingui/macro' import { createContext, useCallback, useMemo, useState } from 'react' -import { useParams } from 'react-router-dom' import { Text } from 'rebass' import styled, { useTheme } from 'styled-components' @@ -23,11 +22,10 @@ import ProchartShareContent from '../components/shareContent/ProchartShareConten import SupportResistanceShareContent from '../components/shareContent/SupportResistanceShareContent' import { FundingRateTable, LiveDEXTrades, SupportResistanceLevel } from '../components/table' import { KYBERAI_CHART_ID, NETWORK_TO_CHAINID } from '../constants' +import useKyberAIAssetOverview from '../hooks/useKyberAIAssetOverview' import { useChartingDataQuery } from '../hooks/useKyberAIData' -import useKyberAITokenOverview from '../hooks/useKyberAITokenOverview' import { ChartTab, ISRLevel, KyberAITimeframe, OHLCData } from '../types' import { navigateToLimitPage } from '../utils' -import { defaultExplorePageToken } from './SingleToken' const Wrapper = styled.div` padding: 20px 0; @@ -82,23 +80,24 @@ export const TechnicalAnalysisContext = createContext() const [prochartDataURL, setProchartDataURL] = useState() const [liveChartTab, setLiveChartTab] = useState(ChartTab.First) const [showSRLevels, setShowSRLevels] = useState(true) const [priceChartResolution, setPriceChartResolution] = useState('4h') const now = Math.floor(Date.now() / 60000) * 60 - const { data, isLoading } = useChartingDataQuery({ - chain: chain || defaultExplorePageToken.chain, - address: address || defaultExplorePageToken.address, - from: now - ({ '1h': 1080000, '4h': 4320000, '1d': 12960000 }[priceChartResolution] || 1080000), - to: now, - candleSize: priceChartResolution, - currency: liveChartTab === ChartTab.First ? 'USD' : 'BTC', - }) - - const { data: tokenOverview } = useKyberAITokenOverview() + const { data, isLoading } = useChartingDataQuery( + { + chain: chain, + address: address, + from: now - ({ '1h': 1080000, '4h': 4320000, '1d': 12960000 }[priceChartResolution] || 1080000), + to: now, + candleSize: priceChartResolution, + currency: liveChartTab === ChartTab.First ? 'USD' : 'BTC', + }, + { skip: !chain || !address }, + ) const SRLevels: ISRLevel[] = useMemo(() => { if (isLoading && !data) return [] diff --git a/src/pages/TrueSightV2/pages/TokenAnalysisList.tsx b/src/pages/TrueSightV2/pages/TokenAnalysisList.tsx index c37d2bba0d..28acb84d8a 100644 --- a/src/pages/TrueSightV2/pages/TokenAnalysisList.tsx +++ b/src/pages/TrueSightV2/pages/TokenAnalysisList.tsx @@ -23,25 +23,22 @@ import { APP_PATHS, ICON_ID } from 'constants/index' import { NETWORKS_INFO } from 'constants/networks' import { useActiveWeb3React } from 'hooks' import { MIXPANEL_TYPE, useMixpanelKyberAI } from 'hooks/useMixpanel' -import { useOnClickOutside } from 'hooks/useOnClickOutside' import useTheme from 'hooks/useTheme' import { MEDIA_WIDTHS } from 'theme' import ChevronIcon from '../components/ChevronIcon' import FeedbackSurvey from '../components/FeedbackSurvey' import KyberAIShareModal from '../components/KyberAIShareModal' -import MultipleChainDropdown from '../components/MultipleChainDropdown' import NetworkSelect from '../components/NetworkSelect' import SimpleTooltip from '../components/SimpleTooltip' import SmallKyberScoreMeter from '../components/SmallKyberScoreMeter' import TokenChart from '../components/TokenChartSVG' -import TokenListVariants from '../components/TokenListVariants' import { StarWithAnimation } from '../components/WatchlistStar' import KyberScoreChart from '../components/chart/KyberScoreChart' import TokenAnalysisListShareContent from '../components/shareContent/TokenAnalysisListShareContent' import { KYBERAI_LISTYPE_TO_MIXPANEL, SUPPORTED_NETWORK_KYBERAI } from '../constants' import useIsReachMaxLimitWatchedToken from '../hooks/useIsReachMaxLimitWatchedToken' -import { useAddToWatchlistMutation, useRemoveFromWatchlistMutation, useTokenListQuery } from '../hooks/useKyberAIData' +import { useTokenListQuery } from '../hooks/useKyberAIData' import { IKyberScoreChart, ITokenList, KyberAIListType } from '../types' import { calculateValueToColor, formatLocaleStringNum, formatTokenPrice, navigateToSwapPage } from '../utils' @@ -478,37 +475,17 @@ const TokenRow = ({ const mixpanelHandler = useMixpanelKyberAI() const { account } = useActiveWeb3React() const theme = useTheme() - const [showMenu, setShowMenu] = useState(false) - const [showSwapMenu, setShowSwapMenu] = useState(false) - const [menuLeft, setMenuLeft] = useState(undefined) - const [addToWatchlist] = useAddToWatchlistMutation() - const [removeFromWatchlist] = useRemoveFromWatchlistMutation() - const reachedMaxLimit = useIsReachMaxLimitWatchedToken(token?.tokens.length) + const reachedMaxLimit = useIsReachMaxLimitWatchedToken() const [isWatched, setIsWatched] = useState(false) const [loadingStar, setLoadingStar] = useState(false) const rowRef = useRef(null) - const menuRef = useRef(null) - useOnClickOutside(menuRef, () => setShowMenu(false)) - useOnClickOutside(menuRef, () => setShowSwapMenu(false)) const above768 = useMedia(`(min-width:${MEDIA_WIDTHS.upToSmall}px)`) - const hasMutipleChain = token.tokens.length > 1 - - const handleRowClick = (e: any) => { - if (hasMutipleChain) { - const left = e.clientX - (rowRef.current?.getBoundingClientRect()?.left || 0) - const rowWidth = rowRef.current?.getBoundingClientRect()?.width || 0 - const menuWidth = menuRef.current?.getBoundingClientRect()?.width || 0 - if (left !== undefined) { - setMenuLeft(Math.min(left, rowWidth - menuWidth)) - setShowMenu(true) - } - } else { - navigate(`${APP_PATHS.KYBERAI_EXPLORE}/${token.tokens[0].chain}/${token.tokens[0].address}`, { - state: { from: location }, - }) - } + const handleRowClick = () => { + navigate(`${APP_PATHS.KYBERAI_EXPLORE}/${token.asset_id}`, { + state: { from: location }, + }) } const handleWatchlistClick = (e: any) => { @@ -522,10 +499,11 @@ const TokenRow = ({ ranking_order: index, option: 'remove', }) - Promise.all(token.tokens.map(t => removeFromWatchlist({ tokenAddress: t.address, chain: t.chain }))).then(() => { - setIsWatched(false) - setLoadingStar(false) - }) + // TODO: refactor removeFromWatchlist + // Promise.all(token.tokens.map(t => removeFromWatchlist({ tokenAddress: t.address, chain: t.chain }))).then(() => { + // setIsWatched(false) + // setLoadingStar(false) + // }) } else { if (!reachedMaxLimit) { mixpanelHandler(MIXPANEL_TYPE.KYBERAI_ADD_TOKEN_TO_WATCHLIST, { @@ -534,10 +512,11 @@ const TokenRow = ({ ranking_order: index, option: 'add', }) - Promise.all(token.tokens.map(t => addToWatchlist({ tokenAddress: t.address, chain: t.chain }))).then(() => { - setIsWatched(true) - setLoadingStar(false) - }) + // TODO: refactor addToWatchlist + // Promise.all(token.tokens.map(t => addToWatchlist({ tokenAddress: t.address, chain: t.chain }))).then(() => { + // setIsWatched(true) + // setLoadingStar(false) + // }) } } } @@ -548,7 +527,7 @@ const TokenRow = ({ const latestKyberScore: IKyberScoreChart | undefined = token?.ks_3d?.[token.ks_3d.length - 1] return ( - + {token.symbol}{' '} - - - @@ -665,14 +641,9 @@ const TokenRow = ({ source: KYBERAI_LISTYPE_TO_MIXPANEL[listType], option: 'explore', }) - if (hasMutipleChain) { - setMenuLeft(undefined) - setShowMenu(true) - } else { - navigate(`${APP_PATHS.KYBERAI_EXPLORE}/${token.tokens[0].chain}/${token.tokens[0].address}`, { - state: { from: location }, - }) - } + navigate(`${APP_PATHS.KYBERAI_EXPLORE}/${token.asset_id}`, { + state: { from: location }, + }) }} > @@ -688,42 +659,12 @@ const TokenRow = ({ source: KYBERAI_LISTYPE_TO_MIXPANEL[listType], option: 'swap', }) - if (hasMutipleChain) { - setMenuLeft(undefined) - setShowSwapMenu(true) - } else { - navigateToSwapPage(token.tokens[0]) - } + navigateToSwapPage(token.tokens[0]) }} > - {hasMutipleChain && ( - <> - - navigate(`${APP_PATHS.KYBERAI_EXPLORE}/${chain}/${address}`, { - state: { from: location }, - }) - } - /> - { - if (chain && address) { - navigateToSwapPage({ chain, address }) - } - }} - /> - - )} @@ -1054,7 +995,7 @@ export default function TokenAnalysisList() { listData.map((token: ITokenList, index: number) => ( price: number percent_change_24h: number @@ -103,11 +104,10 @@ export interface IFundingRate { } export interface ITokenSearchResult { - address: string name: string symbol: string logo: string - chain: string + assetId: string price: number priceChange24h: number kyberScore?: { From fe55bf716828441b8f53f3b9891ae3797fb7a9f4 Mon Sep 17 00:00:00 2001 From: XiaoYhun Date: Wed, 20 Sep 2023 09:32:54 +0700 Subject: [PATCH 02/15] add variant select in explore page --- .../components/SwitchVariantDropdown.tsx | 131 ++++++++++++++++++ .../components/TokenListVariants.tsx | 43 +++--- src/pages/TrueSightV2/pages/SingleToken.tsx | 71 +++++----- .../TrueSightV2/pages/TokenAnalysisList.tsx | 2 + 4 files changed, 196 insertions(+), 51 deletions(-) create mode 100644 src/pages/TrueSightV2/components/SwitchVariantDropdown.tsx diff --git a/src/pages/TrueSightV2/components/SwitchVariantDropdown.tsx b/src/pages/TrueSightV2/components/SwitchVariantDropdown.tsx new file mode 100644 index 0000000000..d3d92a4d19 --- /dev/null +++ b/src/pages/TrueSightV2/components/SwitchVariantDropdown.tsx @@ -0,0 +1,131 @@ +import { AnimatePresence, motion } from 'framer-motion' +import { useRef, useState } from 'react' +import Skeleton, { SkeletonTheme } from 'react-loading-skeleton' +import { useSearchParams } from 'react-router-dom' +import { Text } from 'rebass' +import styled from 'styled-components' + +import { ReactComponent as Down } from 'assets/svg/down.svg' +import Icon from 'components/Icons/Icon' +import Row, { RowFit } from 'components/Row' +import { ICON_ID } from 'constants/index' +import { useOnClickOutside } from 'hooks/useOnClickOutside' +import useTheme from 'hooks/useTheme' + +const Wrapper = styled.div` + position: relative; +` +const SelectButton = styled(RowFit)` + height: 36px; + border-radius: 99px; + padding: 8px 12px; + background-color: ${({ theme }) => theme.buttonGray}; + gap: 8px; + cursor: pointer; + font-size: 14px; + width: 135px; + + :hover { + z-index: 10; + filter: brightness(1.2); + } +` + +const DropdownWrapper = styled(motion.div)` + position: absolute; + width: 100%; + border-radius: 14px; + background-color: ${({ theme }) => theme.buttonGray}; + left: 0; + top: calc(100% + 2px); + padding: 4px; + z-index: 10; + display: flex; + flex-direction: column; + gap: 4px; +` + +const DropdownItem = styled(Row)` + height: 32px; + padding: 4px 8px; + gap: 8px; + border-radius: 4px; + cursor: pointer; + :hover { + filter: brightness(1.2); + background-color: ${({ theme }) => theme.background}; + } +` + +const VARIANTS: { [key: string]: { icon_id: ICON_ID; title: string } } = { + ethereum: { icon_id: 'eth-mono', title: 'Ethereum' }, + bsc: { icon_id: 'bnb-mono', title: 'Binance' }, + avalanche: { icon_id: 'ava-mono', title: 'Avalanche' }, + polygon: { icon_id: 'matic-mono', title: 'Polygon' }, + arbitrum: { icon_id: 'arbitrum-mono', title: 'Arbitrum' }, + fantom: { icon_id: 'fantom-mono', title: 'Fantom' }, + optimism: { icon_id: 'optimism-mono', title: 'Optimism' }, +} + +export default function SwitchVariantDropdown({ variants }: { variants?: { chain: string; address: string }[] }) { + const theme = useTheme() + const [show, setShow] = useState(false) + const ref = useRef(null) + const [, setSearchParams] = useSearchParams() + useOnClickOutside(ref, () => setShow(false)) + const firstItem = variants?.[0] + if (!firstItem) + return ( + + + + ) + + const setChainAndAdress = (variant: { chain: string; address: string }) => { + setSearchParams({ chain: variant.chain, address: variant.address }) + } + const variant = !!firstItem && VARIANTS[firstItem?.chain] + return ( + + setShow(true)}> + + {variant.title} + + + + {show && ( + + {variants.map(item => { + const itemVariant = VARIANTS[item.chain] + return ( + { + setShow(false) + setChainAndAdress(item) + }} + > + + {itemVariant.title} + + ) + })} + + )} + + + ) +} diff --git a/src/pages/TrueSightV2/components/TokenListVariants.tsx b/src/pages/TrueSightV2/components/TokenListVariants.tsx index 0bc5a4c6e0..ce3a4a807b 100644 --- a/src/pages/TrueSightV2/components/TokenListVariants.tsx +++ b/src/pages/TrueSightV2/components/TokenListVariants.tsx @@ -1,4 +1,20 @@ +import { useTheme } from 'styled-components' + import Icon from 'components/Icons/Icon' +import Row from 'components/Row' +import { ICON_ID } from 'constants/index' + +const VARIANTS: { [key: string]: { icon_id: ICON_ID; title: string } } = { + ethereum: { icon_id: 'eth-mono', title: 'Ethereum' }, + bsc: { icon_id: 'bnb-mono', title: 'Binance' }, + avalanche: { icon_id: 'ava-mono', title: 'Avalanche' }, + polygon: { icon_id: 'matic-mono', title: 'Polygon' }, + arbitrum: { icon_id: 'arbitrum-mono', title: 'Arbitrum' }, + fantom: { icon_id: 'fantom-mono', title: 'Fantom' }, + optimism: { icon_id: 'optimism-mono', title: 'Optimism' }, +} + +const MAX_ICONS_SHOWING = 8 export default function TokenListVariants({ tokens, @@ -7,29 +23,16 @@ export default function TokenListVariants({ tokens: Array<{ address: string; logo: string; chain: string }> iconSize?: number }) { + const theme = useTheme() return ( - <> + {tokens.map((item, index) => { + if (index > MAX_ICONS_SHOWING) return + if (index === MAX_ICONS_SHOWING) return ... const key = item.address + '_' + index - switch (item.chain) { - case 'ethereum': - return - case 'bsc': - return - case 'avalanche': - return - case 'polygon': - return - case 'arbitrum': - return - case 'fantom': - return - case 'optimism': - return - default: - return <> - } + const variant = VARIANTS[item.chain] + return })} - + ) } diff --git a/src/pages/TrueSightV2/pages/SingleToken.tsx b/src/pages/TrueSightV2/pages/SingleToken.tsx index f6b7532809..f34fa9c260 100644 --- a/src/pages/TrueSightV2/pages/SingleToken.tsx +++ b/src/pages/TrueSightV2/pages/SingleToken.tsx @@ -3,6 +3,7 @@ import { rgba } from 'polished' import { stringify } from 'querystring' import { ReactNode, useEffect, useLayoutEffect, useRef, useState } from 'react' import { ChevronLeft } from 'react-feather' +import Skeleton from 'react-loading-skeleton' import { useLocation, useNavigate, useParams, useSearchParams } from 'react-router-dom' import { useMedia } from 'react-use' import { Text } from 'rebass' @@ -13,7 +14,8 @@ import Icon from 'components/Icons/Icon' import { DotsLoader } from 'components/Loader/DotsLoader' import Row, { RowBetween, RowFit } from 'components/Row' import { APP_PATHS } from 'constants/index' -import { MIXPANEL_TYPE, useMixpanelKyberAI } from 'hooks/useMixpanel' +import { useActiveWeb3React } from 'hooks' +import useMixpanel, { MIXPANEL_TYPE, useMixpanelKyberAI } from 'hooks/useMixpanel' import useTheme from 'hooks/useTheme' import { PROFILE_MANAGE_ROUTES } from 'pages/NotificationCenter/const' import { MEDIA_WIDTHS } from 'theme' @@ -22,6 +24,7 @@ import DisplaySettings from '../components/DisplaySettings' import FeedbackSurvey from '../components/FeedbackSurvey' import KyberAIShareModal from '../components/KyberAIShareModal' import SimpleTooltip from '../components/SimpleTooltip' +import SwitchVariantDropdown from '../components/SwitchVariantDropdown' import { TokenOverview } from '../components/TokenOverview' import { StarWithAnimation } from '../components/WatchlistStar' import ExploreShareContent from '../components/shareContent/ExploreTopShareContent' @@ -29,6 +32,7 @@ import { MIXPANEL_KYBERAI_TAG, NETWORK_IMAGE_URL } from '../constants' import useChartStatesReducer, { ChartStatesContext } from '../hooks/useChartStatesReducer' import useIsReachMaxLimitWatchedToken from '../hooks/useIsReachMaxLimitWatchedToken' import useKyberAIAssetOverview from '../hooks/useKyberAIAssetOverview' +import { useAddToWatchlistMutation, useRemoveFromWatchlistMutation } from '../hooks/useKyberAIData' import { DiscoverTokenTab, IAssetOverview } from '../types' import { navigateToSwapPage } from '../utils' import OnChainAnalysis from './OnChainAnalysis' @@ -236,39 +240,41 @@ const TokenDescription = ({ description }: { description: string }) => { const TokenNameGroup = ({ token, isLoading }: { token?: IAssetOverview; isLoading?: boolean }) => { const theme = useTheme() + const { account } = useActiveWeb3React() const navigate = useNavigate() const location = useLocation() + const { mixpanelHandler } = useMixpanel() + const above768 = useMedia(`(min-width:${MEDIA_WIDTHS.upToSmall}px)`) const { chain } = useParams() const reachedMaxLimit = useIsReachMaxLimitWatchedToken() - // const [addToWatchlist, { isLoading: loadingAddtoWatchlist }] = useAddToWatchlistMutation() - // const [removeFromWatchlist, { isLoading: loadingRemovefromWatchlist }] = useRemoveFromWatchlistMutation() + const [addToWatchlist, { isLoading: loadingAddtoWatchlist }] = useAddToWatchlistMutation() + const [removeFromWatchlist, { isLoading: loadingRemovefromWatchlist }] = useRemoveFromWatchlistMutation() const [isWatched, setIsWatched] = useState(false) + const handleStarClick = () => { + if (!token || !chain || !account) return + if (isWatched) { + mixpanelHandler(MIXPANEL_TYPE.KYBERAI_ADD_TOKEN_TO_WATCHLIST, { + token_name: token.symbol?.toUpperCase(), + source: 'explore', + option: 'remove', + }) - // const handleStarClick = () => { - // if (!token || !chain || !account) return - // if (isWatched) { - // mixpanelHandler(MIXPANEL_TYPE.KYBERAI_ADD_TOKEN_TO_WATCHLIST, { - // token_name: token.symbol?.toUpperCase(), - // source: 'explore', - // option: 'remove', - // }) - - // removeFromWatchlist({ - // tokenAddress: token?.address, - // chain, - // }).then(() => setIsWatched(false)) - // } else { - // if (!reachedMaxLimit) { - // mixpanelHandler(MIXPANEL_TYPE.KYBERAI_ADD_TOKEN_TO_WATCHLIST, { - // token_name: token.symbol?.toUpperCase(), - // source: 'explore', - // option: 'add', - // }) - // addToWatchlist({ tokenAddress: token?.address, chain }).then(() => setIsWatched(true)) - // } - // } - // } + removeFromWatchlist({ + tokenAddress: token?.address, + chain, + }).then(() => setIsWatched(false)) + } else { + if (!reachedMaxLimit) { + mixpanelHandler(MIXPANEL_TYPE.KYBERAI_ADD_TOKEN_TO_WATCHLIST, { + token_name: token.symbol?.toUpperCase(), + source: 'explore', + option: 'add', + }) + addToWatchlist({ tokenAddress: token?.address, chain }).then(() => setIsWatched(true)) + } + } + } const handleGoBackClick = () => { if (!!location?.state?.from) { navigate(location.state.from) @@ -294,7 +300,7 @@ const TokenNameGroup = ({ token, isLoading }: { token?: IAssetOverview; isLoadin >
@@ -450,6 +457,7 @@ const TokenHeader = ({ + setShowShare(true)} /> - {isLoading ? : } + {isLoading ? : } @@ -611,7 +620,7 @@ export default function SingleToken() { onShareClick={social => mixpanelHandler(MIXPANEL_TYPE.KYBERAI_SHARE_TOKEN_CLICK, { token_name: token?.symbol?.toUpperCase(), - network: 1, //TODO + network: 1, // TODO source: MIXPANEL_KYBERAI_TAG.EXPLORE_SHARE_THIS_TOKEN, share_via: social, }) diff --git a/src/pages/TrueSightV2/pages/TokenAnalysisList.tsx b/src/pages/TrueSightV2/pages/TokenAnalysisList.tsx index 28acb84d8a..589e414fb2 100644 --- a/src/pages/TrueSightV2/pages/TokenAnalysisList.tsx +++ b/src/pages/TrueSightV2/pages/TokenAnalysisList.tsx @@ -33,6 +33,7 @@ import NetworkSelect from '../components/NetworkSelect' import SimpleTooltip from '../components/SimpleTooltip' import SmallKyberScoreMeter from '../components/SmallKyberScoreMeter' import TokenChart from '../components/TokenChartSVG' +import TokenListVariants from '../components/TokenListVariants' import { StarWithAnimation } from '../components/WatchlistStar' import KyberScoreChart from '../components/chart/KyberScoreChart' import TokenAnalysisListShareContent from '../components/shareContent/TokenAnalysisListShareContent' @@ -571,6 +572,7 @@ const TokenRow = ({ {token.symbol}{' '} + From 4c85b7ceb1a242f23c47c2275d5722843458af9c Mon Sep 17 00:00:00 2001 From: XiaoYhun Date: Wed, 20 Sep 2023 09:43:49 +0700 Subject: [PATCH 03/15] revert watchlist updates --- .../TrueSightV2/components/table/index.tsx | 105 ++++++++++++------ .../hooks/useIsReachMaxLimitWatchedToken.tsx | 16 ++- 2 files changed, 81 insertions(+), 40 deletions(-) diff --git a/src/pages/TrueSightV2/components/table/index.tsx b/src/pages/TrueSightV2/components/table/index.tsx index e236e650e0..0a1ad6205b 100644 --- a/src/pages/TrueSightV2/components/table/index.tsx +++ b/src/pages/TrueSightV2/components/table/index.tsx @@ -19,12 +19,20 @@ import AnimatedLoader from 'components/Loader/AnimatedLoader' import Pagination from 'components/Pagination' import Row, { RowFit } from 'components/Row' import { APP_PATHS } from 'constants/index' +import { useActiveWeb3React } from 'hooks' +import { MIXPANEL_TYPE, useMixpanelKyberAI } from 'hooks/useMixpanel' import { useOnClickOutside } from 'hooks/useOnClickOutside' import useTheme from 'hooks/useTheme' import { NETWORK_IMAGE_URL, NETWORK_TO_CHAINID } from 'pages/TrueSightV2/constants' import useIsReachMaxLimitWatchedToken from 'pages/TrueSightV2/hooks/useIsReachMaxLimitWatchedToken' import useKyberAIAssetOverview from 'pages/TrueSightV2/hooks/useKyberAIAssetOverview' -import { useFundingRateQuery, useHolderListQuery, useLiveDexTradesQuery } from 'pages/TrueSightV2/hooks/useKyberAIData' +import { + useAddToWatchlistMutation, + useFundingRateQuery, + useHolderListQuery, + useLiveDexTradesQuery, + useRemoveFromWatchlistMutation, +} from 'pages/TrueSightV2/hooks/useKyberAIData' import { TechnicalAnalysisContext } from 'pages/TrueSightV2/pages/TechnicalAnalysis' import { IHolderList, IKyberScoreChart, ILiveTrade, ITokenList, KyberAITimeframe } from 'pages/TrueSightV2/types' import { @@ -38,6 +46,7 @@ import { getEtherscanLink, shortenAddress } from 'utils' import { getProxyTokenLogo } from 'utils/tokenInfo' import ChevronIcon from '../ChevronIcon' +import { WidgetTab } from '../KyberAIWidget' import MultipleChainDropdown from '../MultipleChainDropdown' import SimpleTooltip from '../SimpleTooltip' import SmallKyberScoreMeter from '../SmallKyberScoreMeter' @@ -567,11 +576,22 @@ const WidgetTableWrapper = styled(Table)` } ` -const WidgetTokenRow = ({ token, onClick }: { token: ITokenList; onClick?: () => void }) => { +const WidgetTokenRow = ({ + token, + onClick, + activeTab, + index, +}: { + token: ITokenList + onClick?: () => void + activeTab: WidgetTab + index: number +}) => { const theme = useTheme() const navigate = useNavigate() - - const reachedMaxLimit = useIsReachMaxLimitWatchedToken() + const { account } = useActiveWeb3React() + const mixpanelHandler = useMixpanelKyberAI() + const reachedMaxLimit = useIsReachMaxLimitWatchedToken(token?.tokens.length) const latestKyberScore: IKyberScoreChart | undefined = token?.ks_3d?.[token.ks_3d.length - 1] const hasMutipleChain = token?.tokens?.length > 1 @@ -579,6 +599,9 @@ const WidgetTokenRow = ({ token, onClick }: { token: ITokenList; onClick?: () => const [showSwapMenu, setShowSwapMenu] = useState(false) const [menuLeft, setMenuLeft] = useState(undefined) const [isWatched, setIsWatched] = useState(!!token.isWatched) + const [loadingStar, setLoadingStar] = useState(false) + const [addToWatchlist] = useAddToWatchlistMutation() + const [removeFromWatchlist] = useRemoveFromWatchlistMutation() const rowRef = useRef(null) const menuRef = useRef(null) @@ -619,36 +642,36 @@ const WidgetTokenRow = ({ token, onClick }: { token: ITokenList; onClick?: () => navigateToSwapPage({ address, chain }) } - // const handleWatchlistClick = (e: any) => { - // e.stopPropagation() - // if (!account) return - // setLoadingStar(true) - // if (isWatched) { - // mixpanelHandler(MIXPANEL_TYPE.KYBERAI_ADD_TOKEN_TO_WATCHLIST, { - // token_name: token.symbol?.toUpperCase(), - // source: activeTab, - // ranking_order: index, - // option: 'remove', - // }) - // Promise.all(token.tokens.map(t => removeFromWatchlist({ tokenAddress: t.address, chain: t.chain }))).then(() => { - // setIsWatched(false) - // setLoadingStar(false) - // }) - // } else { - // if (!isWatched) { - // mixpanelHandler(MIXPANEL_TYPE.KYBERAI_ADD_TOKEN_TO_WATCHLIST, { - // token_name: token.symbol?.toUpperCase(), - // source: activeTab, - // ranking_order: index, - // option: 'add', - // }) - // Promise.all(token.tokens.map(t => addToWatchlist({ tokenAddress: t.address, chain: t.chain }))).then(() => { - // setIsWatched(true) - // setLoadingStar(false) - // }) - // } - // } - // } + const handleWatchlistClick = (e: any) => { + e.stopPropagation() + if (!account) return + setLoadingStar(true) + if (isWatched) { + mixpanelHandler(MIXPANEL_TYPE.KYBERAI_ADD_TOKEN_TO_WATCHLIST, { + token_name: token.symbol?.toUpperCase(), + source: activeTab, + ranking_order: index, + option: 'remove', + }) + Promise.all(token.tokens.map(t => removeFromWatchlist({ tokenAddress: t.address, chain: t.chain }))).then(() => { + setIsWatched(false) + setLoadingStar(false) + }) + } else { + if (!isWatched) { + mixpanelHandler(MIXPANEL_TYPE.KYBERAI_ADD_TOKEN_TO_WATCHLIST, { + token_name: token.symbol?.toUpperCase(), + source: activeTab, + ranking_order: index, + option: 'add', + }) + Promise.all(token.tokens.map(t => addToWatchlist({ tokenAddress: t.address, chain: t.chain }))).then(() => { + setIsWatched(true) + setLoadingStar(false) + }) + } + } + } useEffect(() => { setIsWatched(token.isWatched) @@ -661,7 +684,12 @@ const WidgetTokenRow = ({ token, onClick }: { token: ITokenList; onClick?: () => - + tokenInList : t`Add to watchlist` } > - + { + let count = 0 + data?.data.forEach((t: ITokenList) => { + count += t.tokens.length + }) + return count + }, [data]) - return watchedCount + 1 > MAX_LIMIT_WATCHED_TOKEN + return watchedCount + (tokenCount || 1) > MAX_LIMIT_WATCHED_TOKEN } From 32ebd93e65e0a7f57ae4aa364a6b0cf70898f2b9 Mon Sep 17 00:00:00 2001 From: XiaoYhun Date: Wed, 20 Sep 2023 09:59:58 +0700 Subject: [PATCH 04/15] fix failed errors --- src/pages/TrueSightV2/components/KyberAIWidget.tsx | 9 ++++++++- src/pages/TrueSightV2/components/table/index.tsx | 8 ++++++-- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/src/pages/TrueSightV2/components/KyberAIWidget.tsx b/src/pages/TrueSightV2/components/KyberAIWidget.tsx index c908d5ebfb..37e77c908b 100644 --- a/src/pages/TrueSightV2/components/KyberAIWidget.tsx +++ b/src/pages/TrueSightV2/components/KyberAIWidget.tsx @@ -353,6 +353,7 @@ export default function Widget() { isLoading={isFetching} isError={isError} onRowClick={() => setShowExpanded(false)} + activeTab={activeTab} /> )} @@ -470,7 +471,13 @@ const KyberAIWidgetMobileContent = ({
- +
diff --git a/src/pages/TrueSightV2/components/table/index.tsx b/src/pages/TrueSightV2/components/table/index.tsx index 0a1ad6205b..d077a8f12a 100644 --- a/src/pages/TrueSightV2/components/table/index.tsx +++ b/src/pages/TrueSightV2/components/table/index.tsx @@ -830,11 +830,13 @@ export const WidgetTable = ({ isLoading, isError, onRowClick, + activeTab, }: { data?: ITokenList[] isLoading: boolean isError: boolean onRowClick?: () => void + activeTab: WidgetTab }) => { const theme = useTheme() return ( @@ -916,7 +918,7 @@ export const WidgetTable = ({ ) : ( {data?.map((token, i) => { - return + return })} )} @@ -929,11 +931,13 @@ export const WidgetMobileTable = ({ isLoading, isError, onRowClick, + activeTab, }: { data?: ITokenList[] isLoading: boolean isError: boolean onRowClick?: () => void + activeTab: WidgetTab }) => { const theme = useTheme() return ( @@ -988,7 +992,7 @@ export const WidgetMobileTable = ({ ) : ( {data?.map((token, i) => { - return + return })} )} From 74a3217a80702e586eab30111173b9a1c3bbcfed Mon Sep 17 00:00:00 2001 From: XiaoYhun Date: Thu, 21 Sep 2023 14:33:49 +0700 Subject: [PATCH 05/15] fix issues --- .../components/MultipleChainDropdown.tsx | 5 +- .../components/SwitchVariantDropdown.tsx | 31 +++++++--- .../TrueSightV2/components/table/index.tsx | 42 ++------------ src/pages/TrueSightV2/pages/SingleToken.tsx | 56 +++++++++++++------ .../TrueSightV2/pages/TokenAnalysisList.tsx | 47 ++++++++++++---- 5 files changed, 103 insertions(+), 78 deletions(-) diff --git a/src/pages/TrueSightV2/components/MultipleChainDropdown.tsx b/src/pages/TrueSightV2/components/MultipleChainDropdown.tsx index fac2caac39..0c82854688 100644 --- a/src/pages/TrueSightV2/components/MultipleChainDropdown.tsx +++ b/src/pages/TrueSightV2/components/MultipleChainDropdown.tsx @@ -73,13 +73,12 @@ const MultipleChainDropdown = React.forwardRef( ( props: { show: boolean - menuLeft?: number tokens?: Array<{ address: string; logo: string; chain: string }> onChainClick: (chain: string, address: string) => void }, ref, ) => { - const { show, menuLeft, tokens, onChainClick } = props + const { show, tokens, onChainClick } = props const theme = useTheme() if (isMobile) { return ( @@ -167,7 +166,7 @@ const MultipleChainDropdown = React.forwardRef( className={show ? 'show' : ''} gap="8px" color={theme.text} - style={{ left: menuLeft !== undefined ? `${menuLeft}px` : undefined }} + style={{ right: 0 }} ref={ref} onClick={e => e.stopPropagation()} > diff --git a/src/pages/TrueSightV2/components/SwitchVariantDropdown.tsx b/src/pages/TrueSightV2/components/SwitchVariantDropdown.tsx index d3d92a4d19..22563f35c8 100644 --- a/src/pages/TrueSightV2/components/SwitchVariantDropdown.tsx +++ b/src/pages/TrueSightV2/components/SwitchVariantDropdown.tsx @@ -34,7 +34,7 @@ const SelectButton = styled(RowFit)` const DropdownWrapper = styled(motion.div)` position: absolute; width: 100%; - border-radius: 14px; + border-radius: 10px; background-color: ${({ theme }) => theme.buttonGray}; left: 0; top: calc(100% + 2px); @@ -50,6 +50,7 @@ const DropdownItem = styled(Row)` padding: 4px 8px; gap: 8px; border-radius: 4px; + font-size: 14px; cursor: pointer; :hover { filter: brightness(1.2); @@ -67,14 +68,20 @@ const VARIANTS: { [key: string]: { icon_id: ICON_ID; title: string } } = { optimism: { icon_id: 'optimism-mono', title: 'Optimism' }, } -export default function SwitchVariantDropdown({ variants }: { variants?: { chain: string; address: string }[] }) { +export default function SwitchVariantDropdown({ + variants, + isLoading, +}: { + variants?: { chain: string; address: string }[] + isLoading?: boolean +}) { const theme = useTheme() const [show, setShow] = useState(false) const ref = useRef(null) const [, setSearchParams] = useSearchParams() useOnClickOutside(ref, () => setShow(false)) const firstItem = variants?.[0] - if (!firstItem) + if (!firstItem && isLoading) { return ( ) + } const setChainAndAdress = (variant: { chain: string; address: string }) => { setSearchParams({ chain: variant.chain, address: variant.address }) } - const variant = !!firstItem && VARIANTS[firstItem?.chain] + const variant = !!firstItem ? VARIANTS[firstItem?.chain] : undefined + return ( setShow(true)}> - - {variant.title} + + {variant && ( + <> + + {variant.title}{' '} + + )} + - {show && ( + {show && !!variants?.length && ( - {variants.map(item => { + {variants?.map(item => { const itemVariant = VARIANTS[item.chain] return ( 1 - const [showMenu, setShowMenu] = useState(false) const [showSwapMenu, setShowSwapMenu] = useState(false) - const [menuLeft, setMenuLeft] = useState(undefined) const [isWatched, setIsWatched] = useState(!!token.isWatched) const [loadingStar, setLoadingStar] = useState(false) const [addToWatchlist] = useAddToWatchlistMutation() const [removeFromWatchlist] = useRemoveFromWatchlistMutation() const rowRef = useRef(null) - const menuRef = useRef(null) - useOnClickOutside(rowRef, () => setShowMenu(false)) useOnClickOutside(rowRef, () => setShowSwapMenu(false)) - const handleRowClick = (e: any) => { - if (hasMutipleChain) { - const left = e.clientX - (rowRef.current?.getBoundingClientRect()?.left || 0) - const rowWidth = rowRef.current?.getBoundingClientRect()?.width || 0 - const menuWidth = menuRef.current?.getBoundingClientRect()?.width || 0 - if (left !== undefined) { - setMenuLeft(Math.min(left, rowWidth - menuWidth)) - setShowMenu(true) - } - } else { - navigate(`${APP_PATHS.KYBERAI_EXPLORE}/${token.tokens[0].chain}/${token.tokens[0].address}`) - onClick?.() - } + const handleRowClick = () => { + navigate(`${APP_PATHS.KYBERAI_EXPLORE}/${token.asset_id}`) + onClick?.() } const handleSwapClick = (e: any) => { e.stopPropagation() if (hasMutipleChain) { - const left = - e.clientX - - (rowRef.current?.getBoundingClientRect()?.left || 0) - - (menuRef.current?.getBoundingClientRect()?.width || 0) setShowSwapMenu(true) - setMenuLeft(left) } else { navigateToSwapPage({ address: token.tokens[0].address, chain: token.tokens[0].chain }) } @@ -803,22 +784,7 @@ const WidgetTokenRow = ({ {hasMutipleChain && ( <> - { - onClick?.() - navigate(`${APP_PATHS.KYBERAI_EXPLORE}/${chain}/${address}`) - }} - /> - + )} diff --git a/src/pages/TrueSightV2/pages/SingleToken.tsx b/src/pages/TrueSightV2/pages/SingleToken.tsx index f34fa9c260..d6b1059b42 100644 --- a/src/pages/TrueSightV2/pages/SingleToken.tsx +++ b/src/pages/TrueSightV2/pages/SingleToken.tsx @@ -3,19 +3,20 @@ import { rgba } from 'polished' import { stringify } from 'querystring' import { ReactNode, useEffect, useLayoutEffect, useRef, useState } from 'react' import { ChevronLeft } from 'react-feather' -import Skeleton from 'react-loading-skeleton' +import Skeleton, { SkeletonTheme } from 'react-loading-skeleton' import { useLocation, useNavigate, useParams, useSearchParams } from 'react-router-dom' import { useMedia } from 'react-use' import { Text } from 'rebass' import styled, { css } from 'styled-components' import { ButtonPrimary } from 'components/Button' +import Column from 'components/Column' import Icon from 'components/Icons/Icon' import { DotsLoader } from 'components/Loader/DotsLoader' import Row, { RowBetween, RowFit } from 'components/Row' import { APP_PATHS } from 'constants/index' import { useActiveWeb3React } from 'hooks' -import useMixpanel, { MIXPANEL_TYPE, useMixpanelKyberAI } from 'hooks/useMixpanel' +import { MIXPANEL_TYPE, useMixpanelKyberAI } from 'hooks/useMixpanel' import useTheme from 'hooks/useTheme' import { PROFILE_MANAGE_ROUTES } from 'pages/NotificationCenter/const' import { MEDIA_WIDTHS } from 'theme' @@ -28,7 +29,7 @@ import SwitchVariantDropdown from '../components/SwitchVariantDropdown' import { TokenOverview } from '../components/TokenOverview' import { StarWithAnimation } from '../components/WatchlistStar' import ExploreShareContent from '../components/shareContent/ExploreTopShareContent' -import { MIXPANEL_KYBERAI_TAG, NETWORK_IMAGE_URL } from '../constants' +import { MIXPANEL_KYBERAI_TAG, NETWORK_IMAGE_URL, NETWORK_TO_CHAINID } from '../constants' import useChartStatesReducer, { ChartStatesContext } from '../hooks/useChartStatesReducer' import useIsReachMaxLimitWatchedToken from '../hooks/useIsReachMaxLimitWatchedToken' import useKyberAIAssetOverview from '../hooks/useKyberAIAssetOverview' @@ -239,18 +240,18 @@ const TokenDescription = ({ description }: { description: string }) => { } const TokenNameGroup = ({ token, isLoading }: { token?: IAssetOverview; isLoading?: boolean }) => { - const theme = useTheme() const { account } = useActiveWeb3React() + const theme = useTheme() + const mixpanelHandler = useMixpanelKyberAI() const navigate = useNavigate() const location = useLocation() - const { mixpanelHandler } = useMixpanel() - const above768 = useMedia(`(min-width:${MEDIA_WIDTHS.upToSmall}px)`) - const { chain } = useParams() + const { chain } = useKyberAIAssetOverview() const reachedMaxLimit = useIsReachMaxLimitWatchedToken() const [addToWatchlist, { isLoading: loadingAddtoWatchlist }] = useAddToWatchlistMutation() const [removeFromWatchlist, { isLoading: loadingRemovefromWatchlist }] = useRemoveFromWatchlistMutation() const [isWatched, setIsWatched] = useState(false) + const handleStarClick = () => { if (!token || !chain || !account) return if (isWatched) { @@ -347,11 +348,11 @@ const TokenNameGroup = ({ token, isLoading }: { token?: IAssetOverview; isLoadin {isLoading ? ( ) : ( - <> + token && ( {token?.name} ({token?.symbol.toUpperCase()}) - + ) )} ) @@ -359,6 +360,7 @@ const TokenNameGroup = ({ token, isLoading }: { token?: IAssetOverview; isLoadin const SettingButtons = ({ token, onShareClick }: { token?: IAssetOverview; onShareClick: () => void }) => { const theme = useTheme() const navigate = useNavigate() + const { chain } = useKyberAIAssetOverview() return ( <> @@ -367,7 +369,7 @@ const SettingButtons = ({ token, onShareClick }: { token?: IAssetOverview; onSha navigate( `${APP_PATHS.PROFILE_MANAGE}${PROFILE_MANAGE_ROUTES.CREATE_ALERT}?${stringify({ inputCurrency: token?.address ?? '', - chainId: 1, //TODO + chainId: chain ? NETWORK_TO_CHAINID[chain] : '', })}`, ) } @@ -449,7 +451,7 @@ const TokenHeader = ({ }) => { const mixpanelHandler = useMixpanelKyberAI() const above768 = useMedia(`(min-width:${MEDIA_WIDTHS.upToSmall}px)`) - const { chain } = useParams() + const { chain } = useKyberAIAssetOverview() return above768 ? ( @@ -457,7 +459,7 @@ const TokenHeader = ({ - + (DiscoverTokenTab.TechnicalAnalysis) - const { data: token, isLoading } = useKyberAIAssetOverview() + const { data: token, isLoading, chain } = useKyberAIAssetOverview() const [viewAllTag, setViewAllTag] = useState(false) @@ -551,7 +553,27 @@ export default function SingleToken() { setShowShare(true)} /> - {isLoading ? : } + {isLoading ? ( + + + + + + + + + + + ) : ( + + )} @@ -564,7 +586,7 @@ export default function SingleToken() { onClick={() => { mixpanelHandler(MIXPANEL_TYPE.KYBERAI_EXPLORING_VIEW_ALL_CLICK, { token_name: token?.symbol?.toUpperCase(), - network: 1, //TODO + network: chain, }) setViewAllTag(true) }} @@ -586,7 +608,7 @@ export default function SingleToken() { onClick={() => { mixpanelHandler(MIXPANEL_TYPE.KYBERAI_EXPLORING_ANALYSIS_TYPE_CLICK, { token_name: token?.symbol?.toUpperCase(), - network: 1, //TODO + network: chain, option: tab === DiscoverTokenTab.OnChainAnalysis ? 'onchain_analysis' : 'technical_analysis', }) setCurrentTab(tab) @@ -620,7 +642,7 @@ export default function SingleToken() { onShareClick={social => mixpanelHandler(MIXPANEL_TYPE.KYBERAI_SHARE_TOKEN_CLICK, { token_name: token?.symbol?.toUpperCase(), - network: 1, // TODO + network: chain, source: MIXPANEL_KYBERAI_TAG.EXPLORE_SHARE_THIS_TOKEN, share_via: social, }) diff --git a/src/pages/TrueSightV2/pages/TokenAnalysisList.tsx b/src/pages/TrueSightV2/pages/TokenAnalysisList.tsx index 589e414fb2..33ec558146 100644 --- a/src/pages/TrueSightV2/pages/TokenAnalysisList.tsx +++ b/src/pages/TrueSightV2/pages/TokenAnalysisList.tsx @@ -23,12 +23,14 @@ import { APP_PATHS, ICON_ID } from 'constants/index' import { NETWORKS_INFO } from 'constants/networks' import { useActiveWeb3React } from 'hooks' import { MIXPANEL_TYPE, useMixpanelKyberAI } from 'hooks/useMixpanel' +import { useOnClickOutside } from 'hooks/useOnClickOutside' import useTheme from 'hooks/useTheme' import { MEDIA_WIDTHS } from 'theme' import ChevronIcon from '../components/ChevronIcon' import FeedbackSurvey from '../components/FeedbackSurvey' import KyberAIShareModal from '../components/KyberAIShareModal' +import MultipleChainDropdown from '../components/MultipleChainDropdown' import NetworkSelect from '../components/NetworkSelect' import SimpleTooltip from '../components/SimpleTooltip' import SmallKyberScoreMeter from '../components/SmallKyberScoreMeter' @@ -39,7 +41,7 @@ import KyberScoreChart from '../components/chart/KyberScoreChart' import TokenAnalysisListShareContent from '../components/shareContent/TokenAnalysisListShareContent' import { KYBERAI_LISTYPE_TO_MIXPANEL, SUPPORTED_NETWORK_KYBERAI } from '../constants' import useIsReachMaxLimitWatchedToken from '../hooks/useIsReachMaxLimitWatchedToken' -import { useTokenListQuery } from '../hooks/useKyberAIData' +import { useAddToWatchlistMutation, useRemoveFromWatchlistMutation, useTokenListQuery } from '../hooks/useKyberAIData' import { IKyberScoreChart, ITokenList, KyberAIListType } from '../types' import { calculateValueToColor, formatLocaleStringNum, formatTokenPrice, navigateToSwapPage } from '../utils' @@ -477,12 +479,18 @@ const TokenRow = ({ const { account } = useActiveWeb3React() const theme = useTheme() const reachedMaxLimit = useIsReachMaxLimitWatchedToken() + const [showSwapMenu, setShowSwapMenu] = useState(false) + const [addToWatchlist] = useAddToWatchlistMutation() + const [removeFromWatchlist] = useRemoveFromWatchlistMutation() const [isWatched, setIsWatched] = useState(false) const [loadingStar, setLoadingStar] = useState(false) const rowRef = useRef(null) + useOnClickOutside(rowRef, () => setShowSwapMenu(false)) const above768 = useMedia(`(min-width:${MEDIA_WIDTHS.upToSmall}px)`) + const hasMutipleChain = token.tokens.length > 1 + const handleRowClick = () => { navigate(`${APP_PATHS.KYBERAI_EXPLORE}/${token.asset_id}`, { state: { from: location }, @@ -500,11 +508,10 @@ const TokenRow = ({ ranking_order: index, option: 'remove', }) - // TODO: refactor removeFromWatchlist - // Promise.all(token.tokens.map(t => removeFromWatchlist({ tokenAddress: t.address, chain: t.chain }))).then(() => { - // setIsWatched(false) - // setLoadingStar(false) - // }) + Promise.all(token.tokens.map(t => removeFromWatchlist({ tokenAddress: t.address, chain: t.chain }))).then(() => { + setIsWatched(false) + setLoadingStar(false) + }) } else { if (!reachedMaxLimit) { mixpanelHandler(MIXPANEL_TYPE.KYBERAI_ADD_TOKEN_TO_WATCHLIST, { @@ -513,11 +520,10 @@ const TokenRow = ({ ranking_order: index, option: 'add', }) - // TODO: refactor addToWatchlist - // Promise.all(token.tokens.map(t => addToWatchlist({ tokenAddress: t.address, chain: t.chain }))).then(() => { - // setIsWatched(true) - // setLoadingStar(false) - // }) + Promise.all(token.tokens.map(t => addToWatchlist({ tokenAddress: t.address, chain: t.chain }))).then(() => { + setIsWatched(true) + setLoadingStar(false) + }) } } } @@ -661,12 +667,29 @@ const TokenRow = ({ source: KYBERAI_LISTYPE_TO_MIXPANEL[listType], option: 'swap', }) - navigateToSwapPage(token.tokens[0]) + if (hasMutipleChain) { + setShowSwapMenu(true) + } else { + navigateToSwapPage(token.tokens[0]) + } }} > + {hasMutipleChain && ( + <> + { + if (chain && address) { + navigateToSwapPage({ chain, address }) + } + }} + /> + + )} From d375ad9d1ebee392b35281bd5544414f496bf678 Mon Sep 17 00:00:00 2001 From: XiaoYhun Date: Thu, 21 Sep 2023 16:09:28 +0700 Subject: [PATCH 06/15] update select variant --- .../components/SwitchVariantDropdown.tsx | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/pages/TrueSightV2/components/SwitchVariantDropdown.tsx b/src/pages/TrueSightV2/components/SwitchVariantDropdown.tsx index 22563f35c8..b27552cc54 100644 --- a/src/pages/TrueSightV2/components/SwitchVariantDropdown.tsx +++ b/src/pages/TrueSightV2/components/SwitchVariantDropdown.tsx @@ -12,6 +12,8 @@ import { ICON_ID } from 'constants/index' import { useOnClickOutside } from 'hooks/useOnClickOutside' import useTheme from 'hooks/useTheme' +import useKyberAIAssetOverview from '../hooks/useKyberAIAssetOverview' + const Wrapper = styled.div` position: relative; ` @@ -79,9 +81,11 @@ export default function SwitchVariantDropdown({ const [show, setShow] = useState(false) const ref = useRef(null) const [, setSearchParams] = useSearchParams() + const { chain, address } = useKyberAIAssetOverview() useOnClickOutside(ref, () => setShow(false)) - const firstItem = variants?.[0] - if (!firstItem && isLoading) { + const variant = variants?.find(item => item.address.toLowerCase() === address && item.chain.toLowerCase() === chain) + console.log('🚀 ~ file: SwitchVariantDropdown.tsx:87 ~ variant:', variant) + if (!variant && isLoading) { return ( { setSearchParams({ chain: variant.chain, address: variant.address }) } - const variant = !!firstItem ? VARIANTS[firstItem?.chain] : undefined + const variantInfo = !!variant ? VARIANTS[variant?.chain] : undefined return ( setShow(true)}> - {variant && ( + {variantInfo && ( <> - - {variant.title}{' '} + + {variantInfo.title}{' '} )} From 993d8a658c32c48581d908fdc55545b81c3e5f87 Mon Sep 17 00:00:00 2001 From: XiaoYhun Date: Fri, 22 Sep 2023 10:30:26 +0700 Subject: [PATCH 07/15] fix hide button not works --- src/pages/TrueSightV2/pages/SingleToken.tsx | 54 +++++++++++++-------- 1 file changed, 35 insertions(+), 19 deletions(-) diff --git a/src/pages/TrueSightV2/pages/SingleToken.tsx b/src/pages/TrueSightV2/pages/SingleToken.tsx index d6b1059b42..487cbb5a1d 100644 --- a/src/pages/TrueSightV2/pages/SingleToken.tsx +++ b/src/pages/TrueSightV2/pages/SingleToken.tsx @@ -1,7 +1,7 @@ import { Trans, t } from '@lingui/macro' import { rgba } from 'polished' import { stringify } from 'querystring' -import { ReactNode, useEffect, useLayoutEffect, useRef, useState } from 'react' +import React, { ReactNode, useCallback, useEffect, useRef, useState } from 'react' import { ChevronLeft } from 'react-feather' import Skeleton, { SkeletonTheme } from 'react-loading-skeleton' import { useLocation, useNavigate, useParams, useSearchParams } from 'react-router-dom' @@ -160,7 +160,7 @@ export const defaultExplorePageToken = { assetId: 1, } -const StyledTokenDescription = styled.div<{ show?: boolean }>` +const StyledTokenDescription = styled.span<{ show?: boolean }>` text-overflow: ellipsis; overflow: hidden; font-size: 12px; @@ -188,11 +188,16 @@ const TokenDescription = ({ description }: { description: string }) => { const theme = useTheme() const [show, setShow] = useState(true) const [isTextExceeded, setIsTextExceeded] = useState(false) - const ref = useRef(null) + console.log('🚀 ~ file: SingleToken.tsx:191 ~ TokenDescription ~ isTextExceeded:', isTextExceeded) - useLayoutEffect(() => { - setIsTextExceeded((!!description && ref.current && ref.current?.clientWidth <= ref.current?.scrollWidth) || false) - }, [description]) + const ref = useCallback( + (el: HTMLDivElement) => { + if (el && !!description) { + setIsTextExceeded(el.clientHeight > 18 || el.scrollWidth > el.clientWidth || false) + } + }, + [description], + ) useEffect(() => { const hideBtn = document.getElementById('hide-token-description-span') @@ -205,19 +210,30 @@ const TokenDescription = ({ description }: { description: string }) => { return ( - ${t`Hide`}` - : ''), - }} - /> + + + {isTextExceeded && show && ( + setShow(false)} + > + Hide + + )} + {isTextExceeded && !show && ( Date: Fri, 22 Sep 2023 11:04:39 +0700 Subject: [PATCH 08/15] fix bugs --- .../components/SwitchVariantDropdown.tsx | 2 +- src/pages/TrueSightV2/pages/SingleToken.tsx | 23 +++++++++---------- 2 files changed, 12 insertions(+), 13 deletions(-) diff --git a/src/pages/TrueSightV2/components/SwitchVariantDropdown.tsx b/src/pages/TrueSightV2/components/SwitchVariantDropdown.tsx index b27552cc54..db550fcc49 100644 --- a/src/pages/TrueSightV2/components/SwitchVariantDropdown.tsx +++ b/src/pages/TrueSightV2/components/SwitchVariantDropdown.tsx @@ -25,7 +25,7 @@ const SelectButton = styled(RowFit)` gap: 8px; cursor: pointer; font-size: 14px; - width: 135px; + width: 145px; :hover { z-index: 10; diff --git a/src/pages/TrueSightV2/pages/SingleToken.tsx b/src/pages/TrueSightV2/pages/SingleToken.tsx index 487cbb5a1d..535a19d5b4 100644 --- a/src/pages/TrueSightV2/pages/SingleToken.tsx +++ b/src/pages/TrueSightV2/pages/SingleToken.tsx @@ -262,23 +262,22 @@ const TokenNameGroup = ({ token, isLoading }: { token?: IAssetOverview; isLoadin const navigate = useNavigate() const location = useLocation() const above768 = useMedia(`(min-width:${MEDIA_WIDTHS.upToSmall}px)`) - const { chain } = useKyberAIAssetOverview() + const { chain, address } = useKyberAIAssetOverview() const reachedMaxLimit = useIsReachMaxLimitWatchedToken() const [addToWatchlist, { isLoading: loadingAddtoWatchlist }] = useAddToWatchlistMutation() const [removeFromWatchlist, { isLoading: loadingRemovefromWatchlist }] = useRemoveFromWatchlistMutation() const [isWatched, setIsWatched] = useState(false) const handleStarClick = () => { - if (!token || !chain || !account) return + if (!token || !chain || !address || !account) return if (isWatched) { mixpanelHandler(MIXPANEL_TYPE.KYBERAI_ADD_TOKEN_TO_WATCHLIST, { token_name: token.symbol?.toUpperCase(), source: 'explore', option: 'remove', }) - removeFromWatchlist({ - tokenAddress: token?.address, + tokenAddress: address, chain, }).then(() => setIsWatched(false)) } else { @@ -288,7 +287,7 @@ const TokenNameGroup = ({ token, isLoading }: { token?: IAssetOverview; isLoadin source: 'explore', option: 'add', }) - addToWatchlist({ tokenAddress: token?.address, chain }).then(() => setIsWatched(true)) + addToWatchlist({ tokenAddress: address, chain }).then(() => setIsWatched(true)) } } } @@ -373,10 +372,10 @@ const TokenNameGroup = ({ token, isLoading }: { token?: IAssetOverview; isLoadin ) } -const SettingButtons = ({ token, onShareClick }: { token?: IAssetOverview; onShareClick: () => void }) => { +const SettingButtons = ({ onShareClick }: { token?: IAssetOverview; onShareClick: () => void }) => { const theme = useTheme() const navigate = useNavigate() - const { chain } = useKyberAIAssetOverview() + const { chain, address } = useKyberAIAssetOverview() return ( <> @@ -384,7 +383,7 @@ const SettingButtons = ({ token, onShareClick }: { token?: IAssetOverview; onSha onClick={() => navigate( `${APP_PATHS.PROFILE_MANAGE}${PROFILE_MANAGE_ROUTES.CREATE_ALERT}?${stringify({ - inputCurrency: token?.address ?? '', + inputCurrency: address ?? '', chainId: chain ? NETWORK_TO_CHAINID[chain] : '', })}`, ) @@ -467,14 +466,14 @@ const TokenHeader = ({ }) => { const mixpanelHandler = useMixpanelKyberAI() const above768 = useMedia(`(min-width:${MEDIA_WIDTHS.upToSmall}px)`) - const { chain } = useKyberAIAssetOverview() + const { chain, address } = useKyberAIAssetOverview() return above768 ? ( - + @@ -502,7 +501,7 @@ const TokenHeader = ({ - + Date: Fri, 22 Sep 2023 11:05:37 +0700 Subject: [PATCH 09/15] remove console.log --- src/pages/TrueSightV2/components/SwitchVariantDropdown.tsx | 1 - src/pages/TrueSightV2/pages/SingleToken.tsx | 1 - 2 files changed, 2 deletions(-) diff --git a/src/pages/TrueSightV2/components/SwitchVariantDropdown.tsx b/src/pages/TrueSightV2/components/SwitchVariantDropdown.tsx index db550fcc49..6257aeb224 100644 --- a/src/pages/TrueSightV2/components/SwitchVariantDropdown.tsx +++ b/src/pages/TrueSightV2/components/SwitchVariantDropdown.tsx @@ -84,7 +84,6 @@ export default function SwitchVariantDropdown({ const { chain, address } = useKyberAIAssetOverview() useOnClickOutside(ref, () => setShow(false)) const variant = variants?.find(item => item.address.toLowerCase() === address && item.chain.toLowerCase() === chain) - console.log('🚀 ~ file: SwitchVariantDropdown.tsx:87 ~ variant:', variant) if (!variant && isLoading) { return ( { const theme = useTheme() const [show, setShow] = useState(true) const [isTextExceeded, setIsTextExceeded] = useState(false) - console.log('🚀 ~ file: SingleToken.tsx:191 ~ TokenDescription ~ isTextExceeded:', isTextExceeded) const ref = useCallback( (el: HTMLDivElement) => { From 20d5c8fc73a0a9b8b67fa0d27912f3abf5953aa9 Mon Sep 17 00:00:00 2001 From: XiaoYhun Date: Fri, 22 Sep 2023 12:22:14 +0700 Subject: [PATCH 10/15] fix header gap not consistent --- src/components/Header/groups/EarnNavGroup.tsx | 8 ++++---- src/components/Header/groups/KyberDaoGroup.tsx | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/components/Header/groups/EarnNavGroup.tsx b/src/components/Header/groups/EarnNavGroup.tsx index 2dfdee206e..3baad2ee91 100644 --- a/src/components/Header/groups/EarnNavGroup.tsx +++ b/src/components/Header/groups/EarnNavGroup.tsx @@ -47,7 +47,7 @@ const EarnNavGroup = () => { to={`${APP_PATHS.POOLS}/${networkInfo.route}`} style={{ width: '100%' }} > - + Pools @@ -61,14 +61,14 @@ const EarnNavGroup = () => { data-testid="farms-nav-link" to={`${APP_PATHS.FARMS}/${networkInfo.route}`} > - + Farms - + My Earnings @@ -82,7 +82,7 @@ const EarnNavGroup = () => { data-testid="my-pools-nav-link" to={`${APP_PATHS.MY_POOLS}/${networkInfo.route}`} > - + My Pools diff --git a/src/components/Header/groups/KyberDaoGroup.tsx b/src/components/Header/groups/KyberDaoGroup.tsx index 918647cfc6..2da86eba10 100644 --- a/src/components/Header/groups/KyberDaoGroup.tsx +++ b/src/components/Header/groups/KyberDaoGroup.tsx @@ -38,18 +38,18 @@ const KyberDAONavGroup = () => { } dropdownContent={ - + Stake KNC - + Vote { mixpanelHandler(MIXPANEL_TYPE.GAS_REFUND_SOURCE_CLICK, { source: 'KyberDAO_tab' }) }} @@ -61,7 +61,7 @@ const KyberDAONavGroup = () => { id="kyberdao-feature-request" href="https://kyberswap.canny.io/feature-request" target="_blank" - style={{ gap: '4px' }} + style={{ gap: '12px' }} onClick={() => { mixpanelHandler(MIXPANEL_TYPE.KYBER_DAO_FEATURE_REQUEST_CLICK) }} From 94e758e6d3303bb672f7a4c60e0b4c56a6bf8961 Mon Sep 17 00:00:00 2001 From: XiaoYhun Date: Mon, 25 Sep 2023 08:54:59 +0700 Subject: [PATCH 11/15] navigate to explore page using provided chain and address --- .../TrueSightV2/components/table/index.tsx | 4 +- src/pages/TrueSightV2/pages/SingleToken.tsx | 14 +++--- .../TrueSightV2/pages/TokenAnalysisList.tsx | 44 +++++++++---------- 3 files changed, 31 insertions(+), 31 deletions(-) diff --git a/src/pages/TrueSightV2/components/table/index.tsx b/src/pages/TrueSightV2/components/table/index.tsx index e133403d5d..61b88974ae 100644 --- a/src/pages/TrueSightV2/components/table/index.tsx +++ b/src/pages/TrueSightV2/components/table/index.tsx @@ -606,7 +606,9 @@ const WidgetTokenRow = ({ useOnClickOutside(rowRef, () => setShowSwapMenu(false)) const handleRowClick = () => { - navigate(`${APP_PATHS.KYBERAI_EXPLORE}/${token.asset_id}`) + navigate( + `${APP_PATHS.KYBERAI_EXPLORE}/${token.asset_id}?chain=${token.tokens[0].chain}&address=${token.tokens[0].address}`, + ) onClick?.() } diff --git a/src/pages/TrueSightV2/pages/SingleToken.tsx b/src/pages/TrueSightV2/pages/SingleToken.tsx index a5d0ad84c2..36e8d94541 100644 --- a/src/pages/TrueSightV2/pages/SingleToken.tsx +++ b/src/pages/TrueSightV2/pages/SingleToken.tsx @@ -156,8 +156,8 @@ const TabButton = styled.div<{ active?: boolean }>` export const defaultExplorePageToken = { chain: 'ethereum', - address: '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2', //TODO: remove - assetId: 1, + address: '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2', + assetId: 19277, } const StyledTokenDescription = styled.span<{ show?: boolean }>` @@ -536,7 +536,7 @@ export default function SingleToken() { const { assetId } = useParams() const [currentTab, setCurrentTab] = useState(DiscoverTokenTab.TechnicalAnalysis) - const { data: token, isLoading, chain } = useKyberAIAssetOverview() + const { data: token, isLoading, chain: chainParam, address: addressParam } = useKyberAIAssetOverview() const [viewAllTag, setViewAllTag] = useState(false) @@ -556,7 +556,7 @@ export default function SingleToken() { }, []) useEffect(() => { - if (token?.addresses && token.addresses[0].address && token.addresses[0].chain) { + if ((!chainParam || !addressParam) && token?.addresses && token.addresses[0].address && token.addresses[0].chain) { setSearchParams({ chain: token.addresses[0].chain, address: token.addresses[0].address }) } // eslint-disable-next-line react-hooks/exhaustive-deps @@ -600,7 +600,7 @@ export default function SingleToken() { onClick={() => { mixpanelHandler(MIXPANEL_TYPE.KYBERAI_EXPLORING_VIEW_ALL_CLICK, { token_name: token?.symbol?.toUpperCase(), - network: chain, + network: chainParam, }) setViewAllTag(true) }} @@ -622,7 +622,7 @@ export default function SingleToken() { onClick={() => { mixpanelHandler(MIXPANEL_TYPE.KYBERAI_EXPLORING_ANALYSIS_TYPE_CLICK, { token_name: token?.symbol?.toUpperCase(), - network: chain, + network: chainParam, option: tab === DiscoverTokenTab.OnChainAnalysis ? 'onchain_analysis' : 'technical_analysis', }) setCurrentTab(tab) @@ -656,7 +656,7 @@ export default function SingleToken() { onShareClick={social => mixpanelHandler(MIXPANEL_TYPE.KYBERAI_SHARE_TOKEN_CLICK, { token_name: token?.symbol?.toUpperCase(), - network: chain, + network: chainParam, source: MIXPANEL_KYBERAI_TAG.EXPLORE_SHARE_THIS_TOKEN, share_via: social, }) diff --git a/src/pages/TrueSightV2/pages/TokenAnalysisList.tsx b/src/pages/TrueSightV2/pages/TokenAnalysisList.tsx index 33ec558146..a4488ad027 100644 --- a/src/pages/TrueSightV2/pages/TokenAnalysisList.tsx +++ b/src/pages/TrueSightV2/pages/TokenAnalysisList.tsx @@ -3,7 +3,7 @@ import { Trans, t } from '@lingui/macro' import dayjs from 'dayjs' import { motion } from 'framer-motion' import { rgba } from 'polished' -import { ReactNode, useEffect, useRef, useState } from 'react' +import React, { ReactNode, useEffect, useRef, useState } from 'react' import { Info } from 'react-feather' import Skeleton, { SkeletonTheme } from 'react-loading-skeleton' import { useLocation, useNavigate, useSearchParams } from 'react-router-dom' @@ -460,7 +460,7 @@ const TokenListDraggableTabs = ({ tab, setTab }: { tab: KyberAIListType; setTab: ) } -const TokenRow = ({ +const TokenRow = React.memo(function TokenRow({ token, currentTab, index, @@ -472,7 +472,7 @@ const TokenRow = ({ index: number isScrolling?: boolean listType: KyberAIListType -}) => { +}) { const navigate = useNavigate() const location = useLocation() const mixpanelHandler = useMixpanelKyberAI() @@ -492,9 +492,12 @@ const TokenRow = ({ const hasMutipleChain = token.tokens.length > 1 const handleRowClick = () => { - navigate(`${APP_PATHS.KYBERAI_EXPLORE}/${token.asset_id}`, { - state: { from: location }, - }) + navigate( + `${APP_PATHS.KYBERAI_EXPLORE}/${token.asset_id}?chain=${token.tokens[0].chain}&address=${token.tokens[0].address}`, + { + state: { from: location }, + }, + ) } const handleWatchlistClick = (e: any) => { @@ -649,9 +652,12 @@ const TokenRow = ({ source: KYBERAI_LISTYPE_TO_MIXPANEL[listType], option: 'explore', }) - navigate(`${APP_PATHS.KYBERAI_EXPLORE}/${token.asset_id}`, { - state: { from: location }, - }) + navigate( + `${APP_PATHS.KYBERAI_EXPLORE}/${token.asset_id}?chain=${token.tokens[0].chain}&address=${token.tokens[0].address}`, + { + state: { from: location }, + }, + ) }} > @@ -694,7 +700,7 @@ const TokenRow = ({ ) -} +}) const LoadingRowSkeleton = ({ hasExtraCol }: { hasExtraCol?: boolean }) => { return ( <> @@ -737,21 +743,22 @@ export default function TokenAnalysisList() { const [searchParams, setSearchParams] = useSearchParams() const listTypeParam = (searchParams.get('listType') as KyberAIListType) || KyberAIListType.BULLISH const page = +(searchParams.get('page') || 1) - const chain = searchParams.get('chain') || 'all' + const chain = searchParams.get('chain') + const chainName = chain ? SUPPORTED_NETWORK_KYBERAI[Number(chain) as ChainId] : 'all' const pageSize = 25 const { data, isLoading, isFetching, isError } = useTokenListQuery( listTypeParam === KyberAIListType.MYWATCHLIST ? { type: KyberAIListType.ALL, - chain: (chain && SUPPORTED_NETWORK_KYBERAI[Number(chain) as ChainId]) || 'all', + chain: chainName, page, pageSize, watchlist: true, } : { type: listTypeParam, - chain: (chain && SUPPORTED_NETWORK_KYBERAI[Number(chain) as ChainId]) || 'all', + chain: chainName, page, pageSize, }, @@ -933,15 +940,6 @@ export default function TokenAnalysisList() { [KyberAIListType.TRENDING_SOON]: 'First Discovered On', }[listType as string] || ''} - {/* {sortedColumn === SORT_FIELD.VOLUME ? ( - !sortDirection ? ( - - ) : ( - - ) - ) : ( - '' - )} */} )} @@ -1053,7 +1051,7 @@ export default function TokenAnalysisList() { onShareClick={social => mixpanelHandler(MIXPANEL_TYPE.KYBERAI_SHARE_TOKEN_CLICK, { token_name: 'share_list_token', - network: chain, + network: chainName, source: KYBERAI_LISTYPE_TO_MIXPANEL[listType], share_via: social, }) From 996daf2b559e6fa1f370bd70153322b828ea9fcc Mon Sep 17 00:00:00 2001 From: XiaoYhun Date: Mon, 25 Sep 2023 09:38:22 +0700 Subject: [PATCH 12/15] improve network select --- .../TrueSightV2/components/NetworkSelect.tsx | 119 ++++++++++++------ src/pages/TrueSightV2/pages/SingleToken.tsx | 42 +++++-- .../TrueSightV2/pages/TokenAnalysisList.tsx | 22 ++-- 3 files changed, 122 insertions(+), 61 deletions(-) diff --git a/src/pages/TrueSightV2/components/NetworkSelect.tsx b/src/pages/TrueSightV2/components/NetworkSelect.tsx index 364fd54517..d85924efcd 100644 --- a/src/pages/TrueSightV2/components/NetworkSelect.tsx +++ b/src/pages/TrueSightV2/components/NetworkSelect.tsx @@ -1,18 +1,19 @@ import { ChainId } from '@kyberswap/ks-sdk-core' import { Trans } from '@lingui/macro' +import { AnimatePresence, motion } from 'framer-motion' import { useRef, useState } from 'react' import { X } from 'react-feather' -import { Flex, Image, Text } from 'rebass' +import { Image, Text } from 'rebass' import styled from 'styled-components' import { ReactComponent as ChevronDown } from 'assets/svg/down.svg' -import { OptionsContainer } from 'components' import Kyber from 'components/Icons/Kyber' +import Row, { RowFit } from 'components/Row' import { NETWORKS_INFO } from 'constants/networks' import { useOnClickOutside } from 'hooks/useOnClickOutside' import useTheme from 'hooks/useTheme' -import { SUPPORTED_NETWORK_KYBERAI } from '../constants' +import { NETWORK_TO_CHAINID, SUPPORTED_NETWORK_KYBERAI } from '../constants' const NetworkSelectContainer = styled.div` display: flex; @@ -24,9 +25,42 @@ const NetworkSelectContainer = styled.div` background: ${({ theme }) => theme.background}; min-width: 160px; cursor: pointer; + + :hover { + z-index: 10; + filter: brightness(1.2); + } +` + +const DropdownWrapper = styled(motion.div)` + position: absolute; + width: 100%; + border-radius: 10px; + background-color: ${({ theme }) => theme.buttonGray}; + left: 0; + top: calc(100% + 2px); + padding: 4px; + z-index: 10; + display: flex; + flex-direction: column; + gap: 4px; +` + +const DropdownItem = styled(Row)` + height: 32px; + padding: 4px 8px; + gap: 8px; + border-radius: 4px; + font-size: 14px; + cursor: pointer; + :hover { + filter: brightness(1.2); + background-color: ${({ theme }) => theme.background}; + } ` -const NetworkSelect = ({ filter, setFilter }: { filter?: ChainId; setFilter: (c?: ChainId) => void }) => { +const NetworkSelect = ({ filter, setFilter }: { filter?: string; setFilter: (c?: string) => void }) => { + console.log('🚀 ~ file: NetworkSelect.tsx:63 ~ NetworkSelect ~ filter:', filter) const theme = useTheme() const [isShowOptions, setIsShowOptions] = useState(false) @@ -36,23 +70,28 @@ const NetworkSelect = ({ filter, setFilter }: { filter?: ChainId; setFilter: (c? return ( { setIsShowOptions(prev => !prev) }} ref={containerRef} > - + {filter ? ( - + ) : ( - + )} - {filter ? NETWORKS_INFO[filter].name : All Chains} + {filter ? NETWORKS_INFO[NETWORK_TO_CHAINID[filter]].name : All Chains} - - + + {filter ? ( )} - - - {isShowOptions && ( - - {Object.keys(SUPPORTED_NETWORK_KYBERAI).map((network, index) => ( - { - setFilter(+network as ChainId) - }} - > - - - {NETWORKS_INFO[+network as ChainId].name} - - - ))} - - )} +
+ + {isShowOptions && ( + + {Object.keys(SUPPORTED_NETWORK_KYBERAI).map((chainId, index) => ( + { + setFilter(SUPPORTED_NETWORK_KYBERAI[+chainId as ChainId]) + }} + > + + + {NETWORKS_INFO[+chainId as ChainId].name} + + + ))} + + )} + ) } diff --git a/src/pages/TrueSightV2/pages/SingleToken.tsx b/src/pages/TrueSightV2/pages/SingleToken.tsx index 36e8d94541..01439c4f63 100644 --- a/src/pages/TrueSightV2/pages/SingleToken.tsx +++ b/src/pages/TrueSightV2/pages/SingleToken.tsx @@ -12,7 +12,6 @@ import styled, { css } from 'styled-components' import { ButtonPrimary } from 'components/Button' import Column from 'components/Column' import Icon from 'components/Icons/Icon' -import { DotsLoader } from 'components/Loader/DotsLoader' import Row, { RowBetween, RowFit } from 'components/Row' import { APP_PATHS } from 'constants/index' import { useActiveWeb3React } from 'hooks' @@ -330,15 +329,27 @@ const TokenNameGroup = ({ token, isLoading }: { token?: IAssetOverview; isLoadin
- + {token?.logo ? ( + + ) : ( + + )}
{isLoading ? ( - + ) : ( token && ( diff --git a/src/pages/TrueSightV2/pages/TokenAnalysisList.tsx b/src/pages/TrueSightV2/pages/TokenAnalysisList.tsx index a4488ad027..91b60f8b62 100644 --- a/src/pages/TrueSightV2/pages/TokenAnalysisList.tsx +++ b/src/pages/TrueSightV2/pages/TokenAnalysisList.tsx @@ -1,4 +1,3 @@ -import { ChainId } from '@kyberswap/ks-sdk-core' import { Trans, t } from '@lingui/macro' import dayjs from 'dayjs' import { motion } from 'framer-motion' @@ -39,7 +38,7 @@ import TokenListVariants from '../components/TokenListVariants' import { StarWithAnimation } from '../components/WatchlistStar' import KyberScoreChart from '../components/chart/KyberScoreChart' import TokenAnalysisListShareContent from '../components/shareContent/TokenAnalysisListShareContent' -import { KYBERAI_LISTYPE_TO_MIXPANEL, SUPPORTED_NETWORK_KYBERAI } from '../constants' +import { KYBERAI_LISTYPE_TO_MIXPANEL, NETWORK_TO_CHAINID } from '../constants' import useIsReachMaxLimitWatchedToken from '../hooks/useIsReachMaxLimitWatchedToken' import { useAddToWatchlistMutation, useRemoveFromWatchlistMutation, useTokenListQuery } from '../hooks/useKyberAIData' import { IKyberScoreChart, ITokenList, KyberAIListType } from '../types' @@ -743,22 +742,21 @@ export default function TokenAnalysisList() { const [searchParams, setSearchParams] = useSearchParams() const listTypeParam = (searchParams.get('listType') as KyberAIListType) || KyberAIListType.BULLISH const page = +(searchParams.get('page') || 1) - const chain = searchParams.get('chain') - const chainName = chain ? SUPPORTED_NETWORK_KYBERAI[Number(chain) as ChainId] : 'all' + const chain = searchParams.get('chain') || undefined const pageSize = 25 const { data, isLoading, isFetching, isError } = useTokenListQuery( listTypeParam === KyberAIListType.MYWATCHLIST ? { type: KyberAIListType.ALL, - chain: chainName, + chain: chain || 'all', page, pageSize, watchlist: true, } : { type: listTypeParam, - chain: chainName, + chain: chain || 'all', page, pageSize, }, @@ -774,18 +772,18 @@ export default function TokenAnalysisList() { searchParams.set('page', page.toString()) setSearchParams(searchParams) } - const handleChainChange = (chainId?: ChainId) => { - if (!chainId) { + const handleChainChange = (chainName?: string) => { + if (!chainName) { searchParams.delete('chain') mixpanelHandler(MIXPANEL_TYPE.KYBERAI_RANKING_SWITCH_CHAIN_CLICK, { source: KYBERAI_LISTYPE_TO_MIXPANEL[listType], network: 'All', }) } else { - searchParams.set('chain', chainId.toString()) + searchParams.set('chain', chainName) mixpanelHandler(MIXPANEL_TYPE.KYBERAI_RANKING_SWITCH_CHAIN_CLICK, { source: KYBERAI_LISTYPE_TO_MIXPANEL[listType], - network: NETWORKS_INFO[chainId].name, + network: NETWORKS_INFO[NETWORK_TO_CHAINID[chainName]].name, }) } searchParams.set('page', '1') @@ -845,7 +843,7 @@ export default function TokenAnalysisList() { > - + @@ -1051,7 +1049,7 @@ export default function TokenAnalysisList() { onShareClick={social => mixpanelHandler(MIXPANEL_TYPE.KYBERAI_SHARE_TOKEN_CLICK, { token_name: 'share_list_token', - network: chainName, + network: chain, source: KYBERAI_LISTYPE_TO_MIXPANEL[listType], share_via: social, }) From 4e24a24a4c468221ea3e54f91d56c4283fb5006d Mon Sep 17 00:00:00 2001 From: XiaoYhun Date: Mon, 25 Sep 2023 09:42:28 +0700 Subject: [PATCH 13/15] fix kyberai banner fetch api event user closed it --- src/components/KyberAITokenBanner/index.tsx | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/components/KyberAITokenBanner/index.tsx b/src/components/KyberAITokenBanner/index.tsx index 84893a8175..828f643f6e 100644 --- a/src/components/KyberAITokenBanner/index.tsx +++ b/src/components/KyberAITokenBanner/index.tsx @@ -24,7 +24,7 @@ import { NETWORK_TO_CHAINID } from 'pages/TrueSightV2/constants' import { SUPPORTED_NETWORK_KYBERAI } from 'pages/TrueSightV2/constants/index' import { useTokenOverviewQuery } from 'pages/TrueSightV2/hooks/useKyberAIData' import { calculateValueToColor } from 'pages/TrueSightV2/utils' -import { useIsWhiteListKyberAI } from 'state/user/hooks' +import { useIsWhiteListKyberAI, useShowKyberAIBanner } from 'state/user/hooks' import { MEDIA_WIDTHS } from 'theme' const KyberAITokenBanner = ({ @@ -36,6 +36,8 @@ const KyberAITokenBanner = ({ }) => { const { chainId, account } = useActiveWeb3React() const { isWhiteList } = useIsWhiteListKyberAI() + const isShowKyberAIBanner = useShowKyberAIBanner() + const navigate = useNavigate() const { mixpanelHandler } = useMixpanel() const chain = Object.keys(NETWORK_TO_CHAINID).find(i => NETWORK_TO_CHAINID[i] === chainId) @@ -49,17 +51,23 @@ const KyberAITokenBanner = ({ const { data: tokenInputOverview } = useTokenOverviewQuery( { address: token0?.address, chain }, - { skip: !token0?.address || !account || !isWhiteList || !chain, refetchOnMountOrArgChange: true }, + { + skip: !token0?.address || !account || !isWhiteList || !chain || !isShowKyberAIBanner, + refetchOnMountOrArgChange: true, + }, ) const { data: tokenOutputOverview } = useTokenOverviewQuery( { address: token1?.address, chain }, - { skip: !token1?.address || !account || !isWhiteList || !chain, refetchOnMountOrArgChange: true }, + { + skip: !token1?.address || !account || !isWhiteList || !chain || !isShowKyberAIBanner, + refetchOnMountOrArgChange: true, + }, ) const { data: tokenNativeOverview } = useTokenOverviewQuery( { address: NativeCurrencies[chainId].wrapped.address, chain }, - { skip: !account || !isWhiteList || !chain, refetchOnMountOrArgChange: true }, + { skip: !account || !isWhiteList || !chain || !isShowKyberAIBanner, refetchOnMountOrArgChange: true }, ) const token: { kyberScore?: number; label?: string; address?: string; logo?: string; symbol?: string } | undefined = From 48f325b0324f3310f75c729793882e75d5f69669 Mon Sep 17 00:00:00 2001 From: XiaoYhun Date: Mon, 25 Sep 2023 09:55:19 +0700 Subject: [PATCH 14/15] skip some api calls --- .../TrueSightV2/components/KyberAIWidget.tsx | 3 ++- .../hooks/useIsReachMaxLimitWatchedToken.tsx | 21 ++++++++++++------- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/src/pages/TrueSightV2/components/KyberAIWidget.tsx b/src/pages/TrueSightV2/components/KyberAIWidget.tsx index 37e77c908b..32e5549dd6 100644 --- a/src/pages/TrueSightV2/components/KyberAIWidget.tsx +++ b/src/pages/TrueSightV2/components/KyberAIWidget.tsx @@ -214,8 +214,9 @@ export default function Widget() { page: 1, pageSize: 5, }, - { refetchOnMountOrArgChange: true, skip: !isWhiteList }, + { refetchOnMountOrArgChange: true, skip: !isWhiteList || !showWidget }, ) + if (!account) return <> return ( diff --git a/src/pages/TrueSightV2/hooks/useIsReachMaxLimitWatchedToken.tsx b/src/pages/TrueSightV2/hooks/useIsReachMaxLimitWatchedToken.tsx index 9a06730b1f..cbf9e8902b 100644 --- a/src/pages/TrueSightV2/hooks/useIsReachMaxLimitWatchedToken.tsx +++ b/src/pages/TrueSightV2/hooks/useIsReachMaxLimitWatchedToken.tsx @@ -1,17 +1,24 @@ import { useMemo } from 'react' +import { useIsWhiteListKyberAI } from 'state/user/hooks' + import { ITokenList, KyberAIListType } from '../types' import { useTokenListQuery } from './useKyberAIData' const MAX_LIMIT_WATCHED_TOKEN = 30 export default function useIsReachMaxLimitWatchedToken(tokenCount?: number) { - const { data } = useTokenListQuery({ - type: KyberAIListType.ALL, - chain: 'all', - page: 1, - pageSize: 30, - watchlist: true, - }) + const { isWhiteList } = useIsWhiteListKyberAI() + + const { data } = useTokenListQuery( + { + type: KyberAIListType.ALL, + chain: 'all', + page: 1, + pageSize: 30, + watchlist: true, + }, + { skip: !isWhiteList }, + ) const watchedCount = useMemo(() => { let count = 0 From 13b162dc27fd546307a7129fcddfa42089cef937 Mon Sep 17 00:00:00 2001 From: XiaoYhun Date: Mon, 25 Sep 2023 11:13:34 +0700 Subject: [PATCH 15/15] fix comments --- src/pages/TrueSightV2/components/SearchWithDropDown.tsx | 2 +- src/pages/TrueSightV2/hooks/useKyberAIData.tsx | 2 -- src/pages/TrueSightV2/pages/SingleToken.tsx | 3 ++- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/pages/TrueSightV2/components/SearchWithDropDown.tsx b/src/pages/TrueSightV2/components/SearchWithDropDown.tsx index 3df6a4f1d9..d75259ae01 100644 --- a/src/pages/TrueSightV2/components/SearchWithDropDown.tsx +++ b/src/pages/TrueSightV2/components/SearchWithDropDown.tsx @@ -320,7 +320,7 @@ const SearchWithDropdown = () => { ) const [history, setHistory] = useLocalStorage>('kyberai-search-history') const saveToHistory = (token: ITokenSearchResult) => { - if (!(history && history.findIndex(t => t.assetId === token.assetId) >= 0)) { + if (!(history && history.some(t => t.assetId === token.assetId))) { setHistory([token, ...(history || [])].slice(0, 3)) } } diff --git a/src/pages/TrueSightV2/hooks/useKyberAIData.tsx b/src/pages/TrueSightV2/hooks/useKyberAIData.tsx index d57b590b1b..7f28e3e64a 100644 --- a/src/pages/TrueSightV2/hooks/useKyberAIData.tsx +++ b/src/pages/TrueSightV2/hooks/useKyberAIData.tsx @@ -57,7 +57,6 @@ const kyberAIApi = createApi({ }, providesTags: (result, error, arg) => (arg.watchlist === true ? ['myWatchList', 'tokenList'] : ['tokenList']), }), - //2. TODO addToWatchlist: builder.mutation({ query: (params: { tokenAddress: string; chain: string }) => ({ url: `/watchlist`, @@ -66,7 +65,6 @@ const kyberAIApi = createApi({ }), invalidatesTags: (res, err, params) => [{ type: 'tokenOverview', id: params.tokenAddress }, 'myWatchList'], }), - //3. TODO removeFromWatchlist: builder.mutation({ query: (params: { tokenAddress: string; chain: string }) => ({ url: `/watchlist`, diff --git a/src/pages/TrueSightV2/pages/SingleToken.tsx b/src/pages/TrueSightV2/pages/SingleToken.tsx index 01439c4f63..8e01028a24 100644 --- a/src/pages/TrueSightV2/pages/SingleToken.tsx +++ b/src/pages/TrueSightV2/pages/SingleToken.tsx @@ -19,6 +19,7 @@ import { MIXPANEL_TYPE, useMixpanelKyberAI } from 'hooks/useMixpanel' import useTheme from 'hooks/useTheme' import { PROFILE_MANAGE_ROUTES } from 'pages/NotificationCenter/const' import { MEDIA_WIDTHS } from 'theme' +import { escapeScriptHtml } from 'utils/string' import DisplaySettings from '../components/DisplaySettings' import FeedbackSurvey from '../components/FeedbackSurvey' @@ -211,7 +212,7 @@ const TokenDescription = ({ description }: { description: string }) => { {isTextExceeded && show && (