From a348f73142dd2e3b1874c50949c0a8b63b1a4b71 Mon Sep 17 00:00:00 2001 From: Madhur Gupta Date: Wed, 7 Jan 2026 19:33:26 +0530 Subject: [PATCH 1/2] feat(frontend): add TPS tracker component and extract LiveBadge into reusable component --- frontend/app/page.tsx | 3 + frontend/components/common/live-badge.tsx | 37 ++++++++++++ .../swap-transfer-tracker/index.tsx | 27 +-------- frontend/components/tps-tracker/index.tsx | 48 +++++++++++++++ frontend/hooks/use-tps.ts | 60 +++++++++++++++++++ 5 files changed, 149 insertions(+), 26 deletions(-) create mode 100644 frontend/components/common/live-badge.tsx create mode 100644 frontend/components/tps-tracker/index.tsx create mode 100644 frontend/hooks/use-tps.ts diff --git a/frontend/app/page.tsx b/frontend/app/page.tsx index 4308c61..ce023a5 100644 --- a/frontend/app/page.tsx +++ b/frontend/app/page.tsx @@ -4,6 +4,7 @@ import PageHeader from '@/components/common/page-header' import HotAccountsBubbleMap from '@/components/hot-accounts-bubble-map' import HotSlotsBubbleMap from '@/components/hot-slots-bubble-map' import SwapTransferTracker from '@/components/swap-transfer-tracker' +import TpsTracker from '@/components/tps-tracker' export default function Home() { return ( @@ -11,6 +12,8 @@ export default function Home() {
+ + diff --git a/frontend/components/common/live-badge.tsx b/frontend/components/common/live-badge.tsx new file mode 100644 index 0000000..b227d9d --- /dev/null +++ b/frontend/components/common/live-badge.tsx @@ -0,0 +1,37 @@ +'use client' + +import { cn } from '@/lib/utils' + +interface LiveBadgeProps { + isConnected: boolean +} + +/** + * Reusable live badge component with animated ping effect. + * Used to indicate real-time connection status. + */ +export function LiveBadge({ isConnected }: LiveBadgeProps) { + return ( + + + {isConnected && ( + + )} + + + Live + + ) +} diff --git a/frontend/components/swap-transfer-tracker/index.tsx b/frontend/components/swap-transfer-tracker/index.tsx index d0b6d3b..a01b0ec 100644 --- a/frontend/components/swap-transfer-tracker/index.tsx +++ b/frontend/components/swap-transfer-tracker/index.tsx @@ -1,6 +1,7 @@ 'use client' import { ArrowLeftRight, Send } from 'lucide-react' +import { LiveBadge } from '@/components/common/live-badge' import { SectionHeader } from '@/components/ui/section-header' import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs' import { useSwapEvents } from '@/hooks/use-swap-events' @@ -18,32 +19,6 @@ const TAB_TRIGGER_CLASS = cn( 'data-[state=active]:bg-transparent data-[state=active]:shadow-none', ) -function LiveBadge({ isConnected }: { isConnected: boolean }) { - return ( - - - {isConnected && ( - - )} - - - Live - - ) -} - export default function SwapTransferTracker() { const { allSwaps, isConnected: isSwapConnected } = useSwapEvents() const { diff --git a/frontend/components/tps-tracker/index.tsx b/frontend/components/tps-tracker/index.tsx new file mode 100644 index 0000000..6429845 --- /dev/null +++ b/frontend/components/tps-tracker/index.tsx @@ -0,0 +1,48 @@ +'use client' + +import { Activity } from 'lucide-react' +import { SectionHeader } from '@/components/ui/section-header' +import { StatCard } from '@/components/ui/stat-card' +import { useTps } from '@/hooks/use-tps' +import { formatIntNumber } from '@/utils/ui' + +/** + * TPS Tracker component displaying real-time transactions per second on Monad + */ +export default function TpsTracker() { + const { currentTps, peakTps, totalTransactions } = useTps() + + return ( +
+ + +
+ + + +
+
+ ) +} diff --git a/frontend/hooks/use-tps.ts b/frontend/hooks/use-tps.ts new file mode 100644 index 0000000..db7dc89 --- /dev/null +++ b/frontend/hooks/use-tps.ts @@ -0,0 +1,60 @@ +'use client' + +import { useCallback, useEffect, useRef, useState } from 'react' +import { useEvents } from '@/hooks/use-events' +import type { SerializableEventData } from '@/types/events' + +const TPS_INTERVAL_MS = 1000 + +interface TpsData { + currentTps: number + peakTps: number + totalTransactions: number +} + +/** + * Hook to calculate and track TPS (Transactions Per Second) from execution events. + * Subscribes to TxnHeaderStart events and calculates TPS every second. + */ +export function useTps() { + const [tpsData, setTpsData] = useState({ + currentTps: 0, + peakTps: 0, + totalTransactions: 0, + }) + + const txCountRef = useRef(0) + const intervalRef = useRef(null) + + const handleEvent = useCallback((event: SerializableEventData) => { + if (event.payload.type === 'TxnHeaderStart') { + txCountRef.current += 1 + } + }, []) + + useEvents({ + filters: [{ eventName: 'TxnHeaderStart' }], + onEvent: handleEvent, + }) + + useEffect(() => { + intervalRef.current = setInterval(() => { + const count = txCountRef.current + txCountRef.current = 0 + + setTpsData((prev) => ({ + currentTps: count, + peakTps: Math.max(prev.peakTps, count), + totalTransactions: prev.totalTransactions + count, + })) + }, TPS_INTERVAL_MS) + + return () => { + if (intervalRef.current) { + clearInterval(intervalRef.current) + } + } + }, []) + + return tpsData +} From 76ce23e82ea7e790c4c2999d2acc6bb045e8f597 Mon Sep 17 00:00:00 2001 From: Madhur Gupta Date: Wed, 7 Jan 2026 19:45:49 +0530 Subject: [PATCH 2/2] feat(frontend): update TPS tracker icons for better visual distinction --- frontend/components/tps-tracker/index.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/frontend/components/tps-tracker/index.tsx b/frontend/components/tps-tracker/index.tsx index 6429845..fcda94b 100644 --- a/frontend/components/tps-tracker/index.tsx +++ b/frontend/components/tps-tracker/index.tsx @@ -1,6 +1,6 @@ 'use client' -import { Activity } from 'lucide-react' +import { Activity, Hash, TrendingUp } from 'lucide-react' import { SectionHeader } from '@/components/ui/section-header' import { StatCard } from '@/components/ui/stat-card' import { useTps } from '@/hooks/use-tps' @@ -30,7 +30,7 @@ export default function TpsTracker() { label="Peak TPS" value={formatIntNumber(peakTps)} description="Highest TPS observed since page load" - icon={Activity} + icon={TrendingUp} iconClassName="text-amber-400" iconBgClassName="bg-amber-400/10" /> @@ -38,7 +38,7 @@ export default function TpsTracker() { label="Total Transactions" value={formatIntNumber(totalTransactions)} description="Transactions since page load" - icon={Activity} + icon={Hash} iconClassName="text-blue-400" iconBgClassName="bg-blue-400/10" />