Skip to content

Commit

Permalink
feat: XYK pool timeseries (#46)
Browse files Browse the repository at this point in the history
  • Loading branch information
nguyenlejoe authored Jan 16, 2024
1 parent d4846e1 commit be36171
Show file tree
Hide file tree
Showing 4 changed files with 183 additions and 1 deletion.
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { type Meta, type StoryObj } from "@storybook/react";
import { XYKPoolTimeSeriesView } from "./XYKPoolTimeSeriesView";

type Story = StoryObj<typeof XYKPoolTimeSeriesView>;

const meta: Meta<typeof XYKPoolTimeSeriesView> = {
title: "Molecules/XYK",
component: XYKPoolTimeSeriesView,
};

export default meta;

export const XYKPoolTimeSeries: Story = {
args: {
chain_name: "eth-mainnet",
dex_name: "uniswap_v2",
pool_address: "0x02af166a28393809f55bb5befbcc27ec15908241",
},
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
import { type Option, None, Some } from "@/utils/option";
import { useEffect, useState } from "react";
import { Button } from "@/components/ui/button";
import { BarChart } from "@tremor/react";
import { rootColor, timestampParser } from "@/utils/functions";
import { TypographyH4 } from "@/components/ui/typography";
import { Skeleton } from "@/components/ui/skeleton";
import { GRK_SIZES, PERIOD } from "@/utils/constants/shared.constants";
import { CHART_COLORS } from "@/utils/constants/shared.constants";
import { useCovalent } from "@/utils/store/Covalent";
import { type XYKPoolTimeSeriesViewProps } from "@/utils/types/molecules.types";
import { prettifyCurrency } from "@covalenthq/client-sdk";
import { capitalizeFirstLetter } from "@/utils/functions/capitalize";

export const XYKPoolTimeSeriesView: React.FC<XYKPoolTimeSeriesViewProps> = ({
chain_name,
dex_name,
pool_address,
pool_data,
}) => {
const [maybeResult, setResult] = useState<Option<any>>(None);
const [chartData, setChartData] = useState<Option<any>>(None);
const [period, setPeriod] = useState<PERIOD>(PERIOD.DAYS_7);
const [timeSeries, setTimeSerious] = useState<string>("liquidity");
const [chartColor, setColor] = useState<any>("");
const { covalentClient } = useCovalent();

const handleChartData = () => {
maybeResult.match({
None: () => null,
Some: (response) => {
const chart_key = `${timeSeries}_timeseries_${period}d`;
const value_key =
timeSeries === "price"
? "price_of_token0_in_token1"
: `${timeSeries}_quote`;

const result = response[chart_key].map((x: any) => {
const dt = timestampParser(x.dt, "DD MMM YY");
return {
date: dt,
[`${capitalizeFirstLetter(timeSeries)} (USD)`]:
x[value_key],
};
});
setChartData(new Some(result));
},
});
};

useEffect(() => {
(async () => {
setResult(None);
const response = await covalentClient.XykService.getPoolByAddress(
chain_name,
dex_name,
pool_address
);
setColor(rootColor());
setResult(new Some(response.data.items[0]));
})();
}, [pool_data, dex_name, chain_name]);

useEffect(() => {
handleChartData();
}, [maybeResult, period, timeSeries]);

const body = chartData.match({
None: () => {
return (
<div className="mt-8">
<Skeleton size={GRK_SIZES.LARGE} />
</div>
);
},
Some: (result) => {
return (
<div>
<BarChart
className="mt-2 p-2"
data={result}
index="date"
valueFormatter={prettifyCurrency}
categories={[
`${capitalizeFirstLetter(timeSeries)} (USD)`,
]}
colors={chartColor ? [chartColor] : CHART_COLORS}
/>
</div>
);
},
});

return (
<div className="min-h-[20rem] w-full rounded border p-4">
<div className="pb-4">
<TypographyH4>{`${capitalizeFirstLetter(
timeSeries
)} (USD)`}</TypographyH4>
</div>

<div className="flex justify-between">
<div className="flex gap-2">
<Button
disabled={!maybeResult.isDefined}
variant={
timeSeries === "liquidity" ? "accent" : "outline"
}
onClick={() => setTimeSerious("liquidity")}
>
Liquidity
</Button>
<Button
disabled={!maybeResult.isDefined}
variant={timeSeries === "volume" ? "accent" : "outline"}
onClick={() => setTimeSerious("volume")}
>
Volume
</Button>
{/* <Button
disabled={!maybeResult.isDefined}
variant={timeSeries === "price" ? "accent" : "outline"}
onClick={() => setTimeSerious("price")}
>
Price
</Button> */}
</div>
<div className="flex gap-2">
<Button
disabled={!maybeResult.isDefined}
variant={
period === PERIOD.DAYS_7 ? "accent" : "outline"
}
onClick={() => setPeriod(PERIOD.DAYS_7)}
>
7 days
</Button>
<Button
disabled={!maybeResult.isDefined}
variant={
period === PERIOD.DAYS_30 ? "accent" : "outline"
}
onClick={() => setPeriod(PERIOD.DAYS_30)}
>
30 days
</Button>
</div>
</div>

{body}
</div>
);
};
3 changes: 3 additions & 0 deletions src/utils/functions/capitalize.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export function capitalizeFirstLetter(str: string) {
return str.charAt(0).toUpperCase() + str.slice(1);
}
9 changes: 8 additions & 1 deletion src/utils/types/molecules.types.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { type Chain } from "@covalenthq/client-sdk";
import { type Chain, type PoolWithTimeseries } from "@covalenthq/client-sdk";

export interface AccountCardViewProps {
name?: string;
Expand All @@ -23,6 +23,13 @@ export interface NFTSalesCountViewProps {
token_id?: string;
}

export interface XYKPoolTimeSeriesViewProps {
chain_name: Chain;
dex_name: string;
pool_address: string;
pool_data?: PoolWithTimeseries;
}

export interface NFTVolumeViewProps {
chain_name: Chain;
collection_address: string;
Expand Down

0 comments on commit be36171

Please sign in to comment.