feat(timecurve-arena): WarBow revenge hero card BP preview + live countdown (GitLab #236) #394

Merged
Brouie merged 1 commit from feat/236-revenge-hero-refactor into main 2026-05-22 05:21:37 +00:00
Brouie commented 2026-05-22 04:53:53 +00:00 (Migrated from gitlab.com)

Closes #236.

Revenge hero card on /timecurve/arena (WarbowHeroActions) gets a refactor so each open counter-hit row shows what's actually useful at a glance: stealer BP, expected BP gained on revenge, and a live Valid To: HH:MM:SS countdown. Removes the redundant You have N open counter-hits. Earliest expiry … summary paragraph and drops the per-row UTC UnixTimestampDisplay.

Helper

  • New frontend/src/lib/warbowRevengeRowPreview.ts mirrors onchain _warbowStealDrainBp(stealerBp, WARBOW_STEAL_DRAIN_BPS=1000) with BigInt floor semantics — 10% drain, returns 0 for non-positive input.
  • Pure, no React.
  • 7 Vitest cases: constants, non-positive, sub-10 floor threshold, smallest non-zero drain at stealerBp=10, arbitrary inputs vs solidity floor, large BPs via BigInt, regression guard against stealerBp/10n cross-check.

Model (useTimeCurveArenaModel.tsx)

  • Batched useReadContracts on battlePoints(stealer) keyed off pendingRevengeTargets (sorted, expiry-filtered).
  • Stable contracts array via useMemo with explicit deps so the call doesn't churn on every render — same pattern as steal-discovery batching the issue body called out.
  • Exposes stealerBpByAddress as a ReadonlyMap<string, bigint | undefined> from lowercased stealer to live BP; undefined = pending or failed row.

Component (WarbowHeroActions.tsx)

  • Revenge block rewrite.
  • Each row renders Target: {humanBp} BP · Gain: +{drainBp} BP when stealerBp is loaded; muted Loading BP… while the multicall is in flight; Revenge zero (no BP to drain) when drain math floors to 0 instead of a misleading +0 BP.
  • Valid To countdown uses ledgerNowSec (same interpolated chain now as guard / phase / claim-flag via parent's effectiveLedgerSec); clamps to 00:00:00 once a row slips past expiry_exclusive (the 8s indexer poll then drops the row).
  • Old summary paragraph, UnixTimestampDisplay import, and revengeDeadlineSec prop all removed as dead code.

Tests

  • 7 new Vitest cases in WarbowHeroActions.test.tsx cover acceptance criteria: no summary paragraph, BP fields render, loading hint, revenge-zero hint, countdown reflects ledgerNowSec (two static renders at different times asserted to differ), 00:00:00 clamp past expiry, no UTC UnixTimestampDisplay leakage.
  • Helper tests run independently (7 cases).
  • Full frontend suite: 586/586 passing across 99 files.
  • tsc -b silent.
  • Production build: 14.94s clean.

Docs

  • timecurve-views.md Arena WarBow hero section bullet 3 extended with the new per-row contract.
  • New invariant INV-FRONTEND-236-REVENGE-HERO added to invariants-and-business-logic.md right after the #101 hero-actions row.

Acceptance criteria

  • No 'You have N open counter-hit' / 'Earliest expiry' summary line.
  • Each list row shows stealer address, Target BP (humanized), Gain (humanized preview), and Valid To: HH:MM:SS counting down every second until expiry.
  • Countdown uses Arena ledger/interpolated now (not Date.now() alone).
  • UTC UnixTimestampDisplay removed from hero revenge rows.
  • Vitest coverage for: no summary paragraph; row copy includes BP fields + Valid To:; countdown string changes when ledgerNowSec advances.
  • Manual QA on /timecurve/arena with VITE_INDEXER_URL and a wallet holding multiple open stealers (left for reviewer / next live sale).
Closes #236. Revenge hero card on `/timecurve/arena` (`WarbowHeroActions`) gets a refactor so each open counter-hit row shows what's actually useful at a glance: stealer BP, expected BP gained on revenge, and a live `Valid To: HH:MM:SS` countdown. Removes the redundant `You have N open counter-hits. Earliest expiry …` summary paragraph and drops the per-row UTC `UnixTimestampDisplay`. ## Helper - New `frontend/src/lib/warbowRevengeRowPreview.ts` mirrors onchain `_warbowStealDrainBp(stealerBp, WARBOW_STEAL_DRAIN_BPS=1000)` with BigInt floor semantics — 10% drain, returns 0 for non-positive input. - Pure, no React. - 7 Vitest cases: constants, non-positive, sub-10 floor threshold, smallest non-zero drain at `stealerBp=10`, arbitrary inputs vs solidity floor, large BPs via BigInt, regression guard against `stealerBp/10n` cross-check. ## Model (`useTimeCurveArenaModel.tsx`) - Batched `useReadContracts` on `battlePoints(stealer)` keyed off `pendingRevengeTargets` (sorted, expiry-filtered). - Stable contracts array via `useMemo` with explicit deps so the call doesn't churn on every render — same pattern as steal-discovery batching the issue body called out. - Exposes `stealerBpByAddress` as a `ReadonlyMap<string, bigint | undefined>` from lowercased stealer to live BP; `undefined` = pending or failed row. ## Component (`WarbowHeroActions.tsx`) - Revenge block rewrite. - Each row renders `Target: {humanBp} BP · Gain: +{drainBp} BP` when `stealerBp` is loaded; muted `Loading BP…` while the multicall is in flight; `Revenge zero (no BP to drain)` when drain math floors to 0 instead of a misleading `+0 BP`. - `Valid To` countdown uses `ledgerNowSec` (same interpolated chain now as guard / phase / claim-flag via parent's `effectiveLedgerSec`); clamps to `00:00:00` once a row slips past `expiry_exclusive` (the 8s indexer poll then drops the row). - Old summary paragraph, `UnixTimestampDisplay` import, and `revengeDeadlineSec` prop all removed as dead code. ## Tests - 7 new Vitest cases in `WarbowHeroActions.test.tsx` cover acceptance criteria: no summary paragraph, BP fields render, loading hint, revenge-zero hint, countdown reflects `ledgerNowSec` (two static renders at different times asserted to differ), `00:00:00` clamp past expiry, no UTC `UnixTimestampDisplay` leakage. - Helper tests run independently (7 cases). - Full frontend suite: **586/586 passing** across 99 files. - `tsc -b` silent. - Production build: 14.94s clean. ## Docs - `timecurve-views.md` Arena WarBow hero section bullet 3 extended with the new per-row contract. - New invariant `INV-FRONTEND-236-REVENGE-HERO` added to `invariants-and-business-logic.md` right after the #101 hero-actions row. ## Acceptance criteria - [x] No 'You have N open counter-hit' / 'Earliest expiry' summary line. - [x] Each list row shows stealer address, Target BP (humanized), Gain (humanized preview), and `Valid To: HH:MM:SS` counting down every second until expiry. - [x] Countdown uses Arena ledger/interpolated now (not `Date.now()` alone). - [x] UTC `UnixTimestampDisplay` removed from hero revenge rows. - [x] Vitest coverage for: no summary paragraph; row copy includes BP fields + `Valid To:`; countdown string changes when `ledgerNowSec` advances. - [ ] Manual QA on `/timecurve/arena` with `VITE_INDEXER_URL` and a wallet holding multiple open stealers (left for reviewer / next live sale).
Brouie commented 2026-05-22 04:57:29 +00:00 (Migrated from gitlab.com)

mentioned in issue #236

mentioned in issue #236
PlasticDigits (Migrated from gitlab.com) merged commit d348a7e38b into main 2026-05-22 05:21:37 +00:00
PlasticDigits commented 2026-05-22 05:22:02 +00:00 (Migrated from gitlab.com)

mentioned in commit d348a7e38b

mentioned in commit d348a7e38b48ffe9f04642244d7a8134c7b49583
Sign in to join this conversation.
No reviewers
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!394
No description provided.