diff --git a/components/PoolPage.tsx b/components/PoolPage.tsx index 3c6a4b0..6a38b13 100644 --- a/components/PoolPage.tsx +++ b/components/PoolPage.tsx @@ -49,7 +49,7 @@ const PoolContents = () => { {poolData ? ( - + ) : (
diff --git a/components/pool/CollateralAssetRow.tsx b/components/pool/CollateralAssetRow.tsx index 179ffcf..4c14335 100644 --- a/components/pool/CollateralAssetRow.tsx +++ b/components/pool/CollateralAssetRow.tsx @@ -128,7 +128,7 @@ const CollateralAssetRow = ({ crossAxisAlignment="center" width={isMobile ? "33%" : "20%"} > - {collateralValue !== undefined ? ( + {collateralValue !== undefined ? ( <> {smallUsdPriceFormatter( diff --git a/components/pool/DisplayGraph.tsx b/components/pool/DisplayGraph.tsx index 236bff3..bb423b2 100644 --- a/components/pool/DisplayGraph.tsx +++ b/components/pool/DisplayGraph.tsx @@ -6,7 +6,7 @@ import { ModalDivider } from "components/shared/Modal"; import { PoolConfig } from "interfaces/pool"; import RenderGraphSections from "components/pool/graph/RenderGraphSections"; -const DisplayGraph = ({ poolData }: { poolData: PoolConfig }) => { +const DisplayGraph = () => { const { t } = useTranslation(); const isMobile = useIsMobile(); @@ -28,7 +28,7 @@ const DisplayGraph = ({ poolData }: { poolData: PoolConfig }) => { crossAxisAlignment="flex-start" width="100%" > - {RenderGraphSections(poolData)} + {RenderGraphSections()} ) : ( { px={4} my={4} > - {RenderGraphSections(poolData)} + {RenderGraphSections()} )} diff --git a/components/pool/graph/GraphModel.tsx b/components/pool/graph/GraphModel.tsx index 46871b5..8a3d258 100644 --- a/components/pool/graph/GraphModel.tsx +++ b/components/pool/graph/GraphModel.tsx @@ -18,6 +18,7 @@ import { calculateInitialData, calculateYDomain, getTransform, + roundDownToTheFourthDecimalPlace, } from "hooks/util/graph"; import { AxisRange, @@ -34,8 +35,10 @@ import usePoolData from "hooks/pool/usePoolData"; import useInitialUtilization from "hooks/graph/useInitialUtilization"; import { OneHundred } from "constants/graph"; import { truncateTo3DecimalPlaces } from "utils/bigUtils"; +import useRewardData from "hooks/graph/useRewardData"; const GraphModel: React.FC = ({ + poolData, dataKeys, labels, rewardAPRValue, @@ -58,6 +61,7 @@ const GraphModel: React.FC = ({ undefined, ); const [rewardEarn, setRewardEarn] = useState(undefined); + const tempRewardData = useRewardData({ poolData }); useEffect(() => { if (rewardAPRValue?.borrow || rewardAPRValue?.borrow === 0) { @@ -67,13 +71,13 @@ const GraphModel: React.FC = ({ OneHundred, ); } - if (rewardAPRValue?.earn || rewardAPRValue?.earn === 0) { + if (tempRewardData?.earn || tempRewardData?.earn === 0) { setRewardEarn( - (truncateTo3DecimalPlaces(rewardAPRValue?.earn) * hoverData.earnValue) / + (truncateTo3DecimalPlaces(tempRewardData?.earn) * hoverData.earnValue) / OneHundred, ); } - }, [rewardAPRValue, hoverData]); + }, [rewardAPRValue, hoverData, tempRewardData]); const handleMouseMove = (state: any) => { if (state.isTooltipActive) { @@ -122,9 +126,11 @@ const GraphModel: React.FC = ({ {hoverData - ? rewardAPRValue?.borrow || rewardAPRValue?.borrow === 0 - ? `${rewardBorrow?.toFixed(3)}%` - : `${hoverData.borrowValue.toFixed(3)}%` + ? roundDownToTheFourthDecimalPlace( + rewardAPRValue?.borrow || rewardAPRValue?.borrow === 0 + ? rewardBorrow + : hoverData.borrowValue, + ) : "-"} @@ -134,9 +140,11 @@ const GraphModel: React.FC = ({ {hoverData - ? rewardAPRValue?.earn || rewardAPRValue?.earn === 0 - ? `${rewardEarn?.toFixed(3)}%` - : `${hoverData.earnValue.toFixed(3)}%` + ? roundDownToTheFourthDecimalPlace( + rewardAPRValue?.earn || rewardAPRValue?.earn === 0 + ? rewardEarn + : hoverData.earnValue, + ) : "-"} diff --git a/components/pool/graph/APRGraph.tsx b/components/pool/graph/InterestAPRGraph.tsx similarity index 76% rename from components/pool/graph/APRGraph.tsx rename to components/pool/graph/InterestAPRGraph.tsx index 870e99a..2e5f58b 100644 --- a/components/pool/graph/APRGraph.tsx +++ b/components/pool/graph/InterestAPRGraph.tsx @@ -1,8 +1,12 @@ import React from "react"; -import { PoolConfig } from "interfaces/pool"; import GraphModel from "./GraphModel"; +import usePool from "hooks/pool/usePool"; + +const InterestAPRGraph = () => { + const { poolConfig: poolData } = usePool(); + + if (!poolData) return null; -const APRGraph = ({ poolData }: { poolData: PoolConfig }) => { const dataKeys = { earn: { supplyRateSlopeLow: poolData.supplyPerYearInterestRateSlopeLow, @@ -19,10 +23,11 @@ const APRGraph = ({ poolData }: { poolData: PoolConfig }) => { return ( ); }; -export default APRGraph; +export default InterestAPRGraph; diff --git a/components/pool/graph/RenderGraphSections.tsx b/components/pool/graph/RenderGraphSections.tsx index 1495d38..9575169 100644 --- a/components/pool/graph/RenderGraphSections.tsx +++ b/components/pool/graph/RenderGraphSections.tsx @@ -2,15 +2,13 @@ import React from "react"; import { Box } from "@chakra-ui/react"; import { useTranslation } from "react-i18next"; import { Column, useIsMobile } from "utils/chakraUtils"; -import APRGraph from "components/pool/graph/APRGraph"; -import RewardGraph from "components/pool/graph/RewardGraph"; -import { PoolConfig } from "interfaces/pool"; +import InterestAPRGraph from "components/pool/graph/InterestAPRGraph"; +import RewardAPRGraph from "components/pool/graph/RewardAPRGraph"; import { RenderGraphSectionProps } from "interfaces/graph"; const RenderGraphSection = ({ title, GraphComponent, - poolData, }: RenderGraphSectionProps) => { const { t } = useTranslation(); const isMobile = useIsMobile(); @@ -31,22 +29,20 @@ const RenderGraphSection = ({ > {t(title)} - + ); }; -const RenderGraphSections = (poolData: PoolConfig) => ( +const RenderGraphSections = () => ( <> ); diff --git a/components/pool/graph/RewardGraph.tsx b/components/pool/graph/RewardAPRGraph.tsx similarity index 82% rename from components/pool/graph/RewardGraph.tsx rename to components/pool/graph/RewardAPRGraph.tsx index a7e568a..a586778 100644 --- a/components/pool/graph/RewardGraph.tsx +++ b/components/pool/graph/RewardAPRGraph.tsx @@ -1,11 +1,14 @@ import React from "react"; -import { PoolConfig } from "interfaces/pool"; import GraphModel from "./GraphModel"; import { OneHundred, rateSlopeLow } from "constants/graph"; import usePoolData from "hooks/pool/usePoolData"; +import usePool from "hooks/pool/usePool"; -const RewardGraph = ({ poolData }: { poolData: PoolConfig }) => { +const RewardAPRGraph = () => { const { tokenRewardData } = usePoolData(); + const { poolConfig: poolData } = usePool(); + + if (!poolData) return null; const rateSlopeHigh = parseFloat( (OneHundred / (OneHundred - poolData.rewardKink)).toFixed(2), @@ -26,6 +29,7 @@ const RewardGraph = ({ poolData }: { poolData: PoolConfig }) => { return ( { ); }; -export default RewardGraph; +export default RewardAPRGraph; diff --git a/constants/graph.ts b/constants/graph.ts index 1f8c278..82ec7f9 100644 --- a/constants/graph.ts +++ b/constants/graph.ts @@ -1,4 +1,5 @@ export const OneHundred = 100; +export const OneThousand = 1000; export const AxisRange = [0, 100]; export const LeftMin = 20; export const LeftMax = 80; @@ -8,7 +9,6 @@ export const HoverPositionLowerThresholdMobile = 70; export const HoverPositionUpperThresholdMobile = 180; export const rateSlopeLow = 0; export const DAYS_IN_YEAR = 365; -export const REWARD_BONUS_RATE_VALUE = 1; //PNDが1ドルを下回った時に発生するボーナス倍率 export const LightGrayColorCode = "#949494"; export const LightBlackColorCode = "#3a4450"; export const PinkColorCode = "#FF2E6C"; diff --git a/hooks/graph/useRewardData.ts b/hooks/graph/useRewardData.ts new file mode 100644 index 0000000..4549c7a --- /dev/null +++ b/hooks/graph/useRewardData.ts @@ -0,0 +1,42 @@ +import { useEffect, useState } from "react"; +import usePoolData from "hooks/pool/usePoolData"; +import { PoolConfig } from "interfaces/pool"; +import { RewardDataProps } from "interfaces/graph"; +import { calculateTotalBalance, calculateRewardData } from "hooks/util/graph"; + +const useRewardData = ({ poolData }: { poolData: PoolConfig }) => { + const [tempRewardData, setTempRewardData] = useState({ + earn: undefined, + }); + const { priceFeedData, totalPoolData } = usePoolData(); + + useEffect(() => { + if (!poolData) { + return; + } + + const totalSupply = + (totalPoolData?.totalBaseSupplyBalance ?? 0) >= + poolData?.baseMinForRewards + ? totalPoolData?.totalBaseSupplyBalance ?? 0 + : 0; + const totalBaseSupplyBalance = calculateTotalBalance( + totalSupply, + priceFeedData, + ); + + const tempSupplyRewardData = calculateRewardData( + poolData.baseTrackingRewardSpeed, + totalBaseSupplyBalance, + priceFeedData?.rewardAsset, + ); + + setTempRewardData({ + earn: tempSupplyRewardData, + }); + }, [priceFeedData, totalPoolData, poolData]); + + return tempRewardData; +}; + +export default useRewardData; diff --git a/hooks/pool/shared/usePriceFeed.ts b/hooks/pool/shared/usePriceFeed.ts index a011ee3..f4f592b 100644 --- a/hooks/pool/shared/usePriceFeed.ts +++ b/hooks/pool/shared/usePriceFeed.ts @@ -64,20 +64,20 @@ const usePriceFeedData = (poolData: PoolConfig | undefined) => { formatUnits(rewardPrice, poolData.rewardToken.priceFeedDecimals), ) : undefined; - const collateralAssets: { [key: string]: number | undefined } = {}; - for (const assetConfig of poolData.assetConfigs) { - if (assetConfig.priceFeed === AddressZero) { - collateralAssets[assetConfig.symbol] = 0; - } else { - const assetPrice = await fetchPriceFeed( - assetConfig.priceFeed, - poolData.chainId, - ); - collateralAssets[assetConfig.symbol] = assetPrice - ? Number(formatUnits(assetPrice, assetConfig.priceFeedDecimals)) - : undefined; - } + const collateralAssets: { [key: string]: number | undefined } = {}; + for (const assetConfig of poolData.assetConfigs) { + if (assetConfig.priceFeed === AddressZero) { + collateralAssets[assetConfig.symbol] = 0; + } else { + const assetPrice = await fetchPriceFeed( + assetConfig.priceFeed, + poolData.chainId, + ); + collateralAssets[assetConfig.symbol] = assetPrice + ? Number(formatUnits(assetPrice, assetConfig.priceFeedDecimals)) + : undefined; } + } setPriceFeedData({ usdjpy, diff --git a/hooks/util/graph.ts b/hooks/util/graph.ts index 25583cb..b279069 100644 --- a/hooks/util/graph.ts +++ b/hooks/util/graph.ts @@ -1,9 +1,5 @@ import { GenerateDataProps } from "interfaces/graph"; -import { - OneHundred, - DAYS_IN_YEAR, - REWARD_BONUS_RATE_VALUE, -} from "constants/graph"; +import { OneHundred, OneThousand, DAYS_IN_YEAR } from "constants/graph"; import { HoverPositionLowerThreshold, HoverPositionUpperThreshold, @@ -103,3 +99,31 @@ export const getTransform = ( : "translateX(-50%)"; } }; + +export const calculateTotalBalance = ( + balance: number | undefined, + priceFeedData: PriceFeedData | undefined, +) => + balance !== undefined && + balance > 0 && + priceFeedData?.baseAsset !== undefined && + priceFeedData.baseAsset > 0 + ? balance * priceFeedData.baseAsset + : 0; + +export const calculateRewardData = ( + trackingRewardSpeed: number, + totalBalance: number, + rewardAsset: number | undefined, +) => + totalBalance > 0 + ? ((trackingRewardSpeed * DAYS_IN_YEAR * (rewardAsset || 0)) / + totalBalance) * + OneHundred + : 0; + +export const roundDownToTheFourthDecimalPlace = (value: number | undefined) => { + return value !== undefined + ? `${(Math.floor(value * OneThousand) / OneThousand).toFixed(3)}%` + : "-"; +}; diff --git a/interfaces/graph.ts b/interfaces/graph.ts index 0b76d54..3961799 100644 --- a/interfaces/graph.ts +++ b/interfaces/graph.ts @@ -15,6 +15,7 @@ export interface DataKeys { } export interface GraphModelProps { + poolData: PoolConfig; dataKeys: DataKeys; labels: { borrow: string; earn: string }; rewardAPRValue?: { borrow: number | undefined; earn: number | undefined }; @@ -26,6 +27,9 @@ export interface GenerateDataProps { export interface RenderGraphSectionProps { title: string; - GraphComponent: React.FC<{ poolData: PoolConfig }>; - poolData: PoolConfig; + GraphComponent: React.FC<{}>; +} + +export interface RewardDataProps { + earn: number | undefined; }