Compare commits
10 Commits
41250af061
...
3cd3be87bf
| Author | SHA1 | Date | |
|---|---|---|---|
| 3cd3be87bf | |||
| c9f0414df4 | |||
| ba876a434b | |||
| ce30b07ec8 | |||
| 616983559a | |||
| f6a2a52a19 | |||
| 966baaf437 | |||
| c2f2a01bf4 | |||
| c0b7418e24 | |||
| 714ad06eae |
26281
btc_price_history.json
Normal file
26281
btc_price_history.json
Normal file
File diff suppressed because it is too large
Load Diff
3754
btc_price_history_full.csv
Normal file
3754
btc_price_history_full.csv
Normal file
File diff suppressed because it is too large
Load Diff
@ -17,6 +17,11 @@ const Schema = new mongoose.Schema({
|
||||
inr: {
|
||||
type: Number,
|
||||
required: true
|
||||
},
|
||||
count: {
|
||||
type: Number, // New field to track the number of updates for the day
|
||||
default: 1
|
||||
}
|
||||
});
|
||||
module.exports = mongoose.model('PriceHistory', Schema);
|
||||
|
||||
module.exports = mongoose.model('PriceHistory', Schema);
|
||||
|
||||
@ -6,20 +6,27 @@ const fs = require('fs');
|
||||
const path = require('path');
|
||||
const csv = require('csv-parser');
|
||||
|
||||
// Import the PriceHistory model from the external file
|
||||
const PriceHistory = require('../models/price-history');
|
||||
|
||||
const CSV_FILE_PATH = '/home/production/deployed/utility-api/btc_price_history_full.csv';
|
||||
function logWithTimestamp(message) {
|
||||
console.log(`[${new Date().toISOString()}] ${message}`);
|
||||
}
|
||||
|
||||
// Function to read CSV file and return data
|
||||
function readCsvFile() {
|
||||
return new Promise((resolve, reject) => {
|
||||
const results = [];
|
||||
fs.createReadStream(CSV_FILE_PATH)
|
||||
.pipe(csv())
|
||||
.on('data', (data) => results.push(data))
|
||||
.on('end', () => resolve(results))
|
||||
.on('error', (err) => reject(err));
|
||||
});
|
||||
// Function to log errors with the current timestamp
|
||||
function errorWithTimestamp(message, error) {
|
||||
console.error(`[${new Date().toISOString()}] ERROR: ${message}`, error);
|
||||
}
|
||||
|
||||
|
||||
// Function to parse dates in different formats (e.g., 2024-10-2 or 2024-9-3)
|
||||
function parseDateString(dateStr) {
|
||||
const parts = dateStr.split('-');
|
||||
const year = parseInt(parts[0]);
|
||||
const month = parseInt(parts[1]) - 1; // Months are 0-indexed in JavaScript Date
|
||||
const day = parseInt(parts[2]);
|
||||
|
||||
return new Date(year, month, day).setHours(0, 0, 0, 0); // Set time to 00:00:00.000
|
||||
}
|
||||
|
||||
// Function to fetch BTC prices in USD and INR from BitPay API
|
||||
@ -34,14 +41,16 @@ async function fetchBtcPrices() {
|
||||
|
||||
return { usd: btcUsdRate, inr: btcInrRate };
|
||||
} catch (error) {
|
||||
console.error('Error fetching BTC prices from BitPay:', error);
|
||||
errorWithTimestamp('Error fetching BTC prices from BitPay:', error);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// Function to update daily average in the database
|
||||
async function updateDailyAverage(newPrice) {
|
||||
const today = new Date().setHours(0, 0, 0, 0);
|
||||
// Set the date to the start of the day (00:00:00.000)
|
||||
const today = new Date();
|
||||
today.setHours(0, 0, 0, 0);
|
||||
|
||||
try {
|
||||
// Fetch the current record for the day
|
||||
@ -73,9 +82,9 @@ async function updateDailyAverage(newPrice) {
|
||||
});
|
||||
}
|
||||
|
||||
console.log('Daily average updated successfully.');
|
||||
logWithTimestamp('Daily average updated successfully.');
|
||||
} catch (err) {
|
||||
console.error('Error updating daily average:', err);
|
||||
errorWithTimestamp('Error updating daily average:', err);
|
||||
}
|
||||
}
|
||||
|
||||
@ -89,9 +98,86 @@ async function collectAndUpdatePrices() {
|
||||
}
|
||||
}
|
||||
|
||||
// Route to handle price history requests
|
||||
router.get("/", async (req, res) => {
|
||||
try {
|
||||
let { from, to, on, limit = 100, asset = 'btc', currency, sort, dates } = req.query;
|
||||
const searchParams = {
|
||||
asset
|
||||
};
|
||||
|
||||
// Convert 'from' and 'to' dates to proper format
|
||||
if (from && to) {
|
||||
from = parseDateString(from);
|
||||
to = parseDateString(to);
|
||||
if (from > to) {
|
||||
const temp = from;
|
||||
from = to;
|
||||
to = temp;
|
||||
}
|
||||
}
|
||||
|
||||
if (from) {
|
||||
searchParams.date = { $gte: from };
|
||||
}
|
||||
if (to) {
|
||||
searchParams.date = { ...searchParams.date, $lte: to };
|
||||
}
|
||||
|
||||
// If the 'dates' parameter is used
|
||||
if (dates) {
|
||||
const datesArray = dates.split(',').map(date => parseDateString(date.trim()));
|
||||
searchParams.date = { $in: datesArray };
|
||||
}
|
||||
|
||||
// If the 'on' parameter is used for a single date
|
||||
if (on) {
|
||||
const onDate = parseDateString(on);
|
||||
searchParams.date = { $eq: onDate };
|
||||
}
|
||||
|
||||
if (currency) {
|
||||
searchParams[currency] = { $exists: true };
|
||||
}
|
||||
|
||||
if (sort) {
|
||||
if (['asc', 'desc', 'ascending', 'descending', '1', '-1'].includes(sort)) {
|
||||
sort = { date: sort === 'asc' || sort === 'ascending' || sort === '1' ? 1 : -1 };
|
||||
} else {
|
||||
return res.status(400).json({ error: 'Invalid sort. Valid values are asc | desc | ascending | descending | 1 | -1' });
|
||||
}
|
||||
} else {
|
||||
sort = { date: -1 };
|
||||
}
|
||||
|
||||
// Formatting the data to exclude certain fields
|
||||
const dataFormat = { _id: 0, __v: 0, asset: 0 };
|
||||
if (currency === 'inr') {
|
||||
dataFormat.usd = 0;
|
||||
}
|
||||
if (currency === 'usd') {
|
||||
dataFormat.inr = 0;
|
||||
}
|
||||
|
||||
const priceHistory = await PriceHistory.find(searchParams, dataFormat)
|
||||
.sort(sort)
|
||||
.limit(limit === 'all' ? 0 : parseInt(limit))
|
||||
.lean();
|
||||
|
||||
if (!priceHistory || priceHistory.length === 0) {
|
||||
return res.status(404).json({ message: 'No data found' });
|
||||
}
|
||||
|
||||
res.json(priceHistory);
|
||||
} catch (err) {
|
||||
errorWithTimestamp('Error serving data',err);
|
||||
res.status(500).json({ error: err });
|
||||
}
|
||||
});
|
||||
|
||||
// Cron job to collect prices every 4 hours
|
||||
cron.schedule('0 */4 * * *', async () => {
|
||||
console.log('Starting price collection for daily averaging...');
|
||||
logWithTimestamp('Starting price collection for daily averaging...');
|
||||
await collectAndUpdatePrices();
|
||||
});
|
||||
|
||||
|
||||
2
routes/price-history.min.js
vendored
2
routes/price-history.min.js
vendored
@ -1 +1 @@
|
||||
const express=require("express"),router=express.Router(),cron=require("node-cron"),axios=require("axios"),fs=require("fs"),path=require("path"),csv=require("csv-parser"),PriceHistory=require("../models/price-history"),CSV_FILE_PATH="/home/production/deployed/utility-api/btc_price_history_full.csv";function readCsvFile(){return new Promise(((e,r)=>{const t=[];fs.createReadStream(CSV_FILE_PATH).pipe(csv()).on("data",(e=>t.push(e))).on("end",(()=>e(t))).on("error",(e=>r(e)))}))}async function fetchBtcPrices(){try{const e=(await axios.get("https://bitpay.com/api/rates")).data,r=e.find((e=>"USD"===e.code&&"US Dollar"===e.name)).rate;return{usd:r,inr:e.find((e=>"INR"===e.code&&"Indian Rupee"===e.name)).rate}}catch(e){return console.error("Error fetching BTC prices from BitPay:",e),null}}async function updateDailyAverage(e){const r=(new Date).setHours(0,0,0,0);try{const t=await PriceHistory.findOne({date:r,asset:"btc"});if(t){const a=(t.usd*t.count+e.usd)/(t.count+1),c=(t.inr*t.count+e.inr)/(t.count+1);await PriceHistory.updateOne({date:r,asset:"btc"},{$set:{usd:a,inr:c,count:t.count+1}})}else await PriceHistory.create({date:r,asset:"btc",usd:e.usd,inr:e.inr,count:1});console.log("Daily average updated successfully.")}catch(e){console.error("Error updating daily average:",e)}}async function collectAndUpdatePrices(){const e=await fetchBtcPrices();e&&await updateDailyAverage(e)}cron.schedule("0 */4 * * *",(async()=>{console.log("Starting price collection for daily averaging..."),await collectAndUpdatePrices()})),module.exports=router;
|
||||
const express=require("express"),router=express.Router(),cron=require("node-cron"),axios=require("axios"),fs=require("fs"),path=require("path"),csv=require("csv-parser"),PriceHistory=require("../models/price-history");function logWithTimestamp(e){console.log(`[${(new Date).toISOString()}] ${e}`)}function errorWithTimestamp(e,t){console.error(`[${(new Date).toISOString()}] ERROR: ${e}`,t)}function parseDateString(e){const t=e.split("-"),r=parseInt(t[0]),s=parseInt(t[1])-1,a=parseInt(t[2]);return new Date(r,s,a).setHours(0,0,0,0)}async function fetchBtcPrices(){try{const e=(await axios.get("https://bitpay.com/api/rates")).data,t=e.find((e=>"USD"===e.code&&"US Dollar"===e.name)).rate;return{usd:t,inr:e.find((e=>"INR"===e.code&&"Indian Rupee"===e.name)).rate}}catch(e){return errorWithTimestamp("Error fetching BTC prices from BitPay:",e),null}}async function updateDailyAverage(e){const t=new Date;t.setHours(0,0,0,0);try{const r=await PriceHistory.findOne({date:t,asset:"btc"});if(r){const s=(r.usd*r.count+e.usd)/(r.count+1),a=(r.inr*r.count+e.inr)/(r.count+1);await PriceHistory.updateOne({date:t,asset:"btc"},{$set:{usd:s,inr:a,count:r.count+1}})}else await PriceHistory.create({date:t,asset:"btc",usd:e.usd,inr:e.inr,count:1});logWithTimestamp("Daily average updated successfully.")}catch(e){errorWithTimestamp("Error updating daily average:",e)}}async function collectAndUpdatePrices(){const e=await fetchBtcPrices();e&&await updateDailyAverage(e)}router.get("/",(async(e,t)=>{try{let{from:r,to:s,on:a,limit:i=100,asset:n="btc",currency:c,sort:o,dates:d}=e.query;const u={asset:n};if(r&&s&&(r=parseDateString(r),s=parseDateString(s),r>s)){const e=r;r=s,s=e}if(r&&(u.date={$gte:r}),s&&(u.date={...u.date,$lte:s}),d){const e=d.split(",").map((e=>parseDateString(e.trim())));u.date={$in:e}}if(a){const e=parseDateString(a);u.date={$eq:e}}if(c&&(u[c]={$exists:!0}),o){if(!["asc","desc","ascending","descending","1","-1"].includes(o))return t.status(400).json({error:"Invalid sort. Valid values are asc | desc | ascending | descending | 1 | -1"});o={date:"asc"===o||"ascending"===o||"1"===o?1:-1}}else o={date:-1};const l={_id:0,__v:0,asset:0};"inr"===c&&(l.usd=0),"usd"===c&&(l.inr=0);const p=await PriceHistory.find(u,l).sort(o).limit("all"===i?0:parseInt(i)).lean();if(!p||0===p.length)return t.status(404).json({message:"No data found"});t.json(p)}catch(e){errorWithTimestamp("Error serving data",e),t.status(500).json({error:e})}})),cron.schedule("0 */4 * * *",(async()=>{logWithTimestamp("Starting price collection for daily averaging..."),await collectAndUpdatePrices()})),module.exports=router;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user