Fix db version conflicts

This commit is contained in:
natsoni
2024-03-04 20:32:38 +01:00
27 changed files with 1524 additions and 262 deletions

View File

@@ -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>

View File

@@ -25,7 +25,8 @@
flex-direction: column;
padding: 0px 15px;
width: 100%;
height: calc(100vh - 250px);
height: calc(100vh - 225px);
min-height: 400px;
@media (min-width: 992px) {
height: calc(100vh - 150px);
}
@@ -35,6 +36,7 @@
display: flex;
flex: 1;
width: 100%;
height: 100%;
padding-bottom: 20px;
padding-right: 10px;
@media (max-width: 992px) {

View File

@@ -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',
@@ -29,7 +28,7 @@ import { ApiService } from '../../../services/api.service';
})
export class AccelerationFeesGraphComponent implements OnInit, OnDestroy {
@Input() widget: boolean = false;
@Input() height: number | string = '200';
@Input() height: number = 300;
@Input() right: number | string = 45;
@Input() left: number | string = 75;
@Input() accelerations$: Observable<Acceleration[]>;
@@ -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,104 +67,56 @@ 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.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) {
this.radioGroupForm.controls.dateSpan.setValue(fragment, { emitEvent: false });
}
});
this.statsObservable$ = combineLatest([
this.radioGroupForm.get('dateSpan').valueChanges.pipe(
startWith(this.radioGroupForm.controls.dateSpan.value),
switchMap((timespan) => {
this.isLoading = true;
this.storageService.setValue('miningWindowPreference', timespan);
this.timespan = timespan;
return this.servicesApiService.getAccelerationHistory$({});
})
),
this.radioGroupForm.get('dateSpan').valueChanges.pipe(
startWith(this.radioGroupForm.controls.dateSpan.value),
switchMap((timespan) => {
return this.apiService.getHistoricalBlockFees$(timespan);
})
)
]).pipe(
tap(([accelerations, blockFeesResponse]) => {
this.prepareChartOptions(accelerations, blockFeesResponse.body);
})
);
this.miningWindowPreference = this.miningService.getDefaultTimespan('3m');
}
this.statsSubscription = this.statsObservable$.subscribe(() => {
this.isLoading = false;
this.cd.markForCheck();
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', '3m'].indexOf(fragment) > -1) {
this.radioGroupForm.controls.dateSpan.setValue(fragment, { emitEvent: false });
}
});
this.statsObservable$ = combineLatest([
this.radioGroupForm.get('dateSpan').valueChanges.pipe(
startWith(this.radioGroupForm.controls.dateSpan.value),
switchMap((timespan) => {
if (!this.widget) {
this.storageService.setValue('miningWindowPreference', timespan);
}
this.isLoading = true;
this.timespan = timespan;
return this.servicesApiService.getAggregatedAccelerationHistory$({timeframe: this.timespan});
})
),
fromEvent(window, 'resize').pipe(startWith(null)),
]).pipe(
tap(([history]) => {
this.isLoading = false;
this.prepareChartOptions(history);
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 = {
@@ -177,11 +127,11 @@ export class AccelerationFeesGraphComponent implements OnInit, OnDestroy {
],
animation: false,
grid: {
height: this.height,
height: (this.widget && this.height) ? this.height - 30 : undefined,
top: this.widget ? 20 : 40,
bottom: this.widget ? 30 : 80,
right: this.right,
left: this.left,
bottom: this.widget ? 30 : 80,
top: this.widget ? 20 : (this.isMobile() ? 10 : 50),
},
tooltip: {
show: !this.isMobile(),
@@ -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))}</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>`;
} else {
tooltip += `${tick.marker} ${tick.seriesName}: ${formatNumber(tick.data[1], this.locale, '1.0-0')} sats<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 += `${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 :
{
@@ -228,7 +172,7 @@ export class AccelerationFeesGraphComponent implements OnInit, OnDestroy {
nameTextStyle: {
padding: [10, 0, 0, 0],
},
type: 'category',
type: 'time',
boundaryGap: false,
axisLine: { onZero: true },
axisLabel: {
@@ -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
}
},
};
}

View File

@@ -3,16 +3,16 @@
<div class="item">
<h5 class="card-title" i18n="accelerator.requests">Requests</h5>
<div class="card-text">
<div>{{ stats.count }}</div>
<div>{{ stats.totalRequested }}</div>
<div class="symbol" i18n="accelerator.total-accelerated">accelerated</div>
</div>
</div>
<div class="item">
<h5 class="card-title" i18n="accelerator.total-boost">Total Bid Boost</h5>
<div class="card-text">
<div>{{ stats.totalFeesPaid / 100_000_000 | amountShortener: 4 }} <span class="symbol" i18n="shared.btc|BTC">BTC</span></div>
<div>{{ stats.totalBidBoost / 100_000_000 | amountShortener: 4 }} <span class="symbol" i18n="shared.btc|BTC">BTC</span></div>
<span class="fiat">
<app-fiat [value]="stats.totalFeesPaid"></app-fiat>
<app-fiat [value]="stats.totalBidBoost"></app-fiat>
</span>
</div>
</div>

View File

@@ -1,9 +1,12 @@
import { ChangeDetectionStrategy, Component, Input, OnInit } from '@angular/core';
import { Observable, of } from 'rxjs';
import { switchMap } from 'rxjs/operators';
import { ApiService } from '../../../services/api.service';
import { StateService } from '../../../services/state.service';
import { Acceleration } from '../../../interfaces/node-api.interface';
import { ChangeDetectionStrategy, Component, OnInit } from '@angular/core';
import { Observable } from 'rxjs';
import { ServicesApiServices } from '../../../services/services-api.service';
export type AccelerationStats = {
totalRequested: number;
totalBidBoost: number;
successRate: number;
}
@Component({
selector: 'app-acceleration-stats',
@@ -12,35 +15,13 @@ import { Acceleration } from '../../../interfaces/node-api.interface';
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class AccelerationStatsComponent implements OnInit {
@Input() timespan: '24h' | '1w' | '1m' = '24h';
@Input() accelerations$: Observable<Acceleration[]>;
public accelerationStats$: Observable<any>;
accelerationStats$: Observable<AccelerationStats>;
constructor(
private apiService: ApiService,
private stateService: StateService,
private servicesApiService: ServicesApiServices
) { }
ngOnInit(): void {
this.accelerationStats$ = this.accelerations$.pipe(
switchMap(accelerations => {
let totalFeesPaid = 0;
let totalSucceeded = 0;
let totalCanceled = 0;
for (const acc of accelerations) {
if (acc.status === 'completed') {
totalSucceeded++;
totalFeesPaid += (acc.feePaid - acc.baseFee - acc.vsizeFee) || 0;
} else if (acc.status === 'failed') {
totalCanceled++;
}
}
return of({
count: totalSucceeded,
totalFeesPaid,
successRate: (totalSucceeded + totalCanceled > 0) ? ((totalSucceeded / (totalSucceeded + totalCanceled)) * 100) : 0.0,
});
})
);
this.accelerationStats$ = this.servicesApiService.getAccelerationStats$();
}
}

View File

@@ -1,4 +1,4 @@
<div class="container-xl widget-container" [class.widget]="widget" [class.full-height]="!widget">
<div class="container-lg widget-container" [class.widget]="widget" [class.full-height]="!widget">
<h1 *ngIf="!widget" class="float-left" i18n="master-page.blocks">Accelerations</h1>
<div *ngIf="!widget && isLoading" class="spinner-border ml-3" role="status"></div>
@@ -17,6 +17,7 @@
<th class="fee text-right" i18n="transaction.bid-boost|Bid Boost">Bid Boost</th>
<th class="block text-right" i18n="accelerator.block">Block</th>
<th class="status text-right" i18n="transaction.status|Transaction Status">Status</th>
<th class="date text-right" i18n="" *ngIf="!this.widget">Requested</th>
</ng-container>
</thead>
<tbody *ngIf="accelerations; else skeleton" [style]="isLoading ? 'opacity: 0.75' : ''">
@@ -49,9 +50,13 @@
</td>
<td class="status text-right">
<span *ngIf="acceleration.status === 'accelerating'" class="badge badge-warning" i18n="accelerator.pending">Pending</span>
<span *ngIf="acceleration.status === 'mined' || acceleration.status === 'completed'" class="badge badge-success" i18n="transaction.rbf.mined">Mined</span>
<span *ngIf="acceleration.status === 'mined'" class="badge badge-info" i18n="transaction.rbf.mined">Mined</span>
<span *ngIf="acceleration.status === 'completed'" class="badge badge-success" i18n="">Completed</span>
<span *ngIf="acceleration.status === 'failed'" class="badge badge-danger" i18n="accelerator.canceled">Canceled</span>
</td>
<td class="date text-right" *ngIf="!this.widget">
<app-time kind="since" [time]="acceleration.added" [fastRender]="true"></app-time>
</td>
</ng-container>
</tr>
</tbody>
@@ -75,6 +80,11 @@
</ng-template>
</table>
<ngb-pagination *ngIf="!widget" class="pagination-container float-right mt-2" [class]="isLoading ? 'disabled' : ''"
[collectionSize]="this.accelerationCount" [rotate]="true" [maxSize]="maxSize" [pageSize]="15" [(page)]="page"
(pageChange)="pageChange(page)" [boundaryLinks]="true" [ellipses]="false">
</ngb-pagination>
<ng-template [ngIf]="!widget">
<div class="clearfix"></div>
<br>

View File

@@ -63,16 +63,28 @@ tr, td, th {
}
.txid {
@media (max-width: 500px) {
width: 20%;
}
.fee {
width: 15%;
}
.block {
width: 15%;
@media (max-width: 700px) {
display: none;
}
}
.fee, .block, .status {
width: 15%;
.status {
width: 13%;
}
@media (max-width: 720px) {
width: 20%;
.date {
width: 20%;
@media (max-width: 600px) {
display: none;
}
}
@@ -83,23 +95,12 @@ tr, td, th {
text-overflow: ellipsis;
white-space: nowrap;
max-width: 30%;
@media (max-width: 1060px) and (min-width: 768px) {
display: none;
}
@media (max-width: 500px) {
display: none;
}
}
.fee-rate {
width: 20%;
@media (max-width: 1060px) and (min-width: 768px) {
text-align: start !important;
}
@media (max-width: 500px) {
text-align: start !important;
}
@media (max-width: 840px) and (min-width: 768px) {
text-align: end !important;
@media (max-width: 975px) and (min-width: 768px) {
display: none;
}
@media (max-width: 410px) {
@@ -108,32 +109,31 @@ tr, td, th {
}
.bid {
text-align: end !important;
width: 30%;
min-width: 150px;
@media (max-width: 840px) and (min-width: 768px) {
text-align: start !important;
}
@media (max-width: 410px) {
text-align: start !important;
}
}
.time {
width: 25%;
@media (max-width: 600px) {
display: none;
}
@media (max-width: 1200px) and (min-width: 768px) {
display: none;
}
}
.fee {
width: 30%;
@media (max-width: 1060px) and (min-width: 768px) {
text-align: start !important;
}
@media (max-width: 500px) {
text-align: start !important;
}
text-align: end !important;
}
.block {
width: 20%;
@media (max-width: 1200px) and (min-width: 768px) {
display: none;
}
}
.status {

View File

@@ -1,5 +1,5 @@
import { Component, OnInit, ChangeDetectionStrategy, Input, ChangeDetectorRef } from '@angular/core';
import { Observable, catchError, of, switchMap, tap } from 'rxjs';
import { combineLatest, BehaviorSubject, Observable, catchError, of, switchMap, tap } from 'rxjs';
import { Acceleration, BlockExtended } from '../../../interfaces/node-api.interface';
import { StateService } from '../../../services/state.service';
import { WebsocketService } from '../../../services/websocket.service';
@@ -21,9 +21,10 @@ export class AccelerationsListComponent implements OnInit {
isLoading = true;
paginationMaxSize: number;
page = 1;
lastPage = 1;
accelerationCount: number;
maxSize = window.innerWidth <= 767.98 ? 3 : 5;
skeletonLines: number[] = [];
pageSubject: BehaviorSubject<number> = new BehaviorSubject(this.page);
constructor(
private servicesApiService: ServicesApiServices,
@@ -40,34 +41,47 @@ export class AccelerationsListComponent implements OnInit {
this.skeletonLines = this.widget === true ? [...Array(6).keys()] : [...Array(15).keys()];
this.paginationMaxSize = window.matchMedia('(max-width: 670px)').matches ? 3 : 5;
const accelerationObservable$ = this.accelerations$ || (this.pending ? this.servicesApiService.getAccelerations$() : this.servicesApiService.getAccelerationHistory$({ timeframe: '1m' }));
this.accelerationList$ = accelerationObservable$.pipe(
switchMap(accelerations => {
if (this.pending) {
for (const acceleration of accelerations) {
acceleration.status = acceleration.status || 'accelerating';
}
}
for (const acc of accelerations) {
acc.boost = acc.feePaid - acc.baseFee - acc.vsizeFee;
}
if (this.widget) {
return of(accelerations.slice(-6).reverse());
} else {
return of(accelerations.reverse());
}
}),
catchError((err) => {
this.isLoading = false;
return of([]);
}),
tap(() => {
this.isLoading = false;
this.accelerationList$ = this.pageSubject.pipe(
switchMap((page) => {
const accelerationObservable$ = this.accelerations$ || (this.pending ? this.servicesApiService.getAccelerations$() : this.servicesApiService.getAccelerationHistoryObserveResponse$({ timeframe: '1y', page: page }));
return accelerationObservable$.pipe(
switchMap(response => {
let accelerations = response;
if (response.body) {
accelerations = response.body;
this.accelerationCount = parseInt(response.headers.get('x-total-count'), 10);
}
if (this.pending) {
for (const acceleration of accelerations) {
acceleration.status = acceleration.status || 'accelerating';
}
}
for (const acc of accelerations) {
acc.boost = acc.feePaid - acc.baseFee - acc.vsizeFee;
}
if (this.widget) {
return of(accelerations.slice(0, 6));
} else {
return of(accelerations);
}
}),
catchError((err) => {
this.isLoading = false;
return of([]);
}),
tap(() => {
this.isLoading = false;
})
);
})
);
}
pageChange(page: number): void {
this.pageSubject.next(page);
}
trackByBlock(index: number, block: BlockExtended): number {
return block.height;
}

View File

@@ -22,12 +22,12 @@
<div class="col">
<div class="main-title">
<span [attr.data-cy]="'acceleration-stats'" i18n="accelerator.acceleration-stats">Acceleration stats</span>&nbsp;
<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" [accelerations$]="minedAccelerations$"></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 &raquo;</a></div>
@@ -84,7 +83,7 @@
<div class="title-link">
<h5 class="card-title d-inline" i18n="accelerator.pending-accelerations">Active Accelerations</h5>
</div>
<app-accelerations-list [attr.data-cy]="'pending-accelerations'" [widget]=true [pending]="true" [accelerations$]="pendingAccelerations$"></app-accelerations-list>
<app-accelerations-list [attr.data-cy]="'pending-accelerations'" [widget]=true [pending]=true [accelerations$]="pendingAccelerations$"></app-accelerations-list>
</div>
</div>
</div>

View File

@@ -60,7 +60,7 @@ export class AcceleratorDashboardComponent implements OnInit {
this.accelerations$ = this.stateService.chainTip$.pipe(
distinctUntilChanged(),
switchMap(() => {
return this.serviceApiServices.getAccelerationHistory$({ timeframe: '1m' }).pipe(
return this.serviceApiServices.getAccelerationHistory$({ timeframe: '3m', page: 1, pageLength: 100}).pipe(
catchError(() => {
return of([]);
}),
@@ -71,7 +71,7 @@ export class AcceleratorDashboardComponent implements OnInit {
this.minedAccelerations$ = this.accelerations$.pipe(
map(accelerations => {
return accelerations.filter(acc => ['mined', 'completed', 'failed'].includes(acc.status));
return accelerations.filter(acc => ['mined', 'completed'].includes(acc.status));
})
);
@@ -128,11 +128,11 @@ export class AcceleratorDashboardComponent implements OnInit {
@HostListener('window:resize', ['$event'])
onResize(): void {
if (window.innerWidth >= 992) {
this.graphHeight = 330;
this.graphHeight = 380;
} else if (window.innerWidth >= 768) {
this.graphHeight = 245;
this.graphHeight = 300;
} else {
this.graphHeight = 210;
this.graphHeight = 270;
}
}
}

View File

@@ -59,7 +59,7 @@ export default class TxView implements TransactionStripped {
this.acc = tx.acc;
this.rate = tx.rate;
this.status = tx.status;
this.bigintFlags = tx.flags ? (BigInt(tx.flags) ^ (this.acc ? TransactionFlags.acceleration : 0n)): 0n;
this.bigintFlags = tx.flags ? (BigInt(tx.flags) | (this.acc ? TransactionFlags.acceleration : 0n)): 0n;
this.initialised = false;
this.vertexArray = scene.vertexArray;

View File

@@ -28,7 +28,7 @@
<app-fee-rate [fee]="feeRate"></app-fee-rate>
</td>
</tr>
<tr *ngIf="effectiveRate && effectiveRate !== feeRate">
<tr *ngIf="hasEffectiveRate && effectiveRate != null">
<td *ngIf="!this.acceleration" class="td-width" i18n="transaction.effective-fee-rate|Effective transaction fee rate">Effective fee rate</td>
<td *ngIf="this.acceleration" class="td-width" i18n="transaction.effective-fee-rate|Effective transaction fee rate">Accelerated fee rate</td>
<td>

View File

@@ -2,6 +2,7 @@ import { Component, ElementRef, ViewChild, Input, OnChanges, ChangeDetectionStra
import { Position } from '../../components/block-overview-graph/sprite-types.js';
import { Price } from '../../services/price.service';
import { TransactionStripped } from '../../interfaces/node-api.interface.js';
import { TransactionFlags } from '../../shared/filters.utils';
@Component({
selector: 'app-block-overview-tooltip',
@@ -22,6 +23,7 @@ export class BlockOverviewTooltipComponent implements OnChanges {
feeRate = 0;
effectiveRate;
acceleration;
hasEffectiveRate: boolean = false;
tooltipPosition: Position = { x: 0, y: 0 };
@@ -55,6 +57,8 @@ export class BlockOverviewTooltipComponent implements OnChanges {
this.feeRate = this.fee / this.vsize;
this.effectiveRate = tx.rate;
this.acceleration = tx.acc;
this.hasEffectiveRate = Math.abs((this.fee / this.vsize) - this.effectiveRate) > 0.05
|| (tx.bigintFlags && (tx.bigintFlags & (TransactionFlags.cpfp_child | TransactionFlags.cpfp_parent)) > 0n);
}
}
}

View File

@@ -8,6 +8,7 @@
[showFilters]="showFilters"
[filterFlags]="filterFlags"
[filterMode]="filterMode"
[excludeFilters]="['nonstandard']"
[overrideColors]="overrideColors"
(txClickEvent)="onTxClick($event)"
></app-block-overview-graph>