diff options
| author | Adam Soltys <[email protected]> | 2020-04-28 22:09:22 -0700 |
|---|---|---|
| committer | Adam Soltys <[email protected]> | 2020-04-28 22:33:02 -0700 |
| commit | 63c18105e6c66b3b4698c398f356bef1b496816f (patch) | |
| tree | e7ee85e7c3502ed81954448a76be028143990948 | |
| parent | 994dd93f6c45c590ae59a699cbf425d96518da1e (diff) | |
| download | coinos-server-63c18105e6c66b3b4698c398f356bef1b496816f.tar.gz coinos-server-63c18105e6c66b3b4698c398f356bef1b496816f.zip | |
include account in emitted payments objects
| -rw-r--r-- | lib/utils.js | 12 | ||||
| -rw-r--r-- | routes/bitcoin/receive.js | 11 | ||||
| -rw-r--r-- | routes/bitcoin/send.js | 82 | ||||
| -rw-r--r-- | routes/lightning/receive.js | 4 | ||||
| -rw-r--r-- | routes/lightning/send.js | 8 | ||||
| -rw-r--r-- | routes/liquid/fee.js | 2 | ||||
| -rw-r--r-- | routes/liquid/receive.js | 21 | ||||
| -rw-r--r-- | routes/liquid/send.js | 105 | ||||
| -rw-r--r-- | routes/users.js | 8 |
9 files changed, 143 insertions, 110 deletions
diff --git a/lib/utils.js b/lib/utils.js index 98409efc..a861f8b7 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -30,7 +30,11 @@ getUser = async username => { } } }, - limit: 12 + limit: 12, + include: { + model: db.Account, + as: "account" + } }); return user; @@ -65,7 +69,11 @@ getUserById = async id => { } } }, - limit: 12 + limit: 12, + include: { + model: db.Account, + as: "account" + } }); return user; diff --git a/routes/bitcoin/receive.js b/routes/bitcoin/receive.js index acc80b09..deded625 100644 --- a/routes/bitcoin/receive.js +++ b/routes/bitcoin/receive.js @@ -70,12 +70,10 @@ zmqRawTx.on("message", async (topic, message, sequence) => { user.address = await bc.getNewAddress("", "bech32"); await user.save(); - user = await getUser(user.username); - emit(user.username, "user", user); addresses[user.address] = user.username; - const payment = await db.Payment.create({ + let payment = await db.Payment.create({ account_id: account.id, user_id: user.id, hash, @@ -88,9 +86,13 @@ zmqRawTx.on("message", async (topic, message, sequence) => { address, network: "BTC" }); + payment = payment.get({ plain: true }); + payment.account = account.get({ plain: true }); - l.info("bitcoin detected", user.username, o.value); + user = await getUser(user.username); emit(user.username, "payment", payment); + emit(user.username, "user", user); + l.info("bitcoin detected", user.username, o.value); } }) ); @@ -135,6 +137,7 @@ setInterval(async () => { let user = await getUserById(p.user_id); emit(user.username, "user", user); + emit(user.username, "payment", p); l.info("bitcoin confirmed", user.username, p.amount, p.tip); delete queue[hash]; } else { diff --git a/routes/bitcoin/send.js b/routes/bitcoin/send.js index e7cba943..42027f71 100644 --- a/routes/bitcoin/send.js +++ b/routes/bitcoin/send.js @@ -8,10 +8,9 @@ module.exports = async (req, res) => { let fee = toSats(tx.fee); - const isChange = async address => - (await bc.getAddressInfo(address)).ismine && ( - !Object.keys(addresses).includes(address) || - address === user.address); + const isChange = async address => + (await bc.getAddressInfo(address)).ismine && + (!Object.keys(addresses).includes(address) || address === user.address); tx = await bc.decodeRawTransaction(hex); @@ -21,40 +20,55 @@ module.exports = async (req, res) => { for (let i = 0; i < tx.vout.length; i++) { let o = tx.vout[i]; total += toSats(o.value); - + if (o.scriptPubKey.addresses) { - if ((await isChange(o.scriptPubKey.addresses[0]))) { + if (await isChange(o.scriptPubKey.addresses[0])) { change += toSats(o.value); } } - } + } - total = (total - change) + fee; + total = total - change + fee; let amount = total - fee; - l.info("attempting bitcoin payment", user.username, amount, fee); + l.info("attempting bitcoin payment", user.username, total, change, amount, fee); + let account, params; try { await db.transaction(async transaction => { - let { balance } = await db.User.findOne({ + account = await db.Account.findOne({ where: { - username: user.username + user_id: user.id, + asset: config.liquid.btcasset }, lock: transaction.LOCK.UPDATE, transaction }); - if (amount !== balance && total > balance) { + if (total > account.balance) { l.error("amount exceeds balance", amount, fee, balance); throw new Error("insufficient funds"); } - user.balance -= total; - await user.save({ transaction }); + account.balance -= total; + await account.save({ transaction }); + + params = { + amount: -total, + fee, + account_id: account.id, + user_id: user.id, + rate: app.get("rates")[user.currency], + currency: user.currency, + address, + confirmed: true, + received: false, + network: "BTC" + }; }); } catch (e) { - l.warn("insufficient funds for bitcoin payment", user.username); - return res.status(500).send("Not enough satoshis"); + l.error("problem creating bitcoin payment", user.username, e.message); + return res.status(500).send(e.message); } try { @@ -62,37 +76,17 @@ module.exports = async (req, res) => { await bc.walletPassphrase(config.bitcoin.walletpass, 300); hex = (await bc.signRawTransactionWithWallet(hex)).hex; - let txid = await bc.sendRawTransaction(hex); + params.hash = await bc.sendRawTransaction(hex); - await db.transaction(async transaction => { - await user.save({ transaction }); - user = await getUser(user.username); + let payment = await db.Payment.create(params); - const payment = await db.Payment.create( - { - amount: -total, - fee, - account_id: user.account.id, - user_id: user.id, - hash: txid, - rate: app.get("rates")[user.currency], - currency: user.currency, - address, - confirmed: true, - received: false, - network: "BTC" - }, - { transaction } - ); - - user = await getUser(user.username); - emit(user.username, "payment", payment); - emit(user.username, "user", user); + user = await getUser(user.username); + emit(user.username, "user", user); - res.send(payment); - - l.info("sent bitcoin", user.username, total); - }); + payment = payment.get({ plain: true }); + payment.account = account.get({ plain: true }); + res.send(payment); + l.info("sent bitcoin", user.username, total); } catch (e) { l.error("error sending bitcoin", e.message); return res.status(500).send(e.message); diff --git a/routes/lightning/receive.js b/routes/lightning/receive.js index 0805c878..97fe07dc 100644 --- a/routes/lightning/receive.js +++ b/routes/lightning/receive.js @@ -21,7 +21,7 @@ const handlePayment = async msg => { } }); - const payment = await db.Payment.create({ + let payment = await db.Payment.create({ account_id: account.id, user_id, hash, @@ -44,6 +44,8 @@ const handlePayment = async msg => { let user = await getUserById(user_id) + payment = payment.get({ plain: true }); + payment.account = account.get({ plain: true }); emit(user.username, "payment", payment); emit(user.username, "user", user); diff --git a/routes/lightning/send.js b/routes/lightning/send.js index 02149aa8..6f21cc9b 100644 --- a/routes/lightning/send.js +++ b/routes/lightning/send.js @@ -67,7 +67,7 @@ module.exports = async (req, res) => { account.balance -= total - payreq.satoshis; await account.save() - const payment = await db.Payment.create({ + let payment = await db.Payment.create({ amount: -total, account_id: account.id, user_id: user.id, @@ -78,11 +78,13 @@ module.exports = async (req, res) => { network: "LNBTC" }); + payment = payment.get({ plain: true }); + payment.account = account.get({ plain: true }); + seen.push(m.payment_preimage); l.info("sent lightning", user.username, -payment.amount, m); user = await getUser(user.username); - emit(user.username, "payment", payment); emit(user.username, "user", user); if (payreq.payeeNodeKey === config.lnb.id) { @@ -99,7 +101,7 @@ module.exports = async (req, res) => { seen.push(hash); res.send(payment); } catch (e) { - l.info("error sending lightning", e); + l.info("error sending lightning", e.message); return res.status(500).send(e); } }; diff --git a/routes/liquid/fee.js b/routes/liquid/fee.js index 7a53a9b5..56ec7aa1 100644 --- a/routes/liquid/fee.js +++ b/routes/liquid/fee.js @@ -34,6 +34,8 @@ module.exports = async (req, res) => { decoded = await lq.decodeRawTransaction(signed.hex); feeRate = Math.round((tx.fee * SATS * 1000) / decoded.vsize); + l.info("estimated", asset); + res.send({ feeRate, tx }); } catch (e) { l.error("error estimating liquid fee", e); diff --git a/routes/liquid/receive.js b/routes/liquid/receive.js index 858cc0ed..fd280eb9 100644 --- a/routes/liquid/receive.js +++ b/routes/liquid/receive.js @@ -2,7 +2,7 @@ const axios = require("axios"); const reverse = require("buffer-reverse"); const zmq = require("zeromq"); const { Op } = require("sequelize"); -const bitcoin = require("elementsjs-lib"); +const elements = require("elementsjs-lib"); const zmqRawBlock = zmq.socket("sub"); zmqRawBlock.connect(config.liquid.zmqrawblock); @@ -42,7 +42,7 @@ zmqRawTx.on("message", async (topic, message, sequence) => { asset }; - const account = await db.Account.findOne({ + let account = await db.Account.findOne({ where: params }); @@ -51,7 +51,7 @@ zmqRawTx.on("message", async (topic, message, sequence) => { await account.save(); } else { let name = asset.substr(0, 6); - let ticker = asset.substr(0, 3); + let ticker = asset.substr(0, 3).toUpperCase(); let precision = 8; const assets = await axios.get("https://assets.blockstream.info/"); @@ -72,13 +72,9 @@ zmqRawTx.on("message", async (topic, message, sequence) => { )).unconfidential; await user.save(); - user = await getUser(user.username); - emit(user.username, "user", user); addresses[user.liquid] = user.username; - l.info("account", account.id); - let invoice; if (asset === config.liquid.btcasset) { invoice = await db.Invoice.findOne({ @@ -94,7 +90,7 @@ zmqRawTx.on("message", async (topic, message, sequence) => { const rate = invoice ? invoice.rate : app.get("rates")[user.currency]; const tip = invoice ? invoice.tip : null; - const payment = await db.Payment.create({ + let payment = await db.Payment.create({ account_id: account.id, user_id: user.id, hash: blinded.txid, @@ -109,9 +105,13 @@ zmqRawTx.on("message", async (topic, message, sequence) => { }); payments.push(blinded.txid); + payment = payment.get({ plain: true }); + payment.account = account.get({ plain: true }); - l.info("liquid detected", user.username, asset, value); + user = await getUser(user.username); emit(user.username, "payment", payment); + emit(user.username, "user", user); + l.info("liquid detected", user.username, asset, value); } }) ); @@ -126,7 +126,7 @@ zmqRawBlock.on("message", async (topic, message, sequence) => { const hashes = payments.map(p => p.hash); - const block = bitcoin.Block.fromHex(message.toString("hex"), true); + const block = elements.Block.fromHex(message.toString("hex"), true); const hash = await lq.getBlockHash(block.height); const json = await lq.getBlock(hash, 2); @@ -158,6 +158,7 @@ setInterval(async () => { let user = await getUserById(p.user_id); emit(user.username, "user", user); + emit(user.username, "payment", p); l.info("liquid confirmed", user.username, p.asset, p.amount, p.tip); delete queue[hash]; diff --git a/routes/liquid/send.js b/routes/liquid/send.js index 461b0c0a..4d8b8d4c 100644 --- a/routes/liquid/send.js +++ b/routes/liquid/send.js @@ -25,27 +25,32 @@ module.exports = async (req, res) => { scriptPubKey: { type, addresses } } = tx.vout[i]; - if (!totals[asset]) totals[asset] = change[asset] = 0; - totals[asset] += toSats(value); if (type === "fee") fee = toSats(value); + else { + if (!totals[asset]) totals[asset] = change[asset] = 0; + totals[asset] += toSats(value); - if (addresses) { - if (await isChange(addresses[0])) { - change[asset] += toSats(value); + if (addresses) { + if (await isChange(addresses[0])) { + change[asset] += toSats(value); + } } } } - let assets = Object.keys(totals); - for (let i = 0; i < assets.length; i++) { - let asset = assets[i]; - let total = totals[asset]; - if (change[asset]) total -= change[asset]; + const assets = Object.keys(totals); + const payments = []; + + try { + await db.transaction(async transaction => { + for (let i = 0; i < assets.length; i++) { + let asset = assets[i]; + let total = totals[asset]; + if (change[asset]) total -= change[asset]; + if (asset === config.liquid.btcasset) total += fee; - l.info("attempting liquid payment", user.username, asset, total, fee); + l.info("creating liquid payment", user.username, asset, total, fee); - try { - await db.transaction(async transaction => { let account = await db.Account.findOne({ where: { user_id: user.id, @@ -67,41 +72,53 @@ module.exports = async (req, res) => { account.balance -= total; await account.save({ transaction }); - try { - if (config.liquid.walletpass) - await lq.walletPassphrase(config.liquid.walletpass, 300); + let payment = { + amount: -total, + account_id: account.id, + fee, + user_id: user.id, + rate: app.get("rates")[user.currency], + currency: user.currency, + address, + confirmed: true, + received: false, + network: "LBTC" + }; - hex = await lq.blindRawTransaction(hex); - rawtx = (await lq.signRawTransactionWithWallet(hex)).hex; - let txid = await lq.sendRawTransaction(rawtx); + payment.account = account; + payments.push(payment); + } + }); + } catch (e) { + l.error("problem creating liquid payment", user.username, e.message); + return res.status(500).send(e.message); + } - const payment = await db.Payment.create({ - amount: -total, - account_id: account.id, - fee, - user_id: user.id, - hash: txid, - rate: app.get("rates")[user.currency], - currency: user.currency, - address, - confirmed: true, - received: false, - network: "LBTC" - }, { transaction }); + try { + if (config.liquid.walletpass) + await lq.walletPassphrase(config.liquid.walletpass, 300); - payment.account = account; + hex = await lq.blindRawTransaction(hex); + rawtx = (await lq.signRawTransactionWithWallet(hex)).hex; + let txid = await lq.sendRawTransaction(rawtx); - user = await getUser(user.username); - emit(user.username, "user", user); - res.send(payment); - } catch (e) { - l.error("liquid send failed", e); - return res.status(500).send(e.message); - } - }); - } catch (e) { - l.warn("insufficient funds for liquid payment", user.username, e.message); - return res.status(500).send("Not enough satoshis"); + let main; + for (let i = 0; i < assets.length; i++) { + p = payments[i]; + let { account } = p; + p.hash = txid; + p = await db.Payment.create(p); + if (account.ticker !== "BTC" || !main) { + main = p.get({ plain: true }); + main.account = account.get({ plain: true }); + } } + + user = await getUser(user.username); + emit(user.username, "user", user); + res.send(main); + } catch (e) { + l.error("problem sending liquid", user.username, e.message); + return res.status(500).send(e.message); } }; diff --git a/routes/users.js b/routes/users.js index d77cd8a0..9e2700b0 100644 --- a/routes/users.js +++ b/routes/users.js @@ -124,6 +124,9 @@ app.post("/register", async (req, res) => { asset: config.liquid.btcasset, balance: 0, pending: 0, + name: 'Bitcoin', + ticker: 'BTC', + precision: 8, }); user.accounts = [account]; @@ -131,9 +134,10 @@ app.post("/register", async (req, res) => { user.account_id = account.id; await user.save(); - - l.info("new user", user.username); + user = await getUser(user.username); res.send(pick(user, ...whitelist)); + emit(user.username, "user", user); + l.info("new user", user.username); }); app.post("/disable2fa", auth, twofa, async (req, res) => { |
