Skip to content

feat(dashboard): swap history table with miles tracking#111

Open
passandscore wants to merge 8 commits intomainfrom
miles-no-showing
Open

feat(dashboard): swap history table with miles tracking#111
passandscore wants to merge 8 commits intomainfrom
miles-no-showing

Conversation

@passandscore
Copy link
Copy Markdown
Contributor

Summary

  • Swap history table on dashboard — shows 5 most recent swaps inline with per-transaction miles status (Processing / +N miles / 0 miles). "Show all" button opens a paginated modal with full history, matching the leaderboard's pagination pattern.
  • Improved miles estimator — replaces slippage-tolerance-based MEV pot with a historical median surplus rate (0.68%, derived from 654 recent swaps). Fixes false-zero estimates on small/medium swaps where the old model's slippage% × output was structurally lower than real captured surplus.
  • "TBD miles" zero-state UX — when the estimate rounds to zero, the swap interface shows "TBD miles" with an info tooltip linking to a new learn article section, instead of the misleading "No miles" label.
  • Live polling for pending rows — the table polls every 15s while any row is still processing, and switches to a faster 5s cadence when awaiting a just-submitted swap via a cross-component event bus (window events + sessionStorage).
  • AppHeader auto-refresh — when a pending row flips to finalized, refetchMiles() fires so the header balance updates without a page refresh.
  • Pre-fee vs post-fee explanation — info tooltip on the table explains that per-row miles are shown before a 2% referral fee, so the row sum may differ from the header balance.
  • Learn article update — new "About the miles estimate" section in the miles article explains conservative estimation, why zeros happen, and what to trust instead.

New files

File Purpose
src/app/api/fastswap-miles/by-address/route.ts Paginated API endpoint reading from StarRocks fastswap_miles
src/lib/analytics/services/fastswap.service.ts Service layer with address validation and row mapping
src/hooks/use-user-swaps.ts Client hook with pagination, polling, and swap-event awareness
src/lib/swap-events.ts Event bus for swap-submitted signals (window events + sessionStorage)
src/components/dashboard/UserSwapsTable.tsx Inline 5-row dashboard card with "Show all" button
src/components/dashboard/UserSwapsModal.tsx Full-history dialog with leaderboard-style pagination
src/components/dashboard/user-swaps-parts.tsx Shared table components (breaks circular import)

Test plan

  • Connect wallet on dashboard — table shows 5 most recent swaps with correct token logos, amounts, miles badges, and etherscan links
  • "Show all" opens modal with paginated full history; pagination controls work
  • Perform a swap — table should show new row with "Processing" badge within ~15s, then flip to miles once finalized
  • AppHeader miles badge updates when processing completes (no page refresh needed)
  • Zero-estimate swaps show "TBD miles ⓘ" in the swap interface; tooltip renders with learn link
  • Info tooltip on table title explains pre-fee vs header discrepancy
  • No hydration errors on page load (UserSwapsTable loaded client-only via next/dynamic)
  • Disconnected wallet shows "Connect your wallet" empty state
  • Empty swap history shows "No Fast Swaps yet" state

…ve miles estimator

- Add per-transaction swap history table to the dashboard (5 most recent)
  with "Show all" modal for full paginated history matching the
  leaderboard's pagination pattern
- Replace slippage-based MEV pot model with historical median surplus
  rate (0.68%) derived from 654 recent swaps — fixes false-zero miles
  estimates on small/medium swaps
- Show "TBD miles" with info tooltip when estimate is zero instead of
  misleading "No miles" label, linking to new learn article section
- Add swap-submitted event bus (window events + sessionStorage) so the
  dashboard table polls for new rows after a swap completes, even if
  the user navigates to the dashboard after swapping
- Fire refetchMiles when a pending row transitions to finalized so the
  AppHeader balance updates without a page refresh
- Add "About the miles estimate" section to the miles learn article
  explaining the conservative estimator and what to trust instead
- Surface info tooltip explaining pre-fee row totals vs post-fee header
  balance (2% referral fee)
- Load UserSwapsTable via next/dynamic with ssr:false to prevent
  hydration mismatch from wagmi server/client state divergence
@vercel
Copy link
Copy Markdown

vercel bot commented Apr 10, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
fastprotocolapp Ready Ready Preview, Comment Apr 10, 2026 7:03pm

Request Review

Once a user is confirmed as approved (whitelisted or waitlist-approved),
cache that fact in sessionStorage keyed by address. On subsequent page
loads within the same tab session, React Query is seeded with initialData
and staleTime: Infinity so no API call is made and no loading skeleton
is shown. The cache clears naturally when the tab closes, ensuring a
fresh check on the next browsing session.
The previous commit cached the approval flag but SwapOrLandingGate still
started at view="landing", requiring user interaction to proceed. Now an
auto-proceed effect checks the gate status on mount and transitions
directly to the swap view when both isPreApproved and acceptedInvite are
true — which resolves synchronously from the sessionStorage cache with
no API call, no skeleton, and no landing page flash.

Also tightens the cache condition: only persists to sessionStorage after
the user has both been approved AND accepted the invite (clicked "Start
Swapping"), so first-time approved users still see the welcome screen.
…age flash

Previously the auto-proceed logic ran in a useEffect, which fires after
the first render — causing a visible flash of the landing page for
returning approved users. Now:

1. A `ready` flag suppresses all rendering until the mount effect runs
2. The mount effect checks sessionStorage for a cached approval
3. If found, transitions directly to swap view before any content paints
4. If not found, shows the landing page with the Check Access button

The user sees one invisible frame (~16ms of null), then either swap or
landing — never a flash of the wrong one.
Appends "(pre-fee)" to the miles badge on both the inline swap table
and the Show All modal so the 2% referral deduction is visible at a
glance, not only in the info tooltip.
The tooltip from the inline card's info icon was bleeding through the
modal overlay. Removed MilesDiscrepancyInfo from the modal header —
the "(pre-fee)" label on the pill already communicates the same thing.
- Polling and tab-refocus refetches no longer show the loading spinner;
  only the initial mount fetch shows loading feedback
- Tab refocus only triggers a refetch when there are pending or awaited
  rows — fully finalized tables produce zero network activity
- Replace "(pre-fee)" text on miles badge with a hover/tap tooltip on
  the badge itself for a cleaner visual
- Run formatter across all changed files
- Show "TBD" instead of "Swap too small" in confirmation modal with
  the same tooltip copy and Learn link as the swap interface
- Change InfoRow tooltip prop to ReactNode to support inline links
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant