Landing Score v1
After this page you can recompute any published Landing Score from its inputs, and argue with
the methodology on its actual terms. This is the versioned recipe; if any ingredient changes,
the version bumps and both are published. The reference implementation lives in
packages/shared (score.ts, botscore.ts) — the leaderboard, the API, and this page all
run the same code.
Definition
Section titled “Definition”Landing Score = bot-adjusted real-user landing rate.
For a program over a window:
score = landed_real / (landed_real + dropped_real)where a transaction is real iff its signer’s bot score for that UTC day is < 0.5, and
dropped_real counts real-user attempts classified as drops. Programs with zero observed
real-user attempts get score 1 with an interval of [0, 1] — i.e. “no evidence”, not “perfect”.
Bot heuristic v1
Section titled “Bot heuristic v1”Deliberately not ML: three transparent signals per signer per UTC day, combined with fixed weights into a score ∈ [0, 1].
| Signal | Weight | Recipe |
|---|---|---|
| Volume (signer clustering) | 0.5 | Daily tx count, log-scaled: 0 at ≤10 tx/day, 1 at ≥5 000 tx/day |
| Timing regularity | 0.3 | Coefficient of variation of inter-tx gaps: CV 0 (metronome) → 1, CV ≥ 1 (human burstiness) → 0. Needs ≥5 gaps, else 0 |
| Program diversity | 0.2 | Distinct programs touched: 1 program all day → 1, ≥6 programs → 0. Signers with <20 tx/day score 0 (not enough evidence) |
bot_score = 0.5·volume + 0.3·regularity + 0.2·diversity // clamped to [0,1]bot = bot_score ≥ 0.5Known failure modes, accepted for v1: a patient bot under 5 000 tx/day with randomized timing passes as human; a power user who hammers one program all day can look bot-ish. The weights put volume first because it is the hardest signal to fake cheaply. v2 candidates (funding- graph clustering, fee-payer reuse) will be a new version, not a silent change.
Confidence intervals
Section titled “Confidence intervals”Every published score carries a Wilson 95% interval computed on the observed counts:
n = landed_real + dropped_real (observed, not scaled-up)center = (p + z²/2n) / (1 + z²/n) z = 1.96margin = z·√(p(1−p)/n + z²/4n²) / (1 + z²/n)Wilson is chosen over the normal approximation because leaderboard tails — tiny programs,
heavy sampling — hit small n constantly, where the normal interval lies.
Ranking rule: overlapping intervals mean the order between two programs is not a claim.
Sampling honesty note
Section titled “Sampling honesty note”Pre-firehose, mainnet observation is sampled within a fixed public-RPC budget. What that means, stated plainly:
- Counts are observed counts. We do not scale them up and pretend we saw everything; the interval is computed on what was actually seen, so less coverage ⇒ honestly wider bands.
- The sample rate is published per program (
sampleRatein the dataset). - Sampling is time-stratified, so bursty programs are not systematically favored — but a failure mode concentrated in unsampled slots can still be under-observed. That risk shrinks as coverage grows and vanishes with full-firehose funding (a config flip, not a code change).
- Drops attributed to real users can only be observed for programs whose clients run the SDK;
for programs observed purely on-chain,
dropped_realis estimated from send-visible public signals and is the weakest input in v1. The dataset marks which basis applies.
Changelog
Section titled “Changelog”- v1 (current) — initial public recipe, as above.