From 875040c3291cca390193e5afcebd59cee7f11418 Mon Sep 17 00:00:00 2001 From: nymkappa Date: Wed, 25 May 2022 10:51:35 +0200 Subject: [PATCH] Save bisq aggregate exchange rates in the database for each new block --- backend/src/api/blocks.ts | 7 ++++++ backend/src/api/database-migration.ts | 14 ++++++++++- backend/src/api/fiat-conversion.ts | 28 +++++++++++++-------- backend/src/repositories/RatesRepository.ts | 21 ++++++++++++++++ 4 files changed, 59 insertions(+), 11 deletions(-) create mode 100644 backend/src/repositories/RatesRepository.ts diff --git a/backend/src/api/blocks.ts b/backend/src/api/blocks.ts index ba6fdff22..5ab9df6cf 100644 --- a/backend/src/api/blocks.ts +++ b/backend/src/api/blocks.ts @@ -16,6 +16,8 @@ import { prepareBlock } from '../utils/blocks-utils'; import BlocksRepository from '../repositories/BlocksRepository'; import HashratesRepository from '../repositories/HashratesRepository'; import indexer from '../indexer'; +import fiatConversion from './fiat-conversion'; +import RatesRepository from '../repositories/RatesRepository'; class Blocks { private blocks: BlockExtended[] = []; @@ -312,6 +314,8 @@ class Blocks { } } + const currentUsdPrice = fiatConversion.getConversionRates().USD; + while (this.currentBlockHeight < blockHeightTip) { if (this.currentBlockHeight < blockHeightTip - config.MEMPOOL.INITIAL_BLOCKS_AMOUNT) { this.currentBlockHeight = blockHeightTip; @@ -341,6 +345,9 @@ class Blocks { await blocksRepository.$saveBlockInDatabase(blockExtended); } } + if (fiatConversion.ratesInitialized === true) { + await RatesRepository.$saveRate(blockExtended.height, fiatConversion.getConversionRates()); + } if (block.height % 2016 === 0) { this.previousDifficultyRetarget = (block.difficulty - this.currentDifficulty) / this.currentDifficulty * 100; diff --git a/backend/src/api/database-migration.ts b/backend/src/api/database-migration.ts index 8fb534dc5..45207007e 100644 --- a/backend/src/api/database-migration.ts +++ b/backend/src/api/database-migration.ts @@ -4,7 +4,7 @@ import logger from '../logger'; import { Common } from './common'; class DatabaseMigration { - private static currentVersion = 18; + private static currentVersion = 19; private queryTimeout = 120000; private statisticsAddedIndexed = false; @@ -184,6 +184,10 @@ class DatabaseMigration { if (databaseSchemaVersion < 18 && isBitcoin === true) { await this.$executeQuery('ALTER TABLE `blocks` ADD INDEX `hash` (`hash`);'); } + + if (databaseSchemaVersion < 19 && isBitcoin === true) { + await this.$executeQuery(this.getCreateRatesTableQuery(), await this.$checkIfTableExists('rates')); + } } catch (e) { throw e; } @@ -466,6 +470,14 @@ class DatabaseMigration { ) ENGINE=InnoDB DEFAULT CHARSET=utf8;`; } + private getCreateRatesTableQuery(): string { + return `CREATE TABLE IF NOT EXISTS rates ( + height int(10) unsigned NOT NULL, + bisq_rates JSON NOT NULL, + PRIMARY KEY (height) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8;`; + } + public async $truncateIndexedData(tables: string[]) { const allowedTables = ['blocks', 'hashrates']; diff --git a/backend/src/api/fiat-conversion.ts b/backend/src/api/fiat-conversion.ts index 5fdde7274..3562760f1 100644 --- a/backend/src/api/fiat-conversion.ts +++ b/backend/src/api/fiat-conversion.ts @@ -6,12 +6,19 @@ import backendInfo from './backend-info'; import { SocksProxyAgent } from 'socks-proxy-agent'; class FiatConversion { - private conversionRates: IConversionRates = { - 'USD': 0 - }; + private debasingFiatCurrencies = ['AED', 'AUD', 'BDT', 'BHD', 'BMD', 'BRL', 'CAD', 'CHF', 'CLP', + 'CNY', 'CZK', 'DKK', 'EUR', 'GBP', 'HKD', 'HUF', 'IDR', 'ILS', 'INR', 'JPY', 'KRW', 'KWD', + 'LKR', 'MMK', 'MXN', 'MYR', 'NGN', 'NOK', 'NZD', 'PHP', 'PKR', 'PLN', 'RUB', 'SAR', 'SEK', + 'SGD', 'THB', 'TRY', 'TWD', 'UAH', 'USD', 'VND', 'ZAR']; + private conversionRates: IConversionRates = {}; private ratesChangedCallback: ((rates: IConversionRates) => void) | undefined; + public ratesInitialized = false; // If true, it means rates are ready for use - constructor() { } + constructor() { + for (const fiat of this.debasingFiatCurrencies) { + this.conversionRates[fiat] = 0; + } + } public setProgressChangedCallback(fn: (rates: IConversionRates) => void) { this.ratesChangedCallback = fn; @@ -62,13 +69,14 @@ class FiatConversion { response = await axios.get(fiatConversionUrl, { headers: headers, timeout: 10000 }); } - const usd = response.data.data.find((item: any) => item.currencyCode === 'USD'); + for (const rate of response.data.data) { + if (this.debasingFiatCurrencies.includes(rate.currencyCode) && rate.provider === 'Bisq-Aggregate') { + this.conversionRates[rate.currencyCode] = Math.round(100 * rate.price) / 100; + } + } - this.conversionRates = { - 'USD': usd.price, - }; - - logger.debug(`USD Conversion Rate: ${usd.price}`); + this.ratesInitialized = true; + logger.debug(`USD Conversion Rate: ${this.conversionRates.USD}`); if (this.ratesChangedCallback) { this.ratesChangedCallback(this.conversionRates); diff --git a/backend/src/repositories/RatesRepository.ts b/backend/src/repositories/RatesRepository.ts new file mode 100644 index 000000000..e84ef2827 --- /dev/null +++ b/backend/src/repositories/RatesRepository.ts @@ -0,0 +1,21 @@ +import DB from '../database'; +import logger from '../logger'; +import { IConversionRates } from '../mempool.interfaces'; + +class RatesRepository { + public async $saveRate(height: number, rates: IConversionRates) { + try { + await DB.query(`INSERT INTO rates(height, bisq_rates) VALUE (?, ?)`, [height, JSON.stringify(rates)]); + } catch (e: any) { + if (e.errno === 1062) { // ER_DUP_ENTRY - This scenario is possible upon node backend restart + logger.debug(`Rate already exists for block ${height}, ignoring`); + } else { + logger.err(`Cannot save exchange rate into db for block ${height} Reason: ` + (e instanceof Error ? e.message : e)); + throw e; + } + } + } +} + +export default new RatesRepository(); +