From fd7a68de187887e5764e0b29e1b92dea6ed99ce1 Mon Sep 17 00:00:00 2001 From: Flotapponnier <160007691+Flotapponnier@users.noreply.github.com> Date: Fri, 9 Oct 2026 17:58:54 +0200 Subject: [PATCH 1/2] Dwellir joins the private cohort on the eight EVM chains Dwellir was already half-wired: a canonical name, a registry entry and a logo were committed, and only the key was missing. The key arrived, so this adds the provider everywhere it can actually be measured. Verified against the live endpoints before writing a line of spec: all eight EVM chains answer eth_getBlockByNumber with the key, including the three where our private cohort was thinnest. Hyperliquid, Robinhood Chain and Arc get their first new keyed provider since the cohort was created. Solana is deliberately absent. Dwellir publishes no Solana endpoint, their networks index does not list it, and the harness skips a (provider, chain) cell whose URL variable is unset, so that page keeps four providers with no special casing. Budget: the free tier is 100k responses a day, 1 response = 1 credit, so ~3M a month across the three regions sharing the key. Eight chains cost 173k per region per month at the 120 s cadence. The 1M per-region default is a runaway guard, not a quota. The logo was replaced, and that is worth explaining. The committed dwellir.svg is the vendor's wordmark on an A4 artboard whose artwork runs past the viewBox: it renders as a cropped "DWELL". Rendering it is how I found out. Their only square mark is the favicon, so that is what ships, at 128px, which is what getblock and chainstack already do. preflight PASS on all nine pages including the 8 new dwellir-cold slugs, after it caught the alias being written into the path map instead of ALIASES: the same blank-chip bug this guard was written for. pnpm validate clean, tsc clean, 495 tests pass, go build and go vet clean. --- benchmarks/arbitrum-rpc.yml | 47 ++++++++ benchmarks/arc-rpc.yml | 47 ++++++++ benchmarks/base-rpc.yml | 47 ++++++++ benchmarks/bnb-rpc.yml | 47 ++++++++ benchmarks/ethereum-rpc.yml | 47 ++++++++ benchmarks/hyperliquid-rpc.yml | 47 ++++++++ benchmarks/polygon-rpc.yml | 47 ++++++++ benchmarks/robinhood-rpc.yml | 47 ++++++++ .../rpc-keyed-latency/cmd/script/config.go | 9 +- public/logos/dwellir.png | Bin 0 -> 14680 bytes public/logos/dwellir.svg | 101 ------------------ src/lib/logo-manifest.ts | 3 +- 12 files changed, 386 insertions(+), 103 deletions(-) create mode 100644 public/logos/dwellir.png delete mode 100644 public/logos/dwellir.svg diff --git a/benchmarks/arbitrum-rpc.yml b/benchmarks/arbitrum-rpc.yml index 216cf1f5a..4fdfe4def 100644 --- a/benchmarks/arbitrum-rpc.yml +++ b/benchmarks/arbitrum-rpc.yml @@ -339,6 +339,30 @@ providers: p50: avg(ocb:rpc_latency_milliseconds:p50_24h{provider="quicknode",chain="arbitrum",tier="keyed",region="sgp"}) series: avg(avg_over_time(rpc_latency_milliseconds{provider="quicknode",chain="arbitrum",tier="keyed",region="sgp"}[1h])) + - slug: dwellir + name: Dwellir + tier: keyed + tag: Free plan key, 100k responses per day, plan disclosed + formula: "p50 over 24h of round-trip latency (ms) for eth_getBlockByNumber probed every 120 s from us-east, eu-west and Singapore on Dwellir's keyed Arbitrum endpoint." + queries: + p50: avg(ocb:rpc_latency_milliseconds:p50_24h{provider="dwellir",chain="arbitrum",tier="keyed"}) + p90: avg(ocb:rpc_latency_milliseconds:p90_24h{provider="dwellir",chain="arbitrum",tier="keyed"}) + p99: avg(ocb:rpc_latency_milliseconds:p99_24h{provider="dwellir",chain="arbitrum",tier="keyed"}) + mean: avg(ocb:rpc_latency_milliseconds:mean_24h{provider="dwellir",chain="arbitrum",tier="keyed"}) + success: sum(ocb:rpc_call:ok_rate_24h{provider="dwellir",chain="arbitrum",tier="keyed"}) / sum(ocb:rpc_call:rate_24h{provider="dwellir",chain="arbitrum",tier="keyed"}) + sample_size: sum(ocb:rpc_call:increase_24h{provider="dwellir",chain="arbitrum",tier="keyed"}) + series: avg(avg_over_time(rpc_latency_milliseconds{provider="dwellir",chain="arbitrum",tier="keyed"}[1h])) + regions: + - region: us-east + p50: avg(ocb:rpc_latency_milliseconds:p50_24h{provider="dwellir",chain="arbitrum",tier="keyed",region="us-east"}) + series: avg(avg_over_time(rpc_latency_milliseconds{provider="dwellir",chain="arbitrum",tier="keyed",region="us-east"}[1h])) + - region: eu-west + p50: avg(ocb:rpc_latency_milliseconds:p50_24h{provider="dwellir",chain="arbitrum",tier="keyed",region="eu-west"}) + series: avg(avg_over_time(rpc_latency_milliseconds{provider="dwellir",chain="arbitrum",tier="keyed",region="eu-west"}[1h])) + - region: ap-southeast + p50: avg(ocb:rpc_latency_milliseconds:p50_24h{provider="dwellir",chain="arbitrum",tier="keyed",region="sgp"}) + series: avg(avg_over_time(rpc_latency_milliseconds{provider="dwellir",chain="arbitrum",tier="keyed",region="sgp"}[1h])) + - slug: alchemy-cold name: Alchemy tier: keyed-cold @@ -431,3 +455,26 @@ providers: - region: ap-southeast p50: avg(ocb:rpc_latency_cold_milliseconds:p50_24h{provider="quicknode",chain="arbitrum",tier="keyed",region="sgp"}) series: avg(avg_over_time(rpc_latency_cold_milliseconds{provider="quicknode",chain="arbitrum",tier="keyed",region="sgp"}[1h])) + - slug: dwellir-cold + name: Dwellir + tier: keyed-cold + tag: Same endpoint, measured on a connection that is never reused + formula: "p50 over 24h of round-trip latency (ms) for the same call on a connection that is never reused: DNS, TCP and the TLS handshake are paid every time. What a serverless or one-shot client gets." + queries: + p50: avg(ocb:rpc_latency_cold_milliseconds:p50_24h{provider="dwellir",chain="arbitrum",tier="keyed"}) + p90: avg(ocb:rpc_latency_cold_milliseconds:p90_24h{provider="dwellir",chain="arbitrum",tier="keyed"}) + p99: avg(ocb:rpc_latency_cold_milliseconds:p99_24h{provider="dwellir",chain="arbitrum",tier="keyed"}) + mean: avg(ocb:rpc_latency_cold_milliseconds:mean_24h{provider="dwellir",chain="arbitrum",tier="keyed"}) + success: sum(ocb:rpc_call:ok_rate_24h{provider="dwellir",chain="arbitrum",tier="keyed"}) / sum(ocb:rpc_call:rate_24h{provider="dwellir",chain="arbitrum",tier="keyed"}) + sample_size: sum(ocb:rpc_call:increase_24h{provider="dwellir",chain="arbitrum",tier="keyed"}) + series: avg(avg_over_time(rpc_latency_cold_milliseconds{provider="dwellir",chain="arbitrum",tier="keyed"}[1h])) + regions: + - region: us-east + p50: avg(ocb:rpc_latency_cold_milliseconds:p50_24h{provider="dwellir",chain="arbitrum",tier="keyed",region="us-east"}) + series: avg(avg_over_time(rpc_latency_cold_milliseconds{provider="dwellir",chain="arbitrum",tier="keyed",region="us-east"}[1h])) + - region: eu-west + p50: avg(ocb:rpc_latency_cold_milliseconds:p50_24h{provider="dwellir",chain="arbitrum",tier="keyed",region="eu-west"}) + series: avg(avg_over_time(rpc_latency_cold_milliseconds{provider="dwellir",chain="arbitrum",tier="keyed",region="eu-west"}[1h])) + - region: ap-southeast + p50: avg(ocb:rpc_latency_cold_milliseconds:p50_24h{provider="dwellir",chain="arbitrum",tier="keyed",region="sgp"}) + series: avg(avg_over_time(rpc_latency_cold_milliseconds{provider="dwellir",chain="arbitrum",tier="keyed",region="sgp"}[1h])) diff --git a/benchmarks/arc-rpc.yml b/benchmarks/arc-rpc.yml index ee347cb91..32953b61b 100644 --- a/benchmarks/arc-rpc.yml +++ b/benchmarks/arc-rpc.yml @@ -330,6 +330,30 @@ providers: p50: avg(ocb:rpc_latency_milliseconds:p50_24h{provider="quicknode",chain="arc",tier="keyed",region="eu-west"}) series: avg(avg_over_time(rpc_latency_milliseconds{provider="quicknode",chain="arc",tier="keyed",region="eu-west"}[1h])) + - slug: dwellir + name: Dwellir + tier: keyed + tag: Free plan key, 100k responses per day, plan disclosed + formula: "p50 over 24h of round-trip latency (ms) for eth_getBlockByNumber probed every 120 s from us-east, eu-west and Singapore on Dwellir's keyed Arc endpoint." + queries: + p50: avg(ocb:rpc_latency_milliseconds:p50_24h{provider="dwellir",chain="arc",tier="keyed"}) + p90: avg(ocb:rpc_latency_milliseconds:p90_24h{provider="dwellir",chain="arc",tier="keyed"}) + p99: avg(ocb:rpc_latency_milliseconds:p99_24h{provider="dwellir",chain="arc",tier="keyed"}) + mean: avg(ocb:rpc_latency_milliseconds:mean_24h{provider="dwellir",chain="arc",tier="keyed"}) + success: sum(ocb:rpc_call:ok_rate_24h{provider="dwellir",chain="arc",tier="keyed"}) / sum(ocb:rpc_call:rate_24h{provider="dwellir",chain="arc",tier="keyed"}) + sample_size: sum(ocb:rpc_call:increase_24h{provider="dwellir",chain="arc",tier="keyed"}) + series: avg(avg_over_time(rpc_latency_milliseconds{provider="dwellir",chain="arc",tier="keyed"}[1h])) + regions: + - region: us-east + p50: avg(ocb:rpc_latency_milliseconds:p50_24h{provider="dwellir",chain="arc",tier="keyed",region="us-east"}) + series: avg(avg_over_time(rpc_latency_milliseconds{provider="dwellir",chain="arc",tier="keyed",region="us-east"}[1h])) + - region: eu-west + p50: avg(ocb:rpc_latency_milliseconds:p50_24h{provider="dwellir",chain="arc",tier="keyed",region="eu-west"}) + series: avg(avg_over_time(rpc_latency_milliseconds{provider="dwellir",chain="arc",tier="keyed",region="eu-west"}[1h])) + - region: ap-southeast + p50: avg(ocb:rpc_latency_milliseconds:p50_24h{provider="dwellir",chain="arc",tier="keyed",region="sgp"}) + series: avg(avg_over_time(rpc_latency_milliseconds{provider="dwellir",chain="arc",tier="keyed",region="sgp"}[1h])) + - slug: alchemy-cold name: Alchemy tier: keyed-cold @@ -410,3 +434,26 @@ providers: - region: eu-west p50: avg(ocb:rpc_latency_cold_milliseconds:p50_24h{provider="quicknode",chain="arc",tier="keyed",region="eu-west"}) series: avg(avg_over_time(rpc_latency_cold_milliseconds{provider="quicknode",chain="arc",tier="keyed",region="eu-west"}[1h])) + - slug: dwellir-cold + name: Dwellir + tier: keyed-cold + tag: Same endpoint, measured on a connection that is never reused + formula: "p50 over 24h of round-trip latency (ms) for the same call on a connection that is never reused: DNS, TCP and the TLS handshake are paid every time. What a serverless or one-shot client gets." + queries: + p50: avg(ocb:rpc_latency_cold_milliseconds:p50_24h{provider="dwellir",chain="arc",tier="keyed"}) + p90: avg(ocb:rpc_latency_cold_milliseconds:p90_24h{provider="dwellir",chain="arc",tier="keyed"}) + p99: avg(ocb:rpc_latency_cold_milliseconds:p99_24h{provider="dwellir",chain="arc",tier="keyed"}) + mean: avg(ocb:rpc_latency_cold_milliseconds:mean_24h{provider="dwellir",chain="arc",tier="keyed"}) + success: sum(ocb:rpc_call:ok_rate_24h{provider="dwellir",chain="arc",tier="keyed"}) / sum(ocb:rpc_call:rate_24h{provider="dwellir",chain="arc",tier="keyed"}) + sample_size: sum(ocb:rpc_call:increase_24h{provider="dwellir",chain="arc",tier="keyed"}) + series: avg(avg_over_time(rpc_latency_cold_milliseconds{provider="dwellir",chain="arc",tier="keyed"}[1h])) + regions: + - region: us-east + p50: avg(ocb:rpc_latency_cold_milliseconds:p50_24h{provider="dwellir",chain="arc",tier="keyed",region="us-east"}) + series: avg(avg_over_time(rpc_latency_cold_milliseconds{provider="dwellir",chain="arc",tier="keyed",region="us-east"}[1h])) + - region: eu-west + p50: avg(ocb:rpc_latency_cold_milliseconds:p50_24h{provider="dwellir",chain="arc",tier="keyed",region="eu-west"}) + series: avg(avg_over_time(rpc_latency_cold_milliseconds{provider="dwellir",chain="arc",tier="keyed",region="eu-west"}[1h])) + - region: ap-southeast + p50: avg(ocb:rpc_latency_cold_milliseconds:p50_24h{provider="dwellir",chain="arc",tier="keyed",region="sgp"}) + series: avg(avg_over_time(rpc_latency_cold_milliseconds{provider="dwellir",chain="arc",tier="keyed",region="sgp"}[1h])) diff --git a/benchmarks/base-rpc.yml b/benchmarks/base-rpc.yml index 91f7b1292..97f38a052 100644 --- a/benchmarks/base-rpc.yml +++ b/benchmarks/base-rpc.yml @@ -291,6 +291,30 @@ providers: p50: avg(ocb:rpc_latency_milliseconds:p50_24h{provider="quicknode",chain="base",tier="keyed",region="sgp"}) series: avg(avg_over_time(rpc_latency_milliseconds{provider="quicknode",chain="base",tier="keyed",region="sgp"}[1h])) + - slug: dwellir + name: Dwellir + tier: keyed + tag: Free plan key, 100k responses per day, plan disclosed + formula: "p50 over 24h of round-trip latency (ms) for eth_getBlockByNumber probed every 120 s from us-east, eu-west and Singapore on Dwellir's keyed Base endpoint." + queries: + p50: avg(ocb:rpc_latency_milliseconds:p50_24h{provider="dwellir",chain="base",tier="keyed"}) + p90: avg(ocb:rpc_latency_milliseconds:p90_24h{provider="dwellir",chain="base",tier="keyed"}) + p99: avg(ocb:rpc_latency_milliseconds:p99_24h{provider="dwellir",chain="base",tier="keyed"}) + mean: avg(ocb:rpc_latency_milliseconds:mean_24h{provider="dwellir",chain="base",tier="keyed"}) + success: sum(ocb:rpc_call:ok_rate_24h{provider="dwellir",chain="base",tier="keyed"}) / sum(ocb:rpc_call:rate_24h{provider="dwellir",chain="base",tier="keyed"}) + sample_size: sum(ocb:rpc_call:increase_24h{provider="dwellir",chain="base",tier="keyed"}) + series: avg(avg_over_time(rpc_latency_milliseconds{provider="dwellir",chain="base",tier="keyed"}[1h])) + regions: + - region: us-east + p50: avg(ocb:rpc_latency_milliseconds:p50_24h{provider="dwellir",chain="base",tier="keyed",region="us-east"}) + series: avg(avg_over_time(rpc_latency_milliseconds{provider="dwellir",chain="base",tier="keyed",region="us-east"}[1h])) + - region: eu-west + p50: avg(ocb:rpc_latency_milliseconds:p50_24h{provider="dwellir",chain="base",tier="keyed",region="eu-west"}) + series: avg(avg_over_time(rpc_latency_milliseconds{provider="dwellir",chain="base",tier="keyed",region="eu-west"}[1h])) + - region: ap-southeast + p50: avg(ocb:rpc_latency_milliseconds:p50_24h{provider="dwellir",chain="base",tier="keyed",region="sgp"}) + series: avg(avg_over_time(rpc_latency_milliseconds{provider="dwellir",chain="base",tier="keyed",region="sgp"}[1h])) + - slug: alchemy-cold name: Alchemy tier: keyed-cold @@ -383,3 +407,26 @@ providers: - region: ap-southeast p50: avg(ocb:rpc_latency_cold_milliseconds:p50_24h{provider="quicknode",chain="base",tier="keyed",region="sgp"}) series: avg(avg_over_time(rpc_latency_cold_milliseconds{provider="quicknode",chain="base",tier="keyed",region="sgp"}[1h])) + - slug: dwellir-cold + name: Dwellir + tier: keyed-cold + tag: Same endpoint, measured on a connection that is never reused + formula: "p50 over 24h of round-trip latency (ms) for the same call on a connection that is never reused: DNS, TCP and the TLS handshake are paid every time. What a serverless or one-shot client gets." + queries: + p50: avg(ocb:rpc_latency_cold_milliseconds:p50_24h{provider="dwellir",chain="base",tier="keyed"}) + p90: avg(ocb:rpc_latency_cold_milliseconds:p90_24h{provider="dwellir",chain="base",tier="keyed"}) + p99: avg(ocb:rpc_latency_cold_milliseconds:p99_24h{provider="dwellir",chain="base",tier="keyed"}) + mean: avg(ocb:rpc_latency_cold_milliseconds:mean_24h{provider="dwellir",chain="base",tier="keyed"}) + success: sum(ocb:rpc_call:ok_rate_24h{provider="dwellir",chain="base",tier="keyed"}) / sum(ocb:rpc_call:rate_24h{provider="dwellir",chain="base",tier="keyed"}) + sample_size: sum(ocb:rpc_call:increase_24h{provider="dwellir",chain="base",tier="keyed"}) + series: avg(avg_over_time(rpc_latency_cold_milliseconds{provider="dwellir",chain="base",tier="keyed"}[1h])) + regions: + - region: us-east + p50: avg(ocb:rpc_latency_cold_milliseconds:p50_24h{provider="dwellir",chain="base",tier="keyed",region="us-east"}) + series: avg(avg_over_time(rpc_latency_cold_milliseconds{provider="dwellir",chain="base",tier="keyed",region="us-east"}[1h])) + - region: eu-west + p50: avg(ocb:rpc_latency_cold_milliseconds:p50_24h{provider="dwellir",chain="base",tier="keyed",region="eu-west"}) + series: avg(avg_over_time(rpc_latency_cold_milliseconds{provider="dwellir",chain="base",tier="keyed",region="eu-west"}[1h])) + - region: ap-southeast + p50: avg(ocb:rpc_latency_cold_milliseconds:p50_24h{provider="dwellir",chain="base",tier="keyed",region="sgp"}) + series: avg(avg_over_time(rpc_latency_cold_milliseconds{provider="dwellir",chain="base",tier="keyed",region="sgp"}[1h])) diff --git a/benchmarks/bnb-rpc.yml b/benchmarks/bnb-rpc.yml index 6ee0009d7..9724fb670 100644 --- a/benchmarks/bnb-rpc.yml +++ b/benchmarks/bnb-rpc.yml @@ -291,6 +291,30 @@ providers: p50: avg(ocb:rpc_latency_milliseconds:p50_24h{provider="quicknode",chain="bnb",tier="keyed",region="sgp"}) series: avg(avg_over_time(rpc_latency_milliseconds{provider="quicknode",chain="bnb",tier="keyed",region="sgp"}[1h])) + - slug: dwellir + name: Dwellir + tier: keyed + tag: Free plan key, 100k responses per day, plan disclosed + formula: "p50 over 24h of round-trip latency (ms) for eth_getBlockByNumber probed every 120 s from us-east, eu-west and Singapore on Dwellir's keyed BNB Chain endpoint." + queries: + p50: avg(ocb:rpc_latency_milliseconds:p50_24h{provider="dwellir",chain="bnb",tier="keyed"}) + p90: avg(ocb:rpc_latency_milliseconds:p90_24h{provider="dwellir",chain="bnb",tier="keyed"}) + p99: avg(ocb:rpc_latency_milliseconds:p99_24h{provider="dwellir",chain="bnb",tier="keyed"}) + mean: avg(ocb:rpc_latency_milliseconds:mean_24h{provider="dwellir",chain="bnb",tier="keyed"}) + success: sum(ocb:rpc_call:ok_rate_24h{provider="dwellir",chain="bnb",tier="keyed"}) / sum(ocb:rpc_call:rate_24h{provider="dwellir",chain="bnb",tier="keyed"}) + sample_size: sum(ocb:rpc_call:increase_24h{provider="dwellir",chain="bnb",tier="keyed"}) + series: avg(avg_over_time(rpc_latency_milliseconds{provider="dwellir",chain="bnb",tier="keyed"}[1h])) + regions: + - region: us-east + p50: avg(ocb:rpc_latency_milliseconds:p50_24h{provider="dwellir",chain="bnb",tier="keyed",region="us-east"}) + series: avg(avg_over_time(rpc_latency_milliseconds{provider="dwellir",chain="bnb",tier="keyed",region="us-east"}[1h])) + - region: eu-west + p50: avg(ocb:rpc_latency_milliseconds:p50_24h{provider="dwellir",chain="bnb",tier="keyed",region="eu-west"}) + series: avg(avg_over_time(rpc_latency_milliseconds{provider="dwellir",chain="bnb",tier="keyed",region="eu-west"}[1h])) + - region: ap-southeast + p50: avg(ocb:rpc_latency_milliseconds:p50_24h{provider="dwellir",chain="bnb",tier="keyed",region="sgp"}) + series: avg(avg_over_time(rpc_latency_milliseconds{provider="dwellir",chain="bnb",tier="keyed",region="sgp"}[1h])) + - slug: alchemy-cold name: Alchemy tier: keyed-cold @@ -383,3 +407,26 @@ providers: - region: ap-southeast p50: avg(ocb:rpc_latency_cold_milliseconds:p50_24h{provider="quicknode",chain="bnb",tier="keyed",region="sgp"}) series: avg(avg_over_time(rpc_latency_cold_milliseconds{provider="quicknode",chain="bnb",tier="keyed",region="sgp"}[1h])) + - slug: dwellir-cold + name: Dwellir + tier: keyed-cold + tag: Same endpoint, measured on a connection that is never reused + formula: "p50 over 24h of round-trip latency (ms) for the same call on a connection that is never reused: DNS, TCP and the TLS handshake are paid every time. What a serverless or one-shot client gets." + queries: + p50: avg(ocb:rpc_latency_cold_milliseconds:p50_24h{provider="dwellir",chain="bnb",tier="keyed"}) + p90: avg(ocb:rpc_latency_cold_milliseconds:p90_24h{provider="dwellir",chain="bnb",tier="keyed"}) + p99: avg(ocb:rpc_latency_cold_milliseconds:p99_24h{provider="dwellir",chain="bnb",tier="keyed"}) + mean: avg(ocb:rpc_latency_cold_milliseconds:mean_24h{provider="dwellir",chain="bnb",tier="keyed"}) + success: sum(ocb:rpc_call:ok_rate_24h{provider="dwellir",chain="bnb",tier="keyed"}) / sum(ocb:rpc_call:rate_24h{provider="dwellir",chain="bnb",tier="keyed"}) + sample_size: sum(ocb:rpc_call:increase_24h{provider="dwellir",chain="bnb",tier="keyed"}) + series: avg(avg_over_time(rpc_latency_cold_milliseconds{provider="dwellir",chain="bnb",tier="keyed"}[1h])) + regions: + - region: us-east + p50: avg(ocb:rpc_latency_cold_milliseconds:p50_24h{provider="dwellir",chain="bnb",tier="keyed",region="us-east"}) + series: avg(avg_over_time(rpc_latency_cold_milliseconds{provider="dwellir",chain="bnb",tier="keyed",region="us-east"}[1h])) + - region: eu-west + p50: avg(ocb:rpc_latency_cold_milliseconds:p50_24h{provider="dwellir",chain="bnb",tier="keyed",region="eu-west"}) + series: avg(avg_over_time(rpc_latency_cold_milliseconds{provider="dwellir",chain="bnb",tier="keyed",region="eu-west"}[1h])) + - region: ap-southeast + p50: avg(ocb:rpc_latency_cold_milliseconds:p50_24h{provider="dwellir",chain="bnb",tier="keyed",region="sgp"}) + series: avg(avg_over_time(rpc_latency_cold_milliseconds{provider="dwellir",chain="bnb",tier="keyed",region="sgp"}[1h])) diff --git a/benchmarks/ethereum-rpc.yml b/benchmarks/ethereum-rpc.yml index a8e11b528..aeadd3e35 100644 --- a/benchmarks/ethereum-rpc.yml +++ b/benchmarks/ethereum-rpc.yml @@ -339,6 +339,30 @@ providers: p50: avg(ocb:rpc_latency_milliseconds:p50_24h{provider="quicknode",chain="ethereum",tier="keyed",region="sgp"}) series: avg(avg_over_time(rpc_latency_milliseconds{provider="quicknode",chain="ethereum",tier="keyed",region="sgp"}[1h])) + - slug: dwellir + name: Dwellir + tier: keyed + tag: Free plan key, 100k responses per day, plan disclosed + formula: "p50 over 24h of round-trip latency (ms) for eth_getBlockByNumber probed every 120 s from us-east, eu-west and Singapore on Dwellir's keyed Ethereum endpoint." + queries: + p50: avg(ocb:rpc_latency_milliseconds:p50_24h{provider="dwellir",chain="ethereum",tier="keyed"}) + p90: avg(ocb:rpc_latency_milliseconds:p90_24h{provider="dwellir",chain="ethereum",tier="keyed"}) + p99: avg(ocb:rpc_latency_milliseconds:p99_24h{provider="dwellir",chain="ethereum",tier="keyed"}) + mean: avg(ocb:rpc_latency_milliseconds:mean_24h{provider="dwellir",chain="ethereum",tier="keyed"}) + success: sum(ocb:rpc_call:ok_rate_24h{provider="dwellir",chain="ethereum",tier="keyed"}) / sum(ocb:rpc_call:rate_24h{provider="dwellir",chain="ethereum",tier="keyed"}) + sample_size: sum(ocb:rpc_call:increase_24h{provider="dwellir",chain="ethereum",tier="keyed"}) + series: avg(avg_over_time(rpc_latency_milliseconds{provider="dwellir",chain="ethereum",tier="keyed"}[1h])) + regions: + - region: us-east + p50: avg(ocb:rpc_latency_milliseconds:p50_24h{provider="dwellir",chain="ethereum",tier="keyed",region="us-east"}) + series: avg(avg_over_time(rpc_latency_milliseconds{provider="dwellir",chain="ethereum",tier="keyed",region="us-east"}[1h])) + - region: eu-west + p50: avg(ocb:rpc_latency_milliseconds:p50_24h{provider="dwellir",chain="ethereum",tier="keyed",region="eu-west"}) + series: avg(avg_over_time(rpc_latency_milliseconds{provider="dwellir",chain="ethereum",tier="keyed",region="eu-west"}[1h])) + - region: ap-southeast + p50: avg(ocb:rpc_latency_milliseconds:p50_24h{provider="dwellir",chain="ethereum",tier="keyed",region="sgp"}) + series: avg(avg_over_time(rpc_latency_milliseconds{provider="dwellir",chain="ethereum",tier="keyed",region="sgp"}[1h])) + - slug: alchemy-cold name: Alchemy tier: keyed-cold @@ -431,3 +455,26 @@ providers: - region: ap-southeast p50: avg(ocb:rpc_latency_cold_milliseconds:p50_24h{provider="quicknode",chain="ethereum",tier="keyed",region="sgp"}) series: avg(avg_over_time(rpc_latency_cold_milliseconds{provider="quicknode",chain="ethereum",tier="keyed",region="sgp"}[1h])) + - slug: dwellir-cold + name: Dwellir + tier: keyed-cold + tag: Same endpoint, measured on a connection that is never reused + formula: "p50 over 24h of round-trip latency (ms) for the same call on a connection that is never reused: DNS, TCP and the TLS handshake are paid every time. What a serverless or one-shot client gets." + queries: + p50: avg(ocb:rpc_latency_cold_milliseconds:p50_24h{provider="dwellir",chain="ethereum",tier="keyed"}) + p90: avg(ocb:rpc_latency_cold_milliseconds:p90_24h{provider="dwellir",chain="ethereum",tier="keyed"}) + p99: avg(ocb:rpc_latency_cold_milliseconds:p99_24h{provider="dwellir",chain="ethereum",tier="keyed"}) + mean: avg(ocb:rpc_latency_cold_milliseconds:mean_24h{provider="dwellir",chain="ethereum",tier="keyed"}) + success: sum(ocb:rpc_call:ok_rate_24h{provider="dwellir",chain="ethereum",tier="keyed"}) / sum(ocb:rpc_call:rate_24h{provider="dwellir",chain="ethereum",tier="keyed"}) + sample_size: sum(ocb:rpc_call:increase_24h{provider="dwellir",chain="ethereum",tier="keyed"}) + series: avg(avg_over_time(rpc_latency_cold_milliseconds{provider="dwellir",chain="ethereum",tier="keyed"}[1h])) + regions: + - region: us-east + p50: avg(ocb:rpc_latency_cold_milliseconds:p50_24h{provider="dwellir",chain="ethereum",tier="keyed",region="us-east"}) + series: avg(avg_over_time(rpc_latency_cold_milliseconds{provider="dwellir",chain="ethereum",tier="keyed",region="us-east"}[1h])) + - region: eu-west + p50: avg(ocb:rpc_latency_cold_milliseconds:p50_24h{provider="dwellir",chain="ethereum",tier="keyed",region="eu-west"}) + series: avg(avg_over_time(rpc_latency_cold_milliseconds{provider="dwellir",chain="ethereum",tier="keyed",region="eu-west"}[1h])) + - region: ap-southeast + p50: avg(ocb:rpc_latency_cold_milliseconds:p50_24h{provider="dwellir",chain="ethereum",tier="keyed",region="sgp"}) + series: avg(avg_over_time(rpc_latency_cold_milliseconds{provider="dwellir",chain="ethereum",tier="keyed",region="sgp"}[1h])) diff --git a/benchmarks/hyperliquid-rpc.yml b/benchmarks/hyperliquid-rpc.yml index 9ad5ea847..0dc048be3 100644 --- a/benchmarks/hyperliquid-rpc.yml +++ b/benchmarks/hyperliquid-rpc.yml @@ -296,6 +296,30 @@ providers: p50: avg(ocb:rpc_latency_milliseconds:p50_24h{provider="quicknode",chain="hyperliquid",tier="keyed",region="sgp"}) series: avg(avg_over_time(rpc_latency_milliseconds{provider="quicknode",chain="hyperliquid",tier="keyed",region="sgp"}[1h])) + - slug: dwellir + name: Dwellir + tier: keyed + tag: Free plan key, 100k responses per day, plan disclosed + formula: "p50 over 24h of round-trip latency (ms) for eth_getBlockByNumber probed every 120 s from us-east, eu-west and Singapore on Dwellir's keyed HyperEVM endpoint." + queries: + p50: avg(ocb:rpc_latency_milliseconds:p50_24h{provider="dwellir",chain="hyperliquid",tier="keyed"}) + p90: avg(ocb:rpc_latency_milliseconds:p90_24h{provider="dwellir",chain="hyperliquid",tier="keyed"}) + p99: avg(ocb:rpc_latency_milliseconds:p99_24h{provider="dwellir",chain="hyperliquid",tier="keyed"}) + mean: avg(ocb:rpc_latency_milliseconds:mean_24h{provider="dwellir",chain="hyperliquid",tier="keyed"}) + success: sum(ocb:rpc_call:ok_rate_24h{provider="dwellir",chain="hyperliquid",tier="keyed"}) / sum(ocb:rpc_call:rate_24h{provider="dwellir",chain="hyperliquid",tier="keyed"}) + sample_size: sum(ocb:rpc_call:increase_24h{provider="dwellir",chain="hyperliquid",tier="keyed"}) + series: avg(avg_over_time(rpc_latency_milliseconds{provider="dwellir",chain="hyperliquid",tier="keyed"}[1h])) + regions: + - region: us-east + p50: avg(ocb:rpc_latency_milliseconds:p50_24h{provider="dwellir",chain="hyperliquid",tier="keyed",region="us-east"}) + series: avg(avg_over_time(rpc_latency_milliseconds{provider="dwellir",chain="hyperliquid",tier="keyed",region="us-east"}[1h])) + - region: eu-west + p50: avg(ocb:rpc_latency_milliseconds:p50_24h{provider="dwellir",chain="hyperliquid",tier="keyed",region="eu-west"}) + series: avg(avg_over_time(rpc_latency_milliseconds{provider="dwellir",chain="hyperliquid",tier="keyed",region="eu-west"}[1h])) + - region: ap-southeast + p50: avg(ocb:rpc_latency_milliseconds:p50_24h{provider="dwellir",chain="hyperliquid",tier="keyed",region="sgp"}) + series: avg(avg_over_time(rpc_latency_milliseconds{provider="dwellir",chain="hyperliquid",tier="keyed",region="sgp"}[1h])) + - slug: alchemy-cold name: Alchemy tier: keyed-cold @@ -388,3 +412,26 @@ providers: - region: ap-southeast p50: avg(ocb:rpc_latency_cold_milliseconds:p50_24h{provider="quicknode",chain="hyperliquid",tier="keyed",region="sgp"}) series: avg(avg_over_time(rpc_latency_cold_milliseconds{provider="quicknode",chain="hyperliquid",tier="keyed",region="sgp"}[1h])) + - slug: dwellir-cold + name: Dwellir + tier: keyed-cold + tag: Same endpoint, measured on a connection that is never reused + formula: "p50 over 24h of round-trip latency (ms) for the same call on a connection that is never reused: DNS, TCP and the TLS handshake are paid every time. What a serverless or one-shot client gets." + queries: + p50: avg(ocb:rpc_latency_cold_milliseconds:p50_24h{provider="dwellir",chain="hyperliquid",tier="keyed"}) + p90: avg(ocb:rpc_latency_cold_milliseconds:p90_24h{provider="dwellir",chain="hyperliquid",tier="keyed"}) + p99: avg(ocb:rpc_latency_cold_milliseconds:p99_24h{provider="dwellir",chain="hyperliquid",tier="keyed"}) + mean: avg(ocb:rpc_latency_cold_milliseconds:mean_24h{provider="dwellir",chain="hyperliquid",tier="keyed"}) + success: sum(ocb:rpc_call:ok_rate_24h{provider="dwellir",chain="hyperliquid",tier="keyed"}) / sum(ocb:rpc_call:rate_24h{provider="dwellir",chain="hyperliquid",tier="keyed"}) + sample_size: sum(ocb:rpc_call:increase_24h{provider="dwellir",chain="hyperliquid",tier="keyed"}) + series: avg(avg_over_time(rpc_latency_cold_milliseconds{provider="dwellir",chain="hyperliquid",tier="keyed"}[1h])) + regions: + - region: us-east + p50: avg(ocb:rpc_latency_cold_milliseconds:p50_24h{provider="dwellir",chain="hyperliquid",tier="keyed",region="us-east"}) + series: avg(avg_over_time(rpc_latency_cold_milliseconds{provider="dwellir",chain="hyperliquid",tier="keyed",region="us-east"}[1h])) + - region: eu-west + p50: avg(ocb:rpc_latency_cold_milliseconds:p50_24h{provider="dwellir",chain="hyperliquid",tier="keyed",region="eu-west"}) + series: avg(avg_over_time(rpc_latency_cold_milliseconds{provider="dwellir",chain="hyperliquid",tier="keyed",region="eu-west"}[1h])) + - region: ap-southeast + p50: avg(ocb:rpc_latency_cold_milliseconds:p50_24h{provider="dwellir",chain="hyperliquid",tier="keyed",region="sgp"}) + series: avg(avg_over_time(rpc_latency_cold_milliseconds{provider="dwellir",chain="hyperliquid",tier="keyed",region="sgp"}[1h])) diff --git a/benchmarks/polygon-rpc.yml b/benchmarks/polygon-rpc.yml index 6c26c2ab8..b42f6d919 100644 --- a/benchmarks/polygon-rpc.yml +++ b/benchmarks/polygon-rpc.yml @@ -267,6 +267,30 @@ providers: p50: avg(ocb:rpc_latency_milliseconds:p50_24h{provider="quicknode",chain="polygon",tier="keyed",region="sgp"}) series: avg(avg_over_time(rpc_latency_milliseconds{provider="quicknode",chain="polygon",tier="keyed",region="sgp"}[1h])) + - slug: dwellir + name: Dwellir + tier: keyed + tag: Free plan key, 100k responses per day, plan disclosed + formula: "p50 over 24h of round-trip latency (ms) for eth_getBlockByNumber probed every 120 s from us-east, eu-west and Singapore on Dwellir's keyed Polygon endpoint." + queries: + p50: avg(ocb:rpc_latency_milliseconds:p50_24h{provider="dwellir",chain="polygon",tier="keyed"}) + p90: avg(ocb:rpc_latency_milliseconds:p90_24h{provider="dwellir",chain="polygon",tier="keyed"}) + p99: avg(ocb:rpc_latency_milliseconds:p99_24h{provider="dwellir",chain="polygon",tier="keyed"}) + mean: avg(ocb:rpc_latency_milliseconds:mean_24h{provider="dwellir",chain="polygon",tier="keyed"}) + success: sum(ocb:rpc_call:ok_rate_24h{provider="dwellir",chain="polygon",tier="keyed"}) / sum(ocb:rpc_call:rate_24h{provider="dwellir",chain="polygon",tier="keyed"}) + sample_size: sum(ocb:rpc_call:increase_24h{provider="dwellir",chain="polygon",tier="keyed"}) + series: avg(avg_over_time(rpc_latency_milliseconds{provider="dwellir",chain="polygon",tier="keyed"}[1h])) + regions: + - region: us-east + p50: avg(ocb:rpc_latency_milliseconds:p50_24h{provider="dwellir",chain="polygon",tier="keyed",region="us-east"}) + series: avg(avg_over_time(rpc_latency_milliseconds{provider="dwellir",chain="polygon",tier="keyed",region="us-east"}[1h])) + - region: eu-west + p50: avg(ocb:rpc_latency_milliseconds:p50_24h{provider="dwellir",chain="polygon",tier="keyed",region="eu-west"}) + series: avg(avg_over_time(rpc_latency_milliseconds{provider="dwellir",chain="polygon",tier="keyed",region="eu-west"}[1h])) + - region: ap-southeast + p50: avg(ocb:rpc_latency_milliseconds:p50_24h{provider="dwellir",chain="polygon",tier="keyed",region="sgp"}) + series: avg(avg_over_time(rpc_latency_milliseconds{provider="dwellir",chain="polygon",tier="keyed",region="sgp"}[1h])) + - slug: alchemy-cold name: Alchemy tier: keyed-cold @@ -359,3 +383,26 @@ providers: - region: ap-southeast p50: avg(ocb:rpc_latency_cold_milliseconds:p50_24h{provider="quicknode",chain="polygon",tier="keyed",region="sgp"}) series: avg(avg_over_time(rpc_latency_cold_milliseconds{provider="quicknode",chain="polygon",tier="keyed",region="sgp"}[1h])) + - slug: dwellir-cold + name: Dwellir + tier: keyed-cold + tag: Same endpoint, measured on a connection that is never reused + formula: "p50 over 24h of round-trip latency (ms) for the same call on a connection that is never reused: DNS, TCP and the TLS handshake are paid every time. What a serverless or one-shot client gets." + queries: + p50: avg(ocb:rpc_latency_cold_milliseconds:p50_24h{provider="dwellir",chain="polygon",tier="keyed"}) + p90: avg(ocb:rpc_latency_cold_milliseconds:p90_24h{provider="dwellir",chain="polygon",tier="keyed"}) + p99: avg(ocb:rpc_latency_cold_milliseconds:p99_24h{provider="dwellir",chain="polygon",tier="keyed"}) + mean: avg(ocb:rpc_latency_cold_milliseconds:mean_24h{provider="dwellir",chain="polygon",tier="keyed"}) + success: sum(ocb:rpc_call:ok_rate_24h{provider="dwellir",chain="polygon",tier="keyed"}) / sum(ocb:rpc_call:rate_24h{provider="dwellir",chain="polygon",tier="keyed"}) + sample_size: sum(ocb:rpc_call:increase_24h{provider="dwellir",chain="polygon",tier="keyed"}) + series: avg(avg_over_time(rpc_latency_cold_milliseconds{provider="dwellir",chain="polygon",tier="keyed"}[1h])) + regions: + - region: us-east + p50: avg(ocb:rpc_latency_cold_milliseconds:p50_24h{provider="dwellir",chain="polygon",tier="keyed",region="us-east"}) + series: avg(avg_over_time(rpc_latency_cold_milliseconds{provider="dwellir",chain="polygon",tier="keyed",region="us-east"}[1h])) + - region: eu-west + p50: avg(ocb:rpc_latency_cold_milliseconds:p50_24h{provider="dwellir",chain="polygon",tier="keyed",region="eu-west"}) + series: avg(avg_over_time(rpc_latency_cold_milliseconds{provider="dwellir",chain="polygon",tier="keyed",region="eu-west"}[1h])) + - region: ap-southeast + p50: avg(ocb:rpc_latency_cold_milliseconds:p50_24h{provider="dwellir",chain="polygon",tier="keyed",region="sgp"}) + series: avg(avg_over_time(rpc_latency_cold_milliseconds{provider="dwellir",chain="polygon",tier="keyed",region="sgp"}[1h])) diff --git a/benchmarks/robinhood-rpc.yml b/benchmarks/robinhood-rpc.yml index f53e665cc..2668739b0 100644 --- a/benchmarks/robinhood-rpc.yml +++ b/benchmarks/robinhood-rpc.yml @@ -301,6 +301,30 @@ providers: - region: eu-west p50: avg(ocb:rpc_latency_cold_milliseconds:p50_24h{provider="chainstack",chain="robinhood",tier="keyed",region="eu-west"}) series: avg(avg_over_time(rpc_latency_cold_milliseconds{provider="chainstack",chain="robinhood",tier="keyed",region="eu-west"}[1h])) + - slug: dwellir + name: Dwellir + tier: keyed + tag: Free plan key, 100k responses per day, plan disclosed + formula: "p50 over 24h of round-trip latency (ms) for eth_getBlockByNumber probed every 120 s from us-east, eu-west and Singapore on Dwellir's keyed Robinhood Chain endpoint." + queries: + p50: avg(ocb:rpc_latency_milliseconds:p50_24h{provider="dwellir",chain="robinhood",tier="keyed"}) + p90: avg(ocb:rpc_latency_milliseconds:p90_24h{provider="dwellir",chain="robinhood",tier="keyed"}) + p99: avg(ocb:rpc_latency_milliseconds:p99_24h{provider="dwellir",chain="robinhood",tier="keyed"}) + mean: avg(ocb:rpc_latency_milliseconds:mean_24h{provider="dwellir",chain="robinhood",tier="keyed"}) + success: sum(ocb:rpc_call:ok_rate_24h{provider="dwellir",chain="robinhood",tier="keyed"}) / sum(ocb:rpc_call:rate_24h{provider="dwellir",chain="robinhood",tier="keyed"}) + sample_size: sum(ocb:rpc_call:increase_24h{provider="dwellir",chain="robinhood",tier="keyed"}) + series: avg(avg_over_time(rpc_latency_milliseconds{provider="dwellir",chain="robinhood",tier="keyed"}[1h])) + regions: + - region: us-east + p50: avg(ocb:rpc_latency_milliseconds:p50_24h{provider="dwellir",chain="robinhood",tier="keyed",region="us-east"}) + series: avg(avg_over_time(rpc_latency_milliseconds{provider="dwellir",chain="robinhood",tier="keyed",region="us-east"}[1h])) + - region: eu-west + p50: avg(ocb:rpc_latency_milliseconds:p50_24h{provider="dwellir",chain="robinhood",tier="keyed",region="eu-west"}) + series: avg(avg_over_time(rpc_latency_milliseconds{provider="dwellir",chain="robinhood",tier="keyed",region="eu-west"}[1h])) + - region: ap-southeast + p50: avg(ocb:rpc_latency_milliseconds:p50_24h{provider="dwellir",chain="robinhood",tier="keyed",region="sgp"}) + series: avg(avg_over_time(rpc_latency_milliseconds{provider="dwellir",chain="robinhood",tier="keyed",region="sgp"}[1h])) + - slug: alchemy-cold name: Alchemy tier: keyed-cold @@ -361,3 +385,26 @@ providers: - region: eu-west p50: avg(ocb:rpc_latency_cold_milliseconds:p50_24h{provider="getblock",chain="robinhood",tier="keyed",region="eu-west"}) series: avg(avg_over_time(rpc_latency_cold_milliseconds{provider="getblock",chain="robinhood",tier="keyed",region="eu-west"}[1h])) + - slug: dwellir-cold + name: Dwellir + tier: keyed-cold + tag: Same endpoint, measured on a connection that is never reused + formula: "p50 over 24h of round-trip latency (ms) for the same call on a connection that is never reused: DNS, TCP and the TLS handshake are paid every time. What a serverless or one-shot client gets." + queries: + p50: avg(ocb:rpc_latency_cold_milliseconds:p50_24h{provider="dwellir",chain="robinhood",tier="keyed"}) + p90: avg(ocb:rpc_latency_cold_milliseconds:p90_24h{provider="dwellir",chain="robinhood",tier="keyed"}) + p99: avg(ocb:rpc_latency_cold_milliseconds:p99_24h{provider="dwellir",chain="robinhood",tier="keyed"}) + mean: avg(ocb:rpc_latency_cold_milliseconds:mean_24h{provider="dwellir",chain="robinhood",tier="keyed"}) + success: sum(ocb:rpc_call:ok_rate_24h{provider="dwellir",chain="robinhood",tier="keyed"}) / sum(ocb:rpc_call:rate_24h{provider="dwellir",chain="robinhood",tier="keyed"}) + sample_size: sum(ocb:rpc_call:increase_24h{provider="dwellir",chain="robinhood",tier="keyed"}) + series: avg(avg_over_time(rpc_latency_cold_milliseconds{provider="dwellir",chain="robinhood",tier="keyed"}[1h])) + regions: + - region: us-east + p50: avg(ocb:rpc_latency_cold_milliseconds:p50_24h{provider="dwellir",chain="robinhood",tier="keyed",region="us-east"}) + series: avg(avg_over_time(rpc_latency_cold_milliseconds{provider="dwellir",chain="robinhood",tier="keyed",region="us-east"}[1h])) + - region: eu-west + p50: avg(ocb:rpc_latency_cold_milliseconds:p50_24h{provider="dwellir",chain="robinhood",tier="keyed",region="eu-west"}) + series: avg(avg_over_time(rpc_latency_cold_milliseconds{provider="dwellir",chain="robinhood",tier="keyed",region="eu-west"}[1h])) + - region: ap-southeast + p50: avg(ocb:rpc_latency_cold_milliseconds:p50_24h{provider="dwellir",chain="robinhood",tier="keyed",region="sgp"}) + series: avg(avg_over_time(rpc_latency_cold_milliseconds{provider="dwellir",chain="robinhood",tier="keyed",region="sgp"}[1h])) diff --git a/harnesses/rpc-keyed-latency/cmd/script/config.go b/harnesses/rpc-keyed-latency/cmd/script/config.go index 50e6873f0..c795ca1c4 100644 --- a/harnesses/rpc-keyed-latency/cmd/script/config.go +++ b/harnesses/rpc-keyed-latency/cmd/script/config.go @@ -23,7 +23,7 @@ type Endpoint struct { // matrix declares which (provider, chain) cells we look for in env. // Kind is derived from the chain. -var providers = []string{"infura", "alchemy", "chainstack", "ankr", "helius", "quicknode", "getblock"} +var providers = []string{"infura", "alchemy", "chainstack", "ankr", "helius", "quicknode", "getblock", "dwellir"} // Per-provider probe-interval multiplier. Infura's free tier 402'd daily // at the old 60 s cadence (its real daily credit budget is below the @@ -126,6 +126,13 @@ var defaultBudgets = map[string]int64{ "getblock": 600_000, "ankr": 300_000, "helius": 300_000, + // dwellir: free tier is 100k responses/day, 1 RPC response = 1 credit, + // so ~3M/month across the three regions sharing the key. The eight EVM + // chains cost 173k per region per month at the 120 s cadence, so this is + // a runaway guard rather than a quota. Dwellir does not serve Solana, + // and a cell with no URL is simply skipped, so that chain stays at four + // providers without any special casing. + "dwellir": 1_000_000, } func budgetFor(provider string) int64 { diff --git a/public/logos/dwellir.png b/public/logos/dwellir.png new file mode 100644 index 0000000000000000000000000000000000000000..2daec4a2f9757b9dedfd146534ca6854b94802ef GIT binary patch literal 14680 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 literal 0 HcmV?d00001 diff --git a/public/logos/dwellir.svg b/public/logos/dwellir.svg deleted file mode 100644 index b5a801f97..000000000 --- a/public/logos/dwellir.svg +++ /dev/null @@ -1,101 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/lib/logo-manifest.ts b/src/lib/logo-manifest.ts index 898df8b5a..28b17b6da 100644 --- a/src/lib/logo-manifest.ts +++ b/src/lib/logo-manifest.ts @@ -172,7 +172,7 @@ const RAW: Record = { plasma: "/logos/plasma.webp", ondo: "/logos/ondo-perps.svg", onfinality: "/logos/onfinality.png", - dwellir: "/logos/dwellir.svg", + dwellir: "/logos/dwellir.png", berachain: "/logos/berachain.png", @@ -1005,6 +1005,7 @@ const ALIASES: Record = { "quicknode-cold": "quicknode", "alchemy-cold": "alchemy", "chainstack-cold": "chainstack", + "dwellir-cold": "dwellir", }; export function logoPath(slug: string): string | null { From 03cf337cf14cbcf11a5e814178f3c4bcb2759c42 Mon Sep 17 00:00:00 2001 From: Flotapponnier <160007691+Flotapponnier@users.noreply.github.com> Date: Fri, 9 Oct 2026 18:03:59 +0200 Subject: [PATCH 2/2] Dwellir is on a paid Developer plan, not the free tier I wrote "Free plan key, 100k responses per day" into all eight specs from the public pricing page. The account is on the Developer plan: $49 a month, 25 million API responses, 100 responses per second, 1 RPC response = 1 API credit with no compute units. This is not cosmetic. Every keyed page promises a disclosed plan tier for every provider in the cohort, so a wrong tier is a published factual error of the same kind as the seven relays and the four oracle sources. Two places needed it. The row tag, and the "Plan tiers, disclosed" methodology bullet, which named four providers while the table is about to show five. That bullet already runs 482 to 484 characters against a 500 cap, so Dwellir gets its own bullet rather than a rewrite of other vendors' disclosures. The budget comment said free tier too. Three regions share the key, so the plan allows 8.3M per region; the eight chains cost 173k per region per month, under 1% of it. The 1M guard stays, correctly described now as a runaway guard rather than a quota. pnpm validate clean, go build and go vet clean, 495 tests pass. --- benchmarks/arbitrum-rpc.yml | 3 ++- benchmarks/arc-rpc.yml | 3 ++- benchmarks/base-rpc.yml | 3 ++- benchmarks/bnb-rpc.yml | 3 ++- benchmarks/ethereum-rpc.yml | 3 ++- benchmarks/hyperliquid-rpc.yml | 3 ++- benchmarks/polygon-rpc.yml | 3 ++- benchmarks/robinhood-rpc.yml | 3 ++- harnesses/rpc-keyed-latency/cmd/script/config.go | 14 ++++++++------ 9 files changed, 24 insertions(+), 14 deletions(-) diff --git a/benchmarks/arbitrum-rpc.yml b/benchmarks/arbitrum-rpc.yml index 4fdfe4def..7b3f72147 100644 --- a/benchmarks/arbitrum-rpc.yml +++ b/benchmarks/arbitrum-rpc.yml @@ -27,6 +27,7 @@ methodology: - "Chain scope: every query on this page is pinned to chain=\"arbitrum\". Provider coverage: {{count}} no-key public-read endpoints live today, each listed with its URL in the endpoints table on this page. Exclusions follow the cluster-wide rules documented on the parent benchmark." - "Private cohort (Access selector, Private): Alchemy, Chainstack, GetBlock and QuickNode probed on their keyed Arbitrum endpoints every 120 seconds from the same 3 regions, same call (eth_getBlockByNumber, rotating id), same ok / http_err / jsonrpc_err / stale / timeout classification." - "Keys live in the probe environment, never in the repo. Plan tiers, disclosed: Alchemy: a Free plan key (30M CU per month, 25 requests per second), the tier any reader gets; Alchemy states free and paid keys share one routing; Chainstack: a Global Node on the Growth plan; QuickNode: an endpoint on a Build plan ($49 per month), shared fleet; GetBlock: an endpoint on the Enterprise plan, shared by the three probe regions. Chainstack, GetBlock and QuickNode provided their endpoints." + - "Dwellir plan tier, disclosed: a Developer plan key ($49 per month, 25 million API responses, 100 responses per second; 1 RPC response = 1 API credit, no compute units). Shared nodes, the same product a reader buys. Dwellir publishes no Solana endpoint, so it is absent from that page rather than shown as unavailable." - "GetBlock regional pairing: each probe region uses GetBlock's nearest endpoint, us-east to New York, eu-west to Frankfurt, sgp to Singapore. Alchemy, Chainstack and QuickNode publish one routed entry point per chain instead, which in the general case does land a probe on a nearby node. Some of any gap between the two arrangements is deployment topology rather than node speed, and a deployment in one of these regions would see the same benefit GetBlock's endpoint gives the probe." - "Two cohorts, two rankings: the public endpoints are shared, rate-limited gateways probed every 60 seconds; the keyed endpoints are metered or dedicated and probed every 120 seconds. The selector switches the whole page (ranking, chart, region tabs, badges, citation) between them. No figure on this page compares a public endpoint with a keyed one." @@ -342,7 +343,7 @@ providers: - slug: dwellir name: Dwellir tier: keyed - tag: Free plan key, 100k responses per day, plan disclosed + tag: Developer plan key, 25M responses per month, plan disclosed formula: "p50 over 24h of round-trip latency (ms) for eth_getBlockByNumber probed every 120 s from us-east, eu-west and Singapore on Dwellir's keyed Arbitrum endpoint." queries: p50: avg(ocb:rpc_latency_milliseconds:p50_24h{provider="dwellir",chain="arbitrum",tier="keyed"}) diff --git a/benchmarks/arc-rpc.yml b/benchmarks/arc-rpc.yml index 32953b61b..f61d1616f 100644 --- a/benchmarks/arc-rpc.yml +++ b/benchmarks/arc-rpc.yml @@ -41,6 +41,7 @@ methodology: - "The dRPC row of that table (rpc.drpc.mainnet.arc.io) serves the same free tier as arc.drpc.org, identical x-drpc-owner-id, and is measured once under dRPC; the Alchemy row needs a key and sits in the private cohort." - "Private cohort (Access selector, Private): Alchemy, Chainstack, GetBlock and QuickNode probed on their keyed Arc endpoints every 120 seconds from us-east and eu-west, same call (eth_getBlockByNumber, rotating id), same ok / http_err / jsonrpc_err / stale / timeout classification." - "Keys live in the probe environment, never in the repo. Plan tiers, disclosed: Chainstack: a Global Node on the Growth plan; QuickNode: an endpoint on a Build plan ($49 per month), shared fleet; Alchemy: a Free plan key (30M CU per month, 25 requests per second), the tier any reader gets; Alchemy states free and paid keys share one routing; GetBlock: an endpoint on the Enterprise plan, shared by the two probe regions. Chainstack, GetBlock and QuickNode provided their endpoints." + - "Dwellir plan tier, disclosed: a Developer plan key ($49 per month, 25 million API responses, 100 responses per second; 1 RPC response = 1 API credit, no compute units). Shared nodes, the same product a reader buys. Dwellir publishes no Solana endpoint, so it is absent from that page rather than shown as unavailable." - "GetBlock regional pairing: us-east uses GetBlock's New York endpoint and eu-west its Frankfurt endpoint. Alchemy, Chainstack and QuickNode publish one routed entry point per chain instead, which in the general case does land a probe on a nearby node. Some of any gap between the two arrangements is deployment topology rather than node speed, and a deployment in one of these regions would see the same benefit GetBlock's endpoint gives the probe." - "GetBlock coverage: GetBlock does not offer Arc in Singapore, so no GetBlock row exists for that region: the endpoint is not offered there, which is not a failed or pending measurement. The whole keyed cohort is therefore measured from us-east and eu-west, because averaging a two-region row against three-region rows would compare different populations." - "Two cohorts, two rankings: the public endpoints are shared, rate-limited gateways probed every 60 seconds; the keyed endpoints are metered or dedicated and probed every 120 seconds. The selector switches the whole page (ranking, chart, region tabs, badges, citation) between them. No figure on this page compares a public endpoint with a keyed one." @@ -333,7 +334,7 @@ providers: - slug: dwellir name: Dwellir tier: keyed - tag: Free plan key, 100k responses per day, plan disclosed + tag: Developer plan key, 25M responses per month, plan disclosed formula: "p50 over 24h of round-trip latency (ms) for eth_getBlockByNumber probed every 120 s from us-east, eu-west and Singapore on Dwellir's keyed Arc endpoint." queries: p50: avg(ocb:rpc_latency_milliseconds:p50_24h{provider="dwellir",chain="arc",tier="keyed"}) diff --git a/benchmarks/base-rpc.yml b/benchmarks/base-rpc.yml index 97f38a052..f1abbbc43 100644 --- a/benchmarks/base-rpc.yml +++ b/benchmarks/base-rpc.yml @@ -27,6 +27,7 @@ methodology: - "Chain scope: every query on this page is pinned to chain=\"base\". Provider coverage: {{count}} no-key public-read endpoints live today, each listed with its URL in the endpoints table on this page. Blink (formerly Merkle) was delisted 2026-07: its gateway does not serve `eth_getBlockByNumber`, the anti-cache probe this cluster standardized on, so it cannot be measured on equal terms. Exclusions follow the cluster-wide rules documented on the parent benchmark." - "Private cohort (Access selector, Private): Alchemy, Chainstack, GetBlock and QuickNode probed on their keyed Base endpoints every 120 seconds from the same 3 regions, same call (eth_getBlockByNumber, rotating id), same ok / http_err / jsonrpc_err / stale / timeout classification." - "Keys live in the probe environment, never in the repo. Plan tiers, disclosed: Alchemy: a Free plan key (30M CU per month, 25 requests per second), the tier any reader gets; Alchemy states free and paid keys share one routing; Chainstack: a Global Node on the Growth plan; QuickNode: an endpoint on a Build plan ($49 per month), shared fleet; GetBlock: an endpoint on the Enterprise plan, shared by the three probe regions. Chainstack, GetBlock and QuickNode provided their endpoints." + - "Dwellir plan tier, disclosed: a Developer plan key ($49 per month, 25 million API responses, 100 responses per second; 1 RPC response = 1 API credit, no compute units). Shared nodes, the same product a reader buys. Dwellir publishes no Solana endpoint, so it is absent from that page rather than shown as unavailable." - "GetBlock regional pairing: each probe region uses GetBlock's nearest endpoint, us-east to New York, eu-west to Frankfurt, sgp to Singapore. Alchemy, Chainstack and QuickNode publish one routed entry point per chain instead, which in the general case does land a probe on a nearby node. Some of any gap between the two arrangements is deployment topology rather than node speed, and a deployment in one of these regions would see the same benefit GetBlock's endpoint gives the probe." - "Two cohorts, two rankings: the public endpoints are shared, rate-limited gateways probed every 60 seconds; the keyed endpoints are metered or dedicated and probed every 120 seconds. The selector switches the whole page (ranking, chart, region tabs, badges, citation) between them. No figure on this page compares a public endpoint with a keyed one." @@ -294,7 +295,7 @@ providers: - slug: dwellir name: Dwellir tier: keyed - tag: Free plan key, 100k responses per day, plan disclosed + tag: Developer plan key, 25M responses per month, plan disclosed formula: "p50 over 24h of round-trip latency (ms) for eth_getBlockByNumber probed every 120 s from us-east, eu-west and Singapore on Dwellir's keyed Base endpoint." queries: p50: avg(ocb:rpc_latency_milliseconds:p50_24h{provider="dwellir",chain="base",tier="keyed"}) diff --git a/benchmarks/bnb-rpc.yml b/benchmarks/bnb-rpc.yml index 9724fb670..6bdc8b965 100644 --- a/benchmarks/bnb-rpc.yml +++ b/benchmarks/bnb-rpc.yml @@ -27,6 +27,7 @@ methodology: - "Chain scope: every query on this page is pinned to chain=\"bnb\". Provider coverage: {{count}} no-key public-read endpoints live today, each listed with its URL in the endpoints table on this page. Blink (formerly Merkle) was delisted 2026-07: its gateway does not serve `eth_getBlockByNumber`, the anti-cache probe this cluster standardized on, so it cannot be measured on equal terms. Exclusions follow the cluster-wide rules documented on the parent benchmark." - "Private cohort (Access selector, Private): Alchemy, Chainstack, GetBlock and QuickNode probed on their keyed BNB Chain endpoints every 120 seconds from the same 3 regions, same call (eth_getBlockByNumber, rotating id), same ok / http_err / jsonrpc_err / stale / timeout classification." - "Keys live in the probe environment, never in the repo. Plan tiers, disclosed: Alchemy: a Free plan key (30M CU per month, 25 requests per second), the tier any reader gets; Alchemy states free and paid keys share one routing; Chainstack: a Global Node on the Growth plan; QuickNode: an endpoint on a Build plan ($49 per month), shared fleet; GetBlock: an endpoint on the Enterprise plan, shared by the three probe regions. Chainstack, GetBlock and QuickNode provided their endpoints." + - "Dwellir plan tier, disclosed: a Developer plan key ($49 per month, 25 million API responses, 100 responses per second; 1 RPC response = 1 API credit, no compute units). Shared nodes, the same product a reader buys. Dwellir publishes no Solana endpoint, so it is absent from that page rather than shown as unavailable." - "GetBlock regional pairing: each probe region uses GetBlock's nearest endpoint, us-east to New York, eu-west to Frankfurt, sgp to Singapore. Alchemy, Chainstack and QuickNode publish one routed entry point per chain instead, which in the general case does land a probe on a nearby node. Some of any gap between the two arrangements is deployment topology rather than node speed, and a deployment in one of these regions would see the same benefit GetBlock's endpoint gives the probe." - "Two cohorts, two rankings: the public endpoints are shared, rate-limited gateways probed every 60 seconds; the keyed endpoints are metered or dedicated and probed every 120 seconds. The selector switches the whole page (ranking, chart, region tabs, badges, citation) between them. No figure on this page compares a public endpoint with a keyed one." @@ -294,7 +295,7 @@ providers: - slug: dwellir name: Dwellir tier: keyed - tag: Free plan key, 100k responses per day, plan disclosed + tag: Developer plan key, 25M responses per month, plan disclosed formula: "p50 over 24h of round-trip latency (ms) for eth_getBlockByNumber probed every 120 s from us-east, eu-west and Singapore on Dwellir's keyed BNB Chain endpoint." queries: p50: avg(ocb:rpc_latency_milliseconds:p50_24h{provider="dwellir",chain="bnb",tier="keyed"}) diff --git a/benchmarks/ethereum-rpc.yml b/benchmarks/ethereum-rpc.yml index aeadd3e35..05975071f 100644 --- a/benchmarks/ethereum-rpc.yml +++ b/benchmarks/ethereum-rpc.yml @@ -27,6 +27,7 @@ methodology: - "Chain scope: every query on this page is pinned to chain=\"ethereum\". Provider coverage: {{count}} no-key public-read endpoints live today, each listed with its URL in the endpoints table on this page. Cloudflare removed (persistent JSON-RPC -32603). MEV-protection RPCs (Flashbots, MEV Blocker, Blink, bloXroute) share this probe methodology but score on [mev-protect-rpc](/benchmarks/mev-protect-rpc), because their SLA optimises for send-tx privacy, not read speed." - "Private cohort (Access selector, Private): Alchemy, Chainstack, GetBlock and QuickNode probed on their keyed Ethereum endpoints every 120 seconds from the same 3 regions, same call (eth_getBlockByNumber, rotating id), same ok / http_err / jsonrpc_err / stale / timeout classification." - "Keys live in the probe environment, never in the repo. Plan tiers, disclosed: Alchemy: a Free plan key (30M CU per month, 25 requests per second), the tier any reader gets; Alchemy states free and paid keys share one routing; Chainstack: a Global Node on the Growth plan; QuickNode: an endpoint on a Build plan ($49 per month), shared fleet; GetBlock: an endpoint on the Enterprise plan, shared by the three probe regions. Chainstack, GetBlock and QuickNode provided their endpoints." + - "Dwellir plan tier, disclosed: a Developer plan key ($49 per month, 25 million API responses, 100 responses per second; 1 RPC response = 1 API credit, no compute units). Shared nodes, the same product a reader buys. Dwellir publishes no Solana endpoint, so it is absent from that page rather than shown as unavailable." - "GetBlock regional pairing: each probe region uses GetBlock's nearest endpoint, us-east to New York, eu-west to Frankfurt, sgp to Singapore. Alchemy, Chainstack and QuickNode publish one routed entry point per chain instead, which in the general case does land a probe on a nearby node. Some of any gap between the two arrangements is deployment topology rather than node speed, and a deployment in one of these regions would see the same benefit GetBlock's endpoint gives the probe." - "Two cohorts, two rankings: the public endpoints are shared, rate-limited gateways probed every 60 seconds; the keyed endpoints are metered or dedicated and probed every 120 seconds. The selector switches the whole page (ranking, chart, region tabs, badges, citation) between them. No figure on this page compares a public endpoint with a keyed one." @@ -342,7 +343,7 @@ providers: - slug: dwellir name: Dwellir tier: keyed - tag: Free plan key, 100k responses per day, plan disclosed + tag: Developer plan key, 25M responses per month, plan disclosed formula: "p50 over 24h of round-trip latency (ms) for eth_getBlockByNumber probed every 120 s from us-east, eu-west and Singapore on Dwellir's keyed Ethereum endpoint." queries: p50: avg(ocb:rpc_latency_milliseconds:p50_24h{provider="dwellir",chain="ethereum",tier="keyed"}) diff --git a/benchmarks/hyperliquid-rpc.yml b/benchmarks/hyperliquid-rpc.yml index 0dc048be3..1a2a762d0 100644 --- a/benchmarks/hyperliquid-rpc.yml +++ b/benchmarks/hyperliquid-rpc.yml @@ -38,6 +38,7 @@ methodology: - "Excluded by the launch audit: Alchemy demo path (rate-limited dead), thirdweb (`Invalid chain` on HyperEVM), Grove/Pocket public LB (requires an app id at the LB path), AllThatNode + Blast API + Chainstack + Gelato + Imperator HyperEVM paths (DNS-fail or 401 without a key), PublicNode (no HyperEVM subdomain yet). HyperEVM is a young chain (mainnet Feb 2025) so this list will shift quickly." - "Private cohort (Access selector, Private): Alchemy, Chainstack, GetBlock and QuickNode probed on their keyed Hyperliquid endpoints every 120 seconds from the same 3 regions, same call (eth_getBlockByNumber, rotating id), same ok / http_err / jsonrpc_err / stale / timeout classification." - "Keys live in the probe environment, never in the repo. Plan tiers, disclosed: Alchemy: a Free plan key (30M CU per month, 25 requests per second), the tier any reader gets; Alchemy states free and paid keys share one routing; Chainstack: a Global Node on the Growth plan; QuickNode: an endpoint on a Build plan ($49 per month), shared fleet; GetBlock: an endpoint on the Enterprise plan, shared by the three probe regions. Chainstack, GetBlock and QuickNode provided their endpoints." + - "Dwellir plan tier, disclosed: a Developer plan key ($49 per month, 25 million API responses, 100 responses per second; 1 RPC response = 1 API credit, no compute units). Shared nodes, the same product a reader buys. Dwellir publishes no Solana endpoint, so it is absent from that page rather than shown as unavailable." - "GetBlock regional pairing: each probe region uses GetBlock's nearest endpoint, us-east to New York, eu-west to Frankfurt, sgp to Singapore. Alchemy, Chainstack and QuickNode publish one routed entry point per chain instead, which in the general case does land a probe on a nearby node. Some of any gap between the two arrangements is deployment topology rather than node speed, and a deployment in one of these regions would see the same benefit GetBlock's endpoint gives the probe." - "Two cohorts, two rankings: the public endpoints are shared, rate-limited gateways probed every 60 seconds; the keyed endpoints are metered or dedicated and probed every 120 seconds. The selector switches the whole page (ranking, chart, region tabs, badges, citation) between them. No figure on this page compares a public endpoint with a keyed one." @@ -299,7 +300,7 @@ providers: - slug: dwellir name: Dwellir tier: keyed - tag: Free plan key, 100k responses per day, plan disclosed + tag: Developer plan key, 25M responses per month, plan disclosed formula: "p50 over 24h of round-trip latency (ms) for eth_getBlockByNumber probed every 120 s from us-east, eu-west and Singapore on Dwellir's keyed HyperEVM endpoint." queries: p50: avg(ocb:rpc_latency_milliseconds:p50_24h{provider="dwellir",chain="hyperliquid",tier="keyed"}) diff --git a/benchmarks/polygon-rpc.yml b/benchmarks/polygon-rpc.yml index b42f6d919..644d65817 100644 --- a/benchmarks/polygon-rpc.yml +++ b/benchmarks/polygon-rpc.yml @@ -27,6 +27,7 @@ methodology: - "Chain scope: every query on this page is pinned to chain=\"polygon\". Provider coverage: {{count}} no-key public-read endpoints live today, each listed with its URL in the endpoints table on this page. Exclusions follow the cluster-wide rules documented on the parent benchmark." - "Private cohort (Access selector, Private): Alchemy, Chainstack, GetBlock and QuickNode probed on their keyed Polygon endpoints every 120 seconds from the same 3 regions, same call (eth_getBlockByNumber, rotating id), same ok / http_err / jsonrpc_err / stale / timeout classification." - "Keys live in the probe environment, never in the repo. Plan tiers, disclosed: Alchemy: a Free plan key (30M CU per month, 25 requests per second), the tier any reader gets; Alchemy states free and paid keys share one routing; Chainstack: a Global Node on the Growth plan; QuickNode: an endpoint on a Build plan ($49 per month), shared fleet; GetBlock: an endpoint on the Enterprise plan, shared by the three probe regions. Chainstack, GetBlock and QuickNode provided their endpoints." + - "Dwellir plan tier, disclosed: a Developer plan key ($49 per month, 25 million API responses, 100 responses per second; 1 RPC response = 1 API credit, no compute units). Shared nodes, the same product a reader buys. Dwellir publishes no Solana endpoint, so it is absent from that page rather than shown as unavailable." - "GetBlock regional pairing: each probe region uses GetBlock's nearest endpoint, us-east to New York, eu-west to Frankfurt, sgp to Singapore. Alchemy, Chainstack and QuickNode publish one routed entry point per chain instead, which in the general case does land a probe on a nearby node. Some of any gap between the two arrangements is deployment topology rather than node speed, and a deployment in one of these regions would see the same benefit GetBlock's endpoint gives the probe." - "Two cohorts, two rankings: the public endpoints are shared, rate-limited gateways probed every 60 seconds; the keyed endpoints are metered or dedicated and probed every 120 seconds. The selector switches the whole page (ranking, chart, region tabs, badges, citation) between them. No figure on this page compares a public endpoint with a keyed one." @@ -270,7 +271,7 @@ providers: - slug: dwellir name: Dwellir tier: keyed - tag: Free plan key, 100k responses per day, plan disclosed + tag: Developer plan key, 25M responses per month, plan disclosed formula: "p50 over 24h of round-trip latency (ms) for eth_getBlockByNumber probed every 120 s from us-east, eu-west and Singapore on Dwellir's keyed Polygon endpoint." queries: p50: avg(ocb:rpc_latency_milliseconds:p50_24h{provider="dwellir",chain="polygon",tier="keyed"}) diff --git a/benchmarks/robinhood-rpc.yml b/benchmarks/robinhood-rpc.yml index 2668739b0..9b4be8bef 100644 --- a/benchmarks/robinhood-rpc.yml +++ b/benchmarks/robinhood-rpc.yml @@ -39,6 +39,7 @@ methodology: - "Chain scope: every query on this page is pinned to chain=\"robinhood\" (chain id 4663). Provider coverage: {{count}} no-key public-read endpoints live today, each listed with its URL in the endpoints table on this page. Exclusions follow the cluster-wide rules documented on the parent benchmark." - "Private cohort (Access selector, Private): Chainstack, Alchemy, QuickNode and GetBlock probed on their keyed Robinhood Chain endpoints every 120 seconds from us-east and eu-west, same call (eth_getBlockByNumber, rotating id), same ok / http_err / jsonrpc_err / stale / timeout classification." - "Keys live in the probe environment, never in the repo. Plan tiers, disclosed: Chainstack: a Global Node on the Growth plan; Alchemy: a Free plan key (30M CU per month, 25 requests per second), the tier any reader gets; Alchemy states free and paid keys share one routing; QuickNode: an endpoint on a Build plan ($49 per month), shared fleet; GetBlock: an endpoint on the Enterprise plan, shared by the two probe regions. Chainstack, GetBlock and QuickNode provided their endpoints." + - "Dwellir plan tier, disclosed: a Developer plan key ($49 per month, 25 million API responses, 100 responses per second; 1 RPC response = 1 API credit, no compute units). Shared nodes, the same product a reader buys. Dwellir publishes no Solana endpoint, so it is absent from that page rather than shown as unavailable." - "GetBlock regional pairing: us-east uses GetBlock's New York endpoint and eu-west its Frankfurt endpoint. Alchemy, Chainstack and QuickNode publish one routed entry point per chain instead, which in the general case does land a probe on a nearby node. Some of any gap between the two arrangements is deployment topology rather than node speed, and a deployment in one of these regions would see the same benefit GetBlock's endpoint gives the probe." - "GetBlock coverage: GetBlock does not offer Robinhood Chain in Singapore, so no GetBlock row exists for that region: the endpoint is not offered there, which is not a failed or pending measurement. The whole keyed cohort is therefore measured from us-east and eu-west, because averaging a two-region row against three-region rows would compare different populations." - "Two cohorts, two rankings: the public endpoints are shared, rate-limited gateways probed every 60 seconds; the keyed endpoints are metered or dedicated and probed every 120 seconds. The selector switches the whole page (ranking, chart, region tabs, badges, citation) between them. No figure on this page compares a public endpoint with a keyed one." @@ -304,7 +305,7 @@ providers: - slug: dwellir name: Dwellir tier: keyed - tag: Free plan key, 100k responses per day, plan disclosed + tag: Developer plan key, 25M responses per month, plan disclosed formula: "p50 over 24h of round-trip latency (ms) for eth_getBlockByNumber probed every 120 s from us-east, eu-west and Singapore on Dwellir's keyed Robinhood Chain endpoint." queries: p50: avg(ocb:rpc_latency_milliseconds:p50_24h{provider="dwellir",chain="robinhood",tier="keyed"}) diff --git a/harnesses/rpc-keyed-latency/cmd/script/config.go b/harnesses/rpc-keyed-latency/cmd/script/config.go index c795ca1c4..4948d78f9 100644 --- a/harnesses/rpc-keyed-latency/cmd/script/config.go +++ b/harnesses/rpc-keyed-latency/cmd/script/config.go @@ -126,12 +126,14 @@ var defaultBudgets = map[string]int64{ "getblock": 600_000, "ankr": 300_000, "helius": 300_000, - // dwellir: free tier is 100k responses/day, 1 RPC response = 1 credit, - // so ~3M/month across the three regions sharing the key. The eight EVM - // chains cost 173k per region per month at the 120 s cadence, so this is - // a runaway guard rather than a quota. Dwellir does not serve Solana, - // and a cell with no URL is simply skipped, so that chain stays at four - // providers without any special casing. + // dwellir: Developer plan, $49/month, 25M API responses and 100 + // responses/sec, 1 RPC response = 1 API credit with no compute units. + // Three regions share the key, so 8.3M per region is what the plan + // actually allows; the eight EVM chains cost 173k per region per month at + // the 120 s cadence, under 1% of it. The number below is therefore a + // runaway guard, not a quota, and sits well inside the plan. + // Dwellir does not serve Solana, and a cell with no URL is simply + // skipped, so that chain stays at four providers with no special casing. "dwellir": 1_000_000, }