From bc6812f01f03b1b6a77e30728f4ba46569efbccf Mon Sep 17 00:00:00 2001 From: Jason Schwarz Date: Mon, 26 Jan 2026 21:46:32 -0400 Subject: [PATCH 1/3] feat: add eth values to leaderboard --- .../leaderboard/LeaderboardPageClient.tsx | 1 + src/app/api/analytics/leaderboard/route.ts | 1 + src/components/dashboard/LeaderboardTable.tsx | 70 ++++++++++++++----- src/hooks/use-leaderboard-data.ts | 1 + src/lib/analytics-server.ts | 1 + .../services/leaderboard-transform.ts | 2 + 6 files changed, 58 insertions(+), 18 deletions(-) diff --git a/src/app/(app)/leaderboard/LeaderboardPageClient.tsx b/src/app/(app)/leaderboard/LeaderboardPageClient.tsx index 5220459..b328bc4 100644 --- a/src/app/(app)/leaderboard/LeaderboardPageClient.tsx +++ b/src/app/(app)/leaderboard/LeaderboardPageClient.tsx @@ -27,6 +27,7 @@ interface LeaderboardPageClientProps { swapCount: number change24h: number isCurrentUser: boolean + ethValue: number }> } diff --git a/src/app/api/analytics/leaderboard/route.ts b/src/app/api/analytics/leaderboard/route.ts index 820e70b..863c9ed 100644 --- a/src/app/api/analytics/leaderboard/route.ts +++ b/src/app/api/analytics/leaderboard/route.ts @@ -132,6 +132,7 @@ export async function GET(request: NextRequest) { swapCount: userSwapCount, change24h: userChange24hPct, isCurrentUser: true, + ethValue: userTotalSwapVolEth, }) } } diff --git a/src/components/dashboard/LeaderboardTable.tsx b/src/components/dashboard/LeaderboardTable.tsx index 446e88c..5b10b4d 100644 --- a/src/components/dashboard/LeaderboardTable.tsx +++ b/src/components/dashboard/LeaderboardTable.tsx @@ -22,6 +22,7 @@ interface LeaderboardEntry { swapCount?: number change24h: number isCurrentUser?: boolean + ethValue?: number } interface LeaderboardData { @@ -116,6 +117,7 @@ export const LeaderboardTable = ({ swapCount: userSwapTxs !== null ? userSwapTxs : undefined, change24h: 0, isCurrentUser: true, + ethValue: ethPrice && adjustedUserVol ? adjustedUserVol / ethPrice : undefined, }) } @@ -152,6 +154,7 @@ export const LeaderboardTable = ({ let displayData = top15 if (!userInTop15 && userPos && userAddr) { + const fromLb = lbData.find((e) => e.isCurrentUser) // Add user entry after top 15 with actual position from API displayData = [ ...top15, @@ -162,6 +165,9 @@ export const LeaderboardTable = ({ swapCount: userSwapTxs !== null ? userSwapTxs : undefined, change24h: 0, isCurrentUser: true, + ethValue: + fromLb?.ethValue ?? + (ethPrice && adjustedUserVol ? adjustedUserVol / ethPrice : undefined), }, ] } @@ -246,7 +252,7 @@ export const LeaderboardTable = ({ {/* Header Section: Title & Global Stats */}
{/* Branding & Global Metrics */} -
+
@@ -259,23 +265,33 @@ export const LeaderboardTable = ({
-
+
- + Traders - + {activeTraders?.toLocaleString() || "---"}
-
- - Total Volume +
+ + Vol (USD) - + {totalVol ? formatVolumeDisplay(totalVol) : "---"}
+
+ + Vol (ETH) + + + {swapVolumeEth != null + ? `${swapVolumeEth.toLocaleString(undefined, { maximumFractionDigits: 2, minimumFractionDigits: 2 })} ETH` + : "---"} + +
@@ -620,16 +636,34 @@ export const LeaderboardTable = ({
-

- {formatVolumeDisplay(entry.swapVolume24h)} -

-
= 0 ? "text-emerald-500" : "text-rose-500" - }`} - > - {entry.change24h >= 0 ? "+" : ""} - {entry.change24h.toFixed(1)}% + {/* Combined Value Column (ETH + USD) */} +
+
+
= 0 ? "text-emerald-500/80" : "text-rose-500/80" + }`} + > + {entry.change24h >= 0 ? "↑" : "↓"}{" "} + {Math.abs(entry.change24h).toFixed(1)}% +
+
+ + {/* The Hero Metric: USD Volume */} + + {formatVolumeDisplay(entry.swapVolume24h)} + + + {/* The Sub Metric: ETH Value + Price Reference */} +
+ + {entry.ethValue?.toLocaleString(undefined, { + maximumFractionDigits: 4, + minimumFractionDigits: 4, + })}{" "} + ETH + +
diff --git a/src/hooks/use-leaderboard-data.ts b/src/hooks/use-leaderboard-data.ts index 1f41352..1fea41f 100644 --- a/src/hooks/use-leaderboard-data.ts +++ b/src/hooks/use-leaderboard-data.ts @@ -10,6 +10,7 @@ interface LeaderboardEntry { swapCount: number change24h: number isCurrentUser: boolean + ethValue: number } export interface LeaderboardData { diff --git a/src/lib/analytics-server.ts b/src/lib/analytics-server.ts index bb52ee9..12a15c0 100644 --- a/src/lib/analytics-server.ts +++ b/src/lib/analytics-server.ts @@ -222,6 +222,7 @@ export async function getLeaderboardTop15(): Promise<{ swapCount: number change24h: number isCurrentUser: boolean + ethValue: number }> ethPrice: number | null } | null> { diff --git a/src/lib/analytics/services/leaderboard-transform.ts b/src/lib/analytics/services/leaderboard-transform.ts index 6d2e4be..803abf4 100644 --- a/src/lib/analytics/services/leaderboard-transform.ts +++ b/src/lib/analytics/services/leaderboard-transform.ts @@ -24,6 +24,7 @@ export interface TransformedLeaderboardEntry { swapCount: number change24h: number isCurrentUser: boolean + ethValue: number } /** @@ -62,6 +63,7 @@ export function transformLeaderboardRows( swapCount: swapCount, change24h: change24hPct, isCurrentUser: currentUserLower ? walletLower === currentUserLower : false, + ethValue: volumeEth, } }) } From 0cd813daf4f4b4ad8a02f46af62d3d51ebcb5623 Mon Sep 17 00:00:00 2001 From: Jason Schwarz Date: Mon, 26 Jan 2026 21:54:39 -0400 Subject: [PATCH 2/3] feat: add dashboard button to the claim/onboarding header --- src/components/onboarding/OnboardingHeader.tsx | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/components/onboarding/OnboardingHeader.tsx b/src/components/onboarding/OnboardingHeader.tsx index 55de1c0..7532a91 100644 --- a/src/components/onboarding/OnboardingHeader.tsx +++ b/src/components/onboarding/OnboardingHeader.tsx @@ -2,6 +2,7 @@ import Image from "next/image" import { useRouter } from "next/navigation" +import { Button } from "@/components/ui/button" export const OnboardingHeader = () => { const router = useRouter() @@ -28,7 +29,18 @@ export const OnboardingHeader = () => { />
-

Claim Genesis SBT

+
+

Claim Genesis SBT

+ + +
) From 65de0941d01789371f9ad7a72555870b092a236a Mon Sep 17 00:00:00 2001 From: Jason Schwarz Date: Tue, 27 Jan 2026 17:27:46 -0400 Subject: [PATCH 3/3] refactor: eth value formating --- src/app/(app)/leaderboard/page.tsx | 1 + src/components/dashboard/LeaderboardTable.tsx | 20 +++++++++---------- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/src/app/(app)/leaderboard/page.tsx b/src/app/(app)/leaderboard/page.tsx index d5ca7ec..80e3899 100644 --- a/src/app/(app)/leaderboard/page.tsx +++ b/src/app/(app)/leaderboard/page.tsx @@ -29,6 +29,7 @@ async function StatsLoader({ swapCount: number change24h: number isCurrentUser: boolean + ethValue: number }> }) { // Start all stats fetches in parallel - they'll complete independently diff --git a/src/components/dashboard/LeaderboardTable.tsx b/src/components/dashboard/LeaderboardTable.tsx index 5b10b4d..0f242f8 100644 --- a/src/components/dashboard/LeaderboardTable.tsx +++ b/src/components/dashboard/LeaderboardTable.tsx @@ -5,7 +5,7 @@ import { useAccount } from "wagmi" import { Card } from "@/components/ui/card" import { Badge } from "@/components/ui/badge" import { TrendingUp, Target, Zap } from "lucide-react" -import { formatCurrency } from "@/lib/utils" +import { formatCurrency, formatNumber } from "@/lib/utils" import { trimWalletAddress } from "@/lib/analytics/services/leaderboard-transform" import { TIER_THRESHOLDS, @@ -276,22 +276,23 @@ export const LeaderboardTable = ({
- Vol (USD) + Vol (ETH) - {totalVol ? formatVolumeDisplay(totalVol) : "---"} + {swapVolumeEth != null + ? `${formatNumber(swapVolumeEth)} ETH` + : "---"}
- Vol (ETH) + Vol (USD) - {swapVolumeEth != null - ? `${swapVolumeEth.toLocaleString(undefined, { maximumFractionDigits: 2, minimumFractionDigits: 2 })} ETH` - : "---"} + {totalVol ? formatVolumeDisplay(totalVol) : "---"}
+
@@ -657,10 +658,7 @@ export const LeaderboardTable = ({ {/* The Sub Metric: ETH Value + Price Reference */}
- {entry.ethValue?.toLocaleString(undefined, { - maximumFractionDigits: 4, - minimumFractionDigits: 4, - })}{" "} + {formatNumber(entry.ethValue)}{" "} ETH