From 09a3e8cd4f18e629254016308fa2027ab86e67a0 Mon Sep 17 00:00:00 2001 From: Flotapponnier <160007691+Flotapponnier@users.noreply.github.com> Date: Sat, 18 Jul 2026 19:25:24 +0200 Subject: [PATCH] consolidate solana-official + solana-labs into 'solana' provider (#1299) Both slugs pointed at api.mainnet-beta.solana.com and rendered as Solana Labs branding: - solana-official (rpc-capabilities) - solana-labs (ws-head-latency) Neither was a distinct product from the Solana chain brand. Two /products/* pages (solana-official, solana-labs) duplicated content that logically lives on /chains/solana. Consolidation: - Harness config: rename Prom provider label to 'solana' on both harnesses - Spec YAMLs (solana-rpc, ws-head-latency-solana): rename provider slug and all query labels to 'solana' - Registry: delete solana-official entry (redundant with existing 'solana' entry) - PRODUCT_ALIASES: solana-official -> solana + solana-labs -> solana so legacy inbound URLs resolve to canonical - Logo manifest: alias solana-labs to solana (solana-official already aliased) Post-deploy: /products/solana-official and /products/solana-labs will 308-redirect to /products/solana which 308-redirects to /chains/solana (consistent with the arbitrum/base/optimism-official pattern already in place). No 404s on old inbound links. Co-authored-by: Florent Tapponnier --- benchmarks/solana-rpc.yml | 32 +++++++++---------- benchmarks/ws-head-latency-solana.yml | 30 ++++++++--------- .../rpc-capabilities/cmd/script/config.go | 2 +- .../ws-head-latency/cmd/script/config.go | 2 +- src/data/provider-registry.ts | 6 ---- src/lib/logo-manifest.ts | 2 ++ src/lib/providers.ts | 6 ++++ 7 files changed, 41 insertions(+), 39 deletions(-) diff --git a/benchmarks/solana-rpc.yml b/benchmarks/solana-rpc.yml index 63a32c21..bce3f755 100644 --- a/benchmarks/solana-rpc.yml +++ b/benchmarks/solana-rpc.yml @@ -41,7 +41,7 @@ methodology: findings: - "{{best_name}} currently leads free Solana RPC at {{best_p50}} (getSlot p50, 24h) across 5 measured providers." - - "{{name:solana-official}} ({{p50:solana-official}}) is the endpoint every tutorial pastes. Solana Labs documents its limits at 100 requests per 10 seconds per IP, generous for development and exactly the kind of endpoint this bench exists to sanity-check." + - "{{name:solana}} ({{p50:solana}}) is the endpoint every tutorial pastes. Solana Labs documents its limits at 100 requests per 10 seconds per IP, generous for development and exactly the kind of endpoint this bench exists to sanity-check." - "{{name:publicnode}} ({{p50:publicnode}}) extends its EVM cluster footprint to Solana from the same Allnodes infrastructure, and arrives with the credibility of leading a large share of the EVM per-chain boards." - "{{name:lava}} ({{p50:lava}}) routes through the Lava gateway mesh, the same architecture as its Ethereum and Arbitrum endpoints; expect higher variance than single-origin providers." - "{{name:leorpc}} ({{p50:leorpc}}) and {{name:solanavibestation}} ({{p50:solanavibestation}}) are the community tier: smaller operations whose continued keyless availability this bench monitors live rather than assumes." @@ -64,7 +64,7 @@ prometheus: window: 24h freshness_metric: rpc_latency_milliseconds -rank_matrix_query: avg by (provider, region) (ocb:rpc_latency_milliseconds:p50_24h{provider=~"solana-official|publicnode|lava|leorpc|solanavibestation", chain="solana"}) +rank_matrix_query: avg by (provider, region) (ocb:rpc_latency_milliseconds:p50_24h{provider=~"solana|publicnode|lava|leorpc|solanavibestation", chain="solana"}) dimensions: region: @@ -74,28 +74,28 @@ dimensions: - { value: sgp, label: Singapore } providers: - - slug: solana-official + - slug: solana name: Solana Labs tag: Chain-official api.mainnet-beta.solana.com, 100 req per 10s documented formula: "50th percentile over 24h of client-side round-trip latency (ms) for a single `getSlot` POST sent every 60s from 3 regions (us-east + eu-west + sgp) to api.mainnet-beta.solana.com." queries: - p50: avg(ocb:rpc_latency_milliseconds:p50_24h{provider="solana-official", chain="solana"}) - p90: avg(ocb:rpc_latency_milliseconds:p90_24h{provider="solana-official", chain="solana"}) - p99: avg(ocb:rpc_latency_milliseconds:p99_24h{provider="solana-official", chain="solana"}) - mean: avg(ocb:rpc_latency_milliseconds:mean_24h{provider="solana-official", chain="solana"}) - success: sum(ocb:rpc_call:ok_rate_24h{provider="solana-official", chain="solana"}) / sum(ocb:rpc_call:rate_24h{provider="solana-official", chain="solana"}) - sample_size: sum(ocb:rpc_call:increase_24h{provider="solana-official", chain="solana"}) - series: avg(avg_over_time(rpc_latency_milliseconds{provider="solana-official", chain="solana"}[1h])) + p50: avg(ocb:rpc_latency_milliseconds:p50_24h{provider="solana", chain="solana"}) + p90: avg(ocb:rpc_latency_milliseconds:p90_24h{provider="solana", chain="solana"}) + p99: avg(ocb:rpc_latency_milliseconds:p99_24h{provider="solana", chain="solana"}) + mean: avg(ocb:rpc_latency_milliseconds:mean_24h{provider="solana", chain="solana"}) + success: sum(ocb:rpc_call:ok_rate_24h{provider="solana", chain="solana"}) / sum(ocb:rpc_call:rate_24h{provider="solana", chain="solana"}) + sample_size: sum(ocb:rpc_call:increase_24h{provider="solana", chain="solana"}) + series: avg(avg_over_time(rpc_latency_milliseconds{provider="solana", chain="solana"}[1h])) regions: - region: us-east - p50: avg(ocb:rpc_latency_milliseconds:p50_24h{provider="solana-official", chain="solana", region="us-east"}) - series: avg_over_time(rpc_latency_milliseconds{provider="solana-official", chain="solana", region="us-east"}[1h]) + p50: avg(ocb:rpc_latency_milliseconds:p50_24h{provider="solana", chain="solana", region="us-east"}) + series: avg_over_time(rpc_latency_milliseconds{provider="solana", chain="solana", region="us-east"}[1h]) - region: eu-west - p50: avg(ocb:rpc_latency_milliseconds:p50_24h{provider="solana-official", chain="solana", region="eu-west"}) - series: avg_over_time(rpc_latency_milliseconds{provider="solana-official", chain="solana", region="eu-west"}[1h]) + p50: avg(ocb:rpc_latency_milliseconds:p50_24h{provider="solana", chain="solana", region="eu-west"}) + series: avg_over_time(rpc_latency_milliseconds{provider="solana", chain="solana", region="eu-west"}[1h]) - region: ap-southeast - p50: avg(ocb:rpc_latency_milliseconds:p50_24h{provider="solana-official", chain="solana", region="sgp"}) - series: avg_over_time(rpc_latency_milliseconds{provider="solana-official", chain="solana", region="sgp"}[1h]) + p50: avg(ocb:rpc_latency_milliseconds:p50_24h{provider="solana", chain="solana", region="sgp"}) + series: avg_over_time(rpc_latency_milliseconds{provider="solana", chain="solana", region="sgp"}[1h]) - slug: publicnode name: PublicNode diff --git a/benchmarks/ws-head-latency-solana.yml b/benchmarks/ws-head-latency-solana.yml index 284c6319..d2576b05 100644 --- a/benchmarks/ws-head-latency-solana.yml +++ b/benchmarks/ws-head-latency-solana.yml @@ -52,7 +52,7 @@ methodology: findings: - "{{best_name}} leads the Solana cohort at {{best_p50}} (p50, 24 h) across {{count}} measured providers. Solana's ~400ms cadence means each provider gets 30 times more samples per unit time than the Ethereum sibling; the distribution here has very little tail noise for the same 24h window." - - "{{name:solana-labs}} versus {{name:publicnode}}: the Solana Foundation's public endpoint and PublicNode's Solana gateway measured on identical terms. A latency-sensitive Solana integration should read the win rate alongside p50 to see which endpoint delivers slot N first most often." + - "{{name:solana}} versus {{name:publicnode}}: the Solana Foundation's public endpoint and PublicNode's Solana gateway measured on identical terms. A latency-sensitive Solana integration should read the win rate alongside p50 to see which endpoint delivers slot N first most often." - "The p99 column matters more on Solana than on any EVM chain in the cluster: at ~400ms slots, a p99 above 1 second means the provider is routinely 2-3 slots behind the leader. That gap is the exact window where a keeper or liquidator loses to a co-located competitor." - "Cross-chain comparison of absolute lag numbers is not meaningful: Solana runs at 400ms slots, Base at 2s, Ethereum at 12s. Use each per-chain leaderboard on its own terms and the parent [ws-head-latency](https://openchainbench.com/benchmarks/ws-head-latency-ethereum) page for the Ethereum reference." @@ -111,25 +111,25 @@ providers: p50: histogram_quantile(0.50, sum by (le) (rate(ws_head_lag_milliseconds_bucket{provider="publicnode", chain="solana", region="sgp"}[24h]))) series: histogram_quantile(0.50, sum by (le) (rate(ws_head_lag_milliseconds_bucket{provider="publicnode", chain="solana", region="sgp"}[1h]))) - - slug: solana-labs + - slug: solana name: Solana Foundation tag: Keyless WS, wss://api.mainnet-beta.solana.com formula: "Median ms behind the earliest provider to push each Solana slotSubscribe notification, from one persistent WebSocket per provider on the same eu-west host, histogram_quantile over 24h. Lag is relative to the per-slot winner." queries: - p50: histogram_quantile(0.50, sum by (le) (rate(ws_head_lag_milliseconds_bucket{provider="solana-labs", chain="solana"}[24h]))) - p90: histogram_quantile(0.90, sum by (le) (rate(ws_head_lag_milliseconds_bucket{provider="solana-labs", chain="solana"}[24h]))) - p99: histogram_quantile(0.99, sum by (le) (rate(ws_head_lag_milliseconds_bucket{provider="solana-labs", chain="solana"}[24h]))) - mean: sum(rate(ws_head_lag_milliseconds_sum{provider="solana-labs", chain="solana"}[24h])) / sum(rate(ws_head_lag_milliseconds_count{provider="solana-labs", chain="solana"}[24h])) - success: clamp_max(sum(increase(ws_head_blocks_seen_total{provider="solana-labs", chain="solana"}[24h])) / max(sum by (provider) (increase(ws_head_blocks_seen_total{chain="solana"}[24h]))), 1) - sample_size: sum(increase(ws_head_lag_milliseconds_count{provider="solana-labs", chain="solana"}[24h])) - series: histogram_quantile(0.50, sum by (le) (rate(ws_head_lag_milliseconds_bucket{provider="solana-labs", chain="solana"}[1h]))) + p50: histogram_quantile(0.50, sum by (le) (rate(ws_head_lag_milliseconds_bucket{provider="solana", chain="solana"}[24h]))) + p90: histogram_quantile(0.90, sum by (le) (rate(ws_head_lag_milliseconds_bucket{provider="solana", chain="solana"}[24h]))) + p99: histogram_quantile(0.99, sum by (le) (rate(ws_head_lag_milliseconds_bucket{provider="solana", chain="solana"}[24h]))) + mean: sum(rate(ws_head_lag_milliseconds_sum{provider="solana", chain="solana"}[24h])) / sum(rate(ws_head_lag_milliseconds_count{provider="solana", chain="solana"}[24h])) + success: clamp_max(sum(increase(ws_head_blocks_seen_total{provider="solana", chain="solana"}[24h])) / max(sum by (provider) (increase(ws_head_blocks_seen_total{chain="solana"}[24h]))), 1) + sample_size: sum(increase(ws_head_lag_milliseconds_count{provider="solana", chain="solana"}[24h])) + series: histogram_quantile(0.50, sum by (le) (rate(ws_head_lag_milliseconds_bucket{provider="solana", chain="solana"}[1h]))) regions: - region: us-east - p50: histogram_quantile(0.50, sum by (le) (rate(ws_head_lag_milliseconds_bucket{provider="solana-labs", chain="solana", region="us-east"}[24h]))) - series: histogram_quantile(0.50, sum by (le) (rate(ws_head_lag_milliseconds_bucket{provider="solana-labs", chain="solana", region="us-east"}[1h]))) + p50: histogram_quantile(0.50, sum by (le) (rate(ws_head_lag_milliseconds_bucket{provider="solana", chain="solana", region="us-east"}[24h]))) + series: histogram_quantile(0.50, sum by (le) (rate(ws_head_lag_milliseconds_bucket{provider="solana", chain="solana", region="us-east"}[1h]))) - region: eu-west - p50: histogram_quantile(0.50, sum by (le) (rate(ws_head_lag_milliseconds_bucket{provider="solana-labs", chain="solana", region="eu-west"}[24h]))) - series: histogram_quantile(0.50, sum by (le) (rate(ws_head_lag_milliseconds_bucket{provider="solana-labs", chain="solana", region="eu-west"}[1h]))) + p50: histogram_quantile(0.50, sum by (le) (rate(ws_head_lag_milliseconds_bucket{provider="solana", chain="solana", region="eu-west"}[24h]))) + series: histogram_quantile(0.50, sum by (le) (rate(ws_head_lag_milliseconds_bucket{provider="solana", chain="solana", region="eu-west"}[1h]))) - region: ap-southeast - p50: histogram_quantile(0.50, sum by (le) (rate(ws_head_lag_milliseconds_bucket{provider="solana-labs", chain="solana", region="sgp"}[24h]))) - series: histogram_quantile(0.50, sum by (le) (rate(ws_head_lag_milliseconds_bucket{provider="solana-labs", chain="solana", region="sgp"}[1h]))) + p50: histogram_quantile(0.50, sum by (le) (rate(ws_head_lag_milliseconds_bucket{provider="solana", chain="solana", region="sgp"}[24h]))) + series: histogram_quantile(0.50, sum by (le) (rate(ws_head_lag_milliseconds_bucket{provider="solana", chain="solana", region="sgp"}[1h]))) diff --git a/harnesses/rpc-capabilities/cmd/script/config.go b/harnesses/rpc-capabilities/cmd/script/config.go index c4656586..8847bf37 100644 --- a/harnesses/rpc-capabilities/cmd/script/config.go +++ b/harnesses/rpc-capabilities/cmd/script/config.go @@ -107,7 +107,7 @@ func chains() []Chain { Name: "Solana", Kind: "solana", Providers: []Provider{ - {Slug: "solana-official", Name: "Solana Labs", URL: envDefault("RPC_URL_SOLANA_OFFICIAL", "https://api.mainnet-beta.solana.com")}, + {Slug: "solana", Name: "Solana", URL: envDefault("RPC_URL_SOLANA_OFFICIAL", "https://api.mainnet-beta.solana.com")}, {Slug: "publicnode", Name: "PublicNode", URL: envDefault("RPC_URL_SOLANA_PUBLICNODE", "https://solana-rpc.publicnode.com")}, {Slug: "lava", Name: "Lava", URL: envDefault("RPC_URL_SOLANA_LAVA", "https://solana.lava.build")}, {Slug: "leorpc", Name: "LeoRPC", URL: envDefault("RPC_URL_SOLANA_LEORPC", "https://solana.leorpc.com/?api_key=FREE")}, diff --git a/harnesses/ws-head-latency/cmd/script/config.go b/harnesses/ws-head-latency/cmd/script/config.go index 15ad5b85..915deef0 100644 --- a/harnesses/ws-head-latency/cmd/script/config.go +++ b/harnesses/ws-head-latency/cmd/script/config.go @@ -39,7 +39,7 @@ func endpoints() []Endpoint { {Provider: "drpc", Chain: "solana", Kind: "solana", URL: envDefault("WS_URL_DRPC_SOLANA", "wss://solana.drpc.org")}, {Provider: "tenderly", Chain: "ethereum", Kind: "evm", URL: envDefault("WS_URL_TENDERLY_ETHEREUM", "wss://mainnet.gateway.tenderly.co")}, {Provider: "onfinality", Chain: "ethereum", Kind: "evm", URL: envDefault("WS_URL_ONFINALITY_ETHEREUM", "wss://eth.api.onfinality.io/public-ws")}, - {Provider: "solana-labs", Chain: "solana", Kind: "solana", URL: envDefault("WS_URL_SOLANALABS_SOLANA", "wss://api.mainnet-beta.solana.com")}, + {Provider: "solana", Chain: "solana", Kind: "solana", URL: envDefault("WS_URL_SOLANALABS_SOLANA", "wss://api.mainnet-beta.solana.com")}, } // Keyed providers, skipped when the env var is unset. URLs carry the // key inline (e.g. wss://eth-mainnet.g.alchemy.com/v2/) so they diff --git a/src/data/provider-registry.ts b/src/data/provider-registry.ts index 18dda033..bb6a19b2 100644 --- a/src/data/provider-registry.ts +++ b/src/data/provider-registry.ts @@ -214,12 +214,6 @@ export const PROVIDER_REGISTRY: Record = { "Solana transaction landing service by Temporal Labs. Direct-to-leader submission from 9 colocated regions, tip paid only on successful landing.", twitter: "@temporal_xyz", }, - "solana-official": { - url: "https://solana.com", - description: - "api.mainnet-beta.solana.com is the chain-official public RPC operated by Solana Labs, the endpoint every tutorial and SDK defaults to, documented at roughly 100 requests per 10 seconds per IP.", - twitter: "@solana", - }, leorpc: { url: "https://leorpc.com", description: diff --git a/src/lib/logo-manifest.ts b/src/lib/logo-manifest.ts index a81714b3..0f81e592 100644 --- a/src/lib/logo-manifest.ts +++ b/src/lib/logo-manifest.ts @@ -382,6 +382,8 @@ const ALIASES: Record = { // Long-tail RPC cluster (055-066). "sonic-official": "sonic", "monad-official": "monad", + "solana-official": "solana", + "solana-labs": "solana", "polkadot-official": "parity", hood: "robinhood", coin: "coinbase", diff --git a/src/lib/providers.ts b/src/lib/providers.ts index 01043029..3ce54b77 100644 --- a/src/lib/providers.ts +++ b/src/lib/providers.ts @@ -41,6 +41,12 @@ const PRODUCT_ALIASES: Record = { "avalanche-official": "avalanche", "base-official": "base", "optimism-official": "optimism", + // Solana chain-official RPC collapses to the Solana chain brand. + // Legacy slugs `solana-official` (rpc-capabilities) and `solana-labs` + // (ws-head-latency) resolve to the same canonical entry so old inbound + // links keep working while the harnesses re-emit under provider="solana". + "solana-official": "solana", + "solana-labs": "solana", // Polkadot's "official" endpoint is Parity-operated, so the product // page for the endpoint slug collapses to the Parity brand rather // than a synthetic "Polkadot Foundation RPC" entry (there is no such