From 15b98907c97ca623d923c6c4414d4c714cbf43a7 Mon Sep 17 00:00:00 2001 From: damnnou Date: Tue, 23 Apr 2024 15:04:19 +0300 Subject: [PATCH] fix: fill last tick, chore fixes --- src/components/common/Table/poolsColumns.tsx | 80 +++++-------- .../create-position/LiquidityChart/chart.tsx | 12 +- src/components/pools/PoolsList/index.tsx | 107 ++++++++---------- src/components/swap/TicksChart/index.tsx | 17 ++- src/index.css | 4 + src/utils/swap/processTicks.ts | 7 +- 6 files changed, 94 insertions(+), 133 deletions(-) diff --git a/src/components/common/Table/poolsColumns.tsx b/src/components/common/Table/poolsColumns.tsx index 81a18be..1425d59 100644 --- a/src/components/common/Table/poolsColumns.tsx +++ b/src/components/common/Table/poolsColumns.tsx @@ -1,14 +1,14 @@ -import { ColumnDef } from '@tanstack/react-table'; -import { HeaderItem } from './common'; -import { Address } from 'wagmi'; -import CurrencyLogo from '../CurrencyLogo'; -import { TokenFieldsFragment } from '@/graphql/generated/graphql'; -import { DynamicFeePluginIcon } from '../PluginIcons'; -import { formatUSD } from '@/utils/common/formatUSD'; -import { usePoolPlugins } from '@/hooks/pools/usePoolPlugins'; -import { Skeleton } from '@/components/ui/skeleton'; -import { FarmingPluginIcon } from '../PluginIcons'; -import { useCurrency } from '@/hooks/common/useCurrency'; +import { ColumnDef } from "@tanstack/react-table"; +import { HeaderItem } from "./common"; +import { Address } from "wagmi"; +import CurrencyLogo from "../CurrencyLogo"; +import { TokenFieldsFragment } from "@/graphql/generated/graphql"; +import { DynamicFeePluginIcon } from "../PluginIcons"; +import { formatUSD } from "@/utils/common/formatUSD"; +import { usePoolPlugins } from "@/hooks/pools/usePoolPlugins"; +import { Skeleton } from "@/components/ui/skeleton"; +import { FarmingPluginIcon } from "../PluginIcons"; +import { useCurrency } from "@/hooks/common/useCurrency"; interface Pair { token0: TokenFieldsFragment; @@ -23,6 +23,8 @@ interface Pool { volume24USD: number; maxApr: number; avgApr: number; + isMyPool: boolean; + hasActiveFarming: boolean; } const PoolPair = ({ pair, fee }: Pool) => { @@ -36,11 +38,7 @@ const PoolPair = ({ pair, fee }: Pool) => {
- +
{currencyA && currencyB ? ( @@ -67,76 +65,52 @@ const Plugins = ({ poolId }: { poolId: Address }) => { export const poolsColumns: ColumnDef[] = [ { - accessorKey: 'pair', + accessorKey: "pair", header: () => Pool, cell: ({ row }) => , filterFn: (v, _, value) => - [ - v.original.pair.token0.symbol, - v.original.pair.token1.symbol, - v.original.pair.token0.name, - v.original.pair.token1.name, - ] - .join(' ') + [v.original.pair.token0.symbol, v.original.pair.token1.symbol, v.original.pair.token0.name, v.original.pair.token1.name] + .join(" ") .toLowerCase() .includes(value), }, { - accessorKey: 'plugins', + accessorKey: "plugins", header: () => Plugins, cell: ({ row }) => , + filterFn: (v, _, value: boolean) => v.original.hasActiveFarming === value, }, { - accessorKey: 'tvlUSD', + accessorKey: "tvlUSD", header: ({ column }) => ( - - column.toggleSorting(column.getIsSorted() === 'asc') - } - isAsc={column.getIsSorted() === 'asc'} - > + column.toggleSorting(column.getIsSorted() === "asc")} isAsc={column.getIsSorted() === "asc"}> TVL ), cell: ({ getValue }) => formatUSD.format(getValue() as number), }, { - accessorKey: 'volume24USD', + accessorKey: "volume24USD", header: ({ column }) => ( - - column.toggleSorting(column.getIsSorted() === 'asc') - } - isAsc={column.getIsSorted() === 'asc'} - > + column.toggleSorting(column.getIsSorted() === "asc")} isAsc={column.getIsSorted() === "asc"}> Volume 24H ), cell: ({ getValue }) => formatUSD.format(getValue() as number), }, { - accessorKey: 'maxApr', + accessorKey: "maxApr", header: ({ column }) => ( - - column.toggleSorting(column.getIsSorted() === 'asc') - } - isAsc={column.getIsSorted() === 'asc'} - > + column.toggleSorting(column.getIsSorted() === "asc")} isAsc={column.getIsSorted() === "asc"}> Max. APR ), cell: ({ getValue }) => `${getValue()} %`, }, { - accessorKey: 'avgApr', + accessorKey: "avgApr", header: ({ column }) => ( - - column.toggleSorting(column.getIsSorted() === 'asc') - } - isAsc={column.getIsSorted() === 'asc'} - > + column.toggleSorting(column.getIsSorted() === "asc")} isAsc={column.getIsSorted() === "asc"}> Avg. APR ), diff --git a/src/components/create-position/LiquidityChart/chart.tsx b/src/components/create-position/LiquidityChart/chart.tsx index 7f9ae43..70c4628 100644 --- a/src/components/create-position/LiquidityChart/chart.tsx +++ b/src/components/create-position/LiquidityChart/chart.tsx @@ -13,6 +13,7 @@ interface CustomBarProps { percent: number | undefined; isCurrent: boolean; isAfterSwapTick: boolean; + isFocused: boolean; } interface CustomTooltipProps { @@ -41,10 +42,11 @@ const CustomBar = ({ fill, percent, isCurrent, - isAfterSwapTick + isAfterSwapTick, + isFocused, }: CustomBarProps) => { return ( - + @@ -52,8 +54,8 @@ const CustomBar = ({ {percent && {`${percent.toFixed(0)}%`}} - {isCurrent && Current Price} - {isAfterSwapTick && !isCurrent && After Swap} + {isCurrent && isFocused && Current Price} + {isAfterSwapTick && !isCurrent && isFocused && After Swap} ) @@ -145,7 +147,7 @@ export function Chart({ formattedData, currencyA, currencyB, leftPrice, rightPri percent = (props.payload.index < currentPriceRealIndex ? -1 : 1) * ((Math.max(props.payload.index, currentPriceRealIndex) - Math.min(props.payload.index, currentPriceRealIndex)) / currentPriceRealIndex) * 100 } - return + return }} > {formattedData?.map((entry: any, index: number) => { diff --git a/src/components/pools/PoolsList/index.tsx b/src/components/pools/PoolsList/index.tsx index d094a86..4f7ef14 100644 --- a/src/components/pools/PoolsList/index.tsx +++ b/src/components/pools/PoolsList/index.tsx @@ -1,81 +1,66 @@ -import { poolsColumns } from '@/components/common/Table/poolsColumns'; -import { - usePoolsListQuery, - usePoolsVolumeDataQuery, -} from '@/graphql/generated/graphql'; -import { useMemo } from 'react'; -import { Address } from 'viem'; -import { POOL_AVG_APR_API, POOL_MAX_APR_API, fetcher } from '@/constants/api'; -import useSWR from 'swr'; -import PoolsTable from '@/components/common/Table/poolsTable'; +import { poolsColumns } from "@/components/common/Table/poolsColumns"; +import { usePoolsListQuery, usePoolsVolumeDataQuery } from "@/graphql/generated/graphql"; +import { useMemo } from "react"; +import { Address } from "viem"; +import { POOL_AVG_APR_API, POOL_MAX_APR_API, fetcher } from "@/constants/api"; +import useSWR from "swr"; +import PoolsTable from "@/components/common/Table/poolsTable"; +import { usePositions } from "@/hooks/positions/usePositions"; +import { usePoolsStore } from "@/state/poolsStore"; const PoolsList = () => { const { data: pools, loading: isPoolsListLoading } = usePoolsListQuery(); - const { data: poolsVolume, loading: isPoolsVolumeLoading } = - usePoolsVolumeDataQuery(); + const { data: poolsVolume, loading: isPoolsVolumeLoading } = usePoolsVolumeDataQuery(); - const { data: poolsMaxApr, isLoading: isPoolsMaxAprLoading } = useSWR( - POOL_MAX_APR_API, - fetcher - ); - const { data: poolsAvgApr, isLoading: isPoolsAvgAprLoading } = useSWR( - POOL_AVG_APR_API, - fetcher - ); + const { data: poolsMaxApr, isLoading: isPoolsMaxAprLoading } = useSWR(POOL_MAX_APR_API, fetcher); + const { data: poolsAvgApr, isLoading: isPoolsAvgAprLoading } = useSWR(POOL_AVG_APR_API, fetcher); + + const { positions, loading: isPositionsLoading } = usePositions(); - const isLoading = - isPoolsListLoading || - isPoolsVolumeLoading || - isPoolsMaxAprLoading || - isPoolsAvgAprLoading; + const isLoading = isPoolsListLoading || isPoolsVolumeLoading || isPoolsMaxAprLoading || isPoolsAvgAprLoading || isPositionsLoading; + + const { pluginsForPools } = usePoolsStore(); const formattedPools = useMemo(() => { - if ( - !pools?.pools || - !poolsMaxApr || - !poolsAvgApr || - !poolsVolume?.poolDayDatas - ) - return []; + if (!pools?.pools || !poolsMaxApr || !poolsAvgApr || !poolsVolume?.poolDayDatas || !positions) return []; + + return pools.pools.map(({ id, token0, token1, fee, totalValueLockedUSD }) => { + const currentPool = poolsVolume.poolDayDatas.find((currPool) => currPool.pool.id === id); + const lastDate = currentPool ? currentPool.date * 1000 : 0; + const currentDate = new Date().getTime(); + + const timeDifference = currentDate - lastDate; + const msIn24Hours = 24 * 60 * 60 * 1000; - return pools.pools.map( - ({ id, token0, token1, fee, totalValueLockedUSD }) => { - const currentPool = poolsVolume.poolDayDatas.find( - (currPool) => currPool.pool.id === id - ); - const lastDate = currentPool ? currentPool.date * 1000 : 0; - const currentDate = new Date().getTime(); + const openPositions = positions.filter((position) => position.pool.toLowerCase() === id.toLowerCase()); - const timeDifference = currentDate - lastDate; - const msIn24Hours = 24 * 60 * 60 * 1000; + const hasActiveFarming = pluginsForPools[id as Address]?.farmingPlugin; - return { - id: id as Address, - pair: { - token0, - token1, - }, - fee: Number(fee) / 10_000, - tvlUSD: Number(totalValueLockedUSD), - volume24USD: - timeDifference <= msIn24Hours && currentPool - ? currentPool.volumeUSD - : 0, - maxApr: poolsMaxApr[id] ? poolsMaxApr[id].toFixed(2) : 0, - avgApr: poolsAvgApr[id] ? poolsAvgApr[id].toFixed(2) : 0, - }; - } - ); - }, [pools, poolsMaxApr, poolsAvgApr, poolsVolume]); + return { + id: id as Address, + pair: { + token0, + token1, + }, + fee: Number(fee) / 10_000, + tvlUSD: Number(totalValueLockedUSD), + volume24USD: timeDifference <= msIn24Hours && currentPool ? currentPool.volumeUSD : 0, + maxApr: poolsMaxApr[id] ? poolsMaxApr[id].toFixed(2) : 0, + avgApr: poolsAvgApr[id] ? poolsAvgApr[id].toFixed(2) : 0, + isMyPool: openPositions?.length > 0, + hasActiveFarming, + }; + }); + }, [pools, poolsMaxApr, poolsAvgApr, poolsVolume, positions]); return (
diff --git a/src/components/swap/TicksChart/index.tsx b/src/components/swap/TicksChart/index.tsx index 1d638ff..b50748e 100644 --- a/src/components/swap/TicksChart/index.tsx +++ b/src/components/swap/TicksChart/index.tsx @@ -48,15 +48,14 @@ const TicksChart = ({ currencyA, currencyB, zoom = 50 }: TicksChartProps) => { const slicedData = processedData.slice(middle - chunkLength, middle + chunkLength); - if (slicedData[slicedData.length - 1].isAfterSwapRange) { - slicedData.map((t: any) => (t.isAfterSwapTick = false)); - slicedData[slicedData.length - 1].isAfterSwapTick = true; - } - - if (slicedData[0].isAfterSwapRange) { - slicedData.map((t: any) => (t.isAfterSwapTick = false)); - slicedData[0].isAfterSwapTick = true; - } + slicedData.forEach((t: any) => (t.isAfterSwapTick = false)); + + const firstTick = slicedData.find((t: any) => t.isAfterSwapRange && !t.isReversed); + const lastTick = [...slicedData].reverse().find((t: any) => t.isAfterSwapRange && t.isReversed); + + if (firstTick) firstTick.isAfterSwapTick = true; + + if (lastTick) lastTick.isAfterSwapTick = true; return slicedData.reverse(); }, [processedData, zoom, tick]); diff --git a/src/index.css b/src/index.css index 2be99ee..19aee4e 100644 --- a/src/index.css +++ b/src/index.css @@ -92,4 +92,8 @@ } ::-webkit-scrollbar-thumb:active{ background: rgba(255, 255, 255, .8); +} + +.recharts-surface { + overflow: visible; } \ No newline at end of file diff --git a/src/utils/swap/processTicks.ts b/src/utils/swap/processTicks.ts index c508486..d03b78d 100644 --- a/src/utils/swap/processTicks.ts +++ b/src/utils/swap/processTicks.ts @@ -21,10 +21,7 @@ export async function processTicks( const active = currentTick <= tick && tick < nextTick; const afterSwapRange = - tickAfterSwap && - ((tickAfterSwap >= currentTick && currentTick >= tick) || (tickAfterSwap <= currentTick && currentTick <= tick)); - - const afterSwapTick = tickAfterSwap && tickAfterSwap >= currentTick && tickAfterSwap < nextTick; + tickAfterSwap && ((tickAfterSwap >= currentTick && currentTick >= tick) || (tickAfterSwap <= nextTick && nextTick <= tick)); const sqrtPriceX96 = TickMath.getSqrtRatioAtTick(currentTick); const mockTicks = [ @@ -68,7 +65,7 @@ export async function processTicks( index: i, isCurrent: active, isAfterSwapRange: afterSwapRange, - isAfterSwapTick: afterSwapTick, + isAfterSwapTick: null, isReversed, activeLiquidity: parseFloat(t.liquidityActive.toString()), price0: parseFloat(t.price0),