Skip to content

release: the trading apps go to production without Dune - #2699

Merged
Flotapponnier merged 6 commits into
mainfrom
release/trading-apps-off-dune
Sep 27, 2026
Merged

Flotapponnier merged 6 commits into
mainfrom
release/trading-apps-off-dune

Conversation

@Flotapponnier

@Flotapponnier Flotapponnier commented Sep 27, 2026 •

Copy link
Copy Markdown
Collaborator

Ships to production what PRs #2697 and #2698 landed on dev for the trading apps, and nothing else. The Dune team trial ends 2026-10-02 with no paid plan committed, so bench 201 moves onto a free source and the four benches that cannot run without Dune stand down.

Exactly which files are here, and why

22 files, all trading apps. A grep over this diff for capital|hyperliquid|bridge|perp|pm-|chain-kpis|stablecoin|protocol-valuation|rwa returns nothing, so no part of the commits main is behind rode along. (The count was 21 when this PR opened; src/app/products/[slug]/page.tsx joined it in review, to stop the gating taking Maestro's whole Trading app view with it.)

Specs (7) — solana-trading-platform-wars (re-sourced to DeFiLlama), solana-dex-volume (stopped contradicting 201 about the take rate), trading-app-daily-volume (one FAQ saying where 267 ends and 201 begins), and the four that stand down: memecoin-platforms, solana-avg-trade-size, solana-unique-traders, trading-platform-wallets.

Harnesses (2) — trading-app-volume gains the fees leg that feeds bench 201. dune-platform-volume comes along so the source the four gated benches read is the one this repo describes: off the frozen third-party datasets, onto our own SQL, with the freshness guard that is the reason none of them ever served a stale figure as current. Both were deployed before this PR and are running.

Site (5) — trading-apps.ts, trading-apps/page.tsx, trading-apps/opengraph-image.tsx, trading-app-section.tsx and products/[slug]/page.tsx. The first four were byte-identical between main and dev before this work, so they came across whole; the fifth is a review fix made here.

The three shared files, hand-edited (3) — see below.

The two files that could have done damage

src/lib/removed-benches.ts was edited by hand, never copied from dev. This branch keeps 273 chain-bridged-tvl, 274 protocol-pf-ratio and 275 chain-stablecoin-flow gated, where dev has all three live. Copying dev's file would have published the whole capital cohort to production by accident. It also does not carry chain-fees-revenue (280) or usdc-corridor-flows (281), which do not exist on this branch. The only change is the four new slugs and their comment.

The three cache keys are this branch's own numbering, not dev's: bench-unfiltered-v84, all-benchmarks-v77, providers-v11, moved in lockstep from v83/v76/v10. Dev is at v87/v80/v14 and that numbering is deliberately not copied; the comment in spec.ts says so, so the next person does not try to reconcile them.

What production keeps and loses on /trading-apps

before after
serves 201, 267, 205, launchpad-wars, 203, 206, 207, 232, app-store-ratings 201, 267, 205, launchpad-wars, app-store-ratings
201's source frozen third-party Dune datasets (last updated 2026-08-25) DeFiLlama dexs + fees adapters, free and daily
KPI columns Swap Tx, Avg Trade, Active Wallets, Fee Rate, App Rating Commission, Take Rate, App Rating
201's cohort 8 including BasedBot 7, BasedBot removed

Route checks on a local dev server with VERCEL_ENV=production:

route status
/trading-apps 200
/benchmarks/solana-trading-platform-wars 200
/benchmarks/trading-app-daily-volume 200
/benchmarks/solana-dex-volume 200
/products/gmgn 200
/benchmarks/solana-unique-traders 404
/benchmarks/memecoin-platforms 404

And on the hub itself: columns are Commission, Take Rate, App Rating; no href to any gated bench; the footer names benches 203, 206, 207 and 232 as paused; nothing credits Dune. /products/gmgn is headed "Per platform · DeFiLlama and the App Store".

Two figures on that local render are understated and will not be in production: "Platforms tracked" reads 3 and the KPI reads "Highest app rating" because a local dev server has no materialized blob for bench 201's new panels, so only the App Store column has values. With the worker's blob the commission column fills for all seven and the KPI becomes "Highest commission". The gating and column mechanics are what the local render verifies, and they are correct.

Numbers behind the switch

Our Solana-only Dune SQL against DeFiLlama for data day 2026-09-26, which is the check that the two sources measure the same thing:

app ours (Solana) DeFiLlama (all chains) ours, fees DeFiLlama, revenue
trojan 4,793,659 4,790,305 (+0.07%) 48,304 37,823
padre 22,475,283 22,155,967 (+1.4%) 223,671 120,131
photon 1,732,329 1,650,655 (+4.9%) 17,084 17,197 (-0.7%)
axiom 150,856,582 157,774,819 1,349,376 1,381,516 (-2.3%)
gmgn 34,983,860 84,943,809 (ten chains) 352,817 671,487
fomo 103,949,657 209,660,334 (Relay legs) 501,450 965,983

The Solana-heavy apps agree within 5% on volume and within 2.3% on the app's cut. GMGN and FOMO read higher on DeFiLlama for documented reasons.

One correction this PR also carries: bench 205 argued the DeFiLlama revenue-over-volume ratio overstates the fee rate, citing 1.2-2.9% for Axiom on Sep 15-17 2026. Re-reading the same endpoints gives 0.74%, 0.60% and 0.51% for those days, so DeFiLlama restated them. Bench 205 keeps its position for a measured reason instead: the ratio moves between 0.37% and 1.07% for one app across a fortnight, which is too noisy to rank a board on.

Verification on this branch

pnpm validate (237 specs), pnpm typecheck, pnpm lint (0 errors), bun test src/lib (308 pass), go vet and a build of both harnesses, go test on dune-platform-volume, and the route and content checks above.

Known and deliberate

The four gated specs describe their own source correctly here, but bench 201's old FAQ text elsewhere in the repo may still reference the retired datasets in places production does not render. A direct hit on a gated bench URL returns 404 rather than 410, which is how the already-gated benches behave on this branch and is its own decision to make.

Review rounds on this PR

Three rounds. No blockers or majors survived verification, and the fixes are in separate commits.

Round 1's BLOCK was a false positive I caused: I ran the reviewer with --base main, and this checkout's local main ref had not moved since 2026-09-19 (c8c9dc6e, PR #2534), while origin/main is 023875a5. It therefore diffed these 2 commits against a main eight days stale and attributed 394 commits and 635 files to the PR. Re-running with --base origin/main gives a 231k-char bundle instead of 3.58M. What settles it, beyond gh pr view 2699 --json files:

  • git merge-base origin/main HEAD == origin/main, so this branch contains main exactly and adds nothing else.
  • benchmarks/trading-app-daily-volume.yml, src/lib/trading-apps.ts, src/components/trading-app-section.tsx and benchmarks/robinhood-rpc.yml all already exist on origin/main; the report called each of them new.
  • src/lib/removed-benches.ts diffs against origin/main as additions only: 21 lines, the four Dune slugs, nothing ungated.

Fixed across rounds 2 and 3: a 404 on the fees endpoint could silently drop a production row (Trojan, Axiom and Photon have no App Store rating, so losing commission emptied every column and the row left the page); Maestro lost its whole Trading app view, bench 268 fill block included; the hub footer claimed the Dune benches were paused on staging too, and had 206 and 207 swapped; four column tips still described the retired datasets; the commission's "latest closed day" wording when it can trail by up to 72 h; and a newer unpriced day being held back by the priced day on the board, which spent the retry budget and skipped the day for good.

Ships to production what PRs #2697 and #2698 landed on dev for the trading
apps, and nothing else. The Dune team trial ends 2026-10-02 with no paid plan
committed, so bench 201 moves onto a free source and the four benches that
cannot run without Dune stand down.

Bench 201 reads DeFiLlama's open dexs and fees adapters through the
trading-app-volume harness: routed volume from dailyVolume, the app's own cut
from dailyRevenue, and the take rate over the same days. Not dailyFees, which
adds the venue's cut and reads about twice as much. BasedBot leaves the table,
having no adapter of either kind and no published fee wallet list. pump.fun
becomes measurable again.

Benches 203, 206, 207 and 232 are gated to staging, not removed: they come back
by deleting four lines the day the plan is paid for. dune-platform-volume comes
along so the source they read is the one this repo describes, off the frozen
third-party datasets and onto our own SQL with the freshness guard, which is why
none of them ever served a stale figure as current.

The hub and the /products view take their columns from one filtered list, so a
gated bench takes its column and its link with it rather than leaving a stripe
of dashes and four links into 404s, and no page credits Dune for a figure that
came from DeFiLlama.

removed-benches.ts was edited by hand, not taken from dev: this branch keeps
273, 274 and 275 gated where dev has them live, and does not carry 280 or 281,
which do not exist here. The three cache keys are this branch's own numbering,
v84, v77 and v11, not dev's.
…at it measures

Four from the review, none blocking.

A 404 on the fees endpoint came back as an empty series with no error, which was
right for the bots that have a dexs adapter and no fees one, and wrong for the
seven apps bench 201 ranks: one 404 on a renamed or briefly broken slug deleted
their commission, take rate and revenue day, and Trojan, Axiom and Photon have
no App Store rating, so every production column went null and the row left the
page. The cohort now records which apps have a fees adapter; for those a 404 is
an outage, so it carries forward and counts like any other failure.

Three panel descriptions and the column tip said the commission covers the
latest closed day. It covers the newest day with both a volume and a commission
figure, which can trail the volume day by up to three days, and they say so.

The hub row read "pump.fun" while the figures are the mobile app's. It reads
"pump.fun app", as the bench and the harness already did.

The four Dune column tips still described the retired third-party datasets:
Mobula for average trade size, community datasets and cross-chain scope for
active wallets, DeFiLlama for FOMO's fee rate, dex_solana.trades for pump.fun's
swap count. All four are rewritten from the specs, and since every figure in
them is now Solana only they declare that scope and show it once in the header
rather than per cell. Those columns are staging-only, which is why nothing
production serves was affected.
… appears where it is true

Gating the Dune benches took Maestro's whole "Trading app" view with them on
production. It is not in the volume cohort, not a bench 201 provider and has no
App Store row, so once its 206 and 207 figures went the section never rendered,
and its bench 268 fill-quality block went with it. The section renders that
block on its own, so the fill cohort now counts toward showing the view.

The hub footer said the four benches are paused whatever the deployment, so
staging read "paused" directly under their live figures. It only says it where
they are gated, and it no longer has 206 and 207 the wrong way round: 206 is
average trade size, 207 is swap transactions.

Bench 203's two original fee-source bullets did not say which gauges they
describe, so they read as contradicting the take-rate bullet added above them.
They now name the companion gauges. Bench 201's cohort bullet said "the seven
apps with both adapters" when others have both and sit in bench 267 instead. And
the comment claiming Maestro only ever had Dune figures was wrong: its average
trade came from Mobula, through the same bench.
… priced day

The price guard kept the held rows whenever a result came back with no SOL
price, whichever day that result was for. A newer, fully loaded day that ran
before prices.day had its SOL row was therefore discarded: the retry budget went
on a day already on the board, and once the target day moved forward the skipped
day was never measured, so benches 206, 207 and 232 served an older day than
their methodology promises.

The guard now applies only to a restatement of the day already held, which is
what it was for. A newer unpriced day publishes its volume, transactions and
wallets; publishRows already holds back the fee gauges and leaves the day
unrecorded, so the retries continue and a later priced run lands it.

Staging only, since all four readers are gated, but the promise was in their
methodology either way.
…ake rate is no longer ranked as a trader's cost

Two majors, both reaching production.

Only a negative daily revenue was dropped. A day DeFiLlama returns as 0 against
real volume kept HasRev, anchored the walk-back and published a 0% take rate,
which the hub ranked low-is-best and painted green as the cheapest app while
showing its commission of $0 ranked last. The walk-back now prefers the newest
day inside the window with a positive cut and falls back to a zero one only when
there is none, so an app whose fee genuinely is zero still publishes its real 0%.

The deeper error is mine from an earlier round. I made the take rate rank
low-is-better on the argument that a lower cut is cheaper for the trader. It is
not: DeFiLlama's revenue is net of referral and cashback paybacks, so an app that
rebates a third of its fee reads a third lower while its traders pay exactly the
same. Ranking it that way turned an accounting difference into a
recommendation.

The metric has no better end for a reader, so the hub stops ranking it: no rank,
no best, no highlight, and a tip that says what the number is. On bench 201,
where the question is which app is the larger business, it ranks by the app's own
margin, and the panel description and methodology say plainly that it is not the
price of a swap. A trader-cost column would need dailyFees, which is a different
figure this bench does not publish.
The previous fix kept a day returned as zero revenue against real volume out
of the 1d anchor, and left it inside the 7d and 30d windows, where it diluted
the commission and the take rate below any day in them. The window loop now
applies the same rule as the anchor: such a day is left out unless the window
has no positive day at all, in which case the app's cut really is zero and the
zeros are its figures.

This is the second time a rule landed in one place and not the other, so the
harness gains its first tests: the zero day out of every window, a genuinely
zero cut still publishing, a fees adapter one day behind anchoring on the newest
day with both legs, and one more than 72 h behind publishing no commission at
all while volume carries on.
@Flotapponnier

Copy link
Copy Markdown
Collaborator Author

Round 6, pass A on 468ba84 against origin/main: no blockers, no majors, two minors left as follow-ups rather than a seventh round. (A1) The zero-revenue rule cannot distinguish a genuine fee cut to 0 from an adapter artifact, so an app that really drops its fee to zero keeps its old take rate as the latest for up to three days until the window has no positive day left; documented behaviour, acceptable lag. (A2) The 7d and 30d revenue sums cover whichever days passed the filter, which can be as few as 80% of the window, while the panels present them as full-window totals; the panel copy should say the sum spans the days with a positive figure. Pass B was killed by a concurrent process before it wrote; not rerun.

@Flotapponnier
Flotapponnier merged commit 6e26515 into main Sep 27, 2026
2 checks passed
@Flotapponnier
Flotapponnier deleted the release/trading-apps-off-dune branch September 27, 2026 19:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant