Price updation

- Update current_price when no seller or buyer available.
- Inc price only when sell-orders from rated sellers are available.
- User must buy a minimum FLO before placing a sell order unless they are a 'Miner'.
This commit is contained in:
sairajzero 2021-12-02 05:26:01 +05:30
parent 4a92ee7acf
commit 278fc8bcbd
3 changed files with 193 additions and 70 deletions

View File

@ -40,12 +40,18 @@ const bestPair = function(cur_rate, tags_buy, tags_sell) {
});
this.get = () => new Promise((resolve, reject) => {
Promise.all([getBuyOrder(), getSellOrder()]).then(results => {
Promise.allSettled([getBuyOrder(), getSellOrder()]).then(results => {
if (results[0].status === "fulfilled" && results[1].status === "fulfilled")
resolve({
buyOrder: results[0],
sellOrder: results[1],
buyOrder: results[0].value,
sellOrder: results[1].value,
null_base: getSellOrder.cache.mode_null
})
else
reject({
buy: results[0].reason,
sell: results[1].reason
})
}).catch(error => reject(error))
});

View File

@ -1,6 +1,7 @@
const group = require("./group");
const price = require("./price");
const MINIMUM_BUY_REQUIREMENT = 0.1;
var net_FLO_price; //container for FLO price (from API or by model)
var DB; //container for database
const tokenAPI = {
@ -52,46 +53,8 @@ const tokenAPI = {
}
}
function getRates() {
return new Promise((resolve, reject) => {
getRates.FLO_USD().then(FLO_rate => {
getRates.USD_INR().then(INR_rate => {
net_FLO_price = FLO_rate * INR_rate;
console.debug('Rates:', FLO_rate, INR_rate, net_FLO_price);
resolve(net_FLO_price);
}).catch(error => reject(error))
}).catch(error => reject(error))
});
}
getRates.FLO_USD = function() {
return new Promise((resolve, reject) => {
fetch('https://api.coinlore.net/api/ticker/?id=67').then(response => {
if (response.ok) {
response.json()
.then(result => resolve(result[0].price_usd))
.catch(error => reject(error));
} else
reject(response.status);
}).catch(error => reject(error));
});
}
getRates.USD_INR = function() {
return new Promise((resolve, reject) => {
fetch('https://api.exchangerate-api.com/v4/latest/usd').then(response => {
if (response.ok) {
response.json()
.then(result => resolve(result.rates['INR']))
.catch(error => reject(error));
} else
reject(response.status);
}).catch(error => reject(error));
});
}
function returnRates() {
return net_FLO_price;
return price.currentRate;
}
function addSellOrder(floID, quantity, min_price) {
@ -102,6 +65,7 @@ function addSellOrder(floID, quantity, min_price) {
return reject(INVALID(`Invalid quantity (${quantity})`));
else if (typeof min_price !== "number" || min_price <= 0)
return reject(INVALID(`Invalid min_price (${min_price})`));
checkSellRequirement().then(_ => {
DB.query("SELECT SUM(quantity) AS total FROM Vault WHERE floID=?", [floID]).then(result => {
let total = result.pop()["total"] || 0;
if (total < quantity)
@ -116,9 +80,25 @@ function addSellOrder(floID, quantity, min_price) {
.catch(error => reject(error));
}).catch(error => reject(error));
}).catch(error => reject(error));
}).catch(error => reject(error));
});
}
function checkSellRequirement(floID) {
return new Promise((resolve, reject) => {
DB.query("SELECT * FROM Tags WHERE floID=? AND tag=?", [floID, "MINER"]).then(result => {
if (result.length)
return resolve(true);
DB.query("SELECT SUM(quantity) AS brought FROM Transactions WHERE floID=?", [floID]).then(result => {
if (result[0].brought >= MINIMUM_BUY_REQUIREMENT)
resolve(true);
else
reject(INVALID(`Sellers required to buy atleast ${MINIMUM_BUY_REQUIREMENT} FLO before placing a sell order unless they are a Miner`));
}).catch(error => reject(error))
}).catch(error => reject(error))
})
}
function addBuyOrder(floID, quantity, max_price) {
return new Promise((resolve, reject) => {
if (!floID || !floCrypto.validateAddr(floID))
@ -171,9 +151,11 @@ function cancelOrder(type, id, floID) {
}
function initiateCoupling() {
group.getBestPairs(net_FLO_price)
price.getRates().then(cur_rate => {
group.getBestPairs(cur_rate)
.then(bestPairQueue => processCoupling(bestPairQueue))
.catch(error => console.error("initiateCoupling", error))
}).catch(error => reject(error));
}
function processCoupling(bestPairQueue) {
@ -197,10 +179,26 @@ function 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.");
let noBuy, noSell;
if (error.buy === undefined)
noBuy = false;
else if (error.buy !== false) {
console.error(error.buy);
noBuy = null;
} else {
console.log("No valid buyOrders.");
noBuy = true;
}
if (error.sell === undefined)
noSell = false;
if (error.sell !== false) {
console.error(error.sell);
noSell = null;
} else {
console.log("No valid sellOrders.");
noSell = true;
}
price.noOrder(noBuy, noSell);
});
}
@ -597,11 +595,8 @@ function confirmWithdrawalRupee() {
}
function periodicProcess() {
let old_rate = net_FLO_price;
getRates().then(cur_rate => {
transactionReCheck();
initiateCoupling();
}).catch(error => console.error(error));
}
function transactionReCheck() {
@ -628,5 +623,6 @@ module.exports = {
set DB(db) {
DB = db;
group.DB = db;
price.DB = db;
}
};

121
src/price.js Normal file
View File

@ -0,0 +1,121 @@
const MIN_TIME = 1 * 60 * 60 * 1000,
DOWN_RATE = 0.2 / 100,
UP_RATE = 0.5 / 100,
MAX_DOWN_PER_DAY = 4.8 / 100,
MAX_UP_PER_DAY = 12 / 100,
TOP_RANGE = 10 / 100;
var DB; //container for database
var netValue, //container for FLO price (from API or by model)
lastTxTime, //container for timestamp of the last tx
noBuyOrder,
noSellOrder
var dayInitRate;
setInterval(() => dayInitRate = netValue, 24 * 60 * 60 * 1000); //reset the day price every 24 hrs
//store FLO price in DB every 1 hr
setInterval(function storeRate() {
DB.query("INSERT INTO priceHistory (price) VALUE (?)", netValue)
.then(_ => null).catch(error => console.error(error))
})
/* OLD FUNCTION
function getRates() {
return new Promise((resolve, reject) => {
getRates.FLO_USD().then(FLO_rate => {
getRates.USD_INR().then(INR_rate => {
net_FLO_price = FLO_rate * INR_rate;
console.debug('Rates:', FLO_rate, INR_rate, net_FLO_price);
resolve(net_FLO_price);
}).catch(error => reject(error))
}).catch(error => reject(error))
});
}
getRates.FLO_USD = function() {
return new Promise((resolve, reject) => {
fetch('https://api.coinlore.net/api/ticker/?id=67').then(response => {
if (response.ok) {
response.json()
.then(result => resolve(result[0].price_usd))
.catch(error => reject(error));
} else
reject(response.status);
}).catch(error => reject(error));
});
}
getRates.USD_INR = function() {
return new Promise((resolve, reject) => {
fetch('https://api.exchangerate-api.com/v4/latest/usd').then(response => {
if (response.ok) {
response.json()
.then(result => resolve(result.rates['INR']))
.catch(error => reject(error));
} else
reject(response.status);
}).catch(error => reject(error));
});
}
*/
function getRates() {
return new Promise((resolve, reject) => {
let cur_time = Date.now();
if (cur_time - lastTxTime < MIN_TIME) //Minimum time to update not crossed: No update required
resolve(netValue);
else if (noBuyOrder && noSellOrder) //Both are not available: No update required
resolve(netValue);
else if (noBuyOrder === null || noSellOrder === null) //An error has occured during last process: No update (might cause price to crash/jump)
resolve(netValue);
else if (noBuyOrder) {
//No Buy, But Sell available: Decrease the price
let tmp_val = netValue * (1 - DOWN_RATE);
if (tmp_val >= dayInitRate * (1 - MAX_DOWN_PER_DAY))
netValue *= tmp_val;
resolve(netValue);
} else if (noSellOrder) {
//No Sell, But Buy available: Increase the price
checkForRatedSellers().then(result => {
if (result) {
let tmp_val = netValue * (1 + UP_RATE)
if (tmp_val >= dayInitRate * (1 + MAX_UP_PER_DAY))
netValue *= tmp_val;
}
}).catch(error => console.error(error)).finally(_ => resolve(netValue));
}
})
}
function checkForRatedSellers() {
//Check if there are best rated sellers?
return new Promise((resolve, reject) => {
DB.query("SELECT MAX(sellPriority) as maxValue FROM TagList").then(result => {
let ratedMin = result[0].maxValue * (1 - TOP_RANGE);
DB.query("SELECT COUNT(*) as value FROM SellOrder WHERE floID IN (" +
" SELECT Tags.floID FROM Tags INNER JOIN TagList ON Tags.tag = TagList.tag" +
" WHERE TagList.sellPriority > ?)", [ratedMin]).then(result => {
resolve(result[0].value > 0);
}).catch(error => reject(error))
}).catch(error => reject(error))
})
}
module.exports = {
getRates,
set lastTxTime(t) {
lastTxTime = t;
},
set noOrder(buy, sell) {
noBuyOrder = buy;
noSellOrder = sell;
},
set DB(db) {
DB = db;
},
get currentRate() {
return netValue
}
}