diff --git a/ghostkey-web/src/PasswordSetupPortal.tsx b/ghostkey-web/src/PasswordSetupPortal.tsx index c581a7a..a377a74 100644 --- a/ghostkey-web/src/PasswordSetupPortal.tsx +++ b/ghostkey-web/src/PasswordSetupPortal.tsx @@ -77,7 +77,8 @@ * server stores only that public key and never anything spendable. * Strictly non-custodial; the residual above does not apply. */ -import { useEffect, useState } from "react"; +import { useEffect, useMemo, useState } from "react"; +import qrcode from "qrcode-generator"; import { Button, Field, @@ -2450,6 +2451,16 @@ function FundAddressCard({ ? "Send from any Bitcoin wallet, any amount." : `This vault is on the ${network} test network. Don't send real Bitcoin here.`; const [copied, setCopied] = useState(false); + // Uppercase bech32 packs into the QR's alphanumeric mode, giving a + // sparser, easier-to-scan code. Wallets accept either case. Same + // pattern as the dashboard's Add Bitcoin card. + const qrUrl = useMemo(() => { + if (!address) return null; + const qr = qrcode(0, "M"); + qr.addData(address.toUpperCase()); + qr.make(); + return qr.createDataURL(5, 8); + }, [address]); async function copy() { if (!address) return; try { @@ -2479,19 +2490,16 @@ function FundAddressCard({ // In group mode the heading + vault id already names the // card; render the address row directly without the Field // wrapper (which insists on a label). -
- - {address} - - -
- ) : ( - +
+ {qrUrl ? ( +
+ {`QR +
+ ) : null}
{address} @@ -2500,6 +2508,31 @@ function FundAddressCard({ {copied ? "Copied" : "Copy"}
+
+ ) : ( + +
+ {qrUrl ? ( +
+ {`QR +
+ ) : null} +
+ + {address} + + +
+
) ) : (