Skip to content

Commit

Permalink
fix chart not working due to duplicate keys
Browse files Browse the repository at this point in the history
  • Loading branch information
Space-Bean committed Dec 2, 2023
1 parent 65ff5f3 commit 8a8ca26
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 26 deletions.
85 changes: 66 additions & 19 deletions projects/dex-ui/src/components/Well/Chart/ChartSection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,67 @@ import { ChartContainer } from "./ChartStyles";
import { BottomDrawer } from "src/components/BottomDrawer";
import { mediaQuery, size } from "src/breakpoints";
import { LoadingTemplate } from "src/components/LoadingTemplate";
import { IWellHourlySnapshot } from "src/wells/chartDataLoader";
import { TokenValue } from "@beanstalk/sdk";

function timeToLocal(originalTime: number) {
const d = new Date(originalTime * 1000);
return Date.UTC(d.getFullYear(), d.getMonth(), d.getDate(), d.getHours(), d.getMinutes(), d.getSeconds(), d.getMilliseconds()) / 1000;
}

type TimeToHourlySnapshotItem = {
data: Pick<IWellHourlySnapshot, "deltaVolumeUSD" | "totalLiquidityUSD">;
count: number;
};

export type IChartDataItem = {
time: number;
value: string;
};

// some snapshots are duplicated, so we need to deduplicate them
const parseAndDeduplicateSnapshots = (arr: IWellHourlySnapshot[]) => {
const snapshotMap = arr.reduce<Record<string, TimeToHourlySnapshotItem>>((memo, snapshot) => {
const timeKey = timeToLocal(Number(snapshot.lastUpdateTimestamp)).toString();
const deltaVolumeUSD = Number(snapshot.deltaVolumeUSD);
const totalLiquidityUSD = Number(snapshot.totalLiquidityUSD);

if (!(timeKey in memo)) {
memo[timeKey] = {
data: { deltaVolumeUSD, totalLiquidityUSD },
count: 1
};
} else {
memo[timeKey].data.deltaVolumeUSD += deltaVolumeUSD;
memo[timeKey].data.totalLiquidityUSD += totalLiquidityUSD;
memo[timeKey].count++;
}

return memo;
}, {});

const liquidityData: IChartDataItem[] = [];
const volumeData: IChartDataItem[] = [];

for (const [time, { data, count }] of Object.entries(snapshotMap)) {
const timeKey = Number(time);

liquidityData.push({
time: timeKey,
value: Number(TokenValue.ZERO.add(data.totalLiquidityUSD).div(count).toHuman()).toFixed(2)
});
volumeData.push({
time: timeKey,
value: Number(TokenValue.ZERO.add(data.deltaVolumeUSD).div(count).toHuman()).toFixed(2)
});
}

return {
liquidityData,
volumeData
};
};

const ChartSectionContent: FC<{ well: Well }> = ({ well }) => {
const [tab, setTab] = useState(0);
const [showDropdown, setShowDropdown] = useState(false);
Expand All @@ -25,28 +80,17 @@ const ChartSectionContent: FC<{ well: Well }> = ({ well }) => {

const { data: chartData, refetch, error, isLoading: chartDataLoading } = useWellChartData(well, timePeriod);

const [liquidityData, setLiquidityData] = useState<any[]>([]);
const [volumeData, setVolumeData] = useState<any[]>([]);
const [liquidityData, setLiquidityData] = useState<IChartDataItem[]>([]);
const [volumeData, setVolumeData] = useState<IChartDataItem[]>([]);

const [isChartTypeDrawerOpen, setChartTypeDrawerOpen] = useState(false);
const [isChartRangeDrawerOpen, setChartRangeDrawerOpen] = useState(false);

useEffect(() => {
if (!chartData) return;
let _liquidityData: any = [];
let _volumeData: any = [];
for (let i = 0; i < chartData.length; i++) {
_liquidityData.push({
time: timeToLocal(Number(chartData[i].lastUpdateTimestamp)),
value: Number(chartData[i].totalLiquidityUSD).toFixed(2)
});
_volumeData.push({
time: timeToLocal(Number(chartData[i].lastUpdateTimestamp)),
value: Number(chartData[i].deltaVolumeUSD).toFixed(2)
});
}
setLiquidityData([..._liquidityData]);
setVolumeData([..._volumeData]);
const dedupliated = parseAndDeduplicateSnapshots(chartData);
setLiquidityData(dedupliated.liquidityData);
setVolumeData(dedupliated.volumeData);
}, [chartData]);

useEffect(() => {
Expand Down Expand Up @@ -182,16 +226,19 @@ const ChartSectionContent: FC<{ well: Well }> = ({ well }) => {
</BottomDrawer>
</MobileRow>
{error !== null && <ChartError>{`Error Loading Chart Data :(`}</ChartError>}
{chartDataLoading && (
{chartDataLoading ? (
<ChartLoader>
<LoadingTemplate gap={4}>
<LoadingTemplate.Item width={100} height={24} />
<LoadingTemplate.Item width={150} height={24} />
</LoadingTemplate>
</ChartLoader>
) : (
<>
{tab === 0 && !error && <Chart data={liquidityData} legend={"TOTAL LIQUIDITY"} />}
{tab === 1 && !error && <Chart data={volumeData} legend={"HOURLY VOLUME"} />}
</>
)}
{tab === 0 && !error && !chartDataLoading && <Chart data={liquidityData} legend={"TOTAL LIQUIDITY"} />}
{tab === 1 && !error && !chartDataLoading && <Chart data={volumeData} legend={"HOURLY VOLUME"} />}
</Container>
);
};
Expand Down
11 changes: 6 additions & 5 deletions projects/dex-ui/src/wells/chartDataLoader.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import { BeanstalkSDK } from "@beanstalk/sdk";
import { fetchFromSubgraphRequest } from "./subgraphFetch";
import { Well } from "@beanstalk/sdk/Wells";
import { GetWellChartDataDocument } from "src/generated/graph/graphql";
import { GetWellChartDataDocument, GetWellChartDataQuery } from "src/generated/graph/graphql";
import { Log } from "src/utils/logger";

const loadFromGraph = async (sdk: BeanstalkSDK, well: Well, timePeriod: string) => {
export type IWellHourlySnapshot = NonNullable<GetWellChartDataQuery["well"]>["hourlySnapshots"][number];

const loadFromGraph = async (sdk: BeanstalkSDK, well: Well, timePeriod: string): Promise<IWellHourlySnapshot[]> => {
if (!well) return [];

Log.module("wellChartData").debug("Loading chart data from Graph");
Expand All @@ -13,7 +15,7 @@ const loadFromGraph = async (sdk: BeanstalkSDK, well: Well, timePeriod: string)
const HISTORY_DAYS_AGO_BLOCK_TIMESTAMP =
HISTORY_DAYS === 0 ? 0 : Math.floor(new Date(Date.now() - HISTORY_DAYS * 24 * 60 * 60 * 1000).getTime() / 1000);

let results: any[] = [];
let results: IWellHourlySnapshot[] = [];
let goToNextPage: boolean = false;
let nextPage: number = 0;
let skipAmount: number = 0;
Expand All @@ -39,8 +41,7 @@ const loadFromGraph = async (sdk: BeanstalkSDK, well: Well, timePeriod: string)
} else {
goToNextPage = false;
}
}

}
while (goToNextPage === true);

return results;
Expand Down
4 changes: 2 additions & 2 deletions projects/dex-ui/src/wells/useWellChartData.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import { useQuery } from "@tanstack/react-query";

import useSdk from "src/utils/sdk/useSdk";
import { loadChartData } from "./chartDataLoader";
import { IWellHourlySnapshot, loadChartData } from "./chartDataLoader";
import { Well } from "@beanstalk/sdk/Wells";

const useWellChartData = (well: Well, timePeriod: string) => {
const sdk = useSdk();

return useQuery(
return useQuery<IWellHourlySnapshot[]>(
["wells", "wellChartData", well.address],
async () => {
const data = await loadChartData(sdk, well, timePeriod);
Expand Down

0 comments on commit 8a8ca26

Please sign in to comment.