Skip to content

feat: wallet connect persistence, expiry summary, fee estimation, batch send - #514

Merged
phertyameen merged 3 commits into
bridgelet-org:mainfrom
a-malik-gh:feature/issues-424-425-426-427-send-flow-enhancements
Aug 27, 2026
Merged

feat: wallet connect persistence, expiry summary, fee estimation, batch send#514
phertyameen merged 3 commits into
bridgelet-org:mainfrom
a-malik-gh:feature/issues-424-425-426-427-send-flow-enhancements

Conversation

@a-malik-gh

Copy link
Copy Markdown
Contributor

Summary

This PR implements four open issues on the /send flow.


Issue #424 — Wallet connect integration on the send flow

  • Persistence: ConnectStep now calls loadPersistedWallet on mount and restores the wallet from localStorage so the sender doesn't have to re-connect every time they navigate back through the flow.
  • Disconnect: Added a "Disconnect wallet" link that calls clearPersistedWallet and clears the key in the parent form state.
  • Rejection handling: Rejection errors (user declined, User rejected) are mapped to a clear human message distinct from "not installed" errors.
  • Unsupported-browser fallback: isBrowserExtensionSupported() detects non-extension environments (Safari mobile, in-app webviews) and renders an amber informational banner instead of the connect button.

Issue #425 — Expiration time selector for ephemeral accounts

  • The ExpiryStep already had preset selection (24h / 7d / 30d / custom) and a sensible 7-day default.
  • Added: A "Claim expires" row in the ConfirmStep summary table, showing the selected window (e.g. "7 days from now") clearly before the sender submits.
  • SendForm now handles wallet disconnect (empty key) without advancing steps.

Issue #426 — Fee estimation display before sending

  • New: frontend/lib/fee-estimation.ts — fetches /fee_stats from Horizon, uses p50 of max_fee per operation × 2 ops.
  • ConfirmStep now renders an "Estimated network fee" panel with the fee in XLM and USD (when the XLM/USD rate is available).
  • A refresh button and a 30-second auto-refresh keep the estimate current while the user is on the confirm step.
  • Shows a "Network is currently busy" warning when ledger_capacity_usage > 0.8.

Issue #427 — Batch sending to multiple recipients

  • New: frontend/components/batch-send-form.tsx — full batch send UI.
    • Manual row entry with add/remove controls (up to 100 rows).
    • CSV upload (columns: name, email, amount, asset).
    • Per-recipient validation before submission (name required, email optional, positive amount, supported asset).
    • Sequential processing with per-row processing / success / error indicators.
    • Batch summary: "N succeeded, M failed out of total".
    • "Retry failed" button re-queues only failed rows.
  • New: frontend/components/send-page-client.tsx — client wrapper that adds a Single / Batch toggle above the existing SendForm.
  • /send page updated to render SendPageClient instead of SendForm directly.

Tests

  • connect-step.test.tsx updated: mocks loadPersistedWallet, persistWallet, clearPersistedWallet; tests persistence restore, disconnect, rejection message, unsupported-browser fallback via extensionSupportedOverride prop.
  • lib/fee-estimation.test.ts — new: tests XLM + fiat output, caching, error propagation, opCount, capacityUsage.
  • components/batch-send-form.test.tsx — new: tests validateRecipient, parseCsv, wallet restore, add/remove rows, validation errors, batch success and error states.

All 229 tests pass. Build: green.


Closes #424
Closes #425
Closes #426
Closes #427

…ch send

Issue bridgelet-org#424 - Wallet connect enhancements:
- Persist wallet connection to localStorage via persistWallet/loadPersistedWallet
- Restore persisted wallet on ConnectStep mount, skip re-connect prompts
- Show Disconnect button to clear persisted state
- Surface rejection errors with a clear 'declined' message distinct from 'not installed'
- Show unsupported-browser fallback (amber banner) on non-extension environments
  (Safari mobile, in-app webviews) via isBrowserExtensionSupported()

Issue bridgelet-org#425 - Expiry selector in ConfirmStep summary:
- Added 'Claim expires' row to the confirm summary dl, showing the selected
  expiry window clearly (e.g. '7 days from now') before submission
- SendForm updated to handle disconnect (empty key) without advancing steps

Issue bridgelet-org#426 - Fee estimation before final confirm:
- New lib/fee-estimation.ts fetches /fee_stats from Horizon
- Uses p50 of max_fee per op × 2 ops as the recommended fee
- ConfirmStep shows 'Estimated network fee' panel with XLM + fiat amounts
- Refresh button and 30-second auto-refresh while on the confirm step
- Shows 'busy network' warning when ledger_capacity_usage > 0.8

Issue bridgelet-org#427 - Batch sending to multiple recipients:
- New BatchSendForm component with manual row entry and CSV upload
- Per-recipient validation (name required, email optional, positive amount,
  supported asset) before submission
- Sequential batch processing with per-row processing/success/error indicators
- Retry-failed-only button after batch completes
- Wallet connection restored from persistence on mount
- /send page updated to offer Single / Batch toggle via SendPageClient

Tests:
- connect-step.test.tsx updated: mocks loadPersistedWallet/persistWallet/
  clearPersistedWallet, tests persistence restore, disconnect, rejection
  message, unsupported-browser fallback (extensionSupportedOverride prop)
- lib/fee-estimation.test.ts: new, tests XLM+fiat output, caching, error
- components/batch-send-form.test.tsx: new, tests validateRecipient,
  parseCsv, wallet restore, add/remove rows, validation errors, batch
  success and error states

All 229 tests pass. Build: green.
@drips-wave

drips-wave Bot commented Aug 26, 2026

Copy link
Copy Markdown

@a-malik-gh 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

@vercel

vercel Bot commented Aug 26, 2026

Copy link
Copy Markdown

@a-malik-gh is attempting to deploy a commit to the aminubabafatima8-gmailcom's projects Team on Vercel.

A member of the Team first needs to authorize it.

connect-step.tsx: isBrowserExtensionSupported() was called in a useState
lazy initializer, which runs during SSR. On the server navigator is
undefined so it returned false, but in Chromium it returns true, causing a
hydration mismatch on /send. Fix: initialise extensionSupported to true
(the safe default that renders the connect button), then update it in a
useEffect so server and client agree on the initial render.

batch-send-form.test.tsx: parseCsv returns BatchRecipient[] and strict-mode
TypeScript correctly flags rows[0], rows[1] etc. as possibly undefined.
Added non-null assertions (!) to the six affected lines.
The previous fix initialised extensionSupported to true then called
setExtensionSupported(isBrowserExtensionSupported()) in a useEffect.
In Chromium that check returns true — the same as the initial state —
but React still processed the setState call and triggered a re-render,
detaching the button node from the DOM mid-click in Playwright.

Fix: only call setExtensionSupported when the result is false (i.e. we
genuinely need to swap to the fallback banner). In Chromium the check
returns true so setExtensionSupported is never called, no re-render
fires, and the button node remains stable for Playwright to click.
@phertyameen
phertyameen merged commit 4735e0c into bridgelet-org:main Aug 27, 2026
4 of 6 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

2 participants