Skip to content

Preconfirmation notification UX + swap speed optimizations#85

Merged
techgangboss merged 22 commits intomainfrom
preconf-exp
Mar 25, 2026
Merged

Preconfirmation notification UX + swap speed optimizations#85
techgangboss merged 22 commits intomainfrom
preconf-exp

Conversation

@techgangboss
Copy link
Contributor

Summary

  • Preconfirmation celebration: particle burst animation, spring-bounce Fast logo, level-up sound (C5-E5-G5 arpeggio), "Preconfirmed in X.Xs" speed badge
  • Single evolving toast card: pending → preconfirmed (blue, particles, speed timer) → confirmed (green checkmark badge on Fast logo, auto-dismiss 6s with progress bar)
  • Share on X: flush strip below card with natural tweet variations mentioning Ethereum mainnet + @Fast_Protocol/@ethereum/@ethereumfdn. Dynamic OG image card via edge-rendered /api/og/preconfirm
  • 17.4s → 0.6s preconfirmation detection (ETH path): added mevcommit_getTransactionCommitments as fastest polling source — queries FastRPC node directly instead of waiting for mctransactions DB (~15s L1 inclusion lag)
  • Eliminated Vercel serverless proxy for ERC-20 swaps: /api/fastswap was a pure pass-through, FastRPC CORS allows direct client calls
  • Removed redundant getFreshGasFees() before wallet popup (result was unused, saved 200-500ms)
  • Removed duplicate polling: useSwapConfirmation + SwapToast both ran independent polling for the same hash
  • Adaptive polling: 100ms initial (catches sub-second preconfs) → 500ms backoff
  • Pre-warmed tx-timeout config on page load
  • Clickable balance fills max amount (reserves 0.01 ETH gas for native ETH)
  • Removed eth.merkle.io fallback in wagmi transports (no CORS, ~40 console errors/session)
  • Clear error on gas estimation revert instead of raw viem dump
  • Standardized "preconfirmed" (no hyphen) across all UI code
  • Cleaned all debug console.logs

Gating integrity

Zero changes to whitelisting/gating files. Verified:

  • SwapOrLandingGate.tsx — untouched
  • use-gate-status.ts — untouched
  • middleware.ts — untouched
  • /api/gate/*, /api/whitelist/* — untouched
  • use-whitelist.ts, gate-data.ts — untouched

All changes are inside the swap execution path (post-gate).

Known issue

ERC-20 Permit path swaps don't get actual preconfirmations — the /fastswap relayer appears to bypass FastRPC's commitment pipeline. mevcommit_getTransactionCommitments returns errors for relayer-submitted txs. Posted to #claws for backend team investigation.

Test plan

  • ETH → token swap: verify celebration animation, speed timer, sound, share on X
  • Token → token swap (Permit path): verify toast flow works (preconf detection depends on backend fix)
  • Click balance on sell card: fills max with 0.01 ETH gas reserve
  • Click balance on buy card: fills amount
  • Verify whitelisting still blocks non-approved wallets
  • Check console for errors — eth.merkle.io spam should be gone
  • Test share on X tweet text + OG card rendering on production domain

🤖 Generated with Claude Code

techgangboss and others added 20 commits March 24, 2026 18:35
Redesign swap notification experience to make preconfirmations the hero moment:

- Celebration animation with particle burst, glow ring, and spring-bounce Fast logo
- "Preconfirmed in X.Xs" speed timer — the shareable, tweet-able differentiator
- Share on X button with @Fast_Protocol mention and elapsed time
- Tokens Available auto-dismisses after 5s with progress bar + balance flash
- Clickable balance text fills max amount (reserves 0.01 ETH for gas)
- Adaptive polling: 100ms initial → 500ms (catches sub-second preconfs)
- Removed redundant getFreshGasFees() call (-300ms before wallet popup)
- Removed duplicate polling from useSwapConfirmation (halves API calls)
- Pre-warmed tx-timeout config, abort signal propagation
- Standardized "preconfirmed" (no hyphen) across all UI code

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Gas estimation can revert if the quote is stale or liquidity shifted
between quote and execution. Instead of blocking the user with an
opaque "Execution reverted" error before the wallet popup, fall back
to a generous 500k gas limit so the tx can still be attempted.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replaces the silent gas fallback with a user-friendly error message when
gas estimation reverts. The revert means the tx would fail on-chain, so
we should block it — not burn the user's gas on a doomed tx.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Single card transitions in place instead of swapping between components:
- Confirmed: green checkmark badge on Fast logo corner, title changes to
  "Tokens Available", green accent line, auto-dismiss countdown
- Share on X: floating pill popup that slides in 2s after preconfirmed,
  positioned below the card
- Dismiss: subtle 5px circle in top-right corner, only visible on hover
- Explorer link: minimal icon in right column, no button chrome

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Web Audio API synthesized sound — no external files:
- Quick bandpass-filtered noise sweep (whoosh, 150ms)
- Rising two-note sine chime (C6→E6, ~200ms)
- Total ~300ms, subtle volume, respects browser autoplay policy

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Three-note rising major arpeggio, ~350ms. Game-like dopamine hit.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Speed: bold badge to the right (blue/green bg pill with Xs value)
- Explorer link: larger icon, color-matched to state (blue/green)
- Share on X: flush strip below card body with border-t separator,
  slides in after 1.5s, feels like a natural extension of the card
- Dismiss X: bare glyph, no circle/bubble, hover-only opacity

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The /api/fastswap proxy was a pure pass-through adding 100-300ms
(serverless cold start + extra hop). FastRPC CORS allows direct
client calls. This cuts the "Swapping..." spinner duration for
ERC-20 permit path swaps.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The previous implementation used fromBalanceValue (parseFloat) which
could lose precision and produce floating point artifacts like
0.08990300000000001. Now uses fromBalance.value (BigInt wei) with
formatUnits for exact representation. Also fixes disabled check to
use raw balance instead of parsed float.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- /api/og/preconfirm: edge-rendered OG image showing speed, token pair,
  fire emojis (3 for <1s, 2 for 1-4s, 1 for >4s), Fast Swaps branding
- /share/preconfirm: meta page that serves OG tags for Twitter card
  preview, then redirects to main app
- Tweet now includes fire emojis, token pair, and links to share page
  so Twitter renders the visual card with the speed number

The OG card makes the speed claim verifiable — the number in the image
matches the tweet text, adding credibility to the preconfirmation speed.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…confirmed

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
OG card: removed emoji, clean layout — speed number, "Swap Preconfirmed"
label, accent line, fastprotocol.io branding. No pair names.

Tweet: natural message variations based on speed tier:
  <1s: "Didn't even see a spinner" / "That's a Fast Swap"
  1-4s: "Before the block even landed" / "Hit different"
  >4s: "Still faster than waiting for a block"
Fire emoji at end of text only (1-3 based on speed).
No URL in tweet — just the tag and the OG image card.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…thereum/@ethereumfdn

Speed + mev rewards are the two highlights. Tweets now naturally
weave in Ethereum mainnet context and mev surplus being returned
to the swapper. Tags rotate between @ethereum and @ethereumfdn.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…or slow tier

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ring

Twitter requires a URL in the tweet to render OG cards. Using the
separate &url= param in the intent so the link is present but the
tweet text stays clean. Over 10s tweets omit the speed number.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Console logs to measure exactly where the 10s goes:
- [Permit Path] FastRPC /fastswap response time (ms)
- [Toast] Dead time between placeholder creation and real hash arrival
- [TxConfirmation] Time from polling start to preconfirmed detection

Open browser console during a swap to see the breakdown.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The mctransactions DB lags ~15s behind the actual preconfirmation.
Now polls FastRPC's mevcommit_getTransactionCommitments JSON-RPC
in parallel — the node knows about commitments instantly since it
received them directly from the provider.

Three sources now race in parallel:
1. mevcommit_getTransactionCommitments (fastest — node has it)
2. eth_getTransactionReceipt via FastRPC
3. mctransactions DB (slowest, kept as fallback)

Note: ideal solution is eth_sendRawTransactionSync which returns
the commitment in the same call, but requires backend changes to
the /fastswap relayer endpoint for the Permit path.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
wagmi's http() with no URL resolves to the chain's default public RPC
(eth.merkle.io for mainnet) which has no CORS headers, causing ~40+
console errors per session. Alchemy + Ankr + 1rpc are sufficient fallbacks.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Need to see what the endpoint returns for Permit path txs — the 0.6s
ETH path worked but the ERC-20 Permit path still took 9.2s. The node
may not track commitments for relayer-submitted txs the same way.

Also includes the eth.merkle.io fix from previous commit.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Strip all timing/polling debug logs added during development:
[Permit Path], [Toast], [TxConfirmation], [CommitmentPoll]

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@vercel
Copy link

vercel bot commented Mar 25, 2026

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

Project Deployment Actions Updated (UTC)
fastprotocolapp Ready Ready Preview, Comment Mar 25, 2026 2:35pm

Request Review

…, dead state

Critical fixes from code audit:
- Sanitize `time` query param in OG image + share page (parseFloat + range
  check) to prevent metadata injection via crafted URLs
- Remove false positive fallback in fetchCommitmentStatus — only trust
  array results with actual commitment objects, not any truthy value
- Remove dead isSuccess/isConfirming state from useSwapConfirmation —
  confirmation is now owned by SwapToast, these were never set after
  removing the duplicate polling hook

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@techgangboss techgangboss merged commit e24c874 into main Mar 25, 2026
3 checks passed
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