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/(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/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..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, @@ -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,34 @@ export const LeaderboardTable = ({
-
+
- + Traders - + {activeTraders?.toLocaleString() || "---"}
-
- - Total Volume +
+ + Vol (ETH) - + + {swapVolumeEth != null + ? `${formatNumber(swapVolumeEth)} ETH` + : "---"} + +
+
+ + Vol (USD) + + {totalVol ? formatVolumeDisplay(totalVol) : "---"}
+
@@ -620,16 +637,31 @@ 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 */} +
+ + {formatNumber(entry.ethValue)}{" "} + ETH + +
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

+ + +
) 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, } }) }