Skip to content

feat: implement #284 #285 #286 #287 - #363

Open
berriblue-323 wants to merge 1 commit into
stellar-vortex-protocol:mainfrom
berriblue-323:feat/issues-284-285-286-287
Open

feat: implement #284 #285 #286 #287#363
berriblue-323 wants to merge 1 commit into
stellar-vortex-protocol:mainfrom
berriblue-323:feat/issues-284-285-286-287

Conversation

@berriblue-323

Copy link
Copy Markdown

Title: feat: recent chains, price staleness, Tooltip component, useRetry hook

─────────────────────────────────────────────────────────────────────────────────────────────────

Description:

Summary

Implements four high-complexity issues in a single cohesive PR. All changes are additive or
strictly improve existing behaviour — no breaking changes to existing APIs or component
interfaces.

Closes #284
Closes #285
Closes #286
Closes #287

─────────────────────────────────────────────────────────────────────────────────────────────────

#284 — Pinned/recent chains quick-select row

Adds a useRecentChains hook backed by localStorage that tracks the last 3 distinct chains a user
has selected. A compact quick-select row now appears above the full chain grid in the SwapCard
chain picker whenever history exists — first-time users see nothing extra.

  • src/hooks/useRecentChains.ts — capped at 3, deduped, filters chains removed from CHAINS
  • src/hooks/useRecentChains.test.ts — unit coverage of pure list logic + hook (localStorage stub)
  • src/components/SwapCard.tsx — quick-select row; both rows share handleSelectChain which records
    recency identically

─────────────────────────────────────────────────────────────────────────────────────────────────

#285 — Surface token price staleness

Makes the hardcoded priceUSD values in marketData.ts honest about being static estimates.

  • src/lib/marketData.ts — adds PRICES_AS_OF = "2026-08-30" with a detailed contributor JSDoc on
    how/when to refresh values
  • src/components/SwapCard.tsx — shows an inline est. badge (title tooltip: "Estimated price as of
    {date}") next to the approx-USD value, but only before a live quote is available; disappears the
    moment useQuote resolves so it never competes with real quote data
  • en.ts / es.ts — swap.prices.estimated, swap.prices.asOf

─────────────────────────────────────────────────────────────────────────────────────────────────

#286 — Accessible shared Tooltip component

New src/components/Tooltip.tsx implementing the WAI-ARIA tooltip pattern:

  • Shown on hover and keyboard focus — never mouse-only
  • Dismissed via Escape from anywhere on the page
  • aria-describedby wired to the trigger while visible, removed on close
  • Basic viewport-edge collision detection (flips above/below)
  • Tap-to-toggle affordance for touch devices
  • Does not trap focus or interfere with Tab order

Applied to the three quote-detail labels in SwapCard: Price impact, Protocol fee, and Est. fill
time — each with explanatory copy in en.ts and es.ts.

  • src/components/Tooltip.test.tsx — hover-show, focus-show, Escape-dismiss, aria-describedby
    association, blur-hide
  • src/components/Tooltip.stories.tsx — Default, PriceImpact, ProtocolFee, FillTime,
    PlacementBottom
  • docs/components.md — Tooltip entry with props table and behaviour notes

─────────────────────────────────────────────────────────────────────────────────────────────────

#287 — useRetry hook + API call wiring

Implements the missing src/hooks/useRetry.ts so the previously-orphaned useRetry.test.ts now
validates a real, shipped hook.

  • useRetry() hook — exposes onErrorRetry (SWR-compatible) and withRetry (async wrapper) with
    exponential back-off (1 s, 2 s, 4 s), capped at 3 retries
  • swrRetryConfig — drop-in spread for useSWR options
  • Does not retry 4xx client errors — consistent with useQuote's existing policy
  • swrRetryConfig wired into all 7 SWR hooks: useIntents, useIntent, useMyIntents, useSolvers,
    useOpenIntents, useActivityFeed, useQuote
  • useAcceptIntent.ts — accept() wrapped with withRetry so transient network blips are handled
    without requiring a manual solver retry; 4xx errors (e.g. intent already claimed) surface
    immediately
    │ Note: Signature-requiring flows (createIntent → sign → submitIntent) are intentionally excluded
    from automatic retry — a rejected signature must never silently replay without fresh user
    consent.

─────────────────────────────────────────────────────────────────────────────────────────────────

Testing

  • useRecentChains.test.ts — new, full coverage
  • Tooltip.test.tsx — new, full coverage
  • useRetry.test.ts — previously orphaned, now passes against the real implementation
  • Existing SwapCard.test.tsx and all other hook tests remain green

stellar-vortex-protocol#286 stellar-vortex-protocol#287

stellar-vortex-protocol#284 - Add useRecentChains hook + quick-select row in chain picker
- src/hooks/useRecentChains.ts: localStorage-backed, deduped, capped at 3,
  filters removed chains
- src/hooks/useRecentChains.test.ts: full unit coverage of pure logic + hook
- SwapCard.tsx: recent-chains row above full grid, both rows call
  handleSelectChain which records recency

stellar-vortex-protocol#285 - Surface token price staleness
- src/lib/marketData.ts: add PRICES_AS_OF constant with contributor refresh
  instructions
- SwapCard.tsx: show inline 'est.' badge (with 'as of {date}' tooltip title)
  next to the approx-USD value when showing a price-derived estimate (no
  live quote yet) — does not interfere with real quote display
- en.ts / es.ts: swap.prices.estimated, swap.prices.asOf

stellar-vortex-protocol#286 - Accessible shared Tooltip component
- src/components/Tooltip.tsx: WAI-ARIA tooltip pattern — hover/focus show,
  Escape dismiss, aria-describedby, viewport collision handling, tap-toggle
  on touch
- Applied to swap.quote.priceImpact, swap.quote.protocolFee,
  swap.quote.fillTime labels in SwapCard quote details panel
- en.ts / es.ts: tooltip explanation keys for all three fields
- src/components/Tooltip.test.tsx: hover-show, focus-show, Escape-dismiss,
  aria-describedby association, blur-hide
- src/components/Tooltip.stories.tsx: Default, PriceImpact, ProtocolFee,
  FillTime, PlacementBottom stories
- docs/components.md: Tooltip entry

stellar-vortex-protocol#287 - Implement useRetry hook + wire into API calls
- src/hooks/useRetry.ts: useRetry hook (onErrorRetry + withRetry),
  makeOnErrorRetry factory, swrRetryConfig drop-in spread
- Wired swrRetryConfig into all SWR hooks: useIntents, useIntent,
  useMyIntents, useSolvers, useOpenIntents, useActivityFeed, useQuote
  (satisfies useRetry.test.ts contract — retry 5xx, no retry 4xx)
- useAcceptIntent.ts: accept() wrapped with withRetry for transient failure
  resilience; 4xx errors surface immediately without retry
- useQuote.ts: migrated to swrRetryConfig, now also returns quoteErrorType
@drips-wave

drips-wave Bot commented Aug 30, 2026

Copy link
Copy Markdown

@berriblue-323 Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant