2024-05-14 20:31:25 +02:00
import { ChangeDetectionStrategy , ChangeDetectorRef , Component , HostListener , Inject , Input , LOCALE_ID , NgZone , OnInit } from '@angular/core' ;
2024-10-22 21:05:01 +09:00
import { EChartsOption } from '@app/graphs/echarts' ;
2024-05-03 12:33:05 +02:00
import { Observable } from 'rxjs' ;
2024-05-14 20:31:25 +02:00
import { catchError , map , share , startWith , switchMap , tap } from 'rxjs/operators' ;
2024-10-22 21:05:01 +09:00
import { ApiService } from '@app/services/api.service' ;
import { SeoService } from '@app/services/seo.service' ;
2024-05-03 12:33:05 +02:00
import { formatNumber } from '@angular/common' ;
import { UntypedFormBuilder , UntypedFormGroup } from '@angular/forms' ;
2024-10-22 21:05:01 +09:00
import { download , formatterXAxis } from '@app/shared/graphs.utils' ;
2024-05-14 20:31:25 +02:00
import { ActivatedRoute , Router } from '@angular/router' ;
2024-10-22 21:05:01 +09:00
import { FiatShortenerPipe } from '@app/shared/pipes/fiat-shortener.pipe' ;
import { FiatCurrencyPipe } from '@app/shared/pipes/fiat-currency.pipe' ;
import { StateService } from '@app/services/state.service' ;
import { MiningService } from '@app/services/mining.service' ;
import { StorageService } from '@app/services/storage.service' ;
import { RelativeUrlPipe } from '@app/shared/pipes/relative-url/relative-url.pipe' ;
2024-05-03 12:33:05 +02:00
@Component ( {
selector : 'app-block-fees-subsidy-graph' ,
templateUrl : './block-fees-subsidy-graph.component.html' ,
styleUrls : [ './block-fees-subsidy-graph.component.scss' ] ,
styles : [ `
. loadingGraphs {
position : absolute ;
top : 50 % ;
left : calc ( 50 % - 15 px ) ;
2024-07-26 00:00:14 +02:00
z - index : 99 ;
2024-05-03 12:33:05 +02:00
}
` ],
changeDetection : ChangeDetectionStrategy.OnPush ,
} )
export class BlockFeesSubsidyGraphComponent implements OnInit {
@Input ( ) right : number | string = 45 ;
@Input ( ) left : number | string = 75 ;
2024-05-11 14:36:17 +02:00
miningWindowPreference : string ;
2024-05-03 12:33:05 +02:00
radioGroupForm : UntypedFormGroup ;
chartOptions : EChartsOption = { } ;
chartInitOptions = {
renderer : 'svg' ,
} ;
statsObservable$ : Observable < any > ;
2024-05-14 20:31:25 +02:00
data : any ;
subsidies : { [ key : number ] : number } = { } ;
2024-05-03 12:33:05 +02:00
isLoading = true ;
formatNumber = formatNumber ;
2024-05-11 14:36:17 +02:00
timespan = '' ;
2024-05-03 12:33:05 +02:00
chartInstance : any = undefined ;
2024-05-25 12:32:38 +02:00
displayMode : 'normal' | 'fiat' | 'percentage' = 'normal' ;
2024-05-14 20:31:25 +02:00
updateZoom = false ;
zoomSpan = 100 ;
zoomTimeSpan = '' ;
2024-05-03 12:33:05 +02:00
constructor (
@Inject ( LOCALE_ID ) public locale : string ,
private seoService : SeoService ,
private apiService : ApiService ,
private formBuilder : UntypedFormBuilder ,
public stateService : StateService ,
2024-05-11 14:36:17 +02:00
private storageService : StorageService ,
private miningService : MiningService ,
2024-05-03 12:33:05 +02:00
private route : ActivatedRoute ,
2024-05-14 20:31:25 +02:00
private router : Router ,
private zone : NgZone ,
2024-05-03 12:33:05 +02:00
private fiatShortenerPipe : FiatShortenerPipe ,
private fiatCurrencyPipe : FiatCurrencyPipe ,
2024-05-14 20:31:25 +02:00
private cd : ChangeDetectorRef ,
2024-05-03 12:33:05 +02:00
) {
2024-05-11 14:36:17 +02:00
this . radioGroupForm = this . formBuilder . group ( { dateSpan : '1y' } ) ;
this . radioGroupForm . controls . dateSpan . setValue ( '1y' ) ;
2024-05-14 20:31:25 +02:00
this . subsidies = this . initSubsidies ( ) ;
2024-05-03 12:33:05 +02:00
}
ngOnInit ( ) : void {
2024-07-02 17:05:56 +09:00
this . seoService . setTitle ( $localize ` :@@41545303ec98792b738d6237adbd1f3b54a22196:Block Fees Vs Subsidy ` ) ;
2024-05-03 12:33:05 +02:00
this . seoService . setDescription ( $localize ` :@@meta.description.bitcoin.graphs.block-fees-subsidy:See the mining fees earned per Bitcoin block compared to the Bitcoin block subsidy, visualized in BTC and USD over time. ` ) ;
2024-05-12 18:48:50 +02:00
this . miningWindowPreference = this . miningService . getDefaultTimespan ( '24h' ) ;
2024-05-11 14:36:17 +02:00
this . radioGroupForm = this . formBuilder . group ( { dateSpan : this.miningWindowPreference } ) ;
this . radioGroupForm . controls . dateSpan . setValue ( this . miningWindowPreference ) ;
this . route
. fragment
. subscribe ( ( fragment ) = > {
2024-05-12 18:48:50 +02:00
if ( [ '24h' , '3d' , '1w' , '1m' , '3m' , '6m' , '1y' , '2y' , '3y' , 'all' ] . indexOf ( fragment ) > - 1 ) {
2024-05-11 14:36:17 +02:00
this . radioGroupForm . controls . dateSpan . setValue ( fragment , { emitEvent : false } ) ;
2024-05-03 12:33:05 +02:00
}
} ) ;
2024-05-11 14:36:17 +02:00
this . statsObservable $ = this . radioGroupForm . get ( 'dateSpan' ) . valueChanges
2024-05-03 12:33:05 +02:00
. pipe (
2024-05-11 14:36:17 +02:00
startWith ( this . radioGroupForm . controls . dateSpan . value ) ,
switchMap ( ( timespan ) = > {
2024-05-03 12:33:05 +02:00
this . isLoading = true ;
2024-05-11 14:36:17 +02:00
this . storageService . setValue ( 'miningWindowPreference' , timespan ) ;
this . timespan = timespan ;
2024-05-14 20:31:25 +02:00
this . zoomTimeSpan = timespan ;
2024-05-11 14:36:17 +02:00
return this . apiService . getHistoricalBlockFees $ ( timespan )
2024-05-03 12:33:05 +02:00
. pipe (
tap ( ( response ) = > {
2024-05-14 20:31:25 +02:00
this . data = {
2024-05-11 14:36:17 +02:00
timestamp : response.body.map ( val = > val . timestamp * 1000 ) ,
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' ] ) ,
2024-05-27 16:42:17 +02:00
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 ) ,
2024-05-11 14:36:17 +02:00
} ;
2024-05-14 20:31:25 +02:00
this . prepareChartOptions ( ) ;
2024-05-03 12:33:05 +02:00
this . isLoading = false ;
} ) ,
map ( ( response ) = > {
return {
2024-05-11 14:36:17 +02:00
blockCount : parseInt ( response . headers . get ( 'x-total-count' ) , 10 ) ,
2024-05-03 12:33:05 +02:00
} ;
} ) ,
) ;
} ) ,
share ( )
) ;
}
2024-05-14 20:31:25 +02:00
prepareChartOptions() {
2024-05-03 12:33:05 +02:00
let title : object ;
2024-05-14 20:31:25 +02:00
if ( this . data . blockFees . length === 0 ) {
2024-05-03 12:33:05 +02:00
title = {
textStyle : {
color : 'grey' ,
fontSize : 15
} ,
text : $localize ` :@@23555386d8af1ff73f297e89dd4af3f4689fb9dd:Indexing blocks ` ,
left : 'center' ,
top : 'center'
} ;
}
this . chartOptions = {
title : title ,
color : [
2024-05-12 18:48:50 +02:00
'#ff9f00' ,
'#0aab2f' ,
2024-05-03 12:33:05 +02:00
] ,
animation : false ,
grid : {
top : 80 ,
bottom : 80 ,
right : this.right ,
left : this.left ,
} ,
tooltip : {
show : ! this . isMobile ( ) ,
trigger : 'axis' ,
axisPointer : {
type : 'line'
} ,
2024-05-25 12:32:38 +02:00
backgroundColor : 'rgba(17, 19, 31, 1)' ,
2024-05-03 12:33:05 +02:00
borderRadius : 4 ,
2024-05-25 12:32:38 +02:00
shadowColor : 'rgba(0, 0, 0, 0.5)' ,
2024-05-03 12:33:05 +02:00
textStyle : {
color : 'var(--tooltip-grey)' ,
align : 'left' ,
} ,
borderColor : 'var(--active-bg)' ,
formatter : function ( data ) {
if ( data . length <= 0 ) {
return '' ;
}
2024-05-14 20:31:25 +02:00
let tooltip = ` <b style="color: white; margin-left: 2px"> ${ formatterXAxis ( this . locale , this . zoomTimeSpan , parseInt ( this . data . timestamp [ data [ 0 ] . dataIndex ] , 10 ) ) } </b><br> ` ;
2024-05-03 12:33:05 +02:00
for ( let i = data . length - 1 ; i >= 0 ; i -- ) {
const tick = data [ i ] ;
2024-05-25 12:32:38 +02:00
tooltip += ` ${ tick . marker } ${ tick . seriesName . split ( ' ' ) [ 0 ] } : ` ;
if ( this . displayMode === 'normal' ) tooltip += ` ${ formatNumber ( tick . data , this . locale , '1.0-3' ) } BTC<br> ` ;
else if ( this . displayMode === 'fiat' ) tooltip += ` ${ this . fiatCurrencyPipe . transform ( tick . data , null , 'USD' ) } <br> ` ;
else tooltip += ` ${ formatNumber ( tick . data , this . locale , '1.0-2' ) } %<br> ` ;
2024-05-03 12:33:05 +02:00
}
2024-05-25 12:32:38 +02:00
if ( this . displayMode === 'normal' ) tooltip += ` <div style="margin-left: 2px"> ${ formatNumber ( data . reduce ( ( acc , val ) = > acc + val . data , 0 ) , this . locale , '1.0-3' ) } BTC</div> ` ;
else if ( this . displayMode === 'fiat' ) tooltip += ` <div style="margin-left: 2px"> ${ this . fiatCurrencyPipe . transform ( data . reduce ( ( acc , val ) = > acc + val . data , 0 ) , null , 'USD' ) } </div> ` ;
2024-05-14 20:31:25 +02:00
if ( [ '24h' , '3d' ] . includes ( this . zoomTimeSpan ) ) {
2024-07-02 14:02:16 +09:00
tooltip += ` <small> ` + $localize ` At block ${ '<b style="color: white; margin-left: 2px">' + data [ 0 ] . axisValue } ` + ` </small> ` ;
2024-05-14 20:31:25 +02:00
} else {
2024-07-02 14:02:16 +09:00
tooltip += ` <small> ` + $localize ` Around block ${ '<b style="color: white; margin-left: 2px">' + data [ 0 ] . axisValue } ` + ` </small> ` ;
2024-05-14 20:31:25 +02:00
}
2024-05-03 12:33:05 +02:00
return tooltip ;
} . bind ( this )
} ,
2024-05-14 20:31:25 +02:00
xAxis : this.data.blockFees.length === 0 ? undefined : [
2024-05-11 14:36:17 +02:00
{
type : 'category' ,
2024-05-14 20:31:25 +02:00
data : this.data.blockHeight ,
2024-05-11 14:36:17 +02:00
show : false ,
axisLabel : {
hideOverlap : true ,
}
} ,
{
type : 'category' ,
2024-05-14 20:31:25 +02:00
data : this.data.timestamp ,
2024-05-11 14:36:17 +02:00
show : true ,
position : 'bottom' ,
axisLabel : {
color : 'var(--grey)' ,
formatter : ( val ) = > {
return formatterXAxis ( this . locale , this . timespan , parseInt ( val , 10 ) ) ;
}
} ,
axisTick : {
show : false ,
} ,
axisLine : {
show : false ,
} ,
splitLine : {
show : false ,
} ,
2024-05-03 12:33:05 +02:00
}
2024-05-11 14:36:17 +02:00
] ,
2024-05-14 20:31:25 +02:00
legend : this.data.blockFees.length === 0 ? undefined : {
2024-05-03 12:33:05 +02:00
data : [
{
name : 'Subsidy' ,
inactiveColor : 'var(--grey)' ,
textStyle : {
color : 'white' ,
} ,
icon : 'roundRect' ,
} ,
{
name : 'Fees' ,
inactiveColor : 'var(--grey)' ,
textStyle : {
color : 'white' ,
} ,
icon : 'roundRect' ,
} ,
{
name : 'Subsidy (USD)' ,
inactiveColor : 'var(--grey)' ,
textStyle : {
color : 'white' ,
} ,
icon : 'roundRect' ,
} ,
{
name : 'Fees (USD)' ,
inactiveColor : 'var(--grey)' ,
textStyle : {
color : 'white' ,
} ,
icon : 'roundRect' ,
} ,
2024-05-25 12:32:38 +02:00
{
name : 'Subsidy (%)' ,
inactiveColor : 'var(--grey)' ,
textStyle : {
color : 'white' ,
} ,
icon : 'roundRect' ,
} ,
{
name : 'Fees (%)' ,
inactiveColor : 'var(--grey)' ,
textStyle : {
color : 'white' ,
} ,
icon : 'roundRect' ,
} ,
2024-05-11 14:36:17 +02:00
] ,
2024-05-03 12:33:05 +02:00
selected : {
2024-05-25 12:32:38 +02:00
'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' ,
2024-05-03 12:33:05 +02:00
} ,
} ,
2024-05-14 20:31:25 +02:00
yAxis : this.data.blockFees.length === 0 ? undefined : [
2024-05-03 12:33:05 +02:00
{
type : 'value' ,
axisLabel : {
color : 'var(--grey)' ,
formatter : ( val ) = > {
2024-05-25 12:32:38 +02:00
return ` ${ val } ${ this . displayMode === 'percentage' ? '%' : ' BTC' } ` ;
2024-05-03 12:33:05 +02:00
}
} ,
min : 0 ,
2024-05-25 12:32:38 +02:00
max : ( value ) = > {
if ( this . displayMode === 'percentage' ) {
return 100 ;
}
} ,
2024-05-03 12:33:05 +02:00
splitLine : {
lineStyle : {
type : 'dotted' ,
color : 'var(--transparent-fg)' ,
opacity : 0.25 ,
}
} ,
} ,
{
type : 'value' ,
position : 'right' ,
axisLabel : {
color : 'var(--grey)' ,
formatter : function ( val ) {
return this . fiatShortenerPipe . transform ( val , null , 'USD' ) ;
} . bind ( this )
} ,
splitLine : {
show : false ,
} ,
} ,
] ,
2024-05-14 20:31:25 +02:00
series : this.data.blockFees.length === 0 ? undefined : [
2024-05-03 12:33:05 +02:00
{
name : 'Subsidy' ,
yAxisIndex : 0 ,
type : 'bar' ,
2024-05-25 12:32:38 +02:00
barWidth : '90%' ,
2024-05-03 12:33:05 +02:00
stack : 'total' ,
2024-05-14 20:31:25 +02:00
data : this.data.blockSubsidy ,
2024-05-03 12:33:05 +02:00
} ,
{
name : 'Fees' ,
yAxisIndex : 0 ,
type : 'bar' ,
2024-05-25 12:32:38 +02:00
barWidth : '90%' ,
2024-05-03 12:33:05 +02:00
stack : 'total' ,
2024-05-14 20:31:25 +02:00
data : this.data.blockFees ,
2024-05-03 12:33:05 +02:00
} ,
{
name : 'Subsidy (USD)' ,
yAxisIndex : 1 ,
type : 'bar' ,
2024-05-25 12:32:38 +02:00
barWidth : '90%' ,
2024-05-03 12:33:05 +02:00
stack : 'total' ,
2024-05-14 20:31:25 +02:00
data : this.data.blockSubsidyFiat ,
2024-05-03 12:33:05 +02:00
} ,
{
name : 'Fees (USD)' ,
yAxisIndex : 1 ,
type : 'bar' ,
2024-05-25 12:32:38 +02:00
barWidth : '90%' ,
2024-05-03 12:33:05 +02:00
stack : 'total' ,
2024-05-14 20:31:25 +02:00
data : this.data.blockFeesFiat ,
2024-05-03 12:33:05 +02:00
} ,
2024-05-25 12:32:38 +02:00
{
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 ,
} ,
2024-05-03 12:33:05 +02:00
] ,
2024-05-14 20:31:25 +02:00
dataZoom : this.data.blockFees.length === 0 ? undefined : [ {
2024-05-03 12:33:05 +02:00
type : 'inside' ,
realtime : true ,
zoomLock : true ,
maxSpan : 100 ,
minSpan : 1 ,
moveOnMouseMove : false ,
} , {
showDetail : false ,
show : true ,
type : 'slider' ,
brushSelect : false ,
realtime : true ,
left : 20 ,
right : 15 ,
selectedDataBackground : {
lineStyle : {
color : '#fff' ,
opacity : 0.45 ,
} ,
} ,
} ] ,
} ;
}
onChartInit ( ec ) {
this . chartInstance = ec ;
this . chartInstance . on ( 'legendselectchanged' , ( params ) = > {
2024-05-27 16:49:29 +02:00
if ( this . isLoading ) {
return ;
}
2024-05-25 12:32:38 +02:00
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 ;
2024-05-03 12:33:05 +02:00
const isActivation = params . selected [ params . name ] ;
2024-05-25 12:32:38 +02:00
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 (%)' } ) ;
2024-05-03 12:33:05 +02:00
}
} ) ;
2024-05-14 20:31:25 +02:00
this . chartInstance . on ( 'datazoom' , ( params ) = > {
2024-05-15 17:05:18 +02:00
if ( params . silent || this . isLoading || [ '24h' , '3d' ] . includes ( this . timespan ) ) {
2024-05-14 20:31:25 +02:00
return ;
}
this . updateZoom = true ;
} ) ;
this . chartInstance . on ( 'click' , ( e ) = > {
this . zone . run ( ( ) = > {
if ( [ '24h' , '3d' ] . includes ( this . zoomTimeSpan ) ) {
const url = new RelativeUrlPipe ( this . stateService ) . transform ( ` /block/ ${ e . name } ` ) ;
if ( e . event . event . shiftKey || e . event . event . ctrlKey || e . event . event . metaKey ) {
window . open ( url ) ;
} else {
this . router . navigate ( [ url ] ) ;
}
}
} ) ;
} ) ;
}
2024-05-15 13:07:32 +02:00
@HostListener ( 'document:pointerup' , [ '$event' ] )
onPointerUp ( event : PointerEvent ) {
2024-05-14 20:31:25 +02:00
if ( this . updateZoom ) {
this . onZoom ( ) ;
this . updateZoom = false ;
}
2024-05-03 12:33:05 +02:00
}
isMobile() {
return ( window . innerWidth <= 767.98 ) ;
}
2024-05-14 20:31:25 +02:00
initSubsidies ( ) : { [ key : number ] : number } {
let blockReward = 50 * 100 _000_000 ;
const subsidies = { } ;
for ( let i = 0 ; i <= 33 ; i ++ ) {
subsidies [ i ] = blockReward ;
blockReward = Math . floor ( blockReward / 2 ) ;
}
return subsidies ;
}
2024-05-27 16:42:17 +02:00
subsidyAt ( height : number ) : number {
return this . subsidies [ Math . floor ( Math . min ( height / 210000 , 33 ) ) ] ;
}
2024-05-14 20:31:25 +02:00
onZoom() {
const option = this . chartInstance . getOption ( ) ;
const timestamps = option . xAxis [ 1 ] . data ;
const startTimestamp = timestamps [ option . dataZoom [ 0 ] . startValue ] ;
const endTimestamp = timestamps [ option . dataZoom [ 0 ] . endValue ] ;
this . isLoading = true ;
this . cd . detectChanges ( ) ;
const subscription = this . apiService . getBlockFeesFromTimespan $ ( Math . floor ( startTimestamp / 1000 ) , Math . floor ( endTimestamp / 1000 ) )
. pipe (
tap ( ( response ) = > {
const startIndex = option . dataZoom [ 0 ] . startValue ;
const endIndex = option . dataZoom [ 0 ] . endValue ;
// Update series with more granular data
const lengthBefore = this . data . timestamp . length ;
this . data . timestamp . splice ( startIndex , endIndex - startIndex , . . . response . body . map ( val = > val . timestamp * 1000 ) ) ;
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' ] ) ) ;
2024-05-27 16:42:17 +02:00
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 ) ) ;
2024-05-14 20:31:25 +02:00
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 ;
2024-05-25 12:32:38 +02:00
option . series [ 4 ] . data = this . data . blockSubsidyPercent ;
option . series [ 5 ] . data = this . data . blockFeesPercent ;
2024-05-14 20:31:25 +02:00
option . xAxis [ 0 ] . data = this . data . blockHeight ;
option . xAxis [ 1 ] . data = this . data . timestamp ;
this . chartInstance . setOption ( option , true ) ;
const lengthAfter = this . data . timestamp . length ;
// Update the zoom to keep the same range after the update
this . chartInstance . dispatchAction ( {
type : 'dataZoom' ,
startValue : startIndex ,
endValue : endIndex + lengthAfter - lengthBefore ,
silent : true ,
} ) ;
// Update the chart
const newOption = this . chartInstance . getOption ( ) ;
this . zoomSpan = newOption . dataZoom [ 0 ] . end - newOption . dataZoom [ 0 ] . start ;
2024-05-15 13:07:32 +02:00
this . zoomTimeSpan = this . getTimeRangeFromTimespan ( Math . floor ( this . data . timestamp [ newOption . dataZoom [ 0 ] . startValue ] / 1000 ) , Math . floor ( this . data . timestamp [ newOption . dataZoom [ 0 ] . endValue ] / 1000 ) ) ;
2024-05-14 20:31:25 +02:00
this . isLoading = false ;
} ) ,
catchError ( ( ) = > {
const newOption = this . chartInstance . getOption ( ) ;
this . zoomSpan = newOption . dataZoom [ 0 ] . end - newOption . dataZoom [ 0 ] . start ;
2024-05-15 13:07:32 +02:00
this . zoomTimeSpan = this . getTimeRangeFromTimespan ( Math . floor ( this . data . timestamp [ newOption . dataZoom [ 0 ] . startValue ] / 1000 ) , Math . floor ( this . data . timestamp [ newOption . dataZoom [ 0 ] . endValue ] / 1000 ) ) ;
2024-05-14 20:31:25 +02:00
this . isLoading = false ;
this . cd . detectChanges ( ) ;
return [ ] ;
} )
) . subscribe ( ( ) = > {
subscription . unsubscribe ( ) ;
this . cd . detectChanges ( ) ;
} ) ;
}
2024-05-15 13:07:32 +02:00
getTimeRangeFromTimespan ( from : number , to : number ) : string {
2024-05-14 20:31:25 +02:00
const timespan = to - from ;
2024-05-15 13:07:32 +02:00
switch ( true ) {
case timespan >= 3600 * 24 * 365 * 4 : return 'all' ;
case timespan >= 3600 * 24 * 365 * 3 : return '4y' ;
case timespan >= 3600 * 24 * 365 * 2 : return '3y' ;
case timespan >= 3600 * 24 * 365 : return '2y' ;
case timespan >= 3600 * 24 * 30 * 6 : return '1y' ;
case timespan >= 3600 * 24 * 30 * 3 : return '6m' ;
case timespan >= 3600 * 24 * 30 : return '3m' ;
case timespan >= 3600 * 24 * 7 : return '1m' ;
case timespan >= 3600 * 24 * 3 : return '1w' ;
case timespan >= 3600 * 24 : return '3d' ;
default : return '24h' ;
2024-05-14 20:31:25 +02:00
}
}
2024-05-03 12:33:05 +02:00
onSaveChart() {
// @ts-ignore
const prevBottom = this . chartOptions . grid . bottom ;
const now = new Date ( ) ;
// @ts-ignore
this . chartOptions . grid . bottom = 40 ;
this . chartOptions . backgroundColor = 'var(--active-bg)' ;
this . chartInstance . setOption ( this . chartOptions ) ;
download ( this . chartInstance . getDataURL ( {
pixelRatio : 2 ,
excludeComponents : [ 'dataZoom' ] ,
2024-05-11 14:36:17 +02:00
} ) , ` block-fees-subsidy- ${ this . timespan } - ${ Math . round ( now . getTime ( ) / 1000 ) } .svg ` ) ;
2024-05-03 12:33:05 +02:00
// @ts-ignore
this . chartOptions . grid . bottom = prevBottom ;
this . chartOptions . backgroundColor = 'none' ;
this . chartInstance . setOption ( this . chartOptions ) ;
}
}