diff options
| author | Adam Soltys <[email protected]> | 2023-01-24 12:28:49 -0800 |
|---|---|---|
| committer | Adam Soltys <[email protected]> | 2023-01-24 12:28:49 -0800 |
| commit | 692315c0d4259a274322ca579a7b6118d033bf7a (patch) | |
| tree | 50dab3d2760130c5822b21f7293da3b34639579c /routes | |
| parent | f24aec1fb7dd4080d961c26ab5216fd2dfe5d971 (diff) | |
| download | coinos-server-692315c0d4259a274322ca579a7b6118d033bf7a.tar.gz coinos-server-692315c0d4259a274322ca579a7b6118d033bf7a.zip | |
lnurl
Diffstat (limited to 'routes')
| -rw-r--r-- | routes/invoices.js | 75 | ||||
| -rw-r--r-- | routes/lnurl.js | 66 | ||||
| -rw-r--r-- | routes/payments.js | 46 |
3 files changed, 107 insertions, 80 deletions
diff --git a/routes/invoices.js b/routes/invoices.js index 5da481e1..a4155d94 100644 --- a/routes/invoices.js +++ b/routes/invoices.js @@ -1,13 +1,5 @@ -import store from "$lib/store"; -import { l } from "$lib/logging"; -import { emit } from "$lib/sockets"; -import { db, g, s } from "$lib/db"; -import { bip21, fail } from "$lib/utils"; -import { types } from "$lib/payments"; -import { v4 } from "uuid"; - -import bc from "$lib/bitcoin"; -import ln from "$lib/ln"; +import { g, s } from "$lib/db"; +import { invoice } from "$lib/invoices"; export default { async get({ query: { hash } }, res) { @@ -16,66 +8,7 @@ export default { res.send(invoice); }, - async create({ body: { invoice, user }, user: me }, res) { - let { currency, tip, amount, rate, request_id, type } = invoice; - - if (amount < 0) fail("amount out of range"); - if (tip > 5 * amount || tip < 0) fail("tip amount out of range"); - tip = tip || 0; - - if (!user) user = me; - let uid = await g(`user:${user.username}`); - user = await g(`user:${uid}`); - - if (!user) fail("user not provided"); - - if (!currency) currency = user.currency; - if (!rate) rate = store.rates[currency]; - if (amount < 0) fail("invalid amount"); - - let hash, text; - if (type === types.lightning) { - let amt = amount ? `${amount + tip}sat` : "any"; - let r = await ln.invoice(amt, new Date(), "", 3600); - - hash = r.payment_hash; - text = r.bolt11; - } else if (type === types.bitcoin) { - hash = await bc.getNewAddress(); - text = bip21(hash, invoice); - } else if (type === types.internal) { - hash = v4(); - } else { - fail("unrecognized type"); - } - - invoice = { - ...invoice, - amount, - hash, - text, - currency, - rate, - tip, - uid, - received: 0, - created: Date.now() - }; - - l("creating invoice", user.username, amount, tip, currency, invoice.hash); - - await s(`invoice:${hash}`, invoice); - await db.lPush(`${uid}:invoices`, hash); - - if (request_id) { - let request = await g(`request:${request_id}`); - let { invoice_id: prev } = request; - request.invoice_id = invoice.id; - await s(`request:${request_id}`, request); - - if (!prev) emit(request.requester.username, "invoice", invoice); - } - - res.send(invoice); + async create({ body: { invoice, user }, user: sender }, res) { + res.send(await invoice({ invoice, user, sender })); } }; diff --git a/routes/lnurl.js b/routes/lnurl.js new file mode 100644 index 00000000..cb1b75c5 --- /dev/null +++ b/routes/lnurl.js @@ -0,0 +1,66 @@ +import { g, s } from "$lib/db"; +import { l } from "$lib/logging"; +import { fail } from "$lib/utils"; +import { v4 } from "uuid"; +import got from "got"; +import { invoice } from "$lib/invoices"; +import { bech32 } from "bech32"; + +export default { + async encode({ query: { address } }, res) { + let [name, domain] = address.split("@"); + let url = `https://${domain}/.well-known/lnurlp/${name}`; + let r = await got(url).json(); + if (r.tag !== "payRequest") fail("not an ln address"); + let enc = bech32.encode("lnurl", bech32.toWords(Buffer.from(url)), 20000); + res.send(enc); + }, + + async decode({ query: { text } }, res) { + let url = Buffer.from( + bech32.fromWords(bech32.decode(text, 20000).words) + ).toString(); + + res.send(await got(url).json()); + }, + + async lnurlp({ params: { username } }, res) { + let uid = await g(`user:${username}`); + if (!uid) fail("user not found"); + + let id = v4(); + await s(`lnurl:${id}`, uid); + let { URL } = process.env; + let host = URL.split("/").at(-1); + + res.send({ + metadata: [ + ["text/plain", `Paying ${username}@${host}`], + ["text/identifier", `${username}@${host}`] + ], + callback: `${URL}/lnurl/${id}`, + tag: "payRequest" + }); + }, + + async lnurl({ params: { id }, query: { amount } }, res) { + let pr = await g(`lnurlp:${id}`); + + if (!pr) { + let uid = await g(`lnurl:${id}`); + let user = await g(`user:${uid}`); + + ({ text: pr } = await invoice({ + invoice: { + amount, + type: types.lightning + }, + user + })); + + await s(`lnurlp:${id}`, pr); + } + + res.send({ pr }); + } +}; diff --git a/routes/payments.js b/routes/payments.js index 53bb6e4d..b80d54f6 100644 --- a/routes/payments.js +++ b/routes/payments.js @@ -8,13 +8,12 @@ import { fail, btc, sats } from "$lib/utils"; import { requirePin } from "$lib/auth"; import { debit, credit, confirm, types } from "$lib/payments"; import { bech32 } from "bech32"; +import { invoice } from "$lib/invoices"; import got from "got"; import bc from "$lib/bitcoin"; import ln from "$lib/ln"; -const { HOSTNAME: hostname } = process.env; - export default { async create({ body, user }, res) { let { amount, hash, maxfee, name, memo, payreq, tip } = body; @@ -227,7 +226,6 @@ export default { let r = await got(url).json(); if (r.tag !== "payRequest") fail("not an ln address"); let enc = bech32.encode("lnurl", bech32.toWords(Buffer.from(url)), 20000); - console.log(enc); res.send(enc); }, @@ -239,13 +237,43 @@ export default { res.send(await got(url).json()); }, - async lnurl({ params: { code }, query: { amount } }, res) { - let { uid } = await g(`code:${code}`); + async lnurlp({ params: { username } }, res) { + let uid = await g(`user:${username}`); + if (!uid) fail("user not found"); - let url = Buffer.from( - bech32.fromWords(bech32.decode(text, 20000).words) - ).toString(); + let id = v4(); + await s(`lnurl:${id}`, uid); + let { URL } = process.env; + let host = URL.split("/").at(-1); - res.send(await got(url).json()); + res.send({ + metadata: [ + ["text/plain", `Paying ${username}@${host}`], + ["text/identifier", `${username}@${host}`] + ], + callback: `${host}/lnurl/${id}`, + tag: "payRequest" + }); + }, + + async lnurl({ params: { id }, query: { amount } }, res) { + let pr = await g(`lnurlp:${id}`); + + if (!pr) { + let uid = await g(`lnurl:${id}`); + let user = await g(`user:${uid}`); + + ({ text: pr } = await invoice({ + invoice: { + amount, + type: types.lightning + }, + user + })); + + await s(`lnurlp:${id}`, pr); + } + + res.send({ pr }); } }; |
