diff --git a/backend/src/api/mining/mining-routes.ts b/backend/src/api/mining/mining-routes.ts
index b6ce3ba70..bdfc83d43 100644
--- a/backend/src/api/mining/mining-routes.ts
+++ b/backend/src/api/mining/mining-routes.ts
@@ -227,10 +227,8 @@ class MiningRoutes {
throw new Error('from must be less than to');
}
const blockFees = await mining.$getBlockFeesTimespan(parseInt(req.query.from as string, 10), parseInt(req.query.to as string, 10));
- const blockCount = await BlocksRepository.$blockCount(null, null);
res.header('Pragma', 'public');
res.header('Cache-control', 'public');
- res.header('X-total-count', blockCount.toString());
res.setHeader('Expires', new Date(Date.now() + 1000 * 60).toUTCString());
res.json(blockFees);
} catch (e) {
diff --git a/frontend/src/app/components/block-fees-subsidy-graph/block-fees-subsidy-graph.component.ts b/frontend/src/app/components/block-fees-subsidy-graph/block-fees-subsidy-graph.component.ts
index 3fd7c5f46..a6fca2469 100644
--- a/frontend/src/app/components/block-fees-subsidy-graph/block-fees-subsidy-graph.component.ts
+++ b/frontend/src/app/components/block-fees-subsidy-graph/block-fees-subsidy-graph.component.ts
@@ -48,7 +48,7 @@ export class BlockFeesSubsidyGraphComponent implements OnInit {
formatNumber = formatNumber;
timespan = '';
chartInstance: any = undefined;
- showFiat = false;
+ displayMode: 'normal' | 'fiat' | 'percentage' = 'normal';
updateZoom = false;
zoomSpan = 100;
zoomTimeSpan = '';
@@ -106,8 +106,10 @@ export class BlockFeesSubsidyGraphComponent implements OnInit {
blockHeight: response.body.map(val => val.avgHeight),
blockFees: response.body.map(val => val.avgFees / 100_000_000),
blockFeesFiat: response.body.filter(val => val['USD'] > 0).map(val => val.avgFees / 100_000_000 * val['USD']),
- blockSubsidy: response.body.map(val => this.subsidies[Math.floor(Math.min(val.avgHeight / 210000, 33))] / 100_000_000),
- blockSubsidyFiat: response.body.filter(val => val['USD'] > 0).map(val => this.subsidies[Math.floor(Math.min(val.avgHeight / 210000, 33))] / 100_000_000 * val['USD']),
+ blockFeesPercent: response.body.map(val => val.avgFees / (val.avgFees + this.subsidyAt(val.avgHeight)) * 100),
+ blockSubsidy: response.body.map(val => this.subsidyAt(val.avgHeight) / 100_000_000),
+ blockSubsidyFiat: response.body.filter(val => val['USD'] > 0).map(val => this.subsidyAt(val.avgHeight) / 100_000_000 * val['USD']),
+ blockSubsidyPercent: response.body.map(val => this.subsidyAt(val.avgHeight) / (val.avgFees + this.subsidyAt(val.avgHeight)) * 100),
};
this.prepareChartOptions();
@@ -157,9 +159,9 @@ export class BlockFeesSubsidyGraphComponent implements OnInit {
axisPointer: {
type: 'line'
},
- backgroundColor: 'color-mix(in srgb, var(--active-bg) 95%, transparent)',
+ backgroundColor: 'rgba(17, 19, 31, 1)',
borderRadius: 4,
- shadowColor: 'color-mix(in srgb, var(--active-bg) 95%, transparent)',
+ shadowColor: 'rgba(0, 0, 0, 0.5)',
textStyle: {
color: 'var(--tooltip-grey)',
align: 'left',
@@ -172,11 +174,13 @@ export class BlockFeesSubsidyGraphComponent implements OnInit {
let tooltip = `${formatterXAxis(this.locale, this.zoomTimeSpan, parseInt(this.data.timestamp[data[0].dataIndex], 10))}
`;
for (let i = data.length - 1; i >= 0; i--) {
const tick = data[i];
- if (!this.showFiat) tooltip += `${tick.marker} ${tick.seriesName}: ${formatNumber(tick.data, this.locale, '1.0-3')} BTC
`;
- else tooltip += `${tick.marker} ${tick.seriesName}: ${this.fiatCurrencyPipe.transform(tick.data, null, 'USD') }
`;
+ tooltip += `${tick.marker} ${tick.seriesName.split(' ')[0]}: `;
+ if (this.displayMode === 'normal') tooltip += `${formatNumber(tick.data, this.locale, '1.0-3')} BTC
`;
+ else if (this.displayMode === 'fiat') tooltip += `${this.fiatCurrencyPipe.transform(tick.data, null, 'USD') }
`;
+ else tooltip += `${formatNumber(tick.data, this.locale, '1.0-2')}%
`;
}
- if (!this.showFiat) tooltip += `
${formatNumber(data.reduce((acc, val) => acc + val.data, 0), this.locale, '1.0-3')} BTC
`;
- else tooltip += `${this.fiatCurrencyPipe.transform(data.reduce((acc, val) => acc + val.data, 0), null, 'USD')}
`;
+ if (this.displayMode === 'normal') tooltip += `${formatNumber(data.reduce((acc, val) => acc + val.data, 0), this.locale, '1.0-3')} BTC
`;
+ else if (this.displayMode === 'fiat') tooltip += `${this.fiatCurrencyPipe.transform(data.reduce((acc, val) => acc + val.data, 0), null, 'USD')}
`;
if (['24h', '3d'].includes(this.zoomTimeSpan)) {
tooltip += `` + $localize`At block ${data[0].axisValue}` + ``;
} else {
@@ -250,12 +254,30 @@ export class BlockFeesSubsidyGraphComponent implements OnInit {
},
icon: 'roundRect',
},
+ {
+ name: 'Subsidy (%)',
+ inactiveColor: 'var(--grey)',
+ textStyle: {
+ color: 'white',
+ },
+ icon: 'roundRect',
+ },
+ {
+ name: 'Fees (%)',
+ inactiveColor: 'var(--grey)',
+ textStyle: {
+ color: 'white',
+ },
+ icon: 'roundRect',
+ },
],
selected: {
- 'Subsidy (USD)': this.showFiat,
- 'Fees (USD)': this.showFiat,
- 'Subsidy': !this.showFiat,
- 'Fees': !this.showFiat,
+ 'Subsidy (USD)': this.displayMode === 'fiat',
+ 'Fees (USD)': this.displayMode === 'fiat',
+ 'Subsidy': this.displayMode === 'normal',
+ 'Fees': this.displayMode === 'normal',
+ 'Subsidy (%)': this.displayMode === 'percentage',
+ 'Fees (%)': this.displayMode === 'percentage',
},
},
yAxis: this.data.blockFees.length === 0 ? undefined : [
@@ -264,10 +286,15 @@ export class BlockFeesSubsidyGraphComponent implements OnInit {
axisLabel: {
color: 'var(--grey)',
formatter: (val) => {
- return `${val} BTC`;
+ return `${val}${this.displayMode === 'percentage' ? '%' : ' BTC'}`;
}
},
min: 0,
+ max: (value) => {
+ if (this.displayMode === 'percentage') {
+ return 100;
+ }
+ },
splitLine: {
lineStyle: {
type: 'dotted',
@@ -295,6 +322,7 @@ export class BlockFeesSubsidyGraphComponent implements OnInit {
name: 'Subsidy',
yAxisIndex: 0,
type: 'bar',
+ barWidth: '90%',
stack: 'total',
data: this.data.blockSubsidy,
},
@@ -302,6 +330,7 @@ export class BlockFeesSubsidyGraphComponent implements OnInit {
name: 'Fees',
yAxisIndex: 0,
type: 'bar',
+ barWidth: '90%',
stack: 'total',
data: this.data.blockFees,
},
@@ -309,6 +338,7 @@ export class BlockFeesSubsidyGraphComponent implements OnInit {
name: 'Subsidy (USD)',
yAxisIndex: 1,
type: 'bar',
+ barWidth: '90%',
stack: 'total',
data: this.data.blockSubsidyFiat,
},
@@ -316,9 +346,26 @@ export class BlockFeesSubsidyGraphComponent implements OnInit {
name: 'Fees (USD)',
yAxisIndex: 1,
type: 'bar',
+ barWidth: '90%',
stack: 'total',
data: this.data.blockFeesFiat,
},
+ {
+ name: 'Subsidy (%)',
+ yAxisIndex: 0,
+ type: 'bar',
+ barWidth: '90%',
+ stack: 'total',
+ data: this.data.blockSubsidyPercent,
+ },
+ {
+ name: 'Fees (%)',
+ yAxisIndex: 0,
+ type: 'bar',
+ barWidth: '90%',
+ stack: 'total',
+ data: this.data.blockFeesPercent,
+ },
],
dataZoom: this.data.blockFees.length === 0 ? undefined : [{
type: 'inside',
@@ -349,22 +396,31 @@ export class BlockFeesSubsidyGraphComponent implements OnInit {
this.chartInstance = ec;
this.chartInstance.on('legendselectchanged', (params) => {
- const isFiat = params.name.includes('USD');
- if (isFiat === this.showFiat) return;
+ if (this.isLoading) {
+ return;
+ }
+
+ let mode: 'normal' | 'fiat' | 'percentage';
+ if (params.name.includes('USD')) {
+ mode = 'fiat';
+ } else if (params.name.includes('%')) {
+ mode = 'percentage';
+ } else {
+ mode = 'normal';
+ }
+
+ if (this.displayMode === mode) return;
const isActivation = params.selected[params.name];
- if (isFiat === isActivation) {
- this.showFiat = true;
- this.chartInstance.dispatchAction({ type: 'legendUnSelect', name: 'Subsidy' });
- this.chartInstance.dispatchAction({ type: 'legendUnSelect', name: 'Fees' });
- this.chartInstance.dispatchAction({ type: 'legendSelect', name: 'Subsidy (USD)' });
- this.chartInstance.dispatchAction({ type: 'legendSelect', name: 'Fees (USD)' });
- } else {
- this.showFiat = false;
- this.chartInstance.dispatchAction({ type: 'legendSelect', name: 'Subsidy' });
- this.chartInstance.dispatchAction({ type: 'legendSelect', name: 'Fees' });
- this.chartInstance.dispatchAction({ type: 'legendUnSelect', name: 'Subsidy (USD)' });
- this.chartInstance.dispatchAction({ type: 'legendUnSelect', name: 'Fees (USD)' });
+
+ if (isActivation) {
+ this.displayMode = mode;
+ this.chartInstance.dispatchAction({ type: this.displayMode === 'normal' ? 'legendSelect' : 'legendUnSelect', name: 'Subsidy' });
+ this.chartInstance.dispatchAction({ type: this.displayMode === 'normal' ? 'legendSelect' : 'legendUnSelect', name: 'Fees' });
+ this.chartInstance.dispatchAction({ type: this.displayMode === 'fiat' ? 'legendSelect' : 'legendUnSelect', name: 'Subsidy (USD)' });
+ this.chartInstance.dispatchAction({ type: this.displayMode === 'fiat' ? 'legendSelect' : 'legendUnSelect', name: 'Fees (USD)' });
+ this.chartInstance.dispatchAction({ type: this.displayMode === 'percentage' ? 'legendSelect' : 'legendUnSelect', name: 'Subsidy (%)' });
+ this.chartInstance.dispatchAction({ type: this.displayMode === 'percentage' ? 'legendSelect' : 'legendUnSelect', name: 'Fees (%)' });
}
});
@@ -411,6 +467,10 @@ export class BlockFeesSubsidyGraphComponent implements OnInit {
return subsidies;
}
+ subsidyAt(height: number): number {
+ return this.subsidies[Math.floor(Math.min(height / 210000, 33))];
+ }
+
onZoom() {
const option = this.chartInstance.getOption();
const timestamps = option.xAxis[1].data;
@@ -432,12 +492,16 @@ export class BlockFeesSubsidyGraphComponent implements OnInit {
this.data.blockHeight.splice(startIndex, endIndex - startIndex, ...response.body.map(val => val.avgHeight));
this.data.blockFees.splice(startIndex, endIndex - startIndex, ...response.body.map(val => val.avgFees / 100_000_000));
this.data.blockFeesFiat.splice(startIndex, endIndex - startIndex, ...response.body.filter(val => val['USD'] > 0).map(val => val.avgFees / 100_000_000 * val['USD']));
- this.data.blockSubsidy.splice(startIndex, endIndex - startIndex, ...response.body.map(val => this.subsidies[Math.floor(Math.min(val.avgHeight / 210000, 33))] / 100_000_000));
- this.data.blockSubsidyFiat.splice(startIndex, endIndex - startIndex, ...response.body.filter(val => val['USD'] > 0).map(val => this.subsidies[Math.floor(Math.min(val.avgHeight / 210000, 33))] / 100_000_000 * val['USD']));
+ this.data.blockFeesPercent.splice(startIndex, endIndex - startIndex, ...response.body.map(val => val.avgFees / (val.avgFees + this.subsidyAt(val.avgHeight)) * 100));
+ this.data.blockSubsidy.splice(startIndex, endIndex - startIndex, ...response.body.map(val => this.subsidyAt(val.avgHeight) / 100_000_000));
+ this.data.blockSubsidyFiat.splice(startIndex, endIndex - startIndex, ...response.body.filter(val => val['USD'] > 0).map(val => this.subsidyAt(val.avgHeight) / 100_000_000 * val['USD']));
+ this.data.blockSubsidyPercent.splice(startIndex, endIndex - startIndex, ...response.body.map(val => this.subsidyAt(val.avgHeight) / (val.avgFees + this.subsidyAt(val.avgHeight)) * 100));
option.series[0].data = this.data.blockSubsidy;
option.series[1].data = this.data.blockFees;
option.series[2].data = this.data.blockSubsidyFiat;
option.series[3].data = this.data.blockFeesFiat;
+ option.series[4].data = this.data.blockSubsidyPercent;
+ option.series[5].data = this.data.blockFeesPercent;
option.xAxis[0].data = this.data.blockHeight;
option.xAxis[1].data = this.data.timestamp;
this.chartInstance.setOption(option, true);