Add separate effective fee stats fields
This commit is contained in:
parent
3c84505579
commit
2befbec7a5
@ -244,7 +244,7 @@ class Blocks {
|
|||||||
*/
|
*/
|
||||||
private async $getBlockExtended(block: IEsploraApi.Block, transactions: TransactionExtended[]): Promise<BlockExtended> {
|
private async $getBlockExtended(block: IEsploraApi.Block, transactions: TransactionExtended[]): Promise<BlockExtended> {
|
||||||
const coinbaseTx = transactionUtils.stripCoinbaseTransaction(transactions[0]);
|
const coinbaseTx = transactionUtils.stripCoinbaseTransaction(transactions[0]);
|
||||||
|
|
||||||
const blk: Partial<BlockExtended> = Object.assign({}, block);
|
const blk: Partial<BlockExtended> = Object.assign({}, block);
|
||||||
const extras: Partial<BlockExtension> = {};
|
const extras: Partial<BlockExtension> = {};
|
||||||
|
|
||||||
@ -268,15 +268,17 @@ class Blocks {
|
|||||||
extras.segwitTotalWeight = 0;
|
extras.segwitTotalWeight = 0;
|
||||||
} else {
|
} else {
|
||||||
const stats: IBitcoinApi.BlockStats = await bitcoinClient.getBlockStats(block.id);
|
const stats: IBitcoinApi.BlockStats = await bitcoinClient.getBlockStats(block.id);
|
||||||
let feeStats = {
|
const feeStats = {
|
||||||
medianFee: stats.feerate_percentiles[2], // 50th percentiles
|
medianFee: stats.feerate_percentiles[2], // 50th percentiles
|
||||||
feeRange: [stats.minfeerate, stats.feerate_percentiles, stats.maxfeerate].flat(),
|
feeRange: [stats.minfeerate, stats.feerate_percentiles, stats.maxfeerate].flat(),
|
||||||
};
|
};
|
||||||
if (transactions?.length > 1) {
|
|
||||||
feeStats = Common.calcEffectiveFeeStatistics(transactions);
|
|
||||||
}
|
|
||||||
extras.medianFee = feeStats.medianFee;
|
extras.medianFee = feeStats.medianFee;
|
||||||
extras.feeRange = feeStats.feeRange;
|
extras.feeRange = feeStats.feeRange;
|
||||||
|
if (transactions?.length > 1) {
|
||||||
|
const effectiveFeeStats = Common.calcEffectiveFeeStatistics(transactions);
|
||||||
|
extras.effectiveMedianFee = effectiveFeeStats.effective_median;
|
||||||
|
extras.effectiveFeeRange = effectiveFeeStats.effective_range;
|
||||||
|
}
|
||||||
extras.totalFees = stats.totalfee;
|
extras.totalFees = stats.totalfee;
|
||||||
extras.avgFee = stats.avgfee;
|
extras.avgFee = stats.avgfee;
|
||||||
extras.avgFeeRate = stats.avgfeerate;
|
extras.avgFeeRate = stats.avgfeerate;
|
||||||
@ -296,7 +298,7 @@ class Blocks {
|
|||||||
extras.medianFeeAmt = extras.feePercentiles[3];
|
extras.medianFeeAmt = extras.feePercentiles[3];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extras.virtualSize = block.weight / 4.0;
|
extras.virtualSize = block.weight / 4.0;
|
||||||
if (coinbaseTx?.vout.length > 0) {
|
if (coinbaseTx?.vout.length > 0) {
|
||||||
extras.coinbaseAddress = coinbaseTx.vout[0].scriptpubkey_address ?? null;
|
extras.coinbaseAddress = coinbaseTx.vout[0].scriptpubkey_address ?? null;
|
||||||
@ -1316,6 +1318,8 @@ class Blocks {
|
|||||||
avg_fee_rate: block.extras.avgFeeRate ?? null,
|
avg_fee_rate: block.extras.avgFeeRate ?? null,
|
||||||
median_fee_rate: block.extras.medianFee ?? null,
|
median_fee_rate: block.extras.medianFee ?? null,
|
||||||
fee_rate_percentiles: block.extras.feeRange ?? null,
|
fee_rate_percentiles: block.extras.feeRange ?? null,
|
||||||
|
effective_median_fee_rate: block.extras.effectiveMedianFee ?? null,
|
||||||
|
effective_fee_rate_percentiles: block.extras.effectiveFeeRange ?? null,
|
||||||
total_inputs: block.extras.totalInputs ?? null,
|
total_inputs: block.extras.totalInputs ?? null,
|
||||||
total_input_amt: block.extras.totalInputAmt ?? null,
|
total_input_amt: block.extras.totalInputAmt ?? null,
|
||||||
total_outputs: block.extras.totalOutputs ?? null,
|
total_outputs: block.extras.totalOutputs ?? null,
|
||||||
@ -1378,6 +1382,17 @@ class Blocks {
|
|||||||
'perc_90': cleanBlock.fee_rate_percentiles[5],
|
'perc_90': cleanBlock.fee_rate_percentiles[5],
|
||||||
'max': cleanBlock.fee_rate_percentiles[6],
|
'max': cleanBlock.fee_rate_percentiles[6],
|
||||||
};
|
};
|
||||||
|
if (cleanBlock.effective_fee_rate_percentiles) {
|
||||||
|
cleanBlock.effective_fee_rate_percentiles = {
|
||||||
|
'min': cleanBlock.effective_fee_rate_percentiles[0],
|
||||||
|
'perc_10': cleanBlock.effective_fee_rate_percentiles[1],
|
||||||
|
'perc_25': cleanBlock.effective_fee_rate_percentiles[2],
|
||||||
|
'perc_50': cleanBlock.effective_fee_rate_percentiles[3],
|
||||||
|
'perc_75': cleanBlock.effective_fee_rate_percentiles[4],
|
||||||
|
'perc_90': cleanBlock.effective_fee_rate_percentiles[5],
|
||||||
|
'max': cleanBlock.effective_fee_rate_percentiles[6],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
// Re-org can happen after indexing so we need to always get the
|
// Re-org can happen after indexing so we need to always get the
|
||||||
// latest state from core
|
// latest state from core
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import * as bitcoinjs from 'bitcoinjs-lib';
|
import * as bitcoinjs from 'bitcoinjs-lib';
|
||||||
import { Request } from 'express';
|
import { Request } from 'express';
|
||||||
import { EffectiveFeeStats, MempoolBlockWithTransactions, TransactionExtended, MempoolTransactionExtended, TransactionStripped, WorkingEffectiveFeeStats, TransactionClassified, TransactionFlags } from '../mempool.interfaces';
|
import { EffectiveFeeStats, MempoolBlockWithTransactions, TransactionExtended, MempoolTransactionExtended, TransactionStripped, WorkingEffectiveFeeStats, TransactionClassified, TransactionFlags, FeeStats } from '../mempool.interfaces';
|
||||||
import config from '../config';
|
import config from '../config';
|
||||||
import { NodeSocket } from '../repositories/NodesSocketsRepository';
|
import { NodeSocket } from '../repositories/NodesSocketsRepository';
|
||||||
import { isIP } from 'net';
|
import { isIP } from 'net';
|
||||||
@ -856,6 +856,15 @@ export class Common {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static calcFeeStatistics(transactions: { txid: string, feePerVsize: number }[]): FeeStats {
|
||||||
|
// skip the coinbase, then sort the remaining fee rates
|
||||||
|
const sortedRates = transactions.slice(1).map(tx => tx.feePerVsize).sort((a, b) => a - b);
|
||||||
|
return {
|
||||||
|
median: Math.round(Common.getNthPercentile(50, sortedRates)),
|
||||||
|
range: [0, 10, 25, 50, 75, 90, 100].map(n => Math.round(Common.getNthPercentile(n, sortedRates))),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
static calcEffectiveFeeStatistics(transactions: { weight: number, fee: number, effectiveFeePerVsize?: number, txid: string, acceleration?: boolean }[]): EffectiveFeeStats {
|
static calcEffectiveFeeStatistics(transactions: { weight: number, fee: number, effectiveFeePerVsize?: number, txid: string, acceleration?: boolean }[]): EffectiveFeeStats {
|
||||||
const sortedTxs = transactions.map(tx => { return { txid: tx.txid, weight: tx.weight, rate: tx.effectiveFeePerVsize || ((tx.fee || 0) / (tx.weight / 4)) }; }).sort((a, b) => a.rate - b.rate);
|
const sortedTxs = transactions.map(tx => { return { txid: tx.txid, weight: tx.weight, rate: tx.effectiveFeePerVsize || ((tx.fee || 0) / (tx.weight / 4)) }; }).sort((a, b) => a.rate - b.rate);
|
||||||
|
|
||||||
@ -898,8 +907,8 @@ export class Common {
|
|||||||
);
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
medianFee: medianFeeRate,
|
effective_median: medianFeeRate,
|
||||||
feeRange: [
|
effective_range: [
|
||||||
minFee,
|
minFee,
|
||||||
[10,25,50,75,90].map(n => Common.getNthPercentile(n, sortedTxs).rate),
|
[10,25,50,75,90].map(n => Common.getNthPercentile(n, sortedTxs).rate),
|
||||||
maxFee,
|
maxFee,
|
||||||
@ -1150,16 +1159,16 @@ export class OnlineFeeStatsCalculator {
|
|||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
minFee: this.feeRange[0].min,
|
minFee: this.feeRange[0].min,
|
||||||
medianFee: this.feeRange[Math.floor(this.feeRange.length / 2)].avg,
|
effective_median: this.feeRange[Math.floor(this.feeRange.length / 2)].avg,
|
||||||
maxFee: this.feeRange[this.feeRange.length - 1].max,
|
maxFee: this.feeRange[this.feeRange.length - 1].max,
|
||||||
feeRange: this.feeRange.map(f => f.avg),
|
effective_range: this.feeRange.map(f => f.avg),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
getFeeStats(): EffectiveFeeStats {
|
getFeeStats(): EffectiveFeeStats {
|
||||||
const stats = this.getRawFeeStats();
|
const stats = this.getRawFeeStats();
|
||||||
stats.feeRange[0] = stats.minFee;
|
stats.effective_range[0] = stats.minFee;
|
||||||
stats.feeRange[stats.feeRange.length - 1] = stats.maxFee;
|
stats.effective_range[stats.effective_range.length - 1] = stats.maxFee;
|
||||||
return stats;
|
return stats;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@ import cpfpRepository from '../repositories/CpfpRepository';
|
|||||||
import { RowDataPacket } from 'mysql2';
|
import { RowDataPacket } from 'mysql2';
|
||||||
|
|
||||||
class DatabaseMigration {
|
class DatabaseMigration {
|
||||||
private static currentVersion = 94;
|
private static currentVersion = 95;
|
||||||
private queryTimeout = 3600_000;
|
private queryTimeout = 3600_000;
|
||||||
private statisticsAddedIndexed = false;
|
private statisticsAddedIndexed = false;
|
||||||
private uniqueLogs: string[] = [];
|
private uniqueLogs: string[] = [];
|
||||||
@ -1118,6 +1118,16 @@ class DatabaseMigration {
|
|||||||
}
|
}
|
||||||
await this.updateToSchemaVersion(94);
|
await this.updateToSchemaVersion(94);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (databaseSchemaVersion < 95) {
|
||||||
|
// Version 95
|
||||||
|
await this.$executeQuery(`
|
||||||
|
ALTER TABLE \`blocks\`
|
||||||
|
ADD \`effective_median_fee\` BIGINT UNSIGNED NOT NULL DEFAULT 0,
|
||||||
|
ADD \`effective_fee_span\` JSON DEFAULT NULL;
|
||||||
|
`);
|
||||||
|
await this.updateToSchemaVersion(95);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -63,7 +63,8 @@ class FeeApi {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private optimizeMedianFee(pBlock: MempoolBlock, nextBlock: MempoolBlock | undefined, previousFee?: number): number {
|
private optimizeMedianFee(pBlock: MempoolBlock, nextBlock: MempoolBlock | undefined, previousFee?: number): number {
|
||||||
const useFee = previousFee ? (pBlock.medianFee + previousFee) / 2 : pBlock.medianFee;
|
const medianFee = pBlock.effectiveMedianFee ?? pBlock.medianFee;
|
||||||
|
const useFee = previousFee ? (medianFee + previousFee) / 2 : medianFee;
|
||||||
if (pBlock.blockVSize <= 500000) {
|
if (pBlock.blockVSize <= 500000) {
|
||||||
return this.defaultFee;
|
return this.defaultFee;
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { GbtGenerator, GbtResult, ThreadTransaction as RustThreadTransaction, ThreadAcceleration as RustThreadAcceleration } from 'rust-gbt';
|
import { GbtGenerator, GbtResult, ThreadTransaction as RustThreadTransaction, ThreadAcceleration as RustThreadAcceleration } from 'rust-gbt';
|
||||||
import logger from '../logger';
|
import logger from '../logger';
|
||||||
import { MempoolBlock, MempoolTransactionExtended, MempoolBlockWithTransactions, MempoolBlockDelta, Ancestor, CompactThreadTransaction, EffectiveFeeStats, TransactionClassified, TransactionCompressed, MempoolDeltaChange, GbtCandidates, PoolTag } from '../mempool.interfaces';
|
import { MempoolBlock, MempoolTransactionExtended, MempoolBlockWithTransactions, MempoolBlockDelta, Ancestor, CompactThreadTransaction, FeeStats, TransactionClassified, TransactionCompressed, MempoolDeltaChange, GbtCandidates, PoolTag, EffectiveFeeStats } from '../mempool.interfaces';
|
||||||
import { Common, OnlineFeeStatsCalculator } from './common';
|
import { Common, OnlineFeeStatsCalculator } from './common';
|
||||||
import config from '../config';
|
import config from '../config';
|
||||||
import { Worker } from 'worker_threads';
|
import { Worker } from 'worker_threads';
|
||||||
@ -33,6 +33,8 @@ class MempoolBlocks {
|
|||||||
totalFees: block.totalFees,
|
totalFees: block.totalFees,
|
||||||
medianFee: block.medianFee,
|
medianFee: block.medianFee,
|
||||||
feeRange: block.feeRange,
|
feeRange: block.feeRange,
|
||||||
|
effectiveMedianFee: block.effectiveMedianFee,
|
||||||
|
effectiveFeeRange: block.effectiveFeeRange,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -527,7 +529,7 @@ class MempoolBlocks {
|
|||||||
totalSize,
|
totalSize,
|
||||||
totalWeight,
|
totalWeight,
|
||||||
totalFees,
|
totalFees,
|
||||||
(hasBlockStack && blockIndex === lastBlockIndex && feeStatsCalculator) ? feeStatsCalculator.getRawFeeStats() : undefined,
|
(hasBlockStack && blockIndex === lastBlockIndex && feeStatsCalculator) ? feeStatsCalculator.getFeeStats() : undefined,
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -541,17 +543,20 @@ class MempoolBlocks {
|
|||||||
return mempoolBlocks;
|
return mempoolBlocks;
|
||||||
}
|
}
|
||||||
|
|
||||||
private dataToMempoolBlocks(transactionIds: string[], transactions: MempoolTransactionExtended[], totalSize: number, totalWeight: number, totalFees: number, feeStats?: EffectiveFeeStats ): MempoolBlockWithTransactions {
|
private dataToMempoolBlocks(transactionIds: string[], transactions: MempoolTransactionExtended[], totalSize: number, totalWeight: number, totalFees: number, effectiveFeeStats?: EffectiveFeeStats ): MempoolBlockWithTransactions {
|
||||||
if (!feeStats) {
|
const feeStats = Common.calcFeeStatistics(transactions);
|
||||||
feeStats = Common.calcEffectiveFeeStatistics(transactions);
|
if (!effectiveFeeStats) {
|
||||||
|
effectiveFeeStats = Common.calcEffectiveFeeStatistics(transactions);
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
blockSize: totalSize,
|
blockSize: totalSize,
|
||||||
blockVSize: (totalWeight / 4), // fractional vsize to avoid rounding errors
|
blockVSize: (totalWeight / 4), // fractional vsize to avoid rounding errors
|
||||||
nTx: transactionIds.length,
|
nTx: transactionIds.length,
|
||||||
totalFees: totalFees,
|
totalFees: totalFees,
|
||||||
medianFee: feeStats.medianFee, // Common.percentile(transactions.map((tx) => tx.effectiveFeePerVsize), config.MEMPOOL.RECOMMENDED_FEE_PERCENTILE),
|
medianFee: feeStats.median,
|
||||||
feeRange: feeStats.feeRange, //Common.getFeesInRange(transactions, rangeLength),
|
feeRange: feeStats.range,
|
||||||
|
effectiveMedianFee: effectiveFeeStats.effective_median,
|
||||||
|
effectiveFeeRange: effectiveFeeStats.effective_range,
|
||||||
transactionIds: transactionIds,
|
transactionIds: transactionIds,
|
||||||
transactions: transactions.map((tx) => Common.classifyTransaction(tx)),
|
transactions: transactions.map((tx) => Common.classifyTransaction(tx)),
|
||||||
};
|
};
|
||||||
|
@ -73,6 +73,8 @@ export interface MempoolBlock {
|
|||||||
medianFee: number;
|
medianFee: number;
|
||||||
totalFees: number;
|
totalFees: number;
|
||||||
feeRange: number[];
|
feeRange: number[];
|
||||||
|
effectiveMedianFee?: number;
|
||||||
|
effectiveFeeRange?: number[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface MempoolBlockWithTransactions extends MempoolBlock {
|
export interface MempoolBlockWithTransactions extends MempoolBlock {
|
||||||
@ -288,8 +290,10 @@ export const TransactionFlags = {
|
|||||||
|
|
||||||
export interface BlockExtension {
|
export interface BlockExtension {
|
||||||
totalFees: number;
|
totalFees: number;
|
||||||
medianFee: number; // median fee rate
|
medianFee: number; // core median fee rate
|
||||||
feeRange: number[]; // fee rate percentiles
|
feeRange: number[]; // core fee rate percentiles
|
||||||
|
effectiveMedianFee?: number; // effective median fee rate
|
||||||
|
effectiveFeeRange?: number[]; // effective fee rate percentiles
|
||||||
reward: number;
|
reward: number;
|
||||||
matchRate: number | null;
|
matchRate: number | null;
|
||||||
expectedFees: number | null;
|
expectedFees: number | null;
|
||||||
@ -369,9 +373,18 @@ export interface MempoolStats {
|
|||||||
tx_count: number;
|
tx_count: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Core fee stats
|
||||||
|
// measured in individual sats/vbyte
|
||||||
|
export interface FeeStats {
|
||||||
|
median: number; // median core fee rate
|
||||||
|
range: number[]; // 0th, 10th, 25th, 50th, 75th, 90th, 100th percentiles
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mempool effective fee stats
|
||||||
|
// measured in effective sats/vbyte
|
||||||
export interface EffectiveFeeStats {
|
export interface EffectiveFeeStats {
|
||||||
medianFee: number; // median effective fee rate
|
effective_median: number; // median effective fee rate by weight
|
||||||
feeRange: number[]; // 2nd, 10th, 25th, 50th, 75th, 90th, 98th percentiles
|
effective_range: number[]; // 2nd, 10th, 25th, 50th, 75th, 90th, 98th percentiles
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface WorkingEffectiveFeeStats extends EffectiveFeeStats {
|
export interface WorkingEffectiveFeeStats extends EffectiveFeeStats {
|
||||||
|
@ -315,12 +315,12 @@ class AccelerationRepository {
|
|||||||
Infinity
|
Infinity
|
||||||
);
|
);
|
||||||
const feeStats = Common.calcEffectiveFeeStatistics(template);
|
const feeStats = Common.calcEffectiveFeeStatistics(template);
|
||||||
boostRate = feeStats.medianFee;
|
boostRate = feeStats.effective_median;
|
||||||
}
|
}
|
||||||
const accelerationSummaries = accelerations.map(acc => ({
|
const accelerationSummaries = accelerations.map(acc => ({
|
||||||
...acc,
|
...acc,
|
||||||
pools: acc.pools,
|
pools: acc.pools,
|
||||||
}))
|
}));
|
||||||
for (const acc of accelerations) {
|
for (const acc of accelerations) {
|
||||||
if (blockTxs[acc.txid] && acc.pools.includes(block.extras.pool.id)) {
|
if (blockTxs[acc.txid] && acc.pools.includes(block.extras.pool.id)) {
|
||||||
const tx = blockTxs[acc.txid];
|
const tx = blockTxs[acc.txid];
|
||||||
|
@ -33,6 +33,8 @@ interface DatabaseBlock {
|
|||||||
totalFees: number;
|
totalFees: number;
|
||||||
medianFee: number;
|
medianFee: number;
|
||||||
feeRange: string;
|
feeRange: string;
|
||||||
|
effectiveMedianFee?: number;
|
||||||
|
effectiveFeeRange?: string;
|
||||||
reward: number;
|
reward: number;
|
||||||
poolId: number;
|
poolId: number;
|
||||||
poolName: string;
|
poolName: string;
|
||||||
@ -77,6 +79,8 @@ const BLOCK_DB_FIELDS = `
|
|||||||
blocks.fees AS totalFees,
|
blocks.fees AS totalFees,
|
||||||
blocks.median_fee AS medianFee,
|
blocks.median_fee AS medianFee,
|
||||||
blocks.fee_span AS feeRange,
|
blocks.fee_span AS feeRange,
|
||||||
|
blocks.effective_median_fee AS effectiveMedianFee,
|
||||||
|
blocks.effective_fee_span AS effectiveFeeRange,
|
||||||
blocks.reward,
|
blocks.reward,
|
||||||
pools.unique_id AS poolId,
|
pools.unique_id AS poolId,
|
||||||
pools.name AS poolName,
|
pools.name AS poolName,
|
||||||
@ -108,7 +112,7 @@ class BlocksRepository {
|
|||||||
/**
|
/**
|
||||||
* Save indexed block data in the database
|
* Save indexed block data in the database
|
||||||
*/
|
*/
|
||||||
public async $saveBlockInDatabase(block: BlockExtended) {
|
public async $saveBlockInDatabase(block: BlockExtended): Promise<void> {
|
||||||
const truncatedCoinbaseSignature = block?.extras?.coinbaseSignature?.substring(0, 500);
|
const truncatedCoinbaseSignature = block?.extras?.coinbaseSignature?.substring(0, 500);
|
||||||
const truncatedCoinbaseSignatureAscii = block?.extras?.coinbaseSignatureAscii?.substring(0, 500);
|
const truncatedCoinbaseSignatureAscii = block?.extras?.coinbaseSignatureAscii?.substring(0, 500);
|
||||||
|
|
||||||
@ -117,6 +121,7 @@ class BlocksRepository {
|
|||||||
height, hash, blockTimestamp, size,
|
height, hash, blockTimestamp, size,
|
||||||
weight, tx_count, coinbase_raw, difficulty,
|
weight, tx_count, coinbase_raw, difficulty,
|
||||||
pool_id, fees, fee_span, median_fee,
|
pool_id, fees, fee_span, median_fee,
|
||||||
|
effective_fee_span, effective_median_fee,
|
||||||
reward, version, bits, nonce,
|
reward, version, bits, nonce,
|
||||||
merkle_root, previous_block_hash, avg_fee, avg_fee_rate,
|
merkle_root, previous_block_hash, avg_fee, avg_fee_rate,
|
||||||
median_timestamp, header, coinbase_address, coinbase_addresses,
|
median_timestamp, header, coinbase_address, coinbase_addresses,
|
||||||
@ -128,6 +133,7 @@ class BlocksRepository {
|
|||||||
?, ?, FROM_UNIXTIME(?), ?,
|
?, ?, FROM_UNIXTIME(?), ?,
|
||||||
?, ?, ?, ?,
|
?, ?, ?, ?,
|
||||||
?, ?, ?, ?,
|
?, ?, ?, ?,
|
||||||
|
?, ?,
|
||||||
?, ?, ?, ?,
|
?, ?, ?, ?,
|
||||||
?, ?, ?, ?,
|
?, ?, ?, ?,
|
||||||
FROM_UNIXTIME(?), ?, ?, ?,
|
FROM_UNIXTIME(?), ?, ?, ?,
|
||||||
@ -155,6 +161,8 @@ class BlocksRepository {
|
|||||||
block.extras.totalFees,
|
block.extras.totalFees,
|
||||||
JSON.stringify(block.extras.feeRange),
|
JSON.stringify(block.extras.feeRange),
|
||||||
block.extras.medianFee,
|
block.extras.medianFee,
|
||||||
|
block.extras.effectiveFeeRange ? JSON.stringify(block.extras.effectiveFeeRange) : null,
|
||||||
|
block.extras.effectiveMedianFee,
|
||||||
block.extras.reward,
|
block.extras.reward,
|
||||||
block.version,
|
block.version,
|
||||||
block.bits,
|
block.bits,
|
||||||
@ -968,16 +976,16 @@ class BlocksRepository {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Save indexed effective fee statistics
|
* Save indexed effective fee statistics
|
||||||
*
|
*
|
||||||
* @param id
|
* @param id
|
||||||
* @param feeStats
|
* @param feeStats
|
||||||
*/
|
*/
|
||||||
public async $saveEffectiveFeeStats(id: string, feeStats: EffectiveFeeStats): Promise<void> {
|
public async $saveEffectiveFeeStats(id: string, feeStats: EffectiveFeeStats): Promise<void> {
|
||||||
try {
|
try {
|
||||||
await DB.query(`
|
await DB.query(`
|
||||||
UPDATE blocks SET median_fee = ?, fee_span = ?
|
UPDATE blocks SET effective_median_fee = ?, effective_fee_span = ?
|
||||||
WHERE hash = ?`,
|
WHERE hash = ?`,
|
||||||
[feeStats.medianFee, JSON.stringify(feeStats.feeRange), id]
|
[feeStats.effective_median, JSON.stringify(feeStats.effective_range), id]
|
||||||
);
|
);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
logger.err(`Cannot update block fee stats. Reason: ` + (e instanceof Error ? e.message : e));
|
logger.err(`Cannot update block fee stats. Reason: ` + (e instanceof Error ? e.message : e));
|
||||||
@ -1065,11 +1073,13 @@ class BlocksRepository {
|
|||||||
blk.weight = dbBlk.weight;
|
blk.weight = dbBlk.weight;
|
||||||
blk.previousblockhash = dbBlk.previousblockhash;
|
blk.previousblockhash = dbBlk.previousblockhash;
|
||||||
blk.mediantime = dbBlk.mediantime;
|
blk.mediantime = dbBlk.mediantime;
|
||||||
|
|
||||||
// BlockExtension
|
// BlockExtension
|
||||||
extras.totalFees = dbBlk.totalFees;
|
extras.totalFees = dbBlk.totalFees;
|
||||||
extras.medianFee = dbBlk.medianFee;
|
extras.medianFee = dbBlk.medianFee;
|
||||||
extras.feeRange = JSON.parse(dbBlk.feeRange);
|
extras.feeRange = JSON.parse(dbBlk.feeRange);
|
||||||
|
extras.effectiveMedianFee = dbBlk.effectiveMedianFee;
|
||||||
|
extras.effectiveFeeRange = dbBlk.effectiveFeeRange ? JSON.parse(dbBlk.effectiveFeeRange) : null;
|
||||||
extras.reward = dbBlk.reward;
|
extras.reward = dbBlk.reward;
|
||||||
extras.pool = {
|
extras.pool = {
|
||||||
id: dbBlk.poolId,
|
id: dbBlk.poolId,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user