Compare commits
6 commits
c0701775c7
...
6125f99ec6
Author | SHA1 | Date | |
---|---|---|---|
6125f99ec6 | |||
f2618a1f3a | |||
62e42cf12a | |||
d3027506a6 | |||
4590bc8458 | |||
cef3258fa7 |
7 changed files with 94 additions and 21 deletions
|
@ -5,7 +5,7 @@
|
||||||
name: DATABASE_NAME
|
name: DATABASE_NAME
|
||||||
password: DATABASE_PASSWORD
|
password: DATABASE_PASSWORD
|
||||||
}
|
}
|
||||||
currecy: {
|
currency: {
|
||||||
collecting: {
|
collecting: {
|
||||||
fiat: true
|
fiat: true
|
||||||
crypto: false
|
crypto: false
|
||||||
|
@ -27,6 +27,9 @@
|
||||||
USDT,
|
USDT,
|
||||||
TON
|
TON
|
||||||
]
|
]
|
||||||
|
api_keys: {
|
||||||
|
coinmarketcap: TOKEN_COINMARKETCAP
|
||||||
|
}
|
||||||
}
|
}
|
||||||
schedule: 30 8 * * *
|
schedule: 30 8 * * *
|
||||||
}
|
}
|
|
@ -1,8 +1,6 @@
|
||||||
const pg = require('pg');
|
const pg = require('pg');
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
const hjson = require('hjson');
|
const config = require('../utils/load_config.js')();
|
||||||
|
|
||||||
const config = hjson.parse(fs.readFileSync('config.hjson', 'utf-8'));
|
|
||||||
|
|
||||||
const pool = new pg.Pool({
|
const pool = new pg.Pool({
|
||||||
user: config['database']['user'],
|
user: config['database']['user'],
|
||||||
|
|
19
main.js
19
main.js
|
@ -1,12 +1,11 @@
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
const hjson = require('hjson');
|
|
||||||
const schedule = require('node-schedule');
|
const schedule = require('node-schedule');
|
||||||
const cron = require('cron-validator');
|
const cron = require('cron-validator');
|
||||||
|
|
||||||
const { validateCurrency } = require('./models/Currency.js');
|
const { validateCurrency } = require('./models/Currency.js');
|
||||||
const { create_table, pool } = require('./database/data.js');
|
const { create_table, pool } = require('./database/data.js');
|
||||||
const config = hjson.parse(fs.readFileSync('config.hjson', 'utf-8'));
|
const config = require('./utils/load_config.js')();
|
||||||
|
|
||||||
async function main() {
|
async function main() {
|
||||||
if (!config['schedule'])
|
if (!config['schedule'])
|
||||||
|
@ -34,28 +33,28 @@ async function main() {
|
||||||
console.log('Running scheduled task at:', new Date());
|
console.log('Running scheduled task at:', new Date());
|
||||||
|
|
||||||
for (const srv of services) {
|
for (const srv of services) {
|
||||||
try {
|
const results = await srv.parseCurrencies();
|
||||||
const result = await srv.parseCurrencies();
|
|
||||||
|
|
||||||
if (result) {
|
if (Array.isArray(results) && results.length > 0) {
|
||||||
|
for (const result of results) {
|
||||||
try {
|
try {
|
||||||
const currency = await validateCurrency(result);
|
const currency = await validateCurrency(result);
|
||||||
|
|
||||||
await pool.query(
|
await pool.query(
|
||||||
'INSERT INTO currency (from_currency, conv_currency, rate, date) ' +
|
'INSERT INTO currency (from_currency, conv_currency, rate, date) VALUES ($1, $2, $3, $4)',
|
||||||
'VALUES ($1, $2, $3, $4)',
|
|
||||||
[
|
[
|
||||||
currency.from_currency,
|
currency.from_currency,
|
||||||
currency.conv_currency,
|
currency.conv_currency,
|
||||||
currency.rate,
|
currency.rate,
|
||||||
currency.date,
|
currency.date,
|
||||||
]);
|
]
|
||||||
|
);
|
||||||
} catch (validationError) {
|
} catch (validationError) {
|
||||||
console.error(validationError);
|
console.error(validationError);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} else {
|
||||||
console.error(`Error in service ${srv.name || 'unknown'}:`, err);
|
console.error("Data not received for writing to the database.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,14 +1,16 @@
|
||||||
const Joi = require('joi');
|
const Joi = require('joi');
|
||||||
|
|
||||||
const currencySchema = Joi.object({
|
const currencySchema = Joi.object({
|
||||||
from_currency: Joi.string().length(3).required().messages({
|
from_currency: Joi.string().min(3).max(4).required().messages({
|
||||||
'string.base': 'from_currency must be a string',
|
'string.base': 'from_currency must be a string',
|
||||||
'string.length': 'from_currency must be exactly 3 characters long',
|
'string.min': 'from_currency must be at least 3 characters long',
|
||||||
|
'string.max': 'from_currency must be no more than 4 characters long',
|
||||||
'any.required': 'from_currency is required'
|
'any.required': 'from_currency is required'
|
||||||
}),
|
}),
|
||||||
conv_currency: Joi.string().length(3).required().messages({
|
conv_currency: Joi.string().min(3).max(4).required().messages({
|
||||||
'string.base': 'conv_currency must be a string',
|
'string.base': 'conv_currency must be a string',
|
||||||
'string.length': 'conv_currency must be exactly 3 characters long',
|
'string.min': 'conv_currency must be at least 3 characters long',
|
||||||
|
'string.max': 'conv_currency must be no more than 4 characters long',
|
||||||
'any.required': 'conv_currency is required'
|
'any.required': 'conv_currency is required'
|
||||||
}),
|
}),
|
||||||
date: Joi.date().iso().required().messages({
|
date: Joi.date().iso().required().messages({
|
||||||
|
|
47
services/coinmarketcap.js
Normal file
47
services/coinmarketcap.js
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
const axios = require('axios');
|
||||||
|
const config = require('../utils/load_config.js')();
|
||||||
|
const { truncate_number } = require('../utils/truncate_number.js');
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
parseCurrencies: async () => {
|
||||||
|
const promises = config['currency']['crypto'].map(fromCurrency => {
|
||||||
|
return config['currency']['crypto'].map(convCurrency => {
|
||||||
|
if (fromCurrency === convCurrency) return Promise.resolve(null);
|
||||||
|
|
||||||
|
return axios.get(
|
||||||
|
'https://pro-api.coinmarketcap.com/v1/cryptocurrency/quotes/latest',
|
||||||
|
{
|
||||||
|
params: {
|
||||||
|
symbol: fromCurrency,
|
||||||
|
convert: convCurrency,
|
||||||
|
},
|
||||||
|
headers: {
|
||||||
|
'X-CMC_PRO_API_KEY': config['currency']['api_keys']['coinmarketcap'],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.then((res) => {
|
||||||
|
const data = res.data.data[fromCurrency].quote[convCurrency];
|
||||||
|
const truncatedPriceStr = truncate_number(data.price, 3);
|
||||||
|
const rate = parseFloat(truncatedPriceStr);
|
||||||
|
|
||||||
|
return {
|
||||||
|
from_currency: fromCurrency,
|
||||||
|
conv_currency: convCurrency,
|
||||||
|
rate: rate,
|
||||||
|
date: new Date(data['last_updated']).toISOString().substring(0, 10),
|
||||||
|
};
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
console.error(err.respone.data);
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
const flattenedPromises = promises.flat();
|
||||||
|
const results = await Promise.all(flattenedPromises);
|
||||||
|
|
||||||
|
return results.filter(result => result !== null);
|
||||||
|
}
|
||||||
|
};
|
10
utils/load_config.js
Normal file
10
utils/load_config.js
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
const fs = require('fs');
|
||||||
|
const hjson = require('hjson');
|
||||||
|
|
||||||
|
const config = () => {
|
||||||
|
if (!fs.existsSync('../config.hjson')) throw new Error('Config not found');
|
||||||
|
|
||||||
|
return hjson.parse(fs.readFileSync('../config.hjson', 'utf-8'));
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = config;
|
14
utils/truncate_number.js
Normal file
14
utils/truncate_number.js
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
function truncate_number(value, decimals) {
|
||||||
|
const valueStr = value.toString();
|
||||||
|
const dotIndex = valueStr.indexOf('.');
|
||||||
|
if (dotIndex === -1) return valueStr;
|
||||||
|
const desiredLength = dotIndex + decimals + 1;
|
||||||
|
let truncated = valueStr.slice(0, desiredLength);
|
||||||
|
|
||||||
|
if (parseFloat(truncated) === 0 && value > 0) {
|
||||||
|
return valueStr;
|
||||||
|
}
|
||||||
|
return truncated;
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = { truncate_number };
|
Loading…
Add table
Reference in a new issue