diff --git a/backend/src/api/database-migration.ts b/backend/src/api/database-migration.ts index 95f8c8707..a5a203758 100644 --- a/backend/src/api/database-migration.ts +++ b/backend/src/api/database-migration.ts @@ -7,7 +7,7 @@ import cpfpRepository from '../repositories/CpfpRepository'; import { RowDataPacket } from 'mysql2'; class DatabaseMigration { - private static currentVersion = 82; + private static currentVersion = 83; private queryTimeout = 3600_000; private statisticsAddedIndexed = false; private uniqueLogs: string[] = []; @@ -705,6 +705,11 @@ class DatabaseMigration { await this.$fixBadV1AuditBlocks(); await this.updateToSchemaVersion(82); } + + if (databaseSchemaVersion < 83) { + await this.$addPerSecondVsizeToStatistics(); + await this.updateToSchemaVersion(83); + } } /** @@ -1341,6 +1346,47 @@ class DatabaseMigration { } } } + + private async $addPerSecondVsizeToStatistics(): Promise { + await this.$executeQuery('ALTER TABLE `statistics` ADD `vsize_ps_1` int(11) NOT NULL DEFAULT 0'); + await this.$executeQuery('ALTER TABLE `statistics` ADD `vsize_ps_2` int(11) NOT NULL DEFAULT 0'); + await this.$executeQuery('ALTER TABLE `statistics` ADD `vsize_ps_3` int(11) NOT NULL DEFAULT 0'); + await this.$executeQuery('ALTER TABLE `statistics` ADD `vsize_ps_4` int(11) NOT NULL DEFAULT 0'); + await this.$executeQuery('ALTER TABLE `statistics` ADD `vsize_ps_5` int(11) NOT NULL DEFAULT 0'); + await this.$executeQuery('ALTER TABLE `statistics` ADD `vsize_ps_6` int(11) NOT NULL DEFAULT 0'); + await this.$executeQuery('ALTER TABLE `statistics` ADD `vsize_ps_8` int(11) NOT NULL DEFAULT 0'); + await this.$executeQuery('ALTER TABLE `statistics` ADD `vsize_ps_10` int(11) NOT NULL DEFAULT 0'); + await this.$executeQuery('ALTER TABLE `statistics` ADD `vsize_ps_12` int(11) NOT NULL DEFAULT 0'); + await this.$executeQuery('ALTER TABLE `statistics` ADD `vsize_ps_15` int(11) NOT NULL DEFAULT 0'); + await this.$executeQuery('ALTER TABLE `statistics` ADD `vsize_ps_20` int(11) NOT NULL DEFAULT 0'); + await this.$executeQuery('ALTER TABLE `statistics` ADD `vsize_ps_30` int(11) NOT NULL DEFAULT 0'); + await this.$executeQuery('ALTER TABLE `statistics` ADD `vsize_ps_40` int(11) NOT NULL DEFAULT 0'); + await this.$executeQuery('ALTER TABLE `statistics` ADD `vsize_ps_50` int(11) NOT NULL DEFAULT 0'); + await this.$executeQuery('ALTER TABLE `statistics` ADD `vsize_ps_60` int(11) NOT NULL DEFAULT 0'); + await this.$executeQuery('ALTER TABLE `statistics` ADD `vsize_ps_70` int(11) NOT NULL DEFAULT 0'); + await this.$executeQuery('ALTER TABLE `statistics` ADD `vsize_ps_80` int(11) NOT NULL DEFAULT 0'); + await this.$executeQuery('ALTER TABLE `statistics` ADD `vsize_ps_90` int(11) NOT NULL DEFAULT 0'); + await this.$executeQuery('ALTER TABLE `statistics` ADD `vsize_ps_100` int(11) NOT NULL DEFAULT 0'); + await this.$executeQuery('ALTER TABLE `statistics` ADD `vsize_ps_125` int(11) NOT NULL DEFAULT 0'); + await this.$executeQuery('ALTER TABLE `statistics` ADD `vsize_ps_150` int(11) NOT NULL DEFAULT 0'); + await this.$executeQuery('ALTER TABLE `statistics` ADD `vsize_ps_175` int(11) NOT NULL DEFAULT 0'); + await this.$executeQuery('ALTER TABLE `statistics` ADD `vsize_ps_200` int(11) NOT NULL DEFAULT 0'); + await this.$executeQuery('ALTER TABLE `statistics` ADD `vsize_ps_250` int(11) NOT NULL DEFAULT 0'); + await this.$executeQuery('ALTER TABLE `statistics` ADD `vsize_ps_300` int(11) NOT NULL DEFAULT 0'); + await this.$executeQuery('ALTER TABLE `statistics` ADD `vsize_ps_350` int(11) NOT NULL DEFAULT 0'); + await this.$executeQuery('ALTER TABLE `statistics` ADD `vsize_ps_400` int(11) NOT NULL DEFAULT 0'); + await this.$executeQuery('ALTER TABLE `statistics` ADD `vsize_ps_500` int(11) NOT NULL DEFAULT 0'); + await this.$executeQuery('ALTER TABLE `statistics` ADD `vsize_ps_600` int(11) NOT NULL DEFAULT 0'); + await this.$executeQuery('ALTER TABLE `statistics` ADD `vsize_ps_700` int(11) NOT NULL DEFAULT 0'); + await this.$executeQuery('ALTER TABLE `statistics` ADD `vsize_ps_800` int(11) NOT NULL DEFAULT 0'); + await this.$executeQuery('ALTER TABLE `statistics` ADD `vsize_ps_900` int(11) NOT NULL DEFAULT 0'); + await this.$executeQuery('ALTER TABLE `statistics` ADD `vsize_ps_1000` int(11) NOT NULL DEFAULT 0'); + await this.$executeQuery('ALTER TABLE `statistics` ADD `vsize_ps_1200` int(11) NOT NULL DEFAULT 0'); + await this.$executeQuery('ALTER TABLE `statistics` ADD `vsize_ps_1400` int(11) NOT NULL DEFAULT 0'); + await this.$executeQuery('ALTER TABLE `statistics` ADD `vsize_ps_1600` int(11) NOT NULL DEFAULT 0'); + await this.$executeQuery('ALTER TABLE `statistics` ADD `vsize_ps_1800` int(11) NOT NULL DEFAULT 0'); + await this.$executeQuery('ALTER TABLE `statistics` ADD `vsize_ps_2000` int(11) NOT NULL DEFAULT 0'); + } } export default new DatabaseMigration(); diff --git a/backend/src/api/mempool.ts b/backend/src/api/mempool.ts index 1f55179fb..f1dba162c 100644 --- a/backend/src/api/mempool.ts +++ b/backend/src/api/mempool.ts @@ -12,6 +12,7 @@ import rbfCache from './rbf-cache'; import { Acceleration } from './services/acceleration'; import redisCache from './redis-cache'; import blocks from './blocks'; +import { logFees } from './statistics/statistics'; class Mempool { private inSync: boolean = false; @@ -34,6 +35,7 @@ class Mempool { private vBytesPerSecondArray: VbytesPerSecond[] = []; private vBytesPerSecond: number = 0; + private vBytesPerSecondByFeeRate: { [feePerWU: number]: number } = {}; private mempoolProtection = 0; private latestTransactions: any[] = []; @@ -193,6 +195,10 @@ class Mempool { return this.vBytesPerSecond; } + public getVBytesPerSecondByFeeRate(): { [feePerWU: number]: number } { + return this.vBytesPerSecondByFeeRate; + } + public getFirstSeenForTransactions(txIds: string[]): number[] { const txTimes: number[] = []; txIds.forEach((txId: string) => { @@ -270,6 +276,7 @@ class Mempool { this.vBytesPerSecondArray.push({ unixTime: new Date().getTime(), vSize: transaction.vsize, + effectiveFeePerVsize: transaction.effectiveFeePerVsize }); } hasChange = true; @@ -588,6 +595,21 @@ class Mempool { this.vBytesPerSecond = Math.round( this.vBytesPerSecondArray.map((data) => data.vSize).reduce((a, b) => a + b) / config.STATISTICS.TX_PER_SECOND_SAMPLE_PERIOD ); + + if (!Common.isLiquid()) { + this.vBytesPerSecondByFeeRate = {}; + for (const tx of this.vBytesPerSecondArray) { + for (let i = 0; i < logFees.length; i++) { + if (tx.effectiveFeePerVsize < logFees[i + 1] || i === logFees.length - 1) { + this.vBytesPerSecondByFeeRate[logFees[i]] = (this.vBytesPerSecondByFeeRate[logFees[i]] || 0) + tx.vSize; + break; + } + } + } + for (const feeRate of Object.keys(this.vBytesPerSecondByFeeRate)) { + this.vBytesPerSecondByFeeRate[feeRate] = Math.round(this.vBytesPerSecondByFeeRate[feeRate] / config.STATISTICS.TX_PER_SECOND_SAMPLE_PERIOD); + } + } } } diff --git a/backend/src/api/statistics/statistics-api.ts b/backend/src/api/statistics/statistics-api.ts index 2d66d69d9..50974158f 100644 --- a/backend/src/api/statistics/statistics-api.ts +++ b/backend/src/api/statistics/statistics-api.ts @@ -53,7 +53,45 @@ class StatisticsApi { vsize_1400, vsize_1600, vsize_1800, - vsize_2000 + vsize_2000, + vsize_ps_1, + vsize_ps_2, + vsize_ps_3, + vsize_ps_4, + vsize_ps_5, + vsize_ps_6, + vsize_ps_8, + vsize_ps_10, + vsize_ps_12, + vsize_ps_15, + vsize_ps_20, + vsize_ps_30, + vsize_ps_40, + vsize_ps_50, + vsize_ps_60, + vsize_ps_70, + vsize_ps_80, + vsize_ps_90, + vsize_ps_100, + vsize_ps_125, + vsize_ps_150, + vsize_ps_175, + vsize_ps_200, + vsize_ps_250, + vsize_ps_300, + vsize_ps_350, + vsize_ps_400, + vsize_ps_500, + vsize_ps_600, + vsize_ps_700, + vsize_ps_800, + vsize_ps_900, + vsize_ps_1000, + vsize_ps_1200, + vsize_ps_1400, + vsize_ps_1600, + vsize_ps_1800, + vsize_ps_2000 ) VALUES (NOW(), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)`; @@ -67,56 +105,94 @@ class StatisticsApi { public async $create(statistics: Statistic, convertToDatetime = false): Promise { try { const query = `INSERT INTO statistics( - added, - unconfirmed_transactions, - tx_per_second, - vbytes_per_second, - mempool_byte_weight, - fee_data, - total_fee, - min_fee, - vsize_1, - vsize_2, - vsize_3, - vsize_4, - vsize_5, - vsize_6, - vsize_8, - vsize_10, - vsize_12, - vsize_15, - vsize_20, - vsize_30, - vsize_40, - vsize_50, - vsize_60, - vsize_70, - vsize_80, - vsize_90, - vsize_100, - vsize_125, - vsize_150, - vsize_175, - vsize_200, - vsize_250, - vsize_300, - vsize_350, - vsize_400, - vsize_500, - vsize_600, - vsize_700, - vsize_800, - vsize_900, - vsize_1000, - vsize_1200, - vsize_1400, - vsize_1600, - vsize_1800, - vsize_2000 - ) - VALUES (${convertToDatetime ? `FROM_UNIXTIME(${statistics.added})` : statistics.added}, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, - ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`; - + added, + unconfirmed_transactions, + tx_per_second, + vbytes_per_second, + mempool_byte_weight, + fee_data, + total_fee, + min_fee, + vsize_1, + vsize_2, + vsize_3, + vsize_4, + vsize_5, + vsize_6, + vsize_8, + vsize_10, + vsize_12, + vsize_15, + vsize_20, + vsize_30, + vsize_40, + vsize_50, + vsize_60, + vsize_70, + vsize_80, + vsize_90, + vsize_100, + vsize_125, + vsize_150, + vsize_175, + vsize_200, + vsize_250, + vsize_300, + vsize_350, + vsize_400, + vsize_500, + vsize_600, + vsize_700, + vsize_800, + vsize_900, + vsize_1000, + vsize_1200, + vsize_1400, + vsize_1600, + vsize_1800, + vsize_2000, + vsize_ps_1, + vsize_ps_2, + vsize_ps_3, + vsize_ps_4, + vsize_ps_5, + vsize_ps_6, + vsize_ps_8, + vsize_ps_10, + vsize_ps_12, + vsize_ps_15, + vsize_ps_20, + vsize_ps_30, + vsize_ps_40, + vsize_ps_50, + vsize_ps_60, + vsize_ps_70, + vsize_ps_80, + vsize_ps_90, + vsize_ps_100, + vsize_ps_125, + vsize_ps_150, + vsize_ps_175, + vsize_ps_200, + vsize_ps_250, + vsize_ps_300, + vsize_ps_350, + vsize_ps_400, + vsize_ps_500, + vsize_ps_600, + vsize_ps_700, + vsize_ps_800, + vsize_ps_900, + vsize_ps_1000, + vsize_ps_1200, + vsize_ps_1400, + vsize_ps_1600, + vsize_ps_1800, + vsize_ps_2000 + ) + VALUES (${convertToDatetime ? `FROM_UNIXTIME(${statistics.added})` : statistics.added}, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, + ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`; + const params: (string | number)[] = [ statistics.unconfirmed_transactions, statistics.tx_per_second, @@ -163,6 +239,44 @@ class StatisticsApi { statistics.vsize_1600, statistics.vsize_1800, statistics.vsize_2000, + statistics.vsize_ps_1, + statistics.vsize_ps_2, + statistics.vsize_ps_3, + statistics.vsize_ps_4, + statistics.vsize_ps_5, + statistics.vsize_ps_6, + statistics.vsize_ps_8, + statistics.vsize_ps_10, + statistics.vsize_ps_12, + statistics.vsize_ps_15, + statistics.vsize_ps_20, + statistics.vsize_ps_30, + statistics.vsize_ps_40, + statistics.vsize_ps_50, + statistics.vsize_ps_60, + statistics.vsize_ps_70, + statistics.vsize_ps_80, + statistics.vsize_ps_90, + statistics.vsize_ps_100, + statistics.vsize_ps_125, + statistics.vsize_ps_150, + statistics.vsize_ps_175, + statistics.vsize_ps_200, + statistics.vsize_ps_250, + statistics.vsize_ps_300, + statistics.vsize_ps_350, + statistics.vsize_ps_400, + statistics.vsize_ps_500, + statistics.vsize_ps_600, + statistics.vsize_ps_700, + statistics.vsize_ps_800, + statistics.vsize_ps_900, + statistics.vsize_ps_1000, + statistics.vsize_ps_1200, + statistics.vsize_ps_1400, + statistics.vsize_ps_1600, + statistics.vsize_ps_1800, + statistics.vsize_ps_2000, ]; const [result]: any = await DB.query(query, params); return result.insertId; @@ -214,7 +328,45 @@ class StatisticsApi { CAST(avg(vsize_1400) as DOUBLE) as vsize_1400, CAST(avg(vsize_1600) as DOUBLE) as vsize_1600, CAST(avg(vsize_1800) as DOUBLE) as vsize_1800, - CAST(avg(vsize_2000) as DOUBLE) as vsize_2000 \ + CAST(avg(vsize_2000) as DOUBLE) as vsize_2000, + CAST(avg(vsize_ps_1) as DOUBLE) as vsize_ps_1, + CAST(avg(vsize_ps_2) as DOUBLE) as vsize_ps_2, + CAST(avg(vsize_ps_3) as DOUBLE) as vsize_ps_3, + CAST(avg(vsize_ps_4) as DOUBLE) as vsize_ps_4, + CAST(avg(vsize_ps_5) as DOUBLE) as vsize_ps_5, + CAST(avg(vsize_ps_6) as DOUBLE) as vsize_ps_6, + CAST(avg(vsize_ps_8) as DOUBLE) as vsize_ps_8, + CAST(avg(vsize_ps_10) as DOUBLE) as vsize_ps_10, + CAST(avg(vsize_ps_12) as DOUBLE) as vsize_ps_12, + CAST(avg(vsize_ps_15) as DOUBLE) as vsize_ps_15, + CAST(avg(vsize_ps_20) as DOUBLE) as vsize_ps_20, + CAST(avg(vsize_ps_30) as DOUBLE) as vsize_ps_30, + CAST(avg(vsize_ps_40) as DOUBLE) as vsize_ps_40, + CAST(avg(vsize_ps_50) as DOUBLE) as vsize_ps_50, + CAST(avg(vsize_ps_60) as DOUBLE) as vsize_ps_60, + CAST(avg(vsize_ps_70) as DOUBLE) as vsize_ps_70, + CAST(avg(vsize_ps_80) as DOUBLE) as vsize_ps_80, + CAST(avg(vsize_ps_90) as DOUBLE) as vsize_ps_90, + CAST(avg(vsize_ps_100) as DOUBLE) as vsize_ps_100, + CAST(avg(vsize_ps_125) as DOUBLE) as vsize_ps_125, + CAST(avg(vsize_ps_150) as DOUBLE) as vsize_ps_150, + CAST(avg(vsize_ps_175) as DOUBLE) as vsize_ps_175, + CAST(avg(vsize_ps_200) as DOUBLE) as vsize_ps_200, + CAST(avg(vsize_ps_250) as DOUBLE) as vsize_ps_250, + CAST(avg(vsize_ps_300) as DOUBLE) as vsize_ps_300, + CAST(avg(vsize_ps_350) as DOUBLE) as vsize_ps_350, + CAST(avg(vsize_ps_400) as DOUBLE) as vsize_ps_400, + CAST(avg(vsize_ps_500) as DOUBLE) as vsize_ps_500, + CAST(avg(vsize_ps_600) as DOUBLE) as vsize_ps_600, + CAST(avg(vsize_ps_700) as DOUBLE) as vsize_ps_700, + CAST(avg(vsize_ps_800) as DOUBLE) as vsize_ps_800, + CAST(avg(vsize_ps_900) as DOUBLE) as vsize_ps_900, + CAST(avg(vsize_ps_1000) as DOUBLE) as vsize_ps_1000, + CAST(avg(vsize_ps_1200) as DOUBLE) as vsize_ps_1200, + CAST(avg(vsize_ps_1400) as DOUBLE) as vsize_ps_1400, + CAST(avg(vsize_ps_1600) as DOUBLE) as vsize_ps_1600, + CAST(avg(vsize_ps_1800) as DOUBLE) as vsize_ps_1800, + CAST(avg(vsize_ps_2000) as DOUBLE) as vsize_ps_2000 \ FROM statistics \ ${interval === 'all' ? '' : `WHERE added BETWEEN DATE_SUB(NOW(), INTERVAL ${interval}) AND NOW()`} \ GROUP BY UNIX_TIMESTAMP(added) DIV ${div} \ @@ -264,7 +416,45 @@ class StatisticsApi { vsize_1400, vsize_1600, vsize_1800, - vsize_2000 \ + vsize_2000, + vsize_ps_1, + vsize_ps_2, + vsize_ps_3, + vsize_ps_4, + vsize_ps_5, + vsize_ps_6, + vsize_ps_8, + vsize_ps_10, + vsize_ps_12, + vsize_ps_15, + vsize_ps_20, + vsize_ps_30, + vsize_ps_40, + vsize_ps_50, + vsize_ps_60, + vsize_ps_70, + vsize_ps_80, + vsize_ps_90, + vsize_ps_100, + vsize_ps_125, + vsize_ps_150, + vsize_ps_175, + vsize_ps_200, + vsize_ps_250, + vsize_ps_300, + vsize_ps_350, + vsize_ps_400, + vsize_ps_500, + vsize_ps_600, + vsize_ps_700, + vsize_ps_800, + vsize_ps_900, + vsize_ps_1000, + vsize_ps_1200, + vsize_ps_1400, + vsize_ps_1600, + vsize_ps_1800, + vsize_ps_2000 \ FROM statistics \ ${interval === 'all' ? '' : `WHERE added BETWEEN DATE_SUB(NOW(), INTERVAL ${interval}) AND NOW()`} \ GROUP BY UNIX_TIMESTAMP(added) DIV ${div} \ @@ -452,7 +642,47 @@ class StatisticsApi { s.vsize_1600, s.vsize_1800, s.vsize_2000, - ] + ], + vsizes_ps: [ + s.vsize_ps_1, + s.vsize_ps_2, + s.vsize_ps_3, + s.vsize_ps_4, + s.vsize_ps_5, + s.vsize_ps_6, + s.vsize_ps_8, + s.vsize_ps_10, + s.vsize_ps_12, + s.vsize_ps_15, + s.vsize_ps_20, + s.vsize_ps_30, + s.vsize_ps_40, + s.vsize_ps_50, + s.vsize_ps_60, + s.vsize_ps_70, + s.vsize_ps_80, + s.vsize_ps_90, + s.vsize_ps_100, + s.vsize_ps_125, + s.vsize_ps_150, + s.vsize_ps_175, + s.vsize_ps_200, + s.vsize_ps_250, + s.vsize_ps_300, + s.vsize_ps_350, + s.vsize_ps_400, + s.vsize_ps_500, + s.vsize_ps_600, + s.vsize_ps_700, + s.vsize_ps_800, + s.vsize_ps_900, + s.vsize_ps_1000, + s.vsize_ps_1200, + s.vsize_ps_1400, + s.vsize_ps_1600, + s.vsize_ps_1800, + s.vsize_ps_2000, + ], }; }); } @@ -506,6 +736,44 @@ class StatisticsApi { vsize_1600: s.vsizes[35], vsize_1800: s.vsizes[36], vsize_2000: s.vsizes[37], + vsize_ps_1: s.vsizes_ps[0] || 0, + vsize_ps_2: s.vsizes_ps[1] || 0, + vsize_ps_3: s.vsizes_ps[2] || 0, + vsize_ps_4: s.vsizes_ps[3] || 0, + vsize_ps_5: s.vsizes_ps[4] || 0, + vsize_ps_6: s.vsizes_ps[5] || 0, + vsize_ps_8: s.vsizes_ps[6] || 0, + vsize_ps_10: s.vsizes_ps[7] || 0, + vsize_ps_12: s.vsizes_ps[8] || 0, + vsize_ps_15: s.vsizes_ps[9] || 0, + vsize_ps_20: s.vsizes_ps[10] || 0, + vsize_ps_30: s.vsizes_ps[11] || 0, + vsize_ps_40: s.vsizes_ps[12] || 0, + vsize_ps_50: s.vsizes_ps[13] || 0, + vsize_ps_60: s.vsizes_ps[14] || 0, + vsize_ps_70: s.vsizes_ps[15] || 0, + vsize_ps_80: s.vsizes_ps[16] || 0, + vsize_ps_90: s.vsizes_ps[17] || 0, + vsize_ps_100: s.vsizes_ps[18] || 0, + vsize_ps_125: s.vsizes_ps[19] || 0, + vsize_ps_150: s.vsizes_ps[20] || 0, + vsize_ps_175: s.vsizes_ps[21] || 0, + vsize_ps_200: s.vsizes_ps[22] || 0, + vsize_ps_250: s.vsizes_ps[23] || 0, + vsize_ps_300: s.vsizes_ps[24] || 0, + vsize_ps_350: s.vsizes_ps[25] || 0, + vsize_ps_400: s.vsizes_ps[26] || 0, + vsize_ps_500: s.vsizes_ps[27] || 0, + vsize_ps_600: s.vsizes_ps[28] || 0, + vsize_ps_700: s.vsizes_ps[29] || 0, + vsize_ps_800: s.vsizes_ps[30] || 0, + vsize_ps_900: s.vsizes_ps[31] || 0, + vsize_ps_1000: s.vsizes_ps[32] || 0, + vsize_ps_1200: s.vsizes_ps[33] || 0, + vsize_ps_1400: s.vsizes_ps[34] || 0, + vsize_ps_1600: s.vsizes_ps[35] || 0, + vsize_ps_1800: s.vsizes_ps[36] || 0, + vsize_ps_2000: s.vsizes_ps[37] || 0, } }); } diff --git a/backend/src/api/statistics/statistics.ts b/backend/src/api/statistics/statistics.ts index 2926a4b17..7801bba6e 100644 --- a/backend/src/api/statistics/statistics.ts +++ b/backend/src/api/statistics/statistics.ts @@ -4,6 +4,9 @@ import { TransactionExtended, OptimizedStatistic } from '../../mempool.interface import { Common } from '../common'; import statisticsApi from './statistics-api'; +export const logFees = [1, 2, 3, 4, 5, 6, 8, 10, 12, 15, 20, 30, 40, 50, 60, 70, 80, 90, 100, 125, 150, 175, 200, + 250, 300, 350, 400, 500, 600, 700, 800, 900, 1000, 1200, 1400, 1600, 1800, 2000]; + class Statistics { protected intervalTimer: NodeJS.Timer | undefined; protected lastRun: number = 0; @@ -42,6 +45,7 @@ class Statistics { const currentMempool = memPool.getMempool(); const txPerSecond = memPool.getTxPerSecond(); const vBytesPerSecond = memPool.getVBytesPerSecond(); + const vBytesPerSecondByFeeRate = memPool.getVBytesPerSecondByFeeRate(); logger.debug('Running statistics'); @@ -73,9 +77,6 @@ class Statistics { const totalWeight = memPoolArray.map((tx) => tx.vsize).reduce((acc, curr) => acc + curr) * 4; const totalFee = memPoolArray.map((tx) => tx.fee).reduce((acc, curr) => acc + curr); - const logFees = [1, 2, 3, 4, 5, 6, 8, 10, 12, 15, 20, 30, 40, 50, 60, 70, 80, 90, 100, 125, 150, 175, 200, - 250, 300, 350, 400, 500, 600, 700, 800, 900, 1000, 1200, 1400, 1600, 1800, 2000]; - const weightVsizeFees: { [feePerWU: number]: number } = {}; const lastItem = logFees.length - 1; @@ -147,6 +148,44 @@ class Statistics { vsize_1600: weightVsizeFees['1600'] || 0, vsize_1800: weightVsizeFees['1800'] || 0, vsize_2000: weightVsizeFees['2000'] || 0, + vsize_ps_1: vBytesPerSecondByFeeRate['1'] || 0, + vsize_ps_2: vBytesPerSecondByFeeRate['2'] || 0, + vsize_ps_3: vBytesPerSecondByFeeRate['3'] || 0, + vsize_ps_4: vBytesPerSecondByFeeRate['4'] || 0, + vsize_ps_5: vBytesPerSecondByFeeRate['5'] || 0, + vsize_ps_6: vBytesPerSecondByFeeRate['6'] || 0, + vsize_ps_8: vBytesPerSecondByFeeRate['8'] || 0, + vsize_ps_10: vBytesPerSecondByFeeRate['10'] || 0, + vsize_ps_12: vBytesPerSecondByFeeRate['12'] || 0, + vsize_ps_15: vBytesPerSecondByFeeRate['15'] || 0, + vsize_ps_20: vBytesPerSecondByFeeRate['20'] || 0, + vsize_ps_30: vBytesPerSecondByFeeRate['30'] || 0, + vsize_ps_40: vBytesPerSecondByFeeRate['40'] || 0, + vsize_ps_50: vBytesPerSecondByFeeRate['50'] || 0, + vsize_ps_60: vBytesPerSecondByFeeRate['60'] || 0, + vsize_ps_70: vBytesPerSecondByFeeRate['70'] || 0, + vsize_ps_80: vBytesPerSecondByFeeRate['80'] || 0, + vsize_ps_90: vBytesPerSecondByFeeRate['90'] || 0, + vsize_ps_100: vBytesPerSecondByFeeRate['100'] || 0, + vsize_ps_125: vBytesPerSecondByFeeRate['125'] || 0, + vsize_ps_150: vBytesPerSecondByFeeRate['150'] || 0, + vsize_ps_175: vBytesPerSecondByFeeRate['175'] || 0, + vsize_ps_200: vBytesPerSecondByFeeRate['200'] || 0, + vsize_ps_250: vBytesPerSecondByFeeRate['250'] || 0, + vsize_ps_300: vBytesPerSecondByFeeRate['300'] || 0, + vsize_ps_350: vBytesPerSecondByFeeRate['350'] || 0, + vsize_ps_400: vBytesPerSecondByFeeRate['400'] || 0, + vsize_ps_500: vBytesPerSecondByFeeRate['500'] || 0, + vsize_ps_600: vBytesPerSecondByFeeRate['600'] || 0, + vsize_ps_700: vBytesPerSecondByFeeRate['700'] || 0, + vsize_ps_800: vBytesPerSecondByFeeRate['800'] || 0, + vsize_ps_900: vBytesPerSecondByFeeRate['900'] || 0, + vsize_ps_1000: vBytesPerSecondByFeeRate['1000'] || 0, + vsize_ps_1200: vBytesPerSecondByFeeRate['1200'] || 0, + vsize_ps_1400: vBytesPerSecondByFeeRate['1400'] || 0, + vsize_ps_1600: vBytesPerSecondByFeeRate['1600'] || 0, + vsize_ps_1800: vBytesPerSecondByFeeRate['1800'] || 0, + vsize_ps_2000: vBytesPerSecondByFeeRate['2000'] || 0, }); if (this.newStatisticsEntryCallback && insertId) { diff --git a/backend/src/mempool.interfaces.ts b/backend/src/mempool.interfaces.ts index ccbc94bfa..9efd2e4df 100644 --- a/backend/src/mempool.interfaces.ts +++ b/backend/src/mempool.interfaces.ts @@ -439,6 +439,46 @@ export interface Statistic { vsize_1600: number; vsize_1800: number; vsize_2000: number; + + vsize_ps_1: number; + vsize_ps_2: number; + vsize_ps_3: number; + vsize_ps_4: number; + vsize_ps_5: number; + vsize_ps_6: number; + vsize_ps_8: number; + vsize_ps_10: number; + vsize_ps_12: number; + vsize_ps_15: number; + vsize_ps_20: number; + vsize_ps_30: number; + vsize_ps_40: number; + vsize_ps_50: number; + vsize_ps_60: number; + vsize_ps_70: number; + vsize_ps_80: number; + vsize_ps_90: number; + vsize_ps_100: number; + vsize_ps_125: number; + vsize_ps_150: number; + vsize_ps_175: number; + vsize_ps_200: number; + vsize_ps_250: number; + vsize_ps_300: number; + vsize_ps_350: number; + vsize_ps_400: number; + vsize_ps_500: number; + vsize_ps_600: number; + vsize_ps_700: number; + vsize_ps_800: number; + vsize_ps_900: number; + vsize_ps_1000: number; + vsize_ps_1200: number; + vsize_ps_1400: number; + vsize_ps_1600: number; + vsize_ps_1800: number; + vsize_ps_2000: number; + } export interface OptimizedStatistic { @@ -449,6 +489,7 @@ export interface OptimizedStatistic { mempool_byte_weight: number; min_fee: number; vsizes: number[]; + vsizes_ps: number[]; } export interface TxTrackingInfo { @@ -481,6 +522,7 @@ export interface WebsocketResponse { export interface VbytesPerSecond { unixTime: number; vSize: number; + effectiveFeePerVsize: number; } export interface RequiredSpec { [name: string]: RequiredParams; }