Merge branch 'sairajzero:main' into main
This commit is contained in:
commit
eb4100e21b
@ -100,6 +100,24 @@ status VARCHAR(50) NOT NULL,
|
|||||||
PRIMARY KEY(id)
|
PRIMARY KEY(id)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
CREATE TABLE TagList (
|
||||||
|
id INT NOT NULL AUTO_INCREMENT,
|
||||||
|
tag VARCHAR(50) NOT NULL,
|
||||||
|
sellPriority INT,
|
||||||
|
buyPriority INT,
|
||||||
|
api TINYTEXT,
|
||||||
|
PRIMARY KEY(tag),
|
||||||
|
KEY (id)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE Tags (
|
||||||
|
id INT NOT NULL AUTO_INCREMENT,
|
||||||
|
floID CHAR(34) NOT NULL,
|
||||||
|
tag VARCHAR(50) NOT NULL,
|
||||||
|
PRIMARY KEY(floID, tag),
|
||||||
|
KEY (id)
|
||||||
|
);
|
||||||
|
|
||||||
/* Backup feature (Table and Triggers) */
|
/* Backup feature (Table and Triggers) */
|
||||||
|
|
||||||
CREATE TABLE _backup (
|
CREATE TABLE _backup (
|
||||||
@ -164,4 +182,18 @@ FOR EACH ROW INSERT INTO _backup (t_name, id) VALUES ('outputRupee', NEW.id) ON
|
|||||||
CREATE TRIGGER outputRupee_U AFTER UPDATE ON outputRupee
|
CREATE TRIGGER outputRupee_U AFTER UPDATE ON outputRupee
|
||||||
FOR EACH ROW INSERT INTO _backup (t_name, id) VALUES ('outputRupee', NEW.id) ON DUPLICATE KEY UPDATE mode=TRUE, timestamp=DEFAULT;
|
FOR EACH ROW INSERT INTO _backup (t_name, id) VALUES ('outputRupee', NEW.id) ON DUPLICATE KEY UPDATE mode=TRUE, timestamp=DEFAULT;
|
||||||
CREATE TRIGGER outputRupee_D AFTER DELETE ON outputRupee
|
CREATE TRIGGER outputRupee_D AFTER DELETE ON outputRupee
|
||||||
FOR EACH ROW INSERT INTO _backup (t_name, id) VALUES ('outputRupee', OLD.id) ON DUPLICATE KEY UPDATE mode=NULL, timestamp=DEFAULT;
|
FOR EACH ROW INSERT INTO _backup (t_name, id) VALUES ('outputRupee', OLD.id) ON DUPLICATE KEY UPDATE mode=NULL, timestamp=DEFAULT;
|
||||||
|
|
||||||
|
CREATE TRIGGER TagList_I AFTER INSERT ON TagList
|
||||||
|
FOR EACH ROW INSERT INTO _backup (t_name, id) VALUES ('TagList', NEW.id) ON DUPLICATE KEY UPDATE mode=TRUE, timestamp=DEFAULT;
|
||||||
|
CREATE TRIGGER TagList_U AFTER UPDATE ON TagList
|
||||||
|
FOR EACH ROW INSERT INTO _backup (t_name, id) VALUES ('TagList', NEW.id) ON DUPLICATE KEY UPDATE mode=TRUE, timestamp=DEFAULT;
|
||||||
|
CREATE TRIGGER TagList_D AFTER DELETE ON TagList
|
||||||
|
FOR EACH ROW INSERT INTO _backup (t_name, id) VALUES ('TagList', OLD.id) ON DUPLICATE KEY UPDATE mode=NULL, timestamp=DEFAULT;
|
||||||
|
|
||||||
|
CREATE TRIGGER Tags_I AFTER INSERT ON Tags
|
||||||
|
FOR EACH ROW INSERT INTO _backup (t_name, id) VALUES ('Tags', NEW.id) ON DUPLICATE KEY UPDATE mode=TRUE, timestamp=DEFAULT;
|
||||||
|
CREATE TRIGGER Tags_U AFTER UPDATE ON Tags
|
||||||
|
FOR EACH ROW INSERT INTO _backup (t_name, id) VALUES ('Tags', NEW.id) ON DUPLICATE KEY UPDATE mode=TRUE, timestamp=DEFAULT;
|
||||||
|
CREATE TRIGGER Tags_D AFTER DELETE ON Tags
|
||||||
|
FOR EACH ROW INSERT INTO _backup (t_name, id) VALUES ('Tags', OLD.id) ON DUPLICATE KEY UPDATE mode=NULL, timestamp=DEFAULT;
|
||||||
56
public/fn.js
56
public/fn.js
@ -405,4 +405,60 @@ function withdrawRupee(quantity, proxySecret) {
|
|||||||
.catch(error => reject(error)))
|
.catch(error => reject(error)))
|
||||||
.catch(error => reject(error))
|
.catch(error => reject(error))
|
||||||
})
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function addUserTag(floID, tag, proxySecret) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
let request = {
|
||||||
|
user: floID,
|
||||||
|
tag: tag,
|
||||||
|
timestamp: Date.now()
|
||||||
|
};
|
||||||
|
request.sign = signRequest({
|
||||||
|
command: "add_Tag",
|
||||||
|
user: request.user,
|
||||||
|
tag: request.tag,
|
||||||
|
timestamp: request.timestamp
|
||||||
|
}, proxySecret);
|
||||||
|
console.debug(request);
|
||||||
|
|
||||||
|
fetch('/add-tag', {
|
||||||
|
method: "POST",
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
},
|
||||||
|
body: JSON.stringify(request)
|
||||||
|
}).then(result => responseParse(result, false)
|
||||||
|
.then(result => resolve(result))
|
||||||
|
.catch(error => reject(error)))
|
||||||
|
.catch(error => reject(error))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function removeUserTag(floID, tag, proxySecret) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
let request = {
|
||||||
|
user: floID,
|
||||||
|
tag: tag,
|
||||||
|
timestamp: Date.now()
|
||||||
|
};
|
||||||
|
request.sign = signRequest({
|
||||||
|
command: "remove_Tag",
|
||||||
|
user: request.user,
|
||||||
|
tag: request.tag,
|
||||||
|
timestamp: request.timestamp
|
||||||
|
}, proxySecret);
|
||||||
|
console.debug(request);
|
||||||
|
|
||||||
|
fetch('/remove-tag', {
|
||||||
|
method: "POST",
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
},
|
||||||
|
body: JSON.stringify(request)
|
||||||
|
}).then(result => responseParse(result, false)
|
||||||
|
.then(result => resolve(result))
|
||||||
|
.catch(error => reject(error)))
|
||||||
|
.catch(error => reject(error))
|
||||||
|
})
|
||||||
}
|
}
|
||||||
@ -16,7 +16,9 @@ try {
|
|||||||
"sql_host": "localhost",
|
"sql_host": "localhost",
|
||||||
|
|
||||||
"backup-port": "8081",
|
"backup-port": "8081",
|
||||||
"backup-floIDs": []
|
"backup-floIDs": [],
|
||||||
|
|
||||||
|
"trusted-floIDs": []
|
||||||
};
|
};
|
||||||
flag_new = true;
|
flag_new = true;
|
||||||
}
|
}
|
||||||
@ -32,14 +34,14 @@ function flaggedYesOrNo(text) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
function getBackupIDs(ids) {
|
function get_IDs(ids) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
getInput("", "continue").then(id => {
|
getInput.Text("", "continue").then(id => {
|
||||||
if (id === "continue")
|
if (id === "continue")
|
||||||
resolve(Array.from(new Set(ids)));
|
resolve(Array.from(new Set(ids)));
|
||||||
else {
|
else {
|
||||||
ids.push(id);
|
ids.push(id);
|
||||||
getBackupIDs(ids)
|
get_IDs(ids)
|
||||||
.then(result => resolve(result))
|
.then(result => resolve(result))
|
||||||
.catch(error => reject(error));
|
.catch(error => reject(error));
|
||||||
}
|
}
|
||||||
@ -55,8 +57,8 @@ function configureBackup() {
|
|||||||
return resolve(true);
|
return resolve(true);
|
||||||
getInput.YesOrNo('Do you want to add/remove backup floIDs?').then(value => {
|
getInput.YesOrNo('Do you want to add/remove backup floIDs?').then(value => {
|
||||||
if (value) {
|
if (value) {
|
||||||
console("Enter floIDs to add as backup: ");
|
console.log("Enter floIDs to add as backup: ");
|
||||||
getBackupIDs(config["backup-floIDs"]).then(ids => {
|
get_IDs(config["backup-floIDs"]).then(ids => {
|
||||||
//delete backup IDs
|
//delete backup IDs
|
||||||
let tmp_obj = {};
|
let tmp_obj = {};
|
||||||
for (let i in ids) {
|
for (let i in ids) {
|
||||||
@ -84,12 +86,45 @@ function configureBackup() {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function configureTrustedIDs() {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
getInput.YesOrNo('Do you want to add/remove trusted floIDs?').then(value => {
|
||||||
|
if (value) {
|
||||||
|
console.log("Enter floIDs to add as trusted: ");
|
||||||
|
get_IDs(config["trusted-floIDs"]).then(ids => {
|
||||||
|
//delete trusted IDs
|
||||||
|
let tmp_obj = {};
|
||||||
|
for (let i in ids) {
|
||||||
|
console.log(i + 1, ":", ids[i]);
|
||||||
|
tmp_obj[i + 1] = ids[i];
|
||||||
|
}
|
||||||
|
getInput.Text("Enter numbers to delete (seperated by comma)", "continue").then(ri => {
|
||||||
|
if (ri === "continue")
|
||||||
|
config["trusted-floIDs"] = ids;
|
||||||
|
else {
|
||||||
|
for (let i of ri.split(","))
|
||||||
|
delete tmp_obj[parseInt(i)];
|
||||||
|
let tmp_array = [];
|
||||||
|
for (let id of tmp_obj)
|
||||||
|
tmp_array.push(id);
|
||||||
|
config["trusted-floIDs"] = tmp_array;
|
||||||
|
}
|
||||||
|
resolve(true);
|
||||||
|
})
|
||||||
|
})
|
||||||
|
} else
|
||||||
|
resolve(true);
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
function configurePort() {
|
function configurePort() {
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
getInput.Text('Enter port', config["port"]).then(port => {
|
getInput.Text('Enter port', config["port"]).then(port => {
|
||||||
config["port"] = port;
|
config["port"] = port;
|
||||||
configureBackup()
|
configureBackup()
|
||||||
.then(result => resolve(true))
|
.then(_ => configureTrustedIDs()
|
||||||
|
.then(_ => resolve(true)));
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,7 +5,7 @@ const Request = require('./request');
|
|||||||
|
|
||||||
const REFRESH_INTERVAL = 60 * 1000; //1 min
|
const REFRESH_INTERVAL = 60 * 1000; //1 min
|
||||||
|
|
||||||
module.exports = function App(secret, DB) {
|
module.exports = function App(secret, trustedIDs, DB) {
|
||||||
|
|
||||||
const app = express();
|
const app = express();
|
||||||
//session middleware
|
//session middleware
|
||||||
@ -63,6 +63,11 @@ module.exports = function App(secret, DB) {
|
|||||||
app.post('/deposit-rupee', Request.DepositRupee);
|
app.post('/deposit-rupee', Request.DepositRupee);
|
||||||
app.post('/withdraw-rupee', Request.WithdrawRupee);
|
app.post('/withdraw-rupee', Request.WithdrawRupee);
|
||||||
|
|
||||||
|
//Manage user tags (Access to trusted IDs only)
|
||||||
|
Request.trustedIDs = trustedIDs;
|
||||||
|
app.post('/add-tag', Request.addUserTag);
|
||||||
|
app.post('/remove-tag', Request.removeUserTag);
|
||||||
|
|
||||||
Request.DB = DB;
|
Request.DB = DB;
|
||||||
Request.periodicProcess();
|
Request.periodicProcess();
|
||||||
let refresher = setInterval(Request.periodicProcess, REFRESH_INTERVAL);
|
let refresher = setInterval(Request.periodicProcess, REFRESH_INTERVAL);
|
||||||
|
|||||||
369
src/group.js
Normal file
369
src/group.js
Normal file
@ -0,0 +1,369 @@
|
|||||||
|
var DB; //container for database
|
||||||
|
|
||||||
|
function addTag(floID, tag) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
DB.query("INSERT INTO Tags (floID, tag) VALUE (?,?)", [floID, tag])
|
||||||
|
.then(result => resolve(`Added ${floID} to ${tag}`))
|
||||||
|
.catch(error => {
|
||||||
|
if (error.code === "ER_DUP_ENTRY")
|
||||||
|
reject(INVALID(`${floID} already in ${tag}`));
|
||||||
|
else
|
||||||
|
reject(error);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function removeTag(floID, tag) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
DB.query("DELETE FROM Tags WHERE floID=? AND tag=?", [floID, tag])
|
||||||
|
.then(result => resolve(`Removed ${floID} from ${tag}`))
|
||||||
|
.catch(error => reject(error));
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function getBestPairs(currentRate) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
DB.query("SELECT tag, sellPriority, buyPriority FROM TagList").then(result => {
|
||||||
|
//Sorted in Ascending (ie, stack; pop for highest)
|
||||||
|
let tags_buy = result.sort((a, b) => a.buyPriority > b.buyPriority ? 1 : -1).map(r => r.tag);
|
||||||
|
let tags_sell = result.sort((a, b) => a.sellPriority > b.sellPriority ? 1 : -1).map(r => r.tag);
|
||||||
|
resolve(new bestPair(currentRate, tags_buy, tags_sell));
|
||||||
|
}).catch(error => reject(error))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const bestPair = function(cur_rate, tags_buy, tags_sell) {
|
||||||
|
const currentRate = cur_rate;
|
||||||
|
|
||||||
|
Object.defineProperty(this, 'cur_rate', {
|
||||||
|
get: () => currentRate
|
||||||
|
});
|
||||||
|
|
||||||
|
this.get = () => new Promise((resolve, reject) => {
|
||||||
|
Promise.all([getBuyOrder(), getSellOrder()]).then(results => {
|
||||||
|
resolve({
|
||||||
|
buyOrder: results[0],
|
||||||
|
sellOrder: results[1],
|
||||||
|
null_base: getSellOrder.cache.mode_null
|
||||||
|
})
|
||||||
|
}).catch(error => reject(error))
|
||||||
|
});
|
||||||
|
|
||||||
|
this.next = (tx_quantity, incomplete_sell, flag_sell) => {
|
||||||
|
let buy = getBuyOrder.cache,
|
||||||
|
sell = getSellOrder.cache;
|
||||||
|
if (buy.cur_order && sell.cur_order) {
|
||||||
|
//buy order
|
||||||
|
if (tx_quantity < buy.cur_order.quantity)
|
||||||
|
buy.cur_order.quantity -= tx_quantity;
|
||||||
|
else if (tx_quantity == buy.cur_order.quantity)
|
||||||
|
buy.cur_order = null;
|
||||||
|
else
|
||||||
|
throw Error("Tx quantity cannot be more than order quantity");
|
||||||
|
//sell order
|
||||||
|
if (tx_quantity < sell.cur_order.quantity) {
|
||||||
|
sell.cur_order.quantity -= tx_quantity;
|
||||||
|
if (incomplete_sell) {
|
||||||
|
if (!sell.mode_null && flag_sell)
|
||||||
|
sell.null_queue.push(sell.cur_order);
|
||||||
|
sell.cur_order = null;
|
||||||
|
}
|
||||||
|
} else if (tx_quantity == sell.cur_order.quantity)
|
||||||
|
sell.cur_order = null;
|
||||||
|
else
|
||||||
|
throw Error("Tx quantity cannot be more than order quantity");
|
||||||
|
} else
|
||||||
|
throw Error("No current order found");
|
||||||
|
};
|
||||||
|
|
||||||
|
const getSellOrder = () => new Promise((resolve, reject) => {
|
||||||
|
let cache = getSellOrder.cache;
|
||||||
|
if (cache.cur_order) { //If cache already has a pending order
|
||||||
|
verifySellOrder(cache.cur_order, currentRate, cache.mode_null).then(result => {
|
||||||
|
cache.cur_order = result;
|
||||||
|
resolve(result);
|
||||||
|
}).catch(error => {
|
||||||
|
if (error !== false)
|
||||||
|
return reject(error);
|
||||||
|
//Order not valid (minimum gain)
|
||||||
|
cache.cur_order = null;
|
||||||
|
getSellOrder()
|
||||||
|
.then(result => resolve(result))
|
||||||
|
.catch(error => reject(error))
|
||||||
|
})
|
||||||
|
} else if (cache.orders && cache.orders.length) { //If cache already has orders in priority
|
||||||
|
getTopValidSellOrder(cache.orders, currentRate, cache.mode_null).then(result => {
|
||||||
|
cache.cur_order = result;
|
||||||
|
resolve(result);
|
||||||
|
}).catch(error => {
|
||||||
|
if (error !== false)
|
||||||
|
return reject(error);
|
||||||
|
//No valid order found in current tag
|
||||||
|
cache.orders = null;
|
||||||
|
getSellOrder()
|
||||||
|
.then(result => resolve(result))
|
||||||
|
.catch(error => reject(error))
|
||||||
|
})
|
||||||
|
} else if (cache.tags.length) { //If cache has remaining tags
|
||||||
|
cache.cur_tag = cache.tags.pop();
|
||||||
|
getSellOrdersInTag(cache.cur_tag, currentRate).then(orders => {
|
||||||
|
cache.orders = orders;
|
||||||
|
getSellOrder()
|
||||||
|
.then(result => resolve(result))
|
||||||
|
.catch(error => reject(error))
|
||||||
|
}).catch(error => reject(error));
|
||||||
|
} else if (!cache.end) { //Un-tagged floID's orders (do only once)
|
||||||
|
getUntaggedSellOrders(currentRate).then(orders => {
|
||||||
|
cache.orders = orders;
|
||||||
|
cache.cur_tag = null;
|
||||||
|
cache.end = true;
|
||||||
|
getSellOrder()
|
||||||
|
.then(result => resolve(result))
|
||||||
|
.catch(error => reject(error))
|
||||||
|
}).catch(error => reject(error));
|
||||||
|
} else if (!mode_null) { //Lowest priority Coins (FLO Brought from other sources)
|
||||||
|
cache.orders = cache.null_queue.reverse(); //Reverse it so that we can pop the highest priority
|
||||||
|
cache.mode_null = true;
|
||||||
|
cache.null_queue = null;
|
||||||
|
getSellOrder()
|
||||||
|
.then(result => resolve(result))
|
||||||
|
.catch(error => reject(error))
|
||||||
|
} else
|
||||||
|
reject(false);
|
||||||
|
});
|
||||||
|
getSellOrder.cache = {
|
||||||
|
tags: tags_sell,
|
||||||
|
null_queue: [],
|
||||||
|
mode_null: false
|
||||||
|
};
|
||||||
|
|
||||||
|
const getBuyOrder = () => new Promise((resolve, reject) => {
|
||||||
|
let cache = getBuyOrder.cache;
|
||||||
|
if (cache.cur_order) { //If cache already has a pending order
|
||||||
|
verifyBuyOrder(cache.cur_order, currentRate).then(result => {
|
||||||
|
cache.cur_order = result;
|
||||||
|
resolve(result);
|
||||||
|
}).catch(error => {
|
||||||
|
if (error !== false)
|
||||||
|
return reject(error);
|
||||||
|
//Order not valid (cash not available)
|
||||||
|
cache.cur_order = null;
|
||||||
|
getBuyOrder()
|
||||||
|
.then(result => resolve(result))
|
||||||
|
.catch(error => reject(error))
|
||||||
|
})
|
||||||
|
} else if (cache.orders && cache.orders.length) { //If cache already has orders in priority
|
||||||
|
getTopValidBuyOrder(cache.orders, currentRate).then(result => {
|
||||||
|
cache.cur_order = result;
|
||||||
|
resolve(result);
|
||||||
|
}).catch(error => {
|
||||||
|
if (error !== false)
|
||||||
|
return reject(error);
|
||||||
|
//No valid order found in current tag
|
||||||
|
cache.orders = null;
|
||||||
|
getBuyOrder()
|
||||||
|
.then(result => resolve(result))
|
||||||
|
.catch(error => reject(error))
|
||||||
|
})
|
||||||
|
} else if (cache.tags.length) { //If cache has remaining tags
|
||||||
|
cache.cur_tag = cache.tags.pop();
|
||||||
|
getBuyOrdersInTag(cache.cur_tag, currentRate).then(orders => {
|
||||||
|
cache.orders = orders;
|
||||||
|
getBuyOrder()
|
||||||
|
.then(result => resolve(result))
|
||||||
|
.catch(error => reject(error))
|
||||||
|
}).catch(error => reject(error));
|
||||||
|
} else if (!cache.end) { //Un-tagged floID's orders (do only once)
|
||||||
|
getUntaggedBuyOrders(currentRate).then(orders => {
|
||||||
|
cache.orders = orders;
|
||||||
|
cache.cur_tag = null;
|
||||||
|
cache.end = true;
|
||||||
|
getBuyOrder()
|
||||||
|
.then(result => resolve(result))
|
||||||
|
.catch(error => reject(error))
|
||||||
|
}).catch(error => reject(error));
|
||||||
|
} else
|
||||||
|
reject(false);
|
||||||
|
});
|
||||||
|
getBuyOrder.cache = {
|
||||||
|
tags: tags_buy
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function getUntaggedSellOrders(cur_price) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
DB.query("SELECT SellOrder.id, SellOrder.floID, SellOrder.quantity FROM SellOrder" +
|
||||||
|
" LEFT JOIN Tags ON Tags.floID = SellOrder.floID" +
|
||||||
|
" WHERE Tags.floID IS NULL AND SellOrder.minPrice <=? ORDER BY SellOrder.time_placed DESC", [cur_price])
|
||||||
|
.then(orders => resolve(orders))
|
||||||
|
.catch(error => reject(error))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function getUntaggedBuyOrders(cur_price) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
DB.query("SELECT BuyOrder.id, BuyOrder.floID, BuyOrder.quantity FROM BuyOrder" +
|
||||||
|
" LEFT JOIN Tags ON Tags.floID = BuyOrder.floID" +
|
||||||
|
" WHERE Tags.floID IS NULL AND BuyOrder.maxPrice >=? ORDER BY BuyOrder.time_placed DESC", [cur_price])
|
||||||
|
.then(orders => resolve(orders))
|
||||||
|
.catch(error => reject(error))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function getSellOrdersInTag(tag, cur_price) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
DB.query("SELECT SellOrder.id, SellOrder.floID, SellOrder.quantity FROM SellOrder" +
|
||||||
|
" INNER JOIN Tags ON Tags.floID = SellOrder.floID" +
|
||||||
|
" WHERE Tags.tag = ? AND SellOrder.minPrice <=? ORDER BY SellOrder.time_placed DESC", [tag, cur_price]).then(orders => {
|
||||||
|
if (orders.length <= 1) // No (or) Only-one order, hence priority sort not required.
|
||||||
|
resolve(orders);
|
||||||
|
else
|
||||||
|
getPointsFromAPI(tag, orders.map(o => o.floID)).then(points => {
|
||||||
|
let orders_sorted = orders.map(o => [o, points[o.floID]])
|
||||||
|
.sort((a, b) => a[1] > b[1] ? -1 : a[1] < b[1] ? 1 : 0) //sort by points (ascending)
|
||||||
|
.map(x => x[0]);
|
||||||
|
resolve(orders_sorted);
|
||||||
|
}).catch(error => reject(error))
|
||||||
|
}).catch(error => reject(error))
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function getBuyOrdersInTag(tag, cur_price) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
DB.query("SELECT BuyOrder.id, BuyOrder.floID, BuyOrder.quantity FROM BuyOrder" +
|
||||||
|
" INNER JOIN Tags ON Tags.floID = BuyOrder.floID" +
|
||||||
|
" WHERE Tags.tag = ? AND BuyOrder.maxPrice >=? ORDER BY BuyOrder.time_placed DESC", [tag, cur_price]).then(orders => {
|
||||||
|
if (orders.length <= 1) // No (or) Only-one order, hence priority sort not required.
|
||||||
|
resolve(orders);
|
||||||
|
else
|
||||||
|
getPointsFromAPI(tag, orders.map(o => o.floID)).then(points => {
|
||||||
|
let orders_sorted = orders.map(o => [o, points[o.floID]])
|
||||||
|
.sort((a, b) => a[1] > b[1] ? -1 : a[1] < b[1] ? 1 : 0) //sort by points (ascending)
|
||||||
|
.map(x => x[0]);
|
||||||
|
resolve(orders_sorted);
|
||||||
|
}).catch(error => reject(error))
|
||||||
|
}).catch(error => reject(error))
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function getPointsFromAPI(tag, floIDs) {
|
||||||
|
floIDs = Array.from(new Set(floIDs));
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
DB.query("SELECT api FROM TagList WHERE tag=?", [tag]).then(result => {
|
||||||
|
let api = result[0].api;
|
||||||
|
Promise.allSettled(floIDs.map(id => fetch_api(api, id))).then(result => {
|
||||||
|
let points = {};
|
||||||
|
for (let i in result)
|
||||||
|
if (result[i].status === "fulfilled")
|
||||||
|
points[floIDs[i]] = result[i].value;
|
||||||
|
resolve(points);
|
||||||
|
}).catch(error => reject(error))
|
||||||
|
}).catch(error => reject(error))
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function fetch_api(api, id) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
//TODO: fetch data from API
|
||||||
|
let url = api.replace('<flo-id>', id);
|
||||||
|
global.fetch(url).then(response => {
|
||||||
|
if (response.ok)
|
||||||
|
response.text()
|
||||||
|
.then(result => resolve(result))
|
||||||
|
.catch(error => reject(error))
|
||||||
|
else
|
||||||
|
reject(response);
|
||||||
|
}).catch(error => reject(error))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function getTopValidSellOrder(orders, cur_price, mode_null) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
if (!orders.length)
|
||||||
|
return reject(false)
|
||||||
|
verifySellOrder(orders.pop(), cur_price, mode_null) //pop: as the orders are sorted in ascending (highest point should be checked 1st)
|
||||||
|
.then(result => resolve(result))
|
||||||
|
.catch(error => {
|
||||||
|
if (error !== false)
|
||||||
|
return reject(error);
|
||||||
|
getTopValidSellOrder(orders, cur_price, mode_null)
|
||||||
|
.then(result => resolve(result))
|
||||||
|
.catch(error => reject(error));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function verifySellOrder(sellOrder, cur_price, mode_null) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
if (!mode_null)
|
||||||
|
DB.query("SELECT quantity, base FROM Vault WHERE floID=? AND base IS NOT NULL ORDER BY base", [sellOrder.floID]).then(result => {
|
||||||
|
let rem = sellOrder.quantity,
|
||||||
|
sell_base = 0,
|
||||||
|
base_quantity = 0;
|
||||||
|
for (let i = 0; i < result.length && rem > 0; i++) {
|
||||||
|
if (rem < result[i].quantity) {
|
||||||
|
sell_base += (rem * result[i].base);
|
||||||
|
base_quantity += rem;
|
||||||
|
rem = 0;
|
||||||
|
} else {
|
||||||
|
sell_base += (result[i].quantity * result[i].base);
|
||||||
|
base_quantity += result[i].quantity;
|
||||||
|
rem -= result[i].quantity;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (base_quantity)
|
||||||
|
sell_base = sell_base / base_quantity;
|
||||||
|
if (sell_base > cur_price)
|
||||||
|
reject(false);
|
||||||
|
else
|
||||||
|
resolve(sellOrder);
|
||||||
|
}).catch(error => reject(error));
|
||||||
|
else if (mode_null)
|
||||||
|
DB.query("SELECT SUM(quantity) as total FROM Vault WHERE floID=?", [sellOrder.floID]).then(result => {
|
||||||
|
if (result.total < sellOrder.quantity)
|
||||||
|
console.warn(`Sell Order ${sellOrder.id} was made without enough FLO. This should not happen`);
|
||||||
|
if (result.total > 0)
|
||||||
|
resolve(sellOrder);
|
||||||
|
else
|
||||||
|
reject(false);
|
||||||
|
}).catch(error => reject(error))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function getTopValidBuyOrder(orders, cur_price) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
if (!orders.length)
|
||||||
|
return reject(false)
|
||||||
|
verifyBuyOrder(orders.pop(), cur_price) //pop: as the orders are sorted in ascending (highest point should be checked 1st)
|
||||||
|
.then(result => resolve(result))
|
||||||
|
.catch(error => {
|
||||||
|
if (error !== false)
|
||||||
|
return reject(error);
|
||||||
|
getTopValidBuyOrder(orders, cur_price)
|
||||||
|
.then(result => resolve(result))
|
||||||
|
.catch(error => reject(error));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function verifyBuyOrder(buyOrder, cur_price) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
DB.query("SELECT rupeeBalance AS bal FROM Cash WHERE floID=?", [buyOrder.floID]).then(result => {
|
||||||
|
if (result[0].bal < cur_price * buyOrder.quantity) {
|
||||||
|
//This should not happen unless a buy order is placed when user doesnt have enough rupee balance
|
||||||
|
console.warn(`Buy order ${buyOrder.id} is active, but rupee# is insufficient`);
|
||||||
|
reject(false);
|
||||||
|
} else
|
||||||
|
resolve(buyOrder);
|
||||||
|
}).catch(error => reject(error));
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
addTag,
|
||||||
|
removeTag,
|
||||||
|
getBestPairs,
|
||||||
|
set DB(db) {
|
||||||
|
DB = db;
|
||||||
|
}
|
||||||
|
};
|
||||||
@ -36,7 +36,7 @@ module.exports = function startServer(public_dir) {
|
|||||||
console.debug(PUBLIC_DIR, global.myFloID);
|
console.debug(PUBLIC_DIR, global.myFloID);
|
||||||
|
|
||||||
Database(config["sql_user"], config["sql_pwd"], config["sql_db"], config["sql_host"]).then(DB => {
|
Database(config["sql_user"], config["sql_pwd"], config["sql_db"], config["sql_host"]).then(DB => {
|
||||||
const app = App(config['secret'], DB);
|
const app = App(config['secret'], config['trusted-floIDs'], DB);
|
||||||
app.listen(PORT, () => console.log(`Server Running at port ${PORT}`));
|
app.listen(PORT, () => console.log(`Server Running at port ${PORT}`));
|
||||||
//start backup
|
//start backup
|
||||||
if (config["backup-port"] && config["backup-floIDs"].length) {
|
if (config["backup-port"] && config["backup-floIDs"].length) {
|
||||||
|
|||||||
165
src/market.js
165
src/market.js
@ -1,3 +1,5 @@
|
|||||||
|
const group = require("./group");
|
||||||
|
|
||||||
var net_FLO_price; //container for FLO price (from API or by model)
|
var net_FLO_price; //container for FLO price (from API or by model)
|
||||||
var DB; //container for database
|
var DB; //container for database
|
||||||
|
|
||||||
@ -168,124 +170,80 @@ function cancelOrder(type, id, floID) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function matchBuyAndSell() {
|
function initiateCoupling() {
|
||||||
let cur_price = net_FLO_price;
|
group.getBestPairs(net_FLO_price)
|
||||||
//get the best buyer
|
.then(bestPairQueue => processCoupling(bestPairQueue))
|
||||||
getBestBuyer(cur_price).then(buyer_best => {
|
.catch(error => console.error("initiateCoupling", error))
|
||||||
//get the best seller
|
|
||||||
getBestSeller(buyer_best.quantity, cur_price).then(result => {
|
|
||||||
let seller_best = result.sellOrder,
|
|
||||||
txQueries = result.txQueries;
|
|
||||||
console.debug("Sell:", seller_best.id, "Buy:", buyer_best.id);
|
|
||||||
|
|
||||||
//process the Txn
|
|
||||||
var tx_quantity;
|
|
||||||
if (seller_best.quantity > buyer_best.quantity)
|
|
||||||
tx_quantity = processBuyOrder(seller_best, buyer_best, txQueries);
|
|
||||||
else if (seller_best.quantity < buyer_best.quantity)
|
|
||||||
tx_quantity = processSellOrder(seller_best, buyer_best, txQueries);
|
|
||||||
else
|
|
||||||
tx_quantity = processBuyAndSellOrder(seller_best, buyer_best, txQueries);
|
|
||||||
updateBalance(seller_best, buyer_best, txQueries, cur_price, tx_quantity);
|
|
||||||
//process txn query in SQL
|
|
||||||
DB.transaction(txQueries).then(results => {
|
|
||||||
console.log(`Transaction was successful! BuyOrder:${buyer_best.id}| SellOrder:${seller_best.id}`);
|
|
||||||
//Since a tx was successful, match again
|
|
||||||
matchBuyAndSell();
|
|
||||||
}).catch(error => console.error(error));
|
|
||||||
}).catch(error => console.error(error));
|
|
||||||
}).catch(error => console.error(error));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function getBestBuyer(cur_price, n = 0) {
|
function processCoupling(bestPairQueue) {
|
||||||
return new Promise((resolve, reject) => {
|
bestPairQueue.get().then(pair_result => {
|
||||||
DB.query("SELECT * FROM BuyOrder WHERE maxPrice >= ? ORDER BY time_placed LIMIT ?,1", [cur_price, n]).then(result => {
|
let buyer_best = pair_result.buyOrder,
|
||||||
let buyOrder = result.shift();
|
seller_best = pair_result.sellOrder;
|
||||||
if (!buyOrder)
|
console.debug("Sell:", seller_best);
|
||||||
return reject("No valid buyers available");
|
console.debug("Buy:", buyer_best);
|
||||||
DB.query("SELECT rupeeBalance AS bal FROM Cash WHERE floID=?", [buyOrder.floID]).then(result => {
|
spendFLO(buyer_best, seller_best, pair_result.null_base).then(spend_result => {
|
||||||
if (result[0].bal < cur_price * buyOrder.quantity) {
|
let tx_quantity = spend_result.quantity,
|
||||||
//This should not happen unless a buy order is placed when user doesnt have enough rupee balance
|
txQueries = spend_result.txQueries,
|
||||||
console.warn(`Buy order ${buyOrder.id} is active, but rupee# is insufficient`);
|
clear_sell = spend_result.incomplete && !spend_result.flag_baseNull; //clear_sell can be true only if an order is placed without enough FLO
|
||||||
getBestBuyer(cur_price, n + 1)
|
processOrders(seller_best, buyer_best, txQueries, tx_quantity, clear_sell);
|
||||||
.then(result => resolve(result))
|
updateBalance(seller_best, buyer_best, txQueries, bestPairQueue.cur_rate, tx_quantity);
|
||||||
.catch(error => reject(error));
|
//process txn query in SQL
|
||||||
} else
|
DB.transaction(txQueries).then(_ => {
|
||||||
resolve(buyOrder);
|
bestPairQueue.next(quantity, spend_result.incomplete, spend_result.flag_baseNull);
|
||||||
}).catch(error => reject(error));
|
console.log(`Transaction was successful! BuyOrder:${buyer_best.id}| SellOrder:${seller_best.id}`);
|
||||||
}).catch(error => reject(error));
|
//Since a tx was successful, match again
|
||||||
|
processCoupling(bestPairQueue);
|
||||||
|
}).catch(error => console.error(error));
|
||||||
|
}).catch(error => console.error(error));
|
||||||
|
}).catch(error => {
|
||||||
|
if (error !== false)
|
||||||
|
console.error(error);
|
||||||
|
else
|
||||||
|
console.log("No valid orders.");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function getBestSeller(maxQuantity, cur_price, n = 0) {
|
function spendFLO(buyOrder, sellOrder, null_base) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
//TODO: Add order conditions for priority.
|
DB.query("SELECT id, quantity, base FROM Vault WHERE floID=? ORDER BY base", [sellOrder.floID]).then(result => {
|
||||||
DB.query("SELECT * FROM SellOrder WHERE minPrice <=? ORDER BY time_placed LIMIT ?,1", [cur_price, n]).then(result => {
|
let rem = Math.min(buyOrder.quantity, sellOrder.quantity),
|
||||||
let sellOrder = result.shift();
|
txQueries = []
|
||||||
if (!sellOrder)
|
flag_baseNull = false;
|
||||||
return reject("No valid sellers available");
|
for (let i = 0; i < result.length && rem > 0; i++)
|
||||||
DB.query("SELECT id, quantity, base FROM Vault WHERE floID=? ORDER BY base", [sellOrder.floID]).then(result => {
|
if (result[i].base || null_base) {
|
||||||
let rem = Math.min(sellOrder.quantity, maxQuantity),
|
|
||||||
sell_base = 0,
|
|
||||||
base_quantity = 0,
|
|
||||||
txQueries = [];
|
|
||||||
for (let i = 0; i < result.length && rem > 0; i++) {
|
|
||||||
if (rem < result[i].quantity) {
|
if (rem < result[i].quantity) {
|
||||||
txQueries.push(["UPDATE Vault SET quantity=quantity-? WHERE id=?", [rem, result[i].id]]);
|
txQueries.push(["UPDATE Vault SET quantity=quantity-? WHERE id=?", [rem, result[i].id]]);
|
||||||
if (result[i].base) {
|
|
||||||
sell_base += (rem * result[i].base);
|
|
||||||
base_quantity += rem
|
|
||||||
}
|
|
||||||
rem = 0;
|
rem = 0;
|
||||||
} else {
|
} else {
|
||||||
txQueries.push(["DELETE FROM Vault WHERE id=?", [result[i].id]]);
|
txQueries.push(["DELETE FROM Vault WHERE id=?", [result[i].id]]);
|
||||||
if (result[i].base) {
|
|
||||||
sell_base += (result[i].quantity * result[i].base);
|
|
||||||
base_quantity += result[i].quantity
|
|
||||||
}
|
|
||||||
rem -= result[i].quantity;
|
rem -= result[i].quantity;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if (base_quantity)
|
|
||||||
sell_base = sell_base / base_quantity;
|
|
||||||
if (rem > 0 || sell_base > cur_price) {
|
|
||||||
//1st condition (rem>0) should not happen (sell order placement was success when insufficient FLO).
|
|
||||||
if (rem > 0)
|
|
||||||
console.warn(`Sell order ${sellOrder.id} is active, but FLO is insufficient`);
|
|
||||||
getBestSeller(maxQuantity, cur_price, n + 1)
|
|
||||||
.then(result => resolve(result))
|
|
||||||
.catch(error => reject(error));
|
|
||||||
} else
|
} else
|
||||||
resolve({
|
flag_baseNull = true;
|
||||||
sellOrder,
|
resolve({
|
||||||
txQueries
|
quantity: Math.min(buyOrder.quantity, sellOrder.quantity) - rem,
|
||||||
});
|
txQueries,
|
||||||
}).catch(error => reject(error));
|
incomplete: rem > 0,
|
||||||
|
flag_baseNull
|
||||||
|
});
|
||||||
}).catch(error => reject(error));
|
}).catch(error => reject(error));
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
function processBuyOrder(seller_best, buyer_best, txQueries) {
|
function processOrders(seller_best, buyer_best, txQueries, quantity, clear_sell) {
|
||||||
let quantity = buyer_best.quantity;
|
if (quantity > buyer_best.quantity || quantity > seller_best.quantity)
|
||||||
//Buy order is completed, sell order is partially done.
|
throw Error("Tx quantity cannot be more than order quantity");
|
||||||
txQueries.push(["DELETE FROM BuyOrder WHERE id=?", [buyer_best.id]]);
|
//Process Buy Order
|
||||||
txQueries.push(["UPDATE SellOrder SET quantity=quantity-? WHERE id=?", [quantity, seller_best.id]]);
|
if (quantity == buyer_best.quantity)
|
||||||
return quantity;
|
txQueries.push(["DELETE FROM BuyOrder WHERE id=?", [buyer_best.id]]);
|
||||||
}
|
else
|
||||||
|
txQueries.push(["UPDATE BuyOrder SET quantity=quantity-? WHERE id=?", [quantity, buyer_best.id]]);
|
||||||
function processSellOrder(seller_best, buyer_best, txQueries) {
|
//Process Sell Order
|
||||||
let quantity = seller_best.quantity;
|
if (quantity == seller_best.quantity || clear_sell)
|
||||||
//Sell order is completed, buy order is partially done.
|
txQueries.push(["DELETE FROM SellOrder WHERE id=?", [seller_best.id]]);
|
||||||
txQueries.push(["DELETE FROM SellOrder WHERE id=?", [seller_best.id]]);
|
else
|
||||||
txQueries.push(["UPDATE BuyOrder SET quantity=quantity-? WHERE id=?", [quantity, buyer_best.id]]);
|
txQueries.push(["UPDATE SellOrder SET quantity=quantity-? WHERE id=?", [quantity, seller_best.id]]);
|
||||||
return quantity;
|
|
||||||
}
|
|
||||||
|
|
||||||
function processBuyAndSellOrder(seller_best, buyer_best, txQueries) {
|
|
||||||
//Both sell order and buy order is completed
|
|
||||||
txQueries.push(["DELETE FROM SellOrder WHERE id=?", [seller_best.id]]);
|
|
||||||
txQueries.push(["DELETE FROM BuyOrder WHERE id=?", [buyer_best.id]]);
|
|
||||||
return seller_best.quantity;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateBalance(seller_best, buyer_best, txQueries, cur_price, quantity) {
|
function updateBalance(seller_best, buyer_best, txQueries, cur_price, quantity) {
|
||||||
@ -297,7 +255,6 @@ function updateBalance(seller_best, buyer_best, txQueries, cur_price, quantity)
|
|||||||
txQueries.push(["INSERT INTO Vault(floID, base, quantity) VALUES (?, ?, ?)", [buyer_best.floID, cur_price, quantity]])
|
txQueries.push(["INSERT INTO Vault(floID, base, quantity) VALUES (?, ?, ?)", [buyer_best.floID, cur_price, quantity]])
|
||||||
//Record transaction
|
//Record transaction
|
||||||
txQueries.push(["INSERT INTO Transactions (seller, buyer, quantity, unitValue) VALUES (?, ?, ?, ?)", [seller_best.floID, buyer_best.floID, quantity, cur_price]]);
|
txQueries.push(["INSERT INTO Transactions (seller, buyer, quantity, unitValue) VALUES (?, ?, ?, ?)", [seller_best.floID, buyer_best.floID, quantity, cur_price]]);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function getAccountDetails(floID) {
|
function getAccountDetails(floID) {
|
||||||
@ -643,7 +600,7 @@ function periodicProcess() {
|
|||||||
let old_rate = net_FLO_price;
|
let old_rate = net_FLO_price;
|
||||||
getRates().then(cur_rate => {
|
getRates().then(cur_rate => {
|
||||||
transactionReCheck();
|
transactionReCheck();
|
||||||
matchBuyAndSell();
|
initiateCoupling();
|
||||||
}).catch(error => console.error(error));
|
}).catch(error => console.error(error));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -667,7 +624,9 @@ module.exports = {
|
|||||||
depositRupee,
|
depositRupee,
|
||||||
withdrawRupee,
|
withdrawRupee,
|
||||||
periodicProcess,
|
periodicProcess,
|
||||||
|
group,
|
||||||
set DB(db) {
|
set DB(db) {
|
||||||
DB = db;
|
DB = db;
|
||||||
|
group.DB = db;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -1,5 +1,5 @@
|
|||||||
const market = require("./market");
|
const market = require("./market");
|
||||||
var DB; //container for database
|
var DB, trustedIDs; //container for database
|
||||||
|
|
||||||
global.INVALID = function(message) {
|
global.INVALID = function(message) {
|
||||||
if (!(this instanceof INVALID))
|
if (!(this instanceof INVALID))
|
||||||
@ -276,8 +276,11 @@ function Account(req, res) {
|
|||||||
setLogin("Session Expired! Re-login required");
|
setLogin("Session Expired! Re-login required");
|
||||||
else {
|
else {
|
||||||
let floID = req.session.user_id;
|
let floID = req.session.user_id;
|
||||||
market.getAccountDetails(floID)
|
market.getAccountDetails(floID).then(result => {
|
||||||
.then(result => res.send(result));
|
if (trustedIDs.includes(floID))
|
||||||
|
result.subAdmin = true;
|
||||||
|
res.send(result)
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}).catch(_ => res.status(INTERNAL.e_code).send("Try again later!"));
|
}).catch(_ => res.status(INTERNAL.e_code).send("Try again later!"));
|
||||||
}
|
}
|
||||||
@ -407,6 +410,75 @@ function WithdrawRupee(req, res) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function addUserTag(req, res) {
|
||||||
|
let data = req.body,
|
||||||
|
session = req.session;
|
||||||
|
if (!session.user_id)
|
||||||
|
return res.status(INVALID.e_code).send("Login required");
|
||||||
|
else if (!trustedIDs.includes(session.user_id))
|
||||||
|
return res.status(INVALID.e_code).send("Access Denied");
|
||||||
|
validateRequestFromFloID({
|
||||||
|
command: "add_Tag",
|
||||||
|
user: data.user,
|
||||||
|
tag: data.tag,
|
||||||
|
timestamp: data.timestamp
|
||||||
|
}, data.sign, session.user_id).then(req_str => {
|
||||||
|
market.group.addTag(data.user, data.tag).then(result => {
|
||||||
|
storeRequest(session.user_id, req_str, data.sign);
|
||||||
|
res.send(result);
|
||||||
|
}).catch(error => {
|
||||||
|
if (error instanceof INVALID)
|
||||||
|
res.status(INVALID.e_code).send(error.message);
|
||||||
|
else {
|
||||||
|
console.error(error);
|
||||||
|
res.status(INTERNAL.e_code).send("Request processing failed! Try again later!");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}).catch(error => {
|
||||||
|
if (error instanceof INVALID)
|
||||||
|
res.status(INVALID.e_code).send(error.message);
|
||||||
|
else {
|
||||||
|
console.error(error);
|
||||||
|
res.status(INTERNAL.e_code).send("Request processing failed! Try again later!");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function removeUserTag(req, res) {
|
||||||
|
let data = req.body,
|
||||||
|
session = req.session;
|
||||||
|
if (!session.user_id)
|
||||||
|
return res.status(INVALID.e_code).send("Login required");
|
||||||
|
else if (!trustedIDs.includes(session.user_id))
|
||||||
|
return res.status(INVALID.e_code).send("Access Denied");
|
||||||
|
else
|
||||||
|
validateRequestFromFloID({
|
||||||
|
command: "remove_Tag",
|
||||||
|
user: data.user,
|
||||||
|
tag: data.tag,
|
||||||
|
timestamp: data.timestamp
|
||||||
|
}, data.sign, session.user_id).then(req_str => {
|
||||||
|
market.group.removeTag(data.user, data.tag).then(result => {
|
||||||
|
storeRequest(session.user_id, req_str, data.sign);
|
||||||
|
res.send(result);
|
||||||
|
}).catch(error => {
|
||||||
|
if (error instanceof INVALID)
|
||||||
|
res.status(INVALID.e_code).send(error.message);
|
||||||
|
else {
|
||||||
|
console.error(error);
|
||||||
|
res.status(INTERNAL.e_code).send("Request processing failed! Try again later!");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}).catch(error => {
|
||||||
|
if (error instanceof INVALID)
|
||||||
|
res.status(INVALID.e_code).send(error.message);
|
||||||
|
else {
|
||||||
|
console.error(error);
|
||||||
|
res.status(INTERNAL.e_code).send("Request processing failed! Try again later!");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
SignUp,
|
SignUp,
|
||||||
Login,
|
Login,
|
||||||
@ -424,6 +496,11 @@ module.exports = {
|
|||||||
DepositRupee,
|
DepositRupee,
|
||||||
WithdrawRupee,
|
WithdrawRupee,
|
||||||
periodicProcess: market.periodicProcess,
|
periodicProcess: market.periodicProcess,
|
||||||
|
addUserTag,
|
||||||
|
removeUserTag,
|
||||||
|
set trustedIDs(ids) {
|
||||||
|
trustedIDs = ids;
|
||||||
|
},
|
||||||
set DB(db) {
|
set DB(db) {
|
||||||
DB = db;
|
DB = db;
|
||||||
market.DB = db;
|
market.DB = db;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user