import { Invoice } from "@getalby/lightning-tools"; import type { LightningAddress } from "@getalby/lightning-tools/lnurl"; import { XIcon } from "lucide-react"; import React from "react"; import { Link, useLocation, useNavigate } from "react-router"; import { toast } from "sonner"; import AppHeader from "src/components/AppHeader"; import { CurrencyInputField } from "src/components/CurrencyInputField"; import { InsufficientLightningBalanceAlert } from "src/components/InsufficientLightningBalanceAlert"; import Loading from "src/components/Loading"; import { PaymentFailedAlert } from "src/components/PaymentFailedAlert"; import { PendingPaymentAlert } from "src/components/PendingPaymentAlert"; import { LinkButton } from "src/components/ui/custom/link-button"; import { LoadingButton } from "src/components/ui/custom/loading-button"; import { Input } from "src/components/ui/input"; import { Label } from "src/components/ui/label"; import { useBalances } from "src/hooks/useBalances"; import PayFromSelect from "src/screens/wallet/send/PayFromSelect"; import { PayInvoiceRequest, PayInvoiceResponse, TransactionMetadata, } from "src/types"; import { request } from "src/utils/request"; export default function LnurlPay() { const { state } = useLocation(); const navigate = useNavigate(); const { data: balances } = useBalances(); const lnAddress = state?.args?.lnAddress as LightningAddress; const identifier = lnAddress.lnurlpData?.identifier; const [appId, setAppId] = React.useState(); const [amountSat, setAmountSat] = React.useState(""); const [comment, setComment] = React.useState(""); const [isLoading, setLoading] = React.useState(false); const [invoice, setInvoice] = React.useState(); const [errorMessage, setErrorMessage] = React.useState(""); const onSubmit = async (event: React.FormEvent) => { event.preventDefault(); setErrorMessage(""); try { if (!lnAddress) { throw new Error("no lightning address set"); } setLoading(true); const invoice = await lnAddress.requestInvoice({ satoshi: parseInt(amountSat), comment, }); setInvoice(invoice); const metadata: TransactionMetadata = { ...(comment && { comment }), ...(identifier && { recipient_data: { identifier } }), }; const payload: PayInvoiceRequest = { metadata, fromAppId: appId, }; const payInvoiceResponse = await request( `/api/payments/${invoice.paymentRequest}`, { method: "POST", body: JSON.stringify(payload), headers: { "Content-Type": "application/json", }, } ); if (!payInvoiceResponse?.preimage) { throw new Error("No preimage in response"); } navigate(`/wallet/send/success`, { state: { preimage: payInvoiceResponse.preimage, invoice, to: lnAddress.address, pageTitle: "Send to Lightning Address", }, replace: true, }); toast("Successfully paid invoice"); } catch (e) { console.error(e); setErrorMessage("" + e); toast.error("Failed to send payment", { description: "" + e, }); } finally { setLoading(false); } }; React.useEffect(() => { if (!lnAddress) { navigate("/wallet/send"); } }, [navigate, lnAddress]); if (!balances || !lnAddress) { return ; } return (
{errorMessage && invoice && ( )}
Recipient

{lnAddress.address}

{lnAddress.lnurlpData?.description && (

{lnAddress.lnurlpData.description}

)} {!!lnAddress.lnurlpData?.commentAllowed && (
{ setComment(e.target.value); }} />
)}
Back Send
); }