From 807b04f422c727c2178ad694b9ff01d46cea23da Mon Sep 17 00:00:00 2001 From: Flotapponnier Date: Tue, 15 Sep 2026 14:43:49 +0200 Subject: [PATCH] bench 262: only keyed providers declared (MoonPay, Transak) so the worker quorum passes; Ramp, Onramper, Meld return with their keys The worker needs min(ceil(declared/2), 3) ranked rows to publish; with five declared and two keyed it kept the draft render forever. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01L4rjxemTvgRwrCG6D2iK5D --- benchmarks/fiat-onramp-cost.yml | 59 ++++++--------------------------- 1 file changed, 10 insertions(+), 49 deletions(-) diff --git a/benchmarks/fiat-onramp-cost.yml b/benchmarks/fiat-onramp-cost.yml index 3c57f451..0ebecf9d 100644 --- a/benchmarks/fiat-onramp-cost.yml +++ b/benchmarks/fiat-onramp-cost.yml @@ -3,8 +3,8 @@ slug: fiat-onramp-cost number: "262" title: Fiat on-ramp all-in cost, EUR to BTC premium over exchange mid -seo_title: "Fiat on-ramp cost 2026: MoonPay vs Transak vs Ramp, all-in premium over spot in bps" -seo_description: "{{best_name}} quotes the lowest all-in cost for 500 EUR of BTC by card at {{best_p50}} over the Kraken mid. Declared fee plus hidden spread for MoonPay, Transak and Ramp, quoted every 5 minutes from France." +seo_title: "Fiat on-ramp cost 2026: MoonPay vs Transak, all-in premium over spot in bps" +seo_description: "{{best_name}} quotes the lowest all-in cost for 500 EUR of BTC by card at {{best_p50}} over the Kraken mid. Declared fee plus hidden spread for MoonPay and Transak, quoted every 5 minutes from France." subtitle: What a French retail buyer actually pays per bitcoin, in basis points over the Kraken EUR mid, once the declared fee, the network fee and the spread hidden in the provider's rate are folded into one number. 500 EUR by card, quoted every 5 minutes. Lower is better. category: On-ramps status: live @@ -28,11 +28,12 @@ seo_intro: | see where the cost actually lives. One persona: a retail buyer in France paying EUR, 500 EUR by card into bitcoin, quoted every five minutes from an EU vantage; SEPA, USDC and ETH cells are measured on - the same grid and published as their own series. Direct providers (MoonPay, Transak, - Ramp) and aggregators (Onramper, Meld) are two cohorts and are never - ranked against each other: an aggregator's row is the best member - ramp it returned, which is a different product from a single - provider's own price. Lower is better. + the same grid and published as their own series. MoonPay and Transak + are quoted today; Ramp, and the aggregators Onramper and Meld, join + the table as their API keys are granted. Direct providers and + aggregators are two cohorts and are never ranked against each other: + an aggregator's row is the best member ramp it returned, which is a + different product from a single provider's own price. Lower is better. abstract: | The harness quotes each provider on a fixed grid every five minutes: @@ -59,18 +60,17 @@ methodology: - "Metric. all_in_premium_bps = (fiat_in / crypto_out minus spot) / spot times 10 000. fiat_in is the total the buyer pays including every fee the provider adds; crypto_out is the amount the provider says will be delivered. Positive means the buyer pays above the exchange mid. A value near zero means the provider's rate plus fees matched the mid." - "Spot reference. Kraken public Ticker, EUR pairs, mid of best bid and ask, fetched in the same cycle as the quotes (within two seconds). A second reference from Pyth Hermes (BTC/USD, ETH/USD, USDC/USD divided by EUR/USD) is recorded on every quote under spot_ref=pyth and the gap between the two is published as spot_reference_divergence_bps. Kraken is the headline because it has no FX leg." - "Declared versus hidden. declared_fee_bps = (provider fee plus network fee plus partner fee) / fiat_in times 10 000 as the provider itemizes them. hidden_spread_bps = all_in minus declared, the part of the cost that lives in the rate rather than in the fee line." - - "Cohorts. Direct providers (MoonPay, Transak, Ramp; Mercuryo quoted for card only) are one cohort. Aggregators (Onramper, Meld) are another: one request returns one quote per member ramp, each member sample is labelled provider=member and via=aggregator, and the aggregator's row is the minimum across its members. The two cohorts are not ranked against each other." + - "Cohorts. Direct providers (MoonPay and Transak today; Ramp and Mercuryo once keyed) are one cohort. Aggregators (Onramper, Meld, once keyed) are another: one request returns one quote per member ramp, each member sample is labelled provider=member and via=aggregator, and the aggregator's row is the minimum across its members. The two cohorts are not ranked against each other." - "Cadence. Every 5 minutes with a plus or minus 10 percent jitter, 12 cells per provider per cycle, at most 2 requests in flight per provider. Ramp documents 100 requests per minute per IP; the harness stays two orders of magnitude below that. A 4xx is never retried; a 5xx or timeout is retried once." - "Failures. A provider that answers without a usable quote counts as success 0 on that cell and its gauges are deleted rather than frozen. A provider whose key is not configured is skipped, not failed. Errors are counted by reason: no_quote, http_4xx, http_5xx, rate_limited, timeout, network, parse." - "Sample size. The harness increments a counter per usable quote; the table reads increase() over 24h so the count is quote events, not Prometheus scrapes of a gauge. Expected 288 per cell per day." - "Reproducibility. Every sample carries the SHA-256 of the raw provider response in the harness log. The adapters are written against each provider's documented schema; the parameters not yet exercised with a live key are listed in harnesses/fiat-onramp-cost/CHECKLIST.md and stay marked UNVERIFIED until they are." - - "Not measured. Coinbase Onramp is excluded pending a read of the CDP terms on benchmarking. Apple Pay and Google Pay cells need a wallet session and are not quotable server-side. ATM operators publish no quote API. Banxa and Alchemy Pay reach the bench only through the aggregators in this version." + - "Not measured yet. Ramp, Onramper and Meld have adapters in the harness and enter the table when their keys are granted (requested 2026-09-14). Coinbase Onramp is excluded pending a read of the CDP terms on benchmarking. Apple Pay and Google Pay cells need a wallet session and are not quotable server-side. ATM operators publish no quote API. Banxa and Alchemy Pay reach the bench only through the aggregators in this version." findings: - "{{best_name}} currently quotes the lowest all-in premium on the headline cell at {{best_p50}} over the Kraken EUR mid (24h median, 500 EUR by card into BTC)." - "{{name:moonpay}} sits at {{p50:moonpay}}. MoonPay prices by request IP, so the number is what an EU vantage sees, not a country parameter." - "{{name:transak}} sits at {{p50:transak}}. Transak takes the country as a parameter and itemizes the network fee separately from its own fee." - - "{{name:ramp}} sits at {{p50:ramp}}. Ramp returns every payment method in one answer, so its card and SEPA cells come from the same quote." - "Read the hidden spread next to the declared fee: a provider whose declared fee looks low can still sit high on the all-in number when its rate carries the margin." source: https://github.com/ChainBench/OpenChainBench/tree/main/harnesses/fiat-onramp-cost @@ -122,42 +122,3 @@ providers: success: avg_over_time(onramp_quote_success{provider="transak",via="direct",asset="btc",network="bitcoin",payment_method="card",notional="500",fiat="EUR",country="FR",region="eu-west"}[24h]) sample_size: increase(onramp_quote_samples_total{provider="transak",via="direct",asset="btc",network="bitcoin",payment_method="card",notional="500",fiat="EUR",country="FR",region="eu-west"}[24h]) series: onramp_quote_all_in_premium_bps{provider="transak",via="direct",asset="btc",network="bitcoin",payment_method="card",notional="500",fiat="EUR",country="FR",region="eu-west",spot_ref="kraken_eur"} - - slug: ramp - name: Ramp - tag: Direct on-ramp, card and SEPA, quote returns every payment method at once - type: protocol - formula: "24h median of the all-in premium over Kraken EUR mid on the headline cell (BTC, card, 500 EUR, France), quoted directly through Ramp's own API." - queries: - p50: quantile_over_time(0.50, onramp_quote_all_in_premium_bps{provider="ramp",via="direct",asset="btc",network="bitcoin",payment_method="card",notional="500",fiat="EUR",country="FR",region="eu-west",spot_ref="kraken_eur"}[24h]) - p90: quantile_over_time(0.90, onramp_quote_all_in_premium_bps{provider="ramp",via="direct",asset="btc",network="bitcoin",payment_method="card",notional="500",fiat="EUR",country="FR",region="eu-west",spot_ref="kraken_eur"}[24h]) - p99: quantile_over_time(0.99, onramp_quote_all_in_premium_bps{provider="ramp",via="direct",asset="btc",network="bitcoin",payment_method="card",notional="500",fiat="EUR",country="FR",region="eu-west",spot_ref="kraken_eur"}[24h]) - mean: avg_over_time(onramp_quote_all_in_premium_bps{provider="ramp",via="direct",asset="btc",network="bitcoin",payment_method="card",notional="500",fiat="EUR",country="FR",region="eu-west",spot_ref="kraken_eur"}[24h]) - success: avg_over_time(onramp_quote_success{provider="ramp",via="direct",asset="btc",network="bitcoin",payment_method="card",notional="500",fiat="EUR",country="FR",region="eu-west"}[24h]) - sample_size: increase(onramp_quote_samples_total{provider="ramp",via="direct",asset="btc",network="bitcoin",payment_method="card",notional="500",fiat="EUR",country="FR",region="eu-west"}[24h]) - series: onramp_quote_all_in_premium_bps{provider="ramp",via="direct",asset="btc",network="bitcoin",payment_method="card",notional="500",fiat="EUR",country="FR",region="eu-west",spot_ref="kraken_eur"} - - slug: onramper - name: Onramper - tag: Aggregator, one call returns a quote per member ramp - type: aggregator - formula: "Best member ramp Onramper returns on the headline cell: 24h median of each member's all-in premium over Kraken EUR mid, then the minimum across members. Aggregator cohort, not ranked against direct rows." - queries: - p50: min(quantile_over_time(0.50, onramp_quote_all_in_premium_bps{via="onramper",cohort="aggregator",asset="btc",network="bitcoin",payment_method="card",notional="500",fiat="EUR",country="FR",region="eu-west",spot_ref="kraken_eur"}[24h])) - p90: min(quantile_over_time(0.90, onramp_quote_all_in_premium_bps{via="onramper",cohort="aggregator",asset="btc",network="bitcoin",payment_method="card",notional="500",fiat="EUR",country="FR",region="eu-west",spot_ref="kraken_eur"}[24h])) - p99: min(quantile_over_time(0.99, onramp_quote_all_in_premium_bps{via="onramper",cohort="aggregator",asset="btc",network="bitcoin",payment_method="card",notional="500",fiat="EUR",country="FR",region="eu-west",spot_ref="kraken_eur"}[24h])) - mean: min(avg_over_time(onramp_quote_all_in_premium_bps{via="onramper",cohort="aggregator",asset="btc",network="bitcoin",payment_method="card",notional="500",fiat="EUR",country="FR",region="eu-west",spot_ref="kraken_eur"}[24h])) - success: avg_over_time(onramp_quote_success{provider="onramper",via="onramper",asset="btc",network="bitcoin",payment_method="card",notional="500",fiat="EUR",country="FR",region="eu-west"}[24h]) - sample_size: max(increase(onramp_quote_samples_total{via="onramper",cohort="aggregator",asset="btc",network="bitcoin",payment_method="card",notional="500",fiat="EUR",country="FR",region="eu-west"}[24h])) - series: min(onramp_quote_all_in_premium_bps{via="onramper",cohort="aggregator",asset="btc",network="bitcoin",payment_method="card",notional="500",fiat="EUR",country="FR",region="eu-west",spot_ref="kraken_eur"}) - - slug: meld - name: Meld - tag: Aggregator, one call returns a quote per member ramp - type: aggregator - formula: "Best member ramp Meld returns on the headline cell: 24h median of each member's all-in premium over Kraken EUR mid, then the minimum across members. Aggregator cohort, not ranked against direct rows." - queries: - p50: min(quantile_over_time(0.50, onramp_quote_all_in_premium_bps{via="meld",cohort="aggregator",asset="btc",network="bitcoin",payment_method="card",notional="500",fiat="EUR",country="FR",region="eu-west",spot_ref="kraken_eur"}[24h])) - p90: min(quantile_over_time(0.90, onramp_quote_all_in_premium_bps{via="meld",cohort="aggregator",asset="btc",network="bitcoin",payment_method="card",notional="500",fiat="EUR",country="FR",region="eu-west",spot_ref="kraken_eur"}[24h])) - p99: min(quantile_over_time(0.99, onramp_quote_all_in_premium_bps{via="meld",cohort="aggregator",asset="btc",network="bitcoin",payment_method="card",notional="500",fiat="EUR",country="FR",region="eu-west",spot_ref="kraken_eur"}[24h])) - mean: min(avg_over_time(onramp_quote_all_in_premium_bps{via="meld",cohort="aggregator",asset="btc",network="bitcoin",payment_method="card",notional="500",fiat="EUR",country="FR",region="eu-west",spot_ref="kraken_eur"}[24h])) - success: avg_over_time(onramp_quote_success{provider="meld",via="meld",asset="btc",network="bitcoin",payment_method="card",notional="500",fiat="EUR",country="FR",region="eu-west"}[24h]) - sample_size: max(increase(onramp_quote_samples_total{via="meld",cohort="aggregator",asset="btc",network="bitcoin",payment_method="card",notional="500",fiat="EUR",country="FR",region="eu-west"}[24h])) - series: min(onramp_quote_all_in_premium_bps{via="meld",cohort="aggregator",asset="btc",network="bitcoin",payment_method="card",notional="500",fiat="EUR",country="FR",region="eu-west",spot_ref="kraken_eur"})