Indexer: GET /v1/arena/wallet/{{address}}/stats for profile modal #255

Closed
opened 2026-05-27 07:07:38 +00:00 by PlasticDigits · 16 comments
PlasticDigits commented 2026-05-27 07:07:38 +00:00 (Migrated from gitlab.com)

Context

Wallet stats API for participant profile modal. Parent epic: #238.

Relevant files

  • indexer/src/api.rs
  • SQL aggregations over buy, podium payout, XP, CRED, WarBow epochs

Acceptance criteria

API returns:

  • epochs_participated (Last Buy epochs with ≥1 buy)
  • prizes_won[]: { podium, epoch, rank, amount_doub }
  • total_won_doub, total_spent_doub, buy_count
  • xp, level
  • highest_scores[]: { podium, epoch, score, rank } for Streak, TimeBooster, WarBow, LastBuy
  • Bonus stats: first buy timestamp, longest defended streak, WarBow steals/guards, referral CRED earned, CRED claimed, average buy size, max single buy, podium win rate, rank distribution

Verification checklist

  • Integration test with fixture buys across 2 Last Buy epochs
  • p95 query latency acceptable on Anvil-rich dataset
## Context Wallet stats API for participant profile modal. Parent epic: #238. ## Relevant files - `indexer/src/api.rs` - SQL aggregations over buy, podium payout, XP, CRED, WarBow epochs ## Acceptance criteria API returns: - [ ] `epochs_participated` (Last Buy epochs with ≥1 buy) - [ ] `prizes_won[]`: `{ podium, epoch, rank, amount_doub }` - [ ] `total_won_doub`, `total_spent_doub`, `buy_count` - [ ] `xp`, `level` - [ ] `highest_scores[]`: `{ podium, epoch, score, rank }` for Streak, TimeBooster, WarBow, LastBuy - [ ] Bonus stats: first buy timestamp, longest defended streak, WarBow steals/guards, referral CRED earned, CRED claimed, average buy size, max single buy, podium win rate, rank distribution ## Verification checklist - [ ] Integration test with fixture buys across 2 Last Buy epochs - [ ] p95 query latency acceptable on Anvil-rich dataset
PlasticDigits commented 2026-05-27 07:07:39 +00:00 (Migrated from gitlab.com)

marked as related to #238

marked as related to #238
PlasticDigits commented 2026-05-27 07:08:00 +00:00 (Migrated from gitlab.com)

mentioned in issue #238

mentioned in issue #238
PlasticDigits commented 2026-05-28 13:58:53 +00:00 (Migrated from gitlab.com)

Implementation summary

  • GET /v1/arena/wallet/{address}/stats in indexer/src/api_arena.rs.

Acceptance criteria

  • Core spend/buy/level/cred/warbow fields
  • Full bonus stats (partial stub zeros)

Verification checklist

  • Integration test with 2 epochs (follow-up)
## Implementation summary - `GET /v1/arena/wallet/{address}/stats` in `indexer/src/api_arena.rs`. ## Acceptance criteria - [x] Core spend/buy/level/cred/warbow fields - [ ] Full bonus stats (partial stub zeros) ## Verification checklist - [ ] Integration test with 2 epochs (follow-up)
PlasticDigits commented 2026-06-01 03:19:25 +00:00 (Migrated from gitlab.com)

Stub must be removed, required full bonus stats.

Stub must be removed, required full bonus stats.
PlasticDigits commented 2026-06-01 03:28:16 +00:00 (Migrated from gitlab.com)

mentioned in commit 79d8ebb981

mentioned in commit 79d8ebb981db8d534137536e4b8a0523975b3a6d
PlasticDigits commented 2026-06-01 03:28:16 +00:00 (Migrated from gitlab.com)

mentioned in commit 502785819d

mentioned in commit 502785819d93a6aff580f28d80723865005472ca
PlasticDigits commented 2026-06-01 03:28:40 +00:00 (Migrated from gitlab.com)

Implementation complete (#255)

Removed stub zeros from GET /v1/arena/wallet/{address}/stats. Full participant profile aggregates now live in indexer/src/arena_wallet_stats.rs (schema ≥ 2.4.0).

What changed

  • Core: epochs_participated, buy_count, spend stats, xp (sum), level (latest), cred_claimed
  • Prizes: prizes_won[] with 4:2:1 pool_paid split from idx_arena_podium_epoch; total_won_doub
  • Scores: highest_scores[] per podium (last_buy, time_booster, defended_streak, warbow) from indexed buys + WarBow tables
  • Bonus: longest_defended_streak, warbow_steals / warbow_guards, referral_cred_earned, podium_win_rate, rank_distribution
  • Tests: integration_stage2.rs::arena_wallet_stats_two_epochs_and_bonus_fields (2 Last Buy epochs)
  • Docs: INV-INDEXER-255-WALLET-STATS, indexer design §255, guardrails + play skill crosslinks

Merged to main at 79d8ebb.

Verification checklist

  • cd indexer && cargo test — unit + integration (needs YIELDOMEGA_PG_TEST_URL)
  • GET /v1/arena/wallet/0x…/stats on Anvil stack returns non-stub prizes_won, highest_scores, bonus fields after buys across 2 hard-reset epochs
  • Wallet profile modal (WalletProfileModal) loads stats for a buyer with indexed history
  • Empty wallet → zeros / empty arrays (not 404); invalid address → 400
  • x-schema-version: 2.4.0 on response

Follow-ups (optional)

  • Persist LastBuyEpochStarted for exact epoch assignment without timer_hard_reset window inference
  • p95 latency benchmark on Anvil-rich dataset (acceptance criterion — not automated in CI yet)

Requesting verification from the QA agent team.

## Implementation complete (#255) Removed stub zeros from `GET /v1/arena/wallet/{address}/stats`. Full participant profile aggregates now live in `indexer/src/arena_wallet_stats.rs` (schema **≥ 2.4.0**). ### What changed - **Core:** `epochs_participated`, `buy_count`, spend stats, `xp` (sum), `level` (latest), `cred_claimed` - **Prizes:** `prizes_won[]` with 4:2:1 `pool_paid` split from `idx_arena_podium_epoch`; `total_won_doub` - **Scores:** `highest_scores[]` per podium (last_buy, time_booster, defended_streak, warbow) from indexed buys + WarBow tables - **Bonus:** `longest_defended_streak`, `warbow_steals` / `warbow_guards`, `referral_cred_earned`, `podium_win_rate`, `rank_distribution` - **Tests:** `integration_stage2.rs::arena_wallet_stats_two_epochs_and_bonus_fields` (2 Last Buy epochs) - **Docs:** `INV-INDEXER-255-WALLET-STATS`, [indexer design §255](docs/indexer/design.md#arena-wallet-stats-http-gitlab-255), guardrails + play skill crosslinks Merged to `main` at `79d8ebb`. ### Verification checklist - [ ] `cd indexer && cargo test` — unit + integration (needs `YIELDOMEGA_PG_TEST_URL`) - [ ] `GET /v1/arena/wallet/0x…/stats` on Anvil stack returns non-stub `prizes_won`, `highest_scores`, bonus fields after buys across 2 hard-reset epochs - [ ] Wallet profile modal (`WalletProfileModal`) loads stats for a buyer with indexed history - [ ] Empty wallet → zeros / empty arrays (not 404); invalid address → 400 - [ ] `x-schema-version: 2.4.0` on response ### Follow-ups (optional) - Persist `LastBuyEpochStarted` for exact epoch assignment without `timer_hard_reset` window inference - p95 latency benchmark on Anvil-rich dataset (acceptance criterion — not automated in CI yet) Requesting verification from the QA agent team.
PlasticDigits commented 2026-06-01 03:31:04 +00:00 (Migrated from gitlab.com)

mentioned in issue #273

mentioned in issue #273
PlasticDigits commented 2026-06-01 03:41:13 +00:00 (Migrated from gitlab.com)

QA verification (#255) — issue left open

Verified GET /v1/arena/wallet/{address}/stats on branch issue/255-wallet-stats, merged to main at cee483a.

Bugs fixed during verification

  1. fetch_podium_placements rank decode — PostgreSQL CASE … END returns INT4; Rust was decoding as Option<i16>, causing 500 on any wallet with podium placements. Fixed to Option<i32>.
  2. Integration test isolation — parallel cargo test shared one Postgres URL without locking; tests deleted each other's rows. Added PG_INTEGRATION_MUTEX + clear_arena_index_for_test before wallet-stats fixture.

What passed

  • cd indexer && YIELDOMEGA_PG_TEST_URL=… cargo test — 29 unit + 3 integration (including arena_wallet_stats_two_epochs_and_bonus_fields)
  • Acceptance fields in integration fixture: epochs_participated (2), prizes_won[], spend totals, xp/level, highest_scores[] (4 podiums), bonus stats (referral_cred_earned, warbow_guards, rank_distribution, …)
  • Empty wallet → zeros / empty arrays, 200 (not 404)
  • Invalid address → 400 { "error": "invalid_address" }
  • x-schema-version: 2.4.0 on live stack response
  • p95 latency (empty-wallet baseline, 100 requests vs local indexer): ~4 ms (p50 ~2 ms)
  • Docs: INV-INDEXER-255-WALLET-STATS crosslinks; invariants § Postgres integration mutex note

Not fully verified (follow-up for QA team)

  • Anvil-rich dataset p95 — acceptance criterion; integration fixture covers SQL path; live rich-state stack not benchmarked (local cast send gas estimation failed on this host after DeployDev)
  • Live stack: buys across 2 hard-reset epochs → non-stub prizes_won / highest_scores via HTTP after indexer ingest
  • WalletProfileModal loads stats for a buyer with indexed history (#258)

Manual verification checklist

  1. bash scripts/start-local-anvil-stack.sh (or QA host make start-qa)
  2. Execute ≥2 DOUB buys spanning a Last Buy hard reset for wallet 0x…
  3. curl -s http://127.0.0.1:3100/v1/arena/wallet/0x…/stats | jq — confirm non-zero buy_count, epochs_participated ≥ 2, populated highest_scores
  4. Open /arena, click a buyer on live buys → profile modal shows matching stats
  5. Optional: benchmark p95 on rich Anvil DB (100× curl loop; target ≪ 1s)

Requesting verification from the QA agent team before close.

## QA verification (#255) — issue left open Verified **`GET /v1/arena/wallet/{address}/stats`** on branch `issue/255-wallet-stats`, merged to `main` at `cee483a`. ### Bugs fixed during verification 1. **`fetch_podium_placements` rank decode** — PostgreSQL `CASE … END` returns **INT4**; Rust was decoding as `Option<i16>`, causing **500** on any wallet with podium placements. Fixed to `Option<i32>`. 2. **Integration test isolation** — parallel `cargo test` shared one Postgres URL without locking; tests deleted each other's rows. Added `PG_INTEGRATION_MUTEX` + `clear_arena_index_for_test` before wallet-stats fixture. ### What passed - [x] `cd indexer && YIELDOMEGA_PG_TEST_URL=… cargo test` — 29 unit + 3 integration (including `arena_wallet_stats_two_epochs_and_bonus_fields`) - [x] Acceptance fields in integration fixture: `epochs_participated` (2), `prizes_won[]`, spend totals, `xp`/`level`, `highest_scores[]` (4 podiums), bonus stats (`referral_cred_earned`, `warbow_guards`, `rank_distribution`, …) - [x] Empty wallet → zeros / empty arrays, **200** (not 404) - [x] Invalid address → **400** `{ "error": "invalid_address" }` - [x] `x-schema-version: 2.4.0` on live stack response - [x] p95 latency (empty-wallet baseline, 100 requests vs local indexer): **~4 ms** (p50 ~2 ms) - [x] Docs: **`INV-INDEXER-255-WALLET-STATS`** crosslinks; invariants § Postgres integration mutex note ### Not fully verified (follow-up for QA team) - [ ] **Anvil-rich dataset p95** — acceptance criterion; integration fixture covers SQL path; live rich-state stack not benchmarked (local `cast send` gas estimation failed on this host after DeployDev) - [ ] **Live stack: buys across 2 hard-reset epochs** → non-stub `prizes_won` / `highest_scores` via HTTP after indexer ingest - [ ] **`WalletProfileModal`** loads stats for a buyer with indexed history ([#258](https://gitlab.com/PlasticDigits/yieldomega/-/issues/258)) ### Manual verification checklist 1. `bash scripts/start-local-anvil-stack.sh` (or QA host `make start-qa`) 2. Execute ≥2 DOUB buys spanning a Last Buy hard reset for wallet `0x…` 3. `curl -s http://127.0.0.1:3100/v1/arena/wallet/0x…/stats | jq` — confirm non-zero `buy_count`, `epochs_participated ≥ 2`, populated `highest_scores` 4. Open `/arena`, click a buyer on live buys → profile modal shows matching stats 5. Optional: benchmark p95 on rich Anvil DB (`100×` curl loop; target ≪ 1s) Requesting verification from the QA agent team before close.
ghost1 commented 2026-06-02 13:21:03 +00:00 (Migrated from gitlab.com)

QA verification (#255) — issue left open

Verified GET /v1/arena/wallet/{address}/stats on main at 7d7d3da (2026-06-02).

Acceptance criteria (issue body)

Criterion Result Evidence
epochs_participated (Last Buy epochs with ≥1 buy) PASS Integration: epochs_participated == 2; live Anvil: epochs_participated: 2 after hard-reset buy
prizes_won[] { podium, epoch, rank, amount_doub } PASS Integration fixture asserts prizes_won[0] with last_buy rank 1 / amount_doub: 400
total_won_doub, total_spent_doub, buy_count PASS Live: buy_count: 4, total_spent_doub: 13000000000000000000000
xp, level PASS Integration: xp: 5, level: 2; live: xp: 13, level: 1
highest_scores[] (4 podiums) PASS Integration: highest_scores.len() == 4; live: 4 entries across epochs 0/1
Bonus stats (first buy, streak, WarBow, referral CRED, CRED claimed, avg/max buy, win rate, rank distribution) PASS Integration asserts referral_cred_earned, warbow_guards, rank_distribution; live response includes all bonus keys
Integration test — 2 Last Buy epochs PASS cargo test arena_wallet_stats_two_epochs_and_bonus_fields (with YIELDOMEGA_PG_TEST_URL)
p95 query latency (Anvil dataset) PASS 100× curl loop vs local indexer: p50 ~1.4 ms, p95 ~2.9 ms (max ~28 ms)

Verification checklist (comments + invariants)

Check Result How
INV-INDEXER-255-WALLET-STATS PASS indexer/src/arena_wallet_stats.rs, integration_stage2.rs::arena_wallet_stats_two_epochs_and_bonus_fields
Empty wallet → zeros / empty arrays, 200 (not 404) PASS curl …/wallet/0x…0001/stats → HTTP 200, buy_count: 0
Invalid address → 400 { "error": "invalid_address" } PASS curl …/wallet/notanaddress/stats
x-schema-version on response PASS Header x-schema-version: 2.5.0 (≥ 2.4.0)
Live stack: buys across 2 hard-reset epochs → non-stub HTTP stats PASS bash scripts/start-qa-local-full-stack.sh --live-sale --no-swarm --no-frontend; cast DOUB buys + warp-to-deadline hard reset; curl /v1/arena/wallet/0x7099…/stats
Indexer unit tests (arena_wallet_stats::*) PASS 5/5 unit tests
Full indexer cargo test (integration) PASS 3/3 integration_stage2 (PG URL: postgres://yieldomega:password@127.0.0.1:5433/yieldomega_indexer_test)
Frontend modal wiring (#258) PASS (unit) WalletProfileModalSections.test.tsx (8), LiveBuyRow.test.tsx (2), ArenaLiveBuysActivitySection.test.tsx (1)
Manual: click buyer on /arena → modal matches API SKIP Vite bound to 5174 (5173 in use); no Playwright spec for wallet profile. API + component unit tests cover data path; recommend human/Playwright pass on a clean port

Commands (representative)

export PATH="$HOME/.cargo/bin:$PATH"
export YIELDOMEGA_PG_TEST_URL="postgres://yieldomega:password@127.0.0.1:5433/yieldomega_indexer_test"
cd indexer && cargo test arena_wallet_stats

# Live stack (already running):
curl -sI http://127.0.0.1:3100/v1/arena/wallet/0x70997970c51812dc3a010c7d01b50e0d17dc79c8/stats | grep -i x-schema-version
curl -s http://127.0.0.1:3100/v1/arena/wallet/0x70997970c51812dc3a010c7d01b50e0d17dc79c8/stats | jq '.epochs_participated,.buy_count,.highest_scores|length'

Follow-ups (optional)

  • Add bash scripts/verify-wallet-stats-anvil.sh (mirror verify-podium-live-anvil.sh) for repeatable live-stack QA.
  • Playwright E2E: open /arena, click AddressInline on a live buy row, assert modal sections match GET /v1/arena/wallet/{address}/stats (#258).
  • Persist LastBuyEpochStarted for exact epoch assignment without timer_hard_reset window inference (noted in prior implementation comment).

No repository changes required for #255. Leaving issue open per process.

## QA verification (#255) — issue left open Verified **`GET /v1/arena/wallet/{address}/stats`** on `main` at `7d7d3da` (2026-06-02). ### Acceptance criteria (issue body) | Criterion | Result | Evidence | |-----------|--------|----------| | `epochs_participated` (Last Buy epochs with ≥1 buy) | **PASS** | Integration: `epochs_participated == 2`; live Anvil: `epochs_participated: 2` after hard-reset buy | | `prizes_won[]` `{ podium, epoch, rank, amount_doub }` | **PASS** | Integration fixture asserts `prizes_won[0]` with `last_buy` rank 1 / `amount_doub: 400` | | `total_won_doub`, `total_spent_doub`, `buy_count` | **PASS** | Live: `buy_count: 4`, `total_spent_doub: 13000000000000000000000` | | `xp`, `level` | **PASS** | Integration: `xp: 5`, `level: 2`; live: `xp: 13`, `level: 1` | | `highest_scores[]` (4 podiums) | **PASS** | Integration: `highest_scores.len() == 4`; live: 4 entries across epochs 0/1 | | Bonus stats (first buy, streak, WarBow, referral CRED, CRED claimed, avg/max buy, win rate, rank distribution) | **PASS** | Integration asserts `referral_cred_earned`, `warbow_guards`, `rank_distribution`; live response includes all bonus keys | | Integration test — 2 Last Buy epochs | **PASS** | `cargo test arena_wallet_stats_two_epochs_and_bonus_fields` (with `YIELDOMEGA_PG_TEST_URL`) | | p95 query latency (Anvil dataset) | **PASS** | 100× `curl` loop vs local indexer: **p50 ~1.4 ms**, **p95 ~2.9 ms** (max ~28 ms) | ### Verification checklist (comments + invariants) | Check | Result | How | |-------|--------|-----| | `INV-INDEXER-255-WALLET-STATS` | **PASS** | `indexer/src/arena_wallet_stats.rs`, `integration_stage2.rs::arena_wallet_stats_two_epochs_and_bonus_fields` | | Empty wallet → zeros / empty arrays, **200** (not 404) | **PASS** | `curl …/wallet/0x…0001/stats` → HTTP 200, `buy_count: 0` | | Invalid address → **400** `{ "error": "invalid_address" }` | **PASS** | `curl …/wallet/notanaddress/stats` | | `x-schema-version` on response | **PASS** | Header `x-schema-version: 2.5.0` (≥ 2.4.0) | | Live stack: buys across 2 hard-reset epochs → non-stub HTTP stats | **PASS** | `bash scripts/start-qa-local-full-stack.sh --live-sale --no-swarm --no-frontend`; `cast` DOUB buys + warp-to-deadline hard reset; `curl /v1/arena/wallet/0x7099…/stats` | | Indexer unit tests (`arena_wallet_stats::*`) | **PASS** | 5/5 unit tests | | Full indexer `cargo test` (integration) | **PASS** | 3/3 `integration_stage2` (PG URL: `postgres://yieldomega:password@127.0.0.1:5433/yieldomega_indexer_test`) | | Frontend modal wiring ([#258](https://gitlab.com/PlasticDigits/yieldomega/-/issues/258)) | **PASS** (unit) | `WalletProfileModalSections.test.tsx` (8), `LiveBuyRow.test.tsx` (2), `ArenaLiveBuysActivitySection.test.tsx` (1) | | Manual: click buyer on `/arena` → modal matches API | **SKIP** | Vite bound to **5174** (5173 in use); no Playwright spec for wallet profile. API + component unit tests cover data path; recommend human/Playwright pass on a clean port | ### Commands (representative) ```bash export PATH="$HOME/.cargo/bin:$PATH" export YIELDOMEGA_PG_TEST_URL="postgres://yieldomega:password@127.0.0.1:5433/yieldomega_indexer_test" cd indexer && cargo test arena_wallet_stats # Live stack (already running): curl -sI http://127.0.0.1:3100/v1/arena/wallet/0x70997970c51812dc3a010c7d01b50e0d17dc79c8/stats | grep -i x-schema-version curl -s http://127.0.0.1:3100/v1/arena/wallet/0x70997970c51812dc3a010c7d01b50e0d17dc79c8/stats | jq '.epochs_participated,.buy_count,.highest_scores|length' ``` ### Follow-ups (optional) - Add `bash scripts/verify-wallet-stats-anvil.sh` (mirror `verify-podium-live-anvil.sh`) for repeatable live-stack QA. - Playwright E2E: open `/arena`, click `AddressInline` on a live buy row, assert modal sections match `GET /v1/arena/wallet/{address}/stats` ([#258](https://gitlab.com/PlasticDigits/yieldomega/-/issues/258)). - Persist `LastBuyEpochStarted` for exact epoch assignment without `timer_hard_reset` window inference (noted in prior implementation comment). **No repository changes required for #255.** Leaving issue open per process.
ghost1 commented 2026-06-02 13:30:36 +00:00 (Migrated from gitlab.com)

mentioned in issue #278

mentioned in issue #278
PlasticDigits commented 2026-06-02 14:50:48 +00:00 (Migrated from gitlab.com)

mentioned in issue #282

mentioned in issue #282
PlasticDigits commented 2026-06-03 11:40:13 +00:00 (Migrated from gitlab.com)

mentioned in issue #283

mentioned in issue #283
PlasticDigits commented 2026-06-03 13:31:41 +00:00 (Migrated from gitlab.com)

QA verification (#255) — closing

Verified GET /v1/arena/wallet/{address}/stats on main at 6d520e7 (2026-06-03).

Acceptance criteria (issue body)

Criterion Result How
epochs_participated (Last Buy epochs with ≥1 buy) PASS Integration: epochs_participated == 2; live Anvil (2 hard-reset epochs): epochs_participated: 2
prizes_won[] { podium, epoch, rank, amount_doub } PASS Integration fixture asserts prizes_won[0] with last_buy rank 1 / amount_doub: 400
total_won_doub, total_spent_doub, buy_count PASS Live HTTP after buys; integration fixture spend totals
xp, level PASS Integration: xp: 5, level: 2
highest_scores[] (4 podiums) PASS Integration: highest_scores.len() == 4; live: 4 entries
Bonus stats (first buy, streak, WarBow, referral CRED, CRED claimed, avg/max buy, win rate, rank distribution) PASS Integration asserts bonus fields; live HTTP all keys non-null
Integration test — 2 Last Buy epochs PASS cargo test arena_wallet_stats_two_epochs_and_bonus_fields
p95 query latency (Anvil dataset) PASS 100× curl vs local indexer after multi-buy ingest: p50 ~2.7 ms, p95 ~4.2 ms (max ~8.6 ms)

Verification checklist (comments + invariants)

Check Result How
INV-INDEXER-255-WALLET-STATS PASS indexer/src/arena_wallet_stats.rs, integration_stage2.rs::arena_wallet_stats_two_epochs_and_bonus_fields, design §255, guardrails §9a
cd indexer && cargo test PASS 31 unit + 4 integration (YIELDOMEGA_PG_TEST_URL=postgres://yieldomega:password@127.0.0.1:5433/yieldomega_indexer_test)
arena_wallet_stats unit tests PASS 5/5
Live stack: 2 hard-reset epochs → non-stub HTTP stats PASS Anvil deploy + DOUB buys spanning Last Buy hard reset; curl /v1/arena/wallet/0x7099…/stats
Empty wallet → zeros / empty arrays, 200 PASS curl …/wallet/0x…0001/stats → HTTP 200, buy_count: 0
Invalid address → 400 { "error": "invalid_address" } PASS curl …/wallet/notanaddress/stats
x-schema-version on response PASS Header x-schema-version: 2.5.0 (≥ 2.4.0)
bash scripts/verify-wallet-profile-anvil.sh PASS Buy-row parity + wallet stats smoke
bash scripts/verify-last-buy-epoch-anvil.sh PASS Global last_buy_epoch + wallet stats
Frontend unit tests (modal sections / API path) PASS npm test -- WalletProfileModal LiveBuyRow ArenaLiveBuys indexerApi — 33/33
Manual: /arena click buyer → modal matches API PASS Playwright against Vite dev + live indexer: all 7 modal sections visible; buy_count matches GET /v1/arena/wallet/{address}/stats

Commands (representative)

export PATH="$HOME/.foundry/bin:$PATH"
export YIELDOMEGA_PG_TEST_URL="postgres://yieldomega:password@127.0.0.1:5433/yieldomega_indexer_test"
cd indexer && cargo test arena_wallet_stats
bash scripts/verify-wallet-profile-anvil.sh
bash scripts/verify-last-buy-epoch-anvil.sh
cd frontend && npm test -- --run WalletProfileModal LiveBuyRow ArenaLiveBuys indexerApi

No repository changes required. All acceptance criteria pass on main.

## QA verification (#255) — closing Verified **`GET /v1/arena/wallet/{address}/stats`** on `main` at `6d520e7` (2026-06-03). ### Acceptance criteria (issue body) | Criterion | Result | How | |-----------|--------|-----| | `epochs_participated` (Last Buy epochs with ≥1 buy) | **PASS** | Integration: `epochs_participated == 2`; live Anvil (2 hard-reset epochs): `epochs_participated: 2` | | `prizes_won[]` `{ podium, epoch, rank, amount_doub }` | **PASS** | Integration fixture asserts `prizes_won[0]` with `last_buy` rank 1 / `amount_doub: 400` | | `total_won_doub`, `total_spent_doub`, `buy_count` | **PASS** | Live HTTP after buys; integration fixture spend totals | | `xp`, `level` | **PASS** | Integration: `xp: 5`, `level: 2` | | `highest_scores[]` (4 podiums) | **PASS** | Integration: `highest_scores.len() == 4`; live: 4 entries | | Bonus stats (first buy, streak, WarBow, referral CRED, CRED claimed, avg/max buy, win rate, rank distribution) | **PASS** | Integration asserts bonus fields; live HTTP all keys non-null | | Integration test — 2 Last Buy epochs | **PASS** | `cargo test arena_wallet_stats_two_epochs_and_bonus_fields` | | p95 query latency (Anvil dataset) | **PASS** | 100× curl vs local indexer after multi-buy ingest: **p50 ~2.7 ms**, **p95 ~4.2 ms** (max ~8.6 ms) | ### Verification checklist (comments + invariants) | Check | Result | How | |-------|--------|-----| | `INV-INDEXER-255-WALLET-STATS` | **PASS** | `indexer/src/arena_wallet_stats.rs`, `integration_stage2.rs::arena_wallet_stats_two_epochs_and_bonus_fields`, design §255, guardrails §9a | | `cd indexer && cargo test` | **PASS** | 31 unit + 4 integration (`YIELDOMEGA_PG_TEST_URL=postgres://yieldomega:password@127.0.0.1:5433/yieldomega_indexer_test`) | | `arena_wallet_stats` unit tests | **PASS** | 5/5 | | Live stack: 2 hard-reset epochs → non-stub HTTP stats | **PASS** | Anvil deploy + DOUB buys spanning Last Buy hard reset; `curl /v1/arena/wallet/0x7099…/stats` | | Empty wallet → zeros / empty arrays, **200** | **PASS** | `curl …/wallet/0x…0001/stats` → HTTP 200, `buy_count: 0` | | Invalid address → **400** `{ "error": "invalid_address" }` | **PASS** | `curl …/wallet/notanaddress/stats` | | `x-schema-version` on response | **PASS** | Header `x-schema-version: 2.5.0` (≥ 2.4.0) | | `bash scripts/verify-wallet-profile-anvil.sh` | **PASS** | Buy-row parity + wallet stats smoke | | `bash scripts/verify-last-buy-epoch-anvil.sh` | **PASS** | Global `last_buy_epoch` + wallet stats | | Frontend unit tests (modal sections / API path) | **PASS** | `npm test -- WalletProfileModal LiveBuyRow ArenaLiveBuys indexerApi` — 33/33 | | Manual: `/arena` click buyer → modal matches API | **PASS** | Playwright against Vite dev + live indexer: all 7 modal sections visible; `buy_count` matches `GET /v1/arena/wallet/{address}/stats` | ### Commands (representative) ```bash export PATH="$HOME/.foundry/bin:$PATH" export YIELDOMEGA_PG_TEST_URL="postgres://yieldomega:password@127.0.0.1:5433/yieldomega_indexer_test" cd indexer && cargo test arena_wallet_stats bash scripts/verify-wallet-profile-anvil.sh bash scripts/verify-last-buy-epoch-anvil.sh cd frontend && npm test -- --run WalletProfileModal LiveBuyRow ArenaLiveBuys indexerApi ``` **No repository changes required.** All acceptance criteria pass on `main`.
PlasticDigits (Migrated from gitlab.com) closed this issue 2026-06-03 13:31:42 +00:00
PlasticDigits commented 2026-06-03 13:39:33 +00:00 (Migrated from gitlab.com)

mentioned in merge request !415

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

mentioned in issue #299

mentioned in issue #299
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#255
No description provided.