Skip to content

Commit

Permalink
Update Liquidity chart on Analytics page
Browse files Browse the repository at this point in the history
  • Loading branch information
uncoolzero committed Dec 15, 2023
1 parent fa5c023 commit 168a8af
Show file tree
Hide file tree
Showing 2 changed files with 167 additions and 32 deletions.
198 changes: 167 additions & 31 deletions projects/ui/src/components/Analytics/Bean/Liquidity.tsx
Original file line number Diff line number Diff line change
@@ -1,51 +1,187 @@
import React from 'react';
import { tickFormatUSD } from '~/components/Analytics/formatters';
import { LineChartProps } from '~/components/Common/Charts/LineChart';
import SeasonPlot, {
SeasonPlotBaseProps,
} from '~/components/Common/Charts/SeasonPlot';
import React, { useMemo } from 'react';
import {
SeasonalLiquidityDocument,
SeasonalLiquidityQuery,
SeasonalLiquidityPerPoolDocument,
} from '~/generated/graphql';
import useSeason from '~/hooks/beanstalk/useSeason';

import { FC } from '~/types';
import useSeasonsQuery, { SeasonRange } from '~/hooks/beanstalk/useSeasonsQuery';
import { BaseDataPoint, ChartMultiStyles } from '../../Common/Charts/ChartPropProvider';
import useSdk from '~/hooks/sdk';
import useTimeTabState from '~/hooks/app/useTimeTabState';
import BaseSeasonPlot, { QueryData } from '../../Common/Charts/BaseSeasonPlot';
import { BEAN_CRV3_V1_LP, BEAN_LUSD_LP } from '~/constants/tokens';
import { BeanstalkPalette } from '../../App/muiTheme';
import { SeasonPlotBaseProps } from '~/components/Common/Charts/SeasonPlot';

const getValue = (season: SeasonalLiquidityQuery['seasons'][number]) =>
parseFloat(season.liquidityUSD);
const formatValue = (value: number) =>
`$${value.toLocaleString('en-US', { maximumFractionDigits: 0 })}`;
const statProps = {
/// Setup SeasonPlot
const formatValue = (value: number) => (
`$${(value || 0).toLocaleString('en-US', { maximumFractionDigits: 2 })}`
);
const StatProps = {
title: 'Liquidity',
titleTooltip: 'The total USD value of tokens in liquidity pools on the Minting Whitelist at the beginning of every Season. Pre-exploit values include liquidity in pools on the Deposit Whitelist.',
gap: 0.25,
};
const queryConfig = {
variables: { season_gt: 0 },
context: { subgraph: 'bean' },
};
const lineChartProps: Partial<LineChartProps> = {
yTickFormat: tickFormatUSD,
color: 'primary',
sx: { ml: 0 },
};

const Liquidity: FC<{ height?: SeasonPlotBaseProps['height'] }> = ({
height,
const Liquidity: FC<{ height?: SeasonPlotBaseProps['height'] }> = ({
height,
}) => {
//
const sdk = useSdk();
const timeTabParams = useTimeTabState();
const season = useSeason();

const getStatValue = <T extends BaseDataPoint>(v?: T[]) => {
if (!v?.length) return 0;
const dataPoint = v[0];
return dataPoint?.value || 0;
};

const BEAN_LUSD_LP_V1 = BEAN_LUSD_LP[1];
const BEAN_CRV3_V1 = BEAN_CRV3_V1_LP[1];

const poolList = [
sdk.pools.BEAN_CRV3,
sdk.pools.BEAN_ETH_WELL,
sdk.tokens.BEAN_ETH_UNIV2_LP,
BEAN_LUSD_LP_V1,
BEAN_CRV3_V1,
];

const chartStyle: ChartMultiStyles = {
[sdk.pools.BEAN_CRV3.address]: {
stroke: BeanstalkPalette.theme.spring.blue,
fillPrimary: BeanstalkPalette.theme.spring.lightBlue
},
[sdk.pools.BEAN_ETH_WELL.address]: {
stroke: BeanstalkPalette.theme.spring.beanstalkGreen,
fillPrimary: BeanstalkPalette.theme.spring.washedGreen
},
[sdk.tokens.BEAN_ETH_UNIV2_LP.address]: {
stroke: BeanstalkPalette.theme.spring.chart.purple,
fillPrimary: BeanstalkPalette.theme.spring.chart.purpleLight
},
[BEAN_LUSD_LP_V1.address]: {
stroke: BeanstalkPalette.theme.spring.grey,
fillPrimary: BeanstalkPalette.theme.spring.lightishGrey
},
[BEAN_CRV3_V1.address]: {
stroke: BeanstalkPalette.theme.spring.chart.yellow,
fillPrimary: BeanstalkPalette.theme.spring.chart.yellowLight
},
};

// Filters non-relevant tokens from the tooltip on a per-season basis
const seasonFilter = {
[sdk.tokens.BEAN_ETH_UNIV2_LP.address]: { from: 0, to: 6074 },
[BEAN_LUSD_LP_V1.address]: { from: 5502, to: 6074 },
[BEAN_CRV3_V1.address]: { from: 3658, to: 6074 },
[sdk.pools.BEAN_CRV3.address]: { from: 6074, to: Infinity },
[sdk.pools.BEAN_ETH_WELL.address]: { from: 15241, to: Infinity },
};

const queryConfigBeanCrv3 = useMemo(() => ({
variables: { pool: sdk.pools.BEAN_CRV3.address },
context: { subgraph: 'bean' }
}), [sdk.pools.BEAN_CRV3.address]);

const queryConfigBeanEthWell = useMemo(() => ({
variables: { pool: sdk.pools.BEAN_ETH_WELL.address },
context: { subgraph: 'bean' }
}), [sdk.pools.BEAN_ETH_WELL.address]);

const queryConfigBeanEthOld = useMemo(() => ({
variables: { pool: sdk.tokens.BEAN_ETH_UNIV2_LP.address },
context: { subgraph: 'bean' }
}), [sdk.tokens.BEAN_ETH_UNIV2_LP.address]);

const queryConfigBeanLusdOld = useMemo(() => ({
variables: { pool: BEAN_LUSD_LP_V1.address },
context: { subgraph: 'bean' }
}), [BEAN_LUSD_LP_V1.address]);

const queryConfigBeanCrv3Old = useMemo(() => ({
variables: { pool: BEAN_CRV3_V1.address },
context: { subgraph: 'bean' }
}), [BEAN_CRV3_V1.address]);

const beanCrv3 = useSeasonsQuery(SeasonalLiquidityPerPoolDocument, timeTabParams[0][1], queryConfigBeanCrv3);
const beanEthWell = useSeasonsQuery(SeasonalLiquidityPerPoolDocument, timeTabParams[0][1], queryConfigBeanEthWell);
const beanEthOld = useSeasonsQuery(SeasonalLiquidityPerPoolDocument, SeasonRange.ALL, queryConfigBeanEthOld);
const beanLusdOld = useSeasonsQuery(SeasonalLiquidityPerPoolDocument, SeasonRange.ALL, queryConfigBeanLusdOld);
const beanCrv3Old = useSeasonsQuery(SeasonalLiquidityPerPoolDocument, SeasonRange.ALL, queryConfigBeanCrv3Old);

let seasonData
if (timeTabParams[0][1] === SeasonRange.ALL) {
seasonData = [
beanCrv3.data?.seasons,
beanEthWell.data?.seasons,
beanEthOld.data?.seasons,
beanLusdOld.data?.seasons,
beanCrv3Old.data?.seasons
].flat(Infinity);
} else {
seasonData = [
beanCrv3.data?.seasons,
beanEthWell.data?.seasons,
].flat(Infinity);
};

const loading = beanCrv3.loading || beanEthWell.loading || beanEthOld.loading || beanLusdOld.loading || beanCrv3Old.loading;

const processedSeasons: any[] = [];
const defaultDataPoint = {
season: 0,
date: 0,
value: 0,
[sdk.pools.BEAN_CRV3.address]: 0,
[sdk.pools.BEAN_ETH_WELL.address]: 0,
[sdk.tokens.BEAN_ETH_UNIV2_LP.address]: 0,
[BEAN_LUSD_LP_V1.address]: 0,
[BEAN_CRV3_V1.address]: 0,
};

if (season && !loading && seasonData[0] && seasonData[0].season) {
const latestSeason = seasonData[0].season;
seasonData.forEach((dataPoint) => {
const seasonDiff = latestSeason - dataPoint.season;
if (!processedSeasons[seasonDiff]) {
processedSeasons[seasonDiff] = { ...defaultDataPoint };
};
processedSeasons[seasonDiff].season = Number(dataPoint.season);
processedSeasons[seasonDiff].date = new Date(Number(dataPoint.updatedAt) * 1000);
processedSeasons[seasonDiff][dataPoint.id.slice(0, 42)] = Number(dataPoint.liquidityUSD);
processedSeasons[seasonDiff].value += Number(dataPoint.liquidityUSD);
});
};

const queryData: QueryData = {
data: [processedSeasons.filter(Boolean).reverse()],
loading: loading,
keys: poolList.map((pool) => pool.address),
error: undefined,
};

return (
<SeasonPlot
document={SeasonalLiquidityDocument}
<BaseSeasonPlot
queryData={queryData}
height={height}
defaultSeason={season?.gt(0) ? season.toNumber() : 0}
getValue={getValue}
StatProps={StatProps}
timeTabParams={timeTabParams}
formatValue={formatValue}
StatProps={statProps}
LineChartProps={lineChartProps}
queryConfig={queryConfig}
dateKey="timestamp"
stackedArea
ChartProps={{
getDisplayValue: getStatValue,
tooltip: true,
useOldLpTokens: true,
tokenPerSeasonFilter: seasonFilter,
stylesConfig: chartStyle
}}
/>
);
};

export default Liquidity;

1 change: 0 additions & 1 deletion projects/ui/src/components/Forecast/LiquidityOverTime.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import {
SeasonalLiquidityPerPoolDocument,
} from '~/generated/graphql';
import useSeason from '~/hooks/beanstalk/useSeason';

import { FC } from '~/types';
import useSeasonsQuery, { SeasonRange } from '~/hooks/beanstalk/useSeasonsQuery';
import { BaseDataPoint, ChartMultiStyles } from '../Common/Charts/ChartPropProvider';
Expand Down

0 comments on commit 168a8af

Please sign in to comment.