Skip to content

feat: QR code generation and scanning modal for quick wallet pay requests - #456

Merged
Cjay-Cyber-2 merged 2 commits into
mergepay:mainfrom
oyebolarotimi269-ai:feat/qr-wallet-pay-request-328
Sep 8, 2026
Merged

feat: QR code generation and scanning modal for quick wallet pay requests#456
Cjay-Cyber-2 merged 2 commits into
mergepay:mainfrom
oyebolarotimi269-ai:feat/qr-wallet-pay-request-328

Conversation

@oyebolarotimi269-ai

Copy link
Copy Markdown
Contributor

Summary

Implements QR code generation and scanning for quick wallet pay requests, resolving #328.

Sharing a Stellar public key or payment request as raw text is error-prone and cumbersome. This adds a Receive Money modal where users can show a scannable QR code of their address (or a web+stellar: transaction URI) and validate payloads they scan from others — so pay requests move at the speed of a camera shutter, not a copy-paste.

Changes

src/components/ReceiveQrModal.tsx (new)

  • Generate tab — renders the connected Stellar public key (or an optional transaction URI) as a QR code via qrcode.react (QRCodeSVG, level M, 200px). The QR always encodes the full payload; the text readout truncates 56-character ed25519 keys for display only, so long keys never break the layout or the scan.
  • Scan tab — accepts a pasted scanned payload. parseScannedPayload() classifies it as a valid ed25519 public key (via the project's StrKey validator) or a payment URI, and rejects anything else with an inline role="alert" message plus an error toast — garbage never reaches the copy button.
  • Copy-to-clipboard — both the generated payload and a validated scanned payload get a copy button that flips to a check icon with a lime confirmation state and fires a sonner success toast. Clipboard failures (denied permission / insecure origin) surface an error toast instead of a fake "copied" state.
  • Neobrutalist styling — thick border-2/border-3 ink borders, sharp brutal shadows (shadow-brutal-sm/md), grape/butter/lime palette, uppercase font-display labels — matching the existing ShareQrModal / ShareAddressModal patterns.
  • Responsive — fixed 200px QR inside a max-width card, fluid flex layout, and the existing Dialog component handle narrow mobile viewports.
  • Accessibility: labelled inputs, aria-labels on icon-only buttons, state-aware aria-label swap on copy, colour never the sole feedback channel.

src/components/WalletWidget.tsx

  • Adds a Receive button next to the connected address chip that opens the modal with the connected wallet's public key.

src/components/ReceiveQrModal.vitest.test.tsx (new)

10 unit tests covering:

  • QR renders and encodes the full, untruncated public key
  • Optional transaction URI is encoded instead of the address
  • Copy success: full payload written to clipboard, button flips to "copied", success toast fired
  • Copy failure: error toast fired, no fake copied state
  • Scan flow: valid address validated + copied; invalid payload rejected with alert + error toast and no copy target offered
  • parseScannedPayload unit cases (valid key / valid URI / garbage)

Acceptance criteria

  • QR Code modal component using qrcode.react in src/components/
  • Copy-to-clipboard button with visual confirmation (icon swap + sonner toast)
  • Proper sizing and responsiveness on mobile viewports
  • Unit tests for component rendering and the copy handler

Testing

  • bunx vitest run src/components/ReceiveQrModal.vitest.test.tsx — 10/10 pass
  • bunx vitest run src/components/wallet-widget.vitest.test.tsx — 7/7 pass (no regressions)
  • bun tsc -b --noEmit — no new errors introduced (all reported errors are pre-existing in unrelated files: AnchorModal, AssetSelector, queries)
  • Manually verified: QR renders for a full 56-char key, copy button + toast, scan validation of both address and URI payloads, modal at 375px viewport width

Closes #328

…t pay requests

Implements mergepay#328 — a neobrutalist ReceiveQrModal so users can request
funds by sharing a scannable QR of their Stellar public key (or a
web+stellar: transaction URI) instead of copying long text.

- Generate tab encodes the full key/URI via qrcode.react (display text
  is truncated for layout; the QR always carries the whole payload)
- Scan tab validates a pasted payload (ed25519 address or payment URI)
  and offers a copy target so scanners pay the right destination
- Copy buttons flip to a check state and fire sonner toasts; clipboard
  failures surface an error toast instead of a fake success
- WalletWidget gains a "Receive" button that opens the modal

Covers rendering, copy success/failure, scan validation, and payload
parsing with 10 unit tests.
@drips-wave

drips-wave Bot commented Sep 8, 2026

Copy link
Copy Markdown

@oyebolarotimi269-ai 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

@Cjay-Cyber-2
Cjay-Cyber-2 merged commit 8a1a528 into mergepay:main Sep 8, 2026
1 check 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.

Implement QR Code Generation and Scanning Modal for Quick Wallet Pay Requests

2 participants