Indexer + Simple podium: expose active-pool prize preview (DOUB + USD) on GET /v1/arena/podiums #302
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#302
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
Extend
GET /v1/arena/podiumsto return per-category active-epoch prize preview (1st/2nd/3rd DOUB wad strings, 4∶2∶1 split) and wireArenaSimplePage/ArenaSimplePodiumSectionso podium cards show DOUB prizes and USD equivalent — without browser RPC reads.Depends on / pairs with #301 (indexer-first display policy).
Current codebase
Indexer
GET /v1/arena/podiumsindexer/src/api_arena.rsarena_podiumsreturns UX-ordered rows with:category,category_index,epochwinners[],values[](scores)podium_prediction/last_buy_predictionNo prize pool fields. When Postgres has no live row, the handler falls back to head
podium()RPC snapshot atread_block_number(server-side only).Frontend podium UI
ArenaSimplePodiumSection.tsxexpects optionalpodiumPayoutPreview:For each place, if
prizeRawis undefined → rendersEmptyDataPlaceholder“Prizes loading” (#292 requires DOUB + USD prize rows).ArenaSimplePage.tsxpassespodiumPayoutPreview={undefined}— prizes always show loading placeholder even when indexer leaders load correctly.Tests mock preview data in
ArenaSimplePodiumSection.test.tsx; production never supplies it.Onchain prize math (authoritative)
PodiumVaults.activePoolBalance(category)(contracts/src/arena/PodiumVaults.sol).ArenaPodiumSettlement.payoutShares— mirrored in frontendpodiumPlacementShares.Historical context
Pre–Arena v2 [
TimeCurveSimplePage](git history) computed preview from a single poolbalanceOfin the browser via RPC. That path was not ported to v2 per-category vaults; hardcodedundefinedreplaced it.USD display (existing, display-only)
ArenaSimplePodiumSectionalready formats USD viafallbackPayTokenWeiForCl8y+SIMPLE_PODIUM_USD_EQUIV_TITLE(static 0.98× shape, not live oracle — #192).Why the new implementation is needed
chain_timer), notuseReadContractsin every browser tab.Constraints & guardrails
read_block_number; buys/donations/rolls before epoch settlement can change finals. UI copy/tooltip should say “preview” or reuse existing USD equiv disclaimer.PodiumVaults.activePoolBalance(uint8)eth_call at head block — same trust model as existingpodium()head mirror.x-schema-version; document inindexer/README.mdanddocs/indexer/design.md.finalizeWarbowPodiumafter roll (#252) — preview still shows pool balance for current epoch."0"wad strings for all three places; UI shows0 DOUB/≈ $0 USD, not “loading”.Relevant files
Indexer:
indexer/src/api_arena.rs— extendarena_podiumsJSONindexer/src/chain_timer.rs— pollPodiumVaults.activePoolBalance(0..3)at head block (add selector + decode)indexer/src/sale_state.rs— if registry address neededindexer/tests/integration_stage2.rsscripts/verify-podium-prize-preview-anvil.shContracts (reference / test vectors only):
contracts/src/arena/PodiumVaults.solcontracts/src/arena/libraries/ArenaPodiumSettlement.solcontracts/test/TimeArena.t.sol— buy routing / pool fundingFrontend:
frontend/src/lib/indexerApi.ts—ArenaPodiumApiRowtypesfrontend/src/pages/arena/usePodiumReads.ts— map new fields →podiumPayoutPreviewshape (or extendPodiumReadRow)frontend/src/pages/arena/ArenaSimplePage.tsx— pass preview from hookfrontend/src/pages/arena/ArenaSimplePodiumSection.tsx— handle zero pool; optional “preview” ariafrontend/src/pages/arena/ArenaSimplePodiumSection.test.tsxfrontend/src/lib/indexerApi.test.tsDocs:
docs/frontend/arena-views.md§ production components (#292)docs/indexer/design.md§ arena podiumsdocs/testing/invariants-and-business-logic.mdskills/play-active-time-arena/SKILL.mdRecommended direction
Indexer API (schema ≥ 2.8.0 proposed)
Extend each row in
GET /v1/arena/podiums:Computation (server-side at
read_block_number):PodiumVaultsfromADDRESS_REGISTRY.eth_callactivePoolBalance(category_index)for each of 4 categories (batch inchain_timerpoll alongside existing head reads).ArenaPodiumSettlement/ mirrorpodiumPlacementShares).Include
read_block_numberat response root (already present) so clients can show staleness.Frontend
ArenaPodiumApiRow+fetchArenaPodiumsparsing.usePodiumReads(or thin helper), buildpodiumPayoutPreview[categoryIndex].placesfromprize_places_doub_wad.ArenaSimplePage: pass mapped preview; removeundefined.ArenaSimplePodiumSectionunchanged.Verification script
bash scripts/verify-podium-prize-preview-anvil.sh:topUpPodiumPoolscurl GET /v1/arena/podiums→ compareprize_places_doub_wadtocast call PodiumVaults activePoolBalance(cat)+ 4∶2∶1 math at same blockAcceptance criteria
GET /v1/arena/podiumsreturnsprize_places_doub_wad(3 strings) per row for all 4 categories at head block.activePoolBalance(cat)× 4∶2∶1 atread_block_number(verify script PASS)./arenaSimple podium cards show DOUB amounts +≈ $… USDfor populated pools (#292).podiumPayoutPreview={undefined}inArenaSimplePage.0prizes, not “Prizes loading”.INV-INDEXER-PODIUM-PRIZE-PREVIEWproposed).cd frontend && npm run typecheck && npm run lint && npm testPASS.cd indexer && cargo clippy --all-targets -- -D warnings && cargo testPASS.bash scripts/verify-podium-live-anvil.shstill PASS (no regression on leaders).Test plan (functional paths)
GET /v1/arena/podiumsprize_places_doub_wadall"0"; UI0 DOUBtopUpPodiumPools≈ $X USDvisible withSIMPLE_PODIUM_USD_EQUIV_TITLEtooltipTest plan (attack, hack, abuse vectors)
cast call; document display-only — settlement is on-chain at rollmulDivfirst+second+third == poolfor random pool values in Rust unit testcategory_indexmatchesprize_placesmapping in API testformatCompactFromRawmust not throw; reject non-numeric in API layerVerification criteria
Related issues
mentioned in commit
3a663ac58cmentioned in commit 8a9aa54a90cdc1b28dcc74e9d413075a0aba6146
mentioned in commit
e24fb48af9mentioned in merge request !445
Implementation complete — MR !445: https://gitlab.com/PlasticDigits/yieldomega/-/merge_requests/75
Summary:
GET /v1/arena/podiums(schema 2.8.0) now returnsprize_places_doub_wad+active_pool_balance_doub_wadper row from headPodiumVaults.activePoolBalance× 4∶2∶1./arenaSimple podium cards consume indexer preview viausePodiumReads(no browser RPC).Verification (all PASS):
bash scripts/verify-podium-prize-preview-anvil.shbash scripts/verify-podium-live-anvil.shcd indexer && cargo clippy --all-targets -- -D warnings && cargo testcd frontend && npm run typecheck && npm run lint && npm testIssue left open pending MR review/merge.
mentioned in commit
68af94b6acVerification complete — GitLab #302
Issue: Indexer + Simple podium: expose active-pool prize preview (DOUB + USD) on GET /v1/arena/podiums
Verified on branch
main(commits3a663ac,e24fb48). No repo changes required from this verification run.Acceptance criteria
GET /v1/arena/podiumsreturnsprize_places_doub_wad(3 strings) per row for all 4 categoriescurl -sf http://127.0.0.1:3100/v1/arena/podiums— schema2.8.0, 4 rows each withprize_places_doub_wad+active_pool_balance_doub_wadactivePoolBalance(cat)× 4∶2∶1 atread_block_numberbash scripts/verify-podium-prize-preview-anvil.sh→OK (read_block=17, last_buy_pool=1000000000000000000000, schema=2.8.0)/arenaSimple podium cards show DOUB +≈ $… USDfor populated pools (#292)podiumPayoutPreview={undefined}inArenaSimplePagegrep— none; passespodiumReads.podiumPayoutPreviewfrom hook0prizes, not “Prizes loading”"0"strings;ArenaSimplePodiumSection.test.tsx“zero DOUB prizes”; manual UI: all four cards show0 DOUB ≈ $0 USD, no loading placeholderINV-INDEXER-PODIUM-PRIZE-PREVIEW)indexer/src/api.rsSCHEMA_VERSION = "2.8.0";docs/indexer/design.md,indexer/README.md,docs/frontend/arena-views.md,docs/testing/invariants-and-business-logic.md,skills/play-active-time-arena/SKILL.mdcd frontend && npm run typecheck && npm run lint && npm testcd indexer && cargo clippy --all-targets -- -D warnings && cargo testarena_podiums_live_predictions_smoke)bash scripts/verify-podium-live-anvil.shregressionOK (read_block=25, live_rows=12)Additional regression / manual checks
bash scripts/verify-vault-funding-anvil.shArenaSimplePodiumSection.test.tsx—podiumPayoutPreview: nullarena_podium_prize::tests::payout_shares_sum_equals_pool/arenahttp://127.0.0.1:5173/arena— four podium cards, each place shows0 DOUB ≈ $0 USDImplementation notes (confirmed in tree)
arena_podium_prize.rs, head poll inchain_timer.rs, API fields inapi_arena.rsusePodiumReads.tsmapsprize_places_doub_wad→podiumPayoutPreview;ArenaSimplePagewires hook outputscripts/verify-podium-prize-preview-anvil.shAll acceptance criteria met. Closing as verified.
mentioned in commit
cbeb0db44ementioned in merge request !446
mentioned in commit
60cf970f15mentioned in commit
60aea8d8damentioned in commit
818be0ba84mentioned in commit
a34c7b99eamentioned in issue #307