aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAdam Soltys <[email protected]>2020-09-27 13:25:59 -0700
committerAdam Soltys <[email protected]>2020-09-27 13:25:59 -0700
commit8d42a328880dae07960c56a81649583aab0e71f3 (patch)
tree2fcb671868c742c420c1c2bbb5f0c2587d248a14
parent4849c6ac324df67d2f5fc20ed4a958fe9a2bfa1f (diff)
downloadcoinos-server-8d42a328880dae07960c56a81649583aab0e71f3.tar.gz
coinos-server-8d42a328880dae07960c56a81649583aab0e71f3.zip
use account foreign keys in proposals table
-rw-r--r--db/index.js38
-rw-r--r--db/models/proposals.js40
-rw-r--r--routes/send.js9
-rw-r--r--routes/swaps.js284
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);
}