From e30da0732d3a91348c823a47646903251221cfd4 Mon Sep 17 00:00:00 2001 From: Florent Tapponnier <160007691+Flotapponnier@users.noreply.github.com> Date: Wed, 12 Aug 2026 21:31:36 +0200 Subject: [PATCH 1/2] =?UTF-8?q?fix:=20compare=20page=20Lia=20V3=20?= =?UTF-8?q?=E2=80=94=20verb/verdict/provisional/neutral/fee-disclaimer?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- benchmarks/memecoin-platforms.yml | 3 +++ src/app/compare/[slug]/page.tsx | 36 +++++++++++++++++++-------- src/components/compare-bench-card.tsx | 16 +++++++++--- 3 files changed, 42 insertions(+), 13 deletions(-) diff --git a/benchmarks/memecoin-platforms.yml b/benchmarks/memecoin-platforms.yml index 7adfe90c..4a373a40 100644 --- a/benchmarks/memecoin-platforms.yml +++ b/benchmarks/memecoin-platforms.yml @@ -11,6 +11,9 @@ status: live metric: Avg total fee unit: pct +disclaimer: | + Explicit platform fee only — pool-embedded costs (bonding-curve pricing, AMM LP fees) are not captured and apply equally across all frontends. The effective round-trip cost of trading may differ from the figure shown. See methodology for full scope. + source: https://github.com/ChainBench/OpenChainBench/tree/main/harnesses/memecoin-platforms seo_intro: | diff --git a/src/app/compare/[slug]/page.tsx b/src/app/compare/[slug]/page.tsx index d8ed7cfc..72de9fb0 100644 --- a/src/app/compare/[slug]/page.tsx +++ b/src/app/compare/[slug]/page.tsx @@ -296,17 +296,24 @@ type ChainRegionEntry = BreakdownRow & { type SharedBench = CompareBench; -/** Maps a bench to the right comparative verb for FAQ questions. - * "faster" works for latency/time; cost metrics need "cheaper"; - * higher-is-better metrics (success rate, uptime) need "more reliable". */ +/** Maps a bench to the right comparative verb for FAQ questions. */ function verbForBench(bench: SharedBench): string { const unit = (bench.unit ?? "").toLowerCase(); if (unit === "usd" || unit === "gwei" || unit === "bps" || unit === "bp") return "cheaper"; if ((unit === "pct" || unit === "sol") && !bench.higherIsBetter) return "cheaper"; + if (unit === "x" && bench.higherIsBetter) return "higher-rated"; + if (unit === "count" && bench.higherIsBetter) return "more active"; if (bench.higherIsBetter) return "more reliable"; return "faster"; } +/** Strips the provider-list parenthetical from bench titles for use in + * FAQ questions: "Cheapest platform (A vs B vs C)" → "Cheapest platform". */ +function shortBenchTitle(title: string): string { + const idx = title.indexOf(" ("); + return idx > 0 ? title.slice(0, idx) : title; +} + /** Sort comparator that respects `higherIsBetter`. Returns: * "a" if A leads, "b" if B leads, "tie" if both equal. */ function decideWinner( @@ -365,9 +372,13 @@ function buildComparisonProse( const parts: string[] = []; if (aWinTitles.length === 0) { - parts.push(`${bName} leads on all ${total} live ${total === 1 ? "benchmark" : "benchmarks"}.`); + const word = total === 1 ? "the only live benchmark" : `all ${total} live benchmarks`; + parts.push(`${bName} leads on ${word}.`); } else if (bWinTitles.length === 0) { - parts.push(`${aName} leads on all ${total} live ${total === 1 ? "benchmark" : "benchmarks"}.`); + const word = total === 1 ? "the only live benchmark" : `all ${total} live benchmarks`; + parts.push(`${aName} leads on ${word}.`); + } else if (aWinTitles.length === bWinTitles.length) { + parts.push(`Split: ${aName} leads on ${aWinTitles.slice(0, 2).join(", ")}; ${bName} leads on ${bWinTitles.slice(0, 2).join(", ")}.`); } else { parts.push( `${aName} leads on ${aWinTitles.length} of ${total} shared benchmarks, ${bName} on ${bWinTitles.length}${ties > 0 ? ` (${ties} tied)` : ""}.`, @@ -648,6 +659,8 @@ async function buildSharedBenches( higherIsBetter: p.higherIsBetter, aValue: aVal, bValue: bVal, + // "count" panels are size metrics — no win/lose coloring. + neutral: (p.unit ?? "").toLowerCase() === "count", }, ]; }); @@ -667,7 +680,8 @@ async function buildSharedBenches( chainBreakdown, regionBreakdown, panelScopes, - } satisfies SharedBench; + note: fullBench.disclaimer ?? undefined, + } as SharedBench; }), ); const result = built.filter((b): b is SharedBench => b !== null); @@ -803,15 +817,17 @@ export default async function ComparePage({ a: `${a.name} and ${b.name} are compared on ${shared.length} shared OpenChainBench benchmarks. ${aWinsBench ? `${a.name} leads on ${aWinsBench.title}.` : ""} ${bWinsBench ? `${b.name} leads on ${bWinsBench.title}.` : ""} See the live table on this page for every metric.`.trim(), }); if (aWinsBench) { + const st = shortBenchTitle(aWinsBench.title); faqEntries.push({ - q: `Which is ${verbForBench(aWinsBench)} on ${aWinsBench.title}, ${a.name} or ${b.name}?`, - a: `On the ${aWinsBench.title} benchmark, ${a.name} leads at ${fmtUnit(aWinsBench.aResult.p50, aWinsBench.unit)} versus ${b.name} at ${fmtUnit(aWinsBench.bResult.p50, aWinsBench.unit)}. Live measurement is updated continuously by the OpenChainBench harness.`, + q: `Which is ${verbForBench(aWinsBench)} on ${st}, ${a.name} or ${b.name}?`, + a: `On the ${st} benchmark, ${a.name} leads at ${fmtUnit(aWinsBench.aResult.p50, aWinsBench.unit)} versus ${b.name} at ${fmtUnit(aWinsBench.bResult.p50, aWinsBench.unit)}. Live measurement is updated continuously by the OpenChainBench harness.`, }); } if (bWinsBench) { + const st = shortBenchTitle(bWinsBench.title); faqEntries.push({ - q: `Which is ${verbForBench(bWinsBench)} on ${bWinsBench.title}, ${a.name} or ${b.name}?`, - a: `On the ${bWinsBench.title} benchmark, ${b.name} leads at ${fmtUnit(bWinsBench.bResult.p50, bWinsBench.unit)} versus ${a.name} at ${fmtUnit(bWinsBench.aResult.p50, bWinsBench.unit)}. Live measurement is updated continuously by the OpenChainBench harness.`, + q: `Which is ${verbForBench(bWinsBench)} on ${st}, ${a.name} or ${b.name}?`, + a: `On the ${st} benchmark, ${b.name} leads at ${fmtUnit(bWinsBench.bResult.p50, bWinsBench.unit)} versus ${a.name} at ${fmtUnit(bWinsBench.aResult.p50, bWinsBench.unit)}. Live measurement is updated continuously by the OpenChainBench harness.`, }); } faqEntries.push({ diff --git a/src/components/compare-bench-card.tsx b/src/components/compare-bench-card.tsx index eaa79fb2..d88595ce 100644 --- a/src/components/compare-bench-card.tsx +++ b/src/components/compare-bench-card.tsx @@ -32,6 +32,8 @@ export type PanelScope = { higherIsBetter: boolean; aValue: number; bValue: number; + /** When true, don't apply win/lose coloring — size/scale metric, not quality. */ + neutral?: boolean; }; export type CompareBench = { @@ -49,6 +51,8 @@ export type CompareBench = { regionBreakdown: BreakdownRow[]; chainRegionMatrix: ChainRegionEntry[]; panelScopes: PanelScope[]; + /** Optional in-panel note shown below the metric cards (e.g. scope clarification). */ + note?: string; }; function decideWinner( @@ -140,7 +144,13 @@ export function CompareBenchCard({ )} -