aboutsummaryrefslogtreecommitdiffstats
path: root/routes/lightning
diff options
context:
space:
mode:
authorAdam Soltys <[email protected]>2020-03-11 15:10:40 -0700
committerAdam Soltys <[email protected]>2020-03-11 15:10:40 -0700
commitc0888fab024cc9f7c99812bfabf9d7774312dbf7 (patch)
treecad95683af97432f6092a2c2bae10fbb7a588db5 /routes/lightning
parentbf2b51f0c2ae9b8f0f330dde6411e45fc0da8a25 (diff)
downloadcoinos-server-c0888fab024cc9f7c99812bfabf9d7774312dbf7.tar.gz
coinos-server-c0888fab024cc9f7c99812bfabf9d7774312dbf7.zip
refactor
Diffstat (limited to 'routes/lightning')
-rw-r--r--routes/lightning/invoice.js27
-rw-r--r--routes/lightning/query.js7
-rw-r--r--routes/lightning/receive.js36
-rw-r--r--routes/lightning/send.js93
-rw-r--r--routes/lightning/user.js46
5 files changed, 209 insertions, 0 deletions
diff --git a/routes/lightning/invoice.js b/routes/lightning/invoice.js
new file mode 100644
index 00000000..59f0df47
--- /dev/null
+++ b/routes/lightning/invoice.js
@@ -0,0 +1,27 @@
+module.exports = async (req, res) => {
+ let err = m => res.status(500).send(m);
+ let { amount, address, tip } = req.body;
+
+ let invoice;
+ try {
+ invoice = await lnb.addInvoice({ value: amount });
+ } catch (e) {
+ return err(e.message);
+ }
+
+ let hash = invoice.payment_request;
+ if (address) hash = address;
+
+ await db.Payment.create({
+ user_id: req.user.id,
+ hash,
+ amount,
+ currency: "CAD",
+ rate: app.get("rates")[req.user.currency],
+ tip,
+ confirmed: 1,
+ asset: 'LNBTC',
+ });
+
+ res.send(invoice);
+};
diff --git a/routes/lightning/query.js b/routes/lightning/query.js
new file mode 100644
index 00000000..8e25293c
--- /dev/null
+++ b/routes/lightning/query.js
@@ -0,0 +1,7 @@
+const bolt11 = require("bolt11");
+
+module.exports = async (req, res) => {
+ let hash = req.body.payreq;
+ let payreq = bolt11.decode(hash);
+ res.send(await lna.queryRoutes({ pub_key: payreq.payeeNodeKey, amt: payreq.satoshis }));
+};
diff --git a/routes/lightning/receive.js b/routes/lightning/receive.js
new file mode 100644
index 00000000..6befc7a3
--- /dev/null
+++ b/routes/lightning/receive.js
@@ -0,0 +1,36 @@
+module.exports = {
+ const handlePayment = async msg => {
+ if (!msg.settled) return;
+
+ let payment = await db.Payment.findOne({
+ include: { model: db.User, as: "user" },
+ where: {
+ hash: msg.payment_request
+ }
+ });
+
+ if (!payment) return;
+
+ const { user } = payment;
+
+ payment.received = true;
+ user.balance += parseInt(msg.value);
+ payment.rate = app.get("rates")[user.currency];
+ payment.confirmed = true;
+ payment.currency = user.currency;
+
+ await payment.save();
+ await user.save();
+ payments.push(msg.payment_request);
+ l.info("lightning payment received", user.username, payment.amount);
+
+ emit(user.username, "payment", payment);
+ emit(user.username, "user", user);
+ };
+
+ const invoices = lna.subscribeInvoices({});
+ invoices.on("data", handlePayment);
+
+ const invoicesb = lnb.subscribeInvoices({});
+ invoicesb.on("data", handlePayment);
+};
diff --git a/routes/lightning/send.js b/routes/lightning/send.js
new file mode 100644
index 00000000..2b661b60
--- /dev/null
+++ b/routes/lightning/send.js
@@ -0,0 +1,93 @@
+const bolt11 = require("bolt11");
+
+module.exports = async (req, res) => {
+ let hash = req.body.payreq;
+ let payreq = bolt11.decode(hash);
+ let { route } = req.body;
+ let { user } = req;
+
+ if (seen.includes(hash)) {
+ l.warn("attempted to pay a paid invoice", user.username);
+ return res.status(500).send("Invoice has been paid, can't pay again");
+ }
+
+ try {
+ await db.transaction(async transaction => {
+ let { balance } = await db.User.findOne(
+ {
+ where: {
+ username: user.username
+ }
+ },
+ { transaction }
+ );
+
+ if (balance < payreq.satoshis) {
+ throw new Error("insufficient funds");
+ }
+
+ user.balance -= payreq.satoshis;
+ await user.save({ transaction });
+ });
+ } catch (e) {
+ l.warn("insufficient funds for lightning payment", e);
+ return res.status(500).send("Not enough satoshis");
+ }
+
+ let m;
+ try {
+ let paymentHash = payreq.tags.find(t => t.tagName === 'payment_hash').data;
+ m = await lna.sendToRouteSync({
+ "payment_hash": Buffer.from(paymentHash, 'hex'),
+ route
+ });
+
+ if (m.payment_error) return res.status(500).send(m.payment_error);
+ if (seen.includes(m.payment_preimage)) return;
+ seen.push(m.payment_preimage);
+
+ let total = parseInt(m.payment_route.total_amt);
+ let fee = m.payment_route.total_fees;
+
+ user.balance -= total - payreq.satoshis;
+
+ await db.transaction(async transaction => {
+ await user.save({ transaction });
+
+ const payment = await db.Payment.create(
+ {
+ amount: -total,
+ fee,
+ user_id: user.id,
+ hash,
+ rate: app.get("rates")[user.currency],
+ currency: user.currency,
+ confirmed: true,
+ asset: 'LNBTC',
+ },
+ { transaction }
+ );
+
+ l.info("sent lightning", user.username, -payment.amount);
+ emit(user.username, "payment", payment);
+ emit(user.username, "user", user);
+
+ if (payreq.payeeNodeKey === config.lnb.id) {
+ lna.addInvoice({ value: payreq.satoshis }, (err, invoice) => {
+ let payback = lnb.sendPayment(lnb.meta, {});
+
+ /* eslint-disable-next-line */
+ let { payment_request } = invoice;
+ /* eslint-disable-next-line */
+ payback.write({ payment_request });
+ });
+ }
+
+ seen.push(hash);
+ res.send(payment);
+ });
+ } catch (e) {
+ l.info("error sending lightning", e);
+ return res.status(500).send(e);
+ }
+};
diff --git a/routes/lightning/user.js b/routes/lightning/user.js
new file mode 100644
index 00000000..c361600c
--- /dev/null
+++ b/routes/lightning/user.js
@@ -0,0 +1,46 @@
+const bolt11 = require("bolt11");
+
+module.exports = async (req, res) => {
+ let { payuser, amount } = req.body;
+
+ let user = await db.User.findOne({
+ where: {
+ username: payuser
+ }
+ });
+
+ if (!user) {
+ return res.status(500).send("Couldn't find the user you're trying to pay");
+ }
+ let err = m => res.status(500).send(m);
+
+ let invoice;
+ try {
+ invoice = await lnb.addInvoice({ value: amount });
+ } catch (e) {
+ return err(e.message);
+ }
+
+ let hash = invoice.payment_request;
+
+ await db.Payment.create({
+ user_id: user.id,
+ hash,
+ amount,
+ rate: app.get("rates")[req.user.currency],
+ currency: req.user.currency,
+ tip: 0,
+ confirmed: true,
+ received: false,
+ asset: 'LNBTC',
+ });
+
+ req.url = "/sendPayment";
+ let payreq = bolt11.decode(hash);
+ const { routes } = await lna.queryRoutes({ "pub_key": payreq.payeeNodeKey, "amt": payreq.satoshis });
+ if (routes.length) req.body.route = routes[0];
+ else return res.status(500).send("No route available");
+ req.body.payreq = hash;
+
+ return app._router.handle(req, res);
+};