Skip to content

Fee display — Slice 1: single-row Fee + tooltip on validator markets #99

@vipineth

Description

@vipineth

Parent PRD

#98

What to build

The first vertical slice of the fee display overhaul. Cuts end-to-end (pure function → hook → UI) but only covers the validator-dex path. HIP-3 markets will display whatever the validator branch produces and will remain temporarily incorrect until Slice 2 lands.

End-to-end behavior on validator markets (BTC, ETH, SOL, etc.):

  • The current Est. Fee and Builder Fee rows in the trade summary are replaced with a single Fee row showing the effective percentage and dollar amount. The label is underline-dotted to signal the tooltip affordance.
  • Hovering (desktop) or tapping (mobile) the row opens a tooltip with: exchange fee (taker / maker), builder fee with a one-line hint ("Supports interface development"), and a total row.
  • When the wallet is disconnected, the Fee row is hidden entirely.
  • When userFees has not yet resolved, the row renders a skeleton.
  • A new pure function computeEffectiveFee encapsulates fee math. In this slice only the validator branch is implemented (effective = userRate).
  • useFeeRates is rewritten to accept a UnifiedMarket and compose computeEffectiveFee with live API data (userFees). It returns null when disconnected or still loading.
  • The hardcoded ORDER_FEE_RATE_* constants are deleted from config/constants.ts.
  • getOrderMetrics is updated to accept { exchangeRate, builderBps } and return { exchangeFee, builderFee, totalFee } alongside the existing fields.
  • Unit tests cover computeEffectiveFee for: validator no-discount, validator with discount, spot validator, zero rate edge case, string-precision cases.

Reference the parent PRD's Implementation Decisions and Testing Decisions sections for details on module shape and test conventions.

Acceptance criteria

  • Single Fee row renders on validator markets showing the user's effective rate (% and $).
  • Tooltip on hover (desktop) and tap (mobile) shows exchange fee (taker / maker), builder fee row with one-line hint, divider, and total.
  • Fee row is hidden when wallet is disconnected.
  • Fee row renders a skeleton while userFees is loading.
  • computeEffectiveFee pure function exists with the shape described in the PRD; validator branch returns userRate unchanged.
  • useFeeRates(market) returns null when disconnected or data is loading; returns the full rate shape otherwise.
  • ORDER_FEE_RATE_* constants are removed from config/constants.ts with no dangling imports.
  • getOrderMetrics signature and return shape match the PRD.
  • Vitest unit tests for computeEffectiveFee cover all cases listed above; all tests pass.
  • Typecheck passes for the whole app.
  • Manual smoke: placing a market and limit order on BTC-PERP shows a sane Fee row and tooltip.

Blocked by

None — can start immediately.

User stories addressed

Reference by number from the parent PRD:

  • User story 1
  • User story 5
  • User story 6
  • User story 7
  • User story 8
  • User story 9
  • User story 10
  • User story 11
  • User story 12
  • User story 15
  • User story 18
  • User story 19
  • User story 20

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions