Referrals leaderboard: show registered-referral counts (indexer + API + UI) #204
Labels
No labels
agent:fix_bugfix
agent:fix_conflicts
agent:fix_security
agent:gap_analysis
agent:implement
agent:open_issues
agents
agent:security_audit
agent:verify
area
timecurve
arena
arena-v2
audit
block:feature_review
block:security
bug
contracts
design
devops
docs
documentation
enhancement
epic
feature
frontend
indexer
low priority
megaeth
operations
ops
performance
QA
qa checklist
referrals
removal
security
smart-contracts
tech-debt
testing
time-arena
timecurve
visual-qa
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
code/yieldomega#204
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
The
/referralsGuide leaderboard should surface how many referrals have been registered (or an equivalently clear onchain-derived metric). Today the board andGET /v1/referrals/referrer-leaderboardonly aggregate TimeCurveReferralAppliedrows (referred_buy_countis a buy count, and copy speaks in terms of buys / CHARM).Background
ReferralCodeRegisteredon successfulregisterCode. The indexer already persists these in Postgres asidx_referral_code_registered(see initial referral migration).ReferralApplied→idx_timecurve_referral_applied(existing leaderboard SQL ranks by summedreferrer_amount).Work to scope
Product / naming: Decide what “registered” means in UI copy:
ReferralCodeRegisteredtotals (codes claimed onReferralRegistry), and/orCOUNT(DISTINCT buyer)fromidx_timecurve_referral_appliedvs. currentCOUNT(*)buy rows), if the intent is “how many wallets used this guide’s code” rather than “how many qualifying buys”.Indexer / API: Extend the referrals HTTP surface (likely
GET /v1/referrals/referrer-leaderboardresponse schema and SQL, withSCHEMA_VERSIONbump per repo conventions) so the frontend can render the chosen metric(s) without synthetic scores. Reuse existing tables where possible (idx_referral_code_registered,idx_timecurve_referral_applied).Frontend: Update
ReferralLeaderboardSection/indexerApitypes to display the new field(s) and align summary + row copy with the chosen definition.Tests: Add or extend indexer integration coverage for the new aggregates; adjust any Vitest paths for API types if needed.
Related
/referralssurface / register UX: https://gitlab.com/PlasticDigits/yieldomega/-/issues/64/cc @PlasticDigits/yieldomega
quick data dump from prod since the ticket has the A vs B decision still open. counted both event types onchain on MegaETH mainnet so the product call has real numbers to work from.
onchain right now (sale opens May 18 12:00 UTC, so we're 4 days pre-launch):
ReferralCodeRegistered(Registry)0xedebced1...adaf7ReferralApplied(TimeCurve)0x1b68bb67...2bf71unique referrer wallets: 6 (1:1 with codes, contract enforces
ownerCode[msg.sender] == 0atReferralRegistry.sol:64).implication for the A vs B decision:
current leaderboard logic (buys + CHARM, ranks by
referrer_amount) renders zero rows through the entire pre-launch window becauseReferralAppliedis empty until the first qualifying buy lands. that's the "looks broken" state.option A (registered count) gives the leaderboard 6 visible rows immediately, populated by anyone who's already claimed a code. fills the empty-state gap during pre-launch.
option B (distinct referees) is still zero pre-launch — same problem as the current logic.
if the goal is "make the leaderboard feel alive before sale opens", A is the clear win. once sale opens and
ReferralAppliedstarts emitting, the board can blend both: A as a "guides ready" baseline + B as the active-attribution metric layered on top.if you want me to run additional data slices (block ranges, time bands, anything else), happy to.
@PlasticDigits
Must use option a
mentioned in commit
a57d0d9611Shipped: option A (registry union) — ready for verification
Merged to
main: referrer leaderboard now unionsidx_referral_code_registered.owner_addresswithidx_timecurve_referral_applied.referrer, adds JSONcodes_registered_count, bumps indexerx-schema-versionto 1.19.0, and updates/referralsGuide leaderboard copy + summary tiles.Checklist for reviewers
GET /v1/referrals/referrer-leaderboard(indexer ≥ 1.19.0) returns rows for wallets with onlyReferralCodeRegisteredindexed (zeroReferralAppliedrows):codes_registered_count≥ 1,referred_buy_count/ CHARM totals 0./referralsGuide leaderboard lists those wallets with “onchain codes registered” + recorded buys sublines; empty state copy matches when the union is empty.rank/ tie ordering unchanged vs #177 (postgres_gitlab177_referrer_leaderboard_dense_rankstill passes whenYIELDOMEGA_PG_TEST_URLis set).INV-INDEXER-204-REFERRAL-LB-REGISTRY, manual QA #204, invariants §204,skills/README.mdcontributor index./cc @brouie Please verify against prod/staging when the deployed indexer is on 1.19.0+. Issue left open per maintainer request.
Doc anchors (absolute paths for the note UI): invariants §204 · manual QA #204 · product referrals dashboard.
Walked the verification checklist against the local stack with a freshly built indexer at schema 1.19.0. Item 4 (dense-rank) fails — flagging a regression introduced by the #204 SQL rewrite. Other items pass or are deferred where the pre-launch state blocks them.
Item 1 — Endpoint returns
codes_registered_countwith schema 1.19.0Rebuilt indexer to 1.19.0 (registry JSON pointed at the live anvil addresses since the disk file was stale relative to the live anvil state). Seeded a code-only wallet onchain: anvil account #25 (
0xdf37f81d...0913) calledapprove(registry, 1 CL8Y)thenregisterCode("qaonly204"). Tx0xca3d1902...shipped clean (status 1, ReferralCodeRegistered event emitted, 1 CL8Y burn to 0xdead).After indexer restart + ingestion catchup,
curl -i http://127.0.0.1:3100/v1/referrals/referrer-leaderboardreturns:Row 2 is the spec's literal case: wallet with only
ReferralCodeRegisteredindexed, zeroReferralApplied,codes_registered_count=1,referred_buy_count=0,total_referrer_charm_wad=0. The union over the two source tables works as designed.Item 4 —
postgres_gitlab177_referrer_leaderboard_dense_rankFAILSReproduced deterministically on a fresh ephemeral DB (
yieldomega_test_204). Not a data-pollution flake — the test seeds its own clean 4-referrer fixture (300/200/200/100 wad) and asserts dense-competitive ranks1, 2, 2, 4. The endpoint returns1, 2, 3, 4instead, breaking on the tie between the two 200-wad referrers (bbbbandcccc).Root cause looks to be the rewritten window function in
indexer/src/api.rs:1921:With both
total_charm DESCandr.referrer ASCinside the sameORDER BY, RANK() only ties rows when both columns match. Since everyreferreris unique, no two rows ever tie and RANK() degrades to page-ordinal (1, 2, 3, 4). The pre-#204 fix (commit6d92cc4for GitLab #177) had the dense-competitive behavior; #204's SQL rewrite regressed it.The invariants doc still asserts the dense-rank requirement:
invariants-and-business-logic.md:929tiesINV-INDEXER-204-REFERRAL-LB-REGISTRYtoINV-INDEXER-170-REFERRAL-LB-TIEandpostgres_gitlab177_referrer_leaderboard_dense_rank. So docs and test agree — the SQL is the broken piece.Likely fix shape: keep the
referrer ASCtiebreaker on the outer ORDER BY only, and rank ontotal_charm DESCalone inside the window — e.g.:Items 2 + 3 — deferred
ReferralAppliedwon't emit until the first qualifying buy. Onchain check (prior #204 note): 0ReferralAppliedevents on prod TimeCurve.Item 5 — Docs anchors
INV-INDEXER-204-REFERRAL-LB-REGISTRYpresent atdocs/testing/invariants-and-business-logic.md:912and:929with the union spec +codes_registered_countrulemanual-qa-issue-204-referrer-leaderboard-registry-unionanchor indocs/testing/manual-qa-checklists.md:157, TOC entry at:13invariants §204cross-ref from manual-qa file at:165skills/README.md:48indexes the #204 union pointerSummary
Items 1 and 5 sign off cleanly. Item 4 surfaces a real regression in the rank SQL that needs a fix before frontend (item 2) is meaningful, and item 3 stays blocked until sale opens. Holding off on close until the SQL is patched.
@PlasticDigits
mentioned in commit
f0d89b2075mentioned in merge request !390
mentioned in commit
b0b5962e9amentioned in issue #212
mentioned in issue #213
mentioned in commit
336bd5848cVerification complete — dense-rank regression fixed, docs tightened
Walked the full #204 scope against
main@336bd58.What shipped (recap)
GET /v1/referrals/referrer-leaderboardunionsidx_referral_code_registered.owner_addresswithidx_timecurve_referral_applied.referrer; each row exposescodes_registered_count(schema ≥ 1.19.0).f0d89b2restores competitiveRANK()— windowORDER BYis Σ CHARM DESC only;referrer ASCstays on the outerORDER BYonly. Without that split, unique referrers prevent ties and ranks degrade to page-ordinal1, 2, 3, 4instead of1, 2, 2, 4.INV-INDEXER-170-REFERRAL-LB-TIE+INV-INDEXER-204-REFERRAL-LB-REGISTRY, product referrals dashboard table, and manual QA #204 dense-rank checklist row — cross-linked fromskills/README.md.Automated verification (local, Postgres ephemeral)
Checklist for @brouie
GET /v1/referrals/referrer-leaderboardreturns wallets withcodes_registered_count ≥ 1,referred_buy_count == 0,total_referrer_charm_wad == 0when onlyReferralCodeRegisteredis indexed.rank; next rank skips (1, 2, 2, 4).postgres_gitlab177_referrer_leaderboard_dense_rankpasses./referralsUI: Guide leaderboard shows onchain codes registered + recorded buys sublines; summary tiles include registration totals.ReferralAppliedbuy, CHARM / buy counts move;codes_registered_countstays stable.skills/README.mdcontributor index.Please verify against prod/staging when the deployed indexer is on 1.19.0+. Issue left open per maintainer request.
/cc @brouie
mentioned in issue #225
Walked the full verification checklist against production. All 5 items PASS.
Item 1 — registry-only rows: PASS
curl https://indexer.yieldomega.com/v1/referrals/referrer-leaderboard?limit=50(x-schema-version 1.25.0) returns 32 wallets all at rank 13 withtotal_referrer_charm_wad: "0"andcodes_registered_count: 1. These are pure registry-only entries — registered codes on ReferralRegistry with zero attributed ReferralApplied. The union is doing exactly what option A specified.Item 4 — dense rank: PASS
Production data shows clean dense-competitive behavior:
This is the
1, 2, 2, 4pattern but at scale — thef0d89b2window-function fix works on real production data. No degradation to page-ordinal observed.Item 3 — post-buy consistency: PASS
Compared to pre-launch baseline (6 days ago: 6 ReferralCodeRegistered, 0 ReferralApplied, leaderboard fully zero CHARM):
codes_registered_countdidn't drop them when CHARM activity flowed elsewhereItem 2 — frontend /referrals UI: PASS
Walked the Guide leaderboard on production /referrals:
Item 5 — docs: PASS
Anchors resolve cleanly:
#204 verified clean from QA side. Issue can close when convenient. @PlasticDigits