Add permanent arena event pages and audit event directory #364

Closed
opened 2026-07-07 02:38:39 +00:00 by PlasticDigits · 8 comments
PlasticDigits commented 2026-07-07 02:38:39 +00:00 (Migrated from gitlab.com)

Parent

Child of #363 — Improve top of funnel marketing and shareability.

Current codebase

  • AUDIT route: /audit renders ArenaProtocolPage.tsx (legacy /arena/protocol redirects). The page hero is AUDIT only — no event directory, filter, or search at the top.
  • Indexer history tables (already ingested):
    • idx_arena_podium_epoch — PodiumEpochRolled settlements (winners, pool paid, block/tx metadata) · #254
    • idx_arena_last_buy_epoch_started — LastBuyEpochStarted / charm anchor rows · #278
    • idx_arena_buy — full buy log with actual_seconds_added, new_deadline, BP fields, etc. · #282 / #283
  • Existing read APIs (not event-page shaped):
    • GET /v1/arena/activity — mixed feed (buys, WarBow, podium rolls, epoch starts, feature unlocks) · #345
    • GET /v1/arena/session-summary?since_ms=… — 30-day absent-session aggregate only · #338
    • GET /v1/arena/buys — paginated buy list (no per-epoch bundle)
    • No list/detail route for settled epochs or major settlement events.
  • Charts: StandingsVisuals (deadline pressure / raise climb) lives inside the audit Raw data accordion — not exposed as standalone shareable event pages.
  • SEO: Vite injectSocialMeta injects static OG/Twitter tags at build time; SPA routes have no per-event title/description/canonical today.
  • Routing guardrails: referral slug reservation in referralPathReserved.ts — new top-level segments must not collide with reserved slugs (audit, referrals, etc.).

Why needed

Arena activity currently lives inside the live app and audit feed. Epoch rollovers and podium settlements disappear from casual discovery once the play surface moves on. Permanent, indexable event pages plus an audit-top directory turn historical competition into searchable marketing surface — readable titles, winners, charts, and tx replay — without requiring wallet connection.

Constraints / guardrails

  • Onchain authority: Event pages are indexer-derived only; onchain logs/tables are source of truth · guardrails §3.
  • Indexer-first display: No browser RPC mirrors for podium/timer head on event pages · INV-FRONTEND-301-INDEXER-FIRST-DISPLAY · arena-views §301.
  • Branding / copy: User-facing strings use Yield Omega; forbid TimeCurve / sale-end / redemption framing · frontend-content-audit.md.
  • AGPL: Frontend/indexer changes stay AGPL-3.0-only headers.
  • Referral routing: New public paths must be registered in reserved-slug lists and LaunchGate.tsx before the /:referralSegment catch-all.
  • Reorg safety: Any new indexer tables/views must participate in reorg truncation lists in indexer/src/reorg.rs.

Relevant files

Layer Files
Frontend audit ArenaProtocolPage.tsx, ArenaLiveBuysActivitySection.tsx, LaunchGate.tsx
Frontend charts / tx ArenaSections.tsx (StandingsVisuals, TxHash), AddressInline, WalletProfileModal
Indexer ingest indexer/src/persist.rs, indexer/src/arena_podium_epoch.rs, indexer/src/arena_session_summary.rs
Indexer API indexer/src/api_arena.rs
Client API frontend/src/lib/indexerApi.ts
SEO shell frontend/vite.config.ts, frontend/index.html
Docs docs/frontend/arena-views.md, docs/testing/frontend-content-audit.md
  1. Indexer — event catalog API

    • Add paginated GET /v1/arena/events (or split list endpoints) returning stable event ids, kind (podium_settlement, last_buy_epoch_start, optionally major_settlement composite), human title, subtitle, unix time, podium/category, epoch number, tx hash, and deep-link slug.
    • Add GET /v1/arena/events/{id} (or {kind}/{slug}) with: winners + prize breakdown, epoch window stats, related buys sample, chart series (deadline/raise or epoch-local metrics), and explorer tx link fields.
    • Reuse idx_arena_podium_epoch + idx_arena_last_buy_epoch_started; extend only if list/search needs denormalized title/slug columns. Cap page sizes; index for block_timestamp DESC search.
  2. Frontend — permanent event pages

    • New route(s), e.g. /audit/events/:eventId or /events/:slug, lazy-loaded page component with readable H1, winner cards (blockie + AddressInline → profile), chart section reusing/adapting StandingsVisuals patterns, tx replay block (tx hash, block time, key log fields), and CTA back to / play + /audit.
    • Per-route document title + meta description (client-side minimum; optional later SSR/prerender for crawlers).
  3. Frontend — audit directory (top of /audit)

    • Insert a PageSection immediately under the AUDIT hero: filter chips (All · Podium settlements · Last Buy epochs · …), search input (title/epoch/address substring), virtualized or paginated link list to event pages, empty/offline states aligned with indexer connectivity banner patterns.
  4. Search / indexability

    • Stable URLs, canonical slugs, descriptive titles ("WarBow Epoch 12 — Alice wins 1st"), and OG tags populated from event detail payload where feasible.

Acceptance criteria

  • /audit top section exposes filter + searchable list linking to permanent event pages.
  • Each major settlement / epoch event has a dedicated URL with readable title, chart(s), winners, tx replay, and links to current arena (/) and audit (/audit).
  • Event data is served from new indexer list/detail endpoints backed by existing ingest tables (no browser RPC display mirrors).
  • New routes do not break referral slug capture or reserved paths.
  • Offline / empty indexer states degrade gracefully (no blank errors).
  • Copy passes Yield Omega / forbidden-framing audit for new strings.

Test plan

Layer Command / artifact Expect
Indexer unit cd indexer && cargo clippy --all-targets -- -D warnings && cargo test PASS — new handlers + SQL helpers covered
Indexer integration bash scripts/verify-podium-live-anvil.sh (or dedicated verify script if added) PASS — event rows appear after forced epoch roll on Anvil
Frontend unit cd frontend && npm run typecheck && npm run lint && npm test PASS — directory component, route wiring, API client tests
Static IA Extend frontendContentAudit.test.ts or arena static tests for /audit event directory presence PASS
E2E (Anvil) New/extended Playwright spec under frontend/e2e/ with --workers=5 PASS — audit search navigates to event page; winners + tx hash visible
Manual QA Desktop + mobile spot-check audit filter/search + event page share preview PASS — readable, no wallet required

Attack / abuse test plan

  • Indexer list/detail: fuzz limit/offset/search query; assert caps (≤200), no SQL injection, stable 400 on bad cursors/ids.
  • Search: long unicode/query strings; empty result; rate-limit behavior unchanged under rate_limit.rs.
  • Public pages: no PII beyond onchain addresses; no wallet write prompts on read-only event pages.
  • Routing: verify reserved slugs (audit, referrals, home, …) still resolve correctly; event slugs cannot shadow referral codes.

Verification criteria

  • cd indexer && cargo clippy --all-targets -- -D warnings && cargo test — PASS
  • cd frontend && npm run typecheck && npm run lint && npm test — PASS
  • Anvil verify script for event ingest/API (existing or new) — PASS
  • Playwright Anvil spec for audit directory → event page navigation — PASS
  • Manual screenshot: audit directory + one event page legible on mobile width — PASS
## Parent Child of [#363 — Improve top of funnel marketing and shareability](https://gitlab.com/PlasticDigits/yieldomega/-/issues/363). ## Current codebase - **AUDIT route:** `/audit` renders [`ArenaProtocolPage.tsx`](frontend/src/pages/arena/ArenaProtocolPage.tsx) (legacy `/arena/protocol` redirects). The page hero is **AUDIT** only — no event directory, filter, or search at the top. - **Indexer history tables (already ingested):** - `idx_arena_podium_epoch` — `PodiumEpochRolled` settlements (winners, pool paid, block/tx metadata) · [#254](https://gitlab.com/PlasticDigits/yieldomega/-/issues/254) - `idx_arena_last_buy_epoch_started` — `LastBuyEpochStarted` / charm anchor rows · [#278](https://gitlab.com/PlasticDigits/yieldomega/-/issues/278) - `idx_arena_buy` — full buy log with `actual_seconds_added`, `new_deadline`, BP fields, etc. · [#282](https://gitlab.com/PlasticDigits/yieldomega/-/issues/282) / [#283](https://gitlab.com/PlasticDigits/yieldomega/-/issues/283) - **Existing read APIs (not event-page shaped):** - `GET /v1/arena/activity` — mixed feed (buys, WarBow, podium rolls, epoch starts, feature unlocks) · [#345](https://gitlab.com/PlasticDigits/yieldomega/-/issues/345) - `GET /v1/arena/session-summary?since_ms=…` — 30-day absent-session aggregate only · [#338](https://gitlab.com/PlasticDigits/yieldomega/-/issues/338) - `GET /v1/arena/buys` — paginated buy list (no per-epoch bundle) - No list/detail route for settled epochs or major settlement events. - **Charts:** [`StandingsVisuals`](frontend/src/pages/arena/ArenaSections.tsx) (deadline pressure / raise climb) lives inside the audit **Raw data** accordion — not exposed as standalone shareable event pages. - **SEO:** Vite [`injectSocialMeta`](frontend/vite.config.ts) injects static OG/Twitter tags at build time; SPA routes have no per-event title/description/canonical today. - **Routing guardrails:** referral slug reservation in [`referralPathReserved.ts`](frontend/src/lib/referralPathReserved.ts) — new top-level segments must not collide with reserved slugs (`audit`, `referrals`, etc.). ## Why needed Arena activity currently lives inside the live app and audit feed. Epoch rollovers and podium settlements disappear from casual discovery once the play surface moves on. Permanent, indexable event pages plus an audit-top directory turn historical competition into searchable marketing surface — readable titles, winners, charts, and tx replay — without requiring wallet connection. ## Constraints / guardrails - **Onchain authority:** Event pages are indexer-derived only; onchain logs/tables are source of truth · [guardrails §3](docs/testing/invariants-and-business-logic.md). - **Indexer-first display:** No browser RPC mirrors for podium/timer head on event pages · **`INV-FRONTEND-301-INDEXER-FIRST-DISPLAY`** · [arena-views §301](docs/frontend/arena-views.md#indexer-first-display-gitlab-301). - **Branding / copy:** User-facing strings use **Yield Omega**; forbid TimeCurve / sale-end / redemption framing · [frontend-content-audit.md](docs/testing/frontend-content-audit.md). - **AGPL:** Frontend/indexer changes stay AGPL-3.0-only headers. - **Referral routing:** New public paths must be registered in reserved-slug lists and `LaunchGate.tsx` **before** the `/:referralSegment` catch-all. - **Reorg safety:** Any new indexer tables/views must participate in reorg truncation lists in [`indexer/src/reorg.rs`](indexer/src/reorg.rs). ## Relevant files | Layer | Files | |-------|-------| | Frontend audit | [`ArenaProtocolPage.tsx`](frontend/src/pages/arena/ArenaProtocolPage.tsx), [`ArenaLiveBuysActivitySection.tsx`](frontend/src/pages/arena/ArenaLiveBuysActivitySection.tsx), [`LaunchGate.tsx`](frontend/src/app/LaunchGate.tsx) | | Frontend charts / tx | [`ArenaSections.tsx`](frontend/src/pages/arena/ArenaSections.tsx) (`StandingsVisuals`, `TxHash`), [`AddressInline`](frontend/src/components/AddressInline.tsx), [`WalletProfileModal`](frontend/src/components/WalletProfileModal.tsx) | | Indexer ingest | [`indexer/src/persist.rs`](indexer/src/persist.rs), [`indexer/src/arena_podium_epoch.rs`](indexer/src/arena_podium_epoch.rs), [`indexer/src/arena_session_summary.rs`](indexer/src/arena_session_summary.rs) | | Indexer API | [`indexer/src/api_arena.rs`](indexer/src/api_arena.rs) | | Client API | [`frontend/src/lib/indexerApi.ts`](frontend/src/lib/indexerApi.ts) | | SEO shell | [`frontend/vite.config.ts`](frontend/vite.config.ts), [`frontend/index.html`](frontend/index.html) | | Docs | [`docs/frontend/arena-views.md`](docs/frontend/arena-views.md), [`docs/testing/frontend-content-audit.md`](docs/testing/frontend-content-audit.md) | ## Recommended direction 1. **Indexer — event catalog API** - Add paginated `GET /v1/arena/events` (or split list endpoints) returning stable event ids, kind (`podium_settlement`, `last_buy_epoch_start`, optionally `major_settlement` composite), human title, subtitle, unix time, podium/category, epoch number, tx hash, and deep-link slug. - Add `GET /v1/arena/events/{id}` (or `{kind}/{slug}`) with: winners + prize breakdown, epoch window stats, related buys sample, chart series (deadline/raise or epoch-local metrics), and explorer tx link fields. - Reuse `idx_arena_podium_epoch` + `idx_arena_last_buy_epoch_started`; extend only if list/search needs denormalized title/slug columns. Cap page sizes; index for `block_timestamp DESC` search. 2. **Frontend — permanent event pages** - New route(s), e.g. `/audit/events/:eventId` or `/events/:slug`, lazy-loaded page component with readable H1, winner cards (blockie + `AddressInline` → profile), chart section reusing/adapting `StandingsVisuals` patterns, tx replay block (tx hash, block time, key log fields), and CTA back to `/` play + `/audit`. - Per-route document title + meta description (client-side minimum; optional later SSR/prerender for crawlers). 3. **Frontend — audit directory (top of `/audit`)** - Insert a **PageSection** immediately under the AUDIT hero: filter chips (All · Podium settlements · Last Buy epochs · …), search input (title/epoch/address substring), virtualized or paginated link list to event pages, empty/offline states aligned with indexer connectivity banner patterns. 4. **Search / indexability** - Stable URLs, canonical slugs, descriptive titles ("WarBow Epoch 12 — Alice wins 1st"), and OG tags populated from event detail payload where feasible. ## Acceptance criteria - [ ] `/audit` top section exposes filter + searchable list linking to permanent event pages. - [ ] Each major settlement / epoch event has a dedicated URL with readable title, chart(s), winners, tx replay, and links to current arena (`/`) and audit (`/audit`). - [ ] Event data is served from new indexer list/detail endpoints backed by existing ingest tables (no browser RPC display mirrors). - [ ] New routes do not break referral slug capture or reserved paths. - [ ] Offline / empty indexer states degrade gracefully (no blank errors). - [ ] Copy passes **Yield Omega** / forbidden-framing audit for new strings. ## Test plan | Layer | Command / artifact | Expect | |-------|-------------------|--------| | Indexer unit | `cd indexer && cargo clippy --all-targets -- -D warnings && cargo test` | PASS — new handlers + SQL helpers covered | | Indexer integration | `bash scripts/verify-podium-live-anvil.sh` (or dedicated verify script if added) | PASS — event rows appear after forced epoch roll on Anvil | | Frontend unit | `cd frontend && npm run typecheck && npm run lint && npm test` | PASS — directory component, route wiring, API client tests | | Static IA | Extend `frontendContentAudit.test.ts` or arena static tests for `/audit` event directory presence | PASS | | E2E (Anvil) | New/extended Playwright spec under `frontend/e2e/` with `--workers=5` | PASS — audit search navigates to event page; winners + tx hash visible | | Manual QA | Desktop + mobile spot-check audit filter/search + event page share preview | PASS — readable, no wallet required | ## Attack / abuse test plan - **Indexer list/detail:** fuzz `limit`/`offset`/search query; assert caps (≤200), no SQL injection, stable 400 on bad cursors/ids. - **Search:** long unicode/query strings; empty result; rate-limit behavior unchanged under [`rate_limit.rs`](indexer/src/rate_limit.rs). - **Public pages:** no PII beyond onchain addresses; no wallet write prompts on read-only event pages. - **Routing:** verify reserved slugs (`audit`, `referrals`, `home`, …) still resolve correctly; event slugs cannot shadow referral codes. ## Verification criteria - [ ] `cd indexer && cargo clippy --all-targets -- -D warnings && cargo test` — PASS - [ ] `cd frontend && npm run typecheck && npm run lint && npm test` — PASS - [ ] Anvil verify script for event ingest/API (existing or new) — PASS - [ ] Playwright Anvil spec for audit directory → event page navigation — PASS - [ ] Manual screenshot: audit directory + one event page legible on mobile width — PASS
PlasticDigits commented 2026-07-07 02:39:35 +00:00 (Migrated from gitlab.com)

mentioned in issue #363

mentioned in issue #363
PlasticDigits commented 2026-07-07 04:33:52 +00:00 (Migrated from gitlab.com)

mentioned in commit f7e9817f43

mentioned in commit f7e9817f43491ebed054b2dc8f6831f003bd029a
PlasticDigits commented 2026-07-07 04:34:14 +00:00 (Migrated from gitlab.com)

mentioned in merge request !537

mentioned in merge request !537
PlasticDigits commented 2026-07-07 06:28:09 +00:00 (Migrated from gitlab.com)

mentioned in commit ed8dea0040

mentioned in commit ed8dea00405ae404789b837fdbcf0c657e9de004
PlasticDigits commented 2026-07-07 09:59:38 +00:00 (Migrated from gitlab.com)

mentioned in commit c6229c6dd1

mentioned in commit c6229c6dd19cce4594c9d93bf3cbc4ca5a7fe319
PlasticDigits commented 2026-07-07 10:00:34 +00:00 (Migrated from gitlab.com)

mentioned in merge request !538

mentioned in merge request !538
PlasticDigits commented 2026-07-07 12:25:18 +00:00 (Migrated from gitlab.com)

mentioned in commit 25329b9e81

mentioned in commit 25329b9e81ef46ba48e0cc51e90d3400cd5df55d
PlasticDigits commented 2026-07-07 12:43:07 +00:00 (Migrated from gitlab.com)

Verification — GitLab #364 (agent:verify)

Scope: Permanent arena event pages and audit event directory.

Acceptance criteria

Criterion Result How verified
/audit top section: filter + searchable list linking to event pages PASS ArenaEventDirectorySection.test.tsx; Playwright e2e/anvil-audit-events.spec.ts (directory visible, filter chips, search, link navigation)
Dedicated event URLs with title, chart(s), winners, tx replay, CTAs to / and /audit PASS Playwright E2E asserts H1, "Transaction replay", tx hash, "Play Time Arena", "Back to AUDIT directory"; verify-arena-events-anvil.sh detail API
Indexer list/detail endpoints from existing ingest tables (no browser RPC mirrors) PASS bash scripts/verify-arena-events-anvil.sh; INV-INDEXER-364-ARENA-EVENTS integration smoke in integration_stage2.rs
Routes do not break referral slug capture / reserved paths PASS audit/events/:eventId registered before /:referralSegment in LaunchGate.tsx; referralPathReserved.test.ts blocks audit
Offline / empty indexer states degrade gracefully PASS useArenaEventDirectory + ArenaEventPage offline copy; ArenaEventDirectorySection empty/search states (unit + E2E)
Copy passes Yield Omega / forbidden-framing audit PASS Event page sets · Yield Omega title; no TimeCurve/sale-end strings in event components; frontendContentAudit.test.ts PASS

Test plan / verification criteria

Layer Command Result
Indexer unit cd indexer && cargo clippy --all-targets -- -D warnings && cargo test PASS (109 unit + 8 integration)
Indexer Anvil bash scripts/verify-arena-events-anvil.sh PASS — list ≥1 event, last_buy_epoch_start filter, detail 200, bad id → 400
Frontend unit cd frontend && npm run typecheck && npm run lint && npm test PASS (896 tests; includes ArenaEventDirectorySection.test.tsx, indexerApi.test.ts)
Static IA frontendContentAudit.test.ts + arena-views §364 docs PASS
E2E (Anvil) YIELDOMEGA_E2E_INDEXER=1 PLAYWRIGHT_SPECS="e2e/anvil-audit-events.spec.ts" bash scripts/e2e-anvil.sh PASS (2/2 — directory→event navigation + mobile viewport)
Manual QA (mobile legibility) Playwright mobile viewport 390×844: audit directory + event page without wallet PASS

Attack / abuse checks (spot)

Check Result
limit=9999 clamped to ≤200 PASS (integration_stage2.rs::api_arena_events_smoke)
Invalid event id → 400 PASS (verify script + integration)
Filtered ?kind=&q= queries PASS (verify script)

Environment

  • Native Postgres :5433 — bash scripts/verify-cloud-postgres.sh PASS
  • Anvil deploy + indexer ingest via verify/E2E scripts (no Docker required)

Overall: PASS — implementation on main meets all acceptance and verification criteria. Closing #364.

## Verification — GitLab #364 (agent:verify) **Scope:** Permanent arena event pages and audit event directory. ### Acceptance criteria | Criterion | Result | How verified | |-----------|--------|--------------| | `/audit` top section: filter + searchable list linking to event pages | **PASS** | `ArenaEventDirectorySection.test.tsx`; Playwright `e2e/anvil-audit-events.spec.ts` (directory visible, filter chips, search, link navigation) | | Dedicated event URLs with title, chart(s), winners, tx replay, CTAs to `/` and `/audit` | **PASS** | Playwright E2E asserts H1, "Transaction replay", tx hash, "Play Time Arena", "Back to AUDIT directory"; `verify-arena-events-anvil.sh` detail API | | Indexer list/detail endpoints from existing ingest tables (no browser RPC mirrors) | **PASS** | `bash scripts/verify-arena-events-anvil.sh`; `INV-INDEXER-364-ARENA-EVENTS` integration smoke in `integration_stage2.rs` | | Routes do not break referral slug capture / reserved paths | **PASS** | `audit/events/:eventId` registered before `/:referralSegment` in `LaunchGate.tsx`; `referralPathReserved.test.ts` blocks `audit` | | Offline / empty indexer states degrade gracefully | **PASS** | `useArenaEventDirectory` + `ArenaEventPage` offline copy; `ArenaEventDirectorySection` empty/search states (unit + E2E) | | Copy passes Yield Omega / forbidden-framing audit | **PASS** | Event page sets `· Yield Omega` title; no TimeCurve/sale-end strings in event components; `frontendContentAudit.test.ts` PASS | ### Test plan / verification criteria | Layer | Command | Result | |-------|---------|--------| | Indexer unit | `cd indexer && cargo clippy --all-targets -- -D warnings && cargo test` | **PASS** (109 unit + 8 integration) | | Indexer Anvil | `bash scripts/verify-arena-events-anvil.sh` | **PASS** — list ≥1 event, `last_buy_epoch_start` filter, detail 200, bad id → 400 | | Frontend unit | `cd frontend && npm run typecheck && npm run lint && npm test` | **PASS** (896 tests; includes `ArenaEventDirectorySection.test.tsx`, `indexerApi.test.ts`) | | Static IA | `frontendContentAudit.test.ts` + arena-views §364 docs | **PASS** | | E2E (Anvil) | `YIELDOMEGA_E2E_INDEXER=1 PLAYWRIGHT_SPECS="e2e/anvil-audit-events.spec.ts" bash scripts/e2e-anvil.sh` | **PASS** (2/2 — directory→event navigation + mobile viewport) | | Manual QA (mobile legibility) | Playwright mobile viewport 390×844: audit directory + event page without wallet | **PASS** | ### Attack / abuse checks (spot) | Check | Result | |-------|--------| | `limit=9999` clamped to ≤200 | **PASS** (`integration_stage2.rs::api_arena_events_smoke`) | | Invalid event id → 400 | **PASS** (verify script + integration) | | Filtered `?kind=&q=` queries | **PASS** (verify script) | ### Environment - Native Postgres `:5433` — `bash scripts/verify-cloud-postgres.sh` **PASS** - Anvil deploy + indexer ingest via verify/E2E scripts (no Docker required) **Overall: PASS** — implementation on `main` meets all acceptance and verification criteria. Closing #364.
PlasticDigits (Migrated from gitlab.com) closed this issue 2026-07-07 12:43:08 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
code/yieldomega#364
No description provided.