diff options
| author | Adam Soltys <[email protected]> | 2020-09-27 13:25:59 -0700 |
|---|---|---|
| committer | Adam Soltys <[email protected]> | 2020-09-27 13:25:59 -0700 |
| commit | 8d42a328880dae07960c56a81649583aab0e71f3 (patch) | |
| tree | 2fcb671868c742c420c1c2bbb5f0c2587d248a14 | |
| parent | 4849c6ac324df67d2f5fc20ed4a958fe9a2bfa1f (diff) | |
| download | coinos-server-8d42a328880dae07960c56a81649583aab0e71f3.tar.gz coinos-server-8d42a328880dae07960c56a81649583aab0e71f3.zip | |
use account foreign keys in proposals table
| -rw-r--r-- | db/index.js | 38 | ||||
| -rw-r--r-- | db/models/proposals.js | 40 | ||||
| -rw-r--r-- | routes/send.js | 9 | ||||
| -rw-r--r-- | routes/swaps.js | 284 |
4 files changed, 279 insertions, 92 deletions
diff --git a/db/index.js b/db/index.js index 6fa225e6..0772bfc7 100644 --- a/db/index.js +++ b/db/index.js @@ -16,62 +16,76 @@ require("./models/payments.js"); require("./models/proposals.js"); require("./models/users.js"); -db["User"].hasMany(db["Account"], { +const { User, Account, Payment, Invoice, Key, Proposal } = db; + +User.hasMany(Account, { as: "accounts", foreignKey: "user_id" }); -db["User"].hasMany(db["Invoice"], { +User.hasMany(Invoice, { as: "invoices", foreignKey: "user_id" }); -db["User"].hasMany(db["Key"], { +User.hasMany(Key, { as: "keys", foreignKey: "user_id" }); -db["User"].hasMany(db["Payment"], { +User.hasMany(Payment, { as: "payments", foreignKey: "user_id" }); -db["User"].belongsTo(db["Account"], { +User.belongsTo(Account, { as: "account", foreignKey: "account_id" }); -db["Invoice"].belongsTo(db["Account"], { +Invoice.belongsTo(Account, { as: "account", foreignKey: "account_id" }); -db["Account"].belongsTo(db["User"], { +Account.belongsTo(User, { as: "user", foreignKey: "user_id" }); -db["Invoice"].belongsTo(db["User"], { +Invoice.belongsTo(User, { as: "user", foreignKey: "user_id" }); -db["Key"].belongsTo(db["User"], { +Key.belongsTo(User, { as: "user", foreignKey: "user_id" }); -db["Payment"].belongsTo(db["Account"], { +Payment.belongsTo(Account, { as: "account", foreignKey: "account_id" }); -db["Payment"].belongsTo(db["User"], { +Payment.belongsTo(User, { as: "user", foreignKey: "user_id" }); -db["Proposal"].belongsTo(db["User"], { +Proposal.belongsTo(User, { as: "user", foreignKey: "user_id" }); + +Proposal.belongsTo(Account, { + as: "acc1", + foreignKey: "a1_id" +}); + +Proposal.belongsTo(Account, { + as: "acc2", + foreignKey: "a2_id" +}); + +db.Proposal = Proposal; diff --git a/db/models/proposals.js b/db/models/proposals.js index ca3de8eb..44f2f796 100644 --- a/db/models/proposals.js +++ b/db/models/proposals.js @@ -1,4 +1,4 @@ -const { DataTypes } = require('sequelize'); +const { DataTypes } = require("sequelize"); const attributes = { id: { @@ -10,6 +10,24 @@ const attributes = { comment: null, field: "id" }, + a1_id: { + type: DataTypes.INTEGER(11), + allowNull: true, + defaultValue: null, + primaryKey: false, + autoIncrement: false, + comment: null, + field: "a1_id" + }, + a2_id: { + type: DataTypes.INTEGER(11), + allowNull: true, + defaultValue: null, + primaryKey: false, + autoIncrement: false, + comment: null, + field: "a2_id" + }, user_id: { type: DataTypes.INTEGER(11), allowNull: true, @@ -46,24 +64,6 @@ const attributes = { comment: null, field: "updatedAt" }, - a1: { - type: DataTypes.STRING(255), - allowNull: true, - defaultValue: null, - primaryKey: false, - autoIncrement: false, - comment: null, - field: "a1" - }, - a2: { - type: DataTypes.STRING(255), - allowNull: true, - defaultValue: null, - primaryKey: false, - autoIncrement: false, - comment: null, - field: "a2" - }, v1: { type: DataTypes.DOUBLE, allowNull: true, @@ -126,4 +126,4 @@ const options = { indexes: [] }; -db["Proposal"] = db.define("proposals_model", attributes, options); +db.Proposal = db.define("proposals_model", attributes, options); diff --git a/routes/send.js b/routes/send.js index e2836b82..ab67bfaa 100644 --- a/routes/send.js +++ b/routes/send.js @@ -57,7 +57,8 @@ module.exports = ah(async (req, res, next) => { model: db.Account, as: "account" } - }); + }, + { transaction }); let a2; let acc = { @@ -71,9 +72,7 @@ module.exports = ah(async (req, res, next) => { else { a2 = await db.Account.findOne({ where: acc, - lock: transaction.LOCK.UPDATE, - transaction - }); + }, { transaction }); } if (a2) { @@ -96,7 +95,7 @@ module.exports = ah(async (req, res, next) => { }, order: [["id", "ASC"]], limit: 1 - }); + }, { transaction }); if (existing) { ({ domain, ticker, precision, name } = existing); diff --git a/routes/swaps.js b/routes/swaps.js index dbf47ab8..385ad134 100644 --- a/routes/swaps.js +++ b/routes/swaps.js @@ -5,7 +5,12 @@ const fs = require("fs"); const { spawn } = require("child_process"); const leveldb = level("leveldb"); const getAccount = require("../lib/account"); -const { Op } = require("sequelize"); +const { Op, col } = require("sequelize"); +const shallow = a => { + let b = {}; + for (x in a) { if(a[x] instanceof Date || typeof a[x] !== 'object') b[x] = a[x]; } + return b; +} const assets = { b2e15d0d7a0c94e4e2ce0fe6e8691b9e451377f6e46e8045a86f7c4b5d4f0f23: "bitcoin", @@ -97,14 +102,48 @@ app.delete( auth, ah(async (req, res) => { const { id } = req.params; - await db.Proposal.destroy({ - where: { - id, - user_id: req.user.id - } + const { user } = req; + + await db.transaction(async transaction => { + let proposal = await db.Proposal.findOne( + { + where: { + id, + user_id: user.id + }, + include: { + model: db.Account, + as: "acc1" + } + }, + + { transaction } + ); + + let { acc1: account, v1, v2 } = proposal; + account.balance += v1; + await account.save({ transaction }); + + let rate = v2 / v1; + let payment = await db.Payment.create( + { + hash: "Trade Cancelled", + amount: v1, + account_id: account.id, + user_id: user.id, + currency: user.currency, + rate, + confirmed: true, + received: true, + network: "COINOS" + }, + { transaction } + ); + + emit(user.username, "payment", payment); + broadcast("removeProposal", id); + res.end(); }); - broadcast("removeProposal", id); - res.end(); }) ); @@ -114,12 +153,19 @@ app.get( ah(async (req, res) => { try { const { user } = req; + let { a1, v1, a2, v2 } = req.query; + v1 = Math.round(v1 * SATS); + v2 = Math.round(v2 * SATS); + + let rate = v2 / v1; + const b = await lq.getBalance(); Object.keys(b).map(asset => { assets[asset] = asset; }); + assets[config.liquid.btcasset] = "bitcoin"; assets[ "ce091c998b83c78bb71a632313ba3760f1763d9cfcffae02258ffa9865a37bd2" @@ -129,60 +175,170 @@ app.get( ] = "adamcoin"; if (!assets[a1]) throw new Error("unsupported asset"); - if (parseFloat(v1) > parseFloat(b[assets[a1]])) + if (v1 > Math.round(b[assets[a1]] * SATS)) throw new Error(`insufficient server funds, ${v1} ${b[assets[a1]]}`); await db.transaction(async transaction => { - const account = await db.Account.findOne({ - where: { - user_id: user.id, - asset: a1 - }, - lock: transaction.LOCK.UPDATE, - transaction - }); + let a1acc = await getAccount(a1, user, transaction); + let a2acc = await getAccount(a2, user, transaction); - v1 = Math.round(v1 * SATS); - v2 = Math.round(v2 * SATS); - let rate = v2/v1; - - if (v1 > account.balance) - throw new Error(`insufficient funds, ${v1} ${account.balance}`); + if (v1 > a1acc.balance) + throw new Error(`insufficient funds, ${v1} ${a1acc.balance}`); l.info( - `proposal requested to swap ${v1} ${assets[a1]} for ${v2} ${assets[a2]}` + `trade ${v1} ${a1.substr(0, 6)} for ${v2} ${a2.substr(0, 6)}`, + user.username ); - //let text = await createProposal(a1, v1, a2, v2); - //text = text.replace(/\s+/g, "").trim(); + a1acc.balance -= v1; + await a1acc.save({ transaction }); - const proposals = await db.Proposal.findAll({ - where: { - a1: a2, - a2: a1, - rate: { [Op.lte]: v1/v2 }, - accepted: false + let payment = await db.Payment.create( + { + hash: "Trade Funding", + amount: -v1, + account_id: a1acc.id, + user_id: user.id, + currency: user.currency, + rate, + confirmed: true, + received: false, + network: "COINOS" }, - order: [ - ["rate", "ASC"], - ["id", "ASC"] - ] - }); + { transaction } + ); + + emit(user.username, "payment", payment); + + const proposals = await db.Proposal.findAll( + { + where: { + "$acc1.asset$": a2, + "$acc2.asset$": a1, + rate: { [Op.lte]: v1 / v2 }, + accepted: false + }, + order: [ + ["rate", "ASC"], + ["id", "ASC"] + ], + include: [ + { + model: db.User, + as: "user" + }, + { + model: db.Account, + as: "acc1" + }, + { + model: db.Account, + as: "acc2" + } + ] + }, + { transaction } + ); 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); + await p.save({ transaction }); + + p.acc1.balance += v1; + await p.acc1.save({ transaction }); + + p = p.get({ plain: true }); + p.a1 = p.acc1.asset; + p.a2 = p.acc2.asset; + broadcast("proposal", shallow(p)); + v1 = 0; + + let payment = await db.Payment.create( + { + hash: "Oh", + amount: v2, + account_id: p.a1_id, + user_id: p.user_id, + currency: p.user.currency, + rate, + confirmed: true, + received: true, + network: "COINOS" + }, + { transaction } + ); + + emit(p.user.username, "payment", payment); + emit(p.user.username, "account", p.acc1); + + payment = await db.Payment.create( + { + hash: "My", + amount: v1, + account_id: a1acc.id, + user_id: user.id, + currency: user.currency, + rate, + confirmed: true, + received: true, + network: "COINOS" + }, + { transaction } + ); + + emit(user.username, "payment", payment); + emit(user.username, "account", a1acc); } else { v1 -= p.v2; + p.accepted = true; p.completedAt = new Date(); - await p.save(); - broadcast("proposal", p); + + await p.save({ transaction }); + p = p.get({ plain: true }); + p.a1 = p.acc1.asset; + p.a2 = p.acc2.asset; + broadcast("proposal", shallow(p)); + + let payment = await db.Payment.create( + { + hash: "Humm", + amount: p.v1, + account_id: a2acc.id, + user_id: user.id, + currency: user.currency, + rate, + confirmed: true, + received: true, + network: "COINOS" + }, + { transaction } + ); + + emit(user.username, "payment", payment); + emit(user.username, "account", a2acc); + + payment = await db.Payment.create( + { + hash: "Gosh", + amount: p.v2, + account_id: p.a2_id, + user_id: p.user_id, + currency: p.user.currency, + rate, + confirmed: true, + received: true, + network: "COINOS" + }, + { transaction } + ); + + emit(p.user.username, "payment", payment); + emit(p.user.username, "account", p.acc2); } } @@ -190,16 +346,19 @@ app.get( if (v1) { proposal = await db.Proposal.create( { - a1, - a2, v1, v2, user_id: user.id, + a1_id: a1acc.id, + a2_id: a2acc.id }, { transaction } ); + proposal = proposal.get({ plain: true }); proposal.rate = v2 / v1; + proposal.a1 = a1; + proposal.a2 = a2; broadcast("proposal", proposal); } @@ -617,18 +776,33 @@ app.get( 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 - } - }) - ); - } + let proposals = await db.Proposal.findAll({ + attributes: { + include: [ + [col("acc1.asset"), "a1"], + [col("acc2.asset"), "a2"] + ] + }, + include: [ + { + model: db.Account, + as: "acc1", + attributes: [] + }, + { + model: db.Account, + as: "acc2", + attributes: [] + } + ] + }); + + res.send( + proposals.map(p => { + if (p.user_id !== req.user.id) p.user_id = null; + return p; + }) + ); } catch (e) { res.status(500).send(e.message); } |
