aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAdam Soltys <[email protected]>2021-09-30 20:07:26 -0400
committerAdam Soltys <[email protected]>2021-09-30 20:07:26 -0400
commitcd33441e024317cbd89b19d6a04a140733216173 (patch)
treefb51fea9f3610ec6c27fcaeb6930a16e951ca05b
parenta85ed1615e04336ef1e0fea22cb0ee8fd3c99fef (diff)
downloadcoinos-server-cd33441e024317cbd89b19d6a04a140733216173.tar.gz
coinos-server-cd33441e024317cbd89b19d6a04a140733216173.zip
re-enable lnurl
-rw-r--r--routes/lnurl.js339
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);
+ }
}
);