Frontend: LP risk disclosure, swap precision display, and a11y axe coverage #366

Closed
opened 2026-06-12 05:05:52 +00:00 by PlasticDigits · 11 comments
PlasticDigits commented 2026-06-12 05:05:52 +00:00 (Migrated from gitlab.com)

Parent

Gap analysis follow-up from GitLab #361 — bundled retail UX items M6, M10, and H10 (a11y only; enforced coverage gate explicitly rejected).

Current codebase

Impermanent loss (M6)

  • frontend-dapp/src/pages/PoolPage.tsx — add/remove liquidity UI with fee display, outage banners, proportional deposit math; no IL / LP risk disclosure copy.

Swap precision display (M10)

  • Submit path is BigInt-safe via useSubmitAlignedSimQuote + rawAmountMath.ts (#356).
  • SwapPage.tsx still uses parseFloat for input gating, query enabled flags, and price-impact % (lines ~172, 384, 549, 762-766, 844-917, 1443-1591). Amounts above 2⁵³ can mis-display impact and gate validation.

Accessibility (H10)

  • Axe gate in frontend-dapp/e2e/a11y-critical-routes.spec.ts covers trade, charts, and wallet chrome only (#214).
  • Missing: /swap, /limits, /pool, /portfolio.

Why needed

Retail users need concise LP risk awareness, accurate large-amount UX on swap (display/gating), and consistent a11y CI coverage on primary trading surfaces before broader launch.

Constraints / guardrails

  • M6: Keep disclosure succinct (parent triage) — short inline warning + link to docs; no long legal essay.
  • M10: Do not regress BigInt-safe submit path; scope is validation gating + price-impact display.
  • H10: Critical/serious axe violations only (match existing assertNoCriticalA11yViolations); no enforced Vitest coverage thresholds (rejected).
  • E2E runs in e2e-smoke with VITE_PLAYWRIGHT_E2E=true; 5 workers per project config.

Relevant files

  • frontend-dapp/src/pages/PoolPage.tsx, PoolPage.test.tsx
  • frontend-dapp/src/pages/SwapPage.tsx, SwapPage.test.tsx
  • frontend-dapp/src/utils/rawAmountMath.ts, utils/decimalAmountInput.ts
  • frontend-dapp/e2e/a11y-critical-routes.spec.ts, e2e/helpers/a11y.ts
  • frontend-dapp/e2e/fixtures/dev-wallet.ts
  • docs/frontend.md
  1. IL disclosure: Add a compact callout on pool add-liquidity panel (“Impermanent loss risk — LP value can diverge from holding assets”) with link to docs/frontend.md or a short docs/liquidity-pools.md anchor.
  2. Swap precision: Replace parseFloat gating with tryParseBigInt / decimal string helpers for positive-amount checks; compute price-impact % from raw integer strings (spread ÷ total) without float conversion when sim returns integer strings.
  3. A11y: Extend a11y-critical-routes.spec.ts with smoke-stable waits for swap, limits, pool, portfolio (reuse outage-tolerant patterns from trade/charts specs).

Acceptance criteria

  • Pool page shows succinct IL / LP risk notice before first provide-liquidity action.
  • Swap price-impact and amount validation correct for raw amounts > 9007199254740991 (unit test with string fixtures).
  • Axe E2E passes on /swap, /limits, /pool, /portfolio (critical/serious = 0).
  • No new enforced Vitest coverage thresholds.

Test plan

Path Command / action
Frontend unit make test-frontend
Frontend lint make lint-frontend
A11y E2E cd frontend-dapp && npm run test:e2e -- e2e/a11y-critical-routes.spec.ts (smoke project)
Manual Chrome on /pool (IL copy), /swap with large integer paste, axe on four new routes

Attack / abuse test plan

  • IL copy must not promise guaranteed returns or omit that IL is directional risk.
  • Large-amount input must not coerce to scientific notation that bypasses validation.
  • A11y excludes chart canvas only where already excluded (do not hide real violations).

Verification criteria

  • make test-frontend and extended a11y spec green in CI smoke config.
  • Pool IL notice visible in PoolPage.test.tsx without requiring wallet connect.
## Parent Gap analysis follow-up from [GitLab #361](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/work_items/361) — bundled retail UX items **M6**, **M10**, and **H10** (a11y only; enforced coverage gate explicitly rejected). ## Current codebase ### Impermanent loss (M6) - `frontend-dapp/src/pages/PoolPage.tsx` — add/remove liquidity UI with fee display, outage banners, proportional deposit math; **no IL / LP risk disclosure** copy. ### Swap precision display (M10) - Submit path is BigInt-safe via `useSubmitAlignedSimQuote` + `rawAmountMath.ts` ([#356](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/work_items/356)). - `SwapPage.tsx` still uses `parseFloat` for input gating, query `enabled` flags, and **price-impact %** (`lines ~172, 384, 549, 762-766, 844-917, 1443-1591`). Amounts above 2⁵³ can mis-display impact and gate validation. ### Accessibility (H10) - Axe gate in `frontend-dapp/e2e/a11y-critical-routes.spec.ts` covers **trade**, **charts**, and **wallet chrome** only ([#214](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/issues/214)). - Missing: `/swap`, `/limits`, `/pool`, `/portfolio`. ## Why needed Retail users need concise LP risk awareness, accurate large-amount UX on swap (display/gating), and consistent a11y CI coverage on primary trading surfaces before broader launch. ## Constraints / guardrails - **M6**: Keep disclosure **succinct** (parent triage) — short inline warning + link to docs; no long legal essay. - **M10**: Do not regress BigInt-safe **submit** path; scope is validation gating + price-impact display. - **H10**: Critical/serious axe violations only (match existing `assertNoCriticalA11yViolations`); no enforced Vitest coverage thresholds (rejected). - E2E runs in `e2e-smoke` with `VITE_PLAYWRIGHT_E2E=true`; 5 workers per project config. ## Relevant files - `frontend-dapp/src/pages/PoolPage.tsx`, `PoolPage.test.tsx` - `frontend-dapp/src/pages/SwapPage.tsx`, `SwapPage.test.tsx` - `frontend-dapp/src/utils/rawAmountMath.ts`, `utils/decimalAmountInput.ts` - `frontend-dapp/e2e/a11y-critical-routes.spec.ts`, `e2e/helpers/a11y.ts` - `frontend-dapp/e2e/fixtures/dev-wallet.ts` - `docs/frontend.md` ## Recommended direction 1. **IL disclosure**: Add a compact callout on pool add-liquidity panel (“Impermanent loss risk — LP value can diverge from holding assets”) with link to `docs/frontend.md` or a short `docs/liquidity-pools.md` anchor. 2. **Swap precision**: Replace `parseFloat` gating with `tryParseBigInt` / decimal string helpers for positive-amount checks; compute price-impact % from raw integer strings (spread ÷ total) without float conversion when sim returns integer strings. 3. **A11y**: Extend `a11y-critical-routes.spec.ts` with smoke-stable waits for swap, limits, pool, portfolio (reuse outage-tolerant patterns from trade/charts specs). ## Acceptance criteria - [ ] Pool page shows succinct IL / LP risk notice before first provide-liquidity action. - [ ] Swap price-impact and amount validation correct for raw amounts > `9007199254740991` (unit test with string fixtures). - [ ] Axe E2E passes on `/swap`, `/limits`, `/pool`, `/portfolio` (critical/serious = 0). - [ ] No new enforced Vitest coverage thresholds. ## Test plan | Path | Command / action | |------|------------------| | Frontend unit | `make test-frontend` | | Frontend lint | `make lint-frontend` | | A11y E2E | `cd frontend-dapp && npm run test:e2e -- e2e/a11y-critical-routes.spec.ts` (smoke project) | | Manual | Chrome on `/pool` (IL copy), `/swap` with large integer paste, axe on four new routes | ## Attack / abuse test plan - IL copy must not promise guaranteed returns or omit that IL is directional risk. - Large-amount input must not coerce to scientific notation that bypasses validation. - A11y excludes chart canvas only where already excluded (do not hide real violations). ## Verification criteria - `make test-frontend` and extended a11y spec green in CI smoke config. - Pool IL notice visible in `PoolPage.test.tsx` without requiring wallet connect.
PlasticDigits commented 2026-06-12 05:06:04 +00:00 (Migrated from gitlab.com)

mentioned in issue #361

mentioned in issue #361
PlasticDigits commented 2026-06-12 05:21:39 +00:00 (Migrated from gitlab.com)

mentioned in commit 0bb04f445e

mentioned in commit 0bb04f445ea6d58c2eb8eb9133f4e2bbf3195572
PlasticDigits commented 2026-06-12 05:21:50 +00:00 (Migrated from gitlab.com)

mentioned in merge request !875

mentioned in merge request !875
Brouie commented 2026-06-12 07:34:30 +00:00 (Migrated from gitlab.com)

Verified the M10 (swap precision) slice of !875 at the unit layer here; M6 + H10 are browser/e2e and ride the laptop / clean-host pass.

M10 (validation correct for raw amounts > 9007199254740991): decimalAmountInput.ts dropped parseFloat — isPositiveDecimalAmount is "safe above 2^53" and tryParseBigInt uses BigInt. The tests carry explicit above-MAX_SAFE_INTEGER string fixtures ("does not rely on parseFloat for integers above MAX_SAFE_INTEGER"). Ran decimalAmountInput.test.ts + rawAmountMath.test.ts on the branch: 26/26 pass. So the price-impact / amount-validation precision AC is covered.

Deferred to the browser / clean-host pass (not VPS-verifiable here):

  • M6: Pool-page IL / LP-risk notice before first provide-liquidity — visual, laptop.
  • H10: axe E2E (critical/serious = 0) on /swap, /limits, /pool, /portfolio — a11y-critical-routes.spec.ts, clean-host e2e (folds into the same clean-host run #337 is waiting on).

M10 good from my side.

Verified the M10 (swap precision) slice of !875 at the unit layer here; M6 + H10 are browser/e2e and ride the laptop / clean-host pass. M10 (validation correct for raw amounts > 9007199254740991): decimalAmountInput.ts dropped parseFloat — isPositiveDecimalAmount is "safe above 2^53" and tryParseBigInt uses BigInt. The tests carry explicit above-MAX_SAFE_INTEGER string fixtures ("does not rely on parseFloat for integers above MAX_SAFE_INTEGER"). Ran decimalAmountInput.test.ts + rawAmountMath.test.ts on the branch: 26/26 pass. So the price-impact / amount-validation precision AC is covered. Deferred to the browser / clean-host pass (not VPS-verifiable here): - M6: Pool-page IL / LP-risk notice before first provide-liquidity — visual, laptop. - H10: axe E2E (critical/serious = 0) on /swap, /limits, /pool, /portfolio — a11y-critical-routes.spec.ts, clean-host e2e (folds into the same clean-host run #337 is waiting on). M10 good from my side.
PlasticDigits commented 2026-06-12 07:57:07 +00:00 (Migrated from gitlab.com)

mentioned in commit ede4ce9b6b

mentioned in commit ede4ce9b6ba1b71d6ab674c40bbaa30b6b46fcce
PlasticDigits commented 2026-06-12 08:24:52 +00:00 (Migrated from gitlab.com)

Verification — #366 (PASS)

Verified on main at 6205054 (merge 0bb04f4 / !875). No repo changes from this verify pass.

Acceptance criteria

Criterion Result How verified
Pool page shows succinct IL / LP risk notice before first provide-liquidity action PASS make test-frontend → PoolPage.test.tsx “shows impermanent loss notice when provide panel is open (GitLab #366)”. Browser: Playwright on /pool with LocalTerra deploy — pool-il-risk-notice visible above Asset A fields, copy mentions diverge risk, Learn more → #pool-lp-risk-disclosure.
Swap price-impact and amount validation correct for raw amounts > 9007199254740991 PASS make test-frontend (957/957) — decimalAmountInput.test.ts (isPositiveDecimalAmount above MAX_SAFE_INTEGER), rawAmountMath.test.ts (spreadPercentFromRawSim), SwapPage.test.tsx “large-amount precision (GitLab #366)”. Browser: Simulated Wallet on /, pasted 9007199254740992 — no Enter Amount gate. Submit path still BigInt-safe (#356); remaining parseFloat only on custom slippage UI.
Axe E2E passes on /swap, /limits, /pool, /portfolio (critical/serious = 0) PASS PLAYWRIGHT_SKIP_CHAIN=1 npm run test:e2e:smoke -- e2e/a11y-critical-routes.spec.ts — 8/8 passed (5 workers). Routes: / (Swap), /limits, /pool, /portfolio plus existing trade/charts/wallet chrome.
No new enforced Vitest coverage thresholds PASS No coverageThreshold in vitest.config.ts.
Frontend lint PASS make lint-frontend — 0 errors (5 pre-existing hook-deps warnings).

Implementation notes (spot-check)

  • M6: PoolPage.tsx — data-testid="pool-il-risk-notice", role="note", compact copy + docs link (POOL_LP_RISK_DOC).
  • M10: isPositiveDecimalAmount + spreadPercentFromRawSim replace parseFloat on amount gating and hop spread % display.
  • H10: a11y-critical-routes.spec.ts extended with outage-tolerant shell waits (waitForSwapShell, waitForRouteShell).

Environment

  • Pulled latest main; provisioned LocalTerra via make setup-cloud-localterra for browser checks (frontend-dapp/.env.local present).
  • A11y smoke uses VITE_PLAYWRIGHT_E2E=true per CI (e2e-smoke project).

Closing as verified.

## Verification — #366 (PASS) Verified on `main` at `6205054` (merge `0bb04f4` / !875). No repo changes from this verify pass. ### Acceptance criteria | Criterion | Result | How verified | |-----------|--------|--------------| | Pool page shows succinct IL / LP risk notice before first provide-liquidity action | **PASS** | `make test-frontend` → `PoolPage.test.tsx` “shows impermanent loss notice when provide panel is open (GitLab #366)”. Browser: Playwright on `/pool` with LocalTerra deploy — `pool-il-risk-notice` visible above Asset A fields, copy mentions diverge risk, Learn more → `#pool-lp-risk-disclosure`. | | Swap price-impact and amount validation correct for raw amounts > `9007199254740991` | **PASS** | `make test-frontend` (957/957) — `decimalAmountInput.test.ts` (`isPositiveDecimalAmount` above MAX_SAFE_INTEGER), `rawAmountMath.test.ts` (`spreadPercentFromRawSim`), `SwapPage.test.tsx` “large-amount precision (GitLab #366)”. Browser: Simulated Wallet on `/`, pasted `9007199254740992` — no **Enter Amount** gate. Submit path still BigInt-safe (#356); remaining `parseFloat` only on custom slippage UI. | | Axe E2E passes on `/swap`, `/limits`, `/pool`, `/portfolio` (critical/serious = 0) | **PASS** | `PLAYWRIGHT_SKIP_CHAIN=1 npm run test:e2e:smoke -- e2e/a11y-critical-routes.spec.ts` — 8/8 passed (5 workers). Routes: `/` (Swap), `/limits`, `/pool`, `/portfolio` plus existing trade/charts/wallet chrome. | | No new enforced Vitest coverage thresholds | **PASS** | No `coverageThreshold` in `vitest.config.ts`. | | Frontend lint | **PASS** | `make lint-frontend` — 0 errors (5 pre-existing hook-deps warnings). | ### Implementation notes (spot-check) - **M6:** `PoolPage.tsx` — `data-testid="pool-il-risk-notice"`, `role="note"`, compact copy + docs link (`POOL_LP_RISK_DOC`). - **M10:** `isPositiveDecimalAmount` + `spreadPercentFromRawSim` replace `parseFloat` on amount gating and hop spread % display. - **H10:** `a11y-critical-routes.spec.ts` extended with outage-tolerant shell waits (`waitForSwapShell`, `waitForRouteShell`). ### Environment - Pulled latest `main`; provisioned LocalTerra via `make setup-cloud-localterra` for browser checks (`frontend-dapp/.env.local` present). - A11y smoke uses `VITE_PLAYWRIGHT_E2E=true` per CI (`e2e-smoke` project). Closing as verified.
PlasticDigits (Migrated from gitlab.com) closed this issue 2026-06-12 08:24:54 +00:00
PlasticDigits commented 2026-06-26 06:50:32 +00:00 (Migrated from gitlab.com)

mentioned in issue #422

mentioned in issue #422
Brouie commented 2026-06-28 22:41:05 +00:00 (Migrated from gitlab.com)

mentioned in issue #337

mentioned in issue #337
PlasticDigits commented 2026-08-16 07:14:03 +00:00 (Migrated from gitlab.com)

mentioned in issue #531

mentioned in issue #531
PlasticDigits commented 2026-08-16 09:55:49 +00:00 (Migrated from gitlab.com)

mentioned in issue #533

mentioned in issue #533
PlasticDigits commented 2026-08-26 04:11:20 +00:00 (Migrated from gitlab.com)

mentioned in issue #660

mentioned in issue #660
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/cl8y-dex-terraclassic#366
No description provided.