Merge hashrate and difficulty into one chart
This commit is contained in:
parent
98e0e1e9c1
commit
83a382a0cb
@ -42,9 +42,7 @@ class Mining {
|
||||
});
|
||||
|
||||
poolsStatistics['pools'] = poolsStats;
|
||||
|
||||
const oldestBlock = new Date(await BlocksRepository.$oldestBlockTimestamp());
|
||||
poolsStatistics['oldestIndexedBlockTimestamp'] = oldestBlock.getTime();
|
||||
poolsStatistics['oldestIndexedBlockTimestamp'] = await BlocksRepository.$oldestBlockTimestamp();
|
||||
|
||||
const blockCount: number = await BlocksRepository.$blockCount(null, interval);
|
||||
poolsStatistics['blockCount'] = blockCount;
|
||||
@ -79,26 +77,14 @@ class Mining {
|
||||
* Return the historical difficulty adjustments and oldest indexed block timestamp
|
||||
*/
|
||||
public async $getHistoricalDifficulty(interval: string | null): Promise<object> {
|
||||
const difficultyAdjustments = await BlocksRepository.$getBlocksDifficulty(interval);
|
||||
const oldestBlock = new Date(await BlocksRepository.$oldestBlockTimestamp());
|
||||
|
||||
return {
|
||||
adjustments: difficultyAdjustments,
|
||||
oldestIndexedBlockTimestamp: oldestBlock.getTime(),
|
||||
};
|
||||
return await BlocksRepository.$getBlocksDifficulty(interval);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the historical hashrates and oldest indexed block timestamp
|
||||
*/
|
||||
public async $getHistoricalHashrates(interval: string | null): Promise<object> {
|
||||
const hashrates = await HashratesRepository.$get(interval);
|
||||
const oldestBlock = new Date(await BlocksRepository.$oldestBlockTimestamp());
|
||||
|
||||
return {
|
||||
hashrates: hashrates,
|
||||
oldestIndexedBlockTimestamp: oldestBlock.getTime(),
|
||||
};
|
||||
return await HashratesRepository.$get(interval);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -187,12 +187,11 @@ class BlocksRepository {
|
||||
* Get the oldest indexed block
|
||||
*/
|
||||
public async $oldestBlockTimestamp(): Promise<number> {
|
||||
const query = `SELECT blockTimestamp
|
||||
const query = `SELECT UNIX_TIMESTAMP(blockTimestamp) as blockTimestamp
|
||||
FROM blocks
|
||||
ORDER BY height
|
||||
LIMIT 1;`;
|
||||
|
||||
|
||||
// logger.debug(query);
|
||||
const connection = await DB.pool.getConnection();
|
||||
const [rows]: any[] = await connection.query(query);
|
||||
|
@ -588,11 +588,18 @@ class Routes {
|
||||
|
||||
public async $getHistoricalHashrate(req: Request, res: Response) {
|
||||
try {
|
||||
const stats = await mining.$getHistoricalHashrates(req.params.interval ?? null);
|
||||
const hashrates = await mining.$getHistoricalHashrates(req.params.interval ?? null);
|
||||
const difficulty = await mining.$getHistoricalDifficulty(req.params.interval ?? null);
|
||||
const oldestIndexedBlockTimestamp = await BlocksRepository.$oldestBlockTimestamp();
|
||||
console.log(oldestIndexedBlockTimestamp);
|
||||
res.header('Pragma', 'public');
|
||||
res.header('Cache-control', 'public');
|
||||
res.setHeader('Expires', new Date(Date.now() + 1000 * 300).toUTCString());
|
||||
res.json(stats);
|
||||
res.json({
|
||||
oldestIndexedBlockTimestamp: oldestIndexedBlockTimestamp,
|
||||
hashrates: hashrates,
|
||||
difficulty: difficulty,
|
||||
});
|
||||
} catch (e) {
|
||||
res.status(500).send(e instanceof Error ? e.message : e);
|
||||
}
|
||||
|
@ -59,7 +59,7 @@ export class DifficultyChartComponent implements OnInit {
|
||||
}),
|
||||
map(data => {
|
||||
const availableTimespanDay = (
|
||||
(new Date().getTime() / 1000) - (data.oldestIndexedBlockTimestamp / 1000)
|
||||
(new Date().getTime() / 1000) - (data.oldestIndexedBlockTimestamp)
|
||||
) / 3600 / 24;
|
||||
|
||||
const tableData = [];
|
||||
|
@ -23,7 +23,7 @@ import { selectPowerOfTen } from 'src/app/bitcoin.utils';
|
||||
})
|
||||
export class HashrateChartComponent implements OnInit {
|
||||
@Input() widget: boolean = false;
|
||||
@Input() right: number | string = 10;
|
||||
@Input() right: number | string = 45;
|
||||
@Input() left: number | string = 75;
|
||||
|
||||
radioGroupForm: FormGroup;
|
||||
@ -45,7 +45,7 @@ export class HashrateChartComponent implements OnInit {
|
||||
private apiService: ApiService,
|
||||
private formBuilder: FormBuilder,
|
||||
) {
|
||||
this.seoService.setTitle($localize`:@@mining.hashrate:hashrate`);
|
||||
this.seoService.setTitle($localize`:@@mining.hashrate-difficulty:Hashrate and Difficulty`);
|
||||
this.radioGroupForm = this.formBuilder.group({ dateSpan: '1y' });
|
||||
this.radioGroupForm.controls.dateSpan.setValue('1y');
|
||||
}
|
||||
@ -57,17 +57,54 @@ export class HashrateChartComponent implements OnInit {
|
||||
switchMap((timespan) => {
|
||||
return this.apiService.getHistoricalHashrate$(timespan)
|
||||
.pipe(
|
||||
tap(data => {
|
||||
this.prepareChartOptions(data.hashrates.map(val => [val.timestamp * 1000, val.avgHashrate]));
|
||||
map((data: any) => {
|
||||
const diffFixed = [];
|
||||
diffFixed.push({
|
||||
timestamp: data.hashrates[0].timestamp,
|
||||
difficulty: data.difficulty[0].difficulty
|
||||
});
|
||||
|
||||
let diffIndex = 1;
|
||||
let hashIndex = 0;
|
||||
|
||||
while (hashIndex < data.hashrates.length) {
|
||||
if (diffIndex >= data.difficulty.length) {
|
||||
while (hashIndex < data.hashrates.length) {
|
||||
diffFixed.push({
|
||||
timestamp: data.hashrates[hashIndex].timestamp,
|
||||
difficulty: data.difficulty[data.difficulty.length - 1].difficulty
|
||||
});
|
||||
++hashIndex;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
while (data.hashrates[hashIndex].timestamp < data.difficulty[diffIndex].timestamp) {
|
||||
diffFixed.push({
|
||||
timestamp: data.hashrates[hashIndex].timestamp,
|
||||
difficulty: data.difficulty[diffIndex - 1].difficulty
|
||||
});
|
||||
++hashIndex;
|
||||
}
|
||||
++diffIndex;
|
||||
}
|
||||
|
||||
data.difficulty = diffFixed;
|
||||
return data;
|
||||
}),
|
||||
tap((data: any) => {
|
||||
this.prepareChartOptions({
|
||||
hashrates: data.hashrates.map(val => [val.timestamp * 1000, val.avgHashrate]),
|
||||
difficulty: data.difficulty.map(val => [val.timestamp * 1000, val.difficulty])
|
||||
});
|
||||
this.isLoading = false;
|
||||
}),
|
||||
map(data => {
|
||||
map((data: any) => {
|
||||
const availableTimespanDay = (
|
||||
(new Date().getTime() / 1000) - (data.oldestIndexedBlockTimestamp / 1000)
|
||||
(new Date().getTime() / 1000) - (data.oldestIndexedBlockTimestamp)
|
||||
) / 3600 / 24;
|
||||
return {
|
||||
availableTimespanDay: availableTimespanDay,
|
||||
data: data.hashrates
|
||||
};
|
||||
}),
|
||||
);
|
||||
@ -78,27 +115,25 @@ export class HashrateChartComponent implements OnInit {
|
||||
|
||||
prepareChartOptions(data) {
|
||||
this.chartOptions = {
|
||||
color: new graphic.LinearGradient(0, 0, 0, 0.65, [
|
||||
{ offset: 0, color: '#F4511E' },
|
||||
{ offset: 0.25, color: '#FB8C00' },
|
||||
{ offset: 0.5, color: '#FFB300' },
|
||||
{ offset: 0.75, color: '#FDD835' },
|
||||
{ offset: 1, color: '#7CB342' }
|
||||
]),
|
||||
color: [
|
||||
new graphic.LinearGradient(0, 0, 0, 0.65, [
|
||||
{ offset: 0, color: '#F4511E' },
|
||||
{ offset: 0.25, color: '#FB8C00' },
|
||||
{ offset: 0.5, color: '#FFB300' },
|
||||
{ offset: 0.75, color: '#FDD835' },
|
||||
{ offset: 1, color: '#7CB342' }
|
||||
]),
|
||||
'#D81B60',
|
||||
],
|
||||
grid: {
|
||||
right: this.right,
|
||||
left: this.left,
|
||||
},
|
||||
title: {
|
||||
text: this.widget ? '' : $localize`:@@mining.hashrate:Hashrate`,
|
||||
left: 'center',
|
||||
textStyle: {
|
||||
color: '#FFF',
|
||||
},
|
||||
},
|
||||
tooltip: {
|
||||
show: true,
|
||||
trigger: 'axis',
|
||||
axisPointer: {
|
||||
type: 'line'
|
||||
},
|
||||
backgroundColor: 'rgba(17, 19, 31, 1)',
|
||||
borderRadius: 4,
|
||||
shadowColor: 'rgba(0, 0, 0, 0.5)',
|
||||
@ -106,44 +141,91 @@ export class HashrateChartComponent implements OnInit {
|
||||
color: '#b1b1b1',
|
||||
},
|
||||
borderColor: '#000',
|
||||
formatter: params => {
|
||||
return `<b style="color: white">${params[0].axisValueLabel}</b><br>
|
||||
${params[0].marker} ${formatNumber(params[0].value[1], this.locale, '1.0-0')} H/s`
|
||||
}
|
||||
},
|
||||
axisPointer: {
|
||||
type: 'line',
|
||||
},
|
||||
xAxis: {
|
||||
type: 'time',
|
||||
splitNumber: this.isMobile() ? 5 : 10,
|
||||
},
|
||||
yAxis: {
|
||||
type: 'value',
|
||||
axisLabel: {
|
||||
formatter: (val) => {
|
||||
const selectedPowerOfTen: any = selectPowerOfTen(val);
|
||||
const newVal = val / selectedPowerOfTen.divider;
|
||||
return `${newVal} ${selectedPowerOfTen.unit}H/s`
|
||||
legend: {
|
||||
data: [
|
||||
{
|
||||
name: 'Hashrate',
|
||||
inactiveColor: 'rgb(110, 112, 121)',
|
||||
textStyle: {
|
||||
color: 'white',
|
||||
},
|
||||
icon: 'roundRect',
|
||||
itemStyle: {
|
||||
color: '#FFB300',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'Difficulty',
|
||||
inactiveColor: 'rgb(110, 112, 121)',
|
||||
textStyle: {
|
||||
color: 'white',
|
||||
},
|
||||
icon: 'roundRect',
|
||||
itemStyle: {
|
||||
color: '#D81B60',
|
||||
}
|
||||
},
|
||||
],
|
||||
},
|
||||
yAxis: [
|
||||
{
|
||||
type: 'value',
|
||||
name: 'Hashrate',
|
||||
axisLabel: {
|
||||
color: 'rgb(110, 112, 121)',
|
||||
formatter: (val) => {
|
||||
const selectedPowerOfTen: any = selectPowerOfTen(val);
|
||||
const newVal = val / selectedPowerOfTen.divider;
|
||||
return `${newVal} ${selectedPowerOfTen.unit}H/s`
|
||||
}
|
||||
},
|
||||
splitLine: {
|
||||
show: false,
|
||||
}
|
||||
},
|
||||
splitLine: {
|
||||
{
|
||||
type: 'value',
|
||||
name: 'Difficulty',
|
||||
position: 'right',
|
||||
axisLabel: {
|
||||
color: 'rgb(110, 112, 121)',
|
||||
formatter: (val) => {
|
||||
const selectedPowerOfTen: any = selectPowerOfTen(val);
|
||||
const newVal = val / selectedPowerOfTen.divider;
|
||||
return `${newVal} ${selectedPowerOfTen.unit}`
|
||||
}
|
||||
},
|
||||
splitLine: {
|
||||
show: false,
|
||||
}
|
||||
}
|
||||
],
|
||||
series: [
|
||||
{
|
||||
name: 'Hashrate',
|
||||
showSymbol: false,
|
||||
data: data.hashrates,
|
||||
type: 'line',
|
||||
lineStyle: {
|
||||
type: 'dotted',
|
||||
color: '#ffffff66',
|
||||
opacity: 0.25,
|
||||
width: 2,
|
||||
},
|
||||
},
|
||||
{
|
||||
yAxisIndex: 1,
|
||||
name: 'Difficulty',
|
||||
showSymbol: false,
|
||||
data: data.difficulty,
|
||||
type: 'line',
|
||||
lineStyle: {
|
||||
width: 3,
|
||||
}
|
||||
},
|
||||
},
|
||||
series: {
|
||||
showSymbol: false,
|
||||
data: data,
|
||||
type: 'line',
|
||||
smooth: false,
|
||||
lineStyle: {
|
||||
width: 2,
|
||||
},
|
||||
},
|
||||
}
|
||||
],
|
||||
dataZoom: this.widget ? null : [{
|
||||
type: 'inside',
|
||||
realtime: true,
|
||||
|
@ -82,7 +82,7 @@ export class MiningService {
|
||||
});
|
||||
|
||||
const availableTimespanDay = (
|
||||
(new Date().getTime() / 1000) - (stats.oldestIndexedBlockTimestamp / 1000)
|
||||
(new Date().getTime() / 1000) - (stats.oldestIndexedBlockTimestamp)
|
||||
) / 3600 / 24;
|
||||
|
||||
return {
|
||||
|
Loading…
x
Reference in New Issue
Block a user