diff options
| author | Adam Soltys <[email protected]> | 2020-07-29 10:04:57 -0700 |
|---|---|---|
| committer | Adam Soltys <[email protected]> | 2020-07-29 10:19:22 -0700 |
| commit | ffee4c7051982f3677d6717d24e7b357a89802eb (patch) | |
| tree | bda672176e7fc4f585df483c2a2568c3bd573037 | |
| parent | d22869941ec704edd17d1d05038e6139681f97cf (diff) | |
| download | coinos-server-ffee4c7051982f3677d6717d24e7b357a89802eb.tar.gz coinos-server-ffee4c7051982f3677d6717d24e7b357a89802eb.zip | |
warn about missing and unconfirmed transactions
| -rw-r--r-- | .gitignore | 1 | ||||
| -rw-r--r-- | createExceptions.js | 32 | ||||
| -rw-r--r-- | lib/read.js | 25 | ||||
| -rw-r--r-- | routes/payments.js | 100 |
4 files changed, 135 insertions, 23 deletions
@@ -10,3 +10,4 @@ yarn-error.log tls.* leveldb swaps +exceptions diff --git a/createExceptions.js b/createExceptions.js new file mode 100644 index 00000000..bec6ebc6 --- /dev/null +++ b/createExceptions.js @@ -0,0 +1,32 @@ +BitcoinCore = require("bitcoin-core"); +fs = require("fs"); +config = require("./config"); +bc = new BitcoinCore(config.bitcoin); +l = require("pino")(); +require("./db"); + +console.log(db.Payment); + +(async () => { + payments = ( + await db.Payment.findAll({ + attributes: ["hash"], + }) + ).map((p) => p.hash); + const transactions = await bc.listTransactions("*", 1000); + var stream = fs.createWriteStream("exceptions", { + flags: "a", + emitClose: true, + }); + transactions.map((tx) => { + if (!payments.includes(tx.txid)) { + l.info("writing", tx.txid); + stream.write(tx.txid + "\n"); + } + }); + stream.end(); + stream.on("close", () => { + l.info("done"); + process.exit(); + }); +})(); diff --git a/lib/read.js b/lib/read.js new file mode 100644 index 00000000..dfd70e75 --- /dev/null +++ b/lib/read.js @@ -0,0 +1,25 @@ +module.exports = (stream, func) => { + var remaining = ""; + + stream.on("data", function (data) { + remaining += data; + var index = remaining.indexOf("\n"); + var last = 0; + while (index > -1) { + var line = remaining.substring(last, index); + last = index + 1; + func(line); + index = remaining.indexOf("\n", last); + } + + remaining = remaining.substring(last); + }); + + stream.on("error", () => {}); + + stream.on("end", function () { + if (remaining.length > 0) { + func(remaining); + } + }); +}; diff --git a/routes/payments.js b/routes/payments.js index e16d6c3d..20a56baf 100644 --- a/routes/payments.js +++ b/routes/payments.js @@ -2,33 +2,80 @@ const BitcoinCore = require("bitcoin-core"); const lnd = require("../lib/lnd"); const { Op } = require("sequelize"); const { join } = require("path"); +const fs = require("fs"); +const read = require("../lib/read"); (async () => { seen = []; addresses = {}; issuances = {}; + const exceptions = []; + try { + read(fs.createReadStream("exceptions"), (data) => exceptions.push(data)); + } catch (e) { + l.warn("couldn't read exceptions file", e.message); + } + await db.User.findAll({ - attributes: ["username", "address", "liquid"] - }).map(u => { + attributes: ["username", "address", "liquid"], + }).map((u) => { if (u.address) addresses[u.address] = u.username; if (u.liquid) addresses[u.liquid] = u.username; }); await db.Invoice.findAll({ - include: [{ - model: db.User, - as: 'user'}] - }).map(i => { + include: [ + { + model: db.User, + as: "user", + }, + ], + }).map((i) => { if (i.address && i.user) addresses[i.address] = i.user.username; - if (i.unconfidential && i.user) addresses[i.unconfidential] = i.user.username; + if (i.unconfidential && i.user) + addresses[i.unconfidential] = i.user.username; }); payments = ( await db.Payment.findAll({ - attributes: ["hash"] + attributes: ["hash"], }) - ).map(p => p.hash); + ).map((p) => p.hash); + + setInterval(async () => { + const unconfirmed = ( + await db.Payment.findAll({ + where: { + confirmed: 0, + }, + }) + ).map((p) => p.address); + + const transactions = await bc.listTransactions("*", 1000); + + transactions + .filter( + (tx) => + tx.category === "receive" && + tx.confirmations > 0 && + unconfirmed.includes(tx.address) + ) + .map((tx) => { + l.warn("tx unconfirmed in db", tx.txid); + }); + + const unaccounted = []; + + transactions.map((tx) => { + if (!payments.includes(tx.txid) && !exceptions.includes(tx.txid)) { + unaccounted.push(tx.txid); + } + }); + + if (unaccounted.length) + l.warn("wallet transactions missing from database", unaccounted); + }, 60000); app.post("/send", auth, require("./send")); @@ -44,7 +91,10 @@ const { join } = require("path"); } app.post("/lightning/channel", require("./lightning/channel")); - app.post("/lightning/channelRequest", require("./lightning/channelRequest")); + app.post( + "/lightning/channelRequest", + require("./lightning/channelRequest") + ); app.post("/lightning/invoice", auth, require("./lightning/invoice")); app.post("/lightning/query", auth, require("./lightning/query")); app.post("/lightning/send", auth, require("./lightning/send")); @@ -68,18 +118,22 @@ const { join } = require("path"); require("./liquid/receive"); } - app.get("/payments", auth, ah(async (req, res, next) => { - let payments = await req.user.getPayments({ - where: { - account_id: req.user.account_id - }, - order: [["id", "DESC"]], - include: { - model: db.Account, - as: "account" - } - }); + app.get( + "/payments", + auth, + ah(async (req, res, next) => { + let payments = await req.user.getPayments({ + where: { + account_id: req.user.account_id, + }, + order: [["id", "DESC"]], + include: { + model: db.Account, + as: "account", + }, + }); - res.send(payments); - })); + res.send(payments); + }) + ); })(); |
