Skip to content

Commit

Permalink
feat: XYK pool detail view (#50)
Browse files Browse the repository at this point in the history
  • Loading branch information
nguyenlejoe authored Jan 16, 2024
1 parent 8c4e281 commit 74d27bc
Show file tree
Hide file tree
Showing 4 changed files with 265 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,10 @@ 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 {
prettifyCurrency,
type PoolWithTimeseries,
} from "@covalenthq/client-sdk";
import { capitalizeFirstLetter } from "@/utils/functions/capitalize";

export const XYKPoolTimeSeriesView: React.FC<XYKPoolTimeSeriesViewProps> = ({
Expand All @@ -18,7 +21,7 @@ export const XYKPoolTimeSeriesView: React.FC<XYKPoolTimeSeriesViewProps> = ({
pool_address,
pool_data,
}) => {
const [maybeResult, setResult] = useState<Option<any>>(None);
const [maybeResult, setResult] = useState<Option<PoolWithTimeseries>>(None);
const [chartData, setChartData] = useState<Option<any>>(None);
const [period, setPeriod] = useState<PERIOD>(PERIOD.DAYS_7);
const [timeSeries, setTimeSerious] = useState<string>("liquidity");
Expand All @@ -28,7 +31,7 @@ export const XYKPoolTimeSeriesView: React.FC<XYKPoolTimeSeriesViewProps> = ({
const handleChartData = () => {
maybeResult.match({
None: () => null,
Some: (response) => {
Some: (response: any) => {
const chart_key = `${timeSeries}_timeseries_${period}d`;
const value_key =
timeSeries === "price"
Expand All @@ -49,17 +52,21 @@ export const XYKPoolTimeSeriesView: React.FC<XYKPoolTimeSeriesViewProps> = ({
};

useEffect(() => {
setColor(rootColor());
if (pool_data) {
setResult(new Some(pool_data));
return;
}
(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]);
}, [pool_data, dex_name, pool_address, chain_name]);

useEffect(() => {
handleChartData();
Expand All @@ -81,6 +88,7 @@ export const XYKPoolTimeSeriesView: React.FC<XYKPoolTimeSeriesViewProps> = ({
data={result}
index="date"
valueFormatter={prettifyCurrency}
yAxisWidth={100}
categories={[
`${capitalizeFirstLetter(timeSeries)} (USD)`,
]}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { type Meta, type StoryObj } from "@storybook/react";
import { XYKPoolDetailView } from "./XYKPoolDetailView";

type Story = StoryObj<typeof XYKPoolDetailView>;

const meta: Meta<typeof XYKPoolDetailView> = {
title: "Organisms/XYK/Pool",
component: XYKPoolDetailView,
};

export default meta;

export const XYKPoolDetail: Story = {
args: {
chain_name: "eth-mainnet",
dex_name: "uniswap_v2",
pool_address: "0x21b8065d10f73ee2e260e5b47d3344d3ced7596e",
},
};
227 changes: 227 additions & 0 deletions src/components/Organisms/XYK/XYKPoolDetailView/XYKPoolDetailView.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,227 @@
import { TypographyH1 } from "@/components/ui/typography";
import { useCovalent } from "@/utils/store/Covalent";
import { type Option, Some, None } from "@/utils/option";
import { type XYKPoolDetailViewProps } from "@/utils/types/organisms.types";
import { useEffect, useState } from "react";
import { Skeleton } from "@/components/ui/skeleton";
import { GRK_SIZES } from "@/utils/constants/shared.constants";
import { XYKPoolTimeSeriesView } from "@/components/Molecules/XYK/XYKPoolTimeSeriesView/XYKPoolTimeSeriesView";
import { TokenAvatar } from "@/components/Atoms/TokenAvatar/TokenAvatar";
import { prettyToken } from "@/utils/functions/pretty-token";

export const XYKPoolDetailView: React.FC<XYKPoolDetailViewProps> = ({
chain_name,
dex_name,
pool_address,
}) => {
const [maybeResult, setResult] = useState<Option<any>>(None);
const [error, setError] = useState({ error: false, error_message: "" });
const { covalentClient } = useCovalent();

useEffect(() => {
(async () => {
let response;
setResult(None);
try {
response = await covalentClient.XykService.getPoolByAddress(
chain_name,
dex_name,
pool_address
);
setResult(new Some(response.data.items[0]));
} catch (error) {
setError({
error: response ? response.error : false,
error_message: response ? response.error_message : "",
});
}
})();
}, [chain_name, dex_name]);

if (error.error) {
return <>{error.error_message}</>;
}

return (
<div className="w-full">
<div className="flex items-center gap-4">
{maybeResult.match({
None: () => (
<div className="relative mr-2 flex">
<div className="h-20 w-20 animate-pulse rounded-[100%] bg-slate-600" />
<div className="absolute left-12 h-20 w-20 animate-pulse rounded-[100%] bg-slate-200" />
</div>
),
Some: (result) => (
<div className="relative mr-2 flex">
<TokenAvatar
size={GRK_SIZES.MEDIUM}
token_url={result.token_0.logo_url}
/>
<div className="absolute left-12">
<TokenAvatar
size={GRK_SIZES.MEDIUM}
token_url={result.token_1.logo_url}
/>
</div>
</div>
),
})}{" "}
{maybeResult.match({
None: () => (
<div className="ml-8 flex items-center gap-4">
<Skeleton size={GRK_SIZES.LARGE} /> -
<Skeleton size={GRK_SIZES.LARGE} />
</div>
),
Some: (result) => (
<TypographyH1>
<span className="ml-8">
{" "}
{result.token_0.contract_ticker_symbol}-
{result.token_1.contract_ticker_symbol}{" "}
</span>
Pair
</TypographyH1>
),
})}{" "}
</div>

<div className="mt-4 flex flex-col gap-4 md:flex-row">
<div className="flex min-w-[20rem] max-w-[70rem] flex-col gap-2 rounded">
<div className="flex w-full flex-grow flex-col justify-center gap-2 rounded border p-4">
<h2 className="text-md text-secondary">
Total Liquidity
</h2>
<div className="flex items-end gap-2">
<span className="text-xl">
{maybeResult.match({
None: () => (
<Skeleton size={GRK_SIZES.MEDIUM} />
),
Some: (result) => {
return (
<span>
{
result.pretty_total_liquidity_quote
}
</span>
);
},
})}
</span>
</div>
</div>
<div className="flex w-full flex-grow flex-col justify-center gap-2 rounded border p-4">
<h2 className="text-md text-secondary">
Volume (24hrs)
</h2>
<div className="flex items-end gap-2">
<span className="text-xl">
{maybeResult.match({
None: () => (
<Skeleton size={GRK_SIZES.MEDIUM} />
),
Some: (result) => {
return (
<span>
{result.pretty_volume_24h_quote}
</span>
);
},
})}
</span>
</div>
</div>
<div className="flex w-full flex-grow flex-col justify-center gap-2 rounded border p-4">
<h2 className="text-md text-secondary">Fee (24hrs)</h2>
<div className="flex items-end gap-2">
<span className="text-xl">
{maybeResult.match({
None: () => (
<Skeleton size={GRK_SIZES.MEDIUM} />
),
Some: (result) => {
return (
<span>
{result.pretty_fee_24h_quote}
</span>
);
},
})}
</span>
</div>
</div>
<div className="flex w-full flex-grow flex-col justify-center gap-2 rounded border p-4">
<h2 className="text-md text-secondary">
Pooled Tokens
</h2>
<div className="flex items-end gap-2">
<span className="text-xl">
{maybeResult.match({
None: () => (
<Skeleton size={GRK_SIZES.MEDIUM} />
),
Some: (result) => {
const token_0 = result.token_0;
const token_1 = result.token_1;

return (
<div className="flex flex-col gap-2">
<div className="flex items-center gap-2">
<TokenAvatar
size={
GRK_SIZES.EXTRA_SMALL
}
token_url={
token_0.logo_url
}
/>
{`${prettyToken(
token_0.reserve,
token_0.contract_decimals
)} ${
token_0.contract_ticker_symbol
}`}
</div>
<div className="flex items-center gap-2">
<TokenAvatar
size={
GRK_SIZES.EXTRA_SMALL
}
token_url={
token_1.logo_url
}
/>
{`${prettyToken(
token_1.reserve,
token_1.contract_decimals
)} ${
token_1.contract_ticker_symbol
}`}
</div>
</div>
);
},
})}
</span>
</div>
</div>
</div>
<div className=" flex w-full flex-col gap-4">
<div className="">
<XYKPoolTimeSeriesView
pool_data={maybeResult.match({
None: () => null,
Some: (pool_data) => pool_data,
})}
chain_name={chain_name}
dex_name={dex_name}
pool_address={pool_address}
/>
</div>
</div>
</div>
</div>
);
};
6 changes: 6 additions & 0 deletions src/utils/types/organisms.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,12 @@ export interface NFTDetailViewProps {
token_id: string;
}

export interface XYKPoolDetailViewProps {
chain_name: Chain;
dex_name: string;
pool_address: string;
}

export interface NFTWalletCollectionViewProps {
chain_name: Chain;
address: string;
Expand Down

0 comments on commit 74d27bc

Please sign in to comment.