diff options
| author | Adam Soltys <[email protected]> | 2020-03-11 15:10:40 -0700 |
|---|---|---|
| committer | Adam Soltys <[email protected]> | 2020-03-11 15:10:40 -0700 |
| commit | c0888fab024cc9f7c99812bfabf9d7774312dbf7 (patch) | |
| tree | cad95683af97432f6092a2c2bae10fbb7a588db5 /routes/lightning | |
| parent | bf2b51f0c2ae9b8f0f330dde6411e45fc0da8a25 (diff) | |
| download | coinos-server-c0888fab024cc9f7c99812bfabf9d7774312dbf7.tar.gz coinos-server-c0888fab024cc9f7c99812bfabf9d7774312dbf7.zip | |
refactor
Diffstat (limited to 'routes/lightning')
| -rw-r--r-- | routes/lightning/invoice.js | 27 | ||||
| -rw-r--r-- | routes/lightning/query.js | 7 | ||||
| -rw-r--r-- | routes/lightning/receive.js | 36 | ||||
| -rw-r--r-- | routes/lightning/send.js | 93 | ||||
| -rw-r--r-- | routes/lightning/user.js | 46 |
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); +}; |
