Feat/420 421 422 423 send flow validation states success qr - #523
Merged
phertyameen merged 4 commits intoAug 29, 2026
Conversation
… before submit Adds client-side validation to the send form so bad input never reaches the API (Issue bridgelet-org#420): - Extracts the Stellar public-key regex that already existed in WalletAddressInput into a shared lib/validation/stellar-address.ts utility, and reuses it in ConnectStep (reject a malformed address returned by Freighter or restored from localStorage before it can become the funding/recovery address) and WalletAddressInput itself. - DetailsStep now enforces a minimum send amount per asset and blocks amounts above the connected wallet's actual balance, looked up via a new lib/wallet-balance.ts (Horizon fetch, fails open/never blocks when the balance can't be determined). - Field errors are now also validated on blur, not just on submit. Also fixes a pre-existing, unrelated bug that was blocking this repo's whole test suite from compiling: lib/create-bridgelet-client.ts had every template literal written with literally-escaped backticks (\` / \${) instead of real ones, a syntax error that made the file (and everything importing it, including the send flow) fail to parse. Fixed so `npm test` actually exercises the send flow's existing coverage, and added the missing @testing-library/dom devDependency the test suite needs. Tests: lib/validation/stellar-address.test.ts, lib/wallet-balance.test.ts, and new/updated coverage in details-step.test.tsx and connect-step.test.tsx (53 tests, all passing). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Adds dedicated visual states for the gap between submitting a send transaction and getting confirmation back (Issue bridgelet-org#421): - New 'confirming' SubmitPhase, entered ~2.5s into a still-pending request, distinct from the initial 'preparing'/'awaiting-freighter'/ 'submitting' phases and from 'success'. - A visible pending panel (role="status", spinner + phase label) is shown for the whole submitting/confirming window, replacing the previous "only the button label changes" feedback. - The Confirm/Try Again button is already disabled for the entire pending window (submitPhase !== 'idle' && !== 'success'), so this also prevents double-submitting the same payment. - Timeout handling: after 15s still waiting, a non-blocking "this is taking longer than usual" notice appears. It does not abort the request — the client already retries with backoff, and the payment may have already landed on-chain even if the HTTP response is slow, so cancelling client-side could desync the UI from reality. Also adds the Issue bridgelet-org#420 defense-in-depth check to this same submit handler: the funding/recovery address is validated with the shared isValidStellarAddress() helper before the create-account request is ever built, so a corrupted address can't reach the API from here either (ConnectStep already blocks it earlier, in the previous commit). Updates the pre-existing ConfirmStep test fixture's placeholder public key (was 41 chars, not a valid Stellar address shape) to a valid one so it isn't rejected by the new guard. Tests: components/send-form/steps/confirm-step.test.tsx (new — pending panel, button disabled while submitting, and the invalid-address rejection), plus the existing 9 ConfirmStep error/signing tests continue to pass unchanged. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
After a successful send, ConfirmStep's success view now surfaces the claim link itself, not just a description of it (Issue bridgelet-org#422): - The full claim URL is displayed prominently as a link, in a dedicated "Claim link" panel (previously the URL was only used internally for the WhatsApp/NFC share actions and never shown to the sender as readable/selectable text). - A one-click copy-to-clipboard button next to it, using the existing (previously unused anywhere) CopyToClipboard component. - The panel states the link's absolute expiration deadline (e.g. "September 4, 2026 at 3:45 PM"), preferring the server-reported account.expiresAt and falling back to a client-computed one from the chosen expiry window — so the sender knows exactly when the link stops working, not just the relative "7 days" window shown above it. Tests: components/copy-to-clipboard.test.tsx (new — this component had no coverage before) and new ConfirmStep cases covering the visible claim link, the copy button, and the expiry deadline text. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Adds a QR code of the claim link to the success screen for in-person / SMS-limited disbursement (Issue bridgelet-org#423). The QRCode component already existed (components/qr-code.tsx, wired up via QRCodeModalButton) but its "QR code" was actually a hash-scrambled 21x21 grid dressed up with finder/timing patterns — genuinely QR-shaped, but not a real encoding, so nothing could ever scan or decode it. Swaps the matrix generation to the `qrcode` package's synchronous, pure-JS `create()` encoder (real Reed–Solomon error correction, no network calls, safe for SSR) while keeping the component's public API and SVG rendering approach unchanged, so none of its existing tests needed to change. Also adds a proper quiet zone around the modules, which the previous edge-to-edge rendering lacked and real scanners rely on. - Round-trip verified: added tests that encode a claim URL with generateQrMatrix(), rasterize the module matrix into a plain RGBA bitmap (no canvas/DOM rasterization needed), and decode it with an independent decoder (`jsqr`) — asserting the decoded text matches the original claim URL exactly, for several URL shapes. - Downloadable as an image: the component's existing SVG download button (unchanged) now downloads a real, scannable QR code instead of a fake one. - Accessible alt text: QRCodeModalButton passes a purpose-specific label ("Scannable QR code — scan to open the claim link: ...") to the underlying <QRCode>'s aria-label, describing what the code is for. Wires QRCodeModalButton into ConfirmStep's success screen, next to the claim link and copy button added in the previous commit. Tests: components/qr-code.test.tsx (existing 2 tests unchanged/passing + 4 new round-trip/structural tests) and a new ConfirmStep case covering reveal-QR-on-demand. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
|
@A6dulmalik 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. |
3 tasks
Contributor
|
Merged to \main\ as part of a consolidated integration (branch \merge-final, now pushed as commit \5155235\ on main). Validation on main:
Note: the Mobile CI Android/iOS native debug build jobs still fail on pre-existing repo issues unrelated to this PR (react-native-reanimated vs RN 0.81 compile error, and the macos-14 runner's Xcode 15.4 vs RN's required Xcode >= 16.1). Tracked as follow-up work, not blocked by this change. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Four related send-flow issues, implemented in dependency order (validation → pending
states → success screen → QR code), one commit per issue.
#420 — Send form input validation for amount and destination
Extracted the existing Stellar-address regex from
WalletAddressInputinto a sharedlib/validation/stellar-address.ts.ConnectStepnow rejects a malformed addressfrom Freighter or persisted storage.
DetailsStepenforces a per-asset minimumamount and blocks amounts above the wallet's actual balance (new
lib/wallet-balance.ts, Horizon lookup, fails open on lookup error). Errors alsovalidate on blur, not just on submit.
Note: this flow uses claim links rather than a manual destination-address field, so
validation targets the sender's connected wallet address (the actual Stellar address
the form collects) rather than a recipient-address input.
#421 — Send flow loading and pending transaction states
Added a distinct
confirmingphase separate from preparing/awaiting-Freighter/submitting/success. A visible pending panel is shown throughout. The submit button
stays disabled for the entire window to prevent double-send. A non-blocking 15s
"taking longer than usual" notice appears if confirmation is slow — it does not
abort the transaction, since the payment may already have landed on-chain.
#422 — Send flow success screen with shareable claim link
The claim URL is now displayed prominently as a link, with one-click copy via the
previously-unused
CopyToClipboardcomponent, and an absolute expiration deadline(prefers the server-provided
expiresAtwhen available).#423 — QR code generation for claim links
Found and fixed a real bug: the existing
QRCodecomponent's matrix was ahash-scrambled fake — not a real QR encoding, and not actually scannable. Replaced
it with the
qrcodepackage's real encoder plus a proper quiet zone. Addedround-trip decode tests using an independent decoder (
jsqr) that confirm thegenerated QR actually decodes back to the exact claim URL. Wired into the success
screen with accessible alt text and a downloadable image.
Also fixed (necessary prerequisite)
lib/create-bridgelet-client.tshad every template literal written with literally-escaped backticks — a pre-existing syntax error that blocked the entire test suite
from compiling. Fixed as part of the first commit since no test could run without
it. Added the missing
@testing-library/domdevDependency.Tests/checks performed
npm test: 268 passing (was 0 before the prerequisite syntax fix, since thecorrupted file blocked test collection entirely; 231 passing on a version of
main with just that one file manually patched, for comparison — this branch
adds ~55 new/updated tests on top of that).
mainbefore any of these changes and unrelated to these issues (mock-shape mismatches
in
create-bridgelet-client.test.ts,next-config-headers.test.ts,how-it-works.test.tsx,keyboard-navigation.test.tsx).tsc --noEmitandeslintclean on every file this PR touches.(
auto-sweep-retry.tsx,education-tooltip.tsx,mobile-deep-link.tsx,multi-step-progress.tsx) have the same kind of backtick corruption — untouchedhere since they're unrelated to and not imported by anything these issues cover.
Closes #420
Closes #421
Closes #422
Closes #423