diff options
| -rw-r--r-- | routes/bitcoin/fee.js | 6 | ||||
| -rw-r--r-- | routes/lightning/query.js | 20 | ||||
| -rw-r--r-- | routes/lightning/send.js | 21 | ||||
| -rw-r--r-- | routes/liquid/fee.js | 6 | ||||
| -rw-r--r-- | routes/payments.js | 2 | ||||
| -rw-r--r-- | routes/send.js | 120 |
6 files changed, 163 insertions, 12 deletions
diff --git a/routes/bitcoin/fee.js b/routes/bitcoin/fee.js index ba24c4bf..fab17307 100644 --- a/routes/bitcoin/fee.js +++ b/routes/bitcoin/fee.js @@ -3,6 +3,12 @@ module.exports = async (req, res) => { let { address, amount, feeRate } = req.body; let tx, fee; + let recipient = await db.User.findOne({ + where: { address } + }); + if (recipient) + emit(user.username, "to", recipient); + try { amount = parseInt(amount); diff --git a/routes/lightning/query.js b/routes/lightning/query.js index 48af8b8e..6e70f30a 100644 --- a/routes/lightning/query.js +++ b/routes/lightning/query.js @@ -4,9 +4,25 @@ module.exports = async (req, res) => { let { amount, payreq } = req.body; try { + let invoice = await db.Invoice.findOne({ + where: { text: payreq }, + include: { + model: db.User, + as: "user" + } + }); + + if (invoice) emit(req.user.username, "to", invoice.user); + payreq = bolt11.decode(payreq); - res.send(await lna.queryRoutes({ pub_key: payreq.payeeNodeKey, amt: amount || payreq.satoshis })); + + res.send( + await lna.queryRoutes({ + pub_key: payreq.payeeNodeKey, + amt: amount || payreq.satoshis + }) + ); } catch (e) { res.status(500).send(e.message); - } + } }; diff --git a/routes/lightning/send.js b/routes/lightning/send.js index 9141bc1d..2c17ba1f 100644 --- a/routes/lightning/send.js +++ b/routes/lightning/send.js @@ -32,10 +32,14 @@ module.exports = async (req, res) => { let m = await lna.sendPaymentSync({ amt: amount, - payment_request: hash + payment_request: hash, + max_parts: 10, }); - if (m.payment_error) return res.status(500).send(m.payment_error); + if (m.payment_error) { + l.error("error sending lightning", m.payment_hash.toString('hex'), m.payment_error); + return res.status(500).send(m.payment_error); + } if (seen.includes(m.payment_preimage)) { l.warn("duplicate payment detected", m.payment_preimage); @@ -69,15 +73,12 @@ module.exports = async (req, res) => { user = await getUser(user.username, transaction); emit(user.username, "user", user); + l.info(config.lnb.id, payreq.payeeNodeKey); if (payreq.payeeNodeKey === config.lnb.id) { - lna.addInvoice({ value: amount }, (err, invoice) => { - let payback = lnb.sendPayment(lnb.meta, {}); - - /* eslint-disable-next-line */ - let { payment_request } = invoice; - /* eslint-disable-next-line */ - payback.write({ payment_request }); - }); + let invoice = await lna.addInvoice({ value: amount }) + let { payment_request } = invoice; + await lnb.sendPaymentSync({ payment_request, max_parts: 10 }); + l.info("lnb sending back", amount); } seen.push(hash); diff --git a/routes/liquid/fee.js b/routes/liquid/fee.js index 56ec7aa1..d041a5e2 100644 --- a/routes/liquid/fee.js +++ b/routes/liquid/fee.js @@ -3,6 +3,12 @@ module.exports = async (req, res) => { let { address, asset, amount, feeRate } = req.body; let tx, fee; + let recipient = await db.User.findOne({ + where: { confidential: address } + }); + if (recipient) + emit(user.username, "to", recipient); + try { amount = parseInt(amount); diff --git a/routes/payments.js b/routes/payments.js index 0e829029..4089ae23 100644 --- a/routes/payments.js +++ b/routes/payments.js @@ -22,6 +22,8 @@ const { Op } = require("sequelize"); attributes: ["hash"] })).map(p => p.hash); + app.post("/send", auth, require("./send")); + app.post("/lightning/invoice", auth, require("./lightning/invoice")); app.post("/lightning/query", auth, require("./lightning/query")); app.post("/lightning/send", auth, require("./lightning/send")); diff --git a/routes/send.js b/routes/send.js new file mode 100644 index 00000000..89e2034b --- /dev/null +++ b/routes/send.js @@ -0,0 +1,120 @@ +const axios = require("axios"); + +module.exports = async (req, res) => { + let { amount, asset, username } = req.body; + let { user } = req; + + l.info("attempting internal payment", user.username, amount); + + try { + await db.transaction(async transaction => { + let account = await db.Account.findOne({ + where: { + user_id: user.id, + asset + }, + lock: transaction.LOCK.UPDATE, + transaction + }); + + if (account.balance < amount) { + throw new Error("Insufficient funds"); + } + + let fee = 0; + + account.balance -= amount; + await account.save({ transaction }); + + let payment = await db.Payment.create( + { + amount: -amount, + account_id: account.id, + user_id: user.id, + rate: app.get("rates")[user.currency], + currency: user.currency, + confirmed: true, + hash: "Internal Transfer", + network: "COINOS" + }, + { transaction } + ); + + payment = payment.get({ plain: true }); + payment.account = account.get({ plain: true }); + + l.info("sent internal", user.username, -payment.amount); + + user = await getUser(user.username, transaction); + emit(user.username, "user", user); + res.send(payment); + + user = await db.User.findOne({ + where: { username } + }); + + let params = { + user_id: user.id, + asset + }; + + account = await db.Account.findOne({ + where: params, + lock: transaction.LOCK.UPDATE, + transaction + }); + + if (account) { + account.balance += amount; + await account.save({ transaction }); + } else { + let name = asset.substr(0, 6); + let ticker = asset.substr(0, 3).toUpperCase(); + let precision = 8; + + const assets = (await axios.get("https://assets.blockstream.info/")).data; + + if (assets[asset]) { + ({ticker, precision, name } = assets[asset]); + } + + params = { ...params, ...{ ticker, precision, name } }; + params.balance = amount; + params.pending = 0; + account = await db.Account.create(params, { transaction }); + } + + payment = await db.Payment.create( + { + amount, + account_id: account.id, + user_id: user.id, + rate: app.get("rates")[user.currency], + currency: user.currency, + confirmed: true, + hash: "Internal Transfer", + network: "COINOS", + received: true, + }, + { transaction } + ); + + user = await getUser(user.username, transaction); + emit(user.username, "user", user); + + payment = payment.get({ plain: true }); + payment.account = account.get({ plain: true }); + emit(user.username, "payment", payment); + + l.info("received internal", user.username, payment.amount); + }); + } catch (e) { + l.error( + "problem sending internal payment", + user.username, + user.balance, + e.message + ); + return res.status(500).send(e.message); + } +}; |
