[accelerator] show 3m stats, fix accel fee chart
This commit is contained in:
		
							parent
							
								
									cda5448f13
								
							
						
					
					
						commit
						8bd939b374
					
				@ -23,6 +23,9 @@
 | 
			
		||||
        <label class="btn btn-primary btn-sm" [class.active]="radioGroupForm.get('dateSpan').value === '1m'">
 | 
			
		||||
          <input type="radio" [value]="'1m'" fragment="1m" [routerLink]="['/graphs/acceleration/fees' | relativeUrl]" formControlName="dateSpan"> 1M
 | 
			
		||||
        </label>
 | 
			
		||||
        <label class="btn btn-primary btn-sm" [class.active]="radioGroupForm.get('dateSpan').value === '3m'">
 | 
			
		||||
          <input type="radio" [value]="'3m'" fragment="3m" [routerLink]="['/graphs/acceleration/fees' | relativeUrl]" formControlName="dateSpan"> 3M
 | 
			
		||||
        </label>
 | 
			
		||||
      </div>
 | 
			
		||||
    </form>
 | 
			
		||||
  </div>
 | 
			
		||||
 | 
			
		||||
@ -1,7 +1,7 @@
 | 
			
		||||
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, Inject, Input, LOCALE_ID, OnDestroy, OnInit } from '@angular/core';
 | 
			
		||||
import { EChartsOption, graphic } from 'echarts';
 | 
			
		||||
import { EChartsOption } from 'echarts';
 | 
			
		||||
import { Observable, Subscription, combineLatest, fromEvent } from 'rxjs';
 | 
			
		||||
import { map, max, startWith, switchMap, tap } from 'rxjs/operators';
 | 
			
		||||
import { startWith, switchMap, tap } from 'rxjs/operators';
 | 
			
		||||
import { SeoService } from '../../../services/seo.service';
 | 
			
		||||
import { formatNumber } from '@angular/common';
 | 
			
		||||
import { UntypedFormBuilder, UntypedFormGroup } from '@angular/forms';
 | 
			
		||||
@ -11,7 +11,6 @@ import { MiningService } from '../../../services/mining.service';
 | 
			
		||||
import { ActivatedRoute } from '@angular/router';
 | 
			
		||||
import { Acceleration } from '../../../interfaces/node-api.interface';
 | 
			
		||||
import { ServicesApiServices } from '../../../services/services-api.service';
 | 
			
		||||
import { ApiService } from '../../../services/api.service';
 | 
			
		||||
 | 
			
		||||
@Component({
 | 
			
		||||
  selector: 'app-acceleration-fees-graph',
 | 
			
		||||
@ -55,7 +54,6 @@ export class AccelerationFeesGraphComponent implements OnInit, OnDestroy {
 | 
			
		||||
  constructor(
 | 
			
		||||
    @Inject(LOCALE_ID) public locale: string,
 | 
			
		||||
    private seoService: SeoService,
 | 
			
		||||
    private apiService: ApiService,
 | 
			
		||||
    private servicesApiService: ServicesApiServices,
 | 
			
		||||
    private formBuilder: UntypedFormBuilder,
 | 
			
		||||
    private storageService: StorageService,
 | 
			
		||||
@ -69,32 +67,17 @@ export class AccelerationFeesGraphComponent implements OnInit, OnDestroy {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  ngOnInit(): void {
 | 
			
		||||
    this.isLoading = true;
 | 
			
		||||
    if (this.widget) {
 | 
			
		||||
      this.miningWindowPreference = '1m';
 | 
			
		||||
      this.timespan = this.miningWindowPreference;
 | 
			
		||||
 | 
			
		||||
      this.statsObservable$ = combineLatest([
 | 
			
		||||
        (this.accelerations$ || this.servicesApiService.getAccelerationHistory$({ timeframe: this.miningWindowPreference })),
 | 
			
		||||
        this.apiService.getHistoricalBlockFees$(this.miningWindowPreference),
 | 
			
		||||
        fromEvent(window, 'resize').pipe(startWith(null)),
 | 
			
		||||
      ]).pipe(
 | 
			
		||||
        tap(([accelerations, blockFeesResponse]) => {
 | 
			
		||||
          this.prepareChartOptions(accelerations, blockFeesResponse.body);
 | 
			
		||||
        }),
 | 
			
		||||
        map(([accelerations, blockFeesResponse]) => {
 | 
			
		||||
          return {
 | 
			
		||||
            avgFeesPaid: accelerations.filter(acc => acc.status === 'completed').reduce((total, acc) => total + (acc.feePaid - acc.baseFee - acc.vsizeFee), 0) / accelerations.length
 | 
			
		||||
          };
 | 
			
		||||
        }),
 | 
			
		||||
      );
 | 
			
		||||
      this.miningWindowPreference = '3m';
 | 
			
		||||
    } else {
 | 
			
		||||
      this.seoService.setTitle($localize`:@@bcf34abc2d9ed8f45a2f65dd464c46694e9a181e:Acceleration Fees`);
 | 
			
		||||
      this.miningWindowPreference = this.miningService.getDefaultTimespan('1w');
 | 
			
		||||
      this.miningWindowPreference = this.miningService.getDefaultTimespan('3m');
 | 
			
		||||
    }
 | 
			
		||||
    this.radioGroupForm = this.formBuilder.group({ dateSpan: this.miningWindowPreference });
 | 
			
		||||
    this.radioGroupForm.controls.dateSpan.setValue(this.miningWindowPreference);
 | 
			
		||||
    
 | 
			
		||||
    this.route.fragment.subscribe((fragment) => {
 | 
			
		||||
        if (['24h', '3d', '1w', '1m'].indexOf(fragment) > -1) {
 | 
			
		||||
      if (['24h', '3d', '1w', '1m', '3m'].indexOf(fragment) > -1) {
 | 
			
		||||
        this.radioGroupForm.controls.dateSpan.setValue(fragment, { emitEvent: false });
 | 
			
		||||
      }
 | 
			
		||||
    });
 | 
			
		||||
@ -102,71 +85,38 @@ export class AccelerationFeesGraphComponent implements OnInit, OnDestroy {
 | 
			
		||||
      this.radioGroupForm.get('dateSpan').valueChanges.pipe(
 | 
			
		||||
        startWith(this.radioGroupForm.controls.dateSpan.value),
 | 
			
		||||
        switchMap((timespan) => {
 | 
			
		||||
            this.isLoading = true;
 | 
			
		||||
          if (!this.widget) {
 | 
			
		||||
            this.storageService.setValue('miningWindowPreference', timespan);
 | 
			
		||||
          }
 | 
			
		||||
          this.isLoading = true;
 | 
			
		||||
          this.timespan = timespan;
 | 
			
		||||
            return this.servicesApiService.getAccelerationHistory$({});
 | 
			
		||||
          return this.servicesApiService.getAggregatedAccelerationHistory$({timeframe: this.timespan});
 | 
			
		||||
        })
 | 
			
		||||
      ),
 | 
			
		||||
        this.radioGroupForm.get('dateSpan').valueChanges.pipe(
 | 
			
		||||
          startWith(this.radioGroupForm.controls.dateSpan.value),
 | 
			
		||||
          switchMap((timespan) => {
 | 
			
		||||
            return this.apiService.getHistoricalBlockFees$(timespan);
 | 
			
		||||
          })
 | 
			
		||||
        )
 | 
			
		||||
      fromEvent(window, 'resize').pipe(startWith(null)),
 | 
			
		||||
    ]).pipe(
 | 
			
		||||
        tap(([accelerations, blockFeesResponse]) => {
 | 
			
		||||
          this.prepareChartOptions(accelerations, blockFeesResponse.body);
 | 
			
		||||
      tap(([history]) => {
 | 
			
		||||
        this.isLoading = false;
 | 
			
		||||
        this.prepareChartOptions(history);
 | 
			
		||||
        this.cd.markForCheck();
 | 
			
		||||
      })
 | 
			
		||||
    );
 | 
			
		||||
    }
 | 
			
		||||
    this.statsSubscription = this.statsObservable$.subscribe(() => {
 | 
			
		||||
      this.isLoading = false;
 | 
			
		||||
      this.cd.markForCheck();
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    this.statsObservable$.subscribe();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  prepareChartOptions(accelerations, blockFees) {
 | 
			
		||||
  prepareChartOptions(data) {
 | 
			
		||||
    let title: object;
 | 
			
		||||
 | 
			
		||||
    const blockAccelerations = {};
 | 
			
		||||
 | 
			
		||||
    for (const acceleration of accelerations) {
 | 
			
		||||
      if (acceleration.status === 'completed') {
 | 
			
		||||
        if (!blockAccelerations[acceleration.blockHeight]) {
 | 
			
		||||
          blockAccelerations[acceleration.blockHeight] = [];
 | 
			
		||||
        }
 | 
			
		||||
        blockAccelerations[acceleration.blockHeight].push(acceleration);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    let last = null;
 | 
			
		||||
    let minValue = Infinity;
 | 
			
		||||
    let maxValue = 0;
 | 
			
		||||
    const data = [];
 | 
			
		||||
    for (const val of blockFees) {
 | 
			
		||||
      if (last == null) {
 | 
			
		||||
        last = val.avgHeight;
 | 
			
		||||
      }
 | 
			
		||||
      let totalFeeDelta = 0;
 | 
			
		||||
      let totalFeePaid = 0;
 | 
			
		||||
      let totalCount = 0;
 | 
			
		||||
      let blockCount = 0;
 | 
			
		||||
      while (last <= val.avgHeight) {
 | 
			
		||||
        blockCount++;
 | 
			
		||||
        totalFeeDelta += (blockAccelerations[last] || []).reduce((total, acc) => total + acc.feeDelta, 0);
 | 
			
		||||
        totalFeePaid += (blockAccelerations[last] || []).reduce((total, acc) => total + (acc.feePaid - acc.baseFee - acc.vsizeFee), 0);
 | 
			
		||||
        totalCount += (blockAccelerations[last] || []).length;
 | 
			
		||||
        last++;
 | 
			
		||||
      }
 | 
			
		||||
      minValue = Math.min(minValue, val.avgFees);
 | 
			
		||||
      maxValue = Math.max(maxValue, val.avgFees);
 | 
			
		||||
      data.push({
 | 
			
		||||
        ...val,
 | 
			
		||||
        feeDelta: totalFeeDelta,
 | 
			
		||||
        avgFeePaid: (totalFeePaid / blockCount),
 | 
			
		||||
        accelerations: totalCount / blockCount,
 | 
			
		||||
      });
 | 
			
		||||
    if (data.length === 0) {
 | 
			
		||||
      title = {
 | 
			
		||||
        textStyle: {
 | 
			
		||||
          color: 'grey',
 | 
			
		||||
          fontSize: 15
 | 
			
		||||
        },
 | 
			
		||||
        text: $localize`No accelerated transaction for this timeframe`,
 | 
			
		||||
        left: 'center',
 | 
			
		||||
        top: 'center'
 | 
			
		||||
      };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    this.chartOptions = {
 | 
			
		||||
@ -197,29 +147,23 @@ export class AccelerationFeesGraphComponent implements OnInit, OnDestroy {
 | 
			
		||||
          align: 'left',
 | 
			
		||||
        },
 | 
			
		||||
        borderColor: '#000',
 | 
			
		||||
        formatter: function (data) {
 | 
			
		||||
          if (data.length <= 0) {
 | 
			
		||||
            return '';
 | 
			
		||||
          }
 | 
			
		||||
          let tooltip = `<b style="color: white; margin-left: 2px">
 | 
			
		||||
            ${formatterXAxis(this.locale, this.timespan, parseInt(data[0].axisValue, 10))}</b><br>`;
 | 
			
		||||
        formatter: (ticks) => {
 | 
			
		||||
          let tooltip = `<b style="color: white; margin-left: 2px">${formatterXAxis(this.locale, this.timespan, parseInt(ticks[0].axisValue, 10) * 1000)}</b><br>`;
 | 
			
		||||
 | 
			
		||||
          for (const tick of data.reverse()) {
 | 
			
		||||
            if (tick.data[1] >= 1_000_000) {
 | 
			
		||||
              tooltip += `${tick.marker} ${tick.seriesName}: ${formatNumber(tick.data[1] / 100_000_000, this.locale, '1.0-3')} BTC<br>`;
 | 
			
		||||
          if (ticks[0].data[1] > 10_000_000) {
 | 
			
		||||
            tooltip += `${ticks[0].marker} ${ticks[0].seriesName}: ${formatNumber(ticks[0].data[1] / 100_000_000, this.locale, '1.0-0')} BTC<br>`;
 | 
			
		||||
          } else {
 | 
			
		||||
              tooltip += `${tick.marker} ${tick.seriesName}: ${formatNumber(tick.data[1], this.locale, '1.0-0')} sats<br>`;
 | 
			
		||||
            }
 | 
			
		||||
            tooltip += `${ticks[0].marker} ${ticks[0].seriesName}: ${formatNumber(ticks[0].data[1], this.locale, '1.0-0')} sats<br>`;
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
          if (['24h', '3d'].includes(this.timespan)) {
 | 
			
		||||
            tooltip += `<small>` + $localize`At block: ${data[0].data[2]}` + `</small>`;
 | 
			
		||||
            tooltip += `<small>` + $localize`At block: ${ticks[0].data[2]}` + `</small>`;
 | 
			
		||||
          } else {
 | 
			
		||||
            tooltip += `<small>` + $localize`Around block: ${data[0].data[2]}` + `</small>`;
 | 
			
		||||
            tooltip += `<small>` + $localize`Around block: ${ticks[0].data[2]}` + `</small>`;
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
          return tooltip;
 | 
			
		||||
        }.bind(this)
 | 
			
		||||
        }
 | 
			
		||||
      },
 | 
			
		||||
      xAxis: data.length === 0 ? undefined :
 | 
			
		||||
      {
 | 
			
		||||
@ -243,15 +187,7 @@ export class AccelerationFeesGraphComponent implements OnInit, OnDestroy {
 | 
			
		||||
      legend: {
 | 
			
		||||
        data: [
 | 
			
		||||
          {
 | 
			
		||||
            name: 'In-band fees per block',
 | 
			
		||||
            inactiveColor: 'rgb(110, 112, 121)',
 | 
			
		||||
            textStyle: {
 | 
			
		||||
              color: 'white',
 | 
			
		||||
            },
 | 
			
		||||
            icon: 'roundRect',
 | 
			
		||||
          },
 | 
			
		||||
          {
 | 
			
		||||
            name: 'Total bid boost per block',
 | 
			
		||||
            name: 'Total bid boost',
 | 
			
		||||
            inactiveColor: 'rgb(110, 112, 121)',
 | 
			
		||||
            textStyle: {
 | 
			
		||||
              color: 'white',
 | 
			
		||||
@ -260,8 +196,7 @@ export class AccelerationFeesGraphComponent implements OnInit, OnDestroy {
 | 
			
		||||
          },
 | 
			
		||||
        ],
 | 
			
		||||
        selected: {
 | 
			
		||||
          'In-band fees per block': false,
 | 
			
		||||
          'Total bid boost per block': true,
 | 
			
		||||
          'Total bid boost': true,
 | 
			
		||||
        },
 | 
			
		||||
        show: !this.widget,
 | 
			
		||||
      },
 | 
			
		||||
@ -304,21 +239,13 @@ export class AccelerationFeesGraphComponent implements OnInit, OnDestroy {
 | 
			
		||||
        {
 | 
			
		||||
          legendHoverLink: false,
 | 
			
		||||
          zlevel: 1,
 | 
			
		||||
          name: 'Total bid boost per block',
 | 
			
		||||
          data: data.map(block =>  [block.timestamp * 1000, block.avgFeePaid, block.avgHeight]),
 | 
			
		||||
          name: 'Total bid boost',
 | 
			
		||||
          data: data.map(h =>  {
 | 
			
		||||
            return [h.timestamp * 1000, h.sumBidBoost, h.avgHeight]
 | 
			
		||||
          }),
 | 
			
		||||
          stack: 'Total',
 | 
			
		||||
          type: 'bar',
 | 
			
		||||
          barWidth: '100%',
 | 
			
		||||
          large: true,
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
          legendHoverLink: false,
 | 
			
		||||
          zlevel: 0,
 | 
			
		||||
          name: 'In-band fees per block',
 | 
			
		||||
          data: data.map(block =>  [block.timestamp * 1000, block.avgFees, block.avgHeight]),
 | 
			
		||||
          stack: 'Total',
 | 
			
		||||
          type: 'bar',
 | 
			
		||||
          barWidth: '100%',
 | 
			
		||||
          barWidth: '90%',
 | 
			
		||||
          large: true,
 | 
			
		||||
        },
 | 
			
		||||
      ],
 | 
			
		||||
@ -347,17 +274,6 @@ export class AccelerationFeesGraphComponent implements OnInit, OnDestroy {
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
      }],
 | 
			
		||||
      visualMap: {
 | 
			
		||||
        type: 'continuous',
 | 
			
		||||
        min: minValue,
 | 
			
		||||
        max: maxValue,
 | 
			
		||||
        dimension: 1,
 | 
			
		||||
        seriesIndex: 1,
 | 
			
		||||
        show: false,
 | 
			
		||||
        inRange: {
 | 
			
		||||
          color: ['#F4511E7f', '#FB8C007f', '#FFB3007f', '#FDD8357f', '#7CB3427f'].reverse() // Gradient color range
 | 
			
		||||
        }
 | 
			
		||||
      },
 | 
			
		||||
    };
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -22,12 +22,12 @@
 | 
			
		||||
    <div class="col">
 | 
			
		||||
      <div class="main-title">
 | 
			
		||||
        <span [attr.data-cy]="'acceleration-stats'" i18n="accelerator.acceleration-stats">Acceleration stats</span> 
 | 
			
		||||
        <span style="font-size: xx-small" i18n="mining.144-blocks">(1 month)</span>
 | 
			
		||||
        <span style="font-size: xx-small" i18n="mining.3-months">(3 months)</span>
 | 
			
		||||
      </div>
 | 
			
		||||
      <div class="card-wrapper">
 | 
			
		||||
        <div class="card">
 | 
			
		||||
          <div class="card-body more-padding">
 | 
			
		||||
            <app-acceleration-stats timespan="1m"></app-acceleration-stats>
 | 
			
		||||
            <app-acceleration-stats></app-acceleration-stats>
 | 
			
		||||
          </div>
 | 
			
		||||
        </div>
 | 
			
		||||
      </div>
 | 
			
		||||
@ -59,7 +59,6 @@
 | 
			
		||||
              [height]="graphHeight"
 | 
			
		||||
              [attr.data-cy]="'acceleration-fees'"
 | 
			
		||||
              [widget]=true
 | 
			
		||||
              [accelerations$]="accelerations$"
 | 
			
		||||
            ></app-acceleration-fees-graph>
 | 
			
		||||
          </div>
 | 
			
		||||
          <div class="mt-1"><a [attr.data-cy]="'acceleration-fees-view-more'" [routerLink]="['/graphs/acceleration/fees' | relativeUrl]" i18n="dashboard.view-more">View more »</a></div>
 | 
			
		||||
 | 
			
		||||
@ -60,7 +60,7 @@ export class AcceleratorDashboardComponent implements OnInit {
 | 
			
		||||
    this.accelerations$ = this.stateService.chainTip$.pipe(
 | 
			
		||||
      distinctUntilChanged(),
 | 
			
		||||
      switchMap(() => {
 | 
			
		||||
        return this.serviceApiServices.getAccelerationHistory$({ timeframe: '1m', page: 1, pageLength: 100}).pipe(
 | 
			
		||||
        return this.serviceApiServices.getAccelerationHistory$({ timeframe: '3m', page: 1, pageLength: 100}).pipe(
 | 
			
		||||
          catchError(() => {
 | 
			
		||||
            return of([]);
 | 
			
		||||
          }),
 | 
			
		||||
 | 
			
		||||
@ -145,6 +145,10 @@ export class ServicesApiServices {
 | 
			
		||||
    return this.httpClient.get<Acceleration[]>(`${SERVICES_API_PREFIX}/accelerator/accelerations`);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  getAggregatedAccelerationHistory$(params: AccelerationHistoryParams): Observable<Acceleration[]> {
 | 
			
		||||
    return this.httpClient.get<Acceleration[]>(`${SERVICES_API_PREFIX}/accelerator/accelerations/history/aggregated`, { params: { ...params } });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  getAccelerationHistory$(params: AccelerationHistoryParams): Observable<Acceleration[]> {
 | 
			
		||||
    return this.httpClient.get<Acceleration[]>(`${SERVICES_API_PREFIX}/accelerator/accelerations/history`, { params: { ...params } });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user