2022-06-25 12:14:32 +02:00
|
|
|
import { Common } from '../api/common';
|
2022-07-06 21:03:55 +02:00
|
|
|
import config from '../config';
|
2022-06-25 12:14:32 +02:00
|
|
|
import DB from '../database';
|
|
|
|
import logger from '../logger';
|
|
|
|
import { IndexedDifficultyAdjustment } from '../mempool.interfaces';
|
|
|
|
|
|
|
|
class DifficultyAdjustmentsRepository {
|
|
|
|
public async $saveAdjustments(adjustment: IndexedDifficultyAdjustment): Promise<void> {
|
|
|
|
if (adjustment.height === 1) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
try {
|
|
|
|
const query = `INSERT INTO difficulty_adjustments(time, height, difficulty, adjustment) VALUE (FROM_UNIXTIME(?), ?, ?, ?)`;
|
|
|
|
const params: any[] = [
|
|
|
|
adjustment.time,
|
|
|
|
adjustment.height,
|
|
|
|
adjustment.difficulty,
|
|
|
|
adjustment.adjustment,
|
|
|
|
];
|
|
|
|
await DB.query(query, params);
|
|
|
|
} catch (e: any) {
|
|
|
|
if (e.errno === 1062) { // ER_DUP_ENTRY - This scenario is possible upon node backend restart
|
|
|
|
logger.debug(`Cannot save difficulty adjustment at block ${adjustment.height}, already indexed, ignoring`);
|
|
|
|
} else {
|
|
|
|
logger.err(`Cannot save difficulty adjustment at block ${adjustment.height}. Reason: ${e instanceof Error ? e.message : e}`);
|
|
|
|
throw e;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public async $getAdjustments(interval: string | null, descOrder: boolean = false): Promise<IndexedDifficultyAdjustment[]> {
|
|
|
|
interval = Common.getSqlInterval(interval);
|
|
|
|
|
2022-07-06 21:03:55 +02:00
|
|
|
let query = `SELECT
|
|
|
|
CAST(AVG(UNIX_TIMESTAMP(time)) as INT) as time,
|
|
|
|
CAST(AVG(height) AS INT) as height,
|
|
|
|
CAST(AVG(difficulty) as DOUBLE) as difficulty,
|
|
|
|
CAST(AVG(adjustment) as DOUBLE) as adjustment
|
2022-06-25 12:14:32 +02:00
|
|
|
FROM difficulty_adjustments`;
|
|
|
|
|
|
|
|
if (interval) {
|
|
|
|
query += ` WHERE time BETWEEN DATE_SUB(NOW(), INTERVAL ${interval}) AND NOW()`;
|
|
|
|
}
|
|
|
|
|
2022-07-06 21:03:55 +02:00
|
|
|
query += ` GROUP BY UNIX_TIMESTAMP(time) DIV ${86400}`;
|
|
|
|
|
2022-06-25 12:14:32 +02:00
|
|
|
if (descOrder === true) {
|
|
|
|
query += ` ORDER BY time DESC`;
|
|
|
|
} else {
|
|
|
|
query += ` ORDER BY time`;
|
|
|
|
}
|
|
|
|
|
|
|
|
try {
|
|
|
|
const [rows] = await DB.query(query);
|
|
|
|
return rows as IndexedDifficultyAdjustment[];
|
|
|
|
} catch (e) {
|
|
|
|
logger.err(`Cannot get difficulty adjustments from the database. Reason: ` + (e instanceof Error ? e.message : e));
|
|
|
|
throw e;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public async $getAdjustmentsHeights(): Promise<number[]> {
|
|
|
|
try {
|
|
|
|
const [rows]: any[] = await DB.query(`SELECT height FROM difficulty_adjustments`);
|
|
|
|
return rows.map(block => block.height);
|
|
|
|
} catch (e: any) {
|
|
|
|
logger.err(`Cannot get difficulty adjustment block heights. Reason: ${e instanceof Error ? e.message : e}`);
|
|
|
|
throw e;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public async $deleteAdjustementsFromHeight(height: number): Promise<void> {
|
|
|
|
try {
|
|
|
|
logger.info(`Delete newer difficulty adjustments from height ${height} from the database`);
|
|
|
|
await DB.query(`DELETE FROM difficulty_adjustments WHERE height >= ?`, [height]);
|
|
|
|
} catch (e: any) {
|
|
|
|
logger.err(`Cannot delete difficulty adjustments from the database. Reason: ${e instanceof Error ? e.message : e}`);
|
|
|
|
throw e;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public async $deleteLastAdjustment(): Promise<void> {
|
|
|
|
try {
|
|
|
|
logger.info(`Delete last difficulty adjustment from the database`);
|
|
|
|
await DB.query(`DELETE FROM difficulty_adjustments ORDER BY time LIMIT 1`);
|
|
|
|
} catch (e: any) {
|
|
|
|
logger.err(`Cannot delete last difficulty adjustment from the database. Reason: ${e instanceof Error ? e.message : e}`);
|
|
|
|
throw e;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
export default new DifficultyAdjustmentsRepository();
|
|
|
|
|