Fix post-buy effect toast visibility on Arena play route (#337) #513

Merged
PlasticDigits merged 2 commits from issue-337-post-buy-effect-toast-visibility into main 2026-06-19 10:44:29 +00:00
PlasticDigits commented 2026-06-19 08:50:21 +00:00 (Migrated from gitlab.com)

Summary

Fixes post-buy effect toast visibility on the Arena play route (#337). Prior implementation rendered toasts at the bottom of the full command-console document (often below the fold) and delayed display up to 2.5s waiting for indexer head.

This MR:

  • Portals ArenaEffectToastStack to document.body with fixed viewport glass styling (z-index: 110, safe-area insets).
  • Shows preview effect lines immediately on successful buy; upgrades copy when the viewer's buy reaches indexer head.
  • Adds E2E cooldown warp helper and a Playwright screenshot capture script for QA evidence.

Acceptance criteria

Criterion Verification Result
Successful CHARM buy on / emits one toast per effect ANVIL_E2E=1 E2E_REUSE_PREVIEW=1 npm run test:e2e -- e2e/anvil-arena-03-wallet-writes.spec.ts PASS
Toasts auto-dismiss without user action ArenaEffectToastStack.test.tsx + ARENA_BUY_EFFECT_TOAST_DISMISS_MS=4000 PASS
No layout shift; overlay on mobile Fixed position: fixed overlay; screenshots below PASS
Glass styling + screenshots (desktop/tablet/mobile) node scripts/capture-buy-effect-toast-screenshots.mjs PASS
typecheck && lint && npm test cd frontend && npm run typecheck && npm run lint && npm test PASS

Screenshots (desktop / tablet / mobile)

issue-337-toast-desktop

issue-337-toast-tablet

issue-337-toast-mobile

Third-party verification

  1. bash scripts/start-qa-local-full-stack.sh --live-sale --no-swarm (or reuse running stack).
  2. cd frontend && npm run dev → open http://127.0.0.1:5173/.
  3. Connect mock/Rabby wallet on Anvil 31337; submit minimum DOUB buy.
  4. Confirm glass toasts appear bottom-right in viewport (data-testid="arena-buy-effect-toast") with timer/XP/Last Buyer copy.
  5. cd frontend && npm run typecheck && npm run lint && npm test.
  6. Optional E2E: ANVIL_E2E=1 bash scripts/e2e-anvil.sh or build preview + ANVIL_E2E=1 E2E_REUSE_PREVIEW=1 npm run test:e2e -- e2e/anvil-arena-03-wallet-writes.spec.ts.

Docs: arena-views §337 · INV-FRONTEND-337-BUY-EFFECT-TOASTS.

## Summary Fixes post-buy effect toast visibility on the Arena play route ([#337](https://gitlab.com/PlasticDigits/yieldomega/-/issues/337)). Prior implementation rendered toasts at the bottom of the full command-console document (often below the fold) and delayed display up to 2.5s waiting for indexer head. This MR: - Portals `ArenaEffectToastStack` to `document.body` with **fixed viewport** glass styling (`z-index: 110`, safe-area insets). - Shows **preview effect lines immediately** on successful buy; upgrades copy when the viewer's buy reaches indexer head. - Adds E2E cooldown warp helper and a Playwright screenshot capture script for QA evidence. ## Acceptance criteria | Criterion | Verification | Result | |-----------|--------------|--------| | Successful CHARM buy on `/` emits one toast per effect | `ANVIL_E2E=1 E2E_REUSE_PREVIEW=1 npm run test:e2e -- e2e/anvil-arena-03-wallet-writes.spec.ts` | PASS | | Toasts auto-dismiss without user action | `ArenaEffectToastStack.test.tsx` + `ARENA_BUY_EFFECT_TOAST_DISMISS_MS=4000` | PASS | | No layout shift; overlay on mobile | Fixed `position: fixed` overlay; screenshots below | PASS | | Glass styling + screenshots (desktop/tablet/mobile) | `node scripts/capture-buy-effect-toast-screenshots.mjs` | PASS | | `typecheck && lint && npm test` | `cd frontend && npm run typecheck && npm run lint && npm test` | PASS | ### Screenshots (desktop / tablet / mobile) ![issue-337-toast-desktop](/uploads/2488a9510869d91026470e2ee0672d8a/issue-337-toast-desktop.png) ![issue-337-toast-tablet](/uploads/69021805dc27b120fba0ca48a4884d38/issue-337-toast-tablet.png) ![issue-337-toast-mobile](/uploads/6b9949820f58b923a4c4febbb33778cd/issue-337-toast-mobile.png) ## Third-party verification 1. `bash scripts/start-qa-local-full-stack.sh --live-sale --no-swarm` (or reuse running stack). 2. `cd frontend && npm run dev` → open `http://127.0.0.1:5173/`. 3. Connect mock/Rabby wallet on Anvil **31337**; submit minimum DOUB buy. 4. Confirm glass toasts appear bottom-right in viewport (`data-testid="arena-buy-effect-toast"`) with timer/XP/Last Buyer copy. 5. `cd frontend && npm run typecheck && npm run lint && npm test`. 6. Optional E2E: `ANVIL_E2E=1 bash scripts/e2e-anvil.sh` or build preview + `ANVIL_E2E=1 E2E_REUSE_PREVIEW=1 npm run test:e2e -- e2e/anvil-arena-03-wallet-writes.spec.ts`. Docs: [arena-views §337](docs/frontend/arena-views.md#post-buy-effect-toasts-gitlab-337) · `INV-FRONTEND-337-BUY-EFFECT-TOASTS`.
PlasticDigits commented 2026-06-19 08:53:23 +00:00 (Migrated from gitlab.com)

Security review

Commit reviewed: 5448ee6f2d81a6096be2b5817de6255fb57a7a8d
Scope: MR !513 — post-buy effect toast visibility (#337): React portal overlay, immediate preview-to-indexer toast upgrade, E2E Anvil cooldown warp helper, QA screenshot script, docs/invariant updates.

Outcome: FINDINGS: 0 medium+

Summary

Reviewed added/modified application code and traced attacker-controlled input to sinks. No exploitable authn/authz bypass, injection, SSRF, XSS, secret leakage, or EVM/on-chain risk introduced by this diff.

Area Assessment
Toast rendering Effect copy is rendered as React text ({toast.line}); no dangerouslySetInnerHTML. Lines are built from formatted numeric/game-state helpers (buildArenaBuyProjectedEffectLines / buildArenaBuyActualEffectLines), not raw indexer strings.
Portal / overlay createPortal(..., document.body) with pointer-events: none on the stack — UI positioning only; no click interception.
Preview vs indexer upgrade Behavioral change shows checkout preview immediately, then swaps batch when head buy indexes. Race on rapid serial buys could mis-associate preview/actual copy for the same wallet (UX integrity); not a cross-user or privilege-boundary issue.
E2E warpAnvilPastBuyCooldown fetch to VITE_RPC_URL (default 127.0.0.1:8545) with fixed Anvil JSON-RPC methods — test/CI helper only; env-controlled endpoint, not production attack surface.
QA screenshot script Playwright against BUY_TOAST_SCREENSHOT_BASE_URL (default localhost) — local dev artifact; out of production deployment path.

Prior security-review threads: none on this MR.

Inline findings: none (no medium+ issues to thread on the diff).

## Security review **Commit reviewed:** `5448ee6f2d81a6096be2b5817de6255fb57a7a8d` **Scope:** MR !513 — post-buy effect toast visibility (#337): React portal overlay, immediate preview-to-indexer toast upgrade, E2E Anvil cooldown warp helper, QA screenshot script, docs/invariant updates. **Outcome:** `FINDINGS: 0` medium+ ### Summary Reviewed added/modified application code and traced attacker-controlled input to sinks. No exploitable authn/authz bypass, injection, SSRF, XSS, secret leakage, or EVM/on-chain risk introduced by this diff. | Area | Assessment | |------|------------| | **Toast rendering** | Effect copy is rendered as React text (`{toast.line}`); no `dangerouslySetInnerHTML`. Lines are built from formatted numeric/game-state helpers (`buildArenaBuyProjectedEffectLines` / `buildArenaBuyActualEffectLines`), not raw indexer strings. | | **Portal / overlay** | `createPortal(..., document.body)` with `pointer-events: none` on the stack — UI positioning only; no click interception. | | **Preview vs indexer upgrade** | Behavioral change shows checkout preview immediately, then swaps batch when head buy indexes. Race on rapid serial buys could mis-associate preview/actual copy for the same wallet (UX integrity); not a cross-user or privilege-boundary issue. | | **E2E `warpAnvilPastBuyCooldown`** | `fetch` to `VITE_RPC_URL` (default `127.0.0.1:8545`) with fixed Anvil JSON-RPC methods — test/CI helper only; env-controlled endpoint, not production attack surface. | | **QA screenshot script** | Playwright against `BUY_TOAST_SCREENSHOT_BASE_URL` (default localhost) — local dev artifact; out of production deployment path. | **Prior security-review threads:** none on this MR. **Inline findings:** none (no medium+ issues to thread on the diff).
PlasticDigits commented 2026-06-19 10:11:40 +00:00 (Migrated from gitlab.com)

Looks good on tablet and desktop.
FIX: On mobile, the toast icons are sometimes behind the mobile bottom nav. Instead, the bottom of the toast icons should be higher up the page, with a small gap above the mobile nav.

Looks good on tablet and desktop. FIX: On mobile, the toast icons are sometimes behind the mobile bottom nav. Instead, the bottom of the toast icons should be higher up the page, with a small gap above the mobile nav.
PlasticDigits commented 2026-06-19 10:16:29 +00:00 (Migrated from gitlab.com)

added 1 commit

  • c7680a85 - fix(frontend): clear mobile buy-effect toasts above bottom nav

Compare with previous version

added 1 commit <ul><li>c7680a85 - fix(frontend): clear mobile buy-effect toasts above bottom nav</li></ul> [Compare with previous version](/PlasticDigits/yieldomega/-/merge_requests/143/diffs?diff_id=1860864228&start_sha=5448ee6f2d81a6096be2b5817de6255fb57a7a8d)
PlasticDigits commented 2026-06-19 10:16:45 +00:00 (Migrated from gitlab.com)

Fix bugfix follow-up

Review item Fix
Mobile toasts behind bottom nav Raised .arena-effect-toast-stack on ≤720px to bottom: calc(max(0.4rem, env(safe-area-inset-bottom, 0px)) + 3.95rem + 0.35rem) — same header clearance as the album dock plus a small gap above the fixed .app-header bar. Commit c7680a85.
Regression guard Added mobileBuyEffectToastLayout.test.ts asserting mobile bottom offset parity with MOBILE_ALBUM_DOCK_CLEARANCE_ABOVE_HEADER_REM.

Tests: npm run typecheck && npm run lint && npm test -- --run src/pages/arena/mobileBuyEffectToastLayout.test.ts src/pages/arena/ArenaEffectToastStack.test.tsx — PASS.

Thread resolution: glab mr note resolve 143 420d3ca0e67ad9304bcd3e0e8db8d9c35b0da90b returned 403 with GITLAB_TOKEN (PlasticDigits) — please resolve note 3472886050 manually if still open.

Removed agent:fix_bugfix label.

## Fix bugfix follow-up | Review item | Fix | |-------------|-----| | **Mobile toasts behind bottom nav** | Raised `.arena-effect-toast-stack` on `≤720px` to `bottom: calc(max(0.4rem, env(safe-area-inset-bottom, 0px)) + 3.95rem + 0.35rem)` — same header clearance as the album dock plus a small gap above the fixed `.app-header` bar. Commit `c7680a85`. | | **Regression guard** | Added `mobileBuyEffectToastLayout.test.ts` asserting mobile bottom offset parity with `MOBILE_ALBUM_DOCK_CLEARANCE_ABOVE_HEADER_REM`. | **Tests:** `npm run typecheck && npm run lint && npm test -- --run src/pages/arena/mobileBuyEffectToastLayout.test.ts src/pages/arena/ArenaEffectToastStack.test.tsx` — PASS. **Thread resolution:** `glab mr note resolve 143 420d3ca0e67ad9304bcd3e0e8db8d9c35b0da90b` returned 403 with `GITLAB_TOKEN` (PlasticDigits) — please resolve note `3472886050` manually if still open. Removed `agent:fix_bugfix` label.
PlasticDigits commented 2026-06-19 10:19:24 +00:00 (Migrated from gitlab.com)

Security review

Commit reviewed: c7680a851f2f67fa5a89e015493fbc4fdc6058c3
Scope: MR !513 — post-buy effect toast visibility (#337): React portal + fixed viewport overlay, immediate preview with indexer batch upgrade, mobile bottom-nav clearance (c7680a85), E2E Anvil cooldown warp helper, QA screenshot script, docs/invariant updates.

Outcome: FINDINGS: 0 medium+

Summary

Re-reviewed the full MR diff (including mobile layout follow-up) and traced attacker-controlled input to sinks. No exploitable authn/authz bypass, injection, SSRF, XSS, secret leakage, or EVM/on-chain risk introduced by this diff.

Area Assessment
Toast rendering Effect copy is rendered as React text ({toast.line}); no dangerouslySetInnerHTML. Lines come from buildArenaBuyProjectedEffectLines / buildArenaBuyActualEffectLines (formatted numerics + fixed labels), not raw indexer strings. toastToneClass maps to a fixed CSS class allowlist.
Portal / overlay createPortal(..., document.body) with pointer-events: none on the stack — viewport positioning only; no click interception or auth surface.
Preview → indexer upgrade replaceArenaBuyEffectToastBatch swaps client-generated batchId prefixes when findViewerBuyAtHead confirms the connected wallet owns head buy. Rapid serial buys can mis-associate preview/actual copy for the same wallet (UX integrity); not cross-user or privilege-boundary.
Mobile offset (c7680a85) CSS bottom calc + layout regression test only; no new input handling.
E2E warpAnvilPastBuyCooldown fetch to VITE_RPC_URL (default 127.0.0.1:8545) with fixed Anvil JSON-RPC methods — test/CI helper; env-controlled endpoint, not production user attack surface.
QA screenshot script Playwright against BUY_TOAST_SCREENSHOT_BASE_URL (default localhost) — local dev artifact; out of production deployment path.

Prior security-review comment: 5448ee6f thread (note 3472629162) — findings unchanged; mobile follow-up adds no new medium+ surface.

Inline findings: none (no medium+ issues to thread on the diff).

Security review: no medium+ findings on this diff.

## Security review **Commit reviewed:** `c7680a851f2f67fa5a89e015493fbc4fdc6058c3` **Scope:** MR !513 — post-buy effect toast visibility (#337): React portal + fixed viewport overlay, immediate preview with indexer batch upgrade, mobile bottom-nav clearance (`c7680a85`), E2E Anvil cooldown warp helper, QA screenshot script, docs/invariant updates. **Outcome:** `FINDINGS: 0` medium+ ### Summary Re-reviewed the full MR diff (including mobile layout follow-up) and traced attacker-controlled input to sinks. No exploitable authn/authz bypass, injection, SSRF, XSS, secret leakage, or EVM/on-chain risk introduced by this diff. | Area | Assessment | |------|------------| | **Toast rendering** | Effect copy is rendered as React text (`{toast.line}`); no `dangerouslySetInnerHTML`. Lines come from `buildArenaBuyProjectedEffectLines` / `buildArenaBuyActualEffectLines` (formatted numerics + fixed labels), not raw indexer strings. `toastToneClass` maps to a fixed CSS class allowlist. | | **Portal / overlay** | `createPortal(..., document.body)` with `pointer-events: none` on the stack — viewport positioning only; no click interception or auth surface. | | **Preview → indexer upgrade** | `replaceArenaBuyEffectToastBatch` swaps client-generated `batchId` prefixes when `findViewerBuyAtHead` confirms the connected wallet owns head buy. Rapid serial buys can mis-associate preview/actual copy for the same wallet (UX integrity); not cross-user or privilege-boundary. | | **Mobile offset (`c7680a85`)** | CSS `bottom` calc + layout regression test only; no new input handling. | | **E2E `warpAnvilPastBuyCooldown`** | `fetch` to `VITE_RPC_URL` (default `127.0.0.1:8545`) with fixed Anvil JSON-RPC methods — test/CI helper; env-controlled endpoint, not production user attack surface. | | **QA screenshot script** | Playwright against `BUY_TOAST_SCREENSHOT_BASE_URL` (default localhost) — local dev artifact; out of production deployment path. | **Prior security-review comment:** `5448ee6f` thread (note `3472629162`) — findings unchanged; mobile follow-up adds no new medium+ surface. **Inline findings:** none (no medium+ issues to thread on the diff). Security review: no medium+ findings on this diff.
PlasticDigits (Migrated from gitlab.com) merged commit e9af3f8902 into main 2026-06-19 10:44:29 +00:00
PlasticDigits commented 2026-06-19 10:44:30 +00:00 (Migrated from gitlab.com)

mentioned in commit e9af3f8902

mentioned in commit e9af3f890236dbb2acafc460c24cb241db488d22
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!513
No description provided.