diff options
| author | Adam Soltys <[email protected]> | 2021-09-30 20:07:26 -0400 |
|---|---|---|
| committer | Adam Soltys <[email protected]> | 2021-09-30 20:07:26 -0400 |
| commit | cd33441e024317cbd89b19d6a04a140733216173 (patch) | |
| tree | fb51fea9f3610ec6c27fcaeb6930a16e951ca05b | |
| parent | a85ed1615e04336ef1e0fea22cb0ee8fd3c99fef (diff) | |
| download | coinos-server-cd33441e024317cbd89b19d6a04a140733216173.tar.gz coinos-server-cd33441e024317cbd89b19d6a04a140733216173.zip | |
re-enable lnurl
| -rw-r--r-- | routes/lnurl.js | 339 |
1 files changed, 182 insertions, 157 deletions
diff --git a/routes/lnurl.js b/routes/lnurl.js index b07aeeab..99e4fad3 100644 --- a/routes/lnurl.js +++ b/routes/lnurl.js @@ -4,10 +4,10 @@ const jwt = require("jsonwebtoken"); const qs = require("query-string"); const persist = require("../lib/persist"); -logins = persist('data/logins.json'); -recipients = persist('data/recipients.json'); -payments = persist('data/payments.json'); -withdrawals = persist('data/withdrawals.json'); +logins = persist("data/logins.json"); +recipients = persist("data/recipients.json"); +payments = persist("data/payments.json"); +withdrawals = persist("data/withdrawals.json"); lnurlServer = lnurl.createServer(config.lnurl); @@ -117,20 +117,21 @@ app.post( app.get( "/lnurlp/:username", ah(async (req, res, next) => { - throw new Error("LNURL payments temporarily disabled due to a server issue. Sep. 2, 2021. Join our Telegram channel https://t.me/coinoswallet for updates"); - const { username } = req.params; - let user = await db.User.findOne({ - where: { - username - } - }); + try { + const { username } = req.params; + let user = await db.User.findOne({ + where: { + username + } + }); - let { amount, minSendable, maxSendable } = req.query; - minSendable = minSendable || 1000; - maxSendable = maxSendable || 1000000000; - if (parseInt(amount)) minSendable = maxSendable = amount * 1000; + if (!user) throw new Error("user not found"); + + let { amount, minSendable, maxSendable } = req.query; + minSendable = minSendable || 1000; + maxSendable = maxSendable || 1000000000; + if (parseInt(amount)) minSendable = maxSendable = amount * 1000; - try { let result = await lnurlServer.generateNewUrl("payRequest", { minSendable, maxSendable, @@ -153,7 +154,6 @@ app.get( app.get( "/pay/:username", ah(async (req, res, next) => { - throw new Error("LNURL payments temporarily disabled due to a server issue. Sep. 2, 2021. Join our Telegram channel https://t.me/coinoswallet for updates"); const { username } = req.params; let user = await db.User.findOne({ where: { @@ -187,7 +187,6 @@ app.post( "/pay", auth, ah(async (req, res, next) => { - throw new Error("LNURL payments temporarily disabled due to a server issue. Sep. 2, 2021. Join our Telegram channel https://t.me/coinoswallet for updates"); const { user } = req; const { amount, @@ -284,175 +283,201 @@ app.get( lnurlServer.bindToHook( "middleware:signedLnurl:afterCheckSignature", async (req, res, next) => { - let user; - const { amount: msats, key, tag, pr, k1 } = req.query; + try { + let user; + const { amount: msats, key, tag, pr, k1 } = req.query; - if (msats) { - amount = Math.round(msats / 1000); - const parts = req.originalUrl.split("/"); - const secret = parts[parts.length - 1].split("?")[0]; - user = payments[secret]; + if (msats) { + amount = Math.round(msats / 1000); + const parts = req.originalUrl.split("/"); + const secret = parts[parts.length - 1].split("?")[0]; + user = payments[secret]; - if (user) { - let account = await db.Account.findOne({ - where: { - user_id: user.id, - asset: config.liquid.btcasset, - pubkey: null - } - }); + if (user) { + let account = await db.Account.findOne({ + where: { + user_id: user.id, + asset: config.liquid.btcasset, + pubkey: null + } + }); - if (account.balance < amount) { - throw new Error("Insufficient funds"); + if (account.balance < amount) { + throw new Error("Insufficient funds"); + } } - } - const recipient = recipients[secret]; + const recipient = recipients[secret]; + l.info("lnurl recipient", recipient.username); - if (recipient) { - setTimeout(async () => { - let { invoices } = await lnp.listInvoices({ - pending_only: true - }); + if (recipient) { + setTimeout(async () => { + try { + let result = await lnp.listInvoices({ + num_max_invoices: 5, + reversed: true + }); + let { invoices } = result; - if (invoices.length) { - let invoice = await db.Invoice.create({ - user_id: recipient.id, - text: invoices[invoices.length - 1].payment_request, - rate: app.get("rates")[recipient.currency], - currency: recipient.currency, - amount, - tip: 0, - network: "lightning" - }); - l.info("invoice created", invoice.text, invoice.amount); - } - }, 100); - } - } + if (invoices.length) { + let existing = []; + existing = await db.Invoice.findAll({ + attributes: ["text"], + where: { + text: invoices.map(i => i.payment_request) + } + }); - if (tag === "login") { - let username = logins[k1]; + let candidates = invoices.filter( + i => !existing.map(e => e.text).includes(i.payment_request) + ); - if (!username) { - const keyObj = await db.Key.findOne({ - where: { hex: key }, - include: [ - { - model: db.User, - as: "user" - } - ] - }); + if (candidates.length) { + let invoice = await db.Invoice.create({ + user_id: recipient.id, + text: candidates[candidates.length - 1].payment_request, + rate: app.get("rates")[recipient.currency], + currency: recipient.currency, + amount, + tip: 0, + network: "lightning" + }); - if (keyObj) ({ user } = keyObj); + l.info("invoice created", invoice.text, invoice.amount); + } + } + } catch (e) { + l.error("problem finding lnurl invoice", e.message); + } + }, 2000); + } + } - if (!user) { - let ip = - req.headers["x-forwarded-for"] || req.connection.remoteAddress; + if (tag === "login") { + let username = logins[k1]; - let username = `satoshi-${key.substr(0, 12)}`; - let existing = await db.User.findOne({ where: { username } }); - if (existing) user = existing; - else { - user = await register( + if (!username) { + const keyObj = await db.Key.findOne({ + where: { hex: key }, + include: [ { - username, - password: key - }, - ip - ); + model: db.User, + as: "user" + } + ] + }); + + if (keyObj) ({ user } = keyObj); + + if (!user) { + let ip = + req.headers["x-forwarded-for"] || req.connection.remoteAddress; + + let username = `satoshi-${key.substr(0, 12)}`; + let existing = await db.User.findOne({ where: { username } }); + if (existing) user = existing; + else { + user = await register( + { + username, + password: key + }, + ip + ); + } } + + ({ username } = user); } - ({ username } = user); + logins[key] = { k1, username }; } - logins[key] = { k1, username }; - } - - if (pr) { - user = withdrawals[k1]; - if (!user) { - if (next) next(new Error("withdrawal not found")); - return; - } + if (pr) { + user = withdrawals[k1]; + if (!user) { + if (next) next(new Error("withdrawal not found")); + return; + } - try { - let decoded = await lnp.decodePayReq({ pay_req: pr }); - let amount = decoded.num_satoshis; + try { + let decoded = await lnp.decodePayReq({ pay_req: pr }); + let amount = decoded.num_satoshis; - await db.transaction(async transaction => { - let account = await db.Account.findOne({ - where: { - user_id: user.id, - asset: config.liquid.btcasset - }, - lock: transaction.LOCK.UPDATE, - transaction - }); + await db.transaction(async transaction => { + let account = await db.Account.findOne({ + where: { + user_id: user.id, + asset: config.liquid.btcasset + }, + lock: transaction.LOCK.UPDATE, + transaction + }); - if (account.balance < amount) { - throw new Error("Insufficient funds"); - } + if (account.balance < amount) { + throw new Error("Insufficient funds"); + } - let payment = await db.Payment.create( - { - amount: -amount, - account_id: account.id, - user_id: user.id, - hash: pr, - rate: app.get("rates")[user.currency], - currency: user.currency, - confirmed: true, - network: "lightning" - }, - { transaction } - ); + let payment = await db.Payment.create( + { + amount: -amount, + account_id: account.id, + user_id: user.id, + hash: pr, + rate: app.get("rates")[user.currency], + currency: user.currency, + confirmed: true, + network: "lightning" + }, + { transaction } + ); - setTimeout(async () => { - try { - let { payments } = await lnp.listPayments({ - include_incomplete: false, - max_payments: 5, - reversed: true - }); + setTimeout(async () => { + try { + let { payments } = await lnp.listPayments({ + include_incomplete: false, + max_payments: 5, + reversed: true + }); - let p = payments.find(p => p.payment_request === pr); - if (p) { - l.info("found payment", pr); - payment.fee = p.fee; - await account.decrement({ balance: p.fee }, { transaction }); - await account.reload({ transaction }); - await payment.save(); - payment = payment.get({ plain: true }); - payment.account = account.get({ plain: true }); - emit(user.username, "account", account); - emit(user.username, "payment", payment); - } else { - l.warn("payment not found, fee not set", pr); + let p = payments.find(p => p.payment_request === pr); + if (p) { + l.info("found payment", pr); + payment.fee = p.fee; + await account.decrement({ balance: p.fee }, { transaction }); + await account.reload({ transaction }); + await payment.save(); + payment = payment.get({ plain: true }); + payment.account = account.get({ plain: true }); + emit(user.username, "account", account); + emit(user.username, "payment", payment); + } else { + l.warn("payment not found, fee not set", pr); + } + } catch (e) { + l.error("problem trying to get ln withdrawal payment", e); } - } catch (e) { - l.error("problem trying to get ln withdrawal payment", e); - } - }, 1000); + }, 1000); - await account.decrement({ balance: amount }, { transaction }); - await account.reload({ transaction }); + await account.decrement({ balance: amount }, { transaction }); + await account.reload({ transaction }); - let p = payment.get({ plain: true }); - p.account = account.get({ plain: true }); + let p = payment.get({ plain: true }); + p.account = account.get({ plain: true }); - emit(user.username, "account", p.account); - emit(user.username, "payment", p); - }); - } catch (e) { - l.error("failed to process withdrawal", e.message); - return next(e); + emit(user.username, "account", p.account); + emit(user.username, "payment", p); + }); + } catch (e) { + l.error("failed to process withdrawal", e.message); + return next(e); + } } - } - if (next) next(req, res); + if (next) next(req, res); + } catch (e) { + l.error("unhandled lnurl error", e.message); + } } ); |
