From 08dc929a5daa8e76e972d14b03dd2d767fa50794 Mon Sep 17 00:00:00 2001 From: austinkelsay Date: Wed, 6 Nov 2024 16:53:21 -0600 Subject: [PATCH] lnurl verify, first impl --- .../api/lightning-address/callback/[slug].js | 2 +- .../lightning-address/verify/[name]/[slug].js | 56 +++++++++++++++++++ 2 files changed, 57 insertions(+), 1 deletion(-) create mode 100644 src/pages/api/lightning-address/verify/[name]/[slug].js diff --git a/src/pages/api/lightning-address/callback/[slug].js b/src/pages/api/lightning-address/callback/[slug].js index de03ba1..1c04677 100644 --- a/src/pages/api/lightning-address/callback/[slug].js +++ b/src/pages/api/lightning-address/callback/[slug].js @@ -76,7 +76,7 @@ export default async function handler(req, res) { 'Authorization': PLEBDEVS_API_KEY } }); - res.status(200).json({ pr: response.data }); + res.status(200).json({ pr: response.data, verify: `${BACKEND_URL}/api/lightning-address/verify/${slug}/${response.data.payment_hash}` }); } catch (error) { console.error(error); res.status(500).json({ error: 'Failed to generate invoice' }); diff --git a/src/pages/api/lightning-address/verify/[name]/[slug].js b/src/pages/api/lightning-address/verify/[name]/[slug].js new file mode 100644 index 0000000..af3bded --- /dev/null +++ b/src/pages/api/lightning-address/verify/[name]/[slug].js @@ -0,0 +1,56 @@ +import axios from "axios"; +import { getLightningAddressByName } from "@/db/models/lightningAddressModels"; +import appConfig from "@/config/appConfig"; + +export default async function handler(req, res) { + try { + const { name, slug } = req.query; + + // Find the lightning address + let foundAddress = null; + const customAddress = appConfig.customLightningAddresses.find(addr => addr.name === name); + + if (customAddress) { + foundAddress = customAddress; + } else { + foundAddress = await getLightningAddressByName(name); + } + + if (!foundAddress) { + res.status(404).json({ error: 'Lightning address not found' }); + return; + } + + // Convert hex payment hash to base64 + const paymentHashBuffer = Buffer.from(slug, 'hex'); + const paymentHashBase64 = paymentHashBuffer.toString('base64'); + + // Call LND to check payment status + const response = await axios.get( + `https://${foundAddress.lndHost}/v1/invoice/${paymentHashBase64}`, + { + headers: { + 'Grpc-Metadata-macaroon': foundAddress.invoiceMacaroon, + } + } + ); + + // According to LNURL-pay spec, we should return { status: "OK" } if paid + // or { status: "ERROR", reason: "error message" } if not paid or error + if (response.data.state === 'SETTLED') { + res.status(200).json({ status: "OK" }); + } else { + res.status(200).json({ + status: "ERROR", + reason: "Invoice not paid" + }); + } + + } catch (error) { + console.error('Error verifying payment:', error.message); + res.status(200).json({ + status: "ERROR", + reason: error.message || "Error verifying payment" + }); + } +}