From 6451f025466396334bec52781d43de25b640c642 Mon Sep 17 00:00:00 2001 From: sairajzero Date: Wed, 30 Mar 2022 05:38:55 +0530 Subject: [PATCH] rate-history API --- docs/scripts/floExchangeAPI.js | 10 +++++++ src/app.js | 1 + src/market.js | 12 +++++++++ src/price.js | 48 +++++++++++++++++++++++++++++++--- src/request.js | 20 ++++++++++++++ 5 files changed, 87 insertions(+), 4 deletions(-) diff --git a/docs/scripts/floExchangeAPI.js b/docs/scripts/floExchangeAPI.js index 8fac499..dd40c14 100644 --- a/docs/scripts/floExchangeAPI.js +++ b/docs/scripts/floExchangeAPI.js @@ -577,6 +577,16 @@ }); } + exchangeAPI.getRateHistory = function(asset, duration = null) { + return new Promise((resolve, reject) => { + fetch_api('/rate-history?asset=' + asset + (duration ? '&duration=' + duration : "")) + .then(result => responseParse(result) + .then(result => resolve(result)) + .catch(error => reject(error))) + .catch(error => reject(error)); + }); + } + exchangeAPI.getBalance = function(floID = null, token = null) { return new Promise((resolve, reject) => { if (!floID && !token) diff --git a/src/app.js b/src/app.js index ac5ec04..a461304 100644 --- a/src/app.js +++ b/src/app.js @@ -75,6 +75,7 @@ module.exports = function App(secret, DB) { //get rates, balance and tx app.get('/get-rates', Request.GetRates); + app.get('/rate-history', Request.GetRateHistory); app.get('/get-balance', Request.GetBalance); app.get('/get-transaction', Request.GetTransaction); diff --git a/src/market.js b/src/market.js index bd6bd28..f990b2f 100644 --- a/src/market.js +++ b/src/market.js @@ -30,6 +30,17 @@ function logout(floID) { }) } +function getRateHistory(asset, duration) { + return new Promise((resolve, reject) => { + if (!asset || !assetList.includes(asset)) + reject(INVALID(`Invalid asset(${asset})`)); + else + coupling.price.getHistory(asset, duration) + .then(result => resolve(result)) + .catch(error => reject(error)) + }) +} + function getBalance(floID, token) { return new Promise((resolve, reject) => { if (floID && !floCrypto.validateAddr(floID)) @@ -621,6 +632,7 @@ module.exports = { addBuyOrder, addSellOrder, cancelOrder, + getRateHistory, getBalance, getAccountDetails, getTransactionDetails, diff --git a/src/price.js b/src/price.js index c2e439d..1c47b8e 100644 --- a/src/price.js +++ b/src/price.js @@ -20,14 +20,14 @@ var currentRate = {}, //container for FLO price (from API or by model) const updateLastTime = asset => lastTime[asset] = Date.now(); //store FLO price in DB every 1 hr -function storeRate(asset, rate) { +function storeHistory(asset, rate) { DB.query("INSERT INTO PriceHistory (asset, rate) VALUE (?, ?)", [asset, rate.toFixed(3)]) .then(_ => null).catch(error => console.error(error)) } setInterval(() => { for (let asset in currentRate) - storeRate(asset, currentRate[asset]); -}, REC_HISTORY_INTERVAL) + storeHistory(asset, currentRate[asset]); +}, REC_HISTORY_INTERVAL); function getPastRate(asset, hrs = 24) { return new Promise((resolve, reject) => { @@ -37,6 +37,45 @@ function getPastRate(asset, hrs = 24) { }); } +function getHistory(asset, duration) { + return new Promise((resolve, reject) => { + duration = getHistory.validateDuration(duration); + let statement = "SELECT " + + (!duration || duration.endsWith("year") ? "DATE(rec_time) AS time, AVG(rate) as rate" : "rec_time AS time, rate") + + " WHERE asset=?" + (duration ? " AND rec_time >= NOW() - INTERVAL " + duration : "") + + (!duration || duration.endsWith("year") ? " GROUP BY time" : "") + + " ORDER BY time"; + DB.query(statement, asset) + .then(result => resolve(result)) + .catch(error => reject(error)) + }); +} + +getHistory.validateDuration = duration => { + let n = duration.match(/\d+/g), + d = duration.match(/\D+/g); + n = n ? n[0] || 1 : 1; + d = d ? d[0].replace(/[-\s]/g, '') : ""; + switch (d.toLowerCase()) { + case "day": + case "days": + return n + " day"; + case "week": + case "weeks": + return n + " week"; + case "month": + case "months": + return n + " month"; + case "year": + case "years": + return n + " year"; + case "alltime": + return null; + default: + return '1 day'; + } +} + function loadRate(asset) { return new Promise((resolve, reject) => { if (typeof currentRate[asset] !== "undefined") @@ -60,7 +99,7 @@ function fetchRates() { fetchRates.USD_INR().then(INR_rate => { let FLO_INR_rate = FLO_rate * INR_rate; console.debug('Rates:', FLO_rate, INR_rate, FLO_INR_rate); - storeRate(FLO_INR_rate); + storeHistory(FLO_INR_rate); resolve(FLO_INR_rate); }).catch(error => reject(error)) }).catch(error => reject(error)) @@ -153,6 +192,7 @@ function checkForRatedSellers(asset) { module.exports = { getRates, + getHistory, updateLastTime, noOrder(asset, buy, sell) { noBuyOrder[asset] = buy; diff --git a/src/request.js b/src/request.js index 424ccfb..d9ad6b7 100644 --- a/src/request.js +++ b/src/request.js @@ -334,6 +334,25 @@ function GetRates(req, res) { } +function GetRateHistory(req, res) { + if (!serving) + res.status(INVALID.e_code).send(INVALID_SERVER_MSG); + else { + let asset = req.query.asset, + duration = req.query.duration || ""; + market.getRateHistory(asset, duration) + .then(result => 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("Unable to process! Try again later!"); + } + }); + } +} + function GetTransaction(req, res) { if (!serving) res.status(INVALID.e_code).send(INVALID_SERVER_MSG); @@ -385,6 +404,7 @@ module.exports = { ListBuyOrders, ListTradeTransactions, GetRates, + GetRateHistory, GetTransaction, GetBalance, Account,