Arena: Claim WarBow flag CTA with silence countdown (visible only when user holds pending flag) #218

Closed
opened 2026-05-19 08:06:27 +00:00 by PlasticDigits · 8 comments
PlasticDigits commented 2026-05-19 08:06:27 +00:00 (Migrated from gitlab.com)

Summary

Users can plant a WarBow pending flag from /timecurve (Simple buy → ADVANCED → “Plant WarBow flag”), but the shipped UI does not expose a wallet path to claimWarBowFlag() after the silence window. Arena already implements runWarBowClaimFlag, canClaimWarBowFlag, and gas estimation in useTimeCurveArenaModel, and WarbowSection has a Claim flag button — but WarbowSection is not mounted on /timecurve/arena (hero-only WarbowHeroActions after #101).

Add a Claim flag control with a live hh:mm:ss countdown while silence is active, enabled only when the viewer may claim onchain.

UX requirements

  1. Visibility: Show the control only when the connected wallet is the onchain pending flag holder (warbowPendingFlagOwner === viewer, warbowPendingFlagPlantAt > 0). Hide entirely when the viewer does not hold a planted flag.

  2. Primary control: Button label Claim flag.

  3. Disabled by default during silence: While ledgerNow < plantAt + WARBOW_FLAG_SILENCE_SEC, the button stays disabled.

  4. Countdown on the control: While disabled, show remaining silence as Claim flag hh:mm:ss (or equivalent: label + monospace countdown on the same CTA). Countdown must use the same ledger “now” basis as phase / WarBow eligibility (indexer hero timer when available — see ledgerSecIntForPhase / effectiveLedgerSec in Arena), not wall clock alone.

  5. Enabled after silence: When canClaimWarBowFlag is true (sale live + holder + silence elapsed), enable the button and allow submit → existing runWarBowClaimFlag() → TimeCurve.claimWarBowFlag().

  6. Helper copy (below the button): Always show when the block is visible (values from onchain constants; format with formatLocaleInteger):

    • +1000 BP if you claim after the silence window with no other buyer in between (WARBOW_FLAG_CLAIM_BP)
    • −2000 BP if another wallet buys after silence ends but before you claim (2 × WARBOW_FLAG_CLAIM_BP penalty via WarBowFlagPenalized)

    Optional nuance (muted secondary line or tooltip): if another buyer purchases before silence ends, the pending slot is cleared without the 2× penalty — holder only loses the claim opportunity.

  7. Write barriers: Reuse existing Arena patterns: wrong-network ChainMismatchWriteBarrier, buyFeeRoutingEnabled preflight (note: claimWarBowFlag has no CL8Y leg but sale-live gates still apply onchain), pvpErr for reverts.

Suggested placement

  • /timecurve/arena: Extend WarbowHeroActions (or a small sibling card in the hero grid) so claim is discoverable next to Steal / Guard / Revenge — do not rely on remounting the full orphaned WarbowSection unless product wants the entire detailed section back.
  • Optional follow-up: Mirror a compact claim block on /timecurve Simple when the session reads show the viewer holds the pending flag (planted from Simple) — out of scope unless cheap to share one component.

Onchain reference (authoritative)

From TimeCurve.sol / docs/product/primitives.md:

Constant Value
WARBOW_FLAG_CLAIM_BP 1000
WARBOW_FLAG_SILENCE_SEC 300 (5 minutes)
Outcome BP effect
Successful claimWarBowFlag after silence, no interrupting buy +1000 (WarBowFlagClaimed)
Another buyer after silence (plantAt + 300s) before claim Holder −2000 (2 × WARBOW_FLAG_CLAIM_BP, WarBowFlagPenalized)
Another buyer before silence ends Pending slot cleared; no 2× penalty

Align with existing plant checkbox copy in warbowFlagPlantMutedLine.

Existing code to reuse

  • Eligibility: canClaimWarBowFlag, iHoldPlantFlag, flagSilenceEndSec in useTimeCurveArenaModel.tsx
  • Submit: runWarBowClaimFlag() (already calls claimWarBowFlag + refetchAll)
  • Reads: warbowPendingFlagOwner, warbowPendingFlagPlantAt, WARBOW_FLAG_SILENCE_SEC, WARBOW_FLAG_CLAIM_BP
  • Countdown formatting: consider formatCountdown (used for guard timer in hero)

Acceptance criteria

  • Connected wallet that does not hold warbowPendingFlagOwner sees no Claim flag block on Arena.
  • Holder during silence sees disabled CTA with hh:mm:ss counting down to silence end; countdown ticks without requiring a manual refresh (poll/refetch or interpolated ledger sec).
  • Holder after silence with sale still live sees enabled CTA; click submits claimWarBowFlag and refreshes BP / flag reads on receipt.
  • Helper lines +1000 BP … / −2000 BP … render below the CTA whenever the block is visible (matching onchain constants).
  • Wrong chain / paused sale interactions: button disabled or blocked with existing barrier copy; no silent no-op.
  • Vitest and/or Playwright coverage for visibility gating + disabled/enabled states (mock reads or Anvil fixture).

Verification checklist

  • Plant flag via Simple buy (ADVANCED checkbox) → open Arena as that wallet → claim block appears with ~5:00 countdown.
  • Wait silence (or advance chain time in Anvil) → CTA enables → claim succeeds (+1000 BP) → block hides or updates; rivalry feed reflects Flag won.
  • Second wallet buys after silence before claim → holder penalized (−2000 BP) / flag cleared; no successful claim.
## Summary Users can **plant** a WarBow pending flag from `/timecurve` (Simple buy → ADVANCED → “Plant WarBow flag”), but the shipped UI does **not** expose a wallet path to **`claimWarBowFlag()`** after the silence window. Arena already implements `runWarBowClaimFlag`, `canClaimWarBowFlag`, and gas estimation in `useTimeCurveArenaModel`, and `WarbowSection` has a **Claim flag** button — but **`WarbowSection` is not mounted** on `/timecurve/arena` (hero-only `WarbowHeroActions` after #101). Add a **Claim flag** control with a live **hh:mm:ss** countdown while silence is active, enabled only when the viewer may claim onchain. ## UX requirements 1. **Visibility:** Show the control **only** when the connected wallet is the onchain pending flag holder (`warbowPendingFlagOwner` === viewer, `warbowPendingFlagPlantAt > 0`). Hide entirely when the viewer does not hold a planted flag. 2. **Primary control:** Button label **Claim flag**. 3. **Disabled by default during silence:** While `ledgerNow < plantAt + WARBOW_FLAG_SILENCE_SEC`, the button stays **disabled**. 4. **Countdown on the control:** While disabled, show remaining silence as **`Claim flag hh:mm:ss`** (or equivalent: label + monospace countdown on the same CTA). Countdown must use the same **ledger “now”** basis as phase / WarBow eligibility (indexer hero timer when available — see `ledgerSecIntForPhase` / `effectiveLedgerSec` in Arena), **not** wall clock alone. 5. **Enabled after silence:** When `canClaimWarBowFlag` is true (sale live + holder + silence elapsed), enable the button and allow submit → existing `runWarBowClaimFlag()` → `TimeCurve.claimWarBowFlag()`. 6. **Helper copy (below the button):** Always show when the block is visible (values from onchain constants; format with `formatLocaleInteger`): - **+1000 BP** if you claim after the silence window with no other buyer in between (`WARBOW_FLAG_CLAIM_BP`) - **−2000 BP** if another wallet buys after silence ends but before you claim (`2 × WARBOW_FLAG_CLAIM_BP` penalty via `WarBowFlagPenalized`) Optional nuance (muted secondary line or tooltip): if another buyer purchases **before** silence ends, the pending slot is cleared **without** the 2× penalty — holder only loses the claim opportunity. 7. **Write barriers:** Reuse existing Arena patterns: wrong-network `ChainMismatchWriteBarrier`, `buyFeeRoutingEnabled` preflight (note: `claimWarBowFlag` has **no CL8Y leg** but sale-live gates still apply onchain), `pvpErr` for reverts. ## Suggested placement - **`/timecurve/arena`:** Extend [`WarbowHeroActions`](frontend/src/pages/timeCurveArena/WarbowHeroActions.tsx) (or a small sibling card in the hero grid) so claim is discoverable next to Steal / Guard / Revenge — do **not** rely on remounting the full orphaned [`WarbowSection`](frontend/src/pages/timecurve/TimeCurveSections.tsx) unless product wants the entire detailed section back. - **Optional follow-up:** Mirror a compact claim block on `/timecurve` Simple when the session reads show the viewer holds the pending flag (planted from Simple) — out of scope unless cheap to share one component. ## Onchain reference (authoritative) From [`TimeCurve.sol`](contracts/src/TimeCurve.sol) / [`docs/product/primitives.md`](docs/product/primitives.md): | Constant | Value | |----------|-------| | `WARBOW_FLAG_CLAIM_BP` | **1000** | | `WARBOW_FLAG_SILENCE_SEC` | **300** (5 minutes) | | Outcome | BP effect | |--------|-----------| | Successful `claimWarBowFlag` after silence, no interrupting buy | **+1000** (`WarBowFlagClaimed`) | | Another buyer **after** silence (`plantAt + 300s`) before claim | Holder **−2000** (`2 × WARBOW_FLAG_CLAIM_BP`, `WarBowFlagPenalized`) | | Another buyer **before** silence ends | Pending slot cleared; **no** 2× penalty | Align with existing plant checkbox copy in [`warbowFlagPlantMutedLine`](frontend/src/lib/warbowFlagPlantCopy.ts). ## Existing code to reuse - Eligibility: `canClaimWarBowFlag`, `iHoldPlantFlag`, `flagSilenceEndSec` in [`useTimeCurveArenaModel.tsx`](frontend/src/pages/timeCurveArena/useTimeCurveArenaModel.tsx) - Submit: `runWarBowClaimFlag()` (already calls `claimWarBowFlag` + `refetchAll`) - Reads: `warbowPendingFlagOwner`, `warbowPendingFlagPlantAt`, `WARBOW_FLAG_SILENCE_SEC`, `WARBOW_FLAG_CLAIM_BP` - Countdown formatting: consider [`formatCountdown`](frontend/src/pages/timecurve/formatTimer.ts) (used for guard timer in hero) ## Acceptance criteria - [ ] Connected wallet that **does not** hold `warbowPendingFlagOwner` sees **no** Claim flag block on Arena. - [ ] Holder during silence sees **disabled** CTA with **hh:mm:ss** counting down to silence end; countdown ticks without requiring a manual refresh (poll/refetch or interpolated ledger sec). - [ ] Holder after silence with sale still live sees **enabled** CTA; click submits `claimWarBowFlag` and refreshes BP / flag reads on receipt. - [ ] Helper lines **+1000 BP …** / **−2000 BP …** render below the CTA whenever the block is visible (matching onchain constants). - [ ] Wrong chain / paused sale interactions: button disabled or blocked with existing barrier copy; no silent no-op. - [ ] Vitest and/or Playwright coverage for visibility gating + disabled/enabled states (mock reads or Anvil fixture). ## Verification checklist - [ ] Plant flag via Simple buy (ADVANCED checkbox) → open Arena as that wallet → claim block appears with ~5:00 countdown. - [ ] Wait silence (or advance chain time in Anvil) → CTA enables → claim succeeds (+1000 BP) → block hides or updates; rivalry feed reflects **Flag won**. - [ ] Second wallet buys **after** silence before claim → holder penalized (−2000 BP) / flag cleared; no successful claim. ## Related - Docs gap: [`docs/frontend/timecurve-views.md`](docs/frontend/timecurve-views.md) still describes `WarbowSection` on Arena — update when this ships. - Plant opt-in: [#63](https://gitlab.com/PlasticDigits/yieldomega/-/issues/63) - Pending flag reads UX: [#51](https://gitlab.com/PlasticDigits/yieldomega/-/issues/51) - Hero WarBow surface: [#101](https://gitlab.com/PlasticDigits/yieldomega/-/issues/101)
PlasticDigits commented 2026-05-19 08:09:27 +00:00 (Migrated from gitlab.com)

changed the description

changed the description
PlasticDigits commented 2026-05-20 04:14:21 +00:00 (Migrated from gitlab.com)

Should be component thats only visible when flag planted and at bottom of buy card, And component should also be added to the arena page in the "your rank/your bp" card also at bottom of that card

Should be component thats only visible when flag planted and at bottom of buy card, And component should also be added to the arena page in the "your rank/your bp" card also at bottom of that card
PlasticDigits commented 2026-05-20 04:17:50 +00:00 (Migrated from gitlab.com)

mentioned in commit 724eea2f76

mentioned in commit 724eea2f765988b49761f0329d4c99d6d3b58f6a
PlasticDigits commented 2026-05-20 04:17:55 +00:00 (Migrated from gitlab.com)

Implementation summary (merged to main — 724eea2)

Shipped Claim flag on /timecurve/arena for wallets holding the global pending WarBow flag.

What changed

  • New WarbowClaimFlagHeroCard in the Arena hero grid (between Guard and Revenge), wired through existing useTimeCurveArenaModel eligibility (iHoldPlantFlag, canClaimWarBowFlag, runWarBowClaimFlag).
  • Visibility: card renders only when warbowPendingFlagOwner === connected wallet and warbowPendingFlagPlantAt > 0.
  • Silence UX: disabled CTA shows Claim flag HH:MM:SS using effectiveLedgerSec (same ledger basis as guard / phase); enables to plain Claim flag when silence elapses.
  • Helper copy: onchain WARBOW_FLAG_CLAIM_BP reward line, 2× penalty line, and muted early-interrupt note via warbowClaimFlagCopy.ts.
  • Write barriers: reuses hero ChainMismatchWriteBarrier + existing runWarBowClaimFlag preflight (buyFeeRoutingEnabled, wrong chain → pvpErr).
  • Docs / invariants: INV-FRONTEND-218-WARBOW-CLAIM-FLAG, timecurve-views §218, manual QA #218, guardrails + skills/play-timecurve-warbow cross-links.

Automated tests (passing)

  • warbowClaimFlagCopy.test.ts
  • WarbowClaimFlagHeroCard.test.tsx
  • WarbowHeroActions.test.tsx (visibility + enabled/disabled states)

Verification checklist

  • Plant flag via Simple buy (ADVANCED → Plant WarBow flag) as wallet A → open /timecurve/arena → data-testid="warbow-hero-claim-flag" appears with ~00:05:00 countdown; other wallets see no block.
  • Countdown ticks without manual refresh (ledger / hero timer poll).
  • After silence (wait or Anvil time advance): CTA enables → Claim flag tx succeeds (+1000 BP) → BP / flag reads refresh; rivalry feed shows Flag won.
  • Helper lines +1,000 BP … / −2,000 BP … + muted early-interrupt note visible while block is shown.
  • Wrong chain: hero chain barrier blocks write (no silent no-op).
  • Optional penalty path: wallet B buys after silence before A claims → A penalized (−2000 BP) / flag cleared.

@nullvector_ux — please verify on staging or local Anvil stack when you have a moment. Leaving this issue open until sign-off.

## Implementation summary (merged to `main` — `724eea2`) Shipped **Claim flag** on `/timecurve/arena` for wallets holding the global pending WarBow flag. ### What changed - New **`WarbowClaimFlagHeroCard`** in the Arena hero grid (between Guard and Revenge), wired through existing **`useTimeCurveArenaModel`** eligibility (`iHoldPlantFlag`, `canClaimWarBowFlag`, `runWarBowClaimFlag`). - **Visibility:** card renders only when `warbowPendingFlagOwner` === connected wallet and `warbowPendingFlagPlantAt > 0`. - **Silence UX:** disabled CTA shows **`Claim flag HH:MM:SS`** using **`effectiveLedgerSec`** (same ledger basis as guard / phase); enables to plain **Claim flag** when silence elapses. - **Helper copy:** onchain **`WARBOW_FLAG_CLAIM_BP`** reward line, **2×** penalty line, and muted early-interrupt note via **`warbowClaimFlagCopy.ts`**. - **Write barriers:** reuses hero **`ChainMismatchWriteBarrier`** + existing **`runWarBowClaimFlag`** preflight (`buyFeeRoutingEnabled`, wrong chain → `pvpErr`). - **Docs / invariants:** **`INV-FRONTEND-218-WARBOW-CLAIM-FLAG`**, [timecurve-views §218](docs/frontend/timecurve-views.md#arena-warbow-claim-flag-hero-gitlab-218), [manual QA #218](docs/testing/manual-qa-checklists.md#manual-qa-issue-218), guardrails + `skills/play-timecurve-warbow` cross-links. ### Automated tests (passing) - `warbowClaimFlagCopy.test.ts` - `WarbowClaimFlagHeroCard.test.tsx` - `WarbowHeroActions.test.tsx` (visibility + enabled/disabled states) ### Verification checklist - [ ] Plant flag via Simple buy (ADVANCED → Plant WarBow flag) as wallet **A** → open `/timecurve/arena` → **`data-testid="warbow-hero-claim-flag"`** appears with ~**00:05:00** countdown; other wallets see **no** block. - [ ] Countdown ticks without manual refresh (ledger / hero timer poll). - [ ] After silence (wait or Anvil time advance): CTA enables → **Claim flag** tx succeeds (+1000 BP) → BP / flag reads refresh; rivalry feed shows **Flag won**. - [ ] Helper lines **+1,000 BP …** / **−2,000 BP …** + muted early-interrupt note visible while block is shown. - [ ] Wrong chain: hero chain barrier blocks write (no silent no-op). - [ ] Optional penalty path: wallet **B** buys **after** silence before **A** claims → **A** penalized (−2000 BP) / flag cleared. @nullvector_ux — please verify on staging or local Anvil stack when you have a moment. Leaving this issue **open** until sign-off.
PlasticDigits commented 2026-05-20 07:11:02 +00:00 (Migrated from gitlab.com)

mentioned in commit 8fd08418ae

mentioned in commit 8fd08418aecbf243525e851d1afc2d3508abe519
nullvector_ux commented 2026-05-20 14:37:37 +00:00 (Migrated from gitlab.com)

Verification checklist @PlasticDigits

  • Plant flag via Simple buy (ADVANCED → Plant WarBow flag) as wallet A → open /timecurve/arena → data-testid="warbow-hero-claim-flag" appears with ~00:05:00 countdown; other wallets see no block.
  • Countdown ticks without manual refresh (ledger / hero timer poll).
  • After silence (wait or Anvil time advance): CTA enables → Claim flag tx succeeds (+1000 BP) → BP / flag reads refresh; rivalry feed shows Flag won.
  • Helper lines +1,000 BP … / −2,000 BP … + muted early-interrupt note visible while block is shown.
  • Wrong chain: hero chain barrier blocks write (no silent no-op).
  • (Cannot test because you do not have two wallets) Optional penalty path: wallet B buys after silence before A claims → A penalized (−2000 BP) / flag cleared.
### Verification checklist @PlasticDigits * [x] Plant flag via Simple buy (ADVANCED → Plant WarBow flag) as wallet **A** → open `/timecurve/arena` → **`data-testid="warbow-hero-claim-flag"`** appears with \~**00:05:00** countdown; other wallets see **no** block. * [x] Countdown ticks without manual refresh (ledger / hero timer poll). * [x] After silence (wait or Anvil time advance): CTA enables → **Claim flag** tx succeeds (+1000 BP) → BP / flag reads refresh; rivalry feed shows **Flag won**. * [x] Helper lines **+1,000 BP …** / **−2,000 BP …** + muted early-interrupt note visible while block is shown. * [x] Wrong chain: hero chain barrier blocks write (no silent no-op). * [ ] (Cannot test because you do not have two wallets) Optional penalty path: wallet **B** buys **after** silence before **A** claims → **A** penalized (−2000 BP) / flag cleared.
Brouie commented 2026-05-21 02:58:53 +00:00 (Migrated from gitlab.com)

Adding the optional penalty path (item 6) from earlier — walked it with two wallets.

Wallet A planted flag, waited past silence, wallet B bought during the post-silence window before A claimed. Confirmed:

  • A penalized −2000 BP per WarBowFlagPenalized event
  • Pending flag slot cleared
  • A's Claim flag block hid on Arena after the penalty resolved

Penalty path verified working. Full checklist now PASS from QA side.

Adding the optional penalty path (item 6) from earlier — walked it with two wallets. Wallet A planted flag, waited past silence, wallet B bought during the post-silence window before A claimed. Confirmed: * A penalized −2000 BP per `WarBowFlagPenalized` event * Pending flag slot cleared * A's Claim flag block hid on Arena after the penalty resolved Penalty path verified working. Full checklist now PASS from QA side.
PlasticDigits (Migrated from gitlab.com) closed this issue 2026-05-21 12:02:53 +00:00
PlasticDigits commented 2026-05-22 00:14:56 +00:00 (Migrated from gitlab.com)

mentioned in issue #236

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