From 414f8faba5374bcbc06f695db77b304f771cab7a Mon Sep 17 00:00:00 2001 From: Adam Soltys Date: Tue, 6 May 2025 13:16:47 -0700 Subject: lnurl pay endpoint for latest invoice --- index.ts | 1 + routes/lnurl.ts | 42 +++++++++++++++++++++++++++++++++++++++++- 2 files changed, 42 insertions(+), 1 deletion(-) diff --git a/index.ts b/index.ts index 27decf34..10c2b314 100644 --- a/index.ts +++ b/index.ts @@ -87,6 +87,7 @@ app.get("/decode", lnurl.decode); app.get("/lnurl/verify/:id", lnurl.verify); app.get("/lnurlp/:username", lnurl.lnurlp); app.get("/lnurl/:id", lnurl.lnurl); +app.get("/pay/:username", lnurl.pay); // app.get("/lnurlw", lnurl.withdraw); app.post("/freeze", payments.freeze); diff --git a/routes/lnurl.ts b/routes/lnurl.ts index 9f247267..e5b3e60c 100644 --- a/routes/lnurl.ts +++ b/routes/lnurl.ts @@ -20,7 +20,9 @@ export default { query: { address }, } = req; const [name, domain] = address.split("@"); - const url = `https://${domain}/.well-known/lnurlp/${name.toLowerCase().replace(/\s/g,"")}`; + const url = `https://${domain}/.well-known/lnurlp/${name + .toLowerCase() + .replace(/\s/g, "")}`; try { const r = await got(url).json(); @@ -149,6 +151,44 @@ export default { res.send({ pr: hash, status: "OK", settled, preimage: preimage || null }); }, + async pay(req, res) { + const { username } = req.params; + try { + const user = await getUser(username); + const iid = await db.lIndex(`${user.id}:invoices`, 0); + const invoice = await getInvoice(iid); + const fiveMinutes = 1000 * 60 * 5; + const paid = invoice.received >= invoice.amount; + const expired = Date.now() - invoice.created > fiveMinutes; + if (paid || expired) fail("No active invoice"); + + const { id: uid } = user; + + const metadata = JSON.stringify([ + ["text/plain", `Paying ${username}@${host}`], + ["text/identifier", `${username}@${host}`], + ]); + + const id = v4(); + await s(`lnurl:${id}`, uid); + + res.send({ + allowsNostr: true, + minSendable: invoice.amount * 1000, + maxSendable: invoice.amount * 1000, + metadata, + nostrPubkey: serverPubkey, + commentAllowed: 512, + callback: `${URL}/api/lnurl/${id}`, + tag: "payRequest", + }); + } catch (e) { + if (!e.message.includes("found")) + warn("problem generating lnurlp request", username, e.message); + bail(res, e.message); + } + }, + // async withdraw(req, res) { // try { // const { pr, k1: id } = req.query; -- cgit v1.2.3