Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion apps/scan/app/[locale]/HomeContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import { LiveTicker } from "@/components/home/LiveTicker";
import { StickyStatsBar } from "@/components/home/StickyStatsBar";
import { TxChart14d } from "@/components/home/TxChart14d";
import { FreshnessChip } from "@/components/common/FreshnessChip";
import { useNetwork } from "@/lib/network-context";
import { useNetwork, useNetworkFromQuery } from "@/lib/network-context";
import { useStats, useBlocks, useTransactions, useChainPerformance, useMempool, useCurrentEpoch, useChainStatus } from "@/lib/hooks";
import { useLatestBlock, useLatestFinalized } from "@/lib/ws";
import { formatNumber, formatSRX, toMillis } from "@/lib/format";
Expand Down Expand Up @@ -77,6 +77,10 @@ function estimateTotalTransactions(
export function HomeContent({ initial }: { initial: HomeBundle }) {
const t = useTranslations("home");
const { network } = useNetwork();
// Honour `?network=mainnet|testnet` deeplinks on the home page too —
// without this, https://scan.sentrixchain.com/?network=testnet would
// render mainnet because the cookie never flips.
useNetworkFromQuery();
const router = useRouter();
const [query, setQuery] = useState("");
const [perfRange, setPerfRange] = useState<"1m" | "5m" | "15m" | "1h" | "24h">("1h");
Expand Down
3 changes: 2 additions & 1 deletion apps/scan/app/[locale]/accounts/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { Address } from "@/components/common/Address";
import { PageHeader } from "@/components/common/PageHeader";
import { Pagination } from "@/components/common/Pagination";
import { EmptyState } from "@/components/common/EmptyState";
import { useNetwork } from "@/lib/network-context";
import { useNetwork, useNetworkFromQuery } from "@/lib/network-context";
import { useAccountsTop } from "@/lib/hooks";
import { formatNumber, formatSRX } from "@/lib/format";

Expand All @@ -21,6 +21,7 @@ const PAGE_SIZE = 25;
// SentrixSafe surface their human names automatically.
export default function AccountsPage() {
const { network } = useNetwork();
useNetworkFromQuery();
const searchParams = useSearchParams();
const router = useRouter();
const pathname = usePathname();
Expand Down
3 changes: 2 additions & 1 deletion apps/scan/app/[locale]/analytics/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { Skeleton } from "@/components/ui/skeleton";
import { PageHeader } from "@/components/common/PageHeader";
import { StatCard } from "@/components/common/StatCard";
import { EmptyState } from "@/components/common/EmptyState";
import { useNetwork } from "@/lib/network-context";
import { useNetwork, useNetworkFromQuery } from "@/lib/network-context";
import { useStats, useChainPerformance, useValidators } from "@/lib/hooks";
import { formatNumber, formatSRX } from "@/lib/format";
import { fetchDailyStats } from "@/lib/api";
Expand All @@ -26,6 +26,7 @@ const AnalyticsCharts = dynamic(() => import("./charts").then((m) => m.Analytics
// so no new API work is needed to light this up.
export default function AnalyticsPage() {
const { network } = useNetwork();
useNetworkFromQuery();
const { data: stats, loading: statsLoading } = useStats(network);
const { data: perf } = useChainPerformance(network, "24h");
const { data: validators } = useValidators(network);
Expand Down
3 changes: 2 additions & 1 deletion apps/scan/app/[locale]/api-docs/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { useState } from "react";
import { Code, Copy, ExternalLink, Check } from "lucide-react";
import { PageHeader } from "@/components/common/PageHeader";
import { DetailCard } from "@/components/common/DetailCard";
import { useNetwork } from "@/lib/network-context";
import { useNetwork, useNetworkFromQuery } from "@/lib/network-context";
import { cn } from "@/lib/utils";

// DECISION: hand-curated API docs page rather than Mintlify or Swagger UI.
Expand Down Expand Up @@ -109,6 +109,7 @@ const WS_CHANNELS: Array<{ name: string; method: "eth_subscribe"; summary: strin

export default function ApiDocsPage() {
const { network } = useNetwork();
useNetworkFromQuery();
const restBase = network === "mainnet" ? "https://rpc.sentrixchain.com" : "https://testnet-rpc.sentrixchain.com";
const wsBase = network === "mainnet" ? "wss://rpc.sentrixchain.com/ws" : "wss://testnet-rpc.sentrixchain.com/ws";

Expand Down
4 changes: 3 additions & 1 deletion apps/scan/app/[locale]/blocks/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { Timestamp } from "@/components/common/Timestamp";
import { Copyable } from "@/components/common/Copyable";
import { Pagination } from "@/components/common/Pagination";
import { PageHeader } from "@/components/common/PageHeader";
import { useNetwork } from "@/lib/network-context";
import { useNetwork, useNetworkFromQuery } from "@/lib/network-context";
import { fetchBlocksPage, type BlockData } from "@/lib/api";
import { shortenHash } from "@/lib/format";

Expand All @@ -20,6 +20,8 @@ const PAGE_SIZE = 50; // server cap is 100; 50 is comfortable on a phone
export default function BlocksPage() {
const t = useTranslations("blocks");
const { network } = useNetwork();
// Deeplink network switch — same pattern as detail pages.
useNetworkFromQuery();
// Server-paginated against `/chain/blocks?page=N&limit=M`. Each page hits
// the backend fresh so we get accurate "page N of M" semantics across the
// full in-memory window (CHAIN_WINDOW_SIZE = 1000) — much deeper than the
Expand Down
3 changes: 2 additions & 1 deletion apps/scan/app/[locale]/contracts/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { useEffect, useState } from "react";
import { PageHeader } from "@/components/common/PageHeader";
import { DetailCard } from "@/components/common/DetailCard";
import { Address } from "@/components/common/Address";
import { useNetwork } from "@/lib/network-context";
import { useNetwork, useNetworkFromQuery } from "@/lib/network-context";
import { useSourcifyStatus } from "@/lib/sourcify";
import { fetchRecentContracts, type RecentContract } from "@/lib/api";

Expand Down Expand Up @@ -73,6 +73,7 @@ const CANONICAL: CanonicalEntry[] = [

export default function ContractsPage() {
const { network } = useNetwork();
useNetworkFromQuery();
const [lookup, setLookup] = useState("");
const [submitted, setSubmitted] = useState<string | null>(null);

Expand Down
3 changes: 2 additions & 1 deletion apps/scan/app/[locale]/epochs/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { PageHeader } from "@/components/common/PageHeader";
import { DetailCard } from "@/components/common/DetailCard";
import { InfoRow } from "@/components/common/InfoRow";
import { StatCard } from "@/components/common/StatCard";
import { useNetwork } from "@/lib/network-context";
import { useNetwork, useNetworkFromQuery } from "@/lib/network-context";
import { useStats, useCurrentEpoch, useValidators } from "@/lib/hooks";
import { formatNumber, formatSRX } from "@/lib/format";

Expand All @@ -34,6 +34,7 @@ const PAST_TO_SHOW = 12;

export default function EpochsPage() {
const { network } = useNetwork();
useNetworkFromQuery();
const { data: stats } = useStats(network);
const { data: epoch } = useCurrentEpoch(network);
const { data: validators } = useValidators(network);
Expand Down
3 changes: 2 additions & 1 deletion apps/scan/app/[locale]/forks/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import { GitFork, CheckCircle2, AlertTriangle, Clock } from "lucide-react";
import { PageHeader } from "@/components/common/PageHeader";
import { DetailCard } from "@/components/common/DetailCard";
import { useNetwork } from "@/lib/network-context";
import { useNetwork, useNetworkFromQuery } from "@/lib/network-context";
import { useStats } from "@/lib/hooks";
import { FORKS, forkStateAt, type ForkEntry } from "@/lib/forks/registry";
import { formatNumber } from "@/lib/format";
Expand All @@ -23,6 +23,7 @@ import { cn } from "@/lib/utils";

export default function ForksPage() {
const { network } = useNetwork();
useNetworkFromQuery();
const { data: stats } = useStats(network);
const height = stats?.height ?? 0;

Expand Down
3 changes: 2 additions & 1 deletion apps/scan/app/[locale]/gas/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { Flame, Zap, Gauge, Turtle, Rabbit, Rocket } from "lucide-react";
import { PageHeader } from "@/components/common/PageHeader";
import { DetailCard } from "@/components/common/DetailCard";
import { StatCard } from "@/components/common/StatCard";
import { useNetwork } from "@/lib/network-context";
import { useNetwork, useNetworkFromQuery } from "@/lib/network-context";
import { useStats, useMempool } from "@/lib/hooks";
import { formatNumber } from "@/lib/format";
import { fetchBlocksPage, type BlockData } from "@/lib/api";
Expand All @@ -30,6 +30,7 @@ const SENTRI_PER_SRX = 100_000_000;

export default function GasPage() {
const { network } = useNetwork();
useNetworkFromQuery();
const { data: stats } = useStats(network);
const { data: mempool } = useMempool(network);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,15 @@ import { Skeleton } from "@/components/ui/skeleton";
import { Address } from "@/components/common/Address";
import { Pagination } from "@/components/common/Pagination";
import { RankBadge } from "@/components/common/RankBadge";
import { useNetwork } from "@/lib/network-context";
import { useNetwork, useNetworkFromQuery } from "@/lib/network-context";
import { useActiveAccounts } from "@/lib/hooks";
import { formatNumber } from "@/lib/format";

const PAGE_SIZE = 25;

export default function MostActiveAccountsPage() {
const { network } = useNetwork();
useNetworkFromQuery();
const { data: accounts, loading } = useActiveAccounts(network, 100);
const [page, setPage] = useState(1);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { Skeleton } from "@/components/ui/skeleton";
import { Address } from "@/components/common/Address";
import { Pagination } from "@/components/common/Pagination";
import { RankBadge } from "@/components/common/RankBadge";
import { useNetwork } from "@/lib/network-context";
import { useNetwork, useNetworkFromQuery } from "@/lib/network-context";
import { useRichlist, useValidators } from "@/lib/hooks";
import { formatNumber } from "@/lib/format";

Expand All @@ -16,6 +16,7 @@ const PAGE_SIZE = 25;

export default function TopHoldersPage() {
const { network } = useNetwork();
useNetworkFromQuery();
const { data: holders, loading } = useRichlist(network, 100);
const { data: validators } = useValidators(network);
const [sortKey, setSortKey] = useState<SortKey>("balance");
Expand Down
3 changes: 2 additions & 1 deletion apps/scan/app/[locale]/leaderboard/compare/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { Skeleton } from "@/components/ui/skeleton";
import { Button } from "@/components/ui/button";
import { Address } from "@/components/common/Address";
import { useNetwork } from "@/lib/network-context";
import { useNetwork, useNetworkFromQuery } from "@/lib/network-context";
import { fetchAccountBalance, fetchToken, fetchValidators, type AccountBalance, type TokenData, type ValidatorData } from "@/lib/api";
import { formatNumber } from "@/lib/format";

Expand Down Expand Up @@ -36,6 +36,7 @@ export default function ComparePage() {

function CompareInner() {
const { network } = useNetwork();
useNetworkFromQuery();
const sp = useSearchParams();
const router = useRouter();
const pathname = usePathname();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,15 @@ import { Skeleton } from "@/components/ui/skeleton";
import { Address } from "@/components/common/Address";
import { Pagination } from "@/components/common/Pagination";
import { RankBadge } from "@/components/common/RankBadge";
import { useNetwork } from "@/lib/network-context";
import { useNetwork, useNetworkFromQuery } from "@/lib/network-context";
import { useContractStats } from "@/lib/hooks";
import { formatNumber } from "@/lib/format";

const PAGE_SIZE = 25;

export default function TopContractsByCallsPage() {
const { network } = useNetwork();
useNetworkFromQuery();
const { data, loading } = useContractStats(network, "calls", 100);
const [page, setPage] = useState(1);

Expand Down
3 changes: 2 additions & 1 deletion apps/scan/app/[locale]/leaderboard/contract/gas/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,15 @@ import { Skeleton } from "@/components/ui/skeleton";
import { Address } from "@/components/common/Address";
import { Pagination } from "@/components/common/Pagination";
import { RankBadge } from "@/components/common/RankBadge";
import { useNetwork } from "@/lib/network-context";
import { useNetwork, useNetworkFromQuery } from "@/lib/network-context";
import { useContractStats } from "@/lib/hooks";
import { formatNumber } from "@/lib/format";

const PAGE_SIZE = 25;

export default function TopContractsByGasPage() {
const { network } = useNetwork();
useNetworkFromQuery();
const { data, loading } = useContractStats(network, "gas_used", 100);
const [page, setPage] = useState(1);

Expand Down
3 changes: 2 additions & 1 deletion apps/scan/app/[locale]/leaderboard/whale/recent/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { Address } from "@/components/common/Address";
import { TxHash } from "@/components/common/TxHash";
import { Timestamp } from "@/components/common/Timestamp";
import { EmptyState } from "@/components/common/EmptyState";
import { useNetwork } from "@/lib/network-context";
import { useNetwork, useNetworkFromQuery } from "@/lib/network-context";
import { useBlocks } from "@/lib/hooks";
import { formatNumber } from "@/lib/format";

Expand All @@ -20,6 +20,7 @@ const DEFAULT_THRESHOLD = 10_000; // SRX
// TODO(api): needs GET /whale/tx?threshold=X — currently computed client-side from recent blocks.
export default function WhaleRecentPage() {
const { network } = useNetwork();
useNetworkFromQuery();
const { data: blocks, loading } = useBlocks(network, 100);
const [threshold, setThreshold] = useState(DEFAULT_THRESHOLD);

Expand Down
3 changes: 2 additions & 1 deletion apps/scan/app/[locale]/leaderboard/whale/top/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { Skeleton } from "@/components/ui/skeleton";
import { Address } from "@/components/common/Address";
import { EmptyState } from "@/components/common/EmptyState";
import { RankBadge } from "@/components/common/RankBadge";
import { useNetwork } from "@/lib/network-context";
import { useNetwork, useNetworkFromQuery } from "@/lib/network-context";
import { useRichlist, useValidators } from "@/lib/hooks";
import { formatNumber } from "@/lib/format";

Expand All @@ -17,6 +17,7 @@ const DEFAULT_THRESHOLD = 100_000; // SRX
// Matches Etherscan's whale-wallet convention of "large holders by absolute balance".
export default function WhaleTopWalletsPage() {
const { network } = useNetwork();
useNetworkFromQuery();
const { data: holders, loading } = useRichlist(network, 100);
const { data: validators } = useValidators(network);
const [threshold, setThreshold] = useState(DEFAULT_THRESHOLD);
Expand Down
3 changes: 2 additions & 1 deletion apps/scan/app/[locale]/mempool/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { Address } from "@/components/common/Address";
import { TxHash } from "@/components/common/TxHash";
import { EmptyState } from "@/components/common/EmptyState";
import { Skeleton } from "@/components/ui/skeleton";
import { useNetwork } from "@/lib/network-context";
import { useNetwork, useNetworkFromQuery } from "@/lib/network-context";
import { useMempool } from "@/lib/hooks";
import { formatSRX, timeAgo } from "@/lib/format";
import { classifyRail, RailBadge } from "@/components/common/RailBadge";
Expand All @@ -22,6 +22,7 @@ import { classifyRail, RailBadge } from "@/components/common/RailBadge";

export default function MempoolPage() {
const { network } = useNetwork();
useNetworkFromQuery();
const { data, loading } = useMempool(network);

return (
Expand Down
3 changes: 2 additions & 1 deletion apps/scan/app/[locale]/search/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { Link } from "@/i18n/navigation";
import { Coins, Search, Shield } from "lucide-react";
import { Card, CardContent } from "@/components/ui/card";
import { detectSearchType } from "@/lib/format";
import { useNetwork } from "@/lib/network-context";
import { useNetwork, useNetworkFromQuery } from "@/lib/network-context";
import { useSearchIndex } from "@/lib/search-index";
import { Suspense, useEffect } from "react";

Expand All @@ -22,6 +22,7 @@ function SearchContent() {
const query = searchParams.get("q") || "";
const type = detectSearchType(query);
const { network } = useNetwork();
useNetworkFromQuery();
const { match, ready } = useSearchIndex(network);

const hits = ready ? match(query, 12) : [];
Expand Down
3 changes: 2 additions & 1 deletion apps/scan/app/[locale]/sentinel/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import { useEffect, useState } from "react";
import { Activity, Radio, Users, Clock } from "lucide-react";
import { Address } from "@/components/common/Address";
import { useNetwork } from "@/lib/network-context";
import { useNetwork, useNetworkFromQuery } from "@/lib/network-context";
import { fetchSentrixStatusExtended, type SentrixStatusExtended } from "@/lib/api";
import { formatNumber } from "@/lib/format";

Expand All @@ -28,6 +28,7 @@ const HEALTH_TONE: Record<string, { ring: string; text: string; label: string }>

export default function SentinelPage() {
const { network } = useNetwork();
useNetworkFromQuery();
const [data, setData] = useState<SentrixStatusExtended | null>(null);
const [error, setError] = useState<string | null>(null);

Expand Down
3 changes: 2 additions & 1 deletion apps/scan/app/[locale]/supply/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { InfoRow } from "@/components/common/InfoRow";
import { StatCard } from "@/components/common/StatCard";
import { Address } from "@/components/common/Address";
import { Skeleton } from "@/components/ui/skeleton";
import { useNetwork } from "@/lib/network-context";
import { useNetwork, useNetworkFromQuery } from "@/lib/network-context";
import { useStats, useValidators } from "@/lib/hooks";
import { formatSRX, formatNumber } from "@/lib/format";

Expand Down Expand Up @@ -62,6 +62,7 @@ const PREMINE_TOTAL = PREMINE_WALLETS.reduce((s, e) => s + e.amount, 0);

export default function SupplyPage() {
const { network } = useNetwork();
useNetworkFromQuery();
const { data: stats, loading: statsLoading } = useStats(network);
const { data: validators } = useValidators(network);

Expand Down
4 changes: 3 additions & 1 deletion apps/scan/app/[locale]/tokens/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { Copyable } from "@/components/common/Copyable";
import { Pagination } from "@/components/common/Pagination";
import { PageHeader } from "@/components/common/PageHeader";
import { EmptyState } from "@/components/common/EmptyState";
import { useNetwork } from "@/lib/network-context";
import { useNetwork, useNetworkFromQuery } from "@/lib/network-context";
import { useTokens } from "@/lib/hooks";
import { formatNumber, shortenAddress } from "@/lib/format";

Expand All @@ -22,6 +22,8 @@ const PAGE_SIZE = 25;
export default function TokensPage() {
const t = useTranslations("tokens");
const { network } = useNetwork();
// Deeplink network switch.
useNetworkFromQuery();
const searchParams = useSearchParams();
const { data: tokens, loading } = useTokens(network);
const [sortKey, setSortKey] = useState<SortKey>("none");
Expand Down
4 changes: 3 additions & 1 deletion apps/scan/app/[locale]/validators/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { Address } from "@/components/common/Address";
import { Pagination } from "@/components/common/Pagination";
import { PageHeader } from "@/components/common/PageHeader";
import { StatCard } from "@/components/common/StatCard";
import { useNetwork } from "@/lib/network-context";
import { useNetwork, useNetworkFromQuery } from "@/lib/network-context";
import { useValidators } from "@/lib/hooks";
import { formatNumber } from "@/lib/format";

Expand All @@ -28,6 +28,8 @@ function StatusIcon({ status }: { status?: string }) {
export default function ValidatorsPage() {
const t = useTranslations("validators");
const { network } = useNetwork();
// Deeplink network switch.
useNetworkFromQuery();
const { data: validators, loading } = useValidators(network);
const [sortKey, setSortKey] = useState<SortKey>("none");
const [sortDir, setSortDir] = useState<"asc" | "desc">("desc");
Expand Down
Loading