From b51a87e09a568a7e0fb3f69708a8cd9805f302f3 Mon Sep 17 00:00:00 2001 From: chaojun Date: Thu, 22 Oct 2026 14:59:05 +0800 Subject: [PATCH 1/3] Add dotUSD holders and issuance chart --- .../components/dotusd/dailyStatChart.jsx | 149 ++++++++++++++++++ .../components/dotusd/dailyStats.jsx | 50 ++++++ .../next-common/components/dotusd/index.jsx | 16 ++ .../components/dotusd/useDailyStats.js | 51 ++++++ 4 files changed, 266 insertions(+) create mode 100644 packages/next-common/components/dotusd/dailyStatChart.jsx create mode 100644 packages/next-common/components/dotusd/dailyStats.jsx create mode 100644 packages/next-common/components/dotusd/useDailyStats.js diff --git a/packages/next-common/components/dotusd/dailyStatChart.jsx b/packages/next-common/components/dotusd/dailyStatChart.jsx new file mode 100644 index 0000000000..c372157b04 --- /dev/null +++ b/packages/next-common/components/dotusd/dailyStatChart.jsx @@ -0,0 +1,149 @@ +import dayjs from "dayjs"; +import utc from "dayjs/plugin/utc"; +import { Line } from "react-chartjs-2"; +import "next-common/components/charts/globalConfig"; +import hoverLinePlugin from "next-common/components/charts/plugins/hoverLine"; +import { SecondaryCard } from "next-common/components/styled/containers/secondaryCard"; +import Loading from "next-common/components/loading"; +import NoData from "next-common/components/noData"; +import { useThemeSetting } from "next-common/context/theme"; + +dayjs.extend(utc); + +const chartHeight = 240; + +function buildChartData(points, color, valueOf) { + return { + labels: points.map(({ date }) => dayjs.utc(date).format("MMM D")), + datasets: [ + { + data: points.map(valueOf), + borderColor: color, + backgroundColor: color, + borderWidth: 2, + pointRadius: 2, + pointHoverRadius: 4, + pointBackgroundColor: color, + tension: 0.2, + }, + ], + }; +} + +function buildChartOptions( + points, + { textTertiary, neutral100, neutral300, neutral400, tooltipBg }, + { formatTick, formatTooltip, ticksPrecision }, +) { + return { + responsive: true, + maintainAspectRatio: false, + animation: false, + interaction: { mode: "index", intersect: false }, + scales: { + x: { + border: { display: false }, + grid: { display: false }, + ticks: { color: textTertiary, maxRotation: 0, autoSkip: false }, + }, + y: { + border: { display: false }, + grid: { color: neutral300, drawTicks: false }, + ticks: { + color: textTertiary, + maxTicksLimit: 5, + precision: ticksPrecision, + callback: formatTick, + }, + }, + }, + plugins: { + legend: { display: false }, + hoverLine: { lineColor: neutral400, lineWidth: 1 }, + tooltip: { + displayColors: false, + backgroundColor: tooltipBg, + titleColor: neutral100, + bodyColor: neutral100, + callbacks: { + title: ([{ dataIndex }]) => + dayjs.utc(points[dataIndex].date).format("MMM D, YYYY"), + label: ({ parsed }) => formatTooltip(parsed.y), + }, + }, + }, + }; +} + +function ChartContent({ + points, + colorKey, + valueOf, + renderValue, + formatTick, + formatTooltip, + ticksPrecision, + subtitle, + ariaLabel, +}) { + const theme = useThemeSetting(); + const color = theme[colorKey]; + const latest = points[points.length - 1]; + + return ( + <> +
+
{renderValue(latest)}
+
{subtitle}
+
+
+ +
+ + ); +} + +/** + * The card of one daily dotUSD metric: the latest value, its description and the line of the + * snapshots of the last days. The points are the daily documents served by the backend. + */ +export default function DailyStatChart({ + points, + isLoading, + emptyText, + ...rest +}) { + if (isLoading) { + return ( + +
+ +
+
+ ); + } + + if (!points.length) { + return ( + + + + ); + } + + return ( + + + + ); +} diff --git a/packages/next-common/components/dotusd/dailyStats.jsx b/packages/next-common/components/dotusd/dailyStats.jsx new file mode 100644 index 0000000000..70915108ec --- /dev/null +++ b/packages/next-common/components/dotusd/dailyStats.jsx @@ -0,0 +1,50 @@ +import { toPrecision, toPrecisionNumber } from "next-common/utils"; +import { abbreviateBigNumber } from "next-common/utils/viewfuncs"; +import ValueDisplay from "next-common/components/valueDisplay"; +import DailyStatChart from "./dailyStatChart"; +import { dailyStatsDays } from "./useDailyStats"; + +// dotUSD is an Asset Hub asset with six decimals. +const DOT_USD_DECIMALS = 6; + +export function DotUsdHolderStats({ items, isLoading }) { + return ( + holderCount} + renderValue={({ holderCount }) => holderCount} + formatTick={(value) => value} + ticksPrecision={0} + formatTooltip={(value) => `${value} accounts`} + subtitle={`Accounts holding the asset · last ${dailyStatsDays} days`} + ariaLabel={`dotUSD holders of the last ${dailyStatsDays} days`} + emptyText="No holder data available." + /> + ); +} + +export function DotUsdIssuanceStats({ items, isLoading }) { + return ( + + toPrecisionNumber(totalIssuance, DOT_USD_DECIMALS) + } + renderValue={({ totalIssuance }) => ( + + )} + formatTick={(value) => abbreviateBigNumber(value, 2)} + formatTooltip={(value) => `${abbreviateBigNumber(value, 2)} dotUSD`} + subtitle={`Total issued dotUSD · last ${dailyStatsDays} days`} + ariaLabel={`dotUSD total issuance of the last ${dailyStatsDays} days`} + emptyText="No issuance data available." + /> + ); +} diff --git a/packages/next-common/components/dotusd/index.jsx b/packages/next-common/components/dotusd/index.jsx index d0fd0c14c2..410eb4d42c 100644 --- a/packages/next-common/components/dotusd/index.jsx +++ b/packages/next-common/components/dotusd/index.jsx @@ -5,10 +5,15 @@ import DotUsdInstance from "./instance"; import DotUsdExternalAssets from "./externalAssets"; import DotUsdPool from "./pool"; import DotUsdHolders from "./holders"; +import { DotUsdHolderStats, DotUsdIssuanceStats } from "./dailyStats"; +import useDailyStats from "./useDailyStats"; import DotUsdMintRecords from "./mintRecords"; import DotUsdRedeemRecords from "./redeemRecords"; function DotUsdOverview() { + // Both charts come from the same daily snapshots, so they share one request. + const dailyStats = useDailyStats(); + return (
+
+ +
+ +
+ +
+
{ + let isMounted = true; + // Keep the previous points on screen while the next response loads. + setState((previous) => ({ ...previous, isLoading: true })); + + nextApi + .fetch("dotusd/daily-stats", { days }) + .then(({ result, error }) => { + if (!isMounted) { + return; + } + + if (error) { + console.error("Failed to fetch dotUSD daily stats", error); + setState({ items: [], isLoading: false }); + return; + } + + setState({ + items: Array.isArray(result) ? result : [], + isLoading: false, + }); + }) + .catch((error) => { + console.error("Failed to fetch dotUSD daily stats", error); + + if (isMounted) { + setState({ items: [], isLoading: false }); + } + }); + + return () => { + isMounted = false; + }; + }, [days]); + + return state; +} From 9be2f4e7d34d69b09f221af8f93f9447cacceb8f Mon Sep 17 00:00:00 2001 From: chaojun Date: Thu, 22 Oct 2026 15:14:54 +0800 Subject: [PATCH 2/3] refactor --- .../components/dotusd/dailyStatChart.jsx | 5 +++-- .../components/dotusd/dailyStats.jsx | 19 ++++++++++++------- .../next-common/components/dotusd/index.jsx | 8 ++------ .../components/dotusd/useDailyStats.js | 19 +++++++++---------- .../components/dotusd/useHolderStats.js | 7 +++++++ .../components/dotusd/useIssuanceStats.js | 6 ++++++ 6 files changed, 39 insertions(+), 25 deletions(-) create mode 100644 packages/next-common/components/dotusd/useHolderStats.js create mode 100644 packages/next-common/components/dotusd/useIssuanceStats.js diff --git a/packages/next-common/components/dotusd/dailyStatChart.jsx b/packages/next-common/components/dotusd/dailyStatChart.jsx index c372157b04..1781622701 100644 --- a/packages/next-common/components/dotusd/dailyStatChart.jsx +++ b/packages/next-common/components/dotusd/dailyStatChart.jsx @@ -21,7 +21,8 @@ function buildChartData(points, color, valueOf) { borderColor: color, backgroundColor: color, borderWidth: 2, - pointRadius: 2, + // A long series would otherwise be covered by its own points. + pointRadius: points.length > 31 ? 0 : 2, pointHoverRadius: 4, pointBackgroundColor: color, tension: 0.2, @@ -44,7 +45,7 @@ function buildChartOptions( x: { border: { display: false }, grid: { display: false }, - ticks: { color: textTertiary, maxRotation: 0, autoSkip: false }, + ticks: { color: textTertiary, maxRotation: 0, maxTicksLimit: 7 }, }, y: { border: { display: false }, diff --git a/packages/next-common/components/dotusd/dailyStats.jsx b/packages/next-common/components/dotusd/dailyStats.jsx index 70915108ec..c2c62c15f8 100644 --- a/packages/next-common/components/dotusd/dailyStats.jsx +++ b/packages/next-common/components/dotusd/dailyStats.jsx @@ -2,12 +2,15 @@ import { toPrecision, toPrecisionNumber } from "next-common/utils"; import { abbreviateBigNumber } from "next-common/utils/viewfuncs"; import ValueDisplay from "next-common/components/valueDisplay"; import DailyStatChart from "./dailyStatChart"; -import { dailyStatsDays } from "./useDailyStats"; +import useHolderStats, { holderStatsDays } from "./useHolderStats"; +import useIssuanceStats from "./useIssuanceStats"; // dotUSD is an Asset Hub asset with six decimals. const DOT_USD_DECIMALS = 6; -export function DotUsdHolderStats({ items, isLoading }) { +export function DotUsdHolderStats() { + const { items, isLoading } = useHolderStats(); + return ( value} ticksPrecision={0} formatTooltip={(value) => `${value} accounts`} - subtitle={`Accounts holding the asset · last ${dailyStatsDays} days`} - ariaLabel={`dotUSD holders of the last ${dailyStatsDays} days`} + subtitle={`Accounts holding the asset · last ${holderStatsDays} days`} + ariaLabel={`dotUSD holders of the last ${holderStatsDays} days`} emptyText="No holder data available." /> ); } -export function DotUsdIssuanceStats({ items, isLoading }) { +export function DotUsdIssuanceStats() { + const { items, isLoading } = useIssuanceStats(); + return ( abbreviateBigNumber(value, 2)} formatTooltip={(value) => `${abbreviateBigNumber(value, 2)} dotUSD`} - subtitle={`Total issued dotUSD · last ${dailyStatsDays} days`} - ariaLabel={`dotUSD total issuance of the last ${dailyStatsDays} days`} + subtitle="Total issued dotUSD · since launch" + ariaLabel="dotUSD total issuance since launch" emptyText="No issuance data available." /> ); diff --git a/packages/next-common/components/dotusd/index.jsx b/packages/next-common/components/dotusd/index.jsx index 410eb4d42c..fb6442ba3e 100644 --- a/packages/next-common/components/dotusd/index.jsx +++ b/packages/next-common/components/dotusd/index.jsx @@ -6,14 +6,10 @@ import DotUsdExternalAssets from "./externalAssets"; import DotUsdPool from "./pool"; import DotUsdHolders from "./holders"; import { DotUsdHolderStats, DotUsdIssuanceStats } from "./dailyStats"; -import useDailyStats from "./useDailyStats"; import DotUsdMintRecords from "./mintRecords"; import DotUsdRedeemRecords from "./redeemRecords"; function DotUsdOverview() { - // Both charts come from the same daily snapshots, so they share one request. - const dailyStats = useDailyStats(); - return (
- +
- +
{ @@ -16,15 +13,17 @@ export default function useDailyStats(days = dailyStatsDays) { // Keep the previous points on screen while the next response loads. setState((previous) => ({ ...previous, isLoading: true })); + const params = days === undefined ? {} : { days }; + nextApi - .fetch("dotusd/daily-stats", { days }) + .fetch(path, params) .then(({ result, error }) => { if (!isMounted) { return; } if (error) { - console.error("Failed to fetch dotUSD daily stats", error); + console.error(`Failed to fetch ${path}`, error); setState({ items: [], isLoading: false }); return; } @@ -35,7 +34,7 @@ export default function useDailyStats(days = dailyStatsDays) { }); }) .catch((error) => { - console.error("Failed to fetch dotUSD daily stats", error); + console.error(`Failed to fetch ${path}`, error); if (isMounted) { setState({ items: [], isLoading: false }); @@ -45,7 +44,7 @@ export default function useDailyStats(days = dailyStatsDays) { return () => { isMounted = false; }; - }, [days]); + }, [path, days]); return state; } diff --git a/packages/next-common/components/dotusd/useHolderStats.js b/packages/next-common/components/dotusd/useHolderStats.js new file mode 100644 index 0000000000..48671a2034 --- /dev/null +++ b/packages/next-common/components/dotusd/useHolderStats.js @@ -0,0 +1,7 @@ +import useDailyStats from "./useDailyStats"; + +export const holderStatsDays = 7; + +export default function useHolderStats() { + return useDailyStats("dotusd/holder-stats", holderStatsDays); +} diff --git a/packages/next-common/components/dotusd/useIssuanceStats.js b/packages/next-common/components/dotusd/useIssuanceStats.js new file mode 100644 index 0000000000..03e8ee9a57 --- /dev/null +++ b/packages/next-common/components/dotusd/useIssuanceStats.js @@ -0,0 +1,6 @@ +import useDailyStats from "./useDailyStats"; + +// No days argument: the api returns the whole history since the launch. +export default function useIssuanceStats() { + return useDailyStats("dotusd/issuance-stats"); +} From e9f2650f3199655a3e45b74337487d879b2a12ac Mon Sep 17 00:00:00 2001 From: chaojun Date: Thu, 22 Oct 2026 16:01:47 +0800 Subject: [PATCH 3/3] refactor UI layout --- .../components/dotusd/dailyStatChart.jsx | 150 ------------ .../components/dotusd/dailyStats.jsx | 213 ++++++++++++++---- .../components/dotusd/holdersTab.jsx | 10 + .../next-common/components/dotusd/index.jsx | 25 +- .../components/dotusd/recordsLink.jsx | 21 ++ .../next-common/components/dotusd/summary.jsx | 21 +- .../next-common/components/dotusd/tabs.jsx | 1 + .../components/dotusd/useHolderStats.js | 5 +- 8 files changed, 218 insertions(+), 228 deletions(-) delete mode 100644 packages/next-common/components/dotusd/dailyStatChart.jsx create mode 100644 packages/next-common/components/dotusd/holdersTab.jsx create mode 100644 packages/next-common/components/dotusd/recordsLink.jsx diff --git a/packages/next-common/components/dotusd/dailyStatChart.jsx b/packages/next-common/components/dotusd/dailyStatChart.jsx deleted file mode 100644 index 1781622701..0000000000 --- a/packages/next-common/components/dotusd/dailyStatChart.jsx +++ /dev/null @@ -1,150 +0,0 @@ -import dayjs from "dayjs"; -import utc from "dayjs/plugin/utc"; -import { Line } from "react-chartjs-2"; -import "next-common/components/charts/globalConfig"; -import hoverLinePlugin from "next-common/components/charts/plugins/hoverLine"; -import { SecondaryCard } from "next-common/components/styled/containers/secondaryCard"; -import Loading from "next-common/components/loading"; -import NoData from "next-common/components/noData"; -import { useThemeSetting } from "next-common/context/theme"; - -dayjs.extend(utc); - -const chartHeight = 240; - -function buildChartData(points, color, valueOf) { - return { - labels: points.map(({ date }) => dayjs.utc(date).format("MMM D")), - datasets: [ - { - data: points.map(valueOf), - borderColor: color, - backgroundColor: color, - borderWidth: 2, - // A long series would otherwise be covered by its own points. - pointRadius: points.length > 31 ? 0 : 2, - pointHoverRadius: 4, - pointBackgroundColor: color, - tension: 0.2, - }, - ], - }; -} - -function buildChartOptions( - points, - { textTertiary, neutral100, neutral300, neutral400, tooltipBg }, - { formatTick, formatTooltip, ticksPrecision }, -) { - return { - responsive: true, - maintainAspectRatio: false, - animation: false, - interaction: { mode: "index", intersect: false }, - scales: { - x: { - border: { display: false }, - grid: { display: false }, - ticks: { color: textTertiary, maxRotation: 0, maxTicksLimit: 7 }, - }, - y: { - border: { display: false }, - grid: { color: neutral300, drawTicks: false }, - ticks: { - color: textTertiary, - maxTicksLimit: 5, - precision: ticksPrecision, - callback: formatTick, - }, - }, - }, - plugins: { - legend: { display: false }, - hoverLine: { lineColor: neutral400, lineWidth: 1 }, - tooltip: { - displayColors: false, - backgroundColor: tooltipBg, - titleColor: neutral100, - bodyColor: neutral100, - callbacks: { - title: ([{ dataIndex }]) => - dayjs.utc(points[dataIndex].date).format("MMM D, YYYY"), - label: ({ parsed }) => formatTooltip(parsed.y), - }, - }, - }, - }; -} - -function ChartContent({ - points, - colorKey, - valueOf, - renderValue, - formatTick, - formatTooltip, - ticksPrecision, - subtitle, - ariaLabel, -}) { - const theme = useThemeSetting(); - const color = theme[colorKey]; - const latest = points[points.length - 1]; - - return ( - <> -
-
{renderValue(latest)}
-
{subtitle}
-
-
- -
- - ); -} - -/** - * The card of one daily dotUSD metric: the latest value, its description and the line of the - * snapshots of the last days. The points are the daily documents served by the backend. - */ -export default function DailyStatChart({ - points, - isLoading, - emptyText, - ...rest -}) { - if (isLoading) { - return ( - -
- -
-
- ); - } - - if (!points.length) { - return ( - - - - ); - } - - return ( - - - - ); -} diff --git a/packages/next-common/components/dotusd/dailyStats.jsx b/packages/next-common/components/dotusd/dailyStats.jsx index c2c62c15f8..d38145c45b 100644 --- a/packages/next-common/components/dotusd/dailyStats.jsx +++ b/packages/next-common/components/dotusd/dailyStats.jsx @@ -1,55 +1,190 @@ +import dayjs from "dayjs"; +import utc from "dayjs/plugin/utc"; +import { Line } from "react-chartjs-2"; +import "next-common/components/charts/globalConfig"; +import hoverLinePlugin from "next-common/components/charts/plugins/hoverLine"; +import { SecondaryCard } from "next-common/components/styled/containers/secondaryCard"; +import Loading from "next-common/components/loading"; +import NoData from "next-common/components/noData"; +import ValueDisplay from "next-common/components/valueDisplay"; +import { useThemeSetting } from "next-common/context/theme"; import { toPrecision, toPrecisionNumber } from "next-common/utils"; import { abbreviateBigNumber } from "next-common/utils/viewfuncs"; -import ValueDisplay from "next-common/components/valueDisplay"; -import DailyStatChart from "./dailyStatChart"; -import useHolderStats, { holderStatsDays } from "./useHolderStats"; +import RecordsLink from "./recordsLink"; +import useHolderStats from "./useHolderStats"; import useIssuanceStats from "./useIssuanceStats"; +dayjs.extend(utc); + // dotUSD is an Asset Hub asset with six decimals. const DOT_USD_DECIMALS = 6; +const chartHeight = 240; + +function buildChartData(points, color, valueOf) { + return { + labels: points.map(({ date }) => dayjs.utc(date).format("MMM D")), + datasets: [ + { + data: points.map(valueOf), + borderColor: color, + backgroundColor: color, + borderWidth: 2, + // A long series would otherwise be covered by its own points. + pointRadius: points.length > 31 ? 0 : 2, + pointHoverRadius: 4, + pointBackgroundColor: color, + tension: 0.2, + }, + ], + }; +} -export function DotUsdHolderStats() { - const { items, isLoading } = useHolderStats(); +function buildChartOptions( + points, + { textTertiary, neutral100, neutral300, neutral400, tooltipBg }, + { formatTick, formatTooltip, ticksPrecision }, +) { + return { + responsive: true, + maintainAspectRatio: false, + animation: false, + interaction: { mode: "index", intersect: false }, + scales: { + x: { + border: { display: false }, + grid: { display: false }, + ticks: { color: textTertiary, maxRotation: 0, maxTicksLimit: 7 }, + }, + y: { + border: { display: false }, + grid: { color: neutral300, drawTicks: false }, + ticks: { + color: textTertiary, + maxTicksLimit: 5, + precision: ticksPrecision, + callback: formatTick, + }, + }, + }, + plugins: { + legend: { display: false }, + hoverLine: { lineColor: neutral400, lineWidth: 1 }, + tooltip: { + displayColors: false, + backgroundColor: tooltipBg, + titleColor: neutral100, + bodyColor: neutral100, + callbacks: { + title: ([{ dataIndex }]) => + dayjs.utc(points[dataIndex].date).format("MMM D, YYYY"), + label: ({ parsed }) => formatTooltip(parsed.y), + }, + }, + }, + }; +} + +// One panel of the trend: the latest value, its description and the line of the metric. +function StatPanel({ + points, + isLoading, + colorKey, + valueOf, + value, + label, + action, + formatTick, + formatTooltip, + ticksPrecision, + ariaLabel, + emptyText, +}) { + const theme = useThemeSetting(); return ( - holderCount} - renderValue={({ holderCount }) => holderCount} - formatTick={(value) => value} - ticksPrecision={0} - formatTooltip={(value) => `${value} accounts`} - subtitle={`Accounts holding the asset · last ${holderStatsDays} days`} - ariaLabel={`dotUSD holders of the last ${holderStatsDays} days`} - emptyText="No holder data available." - /> + + {isLoading ? ( +
+ +
+ ) : !points.length ? ( + + ) : ( + <> +
+
{value}
+
+ {label} + {action} +
+
+
+ +
+ + )} +
); } -export function DotUsdIssuanceStats() { - const { items, isLoading } = useIssuanceStats(); +// The two metrics are read from their own apis, so they load and fail independently. +export default function DotUsdStats() { + const holder = useHolderStats(); + const issuance = useIssuanceStats(); + const latestHolder = holder.items[holder.items.length - 1]?.holderCount; + const latestIssuance = + issuance.items[issuance.items.length - 1]?.totalIssuance; return ( - - toPrecisionNumber(totalIssuance, DOT_USD_DECIMALS) - } - renderValue={({ totalIssuance }) => ( - - )} - formatTick={(value) => abbreviateBigNumber(value, 2)} - formatTooltip={(value) => `${abbreviateBigNumber(value, 2)} dotUSD`} - subtitle="Total issued dotUSD · since launch" - ariaLabel="dotUSD total issuance since launch" - emptyText="No issuance data available." - /> +
+ + toPrecisionNumber(totalIssuance, DOT_USD_DECIMALS) + } + value={ + latestIssuance === undefined ? ( + "—" + ) : ( + + ) + } + label="Total issued dotUSD" + formatTick={(value) => abbreviateBigNumber(value, 2)} + formatTooltip={(value) => `${abbreviateBigNumber(value, 2)} dotUSD`} + ariaLabel="dotUSD total issuance since launch" + emptyText="No issuance data available." + /> + + holderCount} + value={latestHolder ?? "—"} + label="Accounts holding the asset" + action={} + formatTick={(value) => value} + ticksPrecision={0} + formatTooltip={(value) => `${value} accounts`} + ariaLabel="dotUSD holders since launch" + emptyText="No holder data available." + /> +
); } diff --git a/packages/next-common/components/dotusd/holdersTab.jsx b/packages/next-common/components/dotusd/holdersTab.jsx new file mode 100644 index 0000000000..a287a43b5d --- /dev/null +++ b/packages/next-common/components/dotusd/holdersTab.jsx @@ -0,0 +1,10 @@ +import { Section } from "./layout"; +import DotUsdHolders from "./holders"; + +export default function DotUsdHoldersTab() { + return ( +
+ +
+ ); +} diff --git a/packages/next-common/components/dotusd/index.jsx b/packages/next-common/components/dotusd/index.jsx index fb6442ba3e..7f7c68c6af 100644 --- a/packages/next-common/components/dotusd/index.jsx +++ b/packages/next-common/components/dotusd/index.jsx @@ -4,8 +4,8 @@ import DotUsdAccount from "./account"; import DotUsdInstance from "./instance"; import DotUsdExternalAssets from "./externalAssets"; import DotUsdPool from "./pool"; -import DotUsdHolders from "./holders"; -import { DotUsdHolderStats, DotUsdIssuanceStats } from "./dailyStats"; +import DotUsdStats from "./dailyStats"; +import DotUsdHoldersTab from "./holdersTab"; import DotUsdMintRecords from "./mintRecords"; import DotUsdRedeemRecords from "./redeemRecords"; @@ -38,21 +38,10 @@ function DotUsdOverview() {
- -
- -
- -
- -
- +
); @@ -61,6 +50,10 @@ function DotUsdOverview() { function DotUsdTabContent() { const { activeTab } = useDotUsdTabs(); + if (activeTab === "holders") { + return ; + } + if (activeTab === "mint") { return ; } diff --git a/packages/next-common/components/dotusd/recordsLink.jsx b/packages/next-common/components/dotusd/recordsLink.jsx new file mode 100644 index 0000000000..170954e44c --- /dev/null +++ b/packages/next-common/components/dotusd/recordsLink.jsx @@ -0,0 +1,21 @@ +import { ArrowExternalLink } from "@osn/icons/subsquare"; +import Tooltip from "next-common/components/tooltip"; +import { useDotUsdTabs } from "./tabs"; + +// Switches to the tab of the list the number is summed from. +export default function RecordsLink({ tab, tooltip }) { + const { setActiveTab } = useDotUsdTabs(); + + return ( + + + + ); +} diff --git a/packages/next-common/components/dotusd/summary.jsx b/packages/next-common/components/dotusd/summary.jsx index 3109678bad..07b1056a48 100644 --- a/packages/next-common/components/dotusd/summary.jsx +++ b/packages/next-common/components/dotusd/summary.jsx @@ -1,4 +1,3 @@ -import { ArrowExternalLink } from "@osn/icons/subsquare"; import BigNumber from "bignumber.js"; import { isNil } from "lodash-es"; import { toPrecision } from "next-common/utils"; @@ -10,7 +9,7 @@ import ValueDisplay from "next-common/components/valueDisplay"; import Tooltip from "next-common/components/tooltip"; import { useDotUsdContext } from "./context"; import usePsmStats from "./usePsmStats"; -import { useDotUsdTabs } from "./tabs"; +import RecordsLink from "./recordsLink"; function EmptyValue() { return —; @@ -57,24 +56,6 @@ function SignedAmountValue({ value, symbol, decimals }) { ); } -// Switches to the records list the flow number is summed from. -function RecordsLink({ tab, tooltip }) { - const { setActiveTab } = useDotUsdTabs(); - - return ( - - - - ); -} - function DebtUsageBar({ ratio, maxDebt }) { const percent = BigNumber.min(BigNumber.max(ratio, 0), 100).toNumber(); diff --git a/packages/next-common/components/dotusd/tabs.jsx b/packages/next-common/components/dotusd/tabs.jsx index eab7fec996..a55125dce7 100644 --- a/packages/next-common/components/dotusd/tabs.jsx +++ b/packages/next-common/components/dotusd/tabs.jsx @@ -2,6 +2,7 @@ import { createContext, useContext, useState } from "react"; export const DOT_USD_TABS = [ { value: "overview", label: "Overview" }, + { value: "holders", label: "Holders" }, { value: "mint", label: "Mint records" }, { value: "redeem", label: "Redeem records" }, ]; diff --git a/packages/next-common/components/dotusd/useHolderStats.js b/packages/next-common/components/dotusd/useHolderStats.js index 48671a2034..c4adad790c 100644 --- a/packages/next-common/components/dotusd/useHolderStats.js +++ b/packages/next-common/components/dotusd/useHolderStats.js @@ -1,7 +1,6 @@ import useDailyStats from "./useDailyStats"; -export const holderStatsDays = 7; - +// No days argument: the api returns the whole history since the launch. export default function useHolderStats() { - return useDailyStats("dotusd/holder-stats", holderStatsDays); + return useDailyStats("dotusd/holder-stats"); }