diff --git a/.gitignore b/.gitignore index 5ef6a520..ef02f9ad 100644 --- a/.gitignore +++ b/.gitignore @@ -36,6 +36,21 @@ yarn-error.log* # vercel .vercel +# Internal-only docs that must NOT ship with the open-source repo. +# Patterns reserved as a tripwire: if a contributor adds a new doc with +# one of these naming conventions, git won't track it without an +# explicit override. The legacy individual filenames stay for safety in +# case anyone restores them from git history locally. +docs/solana-landing-deployment-checklist.md +docs/solana-landing-tiered-architecture.md +docs/solana-landing-cost-model.md +docs/solana-landing-active-bench-plan.md +docs/france-cryptos-roadmap.md +docs/*-internal.md +docs/*-roadmap.md +docs/*-checklist.md +docs/*-cost-model.md + # typescript *.tsbuildinfo next-env.d.ts diff --git a/docs/france-cryptos-roadmap.md b/docs/france-cryptos-roadmap.md deleted file mode 100644 index 9ed8255e..00000000 --- a/docs/france-cryptos-roadmap.md +++ /dev/null @@ -1,416 +0,0 @@ -# France Cryptos × OpenChainBench — Benchmark Roadmap - -10 nouveaux benchmarks proposés, validés sur faisabilité technique (endpoints réels testés) et économique (free / free-tier soutenable). - -Méthodo : chaque candidat a été testé par un agent dédié (curl + WebFetch sur les APIs cibles, vérification rate limits, fallbacks). Verdict = `GREEN` (free, méthodo clean) / `PARTIAL` (free avec scope réduit ou caveat) / `BLOCKED` (paywall / infra coûteuse). - ---- - -## 1. Positionnement stratégique - -France Cryptos demande une couverture éditoriale qui chevauche largement DeFiLlama / TokenTerminal / Artemis / Glassnode. On n'essaie pas de les rejouer — leurs équipes pleins-temps gagnent ce match. - -Le **rôle d'OCB** dans ce partenariat = produire des **benchmarks comparatifs reproductibles** qui répondent à des questions éditoriales précises que les concurrents ne tranchent pas : - -- *"Qui tient sa promesse de buyback ?"* -- *"Qui dilue, et combien d'impact ça a eu historiquement ?"* -- *"Quel oracle dévie ?"* -- *"Quel validator paie réellement ?"* -- *"Quel issuer stablecoin est transparent ?"* - -Chaque bench OCB doit donc produire **(a) un classement public + (b) un seuil/déclencheur de news + (c) un endpoint Prometheus consommable par un agent éditorial / bot TG**. - ---- - -## 2. Matrice de faisabilité - -| # | Bench | Verdict | Coût infra | Bottleneck principal | Priorité | -|---|---|---|---|---|---| -| 017 | Real Earnings | 🟡 PARTIAL | $0 | DeFiLlama `/emissions` désormais 402. Proxy : emissions schedule via vesting on-chain | P3 | -| 018 | Buyback Execution Audit | 🟢 GREEN (3 protos) | $0 | dYdX = stack Cosmos (skip v1), Aave AFC addr à confirmer | **P1** | -| 019 | Sustainable DAU | 🟡 PARTIAL | $0 (light) | Cluster analysis O(N²) infaisable free. Heuristiques de surface seulement | P4 | -| 020 | Perp Funding Spread | 🟡 PARTIAL (4/8 DEX) | $0 | Drift/GMX/Jupiter = lecture on-chain, pas REST | **P2** | -| 021 | BTC On-Chain Indicators | 🟡 PARTIAL (3/8) | $0 light / ~50€/mo Hetzner full | SOPR/MVRV/NUPL = nœud BTC full (740 GB). Free = Puell / Hash Ribbons / MPI proxy | P3 | -| 022 | Token Unlocks Pressure | 🟢 GREEN | $0 | CryptoRank Next.js scraping fragile (`buildId` rotates) | **P1** | -| 023 | Stablecoin Issuer Transparency | 🟡 PARTIAL (4/6 issuers) | $0 | USDT/FDUSD = SPA + PDF hostiles. USDC/DAI/PYUSD/USDe clean | P3 | -| 024 | Bridge Flow Anomaly | 🟡 PARTIAL | $0 | DeFiLlama bridges désormais 402. Wormhole couvre ≠ canonical L2 bridges | P2 | -| 025 | Oracle Deviation | 🟢 GREEN | $0 | Uniswap TWAP = code custom (sqrtPriceX96, multi-hop). v1 sans TWAP | **P1** | -| 026 | Validator Economics Net of MEV | 🟢 GREEN SOL/HL / 🟡 PARTIAL ETH | $0 | ETH = besoin index validators (top-N par stake en MVP, sinon nœud beacon) | **P1** (SOL+HL) | - ---- - -## 3. Specs détaillées par bench - -### Bench № 017 — Real Earnings *(P3, PARTIAL)* - -**Question** : "Quel protocole est réellement profitable une fois les incentives token déduits ?" - -**Méthodo proposée** : `sustainability_ratio = revenue_30d / (unlocked_supply_30d × price_avg_30d)`. Pas strictement "earnings users-distributed" — proxy "emissions schedule valorisé". Documenter le caveat. - -**Sources retenues** (free) : -- `api.llama.fi/summary/fees/{slug}?dataType=dailyRevenue` — pas de clé, ~300 req/5min raisonnable -- `api.coingecko.com/api/v3/coins/{id}/market_chart` — 30 req/min, 10k/mois -- Vesting contracts on-chain via RPC public + Etherscan v2 (5 req/s) - -**Sources écartées (paywall)** : DeFiLlama `/emissions` (402), Tokenomist (pas d'API publique), Token Terminal (full paywall). - -**Métriques Prom** : -``` -ocb_protocol_revenue_30d_usd{protocol, sector} -ocb_protocol_emissions_value_30d_usd{protocol} -ocb_protocol_sustainability_ratio{protocol} -``` - -**Bottleneck** : "incentives" ≠ "emissions schedule". V1 = proxy avec disclaimer. V2 ($300/mo DeFiLlama Pro) débloque la vraie métrique. - ---- - -### Bench № 018 — Buyback Execution Audit *(P1, GREEN)* - -**Question** : "Les protocoles font-ils vraiment leurs buybacks annoncés ?" - -**Méthodo** : `executed_USD / promised_USD` sur fenêtres 7d / 30d, mesuré on-chain par parsing du buyback wallet. - -**Scope v1 — 3 protocoles clean** : - -| Protocole | Wallet | Endpoint | Promesse publique | -|---|---|---|---| -| **Hyperliquid** | `0xfefe...fefe` (Assistance Fund) | `api.hyperliquid.xyz/info` (`userFills` + `spotClearinghouseState`) | 97% des fees → AF (docs + gov) | -| **GMX** | Treasury `0x68863dDE14303BcED249cA8ec6AF85d4694dea6A` (Arbitrum) | Etherscan v2 `chainid=42161` | 27% fees → buyback distrib stakers $90 | -| **Sky / Maker** | `0xBE8E3e3618f7474F8cB1d074A26afFef007E98FB` (SBE receiver) | Etherscan v2 | Smart Burn Engine déterministe : surplus > 50M DAI → buyback MKR sur Uniswap V2 | - -**Sources retenues** : -- Hyperliquid Info API — public, no key, ~100 req/min raisonnable -- Etherscan API v2 — 1 clé free, 5 req/s, 100k/jour, multi-chain (ETH + Arb + Base + OP unifié) -- DeFiLlama `summary/fees` — calcul du dénominateur `promised_USD = revenue × % engagé` -- CoinGecko — USD-ification des token amounts - -**Reporter v2** : dYdX (stack Cosmos, autre scraper), Aave (adresse AFC à confirmer via TokenLogic dashboard), Jupiter (besoin adresse exacte Litterbox Trust). - -**Métriques Prom** : -``` -ocb_buyback_executed_usd{protocol, window} -ocb_buyback_promised_usd{protocol, window} -ocb_buyback_ratio{protocol, window} -``` - ---- - -### Bench № 019 — Sustainable DAU *(P4, PARTIAL — à reconsidérer)* - -**Question** : "Combien d'utilisateurs réels (hors sybil/bots) un protocole a vraiment ?" - -**Verdict honnête** : sans Dune/Flipside payant ou indexer custom, l'angle "real DAU" est creux. Le cluster analysis O(N²) est infaisable en free tier. Seules les heuristiques de surface tournent. - -**Si on garde v1 (avec disclaimer fort)** : -- 3 protocoles : Base, Uniswap, Jupiter -- 3 heuristiques : wallet age <30j, valeur USD médiane tx, % activité dans seul protocole audité -- Refresh quotidien (pas continu) -- Back-test contre dataset public `LayerZero-Labs/sybil-report` pour valider precision/recall -- Métrique : `ocb_sustainable_dau_ratio{protocol}` avec disclaimer "v1 = heuristiques de surface, pas clustering" - -**Reco** : reporter à v2 quand budget ETL custom (Postgres + indexer) débloqué. Sortir un faux "real DAU" décrédibiliserait OCB. - ---- - -### Bench № 020 — Perp Funding Spread *(P2, PARTIAL → GREEN sur 4 DEX)* - -**Question** : "Quel DEX perp a le funding le plus exploitable / le mieux aligné spot ?" - -**Scope v1 — 5 sources REST publiques** : - -| Source | Endpoint | Cadence funding | -|---|---|---| -| Binance (ref CEX) | `fapi.binance.com/fapi/v1/premiumIndex?symbol=BTCUSDT` | 8h | -| Hyperliquid | `api.hyperliquid.xyz/info` (POST `type=metaAndAssetCtxs`) | 1h | -| dYdX v4 | `indexer.dydx.trade/v4/perpetualMarkets?ticker=BTC-USD` | 1h | -| Aster | `fapi.asterdex.com/fapi/v1/premiumIndex?symbol=BTCUSDT` | 8h (clone Binance) | -| Vertex | `archive.prod.vertexprotocol.com/v1` | 1h (format à reverse) | - -**Reporter v2** : -- GMX v2 — funding via `Reader` contract Arbitrum (eth_call) -- Drift — SDK + RPC Solana (Helius free) -- Jupiter Perps — décodage `custody` accounts Solana - -**Normalisation obligatoire** : 3 formats (1h, 8h, per-second) → métrique annualized commune `funding_rate_apr`. - -**Métriques Prom** : -``` -ocb_perp_funding_rate_apr{dex, market} -ocb_perp_funding_spread_bps{market, dex_a, dex_b} -ocb_perp_funding_next_at_seconds{dex, market} -``` - ---- - -### Bench № 021 — BTC On-Chain Indicators *(P3, PARTIAL — repositionnement)* - -**Verdict** : "Glassnode replica full open-source" demande nœud BTC full (740 GB chain + 120 GB electrs, ~50€/mo Hetzner bare-metal — pas Railway). Décision business à prendre. - -**Reposition v1** : "OCB Mining & Cycle Indicators" sur 3 indicateurs faisables 100% free : - -| Indicateur | Source free | Faisabilité | -|---|---|---| -| **Puell Multiple** | `blockchain.info/charts/miners-revenue` + price (Coingecko) / MA365 | 🟢 | -| **Hash Ribbons** | `mempool.space/api/v1/mining/hashrate/3y` (MA30/MA60) | 🟢 | -| **MPI proxy** | `mempool.space` outflows top mining pool addresses + price | 🟡 (liste curated à maintenir) | - -**Sources testées mortes / payantes** : -- Glassnode `/v1/metrics/*` → 401 (full paywall) -- Coin Metrics community → 403 sur `SOPR`, `CapRealUSD`, `MVRV` (free = `PriceUSD` only) -- LookIntoBitcoin / Newhedge → 404 (UI-only, pas d'API) -- Bitaps UTXO age → endpoint mort - -**Reporter v2 (avec nœud BTC)** : SOPR, MVRV, NUPL, Supply in Profit, Reserve Risk, Accumulation Trend Score. - -**Métriques Prom** : -``` -ocb_btc_puell_multiple -ocb_btc_hash_ribbon_short -ocb_btc_hash_ribbon_long -ocb_btc_mpi_proxy -``` - ---- - -### Bench № 022 — Token Unlock Pressure *(P1, GREEN)* - -**Question** : pour chaque unlock à venir, distribution conditionnelle de l'impact prix attendu (basé sur 200 derniers unlocks comparables). - -**Sources retenues** : -- **CryptoRank Next.js data routes** (non-API, gratuit, sans auth) : - - `cryptorank.io/_next/data//en/token-unlock.json?page=N` → calendrier complet, 415 tokens - - `.../en/price//vesting.json` → schedule complet par token (batches passés + futurs) - - Bottleneck : `buildId` rotate à chaque deploy CR → scraper la home pour l'extraire dynamiquement (1 req/run) -- **DeFiLlama coins API** (free, no auth) : - - `coins.llama.fi/chart/coingecko:?start=&span=&period=1d` → prix daily depuis launch - - Burst 5 req séquentielles ~200ms sans throttling observé - -**Sources écartées** : DeFiLlama `/emissions` (402), Tokenomist (pas d'API publique), CryptoRank API officielle (401 sans clé), CoinGecko `market_chart/range` (bloqué free), Messari (paywall). - -**Risque schéma** : CryptoRank scraping non-API → monitor schema drift toutes les heures (test canary). - -**Métriques Prom** : -``` -ocb_unlock_upcoming{token, date, allocation} -ocb_unlock_expected_impact_pct{token, date} # médiane conditionnelle bucket %supply -ocb_unlock_historical_impact_pct{token, date, window} # J-30/J/J+30 returns -ocb_unlock_source_freshness_seconds -ocb_unlock_scrape_errors_total -``` - -**Backfill** : 200 unlocks ≈ 400 reqs total (1 vesting + 1 price chart par event). Faisable en 1 batch initial. - ---- - -### Bench № 023 — Stablecoin Issuer Transparency Score *(P3, PARTIAL)* - -**Question** : score multi-critère par issuer (freshness attestations, composition réserves, peg deviation under stress, mint/redeem latency, concentration holders). - -**Matrice sources** : - -| Issuer | Source | Format | Fréquence | Reproductibilité | -|---|---|---|---|---| -| USDC (Circle) | `circle.com/transparency` + DeFiLlama | HTML dashboard + PDF Deloitte | Mensuel | 🟢 HIGH | -| DAI/USDS (Sky) | On-chain Maker vaults + makerburn + DeFiLlama | JSON + RPC | Real-time | 🟢 HIGH | -| PYUSD (Paxos) | `paxos.com/pyusd-transparency` | PDF KPMG | Mensuel T+5bd | 🟡 MEDIUM (URL prévisible) | -| USDe (Ethena) | `app.ethena.fi/dashboards/transparency` + Dune | JS-rendered + custodian attestations | Real-time on-chain + monthly | 🟡 MEDIUM | -| USDT (Tether) | `tether.to/en/transparency` | SPA (curl renvoie shell) + PDF trimestriel | Trimestriel | 🔴 LOW | -| FDUSD (First Digital) | `firstdigitallabs.com/en/transparency` | 403 sur curl direct (Cloudflare) + PDF | Mensuel | 🔴 LOW | - -**Scope v1 — 4 issuers clean** : USDC, DAI/USDS, PYUSD, USDe → full 5-criteria score. - -**v2 — Couverture USDT/FDUSD** : worker PDF dédié (`pdftotext` + regex par template), métrique `transparency_lag_days` only au début. - -**Métriques Prom** : -``` -ocb_stablecoin_attestation_freshness_days{issuer} -ocb_stablecoin_reserve_composition_pct{issuer, category} # cash | treasury | rwa | crypto -ocb_stablecoin_top10_concentration_pct{issuer} -ocb_stablecoin_transparency_score{issuer} -``` - ---- - -### Bench № 024 — Bridge Flow Anomaly *(P2, PARTIAL)* - -**Source primaire retenue** : **Wormhole Scan** (free, sans clé) -``` -GET https://api.wormholescan.io/api/v1/x-chain-activity/tops - ?timespan={1h|1d|1mo}&from={ISO}&to={ISO} - &sourceChain={id}&targetChain={id} -``` - -**Source écartée** : DeFiLlama bridges → tous les endpoints `/bridges/*`, `/bridgevolume/*`, `/netflow/*` renvoient 402 (plan free supprimé). Aussi : Socket (401), LayerZero stats (DNS down), deBridge (404). - -**Couverture v1 — 8 paires Wormhole** : -1. ETH ↔ Solana -2. ETH ↔ Base -3. ETH ↔ Arbitrum -4. ETH ↔ BSC -5. ETH ↔ Polygon -6. ETH ↔ HyperEVM -7. Solana ↔ Base -8. Solana ↔ Arbitrum - -**Couverture v2** : canonical bridges L1↔L2 (Arbitrum Inbox, OP Portal, Base Portal) via scraping RPC direct → 10× plus de code mais nécessaire pour couvrir le flux non-Wormhole. - -**Anomaly detection** : z-score >3 sur fenêtre glissante 12 semaines (2016 points hourly). Trigger news. - -**Métriques Prom** : -``` -ocb_bridge_volume_usd{src_chain, dst_chain, window} -ocb_bridge_flow_zscore{src_chain, dst_chain} -ocb_bridge_anomaly_flag{src_chain, dst_chain} -``` - ---- - -### Bench № 025 — Oracle Deviation *(P1, GREEN)* - -**Extension du bench existant `chainlink-pricefeed`.** - -**4 oracles v1, tous free sans clé** : - -| Oracle | Endpoint | Latence | -|---|---|---| -| Chainlink | RPC reads (existant) | varies | -| Pyth | `hermes.pyth.network/api/latest_price_feeds?ids[]=` | ~200ms, ~30 req/s soft | -| Binance | `api.binance.com/api/v3/ticker/price` | 1200 req/min IP | -| Coinbase | `api.exchange.coinbase.com/products/

/ticker` | 10 req/s public | - -**Reporter v2** : -- Redstone — endpoints répondent mais payload signé long (~2KB/symbole, overhead réseau pour 30 paires × 30s) -- Uniswap v3 TWAP — `observe()` (pas `slot0`), decoder tick cumulatives, sqrtPriceX96 → prix décimal-aware, 2-hop via WETH/USDC pour tokens non-USD. Recommandé Alchemy/Infura free tier ou multi-RPC failover (publicnode flaky). - -**10 paires v1** : BTC, ETH, SOL, BNB, XRP, ADA, DOGE, AVAX, LINK, MATIC (toutes /USD). - -**Métriques Prom** : -``` -ocb_oracle_price{source, pair} -ocb_oracle_deviation_pct{pair, source_a, source_b} -ocb_oracle_update_latency_seconds{source, pair} -``` - ---- - -### Bench № 026 — Validator Economics Net of MEV *(P1, GREEN SOL+HL / PARTIAL ETH)* - -**Question** : pour ETH / SOL / HL, classer validators sur `yield_net = consensus + execution_tips + MEV − slashing − downtime`. - -**Verdict par chain** : - -| Chain | Yield brut | MEV captured | Downtime/Slashing | Verdict | -|---|---|---|---|---| -| **Solana** | 🟢 | 🟢 | 🟢 | **GREEN** | -| **Hyperliquid** | 🟢 | N/A (séquenceur centralisé, pas de MEV séparé) | 🟢 | **GREEN** | -| **Ethereum** | 🟡 | 🟢 | 🟡 | **PARTIAL** | - -**Sources confirmées free sans clé** : -- **Solana** : - - `api.stakewiz.com/validators` — APY total, staking_apy, jito_apy, commission, uptime, skip_rate, is_jito → 1 call = tous les validators - - `kobe.mainnet.jito.network/api/v1/validators` — mev_commission_bps, mev_rewards, priority_fee_rewards, active_stake -- **Hyperliquid** : `api.hyperliquid.xyz/info` type `validatorSummaries` — predictedApr day/week/month, uptimeFraction, isJailed, commission, stake -- **Ethereum (MEV-Boost)** : `boost-relay.flashbots.net/relay/v1/data/bidtraces/proposer_payload_delivered` + ~10 relays publics (ultrasound, agnostic, bloxroute) — même spec API. Mapping `proposer_pubkey → validator_index` via public beacon endpoint (`beaconstate.info`, `publicnode.com`) pour top-N. - -**Sources cassées / payantes** : -- Beaconcha.in — 401 sans clé (free tier 10 req/min insuffisant pour 1M validators) -- Rated Network — 401, fully gated depuis Q1 2026 -- Relayscan.io API — 404 (UI-only) -- mevboost.pics — redirige vers 404 - -**Scope v1** : -1. **Solana** (Stakewiz + Jito Kobe — full coverage) -2. **Hyperliquid** (~20 validators actifs, 1 endpoint) -3. **Ethereum top-100 proposers récents** (filtrer aux validators ayant proposé un bloc dans les 7 derniers jours via relay logs → réduit 1M → top-100 par stake/entity, évite besoin Beaconcha.in payant) - -**Métriques Prom** : -``` -ocb_validator_net_yield_bps{chain, validator} -ocb_validator_uptime{chain, validator} -ocb_validator_mev_share_bps{chain, validator} -ocb_chain_median_net_yield_bps{chain} # gauge pour alerte seuil -``` - ---- - -## 4. Couche transversale — "Make Data Talk" - -Indépendante des benches, à factoriser une fois : - -### 4.1 Threshold engine -Chaque métrique a un seuil (config YAML), franchissement → event posté sur un bus interne. 1 fichier, 1 mécanisme. - -```yaml -# thresholds/buyback.yml -- metric: ocb_buyback_ratio - protocol: hyperliquid - threshold: 0.80 - direction: below - severity: warning - message: "Hyperliquid buyback ratio drops below 80% of promise" -``` - -### 4.2 News events API -``` -GET /v1/events?since=&severity= -``` -Consommable par éditorial France Cryptos ou par un bot. - -### 4.3 Agent subscription (Telegram) -``` -POST /v1/agent/subscribe - { wallet, assets[], thresholds[], delivery: { kind: telegram, chat_id } } -``` -**C'est la différenciation vs DeFiLlama AI / SurfAI** : eux répondent à des questions, OCB *réveille* l'utilisateur sur sa watchlist. - -### 4.4 Chart export shareable -SVG/PNG endpoint avec logo center + toggle bar/line/area. 1 endpoint réutilisable par toutes les bench pages, plus simple que 1 composant React par bench. - ---- - -## 5. Roadmap d'exécution - -### Sprint 1 (3-4 semaines) — 4 benches P1, all free, all clean -- **№ 018** Buyback Execution Audit (Hyperliquid + GMX + Sky) -- **№ 022** Token Unlocks Pressure -- **№ 025** Oracle Deviation (4 oracles × 10 paires) -- **№ 026** Validator Economics — Solana + Hyperliquid d'abord - -Narrative éditoriale FC : "qui tient sa promesse", "qui dilue", "quel oracle est cassé", "qui valide bien". 4 angles éditoriaux distincts → 4 articles publiables au lancement. - -### Sprint 2 — 2 benches élargissant la couverture -- **№ 020** Perp Funding Spread (4 DEX REST en v1, on-chain en v2) -- **№ 024** Bridge Flow Anomaly (Wormhole en v1, canonical L2 en v2) -- **№ 026** Ethereum top-100 proposers (extension du bench 026 SOL/HL) - -### Sprint 3 — 2 benches avec caveats méthodo -- **№ 017** Real Earnings (avec proxy emissions schedule + disclaimer) -- **№ 023** Stablecoin Transparency (4 issuers clean : USDC + DAI + PYUSD + USDe) - -### Reporter / décisions business -- **№ 019** Sustainable DAU — sans budget Dune/Flipside payant ou ETL custom, ne pas shipper. Risque de décrédibiliser OCB avec heuristiques de surface. -- **№ 021** BTC On-Chain full (SOPR/MVRV/NUPL) — décision : budget ~50€/mo Hetzner pour nœud BTC + electrs ? Si oui, sprint 4. Sinon, ship version light "Mining & Cycle" en sprint 3. - ---- - -## 6. Patterns transversaux observés - -1. **L'API DeFiLlama free se réduit** : `/emissions` et `/bridges` sont passés 402. À surveiller : `/fees` et `/revenue` toujours free aujourd'hui mais pas garanti. → caching agressif + plan B systématique par bench. -2. **Etherscan V2 unifié** (1 clé free, 5 req/s, 100k/jour, multi-chain ETH+Arb+Base+OP+...) = couvre Maker/GMX/Aave en une clé. À mutualiser. -3. **CryptoRank Next.js data routes** = gold mine pour unlocks/vesting, mais hors API officielle → fragile, monitorer schema drift. -4. **Stable backbone OCB (5 APIs)** sans clé, sans rate-limit sérieux à privilégier : - - Hyperliquid Info API - - Wormhole Scan - - Stakewiz + Jito Kobe (Solana validators) - - Pyth Hermes - - DeFiLlama coins (prix historique) - ---- - -## 7. Décisions ouvertes (à trancher avant Sprint 1) - -- [ ] Budget Hetzner ~50€/mo pour nœud BTC complet (débloque bench 021 v2 : SOPR/MVRV/NUPL) ? -- [ ] Bench 019 Sustainable DAU : ship version light avec disclaimer fort, ou reporter complètement ? -- [ ] Quel host pour les 4 nouveaux harness P1 ? Railway Mobula comme les autres ? -- [ ] Threshold engine + News API + TG agent endpoint : projet OCB-core ou repo séparé `ocb-events` ? diff --git a/docs/solana-landing-active-bench-plan.md b/docs/solana-landing-active-bench-plan.md deleted file mode 100644 index 5b70f6cf..00000000 --- a/docs/solana-landing-active-bench-plan.md +++ /dev/null @@ -1,31 +0,0 @@ -# Solana TX Landing - Plan obsolète - -> ⚠️ **Ce document est obsolète depuis 2026-05-21.** -> -> Direction validée par Florent : ship **V0-Lean** (5 services × 1 région × 1 / heure × **$159/mo**) au lieu de l'ancien "Phase 0" à 8 services × 3 régions. -> -> Le plan courant est dans [`solana-landing-tiered-architecture.md`](./solana-landing-tiered-architecture.md). -> -> Le cost-model détaillé est dans [`solana-landing-cost-model.md`](./solana-landing-cost-model.md) - note de correction en tête du fichier. - ---- - -## Ce qui a changé - -| Avant (ce doc) | Après (tiered-architecture.md) | -|---|---| -| 8 services × 3 régions × 2 min | 5 services × 1 région × 60 min | -| Phase 0 = $1 452/mo (chiffre faux, vrai = $26 k/mo) | V0-Lean = $159/mo (calcul vérifié) | -| Services V0 : Jito + Helius + Nozomi + NextBlock | Services V0-Lean : Jito + Helius + Nozomi + Astralane + 0slot | -| Launch immédiat avec scope complet | Phasage : V0-Lean → V0-Daily → V1 → V2 sur signature sponsor | - -## Ce qui reste valide depuis ce doc - -- **Le Jito control probe** pour Helius/Nozomi/Astralane fan-out (gardé dans tiered-architecture §5). -- **Les 7 règles méthodologie sponsor-proof** (gardées dans tiered-architecture §6). -- **Le tier ladder Listed / Verified / Featured** pour le sponsoring (gardé). -- **L'ordre d'outreach sponsor** : Nozomi en premier (contact direct), 0slot ensuite via Discord. - -## Conservé pour archive - -Le contenu original n'est plus à jour mais reflète l'analyse initiale des 4 agents (provider matrix, architecture, cost model, sponsor bias). Si besoin de retrouver les détails par service (bloXroute, NextBlock, SVS qui sont reportés V1+), voir le rapport de l'agent provider matrix dans le transcript de la conversation du 2026-05-21. diff --git a/docs/solana-landing-cost-model.md b/docs/solana-landing-cost-model.md deleted file mode 100644 index 5180b3d2..00000000 --- a/docs/solana-landing-cost-model.md +++ /dev/null @@ -1,158 +0,0 @@ -# Solana Tx-Landing Benchmark - Cost Model - -> ⚠️ **Correction 2026-05-21 :** la table de scénarios §3 contient une erreur d'arithmétique d'un facteur ~18× sur les coûts mensuels. Le coût réel d'un "Phase 0" tel que défini ici (8 svc × 3 reg × 2 min) est **~$26 140/mo** et non $1 452/mo. Voir la note de correction §3 corrigée. -> -> **Le plan courant n'utilise plus ce scope.** Le launch validé est V0-Lean (5 svc × 1 reg × 60 min × $159/mo) - voir [`solana-landing-tiered-architecture.md`](./solana-landing-tiered-architecture.md). Les sections §0 (assumptions), §1 (formule), §2 (statistical power), §4 (leviers), §5 (sensibilité), §6 (sponsorship) restent valides. Seul le tableau §3 (scenarios) est faux. - ---- - -> Active probing of 8 landing services × 3 regions, 24/7. Real signed mainnet txs. -> SOL price snapshot: **$86.20** (CoinGecko + Binance, 2026-05-21). Sensitivity from $80 to $300 shown in §5. - ---- - -## 0. Assumptions (explicit) - -| Variable | Value | Source / rationale | -|---|---|---| -| SOL price | $86.20 | CoinGecko `simple/price` 2026-05-21 | -| Solana base fee | 5,000 lamports/sig | Protocol constant | -| Priority fee CU price | 50,000 micro-lamports / CU | Median competitive level for trading txs | -| Compute units per probe | 50,000 CU | A minimal SOL self-transfer + tip transfer + memo | -| Priority fee per probe | 50,000 × 50,000 / 1e6 = **2,500 lamports** | CU price × CU | -| Probe fails ~ wasted tip | ~5% (we still pay tip on landing path; failed sends refund tip on some services) | Conservative | -| Services | 8 (Jito, Helius Sender, Nozomi, bloXroute, Astralane, 0slot, NextBlock, SVS) | Per spec | -| Regions | 3 (us-east, eu-west, sgp) | Per spec | -| Probe = 1 signed tx submitted to 1 service from 1 region | | | - -**Tip floor research (lamports per probe, "realistic competitive" = what you must pay to be representative of trading-bot traffic, not the doc-stated floor):** - -| Service | Doc floor | Competitive floor | Source | -|---|---:|---:|---| -| Jito Block Engine | 1,000 | **10,000** | [docs.jito.wtf](https://docs.jito.wtf/lowlatencytxnsend/) | -| Helius Sender | 1,000 | **10,000** | [helius.dev/docs](https://www.helius.dev/docs/sending-transactions/sender) | -| Nozomi (Temporal) | 1,000,000 | **1,000,000** | [use.temporal.xyz](https://use.temporal.xyz/nozomi/tipping-and-faq) | -| bloXroute Trader | 1,000,000 | **1,000,000** | [docs.bloxroute.com](https://docs.bloxroute.com/solana/trader-api/introduction/tip-and-tipping-addresses) | -| Astralane Iris | ~1,000,000 (refundable) | **500,000** (net of avg refund) | [astralane.gitbook.io](https://astralane.gitbook.io/docs/low-latency/submit-transactions/tip-refunds) | -| 0slot | 1,000,000 | **1,000,000** | [0slot.trade](https://0slot.trade/) | -| NextBlock | 1,000,000 | **1,000,000** | [docs.nextblock.io](https://docs.nextblock.io/) | -| SolanaVibeStation | 100,000 | **100,000** | [docs.solanavibestation.com](https://docs.solanavibestation.com/services/solana-node-services/lightspeed-transactions) | - -**Weighted-avg tip across 8 services** = (10k + 10k + 1M + 1M + 500k + 1M + 1M + 100k) / 8 = **577,500 lamports/probe**. - ---- - -## 1. Probe cost formula - -``` -cost_per_probe (lamports) = 5,000 (base) + 2,500 (priority) + service_tip -cost_per_probe (USD) = lamports × 1e-9 × SOL_USD -``` - -Per-probe USD cost at SOL = $86.20: - -| Service | Lamports | USD/probe | -|---|---:|---:| -| Jito | 17,500 | $0.00151 | -| Helius Sender | 17,500 | $0.00151 | -| SolanaVibeStation | 107,500 | $0.00927 | -| Astralane | 507,500 | $0.04374 | -| Nozomi | 1,007,500 | $0.08685 | -| bloXroute | 1,007,500 | $0.08685 | -| 0slot | 1,007,500 | $0.08685 | -| NextBlock | 1,007,500 | $0.08685 | -| **Sum / probe-set (all 8)** | **4,680,000** | **$0.4034** | - -A "probe-set" = 1 tx to each of the 8 services. Cost per probe-set per region = $0.4034. -A "full sweep" = 1 probe-set × 3 regions = **$1.210 / sweep**. - ---- - -## 2. Statistical power requirement - -Detecting a 5% absolute difference between two services at p₀ = 95% landing rate, α = 0.05, power = 0.80, two-proportion z-test: - -``` -n = (z_α/2 + z_β)² × [p1(1-p1) + p2(1-p2)] / (p1-p2)² -n = (1.96 + 0.84)² × [0.95·0.05 + 0.90·0.10] / 0.05² -n = 7.84 × 0.1375 / 0.0025 ≈ 431 probes per service per arm -``` - -So **~430 probes per service per region** to call a 5pp gap. To resolve the same gap **per hour** (e.g., detect a leader-rotation effect within a single hour window) you need ~430 probes/hour/service/region = **1 probe every 8.4 seconds per (service, region)**. That's the upper bound; weekly aggregation needs only ~2.5 probes/hour. - -For a 2pp gap (95% vs 93%) the requirement balloons to ~2,600/service/region - only Phase 1+ budgets reach this. - ---- - -## 3. Scenarios - -| | Probe interval | Sweeps/day | Daily probes (8 svc × 3 reg) | Daily USD | **Monthly USD** | Statistical resolution | -|---|---|---:|---:|---:|---:|---| -| **Micro** | 1 / 10 min | 144 | 3,456 | $9.69 | **$291** | Daily aggregation only; detects 5pp gaps over ~3 days | -| **Phase 0** | 1 / 2 min | 720 | 17,280 | $48.41 | **$1,452** | Detects 5pp gaps per service/region per **6h window**; daily leader-cycle resolution | -| **Phase 1** | 1 / 30 sec | 2,880 | 69,120 | $193.62 | **$5,809** | Detects 5pp gaps **per hour**; supports 2 tip tiers per service (low/high) → cost ×2 within budget by shrinking to 1/min | -| **Phase 2** | 1 / 10 sec | 8,640 | 207,360 | $580.86 | **$17,426** | 2pp gaps per hour, full leader-rotation (~4-slot) resolution; saturates statistical power for current scope | - -### Defending Phase 0 = $1.2k/mo - -Florent's number is **slightly conservative**: my model puts true Phase 0 at $1,452 at SOL=$86. At Florent's likely working assumption of SOL=$150 the same cadence costs **$2,527/mo** - so $1.2k/mo only holds at today's price OR with a slightly slower cadence (1 sweep per 2.5 min instead of 2 min, which still gives 6h 5pp resolution). The figure is defensible if disclosed with the SOL-price assumption. - -### What each phase unlocks - -- **Micro ($291):** dashboard demo + weekly methodology post. No intra-day signal. -- **Phase 0 ($1.2–1.5k):** public leaderboard with daily updates; can argue "service A beat service B today" within 6h windows. **Recommended launch tier.** -- **Phase 1 ($5.8k):** hourly leaderboard + tip-tier experiments (run each service at floor AND competitive, exposing whether bloXroute's higher mandatory tip actually buys landing). This is where the bench becomes a research product, not a dashboard. -- **Phase 2 ($17.4k):** diminishing returns on Solana alone. The marginal $ is better spent adding chains (Sui, Aptos, BSC priority lanes) or stake-weighted-QoS variants. - ---- - -## 4. Cost levers ranked by elasticity (signal-per-$) - -| Lever | Cost elasticity | Signal elasticity | Verdict | -|---|---|---|---| -| **Tip size on Nozomi/bX/0slot/NB** | Linear, dominant (5 of 8 services @ 1M lamports = 86% of probe cost) | High - these services' landing % is tip-sensitive; we MUST run ≥2 tip tiers to be honest | **#1 lever**: split budget across tip tiers, not more cadence | -| **Cadence** | Linear | Sub-linear (√n in CI width) | #2 - doubling cadence only narrows CI by 1.41× | -| **Regions** | Linear ×3 | High once - first region anchors, 2nd/3rd reveal geo edge but with diminishing returns | #3 - keep all 3, don't add a 4th | -| **# services** | Linear | High but bounded by market (only 8 services exist worth measuring) | Fixed at 8 | -| **SOL price** | Linear, exogenous | Zero | Hedge: hold 30-day SOL float to smooth | - -**Punchline:** the cheapest way to buy 2× more signal is **not** to double cadence - it's to split existing cadence across 2 tip tiers per service. Same budget, exposes the price-of-landing curve. - ---- - -## 5. Sensitivity table (Phase 0 baseline = $1,452/mo) - -| Parameter | -50% | base | +50% / +10× / +2× | -|---|---:|---:|---:| -| SOL price ($80 / $150 / $300) | $1,348 | $1,452 | $5,052 | -| Tip size (÷10× / base / ×10×) | $169 | $1,452 | $14,420 | -| Cadence (÷2 / base / ×2) | $726 | $1,452 | $2,904 | - -Tip size dominates - a 10× shift in tip assumption moves the bench ~10× in cost. SOL price is the most volatile real-world driver; a SOL run to $300 nearly 4× the bench cost (because the lamport tips of the big-5 services are denominated in lamports, not USD). - ---- - -## 6. Sponsorship economics - -**Break-even on Phase 0 ($1,452/mo):** if we charge a "Verified" tier at $500/mo, **3 sponsors** fund the bench. At $1,000/mo, **2 sponsors**. Phase 1 ($5.8k) needs ~6 sponsors at $1k or 3 at $2k. - -### Methodologically-clean tier ladder - -| Tier | Price | What it buys (METHODOLOGICALLY OK) | What it explicitly does NOT buy | -|---|---|---|---| -| **Listed** | $0 | Inclusion in the public benchmark, default tip tier, public CSV exports | - | -| **Verified** | $500/mo | Logo on dashboard, methodology AMA quote, access to raw per-probe latency CSV, monthly 1-pager with their service's percentiles cited in our newsletter | Score adjustments | -| **Featured** | $2,000/mo | All Verified + a **2nd tip tier** probed for their service (so they can advertise "at 5M lamports we land 99.2% - measured by OpenChainBench"), geographic-edge add-on (we add a 4th region of their choice for their service only), newsletter co-write | Score adjustments, exclusivity over competitors | -| **Research partner** | $5,000/mo | All Featured + bespoke A/B experiment design (e.g., "test your new gRPC endpoint vs your REST endpoint for 30 days"), data API access | Anything that biases reported public numbers | - -**Hard rule:** no tier ever modifies a service's headline landing rate or latency percentile shown on the public leaderboard. Sponsorship buys **more measurement, more distribution**, never a better score. This is the methodological cliff we cannot cross without becoming Gartner Magic Quadrant. - ---- - -## 7. Recommendation - -**Launch with Phase 0 ($1,452/mo at SOL=$86, ~$2.5k/mo at SOL=$150).** Cadence of 1 sweep every 2 minutes across 8 services × 3 regions gives a daily-updated public leaderboard with 5pp statistical resolution per 6-hour window - enough to make defensible public claims while staying lean. Pre-sell 2 Verified sponsors ($500/mo each) before launch to halve net burn; pitch Featured tier ($2k/mo, methodologically-clean 2nd-tip-tier slot) to Helius or bloXroute since they're the most likely to want a tip-elasticity story. Upgrade to Phase 1 only once we have ≥4 paying sponsors and a clear research question that needs hourly resolution (e.g., "does Jito's BAM rollout move landing rates?"). Phase 2 is a trap - spend that money on adding a second chain instead. - ---- - -**Word count:** ~1,180. Last updated 2026-05-21. diff --git a/docs/solana-landing-deployment-checklist.md b/docs/solana-landing-deployment-checklist.md deleted file mode 100644 index 397bb776..00000000 --- a/docs/solana-landing-deployment-checklist.md +++ /dev/null @@ -1,250 +0,0 @@ -# Solana TX Landing - Deployment Checklist (V0-Lean) - -> Liste exhaustive de ce dont tu as besoin pour passer du code committé à un bench actif en prod. Ordre conseillé : lis tout, puis suis les étapes 1 → 8. - ---- - -## 0. État actuel - ce qui est déjà fait - -✅ Code écrit, compile, vet propre. 4 fichiers dans `mobula-api/miniapps/solana-tx-landing/cmd/script/` : -- `prober.go` (NEW) - boucle de probe, build/sign tx, polling -- `senders.go` (NEW) - HTTP par service (Jito, Helius, Nozomi, Astralane, 0slot) -- `active_metrics.go` (NEW) - métriques Prom -- `main.go` (EDITED) - lance la goroutine prober en plus du subscriber - -✅ Méthodologie pré-enregistrée dans `OpenChainBench/docs/methodology/solana-tx-landing-active.md` - -✅ Le prober est **opt-in** : si `SOLANA_PROBE_KEYPAIR_BASE58` n'est pas set, il logge `[prober] disabled: ...` et le bench reste en mode observationnel pur. Donc déployer le code sans configurer les secrets ne casse rien. - ---- - -## 1. Générer + funder le keypair Solana - -```bash -# Sur ta machine locale (PAS sur Railway - la clé privée ne doit jamais -# transiter par git ou stdout sur un serveur) -solana-keygen new --no-bip39-passphrase -o ~/probe-keypair-us-east.json - -# Note l'adresse publique -solana address -k ~/probe-keypair-us-east.json - -# Récupère la base58 de la clé privée (à mettre en env var Railway) -# Le fichier JSON contient un tableau de 64 bytes ; on peut le convertir : -node -e "console.log(require('bs58').encode(Buffer.from(JSON.parse(require('fs').readFileSync(process.env.HOME+'/probe-keypair-us-east.json')))))" -# OU avec Python: -# python3 -c "import json, base58; print(base58.b58encode(bytes(json.load(open('/Users/user/probe-keypair-us-east.json')))).decode())" -``` - -**Funder le keypair** : envoie ~1 SOL (~$86) sur l'adresse publique depuis ton wallet perso. À V0-Lean cadence (1/h, 5 services), 1 SOL dure ~2 mois. Le bench logge un warning quand le balance passe sous 0.3 SOL. - -⚠️ **Stocke le fichier `probe-keypair-us-east.json` quelque part de safe** (1Password / coffre Mobula). Si tu le perds, les fonds restent récupérables via la base58 que tu auras mise en Railway - mais inversement, si Railway leak la base58, anyone peut vider le wallet. Le risque est limité à 1 SOL. - ---- - -## 2. Apply pour les API keys - -| Service | Comment apply | Délai estimé | Notes | -|---|---|---|---| -| **Nozomi** | Contact direct (Florent → Temporal Labs) + form `temporal.xyz` | Quelques jours (contact direct accélère) | Pitch : OCB bench, paie ses propres probes en SOL credits | -| **Astralane** | Form sur `astralane.io` | Variable | Plans flexibles, no public price | -| **0slot.trade** | Discord `kurt0slot` ou Telegram `@kurt0slot` | Rapide (manuel) | Première semaine gratuite, puis Trial/Entry/Intermediate/Advanced tier | -| **Jito UUID** *(optional)* | Ticket via `discord.gg/jito` | Variable | Augmente le rate limit au-delà des 1 req/s par IP | - -**Si une clé n'est pas obtenue**, le service est simplement skippé au launch (log `[prober] : not set - service skipped`). Le bench tourne avec les services restants. Tu peux ajouter les services au fur et à mesure. - -**Reco order** : Nozomi → 0slot → Astralane → Jito UUID. Les 2 premiers sont les plus impactants pour la cardinalité du bench. - ---- - -## 3. Setup les env vars Railway - -Service Railway : **`solana-tx-landing`** (existing - pas besoin de créer un nouveau service en V0-Lean ; on déploie le code sur le service existant qui devient hybride observational + active). - -| Env var | Required? | Valeur | Notes | -|---|---|---|---| -| `SOLANA_PROBE_KEYPAIR_BASE58` | **OUI** (active le prober) | base58 du keypair généré en §1 | Sans ça, prober disabled | -| `SOLANA_PROBE_REGION` | non (def: `us-east`) | `us-east` | Label Prom | -| `SOLANA_PROBE_INTERVAL` | non (def: `1h`) | `1h` pour V0-Lean | Go duration : `30m`, `15m`, etc. pour escalader | -| `SOLANA_PROBE_RPC_URL` | non | `https://api.mainnet-beta.solana.com` | RPC public mainnet pour les reads (getSlot, getSignatureStatuses, getBalance) | -| `SOLANA_PROBE_SERVICES` | non (def: tous) | `jito,helius-sender,nozomi,astralane,0slot` | Liste comma-séparée. Permet de skip explicitement | -| `NOZOMI_API_KEY` | non | clé obtenue en §2 | Skip Nozomi si absent | -| `ASTRALANE_API_KEY` | non | clé obtenue en §2 | Skip Astralane si absent | -| `ZEROSLOT_API_KEY` | non | clé obtenue en §2 | Skip 0slot si absent | -| `JITO_AUTH_UUID` | non | UUID obtenu en §2 | Augmente rate limit Jito | - -**Overrides pour le tip floor** (rarement utiles, mais possibles) : -- `JITO_TIP_LAMPORTS` (def 10_000) -- `HELIUS_TIP_LAMPORTS` (def 10_000) -- `NOZOMI_TIP_LAMPORTS` (def 1_000_000) -- `ASTRALANE_TIP_LAMPORTS` (def 500_000) -- `ZEROSLOT_TIP_LAMPORTS` (def 1_000_000) - -⚠️ **Tout changement de tip est une modification méthodologique** = PR + 14 jours de comment window selon Rule #1. - -**Overrides pour les endpoints** (escape hatch ops si un provider change de host sans préavis) : -- `NOZOMI_ENDPOINT` (def `https://ewr.nozomi.temporal.xyz/`) -- `ASTRALANE_ENDPOINT` (def `https://ny.gateway.astralane.io/iris`) -- `ZEROSLOT_ENDPOINT` (def `https://ny.0slot.trade`) - -Pas de override pour Jito ou Helius - leurs hosts sont hardcodés dans `senders.go` (modifier requiert PR méthodologique). - -**Métrique opérationnelle additionnelle :** `solana_landing_probe_enabled{region}` (gauge, 0 ou 1) - permet de distinguer sur le dashboard "prober désactivé" (env var pas set) vs "prober planté" (set mais aucune cycle récente). - ---- - -## 4. Setup Prometheus (rien à toucher) - -Le service Railway `solana-tx-landing` est déjà scrapé par le Prom partagé OCB sur `:2112/metrics`. Les nouvelles métriques `solana_landing_probe_*` apparaîtront automatiquement dès le premier redeploy. **Pas besoin de modifier `miniapps/openchainbench-monitoring/prometheus/prometheus.yml`.** - -Métriques exposées en V0-Lean : -``` -solana_landing_probe_success_total{service, mode, region} -solana_landing_probe_dropped_total{service, mode, region, reason} -solana_landing_probe_latency_slots{service, mode, region} -solana_landing_probe_latency_slots_histogram{service, mode, region} -solana_landing_probe_latency_ms{service, mode, region} -solana_landing_probe_latency_ms_histogram{service, mode, region} -solana_landing_probe_keypair_balance_sol{region} -solana_landing_probe_cycle_total{region} -solana_landing_probe_last_cycle_timestamp_seconds{region} -``` - -Cardinalité totale : ~30 séries. Négligeable pour notre Prom. - ---- - -## 5. Workflow Git pour shipper - -Tu es actuellement sur `feat/france-cryptos-sprint1` sur `mobula-api`. **Ne push pas sur `dev`.** - -```bash -cd /Users/user/mobula/mobula-api - -# Crée une branche dédiée si tu veux isoler le prober du reste du sprint -git checkout -b feat/solana-landing-active-prober - -# Lint avant de committer (CLAUDE.md global rule) -bun lint:fix - -# Stage uniquement les fichiers du prober -git add miniapps/solana-tx-landing/cmd/script/active_metrics.go \ - miniapps/solana-tx-landing/cmd/script/prober.go \ - miniapps/solana-tx-landing/cmd/script/senders.go \ - miniapps/solana-tx-landing/cmd/script/main.go \ - miniapps/solana-tx-landing/go.mod \ - miniapps/solana-tx-landing/go.sum - -git commit -m "solana-tx-landing: add active landing prober (V0-Lean)" -git push -u origin feat/solana-landing-active-prober -``` - -**Pour OpenChainBench (les docs)** : -```bash -cd /Users/user/mobula/OpenChainBench - -git checkout -b feat/solana-landing-active-methodology -git add docs/methodology/solana-tx-landing-active.md \ - docs/solana-landing-tiered-architecture.md \ - docs/solana-landing-cost-model.md \ - docs/solana-landing-active-bench-plan.md \ - docs/solana-landing-deployment-checklist.md - -git commit -m "docs: add Solana TX landing active bench plan + methodology" -git push -u origin feat/solana-landing-active-methodology -``` - -**Liens PR à créer manuellement après push :** -- `mobula-api` → PR vers `dev` (URL générée par GitHub après `git push`) -- `OpenChainBench` → PR vers `main` - -⚠️ **Ordre important** : la méthodologie OCB DOIT être mergée AVANT toute conversation sponsor (Rule #1 : pre-registered methodology before any contract). - ---- - -## 6. Première vérification post-déploiement - -Une fois Railway redéployé avec `SOLANA_PROBE_KEYPAIR_BASE58` set : - -```bash -# Logs Railway - chercher le banner du prober -# Tu devrais voir: -# [prober] enabled - region=us-east interval=1h0m0s services=N -# · jito mode=default tip=10000 lamports endpoint=https://... -# · helius-sender mode=swqos_only tip=10000 lamports endpoint=http://... -# · ... - -# Après ~5 secondes (le warmup) : -# [prober] cycle abc123… done in 8.234s -``` - -Métriques à vérifier dans Prometheus (via Grafana ou query directe) : -```promql -# Probes lancées -sum(rate(solana_landing_probe_cycle_total[1h])) * 3600 -# = doit être ≈ 1.0 (1 cycle par heure) - -# Landing rate par service (rolling 7 jours) -sum(rate(solana_landing_probe_success_total[7d])) by (service) -/ -(sum(rate(solana_landing_probe_success_total[7d])) by (service) + - sum(rate(solana_landing_probe_dropped_total{reason="timeout"}[7d])) by (service)) - -# Keypair balance (doit décroître lentement) -solana_landing_probe_keypair_balance_sol{region="us-east"} -``` - ---- - -## 7. Spec OCB côté site (à faire APRÈS la méthodologie mergée) - -Le fichier `OpenChainBench/benchmarks/solana-tx-landing.yml` actuel décrit la version observational uniquement. À étendre : - -1. Ajouter une section pour les nouvelles métriques (`solana_landing_probe_*`) -2. Ajouter le champ `sponsorship` avec le disclosure block (cf §6 de tiered-architecture.md) -3. Ajouter une référence vers la méthodologie pré-enregistrée -4. *Optionnel* : étendre `src/lib/spec.ts` pour supporter le rendu 2-tabs (Market Share + Landing Latency) - à voir si nécessaire ou si on rend tout dans une seule page allongée - -À faire dans une PR séparée pour découpler infra (mobula-api) et site (OpenChainBench). - ---- - -## 8. Sponsor outreach - DEUX semaines après que la méthodologie soit mergée - -| Étape | Action | -|---|---| -| W+0 | Méthodologie publique mergée sur `OpenChainBench/main` | -| W+1 | Bench tourne en prod, première data semaine arrive | -| W+2 | Premier ping Nozomi avec : link méthodologie + first-week data preview + ask SOL credits | -| W+3 | Nozomi → Featured tier ($1.5-2.5k/mo équivalent SOL ou cash). Avec ça V0-Lean → V1 ($580/mo, OCB net ~$300). | -| W+4 | Ping 0slot via Discord. Idem ask. | -| W+8 | Ré-évaluer : si on a 2 sponsors et la story geographic edge demandée → escalade vers V2 (3 régions). | - ---- - -## 9. Décisions encore ouvertes (à toi de trancher) - -| # | Décision | Reco par défaut | -|---|---|---| -| A | Disclose à Jito/Helius/Nozomi qu'on les probe ? | **Oui**, avant launch - email courte annonçant le bench public | -| B | Renommer le service Railway `solana-tx-landing` → `-us` pour cohérence multi-région future ? | **Oui**, geste de cleanup | -| C | Si Nozomi répond "non" au sponsoring, on probe quand même ? | **Oui**, méthodologie dit "sponsors ne contrôlent pas l'inclusion" | -| D | Configurer un alert Slack sur `solana_landing_probe_keypair_balance_sol < 0.3` ? | **Oui**, sinon on rate des cycles silencieusement | -| E | Activer Helius en dual-mode (en plus de swqos_only) ? | **Pas en V0-Lean.** Méthodologie figée. À reconsidérer en v1.0.1 PR | - ---- - -## Annexe - Que faire si quelque chose plante - -| Symptôme | Cause probable | Fix | -|---|---|---| -| `[prober] disabled: SOLANA_PROBE_KEYPAIR_BASE58 not set` | Env var pas configurée | Set dans Railway settings | -| `[prober] disabled: decode keypair: invalid base58` | Mauvais encoding du keypair | Re-run la commande de §1 | -| `[prober] disabled: no services configured` | Aucune clé sponsor + `SOLANA_PROBE_SERVICES` mal écrit | Vérifier que Jito + Helius (sans clé) sont au moins là | -| `[prober][nozomi] submit: rpc error -32xxx` | Clé invalide ou expirée | Re-issue avec Temporal | -| `[prober][...] submit: http: dial tcp ... no such host` | DNS Railway / endpoint typo | Vérifier l'endpoint dans senders.go | -| Keypair balance ne décroît pas | Service `solana-tx-landing` n'a pas le keypair env | Vérifier les secrets Railway | -| Balance décroît plus vite que prévu | Tip floor mal configuré ou cycle interval trop court | Vérifier `SOLANA_PROBE_INTERVAL` et `*_TIP_LAMPORTS` | - ---- - -**Last updated :** 2026-05-21 - V0-Lean (5 services × us-east × 1 h cadence × $159/mo théorique). diff --git a/docs/solana-landing-tiered-architecture.md b/docs/solana-landing-tiered-architecture.md deleted file mode 100644 index aad72ce1..00000000 --- a/docs/solana-landing-tiered-architecture.md +++ /dev/null @@ -1,289 +0,0 @@ -# Solana TX Landing Bench - Launch Plan (V0-Lean) - -> **Direction validée 2026-05-21.** On lance V0-Lean : 5 services × 1 région × cadence 1 h, **$159/mo** à SOL=$86.20. Escalade par triggers explicites (voir §7). - -Compagnon : [`solana-landing-cost-model.md`](./solana-landing-cost-model.md) pour les calculs détaillés. - ---- - -## 1. Les 5 services qu'on probe (V0-Lean) - -| # | Service | Tip floor (lamports) | Coût / probe | Rôle dans le bench | -|---|---|---:|---:|---| -| 1 | **Jito Block Engine** | 10 000 | $0.0015 | Baseline + *control probe* pour Helius/Nozomi/Astralane (fan-out) | -| 2 | **Helius Sender** | 10 000 (`swqos_only=true`) | $0.0015 | Le plus utilisé, anycast + 7 POPs | -| 3 | **Astralane Iris** | 500 000 (net refunds) | $0.0437 | Angle unique : tip refunds | -| 4 | **Nozomi (Temporal Labs)** | 1 000 000 | $0.0868 | Premium tier, **sponsor cible #1 (contact direct Florent)** | -| 5 | **0slot.trade** | 1 000 000 | $0.0868 | Premium tier, anti-MEV + durable-nonce | - -*Coût par probe = 5 000 base + 2 500 priority + tip floor lamports, converti à SOL=$86.20.* - -**Pas dans V0-Lean (réservés V1+) :** bloXroute, NextBlock, SolanaVibeStation - tous demandent un onboarding manuel (sales call, form, paid plan) qui ralentirait le launch. On les ajoute quand le 1er sponsor est signé. - ---- - -## 2. Architecture - -``` - ┌────────────────────────────────┐ - │ Railway us-east │ - │ Service: solana-tx-landing-us │ - │ Keypair: 1 SOL (~$86) │ - │ Auto-topup alert si < 0.3 SOL │ - └────────────────┬───────────────┘ - │ toutes les 60 min - ▼ - ┌─────────────────────────────────┐ - │ Probe cycle (PARALLELE) │ - │ 5 tx signées simultanément │ - │ Payload: self-transfer + memo │ - └───┬────┬────┬────┬────┬─────────┘ - │ │ │ │ │ - ▼ ▼ ▼ ▼ ▼ - Jito Helius Astralane Nozomi 0slot - │ │ │ │ │ - │ │ (1) mode swqos_only │ - │ │ (2) mode default │ - ▼ ▼ ▼ ▼ ▼ - ════════ Solana mainnet ════════ - │ - ▼ - getSignatureStatuses() poll 1s, timeout 60s - │ - ▼ - ┌─────────────────────────────────────┐ - │ Prometheus :2112 │ - │ solana_landing_probe_success_total │ - │ solana_landing_probe_latency_slots │ - │ solana_landing_probe_latency_ms │ - │ solana_landing_probe_dropped_total │ - │ labels: service, mode, region │ - └─────────────────┬───────────────────┘ - ▼ - prometheus-production-0859.up.railway.app - (scrape par le Prom partagé OCB déjà déployé) - ▼ - openchainbench.com /benchmarks/solana-tx-landing - ┌─────────────────────────────────────────────┐ - │ Tab 1 - Market Share (observationnel, │ - │ garde la logique tip-wallet existante)│ - │ Tab 2 - Landing Latency (NEW, active probe) │ - │ • Leaderboard hebdomadaire │ - │ • p50 / p99 par service │ - │ • Histogram time-to-land │ - └─────────────────────────────────────────────┘ -``` - ---- - -## 3. Maths du coût - -``` - Services : 5 - Région : 1 (us-east) - Cadence : 1 cycle / heure - Probes / jour : 5 × 24 = 120 - Cycles / mois : 24 × 30 = 720 - - Coût par cycle (5 probes en parallèle) : - Jito $0.0015 - Helius $0.0015 - Astralane $0.0437 - Nozomi $0.0868 - 0slot $0.0868 - ─────── - TOTAL / cycle $0.2204 - - Mensuel : 720 × $0.2204 = $158.73/mo -``` - -**Ventilation par service :** - -| Service | $/mo | % du budget | -|---|---:|---:| -| Nozomi | $62.53 | 39.4% ████████ | -| 0slot | $62.53 | 39.4% ████████ | -| Astralane | $31.50 | 19.8% ████ | -| Helius | $1.09 | 0.7% | -| Jito | $1.09 | 0.7% | -| **Total** | **$158.73** | 100% | - -→ **3 services premium = 98.6% du budget.** C'est là qu'il faut négocier des SOL credits sponsor. - ---- - -## 4. Le levier sponsor - SOL credits, pas cash - -Au lieu de demander du cash à Nozomi : -- **Ask :** "Vous payez vos propres frais d'évaluation. ~8 SOL / trimestre couvre votre slot Nozomi dans le bench." -- **C'est plus naturel** qu'un sponsor cash : ils financent leur propre mesure (pas le bench global). -- **Effet sur l'économie OCB :** - -| Scenario sponsor | OCB net $/mo | -|---|---:| -| Aucun sponsor | $158.73 | -| Nozomi paye ses probes en SOL | $96.20 | -| Nozomi + 0slot payent leurs probes | **$33.66** | -| Nozomi + 0slot + Astralane | $2.18 | - -Astralane n'est probablement pas un bon premier ask (plus petit acteur), mais Nozomi + 0slot c'est jouable. - ---- - -## 5. Méthodologie - ce qu'on mesure, comment - -### Probe payload -Self-transfer de 1 lamport + Memo program (8 octets aléatoires). ~5 000 lamports de frais base. Pas de mutation de state extérieur, pas de risque de perte. - -### Le Jito control probe -Helius (mode default), Nozomi, Astralane font tous du fan-out vers Jito en interne. Sans contrôle, on ne sait pas si "Nozomi a landé" ou "Jito a landé pour le compte de Nozomi". - -**Solution :** Jito est probé *en même cycle* que les autres → comparaison slot-par-slot dans la même fenêtre de congestion. Si Nozomi land au même slot que Jito → routing Jito. Si Nozomi land 2 slots plus tôt → vraie valeur ajoutée Nozomi. - -### Helius double-mode -On probe Helius en 2 modes : -1. `?swqos_only=true` → isole le path Helius pur (sans fan-out Jito) -2. mode par défaut → Helius + Jito fan-out - -→ 2 séries Prom : `mode="swqos_only"` et `mode="dual"`. Coût supplémentaire : +$1/mo. - -### Définition "landed" -- Confirmation level : `confirmed` (1+ block). -- Timeout : 60s. Au-delà → classified `dropped` avec `reason=timeout`. -- Métriques : `slot_delta = land_slot - submit_slot` (resolution slot) + `wall_clock_ms` (resolution ms). - -### Statistical power à cette cadence - -| Période | Probes / service | Ce qu'on peut claim | -|---|---:|---| -| 1 jour | 24 | p50 stable, p99 bruité | -| 1 semaine | 168 | p50 + p99 stables, gaps 5pp détectables | -| 2 semaines | 336 | gaps 3pp détectables | - -→ **Rythme de publication recommandé : hebdomadaire.** Article + leaderboard refresh chaque lundi matin. - ---- - -## 6. Garanties méthodologie (sponsor-proof) - -Bake-in dès le launch - ajouter après coup donne l'air défensif. - -1. **Méthodo pré-enregistrée sur GitHub** avant tout contrat sponsor. Changements via PR public + fenêtre commentaire 14 jours. -2. **Inclusion automatique** dès qu'un endpoint est publiquement reachable. Les sponsors n'entrent pas dans le leaderboard via cash. -3. **Harness open-source** dans ce repo (`harnesses/solana-tx-landing/`). -4. **Paramètres probe identiques** entre services. Toute déviation per-service (auth méthode, endpoint) → footnote sur la row. -5. **Clause non-suppression dans le contrat sponsor.** Seul recours sponsor pour résultat défavorable = terminer + refund pro-rata. Jamais d'édit. -6. **Funding itemisé publiquement** par trimestre, tier S/M/L à la L2Beat. -7. **Pas d'accès en avance aux résultats.** Sponsors voient les chiffres en même temps que le public. - -**Disclosure block** (72 mots, à mettre dans le champ `sponsorship` du spec YAML) : - -> OCB measures every reachable Solana transaction-landing service on identical probe parameters. The harness is open-source and re-runnable by anyone. Sponsors fund OCB's operations and receive newsletter visibility, case studies, and integration support - never leaderboard influence, advance results, or methodology changes. Current sponsors : see /funding (updated quarterly). Sponsor contracts include a non-suppression clause : OCB publishes unfavorable results without exception. Disputes go through public GitHub issues. - ---- - -## 7. Échelle de tiers (escalade par triggers) - -``` -START ──► V0-Lean $159/mo - │ 5 svc × 1 reg × 60min - │ Refresh hebdomadaire - │ - ├──► +Cadence ($318/mo) ─── Si on veut leaderboard quotidien - │ 5 svc × 1 reg × 30 min - │ - ├──► +Couverture ($580/mo) ─── Quand 1er sponsor signe - │ 8 svc × 1 reg × 30 min - │ (ajoute bloXroute, NextBlock, SVS) - │ - └──► +Géo edge ($1 743/mo) ── Quand 2-3 sponsors OU - 8 svc × 3 reg × 30 min sponsor demande story géo -``` - -**Triggers explicites :** - -| Trigger | Action | -|---|---| -| 4 semaines de data publiée et la narrative demande de la fraîcheur quotidienne | V0-Lean → V0-Daily ($318) | -| 1 sponsor signe ($500+/mo cash OU SOL credits couvrant ≥1 service premium) | V0-Daily → V1 ($580) | -| 2-3 sponsors signés OU 1 sponsor demande spécifiquement la story "geographic edge" | V1 → V2 ($1 743) | -| SOL passe au-dessus de $200 | Recompute tout, peut imposer un downgrade temporaire | - -**Anti-pattern :** sauter à V2 avant signature sponsor = brûler $1.7k/mo pour répondre à une question (geographic edge) que personne n'a posée publiquement. - ---- - -## 8. Roadmap d'implémentation - -### Étape 1 - mobula-api (refactor harness) - -Fichiers à toucher dans `miniapps/solana-tx-landing/cmd/script/` : - -``` - main.go - fork en 2 goroutines: runSubscriber() (obs) + runProber() (actif) - prober.go - NEW. Boucle 1 cycle/h, fire les 5 services en parallèle - active_metrics.go - NEW. Définitions Prom solana_landing_probe_* - config.go - env vars: SOLANA_LANDING_SERVICES, _CADENCE, _RPC_URL, etc. - subscriber.go - UNCHANGED (la logique observationnelle reste) - wallets.go - UNCHANGED (tip wallets pour l'attribution Market Share) -``` - -### Étape 2 - mobula-api (infra) - -- Générer 1 keypair Solana, le funder de 1 SOL (~$86) via wallet perso, store en Railway Env Secret `SOLANA_PROBE_KEYPAIR`. -- Renommer le service Railway existant `solana-tx-landing` → `solana-tx-landing-us` pour cohérence future multi-région (geste de cleanup, ne change rien à l'usage actuel). -- Ajouter scrape target dans `miniapps/openchainbench-monitoring/prometheus/prometheus.yml` : pointer vers `solana-tx-landing-us.railway.internal:2112` (le service est déjà scraped en V0 - vérifier le job_name). - -### Étape 3 - OpenChainBench (spec + UI) - -``` - benchmarks/solana-tx-landing.yml - - Garder le contenu existant (Market Share) - - Ajouter section "Landing Latency" avec métriques solana_landing_probe_* - - Ajouter champ `sponsorship` avec le disclosure block du §6 - - Mettre à jour `disclaimer` pour mentionner les 2 facettes - docs/methodology/solana-tx-landing-active.md - - NEW. Méthodo pré-enregistrée (les 7 règles du §6 + détails probe) - - Commit AVANT toute conversation contractuelle sponsor - src/lib/spec.ts - - Vérifier qu'il supporte un schema 2-tabs (Market Share + Latency) - - Sinon : étendre minimal le loader -``` - -### Étape 4 - Sponsor outreach - -1. **Nozomi en premier** (contact direct Florent). Pitch : 8 SOL / trimestre = leur slot Nozomi dans le bench. Featured tier dans `/funding`. -2. **0slot ensuite** (Discord `kurt0slot` ou TG `@kurt0slot`). Même ask. -3. Si les 2 signent → OCB net mensuel ≈ $34. Le bench se finance. - -### Étape 5 - Aller live - -- Méthodo committée sur GitHub. -- 4 semaines de data accumulée en privé (pour valider le pipeline + détecter les bugs). -- Annonce publique avec article France Cryptos + cross-post X. - ---- - -## 9. Décisions encore ouvertes (à valider par Florent) - -| # | Question | Reco | -|---|---|---| -| 1 | Disclose aux providers qu'on les probe ? | **Oui**, top-3 (Jito, Helius, Nozomi) avant launch | -| 2 | Helius en double-mode (swqos_only + default) ? | **Oui**, coût négligeable | -| 3 | Ask Nozomi : flat fee cash ou SOL credits ? | **SOL credits** - plus naturel | -| 4 | Garder le tab observational (Market Share) ? | **Oui**, 1 page 2 tabs | -| 5 | Renommer service Railway de `solana-tx-landing` → `solana-tx-landing-us` ? | **Oui**, cleanup pour cohérence future | - ---- - -## 10. Ce qui n'est PAS dans ce plan - -- **Code Go** - pas écrit tant que décisions §9 pas validées. -- **YAML du spec OCB** - pas modifié avant méthodo committée sur GitHub (cf §6.1). -- **Contrat sponsor type** - étape légale séparée, hors scope ingénieur. -- **bloXroute, NextBlock, SVS** - reportés V1+, on les onboard quand le pipeline V0-Lean tourne. -- **Multi-région** - reporté V2, on lance us-east only. - ---- - -**Last updated :** 2026-05-21. Recompute toutes les valeurs $ si SOL bouge de ±30%. diff --git a/src/app/api/cron/health-check/route.ts b/src/app/api/cron/health-check/route.ts index b8180465..a79d16a9 100644 --- a/src/app/api/cron/health-check/route.ts +++ b/src/app/api/cron/health-check/route.ts @@ -1,3 +1,4 @@ +import { timingSafeEqual } from "node:crypto"; import { NextResponse, type NextRequest } from "next/server"; import { getBenchmarkSlugs } from "@/data/benchmarks"; import { getSpecs } from "@/lib/spec"; @@ -57,9 +58,29 @@ function isAuthorized(req: NextRequest): boolean { // historically appended a trailing newline to multi-line copies, which // would otherwise produce a constant 401 with no obvious explanation. const secret = (process.env.CRON_SECRET ?? "").trim(); - if (!secret) return true; // dev mode, no auth required const header = (req.headers.get("authorization") ?? "").trim(); - return header === `Bearer ${secret}`; + + // Fail closed in production: without a configured CRON_SECRET the + // cron route would otherwise accept any request, exposing the alert + // and prom-probe machinery to anyone who guesses the URL. Keep the + // permissive "any request OK" fall-through for local dev only. + if (!secret) { + if (process.env.NODE_ENV === "production") return false; + return true; + } + + // Constant-time comparison. The previous `header === \`Bearer ${secret}\`` + // shortcut leaked the secret one byte at a time under a remote timing + // attack (response latency varied with prefix-match length). Pad to + // equal length before comparing so timingSafeEqual never throws on + // mismatched buffer sizes, then AND the equality with a length check + // so a shorter-but-prefix-matching header still fails. + const expected = Buffer.from(`Bearer ${secret}`); + const provided = Buffer.from(header); + const padded = Buffer.alloc(expected.length); + provided.copy(padded); + const lengthMatches = provided.length === expected.length; + return timingSafeEqual(padded, expected) && lengthMatches; } export async function GET(req: NextRequest) {