diff --git a/next.config.ts b/next.config.ts
index be6528ee..ad07b9bb 100644
--- a/next.config.ts
+++ b/next.config.ts
@@ -269,7 +269,7 @@ const nextConfig: NextConfig = {
},
{
source: "/apps",
- destination: "/benchmarks",
+ destination: "/trading-apps",
permanent: true,
},
...chainRedirects,
diff --git a/src/app/trading-apps/page.tsx b/src/app/trading-apps/page.tsx
new file mode 100644
index 00000000..050557da
--- /dev/null
+++ b/src/app/trading-apps/page.tsx
@@ -0,0 +1,436 @@
+import Link from "next/link";
+import { ProviderLogo } from "@/components/provider-logo";
+import { readSnapshot } from "@/lib/snapshot";
+import { pageMetadata } from "@/lib/page-metadata";
+import { safeJsonLd, buildBreadcrumbJsonLd } from "@/lib/jsonld";
+import { SITE } from "@/data/site";
+
+const DESCRIPTION =
+ "Live benchmarks for Solana trading platforms and Telegram bots — volume, fees, execution quality, unique traders, and app store ratings.";
+
+export const metadata: import("next").Metadata = pageMetadata({
+ path: "/trading-apps",
+ title: "Best Solana Trading Apps 2026, ranked by benchmark",
+ description: DESCRIPTION,
+});
+
+export const revalidate = 60;
+
+const BENCH_SLUGS = [
+ "solana-trading-platform-wars",
+ "solana-dex-volume",
+ "solana-unique-traders",
+ "solana-avg-trade-size",
+ "solana-launchpad-wars",
+ "memecoin-platforms",
+ "trading-app-execution",
+ "app-store-ratings",
+] as const;
+
+const PRODUCTS = [
+ {
+ slug: "pump-fun",
+ name: "pump.fun",
+ description: "Leading Solana memecoin launchpad and AMM",
+ },
+ {
+ slug: "fomo",
+ name: "FOMO",
+ description: "Multi-chain memecoin trading with social copy-trading",
+ },
+ {
+ slug: "gmgn",
+ name: "GMGN",
+ description: "Memecoin terminal with smart money tracking and Telegram bot",
+ },
+ {
+ slug: "axiom",
+ name: "Axiom",
+ description: "Telegram trading bot for Solana memecoins",
+ },
+ {
+ slug: "trojan",
+ name: "Trojan",
+ description: "Fast Solana Telegram bot with sniping and MEV protection",
+ },
+ {
+ slug: "photon",
+ name: "Photon",
+ description: "Advanced Solana trading terminal with wallet tracking",
+ },
+ {
+ slug: "maestro",
+ name: "Maestro",
+ description: "Multi-chain Telegram trading bot with limit orders",
+ },
+ {
+ slug: "banana-gun",
+ name: "Banana Gun",
+ description: "Multi-chain Telegram bot for memecoins and EVM tokens",
+ },
+ {
+ slug: "bullx",
+ name: "BullX",
+ description: "Multi-chain terminal for memecoins on Solana and EVM",
+ },
+] as const;
+
+const GROUPS = [
+ {
+ label: "Volume & activity",
+ items: [
+ {
+ slug: "solana-trading-platform-wars",
+ title: "Trading platform volume",
+ description:
+ "24h volume for pump.fun, GMGN, Axiom, FOMO and Telegram bots",
+ },
+ {
+ slug: "solana-dex-volume",
+ title: "DEX volume & protocol revenue",
+ description: "24h trading volume and protocol fees from DeFiLlama",
+ },
+ {
+ slug: "solana-unique-traders",
+ title: "Unique traders",
+ description: "Unique swap transactions per platform in the last 24h",
+ },
+ {
+ slug: "solana-avg-trade-size",
+ title: "Average trade size",
+ description: "Average swap size in USD per platform",
+ },
+ ],
+ },
+ {
+ label: "Launchpads",
+ items: [
+ {
+ slug: "solana-launchpad-wars",
+ title: "Launchpad volume",
+ description:
+ "24h volume for pump.fun, Flap, Bankr and other bonding-curve programs",
+ },
+ ],
+ },
+ {
+ label: "Fees & execution",
+ items: [
+ {
+ slug: "memecoin-platforms",
+ title: "Platform fee rates",
+ description:
+ "Protocol fee revenue divided by volume — who earns most per dollar traded",
+ },
+ {
+ slug: "trading-app-execution",
+ title: "Execution quality",
+ description:
+ "Priority fees, Jito bundle rates, CU price and platform fee per transaction",
+ },
+ ],
+ },
+ {
+ label: "App store",
+ items: [
+ {
+ slug: "app-store-ratings",
+ title: "iOS app store ratings",
+ description:
+ "Live Apple App Store ratings for Coinbase, Robinhood, Crypto.com and more",
+ },
+ ],
+ },
+] as const;
+
+function fmtUSD(v: number): string {
+ if (v >= 1_000_000_000) return `$${(v / 1_000_000_000).toFixed(1)}B`;
+ if (v >= 1_000_000) return `$${(v / 1_000_000).toFixed(0)}M`;
+ if (v >= 1_000) return `$${(v / 1_000).toFixed(0)}K`;
+ return `$${v.toFixed(0)}`;
+}
+
+export default async function TradingAppsHubPage() {
+ const [volumeSnap, ratingsSnap] = await Promise.all([
+ readSnapshot("solana-trading-platform-wars"),
+ readSnapshot("app-store-ratings"),
+ ]);
+
+ const topVolumePlatform = volumeSnap?.results[0];
+ const topRatedApp = ratingsSnap?.results[0];
+ const platformsTracked = new Set(
+ PRODUCTS.map((p) => p.slug)
+ ).size;
+
+ const breadcrumbLd = {
+ "@context": "https://schema.org",
+ ...buildBreadcrumbJsonLd([
+ { name: "Home", item: SITE.url },
+ { name: "Trading Apps", item: `${SITE.url}/trading-apps` },
+ ]),
+ };
+
+ const itemListLd = {
+ "@context": "https://schema.org",
+ "@type": "ItemList",
+ name: "Trading app benchmarks by OpenChainBench",
+ description: DESCRIPTION,
+ numberOfItems: BENCH_SLUGS.length,
+ itemListElement: BENCH_SLUGS.map((slug, i) => ({
+ "@type": "ListItem",
+ position: i + 1,
+ name: slug,
+ url: `${SITE.url}/benchmarks/${slug}`,
+ })),
+ };
+
+ return (
+
+
+
+
+
+
+ Trading Apps
+
+
+ Solana trading app benchmarks
+
+
+ Eight independent benchmarks across four categories: 24h platform
+ volume, launchpad activity, execution fees, and app store ratings.
+ Every number is measured live from the same harness on the same
+ schedule. No marketing claims, just on-chain data.
+
+
+
+ {BENCH_SLUGS.slice(0, 5).map((slug) => (
+
+
+ Bench
+
+ {slug}
+
+ ))}
+ {BENCH_SLUGS.length > 5 && (
+
+ +{BENCH_SLUGS.length - 5} more
+
+ )}
+
+
+
+ {/* KPI strip */}
+
+
+ {/* Product grid */}
+
+
+ Platforms covered
+
+
+ {PRODUCTS.map((product) => (
+
+
+
+ {product.description}
+
+
+ ))}
+
+
+
+ {/* Benchmarks grouped list */}
+
+
+ Benchmarks
+
+
+ {GROUPS.map((group) => (
+
+
+ {group.label}
+
+
+ {group.items.map((item, i) => (
+
+ {i > 0 &&
}
+
+
+
+ {item.title}
+
+
+ {item.description}
+
+
+
+
+
+
+
+ ))}
+
+
+ ))}
+
+
+
+
+
+ Methodology
+
+
+ Volume figures are pulled from on-chain program activity and
+ DeFiLlama aggregates. Platform fee rates compare fee revenue to
+ reported volume over the same 24h window. Execution quality probes
+ submit a representative transaction per platform and records the
+ priority fee, Jito bundle cost, and compute unit price. App store
+ ratings are fetched directly from the Apple App Store API. All
+ harnesses are open source on{" "}
+
+ GitHub
+
+ . Data released under{" "}
+
+ CC BY 4.0
+
+ .
+
+
+
+ );
+}
+
+function KpiCard({
+ label,
+ value,
+ accent,
+ tip,
+}: {
+ label: string;
+ value: string;
+ accent?: string;
+ tip?: string;
+}) {
+ return (
+
+
+ {accent && (
+
+ )}
+ {label}
+
+
+ {value}
+
+
+ );
+}
diff --git a/src/components/solana-exec-table.tsx b/src/components/solana-exec-table.tsx
deleted file mode 100644
index d6cce78c..00000000
--- a/src/components/solana-exec-table.tsx
+++ /dev/null
@@ -1,156 +0,0 @@
-"use client";
-
-import { useState } from "react";
-import { logoPath } from "@/lib/logo-manifest";
-import Image from "next/image";
-import type { ExecPlatformRow, ExecWindowStats } from "@/lib/solana-exec";
-import { PLATFORM_DISPLAY, fmtCUPrice, lamportsToSOL } from "@/lib/solana-exec";
-
-const WINDOWS = [
- { key: "24h", label: "24h" },
- { key: "7d", label: "7d" },
- { key: "30d", label: "30d" },
-];
-
-const LOGO_KEY: Record = {
- "pump.fun": "pump-portal", // closest available logo
- "fomo": "fomo",
- "axiom": "axiom",
- "gmgn": "gmgn",
-};
-
-function Dash() {
- return — ;
-}
-
-function fmtCount(n: number): string {
- if (n === 0) return "—";
- if (n >= 1e6) return `${(n / 1e6).toFixed(1)}M`;
- if (n >= 1e3) return `${(n / 1e3).toFixed(1)}K`;
- return String(n);
-}
-
-function fmtPct(r: number): string {
- if (r === 0) return "—";
- return `${(r * 100).toFixed(1)}%`;
-}
-
-export function SolanaExecTable({
- platforms,
- updatedAt,
-}: {
- platforms: ExecPlatformRow[];
- updatedAt: string | null;
-}) {
- const [win, setWin] = useState("24h");
-
- if (platforms.length === 0) {
- return (
-
- No data yet — collector is warming up.
-
- );
- }
-
- const sorted = [...platforms].sort(
- (a, b) => (b.windows[win]?.txCount ?? 0) - (a.windows[win]?.txCount ?? 0),
- );
-
- return (
-
-
-
- {WINDOWS.map((w) => (
- setWin(w.key)}
- className={`px-3 py-2 text-sm font-mono border-b-2 transition-colors ${
- win === w.key
- ? "border-accent text-ink font-medium"
- : "border-transparent text-ink-muted hover:text-ink-soft"
- }`}
- >
- {w.label}
-
- ))}
-
- {updatedAt && (
-
- Updated {new Date(updatedAt).toLocaleString()}
-
- )}
-
-
-
-
-
-
- #
- Platform
- Txs
- Avg priority fee
- CU price p50/p95
- Jito rate
- Avg platform fee
-
-
-
- {sorted.map((p, i) => {
- const wm: ExecWindowStats | undefined = p.windows[win];
- const logo = logoPath(LOGO_KEY[p.platform] ?? p.platform);
-
- return (
-
-
- {i + 1}
-
-
-
- {logo && (
-
- )}
-
- {PLATFORM_DISPLAY[p.platform] ?? p.platform}
-
-
-
-
- {wm?.txCount ? fmtCount(wm.txCount) : }
-
-
- {wm?.avgPriorityFeeLamports
- ? `${Math.round(wm.avgPriorityFeeLamports).toLocaleString()} L`
- : }
-
-
- {wm?.p50CUPriceMicro
- ? `${fmtCUPrice(wm.p50CUPriceMicro)} / ${fmtCUPrice(wm.p95CUPriceMicro)}`
- : }
-
-
- {wm?.jitoRate != null && wm.jitoRate > 0 ? fmtPct(wm.jitoRate) : }
-
-
- {wm?.avgPlatformFeeLamports
- ? `${lamportsToSOL(wm.avgPlatformFeeLamports)} SOL`
- : }
-
-
- );
- })}
-
-
-
-
- );
-}