diff options
| author | Adam Soltys <[email protected]> | 2020-09-24 23:49:37 -0700 |
|---|---|---|
| committer | Adam Soltys <[email protected]> | 2020-09-24 23:49:37 -0700 |
| commit | 072dd8dcce4f28eba78838855f6ae977b868c8b6 (patch) | |
| tree | b2cc322a0ee82355460b61a7a7148072eca0086e | |
| parent | a6534130b7d6d4f1659e6419b181b7208767ff73 (diff) | |
| download | coinos-server-072dd8dcce4f28eba78838855f6ae977b868c8b6.tar.gz coinos-server-072dd8dcce4f28eba78838855f6ae977b868c8b6.zip | |
order matching
| -rw-r--r-- | db/models/proposals.js | 13 | ||||
| -rw-r--r-- | lib/account.js | 7 | ||||
| -rw-r--r-- | routes/assets.js | 2 | ||||
| -rw-r--r-- | routes/swaps.js | 741 | ||||
| -rw-r--r-- | routes/users.js | 3 |
5 files changed, 444 insertions, 322 deletions
diff --git a/db/models/proposals.js b/db/models/proposals.js index 6d7ee40e..842101ac 100644 --- a/db/models/proposals.js +++ b/db/models/proposals.js @@ -56,7 +56,7 @@ const attributes = { field: "a2" }, v1: { - type: DataTypes.INTEGER, + type: DataTypes.DOUBLE, allowNull: true, defaultValue: null, primaryKey: false, @@ -65,7 +65,7 @@ const attributes = { field: "v1" }, v2: { - type: DataTypes.INTEGER, + type: DataTypes.DOUBLE, allowNull: true, defaultValue: null, primaryKey: false, @@ -73,6 +73,15 @@ const attributes = { comment: null, field: "v2" }, + rate: { + type: DataTypes.DOUBLE, + allowNull: true, + defaultValue: null, + primaryKey: false, + autoIncrement: false, + comment: null, + field: "rate" + }, text: { type: DataTypes.TEXT, allowNull: false, diff --git a/lib/account.js b/lib/account.js index 27ef830a..ca3ce7ea 100644 --- a/lib/account.js +++ b/lib/account.js @@ -1,11 +1,14 @@ const axios = require("axios"); -module.exports = async (asset, user) => { +module.exports = async (asset, user, transaction) => { const account = await db.Account.findOne({ where: { user_id: user.id, asset, + pubkey: null, }, + lock: transaction.LOCK.UPDATE, + transaction, }); if (account) return account; @@ -30,6 +33,8 @@ module.exports = async (asset, user) => { }, order: [["id", "ASC"]], limit: 1, + lock: transaction.LOCK.UPDATE, + transaction, }); if (existing) { diff --git a/routes/assets.js b/routes/assets.js index 34856f04..b0115897 100644 --- a/routes/assets.js +++ b/routes/assets.js @@ -87,7 +87,6 @@ app.post( params.asset_amount = asset_amount / (SATS / 10 ** precision); - l.info("asset_amount", params.asset_amount); if (token_amount) { params.token_amount = token_amount; params.token_address = token_address; @@ -159,6 +158,7 @@ app.post( ); emit(user.username, "account", account); + l.info("issued asset", user.username, params.asset_amount, ticker, name); const asset_payment = await db.Payment.create( { diff --git a/routes/swaps.js b/routes/swaps.js index f416ffc8..12cf72f9 100644 --- a/routes/swaps.js +++ b/routes/swaps.js @@ -5,15 +5,16 @@ const fs = require("fs"); const { spawn } = require("child_process"); const leveldb = level("leveldb"); const getAccount = require("../lib/account"); +const { Op } = require("sequelize"); const assets = { b2e15d0d7a0c94e4e2ce0fe6e8691b9e451377f6e46e8045a86f7c4b5d4f0f23: "bitcoin", - "4eebe36eb0819e6daa5dd3c97733251ff4eb728c810d949365d6dacaad5ef6e8": "tether", + "4eebe36eb0819e6daa5dd3c97733251ff4eb728c810d949365d6dacaad5ef6e8": "tether" }; -const swapsdir = 'swaps/'; -if (!fs.existsSync(swapsdir)){ - fs.mkdirSync(swapsdir); +const swapsdir = "swaps/"; +if (!fs.existsSync(swapsdir)) { + fs.mkdirSync(swapsdir); } const timeout = 20000; @@ -37,15 +38,15 @@ const createProposal = (a1, v1, a2, v2) => ); const proc = cli("propose", a1, v1, a2, v2); - proc.stdout.on("data", (data) => { + proc.stdout.on("data", data => { resolve(data.toString()); }); - proc.stderr.on("error", (err) => { + proc.stderr.on("error", err => { l.error("proposal error", err.toString()); reject(err.toString()); }); - + proc.on("close", (code, signal) => { let msg = (code && code.toString()) || (signal && signal.toString()); reject(new Error(`Liquid swap tool process closed unexpectedly: ${msg}`)); @@ -56,18 +57,21 @@ const createProposal = (a1, v1, a2, v2) => reject(new Error(`Liquid swap tool process exited unexpectedly: ${msg}`)); }); - setTimeout(() => reject(new Error("Liquid swap tool timed out"), proc), timeout); + setTimeout( + () => reject(new Error("Liquid swap tool timed out"), proc), + timeout + ); }); -const getInfo = (filename) => +const getInfo = filename => new Promise((resolve, reject) => { const proc = cli("info", swapsdir + filename); - proc.stdout.on("data", (data) => { + proc.stdout.on("data", data => { resolve(data.toString()); }); - proc.stderr.on("data", (err) => { + proc.stderr.on("data", err => { l.error("info error", err.toString()); reject(err.toString()); }); @@ -82,324 +86,419 @@ const getInfo = (filename) => reject(new Error(`Liquid swap tool process exited unexpectedly: ${msg}`)); }); - setTimeout(() => reject(new Error("Liquid swap tool timed out"), proc), timeout); - }); - -app.delete("/proposal/:id", auth, ah(async (req, res) => { - const { id } = req.params; - await db.Proposal.destroy({ - where: { - id, - user_id: req.user.id, - }, + setTimeout( + () => reject(new Error("Liquid swap tool timed out"), proc), + timeout + ); }); - res.end(); -})); - -app.get("/proposal", auth, ah(async (req, res) => { - try { - const { user } = req; - const { a1, v1, a2, v2 } = req.query; - const b = await lq.getBalance(); - Object.keys(b).map((asset) => { - assets[asset] = asset; - }); - assets["ce091c998b83c78bb71a632313ba3760f1763d9cfcffae02258ffa9865a37bd2"] = "tether"; - assets["6f0279e9ed041c3d710a9f57d0c02928416460c4b722ae3457a11eec381c526d"] = "bitcoin"; - assets["a0c358a0f6947864af3a06f3f6a2aeb304df7fd95c922f2f22d7412399ce7691"] = "adamcoin"; - - if (!assets[a1]) throw new Error("unsupported asset"); - if (v1 > b[assets[a1]]) throw new Error(`insufficient server funds, ${v1} ${b[assets[a1]]}`); - const account = await db.Account.findOne({ +app.delete( + "/proposal/:id", + auth, + ah(async (req, res) => { + const { id } = req.params; + await db.Proposal.destroy({ where: { - user_id: user.id, - asset: a1, - }, + id, + user_id: req.user.id + } }); - if (v1 > account.balance) throw new Error(`insufficient funds, ${v1} ${account.balance}`); + broadcast("removeProposal", id); + res.end(); + }) +); - l.info( - `proposal requested to swap ${v1} ${assets[a1]} for ${v2} ${assets[a2]}` - ); +app.get( + "/proposal", + auth, + ah(async (req, res) => { + try { + const { user } = req; + let { a1, v1, a2, v2 } = req.query; + const b = await lq.getBalance(); - let text = await createProposal(a1, v1, a2, v2); - text = text.replace(/\s+/g, "").trim(); + Object.keys(b).map(asset => { + assets[asset] = asset; + }); + assets[config.liquid.btcasset] = "bitcoin"; + assets[ + "ce091c998b83c78bb71a632313ba3760f1763d9cfcffae02258ffa9865a37bd2" + ] = "tether"; + assets[ + "a0c358a0f6947864af3a06f3f6a2aeb304df7fd95c922f2f22d7412399ce7691" + ] = "adamcoin"; - const proposal = await db.Proposal.create({ - a1, - a2, - v1: Math.round(v1 * SATS), - v2: Math.round(v2 * SATS), - user_id: user.id, - text, - }); + if (!assets[a1]) throw new Error("unsupported asset"); + if (parseFloat(v1) > parseFloat(b[assets[a1]])) + throw new Error(`insufficient server funds, ${v1} ${b[assets[a1]]}`); - res.send({ proposal }); - } catch (e) { - l.error(req.user.username, e.message); - res.status(500).send({ error: e.message }); - } -})); + await db.transaction(async transaction => { + const account = await db.Account.findOne({ + where: { + user_id: user.id, + asset: a1 + }, + lock: transaction.LOCK.UPDATE, + transaction + }); -app.post("/accept", optionalAuth, ah(async (req, res) => { - try { - const { id, text } = req.body; + v1 = Math.round(v1 * SATS); + v2 = Math.round(v2 * SATS); + let rate = v2 / v1; - const proposal = await db.Proposal.findOne({ - where: { - id, - accepted: false, - }, - include: { - model: db.User, - as: "user", - }, - }); + if (v1 > account.balance) + throw new Error(`insufficient funds, ${v1} ${account.balance}`); - if (!proposal) throw new Error("Proposal not found"); + l.info( + `proposal requested to swap ${v1} ${assets[a1]} for ${v2} ${assets[a2]}` + ); - const filename = `proposal-${id}.txt`; + //let text = await createProposal(a1, v1, a2, v2); + //text = text.replace(/\s+/g, "").trim(); - fs.writeFileSync(swapsdir + filename, proposal.text); - let info = JSON.parse(await getInfo(filename)); + const proposals = await db.Proposal.findAll({ + where: { + a1: a2, + a2: a1, + rate: { [Op.lte]: 1/rate }, + accepted: false, + }, + order: [["rate", "ASC"], ["id", "ASC"]] + }); - const { user } = req; + for (let i = 0; i < proposals.length; i++) { + if (!v1) break; + p = proposals[i]; + if (p.v2 > v1) { + p.v2 -= v1; + await p.save(); + broadcast("proposal", p); + v1 = 0; + } else { + v1 -= p.v2; + p.accepted = true; + await p.save(); + broadcast("proposal", p); + } + } - if (user) { - let [fee, rate, asset] = parse(info); - const leg1 = info.legs.find((leg) => !leg.incoming && leg.funded); - const leg2 = info.legs.find((leg) => leg.incoming && !leg.funded); - await db.transaction(async (transaction) => { - const l1a1 = await getAccount(leg1.asset, user); - const l1a2 = await getAccount(leg1.asset, proposal.user); + let proposal; + if (v1) { + proposal = await db.Proposal.create( + { + a1, + a2, + v1, + v2, + user_id: user.id + }, + { transaction } + ); - let amount = Math.round(leg1.amount * SATS); - if (amount > l1a2.balance) - throw new Error(`Proposer has insufficient funds: ${amount}, ${l1a2.balance}`); + proposal.rate = v2 / v1; + broadcast("proposal", proposal); + } - l1a1.balance += amount; - l1a2.balance -= amount; + res.send({ proposal }); + }); + } catch (e) { + l.error(req.user.username, e.message, e.stack); + res.status(500).send(e.message); + } + }) +); - let l1a1p = await db.Payment.create({ - hash: "Internal Transfer", - amount, - account_id: l1a1.id, - memo: "Atomic Swap", - user_id: user.id, - currency: user.currency, - rate, - confirmed: true, - received: true, - network: "COINOS", - }); +app.post( + "/accept", + optionalAuth, + ah(async (req, res) => { + try { + const { id, text } = req.body; - let l1a2p = await db.Payment.create({ - hash: "Internal Transfer", - amount: -amount, - account_id: l1a2.id, - memo: "Atomic Swap", - user_id: proposal.user_id, - currency: proposal.user.currency, - rate, - confirmed: true, - received: false, - network: "COINOS", - }); + const proposal = await db.Proposal.findOne({ + where: { + id, + accepted: false + }, + include: { + model: db.User, + as: "user" + } + }); - const l2a1 = await getAccount(leg2.asset, user); - const l2a2 = await getAccount(leg2.asset, proposal.user); + if (!proposal) throw new Error("Proposal not found"); - amount = Math.round(leg2.amount * SATS); - if (amount > l2a1.balance) throw new Error("Insufficient funds"); + const filename = `proposal-${id}.txt`; - l2a1.balance -= amount; - l2a2.balance += amount; + fs.writeFileSync(swapsdir + filename, proposal.text); + let info = JSON.parse(await getInfo(filename)); - let l2a1p = await db.Payment.create({ - hash: "Internal Transfer", - amount: -amount, - account_id: l2a1.id, - memo: "Atomic Swap", - user_id: user.id, - currency: user.currency, - rate, - confirmed: true, - received: false, - network: "COINOS", - }); + const { user } = req; - let l2a2p = await db.Payment.create({ - hash: "Internal Transfer", - amount, - account_id: l2a2.id, - memo: "Atomic Swap", - user_id: proposal.user_id, - currency: proposal.user.currency, - rate, - confirmed: true, - received: true, - network: "COINOS", - }); + if (user) { + let [fee, rate, asset] = parse(info); + const leg1 = info.legs.find(leg => !leg.incoming && leg.funded); + const leg2 = info.legs.find(leg => leg.incoming && !leg.funded); + await db.transaction(async transaction => { + const l1a1 = await getAccount(leg1.asset, user, transaction); + const l1a2 = await getAccount(leg1.asset, proposal.user, transaction); - await l1a1.save({ transaction }); - await l1a2.save({ transaction }); - await l2a1.save({ transaction }); - await l2a2.save({ transaction }); + let amount = Math.round(leg1.amount * SATS); + if (amount > l1a2.balance) + throw new Error( + `Proposer has insufficient funds: ${amount}, ${l1a2.balance}` + ); - proposal.accepted = true; - await proposal.save({ transaction }); + l1a1.balance += amount; + l1a2.balance -= amount; - l1a1p = l1a1p.get({ plain: true }); - l1a1p.account = l1a1.get({ plain: true }); - l1a2p = l1a2p.get({ plain: true }); - l1a2p.account = l1a2.get({ plain: true }); - l2a1p = l2a1p.get({ plain: true }); - l2a1p.account = l2a1.get({ plain: true }); - l2a2p = l2a2p.get({ plain: true }); - l2a2p.account = l2a2.get({ plain: true }); + let l1a1p = await db.Payment.create( + { + hash: "Internal Transfer", + amount, + account_id: l1a1.id, + memo: "Atomic Swap", + user_id: user.id, + currency: user.currency, + rate, + confirmed: true, + received: true, + network: "COINOS" + }, + { transaction } + ); - emit(user.username, "account", l1a1); - emit(user.username, "account", l2a1); - emit(proposal.user.username, "account", l1a2); - emit(proposal.user.username, "account", l2a2); - emit(user.username, "payment", l1a1p); - emit(user.username, "payment", l2a1p); - emit(proposal.user.username, "payment", l1a2p); - emit(proposal.user.username, "payment", l2a2p); - emit(user.username, "proposal", proposal); - emit(proposal.user.username, "proposal", proposal); - }); - } else if (text) { - const filename = `acceptance-${id}.txt`; - fs.writeFileSync(swapsdir + filename, text); + let l1a2p = await db.Payment.create( + { + hash: "Internal Transfer", + amount: -amount, + account_id: l1a2.id, + memo: "Atomic Swap", + user_id: proposal.user_id, + currency: proposal.user.currency, + rate, + confirmed: true, + received: false, + network: "COINOS" + }, + { transaction } + ); - info = JSON.parse(await getInfo(filename)); - let [fee, rate, asset] = parse(info); - let { tx, u_address_p, u_address_r } = JSON.parse( - Buffer.from(text, "base64").toString() - ); - const sha256 = crypto.createHash("sha256"); - sha256.update(tx); - const hash = sha256.digest("hex"); + const l2a1 = await getAccount(leg2.asset, user); + const l2a2 = await getAccount(leg2.asset, proposal.user); - const leg1 = info.legs.find((leg) => !leg.incoming); - const leg2 = info.legs.find((leg) => leg.incoming); + amount = Math.round(leg2.amount * SATS); + if (amount > l2a1.balance) throw new Error("Insufficient funds"); - const l1a2 = await getAccount(leg1.asset, proposal.user); - const btc = await getAccount(config.liquid.btcasset, proposal.user); + l2a1.balance -= amount; + l2a2.balance += amount; - await db.transaction(async (transaction) => { + let l2a1p = await db.Payment.create( + { + hash: "Internal Transfer", + amount: -amount, + account_id: l2a1.id, + memo: "Atomic Swap", + user_id: user.id, + currency: user.currency, + rate, + confirmed: true, + received: false, + network: "COINOS" + }, + { transaction } + ); - let amount = Math.round(leg1.amount * SATS); - fee = Math.round(fee * SATS); + let l2a2p = await db.Payment.create( + { + hash: "Internal Transfer", + amount, + account_id: l2a2.id, + memo: "Atomic Swap", + user_id: proposal.user_id, + currency: proposal.user.currency, + rate, + confirmed: true, + received: true, + network: "COINOS" + }, + { transaction } + ); - if (amount > l1a2.balance) - throw new Error(`Proposer has insufficient funds: ${amount}, ${l1a2.balance}`); + await l1a1.save({ transaction }); + await l1a2.save({ transaction }); + await l2a1.save({ transaction }); + await l2a2.save({ transaction }); - if (fee > btc.balance) - throw new Error(`Proposer has insufficient funds for fee: ${fee}, ${btc.balance}`); + proposal.accepted = true; + await proposal.save({ transaction }); - l1a2.balance -= amount; - btc.balance -= fee; + l1a1p = l1a1p.get({ plain: true }); + l1a1p.account = l1a1.get({ plain: true }); + l1a2p = l1a2p.get({ plain: true }); + l1a2p.account = l1a2.get({ plain: true }); + l2a1p = l2a1p.get({ plain: true }); + l2a1p.account = l2a1.get({ plain: true }); + l2a2p = l2a2p.get({ plain: true }); + l2a2p.account = l2a2.get({ plain: true }); - let payment = await db.Payment.create({ - hash, - amount: -amount, - account_id: l1a2.id, - fee, - memo: "Atomic Swap", - user_id: proposal.user_id, - currency: proposal.user.currency, - rate, - address: u_address_r, - confirmed: true, - received: false, - network: "liquid", - }); - - amount = Math.round(leg2.amount * SATS); + emit(user.username, "account", l1a1); + emit(user.username, "account", l2a1); + emit(proposal.user.username, "account", l1a2); + emit(proposal.user.username, "account", l2a2); + emit(user.username, "payment", l1a1p); + emit(user.username, "payment", l2a1p); + emit(proposal.user.username, "payment", l1a2p); + emit(proposal.user.username, "payment", l2a2p); + emit(user.username, "proposal", proposal); - await db.Invoice.create({ - user_id: proposal.user_id, - text: u_address_p, - currency: proposal.user.currency, - memo: "Atomic Swap", - rate, - amount, - tip: 0, - network: "liquid", + console.log("emitting", proposal.user.username, proposal); + emit(proposal.user.username, "proposal", proposal); }); + } else if (text) { + const filename = `acceptance-${id}.txt`; + fs.writeFileSync(swapsdir + filename, text); - addresses[u_address_p] = proposal.user.username; + info = JSON.parse(await getInfo(filename)); + let [fee, rate, asset] = parse(info); + let { tx, u_address_p, u_address_r } = JSON.parse( + Buffer.from(text, "base64").toString() + ); + const sha256 = crypto.createHash("sha256"); + sha256.update(tx); + const hash = sha256.digest("hex"); - await finalize(filename); - await l1a2.save({ transaction }); - await btc.save({ transaction }); + const leg1 = info.legs.find(leg => !leg.incoming); + const leg2 = info.legs.find(leg => leg.incoming); - proposal.accepted = true; - await proposal.save({ transaction }); + await db.transaction(async transaction => { + const l1a2 = await getAccount(leg1.asset, proposal.user, transaction); + const bc = await getAccount( + config.liquid.btcasset, + proposal.user, + transaction + ); - payment = payment.get({ plain: true }); - payment.account = l1a2.get({ plain: true }); + let amount = Math.round(leg1.amount * SATS); + fee = Math.round(fee * SATS); - emit(proposal.user.username, "payment", payment); - emit(proposal.user.username, "account", l1a2); - emit(proposal.user.username, "account", btc); - emit(proposal.user.username, "proposal", proposal); - }); - } else { - throw new Error("no acceptance provided"); - } + if (amount > l1a2.balance) + throw new Error( + `Proposer has insufficient funds: ${amount}, ${l1a2.balance}` + ); - res.send(info); - } catch (e) { - l.error(e.message); - res.status(500).send(e.message); - } -})); + if (fee > btc.balance) + throw new Error( + `Proposer has insufficient funds for fee: ${fee}, ${btc.balance}` + ); -app.post("/acceptance", ah(async (req, res) => { - const { acceptance: text } = req.body; - l.info("acceptance received"); + l1a2.balance -= amount; + btc.balance -= fee; - fs.writeFile(swapsdir + "accepted.txt", text, async (err) => { - if (err) { - return res.status(500).send(err); - } + let payment = await db.Payment.create({ + hash, + amount: -amount, + account_id: l1a2.id, + fee, + memo: "Atomic Swap", + user_id: proposal.user_id, + currency: proposal.user.currency, + rate, + address: u_address_r, + confirmed: true, + received: false, + network: "liquid" + }); - try { - let info = JSON.parse( - await new Promise((resolve, reject) => { - const proc = cli("info", swapsdir + "accepted.txt"); + amount = Math.round(leg2.amount * SATS); - proc.stdout.on("data", (data) => { - resolve(data.toString()); + await db.Invoice.create({ + user_id: proposal.user_id, + text: u_address_p, + currency: proposal.user.currency, + memo: "Atomic Swap", + rate, + amount, + tip: 0, + network: "liquid" }); - proc.stderr.on("data", (err) => { - reject(err.toString()); - }); + addresses[u_address_p] = proposal.user.username; - setTimeout(() => reject(new Error("Liquid swap tool timed out"), proc), timeout); - }) - ); + await finalize(filename); + await l1a2.save({ transaction }); + await btc.save({ transaction }); - const time = Math.floor(new Date()).toString(); - const [fee, rate, asset] = parse(info); - if (!asset) throw new Error("unsupported asset"); - l.info("accepted", info, rate, asset); + proposal.accepted = true; + await proposal.save({ transaction }); - leveldb.put(time, JSON.stringify({ text, info, rate, asset })); - l.info({ text, info, rate, asset }); + payment = payment.get({ plain: true }); + payment.account = l1a2.get({ plain: true }); - res.send({ info, rate }); + emit(proposal.user.username, "payment", payment); + emit(proposal.user.username, "account", l1a2); + emit(proposal.user.username, "account", btc); + emit(proposal.user.username, "proposal", proposal); + }); + } else { + throw new Error("no acceptance provided"); + } + + res.send(info); } catch (e) { - l.error(e); - res.status(500).send({ error: e }); + l.error(e.message); + res.status(500).send(e.message); } - }); -})); + }) +); + +app.post( + "/acceptance", + ah(async (req, res) => { + const { acceptance: text } = req.body; + l.info("acceptance received"); + + fs.writeFile(swapsdir + "accepted.txt", text, async err => { + if (err) { + return res.status(500).send(err); + } + + try { + let info = JSON.parse( + await new Promise((resolve, reject) => { + const proc = cli("info", swapsdir + "accepted.txt"); + + proc.stdout.on("data", data => { + resolve(data.toString()); + }); + + proc.stderr.on("data", err => { + reject(err.toString()); + }); + + setTimeout( + () => reject(new Error("Liquid swap tool timed out"), proc), + timeout + ); + }) + ); + + const time = Math.floor(new Date()).toString(); + const [fee, rate, asset] = parse(info); + if (!asset) throw new Error("unsupported asset"); + l.info("accepted", info, rate, asset); + + leveldb.put(time, JSON.stringify({ text, info, rate, asset })); + l.info({ text, info, rate, asset }); + + res.send({ info, rate }); + } catch (e) { + l.error(e); + res.status(500).send(e.message); + } + }); + }) +); checkQueue = async () => { const ws = app.get("ws"); @@ -407,32 +506,32 @@ checkQueue = async () => { leveldb .createReadStream() - .on("data", async function (data) { + .on("data", async function(data) { txs.push({ ...JSON.parse(data.value), key: data.key }); }) - .on("end", async function (data) { + .on("end", async function(data) { const rate = (a, b) => a.rate - b.rate; const time = (a, b) => b.time - a.time; - const pending = txs.filter((tx) => !tx.id); - const completed = txs.filter((tx) => tx.id).sort(time); + const pending = txs.filter(tx => !tx.id); + const completed = txs.filter(tx => tx.id).sort(time); const bitcoin = pending - .filter((tx) => tx.asset === "bitcoin") + .filter(tx => tx.asset === "bitcoin") .sort(rate) .reverse(); const tether = pending - .filter((tx) => tx.asset === "tether") + .filter(tx => tx.asset === "tether") .sort(rate) .reverse(); - const strip = (a) => + const strip = a => a.map(({ id, key, info, rate, time }) => ({ id, key, info, rate, - time, + time })); ws && @@ -440,7 +539,7 @@ checkQueue = async () => { JSON.stringify({ completed: strip(completed.slice(0, 3)), bitcoin: strip(bitcoin.slice(0, 3)), - tether: strip(tether.slice(0, 3)), + tether: strip(tether.slice(0, 3)) }) ); @@ -469,12 +568,12 @@ checkQueue = async () => { }); }; -const parse = (info) => { +const parse = info => { const fee = info.legs[0].fee; return [ fee, (info.legs[1].amount / (info.legs[0].amount + fee)).toFixed(8), - assets[info.legs[0].asset], + assets[info.legs[0].asset] ]; }; @@ -484,11 +583,11 @@ const finalize = (filename = "finalized.txt", text) => { return new Promise((resolve, reject) => { const proc = cli("finalize", swapsdir + filename, "-s"); - proc.stdout.on("data", (data) => { + proc.stdout.on("data", data => { resolve(data.toString()); }); - proc.stderr.on("data", (err) => { + proc.stderr.on("data", err => { reject(new Error(err.toString())); }); @@ -502,39 +601,49 @@ const finalize = (filename = "finalized.txt", text) => { reject(new Error(`Liquid swap tool process exited unexpectedly: ${msg}`)); }); - setTimeout(() => reject(new Error("Liquid swap tool timed out"), proc), timeout); + setTimeout( + () => reject(new Error("Liquid swap tool timed out"), proc), + timeout + ); }); }; -app.get("/proposals", optionalAuth, ah(async (req, res) => { - try { - if (req.user) { - res.send(await db.Proposal.findAll()); - } else { - res.send( - await db.Proposal.findAll({ - attributes: { exclude: ["user_id"] }, - where: { - accepted: false, - }, - }) - ); +app.get( + "/proposals", + optionalAuth, + ah(async (req, res) => { + try { + if (req.user) { + res.send(await db.Proposal.findAll()); + } else { + res.send( + await db.Proposal.findAll({ + attributes: { exclude: ["user_id"] }, + where: { + accepted: false + } + }) + ); + } + } catch (e) { + res.status(500).send(e.message); } - } catch (e) { - res.status(500).send(e.message); - } -})); - -app.post("/publish", auth, ah(async (req, res) => { - try { - const { id } = req.body; - await db.Proposal.update( - { public: true }, - { where: { id, user_id: req.user.id } } - ); - res.end(); - } catch (e) { - res.status(500).send(e.message); - } -})); + }) +); +app.post( + "/publish", + auth, + ah(async (req, res) => { + try { + const { id } = req.body; + await db.Proposal.update( + { public: true }, + { where: { id, user_id: req.user.id } } + ); + res.end(); + } catch (e) { + res.status(500).send(e.message); + } + }) +); diff --git a/routes/users.js b/routes/users.js index e92bc874..3d0b50e4 100644 --- a/routes/users.js +++ b/routes/users.js @@ -553,9 +553,8 @@ app.post( l.info("user", user.username); } - let account = await getAccount(source.account.asset, user); - await db.transaction(async transaction => { + let account = await getAccount(source.account.asset, user, transaction); let { hash, memo, confirmed, fee, network } = source; source.redeemed = true; |
