Skip to content

Commit

Permalink
chore(perf): move SupplyStats logic to client side and remove state r…
Browse files Browse the repository at this point in the history
…efresh (#1935)

chore: move SupplyStats logic to client side and remove state refresh
  • Loading branch information
fuxingloh authored Jul 5, 2024
1 parent 55700f7 commit d59a745
Show file tree
Hide file tree
Showing 3 changed files with 86 additions and 111 deletions.
39 changes: 0 additions & 39 deletions src/components/index/StatCard.tsx

This file was deleted.

130 changes: 78 additions & 52 deletions src/components/index/SupplyStats.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,55 +2,49 @@ import { PropsWithChildren, useEffect, useState } from "react";
import { InfoHoverPopover } from "@components/commons/popover/InfoHoverPopover";
import { NumericFormat } from "react-number-format";
import { CollapsibleSection } from "@components/commons/sections/CollapsibleSection";
import { RootState } from "@store/index";
import { StatPriceCard } from "@components/index/StatCard";
import { useSelector } from "react-redux";
import {
StatsData,
SupplyData,
} from "@defichain/whale-api-client/dist/api/stats";
import { StatsState } from "@store/stats";
import { useWhaleApiClient } from "@contexts/WhaleContext";
import { DFI as DfiIcon } from "@components/icons/assets/tokens/DFI";
import { CalculatePercentage } from "../../utils/index/CalculatePercentage";

interface SupplyStatsProps {
stats: StatsData;
supply: SupplyData;
}

interface SupplyStatsStateI {
stats: StatsData | StatsState;
supply: SupplyData;
stats: StatsData | null;
supply: SupplyData | null;
}

export function SupplyStats(props: SupplyStatsProps): JSX.Element {
const statsState = useSelector((state: RootState) => state.stats);
const supplyState = useSelector((state: RootState) => state.supply);
export function SupplyStats(): JSX.Element {
const apiClient = useWhaleApiClient();

const [data, setData] = useState<SupplyStatsStateI>({
stats: props.stats,
supply: props.supply,
stats: null,
supply: null,
});

useEffect(() => {
if (statsState?.price?.usd !== undefined && supplyState?.total !== 0) {
setData({
stats: statsState,
supply: supplyState,
});
}
}, [statsState, supplyState]);
apiClient.stats.get().then((stats) => {
setData((prev) => ({
...prev,
stats,
}));
});

apiClient.stats.getSupply().then((supply) => {
setData((prev) => ({
...prev,
supply,
}));
});
}, []);

return (
<section className="mb-12">
<CollapsibleSection heading="Overview" mdNotCollapsible>
<div className="flex flex-wrap" data-testid="SupplyStats.Desktop">
<div className="w-full lg:w-3/12 mr-2 flex">
<StatPriceCard
usd={data.stats.price.usd}
updatedAt={
"updatedAt" in data.stats ? data.stats.updatedAt : undefined
}
/>
<StatPriceCard usd={data.stats?.price.usd} />
</div>
<div
className="w-full lg:w-9/12 flex flex-wrap -m-1"
Expand All @@ -59,29 +53,29 @@ export function SupplyStats(props: SupplyStatsProps): JSX.Element {
<StatCard
infodesc="Total DFI Minted is the total number of DFI emitted to date."
heading="Total DFI Minted"
stat={data.supply.total}
stat={data.supply?.total}
suffix="/ 1.2B"
testId="StatCard.TotalMinted"
>
<div className="mt-auto text-gray-500 text-sm dark:text-gray-400">
<span className="text-black font-medium mr-1 dark:text-gray-100">
{CalculatePercentage(data.supply.total, data.supply.max)}
{CalculatePercentage(data.supply?.total, data.supply?.max)}
</span>
of max supply
</div>
</StatCard>
<StatCard
infodesc="Circulating DFI is the total number of DFI coins that are publicly available and is circulating in the market."
heading="Circulating DFI"
stat={data.supply.circulating}
stat={data.supply?.circulating}
suffix="DFI"
testId="StatCard.Circulating"
>
<div className="mt-auto text-gray-500 text-sm dark:text-gray-400">
<span className="text-black font-medium mr-1 dark:text-gray-100">
{CalculatePercentage(
data.supply.circulating,
data.supply.total
data.supply?.circulating,
data.supply?.total,
)}
</span>
of total minted
Expand All @@ -90,7 +84,7 @@ export function SupplyStats(props: SupplyStatsProps): JSX.Element {
<StatCard
infodesc="Total Value Locked is the overall value of assets deposited in DeFiChain. This includes assets locked in DEXs, Masternodes, and collaterals in vaults"
heading="Total Value Locked"
stat={data.stats.tvl.total}
stat={data.stats?.tvl.total}
prefix="$"
testId="StatCard.Tvl"
>
Expand All @@ -99,8 +93,8 @@ export function SupplyStats(props: SupplyStatsProps): JSX.Element {
DEX:
<span className="text-black font-medium ml-1 dark:text-gray-100">
{CalculatePercentage(
data.stats.tvl.dex,
data.stats.tvl.total
data.stats?.tvl.dex,
data.stats?.tvl.total,
)}
</span>
</div>
Expand All @@ -109,17 +103,17 @@ export function SupplyStats(props: SupplyStatsProps): JSX.Element {
<span className="xl:hidden">MN:</span>
<span className="text-black font-medium ml-1 dark:text-gray-100">
{CalculatePercentage(
data.stats.tvl.masternodes,
data.stats.tvl.total
data.stats?.tvl.masternodes,
data.stats?.tvl.total,
)}
</span>
</div>
<div className="px-1">
Vaults:
<span className="text-black font-medium ml-1 dark:text-gray-100">
{CalculatePercentage(
data.stats.tvl.loan,
data.stats.tvl.total
data.stats?.tvl.loan,
data.stats?.tvl.total,
)}
</span>
</div>
Expand All @@ -128,12 +122,12 @@ export function SupplyStats(props: SupplyStatsProps): JSX.Element {
<StatCard
infodesc="Total DFI Burned is the total amount of DFI coins removed from circulation."
heading="Total DFI Burned"
stat={data.supply.burned}
stat={data.supply?.burned}
testId="StatCard.TotalBurned"
>
<div className="mt-auto text-gray-500 text-sm dark:text-gray-400">
<span className="text-black mr-1 dark:text-gray-100">
{CalculatePercentage(data.supply.burned, data.supply.total)}
{CalculatePercentage(data.supply?.burned, data.supply?.total)}
</span>
of total minted
</div>
Expand All @@ -153,7 +147,7 @@ function StatCard(
prefix?: string;
suffix?: string;
testId: string;
}>
}>,
): JSX.Element {
return (
<div className="w-full md:w-1/2 p-1" data-testid={props.testId}>
Expand All @@ -165,14 +159,18 @@ function StatCard(
<InfoHoverPopover description={props.infodesc} />
</div>
<div className="flex flex-wrap items-center">
<NumericFormat
value={props.stat}
displayType="text"
thousandSeparator
className="text-lg lg:text-2xl font-semibold dark:text-dark-gray-900"
decimalScale={0}
prefix={props.prefix !== undefined ? props.prefix : ""}
/>
{props.stat !== undefined ? (
<NumericFormat
value={props.stat}
displayType="text"
thousandSeparator
className="text-lg lg:text-2xl font-semibold dark:text-dark-gray-900"
decimalScale={0}
prefix={props.prefix !== undefined ? props.prefix : ""}
/>
) : (
"..."
)}
{props.suffix !== undefined && (
<span className="ml-1 dark:text-gray-400">{props.suffix}</span>
)}
Expand All @@ -182,3 +180,31 @@ function StatCard(
</div>
);
}

function StatPriceCard(props: { usd: number | undefined }): JSX.Element {
return (
<div
className="rounded-lg border border-gray-200 dark:bg-gray-800 dark:border-gray-700 p-5 lg:p-8 flex flex-col flex-1 mb-2 lg:mb-0"
data-testid="StatPriceCard"
>
<div className="space-y-1.5 md:space-y-2.5">
<div className="flex items-center">
<DfiIcon className="text-2xl md:text-3xl" />
<div className="ml-2 dark:text-gray-400">$DFI Price</div>
</div>
<div
data-testid="StatPriceCard.Price"
className="font-semibold text-2xl md:text-4xl lg:text-5xl dark:text-dark-gray-900"
>
<NumericFormat
displayType="text"
thousandSeparator
value={props.usd}
decimalScale={2}
prefix="$"
/>
</div>
</div>
</div>
);
}
28 changes: 8 additions & 20 deletions src/pages/index.page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,9 @@ import { BlocksList } from "@components/index/BlocksList";
import { TransactionsList } from "@components/index/TransactionsList";
import { useEffect, useState } from "react";
import { SupplyStats } from "@components/index/SupplyStats";
import {
StatsData,
SupplyData,
} from "@defichain/whale-api-client/dist/api/stats";

interface HomePageProps {
blocks: Block[];
stats: StatsData;
supply: SupplyData;
transactions: Transaction[];
liquidityPools: PoolPairData[];
}
Expand All @@ -34,7 +28,7 @@ interface HomePageStateI {
}

export default function HomePage(
props: InferGetServerSidePropsType<typeof getServerSideProps>
props: InferGetServerSidePropsType<typeof getServerSideProps>,
): JSX.Element {
const api = useWhaleApiClient();
const [data, setData] = useState<HomePageStateI>({
Expand All @@ -58,8 +52,8 @@ export default function HomePage(
async (block) =>
await api.blocks.getTransactions(block.id, 8).then((results) => {
return results;
})
)
}),
),
).then((results) => {
results.map((result) => transactions.push(...result));
});
Expand All @@ -78,7 +72,7 @@ export default function HomePage(
<>
<IndexHeader />
<Container className="pb-20 relative z-1">
<SupplyStats stats={props.stats} supply={props.supply} />
<SupplyStats />
<div className="flex flex-wrap -mx-2">
<div className="w-full lg:w-3/5 xl:w-2/3 px-1">
<TransactionsList transactions={data.transactions} />
Expand All @@ -94,24 +88,20 @@ export default function HomePage(
}

export async function getServerSideProps(
context: GetServerSidePropsContext
context: GetServerSidePropsContext,
): Promise<GetServerSidePropsResult<HomePageProps>> {
const api = getWhaleApiClient(context);

const [blocks, supply, stats] = await Promise.all([
api.blocks.list(8),
api.stats.getSupply(),
api.stats.get(),
]);
const blocks = await api.blocks.list(8);

let transactions: Transaction[] = [];
await Promise.all(
blocks.map(
async (block) =>
await api.blocks.getTransactions(block.id, 8).then((results) => {
return results;
})
)
}),
),
).then((results) => {
results.map((result) => transactions.push(...result));
});
Expand All @@ -122,8 +112,6 @@ export async function getServerSideProps(
return {
props: {
blocks,
stats,
supply,
transactions,
liquidityPools,
},
Expand Down

0 comments on commit d59a745

Please sign in to comment.