Priority case: FLO brought from outside

FLO brought from outside the source will be processed after those brought from source-market.
This commit is contained in:
sairajzero 2021-11-25 05:10:39 +05:30
parent 5ac3316008
commit a7c96e9ce2
2 changed files with 105 additions and 91 deletions

View File

@ -43,25 +43,35 @@ const bestPair = function(cur_rate, tags_buy, tags_sell) {
Promise.all([getBuyOrder(), getSellOrder()]).then(results => { Promise.all([getBuyOrder(), getSellOrder()]).then(results => {
resolve({ resolve({
buyOrder: results[0], buyOrder: results[0],
sellOrder: results[1] sellOrder: results[1],
null_base: getSellOrder.cache.mode_null
}) })
}).catch(error => reject(error)) }).catch(error => reject(error))
}); });
this.next = () => { this.next = (tx_quantity, incomplete_sell, flag_sell) => {
let buy = getBuyOrder.cache, let buy = getBuyOrder.cache,
sell = getSellOrder.cache; sell = getSellOrder.cache;
if (buy.cur_order && sell.cur_order) { if (buy.cur_order && sell.cur_order) {
if (buy.cur_order.quantity > sell.cur_order.quantity) { //buy order
buy.cur_order.quantity -= sell.cur_order.quantity; if (tx_quantity < buy.cur_order.quantity)
sell.cur_order = null; buy.cur_order.quantity -= tx_quantity;
} else if (buy.cur_order.quantity < sell.cur_order.quantity) { else if (tx_quantity == buy.cur_order.quantity)
sell.cur_order.quantity -= buy.cur_order.quantity;
buy.cur_order = null; buy.cur_order = null;
} else { 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; sell.cur_order = null;
buy.cur_order = null; else
} throw Error("Tx quantity cannot be more than order quantity");
} else } else
throw Error("No current order found"); throw Error("No current order found");
}; };
@ -69,7 +79,7 @@ const bestPair = function(cur_rate, tags_buy, tags_sell) {
const getSellOrder = () => new Promise((resolve, reject) => { const getSellOrder = () => new Promise((resolve, reject) => {
let cache = getSellOrder.cache; let cache = getSellOrder.cache;
if (cache.cur_order) { //If cache already has a pending order if (cache.cur_order) { //If cache already has a pending order
verifySellOrder(cache.cur_order, currentRate).then(result => { verifySellOrder(cache.cur_order, currentRate, cache.mode_null).then(result => {
cache.cur_order = result; cache.cur_order = result;
resolve(result); resolve(result);
}).catch(error => { }).catch(error => {
@ -82,7 +92,7 @@ const bestPair = function(cur_rate, tags_buy, tags_sell) {
.catch(error => reject(error)) .catch(error => reject(error))
}) })
} else if (cache.orders && cache.orders.length) { //If cache already has orders in priority } else if (cache.orders && cache.orders.length) { //If cache already has orders in priority
getTopValidSellOrder(cache.orders, currentRate).then(result => { getTopValidSellOrder(cache.orders, currentRate, cache.mode_null).then(result => {
cache.cur_order = result; cache.cur_order = result;
resolve(result); resolve(result);
}).catch(error => { }).catch(error => {
@ -111,11 +121,20 @@ const bestPair = function(cur_rate, tags_buy, tags_sell) {
.then(result => resolve(result)) .then(result => resolve(result))
.catch(error => reject(error)) .catch(error => reject(error))
}).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 } else
reject(false); reject(false);
}); });
getSellOrder.cache = { getSellOrder.cache = {
tags: tags_sell tags: tags_sell,
null_queue: [],
mode_null: false
}; };
const getBuyOrder = () => new Promise((resolve, reject) => { const getBuyOrder = () => new Promise((resolve, reject) => {
@ -258,53 +277,56 @@ function fetch_api(api, id) {
}) })
} }
function getTopValidSellOrder(orders, cur_price) { function getTopValidSellOrder(orders, cur_price, mode_null) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
if (!orders.length) if (!orders.length)
return reject(false) return reject(false)
verifySellOrder(orders.pop(), cur_price) //pop: as the orders are sorted in ascending (highest point should be checked 1st) 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)) .then(result => resolve(result))
.catch(error => { .catch(error => {
if (error !== false) if (error !== false)
return reject(error); return reject(error);
getTopValidSellOrder(orders, cur_price) getTopValidSellOrder(orders, cur_price, mode_null)
.then(result => resolve(result)) .then(result => resolve(result))
.catch(error => reject(error)); .catch(error => reject(error));
}); });
}); });
} }
function verifySellOrder(sellOrder, cur_price) { function verifySellOrder(sellOrder, cur_price, mode_null) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
DB.query("SELECT id, quantity, base FROM Vault WHERE floID=? ORDER BY base", [sellOrder.floID]).then(result => { if (!mode_null)
let rem = sellOrder.quantity, DB.query("SELECT quantity, base FROM Vault WHERE floID=? AND base IS NOT NULL ORDER BY base", [sellOrder.floID]).then(result => {
sell_base = 0, let rem = sellOrder.quantity,
base_quantity = 0; sell_base = 0,
for (let i = 0; i < result.length && rem > 0; i++) { base_quantity = 0;
if (rem < result[i].quantity) { for (let i = 0; i < result.length && rem > 0; i++) {
if (result[i].base) { if (rem < result[i].quantity) {
sell_base += (rem * result[i].base); sell_base += (rem * result[i].base);
base_quantity += rem; base_quantity += rem;
} rem = 0;
rem = 0; } else {
} else {
if (result[i].base) {
sell_base += (result[i].quantity * result[i].base); sell_base += (result[i].quantity * result[i].base);
base_quantity += result[i].quantity; base_quantity += result[i].quantity;
rem -= result[i].quantity;
} }
rem -= result[i].quantity;
} }
} if (base_quantity)
if (base_quantity) sell_base = sell_base / base_quantity;
sell_base = sell_base / base_quantity; if (sell_base > cur_price)
if (rem > 0 || sell_base > cur_price) { reject(false);
//1st condition (rem>0) should not happen (sell order placement was success when insufficient FLO). else
if (rem > 0) resolve(sellOrder);
console.warn(`Sell order ${sellOrder.id} is active, but FLO is insufficient`); }).catch(error => reject(error));
reject(false); else if (mode_null)
} else DB.query("SELECT SUM(quantity) as total FROM Vault WHERE floID=?", [sellOrder.floID]).then(result => {
resolve(sellOrder); if (result.total < sellOrder.quantity)
}).catch(error => reject(error)); 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))
}) })
} }

View File

@ -177,24 +177,20 @@ function initiateCoupling() {
} }
function processCoupling(bestPairQueue) { function processCoupling(bestPairQueue) {
bestPairQueue.get().then(result => { bestPairQueue.get().then(pair_result => {
let buyer_best = result.buyOrder, let buyer_best = pair_result.buyOrder,
seller_best = result.sellOrder; seller_best = pair_result.sellOrder;
console.debug("Sell:", seller_best); console.debug("Sell:", seller_best);
console.debug("Buy:", buyer_best); console.debug("Buy:", buyer_best);
spendFLO(buyer_best, seller_best).then(txQueries => { spendFLO(buyer_best, seller_best, pair_result.null_base).then(spend_result => {
//process the Txn let tx_quantity = spend_result.quantity,
var tx_quantity; txQueries = spend_result.txQueries,
if (seller_best.quantity > buyer_best.quantity) clear_sell = spend_result.incomplete && !spend_result.flag_baseNull; //clear_sell can be true only if an order is placed without enough FLO
tx_quantity = processBuyOrder(seller_best, buyer_best, txQueries); processOrders(seller_best, buyer_best, txQueries, tx_quantity, clear_sell);
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, bestPairQueue.cur_rate, tx_quantity); updateBalance(seller_best, buyer_best, txQueries, bestPairQueue.cur_rate, tx_quantity);
//process txn query in SQL //process txn query in SQL
DB.transaction(txQueries).then(results => { DB.transaction(txQueries).then(_ => {
bestPairQueue.next(); bestPairQueue.next(quantity, spend_result.incomplete, spend_result.flag_baseNull);
console.log(`Transaction was successful! BuyOrder:${buyer_best.id}| SellOrder:${seller_best.id}`); console.log(`Transaction was successful! BuyOrder:${buyer_best.id}| SellOrder:${seller_best.id}`);
//Since a tx was successful, match again //Since a tx was successful, match again
processCoupling(bestPairQueue); processCoupling(bestPairQueue);
@ -208,49 +204,46 @@ function processCoupling(bestPairQueue) {
}); });
} }
function spendFLO(buyOrder, sellOrder) { function spendFLO(buyOrder, sellOrder, null_base) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
DB.query("SELECT id, quantity, base FROM Vault WHERE floID=? ORDER BY base", [sellOrder.floID]).then(result => { DB.query("SELECT id, quantity, base FROM Vault WHERE floID=? ORDER BY base", [sellOrder.floID]).then(result => {
let rem = Math.min(buyOrder.quantity, sellOrder.quantity), let rem = Math.min(buyOrder.quantity, sellOrder.quantity),
txQueries = []; txQueries = []
for (let i = 0; i < result.length && rem > 0; i++) { flag_baseNull = false;
if (rem < result[i].quantity) { for (let i = 0; i < result.length && rem > 0; i++)
txQueries.push(["UPDATE Vault SET quantity=quantity-? WHERE id=?", [rem, result[i].id]]); if (result[i].base || null_base) {
rem = 0; if (rem < result[i].quantity) {
} else { txQueries.push(["UPDATE Vault SET quantity=quantity-? WHERE id=?", [rem, result[i].id]]);
txQueries.push(["DELETE FROM Vault WHERE id=?", [result[i].id]]); rem = 0;
rem -= result[i].quantity; } else {
} txQueries.push(["DELETE FROM Vault WHERE id=?", [result[i].id]]);
} rem -= result[i].quantity;
if (rem > 0) }
reject(`Sell order ${sellOrder.id} is active, but FLO is insufficient`); } else
else flag_baseNull = true;
resolve(txQueries); resolve({
quantity: Math.min(buyOrder.quantity, sellOrder.quantity) - rem,
txQueries,
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) {
@ -262,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) {