Skip to content

fix(send-scanner): navigate before async work#1096

Open
orveth wants to merge 1 commit into
masterfrom
fix/scanner-slowness-navfirst
Open

fix(send-scanner): navigate before async work#1096
orveth wants to merge 1 commit into
masterfrom
fix/scanner-slowness-navfirst

Conversation

@orveth

@orveth orveth commented May 20, 2026

Copy link
Copy Markdown
Contributor

Summary

Minimum-viable fix for #1092 — the slowness on /send/scan was the scanner sitting on the camera view while selectDestination and proceedWithSend ran their network round-trips. Two changes here:

  1. Sync pre-classify in handleDecode using the same classifyInput + validateBolt11 pair that /scan uses. Catches unparseable QRs, cashu tokens (unsupported in send context), and BOLT11s with wrong network / expired / missing amount. These toast and keep the scanner open — user can scan again without re-tapping.
  2. Navigate before the async work. Once the sync pre-classify passes, navigate('/send') fires immediately, then selectDestination (LNURL pre-check) and proceedWithSend (quote) run with the scanner already unmounted. proceedWithSend sets status: 'quoting' synchronously before its first await, so SendInput's Continue button mounts in loading state. On quote success the handler navigates to /send/confirm; on failure (or async LNURL fetch failure) the toast lands on /send.

See discord for video demos of both cases

Behavior summary

QR Old New
BOLT11 with amount scanner stays open during sync resolve + quote, then `/send/confirm` sync-validate → navigate to `/send` immediately, quote in background, then `/send/confirm`
BOLT11 without amount (spark) scanner stays open during sync resolve, then `/send` sync-validate → navigate to `/send` immediately, user enters amount
Lightning address scanner stays open during LNURL pre-check, then `/send` navigate to `/send` immediately, destination pins after LNURL pre-check resolves (~hundreds of ms on slow network)
Unparseable QR / cashu token toast, stays open (specific message per type) toast "Please scan a lightning invoice or lightning address", stays open (single generic message)
BOLT11 expired / wrong network / missing amount toast with specific error, stays open same
LN address that fails LNURL pre-check toast, scanner stays open scanner closes; toast lands on `/send`

The only behavior regression is the last row — LN addresses that pass format validation but fail the LNURL fetch close the scanner before toasting. Acceptable: the LNURL fetch is what makes the LN-address path slow in the first place, and gating navigation on it brings the slowness back. Could be mitigated later (e.g., a sync "looks-like" check + defer the async LNURL toast to /send only when needed).

Also note: unparseable QRs and cashu tokens now share a generic "scan a lightning invoice or lightning address" toast instead of the more specific old messages — single check, single error path.

Related

@vercel

vercel Bot commented May 20, 2026

Copy link
Copy Markdown

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

Project Deployment Actions Updated (UTC)
agicash Ready Ready Preview, Comment Jun 5, 2026 10:17pm
agicash-root-dir-test Error Error Jun 5, 2026 10:17pm

Request Review

@supabase

supabase Bot commented May 20, 2026

Copy link
Copy Markdown

This pull request has been ignored for the connected project hrebgkfhjpkbxpztqqke because there are no changes detected in supabase directory. You can change this behaviour in Project Integrations Settings ↗︎.


Preview Branches by Supabase.
Learn more about Supabase Branching ↗︎.

@gudnuf

gudnuf commented May 20, 2026

Copy link
Copy Markdown
Contributor

The only behavior regression is the last row — LN addresses that pass format validation but fail the LNURL fetch close the scanner before toasting.

I don't think this matters much as its very unlikely to scan a lightning address. I have seen lightning addresses as a QR codes but usually people just type them in.

@gudnuf gudnuf requested a review from jbojcic1 May 20, 2026 23:31
@gudnuf gudnuf self-assigned this May 20, 2026
Comment thread app/features/send/send-scanner.tsx Outdated
const convert = useConverter(sendAccount);

const handleDecode = async (input: string) => {
const classified = classifyInput(input);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hm I am not sure I like that we are now doing similar things in two places. e.g. bolt11 invoice now gets validated more than once

@jbojcic1 jbojcic1 May 26, 2026

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

more important than that, seems like a code smell that now send-scanner component is doing some stuff even after we navigate away that has nothing to do with scanning. seems cleaner to just redirect to /send and pass destination as hash and then let send page handle proceeding with the send

Rebased onto post-monorepo master; paths relocated app/ -> apps/web-wallet/app/. Original commits:
 - fix(send-scanner): pass scanned input via hash, let /send loader resolve
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.

3 participants