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:
parent
5ac3316008
commit
a7c96e9ce2
102
src/group.js
102
src/group.js
@ -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))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -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) {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user