Compare commits
16 Commits
nymkappa/a
...
knorrium/u
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
541555051b | ||
|
|
5aeaa68259 | ||
|
|
e01898a4c5 | ||
|
|
0568a8c6c1 | ||
|
|
e53e810a55 | ||
|
|
e2c44b6c62 | ||
|
|
36b691e25b | ||
|
|
5f5e96984a | ||
|
|
4a14e8d921 | ||
|
|
4e735cc8b0 | ||
|
|
4520e3fdf2 | ||
|
|
390bbf1097 | ||
|
|
f5a54ae62b | ||
|
|
4da145ff5c | ||
|
|
a898701830 | ||
|
|
72ddb8c6a4 |
6
.github/workflows/ci.yml
vendored
6
.github/workflows/ci.yml
vendored
@@ -9,7 +9,7 @@ jobs:
|
|||||||
if: "!contains(github.event.pull_request.labels.*.name, 'ops') && !contains(github.head_ref, 'ops/')"
|
if: "!contains(github.event.pull_request.labels.*.name, 'ops') && !contains(github.head_ref, 'ops/')"
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
node: ["20", "21"]
|
node: ["20", "22"]
|
||||||
flavor: ["dev", "prod"]
|
flavor: ["dev", "prod"]
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
runs-on: "ubuntu-latest"
|
runs-on: "ubuntu-latest"
|
||||||
@@ -160,7 +160,7 @@ jobs:
|
|||||||
if: "!contains(github.event.pull_request.labels.*.name, 'ops') && !contains(github.head_ref, 'ops/')"
|
if: "!contains(github.event.pull_request.labels.*.name, 'ops') && !contains(github.head_ref, 'ops/')"
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
node: ["20", "21"]
|
node: ["20", "22"]
|
||||||
flavor: ["dev", "prod"]
|
flavor: ["dev", "prod"]
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
runs-on: "ubuntu-latest"
|
runs-on: "ubuntu-latest"
|
||||||
@@ -263,7 +263,7 @@ jobs:
|
|||||||
- name: Setup node
|
- name: Setup node
|
||||||
uses: actions/setup-node@v3
|
uses: actions/setup-node@v3
|
||||||
with:
|
with:
|
||||||
node-version: 20
|
node-version: 22
|
||||||
cache: "npm"
|
cache: "npm"
|
||||||
cache-dependency-path: ${{ matrix.module }}/frontend/package-lock.json
|
cache-dependency-path: ${{ matrix.module }}/frontend/package-lock.json
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,18 @@
|
|||||||
<div class="box card w-100 accelerate-checkout-inner" [class.input-disabled]="isCheckoutLocked > 0" style="background: var(--box-bg)" id=acceleratePreviewAnchor>
|
<div class="box card w-100 accelerate-checkout-inner" [class.input-disabled]="isCheckoutLocked > 0" style="background: var(--box-bg)" id=acceleratePreviewAnchor>
|
||||||
@if (accelerateError) {
|
@if (accelerateError) {
|
||||||
<div class="row mb-1 text-center">
|
@if (accelerateError.includes('Payment declined')) {
|
||||||
<div class="col-sm">
|
<div class="row mb-1 text-center">
|
||||||
<h1 style="font-size: larger;" i18n="accelerator.sorry-error-title">Sorry, something went wrong!</h1>
|
<div class="col-sm">
|
||||||
|
<h1 style="font-size: larger;">{{ accelerateError }}</h1>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
} @else {
|
||||||
|
<div class="row mb-1 text-center">
|
||||||
|
<div class="col-sm">
|
||||||
|
<h1 style="font-size: larger;" i18n="accelerator.sorry-error-title">Sorry, something went wrong!</h1>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
<div class="row text-center mt-1">
|
<div class="row text-center mt-1">
|
||||||
<div class="col-sm">
|
<div class="col-sm">
|
||||||
<div class="d-flex flex-row justify-content-center align-items-center">
|
<div class="d-flex flex-row justify-content-center align-items-center">
|
||||||
|
|||||||
@@ -222,7 +222,6 @@ export class AccelerateCheckout implements OnInit, OnDestroy {
|
|||||||
this.loadingBtcpayInvoice = true;
|
this.loadingBtcpayInvoice = true;
|
||||||
this.invoice = null;
|
this.invoice = null;
|
||||||
this.requestBTCPayInvoice();
|
this.requestBTCPayInvoice();
|
||||||
this.scrollToElementWithTimeout('acceleratePreviewAnchor', 'start', 100);
|
|
||||||
} else if (this._step === 'cashapp' && this.cashappEnabled) {
|
} else if (this._step === 'cashapp' && this.cashappEnabled) {
|
||||||
this.loadingCashapp = true;
|
this.loadingCashapp = true;
|
||||||
this.setupSquare();
|
this.setupSquare();
|
||||||
@@ -560,7 +559,7 @@ export class AccelerateCheckout implements OnInit, OnDestroy {
|
|||||||
// Reset everything by reloading the page :D, can be improved
|
// Reset everything by reloading the page :D, can be improved
|
||||||
const urlParams = new URLSearchParams(window.location.search);
|
const urlParams = new URLSearchParams(window.location.search);
|
||||||
window.location.assign(window.location.toString().replace(`?cash_request_id=${urlParams.get('cash_request_id')}`, ``));
|
window.location.assign(window.location.toString().replace(`?cash_request_id=${urlParams.get('cash_request_id')}`, ``));
|
||||||
}, 3000);
|
}, 10000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -687,7 +686,7 @@ export class AccelerateCheckout implements OnInit, OnDestroy {
|
|||||||
// Reset everything by reloading the page :D, can be improved
|
// Reset everything by reloading the page :D, can be improved
|
||||||
const urlParams = new URLSearchParams(window.location.search);
|
const urlParams = new URLSearchParams(window.location.search);
|
||||||
window.location.assign(window.location.toString().replace(`?cash_request_id=${urlParams.get('cash_request_id')}`, ``));
|
window.location.assign(window.location.toString().replace(`?cash_request_id=${urlParams.get('cash_request_id')}`, ``));
|
||||||
}, 3000);
|
}, 10000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -786,7 +785,7 @@ export class AccelerateCheckout implements OnInit, OnDestroy {
|
|||||||
// Reset everything by reloading the page :D, can be improved
|
// Reset everything by reloading the page :D, can be improved
|
||||||
const urlParams = new URLSearchParams(window.location.search);
|
const urlParams = new URLSearchParams(window.location.search);
|
||||||
window.location.assign(window.location.toString().replace(`?cash_request_id=${urlParams.get('cash_request_id')}`, ``));
|
window.location.assign(window.location.toString().replace(`?cash_request_id=${urlParams.get('cash_request_id')}`, ``));
|
||||||
}, 3000);
|
}, 10000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -11,6 +11,12 @@
|
|||||||
|
|
||||||
<form [formGroup]="radioGroupForm" class="formRadioGroup" *ngIf="daysAvailable">
|
<form [formGroup]="radioGroupForm" class="formRadioGroup" *ngIf="daysAvailable">
|
||||||
<div class="btn-group btn-group-toggle" name="radioBasic">
|
<div class="btn-group btn-group-toggle" name="radioBasic">
|
||||||
|
<label class="btn btn-primary btn-sm" [class.active]="radioGroupForm.get('dateSpan').value === '24h'">
|
||||||
|
<input type="radio" [value]="'24h'" fragment="24h" [routerLink]="['/graphs/acceleration/fees' | relativeUrl]" formControlName="dateSpan"> 24H
|
||||||
|
</label>
|
||||||
|
<label class="btn btn-primary btn-sm" *ngIf="daysAvailable >= 1" [class.active]="radioGroupForm.get('dateSpan').value === '3d'">
|
||||||
|
<input type="radio" [value]="'3d'" fragment="3d" [routerLink]="['/graphs/acceleration/fees' | relativeUrl]" formControlName="dateSpan"> 3D
|
||||||
|
</label>
|
||||||
<label class="btn btn-primary btn-sm" *ngIf="daysAvailable >= 3" [class.active]="radioGroupForm.get('dateSpan').value === '1w'">
|
<label class="btn btn-primary btn-sm" *ngIf="daysAvailable >= 3" [class.active]="radioGroupForm.get('dateSpan').value === '1w'">
|
||||||
<input type="radio" [value]="'1w'" fragment="1w" [routerLink]="['/graphs/acceleration/fees' | relativeUrl]" formControlName="dateSpan"> 1W
|
<input type="radio" [value]="'1w'" fragment="1w" [routerLink]="['/graphs/acceleration/fees' | relativeUrl]" formControlName="dateSpan"> 1W
|
||||||
</label>
|
</label>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, Inject, Input, LOCALE_ID, NgZone, OnChanges, OnDestroy, OnInit, SimpleChanges } from '@angular/core';
|
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, Inject, Input, LOCALE_ID, NgZone, OnChanges, OnDestroy, OnInit, SimpleChanges } from '@angular/core';
|
||||||
import { echarts, EChartsOption } from '@app/graphs/echarts';
|
import { EChartsOption } from '@app/graphs/echarts';
|
||||||
import { Observable, Subject, Subscription, combineLatest, fromEvent, merge, share } from 'rxjs';
|
import { Observable, Subject, Subscription, combineLatest, fromEvent, merge, share } from 'rxjs';
|
||||||
import { startWith, switchMap, tap } from 'rxjs/operators';
|
import { startWith, switchMap, tap } from 'rxjs/operators';
|
||||||
import { SeoService } from '@app/services/seo.service';
|
import { SeoService } from '@app/services/seo.service';
|
||||||
@@ -12,6 +12,7 @@ import { ActivatedRoute, Router } from '@angular/router';
|
|||||||
import { Acceleration } from '@interfaces/node-api.interface';
|
import { Acceleration } from '@interfaces/node-api.interface';
|
||||||
import { ServicesApiServices } from '@app/services/services-api.service';
|
import { ServicesApiServices } from '@app/services/services-api.service';
|
||||||
import { StateService } from '@app/services/state.service';
|
import { StateService } from '@app/services/state.service';
|
||||||
|
import { RelativeUrlPipe } from '@app/shared/pipes/relative-url/relative-url.pipe';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-acceleration-fees-graph',
|
selector: 'app-acceleration-fees-graph',
|
||||||
@@ -30,9 +31,9 @@ import { StateService } from '@app/services/state.service';
|
|||||||
export class AccelerationFeesGraphComponent implements OnInit, OnChanges, OnDestroy {
|
export class AccelerationFeesGraphComponent implements OnInit, OnChanges, OnDestroy {
|
||||||
@Input() widget: boolean = false;
|
@Input() widget: boolean = false;
|
||||||
@Input() height: number = 300;
|
@Input() height: number = 300;
|
||||||
@Input() right: number | string = 70;
|
@Input() right: number | string = 45;
|
||||||
@Input() left: number | string = 55;
|
@Input() left: number | string = 75;
|
||||||
@Input() period: '24h' | '1w' | '1m' | '1y' | 'all' = '1y';
|
@Input() period: '24h' | '3d' | '1w' | '1m' | 'all' = '1w';
|
||||||
@Input() accelerations$: Observable<Acceleration[]>;
|
@Input() accelerations$: Observable<Acceleration[]>;
|
||||||
|
|
||||||
miningWindowPreference: string;
|
miningWindowPreference: string;
|
||||||
@@ -50,7 +51,7 @@ export class AccelerationFeesGraphComponent implements OnInit, OnChanges, OnDest
|
|||||||
isLoading = true;
|
isLoading = true;
|
||||||
formatNumber = formatNumber;
|
formatNumber = formatNumber;
|
||||||
timespan = '';
|
timespan = '';
|
||||||
periodSubject$: Subject<'24h' | '1w' | '1m' | '1y' | 'all'> = new Subject();
|
periodSubject$: Subject<'24h' | '3d' | '1w' | '1m' | 'all'> = new Subject();
|
||||||
chartInstance: any = undefined;
|
chartInstance: any = undefined;
|
||||||
daysAvailable: number = 0;
|
daysAvailable: number = 0;
|
||||||
|
|
||||||
@@ -63,7 +64,9 @@ export class AccelerationFeesGraphComponent implements OnInit, OnChanges, OnDest
|
|||||||
private miningService: MiningService,
|
private miningService: MiningService,
|
||||||
private route: ActivatedRoute,
|
private route: ActivatedRoute,
|
||||||
public stateService: StateService,
|
public stateService: StateService,
|
||||||
private cd: ChangeDetectorRef
|
private cd: ChangeDetectorRef,
|
||||||
|
private router: Router,
|
||||||
|
private zone: NgZone,
|
||||||
) {
|
) {
|
||||||
this.radioGroupForm = this.formBuilder.group({ dateSpan: '1w' });
|
this.radioGroupForm = this.formBuilder.group({ dateSpan: '1w' });
|
||||||
this.radioGroupForm.controls.dateSpan.setValue('1w');
|
this.radioGroupForm.controls.dateSpan.setValue('1w');
|
||||||
@@ -80,7 +83,7 @@ export class AccelerationFeesGraphComponent implements OnInit, OnChanges, OnDest
|
|||||||
this.radioGroupForm.controls.dateSpan.setValue(this.miningWindowPreference);
|
this.radioGroupForm.controls.dateSpan.setValue(this.miningWindowPreference);
|
||||||
|
|
||||||
this.fragmentSubscription = this.route.fragment.subscribe((fragment) => {
|
this.fragmentSubscription = this.route.fragment.subscribe((fragment) => {
|
||||||
if (['1w', '1m', '1y', 'all'].indexOf(fragment) > -1) {
|
if (['24h', '3d', '1w', '1m', '3m', 'all'].indexOf(fragment) > -1) {
|
||||||
this.radioGroupForm.controls.dateSpan.setValue(fragment, { emitEvent: false });
|
this.radioGroupForm.controls.dateSpan.setValue(fragment, { emitEvent: false });
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -95,9 +98,7 @@ export class AccelerationFeesGraphComponent implements OnInit, OnChanges, OnDest
|
|||||||
if (!this.widget) {
|
if (!this.widget) {
|
||||||
this.storageService.setValue('miningWindowPreference', timespan);
|
this.storageService.setValue('miningWindowPreference', timespan);
|
||||||
}
|
}
|
||||||
if (timespan !== this.timespan) {
|
this.isLoading = true;
|
||||||
this.isLoading = true;
|
|
||||||
}
|
|
||||||
this.timespan = timespan;
|
this.timespan = timespan;
|
||||||
return this.servicesApiService.getAggregatedAccelerationHistory$({timeframe: this.timespan});
|
return this.servicesApiService.getAggregatedAccelerationHistory$({timeframe: this.timespan});
|
||||||
})
|
})
|
||||||
@@ -119,9 +120,6 @@ export class AccelerationFeesGraphComponent implements OnInit, OnChanges, OnDest
|
|||||||
|
|
||||||
ngOnChanges(changes: SimpleChanges): void {
|
ngOnChanges(changes: SimpleChanges): void {
|
||||||
if (changes.period) {
|
if (changes.period) {
|
||||||
if (this.period === '24h') {
|
|
||||||
this.period = '1m';
|
|
||||||
}
|
|
||||||
this.periodSubject$.next(this.period);
|
this.periodSubject$.next(this.period);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -143,19 +141,13 @@ export class AccelerationFeesGraphComponent implements OnInit, OnChanges, OnDest
|
|||||||
this.chartOptions = {
|
this.chartOptions = {
|
||||||
title: title,
|
title: title,
|
||||||
color: [
|
color: [
|
||||||
new echarts.graphic.LinearGradient(0, 0, 0, 0.65, [
|
'#8F5FF6',
|
||||||
{ offset: 0, color: '#F4511E' },
|
'#6b6b6b',
|
||||||
{ offset: 0.25, color: '#FB8C00' },
|
|
||||||
{ offset: 0.5, color: '#FFB300' },
|
|
||||||
{ offset: 0.75, color: '#FDD835' },
|
|
||||||
{ offset: 1, color: '#7CB342' }
|
|
||||||
]),
|
|
||||||
'#ab2dce',
|
|
||||||
],
|
],
|
||||||
animation: false,
|
animation: false,
|
||||||
grid: {
|
grid: {
|
||||||
height: (this.widget && this.height) ? this.height - 50 : undefined,
|
height: (this.widget && this.height) ? this.height - 30 : undefined,
|
||||||
top: this.widget ? 40 : 60,
|
top: this.widget ? 20 : 40,
|
||||||
bottom: this.widget ? 30 : 80,
|
bottom: this.widget ? 30 : 80,
|
||||||
right: this.right,
|
right: this.right,
|
||||||
left: this.left,
|
left: this.left,
|
||||||
@@ -177,18 +169,17 @@ export class AccelerationFeesGraphComponent implements OnInit, OnChanges, OnDest
|
|||||||
formatter: (ticks) => {
|
formatter: (ticks) => {
|
||||||
let tooltip = `<b style="color: white; margin-left: 2px">${formatterXAxis(this.locale, this.timespan, parseInt(ticks[0].axisValue, 10))}</b><br>`;
|
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 ticks) {
|
if (ticks[0].data[1] > 10_000_000) {
|
||||||
if (tick.seriesName === 'Total bid boost') {
|
tooltip += `${ticks[0].marker} ${ticks[0].seriesName}: ${formatNumber(ticks[0].data[1] / 100_000_000, this.locale, '1.0-8')} BTC<br>`;
|
||||||
if (tick.data[1] > 10_000_000) {
|
} else {
|
||||||
tooltip += `${tick.marker} ${tick.seriesName}: ${formatNumber(tick.data[1] / 100_000_000, this.locale, '1.0-8')} BTC<br>`;
|
tooltip += `${ticks[0].marker} ${ticks[0].seriesName}: ${formatNumber(ticks[0].data[1], this.locale, '1.0-0')} sats<br>`;
|
||||||
} else {
|
}
|
||||||
tooltip += `${tick.marker} ${tick.seriesName}: ${formatNumber(tick.data[1], this.locale, '1.0-0')} sats<br>`;
|
|
||||||
}
|
if (['24h', '3d'].includes(this.timespan)) {
|
||||||
} else if (tick && tick.seriesName === 'Accelerated') {
|
tooltip += `<small>` + $localize`At block: ${ticks[0].data[2]}` + `</small>`;
|
||||||
tooltip += `${tick.marker} ${tick.seriesName}: ${formatNumber(tick.data[1], this.locale, '1.0-0')}<br>`;
|
} else {
|
||||||
}
|
tooltip += `<small>` + $localize`Around block: ${ticks[0].data[2]}` + `</small>`;
|
||||||
}
|
}
|
||||||
tooltip += `<small>` + $localize`Around block: ${ticks[0].data[2]}` + `</small>`;
|
|
||||||
|
|
||||||
return tooltip;
|
return tooltip;
|
||||||
}
|
}
|
||||||
@@ -220,17 +211,6 @@ export class AccelerationFeesGraphComponent implements OnInit, OnChanges, OnDest
|
|||||||
textStyle: {
|
textStyle: {
|
||||||
color: 'white',
|
color: 'white',
|
||||||
},
|
},
|
||||||
itemStyle: {
|
|
||||||
color: '#FFB300',
|
|
||||||
},
|
|
||||||
icon: 'roundRect',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'Accelerated',
|
|
||||||
inactiveColor: 'rgb(110, 112, 121)',
|
|
||||||
textStyle: {
|
|
||||||
color: 'white',
|
|
||||||
},
|
|
||||||
icon: 'roundRect',
|
icon: 'roundRect',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
@@ -242,13 +222,6 @@ export class AccelerationFeesGraphComponent implements OnInit, OnChanges, OnDest
|
|||||||
yAxis: data.length === 0 ? undefined : [
|
yAxis: data.length === 0 ? undefined : [
|
||||||
{
|
{
|
||||||
type: 'value',
|
type: 'value',
|
||||||
name: 'Total bid boost',
|
|
||||||
position: 'right',
|
|
||||||
nameTextStyle: {
|
|
||||||
align: 'right',
|
|
||||||
padding: [0, -65, 0, 0],
|
|
||||||
fontStyle: 'italic',
|
|
||||||
},
|
|
||||||
axisLabel: {
|
axisLabel: {
|
||||||
color: 'rgb(110, 112, 121)',
|
color: 'rgb(110, 112, 121)',
|
||||||
formatter: (val) => {
|
formatter: (val) => {
|
||||||
@@ -259,20 +232,6 @@ export class AccelerationFeesGraphComponent implements OnInit, OnChanges, OnDest
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
splitLine: null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'value',
|
|
||||||
name: 'Accelerated',
|
|
||||||
position: 'left',
|
|
||||||
axisLabel: {
|
|
||||||
color: 'rgb(110, 112, 121)',
|
|
||||||
},
|
|
||||||
nameTextStyle: {
|
|
||||||
align: 'right',
|
|
||||||
padding: [0, -35, 0, 0],
|
|
||||||
fontStyle: 'italic',
|
|
||||||
},
|
|
||||||
splitLine: {
|
splitLine: {
|
||||||
lineStyle: {
|
lineStyle: {
|
||||||
type: 'dotted',
|
type: 'dotted',
|
||||||
@@ -281,28 +240,33 @@ export class AccelerationFeesGraphComponent implements OnInit, OnChanges, OnDest
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
type: 'value',
|
||||||
|
position: 'right',
|
||||||
|
axisLabel: {
|
||||||
|
color: 'rgb(110, 112, 121)',
|
||||||
|
formatter: function(val) {
|
||||||
|
return `${val}`;
|
||||||
|
}.bind(this)
|
||||||
|
},
|
||||||
|
splitLine: {
|
||||||
|
show: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
],
|
],
|
||||||
series: data.length === 0 ? undefined : [
|
series: data.length === 0 ? undefined : [
|
||||||
{
|
{
|
||||||
|
legendHoverLink: false,
|
||||||
|
zlevel: 1,
|
||||||
name: 'Total bid boost',
|
name: 'Total bid boost',
|
||||||
data: data.map(h => {
|
data: data.map(h => {
|
||||||
return [h.timestamp * 1000, h.sumBidBoost, h.avgHeight]
|
return [h.timestamp * 1000, h.sumBidBoost, h.avgHeight]
|
||||||
}),
|
}),
|
||||||
type: 'line',
|
stack: 'Total',
|
||||||
symbol: 'none',
|
|
||||||
lineStyle: {
|
|
||||||
width: 1,
|
|
||||||
},
|
|
||||||
smooth: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'Accelerated',
|
|
||||||
yAxisIndex: 1,
|
|
||||||
data: data.map(h => {
|
|
||||||
return [h.timestamp * 1000, h.count, h.avgHeight]
|
|
||||||
}),
|
|
||||||
type: 'bar',
|
type: 'bar',
|
||||||
barWidth: '90%',
|
barWidth: '90%',
|
||||||
|
large: true,
|
||||||
|
barMinHeight: 3,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
dataZoom: (this.widget || data.length === 0 )? undefined : [{
|
dataZoom: (this.widget || data.length === 0 )? undefined : [{
|
||||||
@@ -335,6 +299,19 @@ export class AccelerationFeesGraphComponent implements OnInit, OnChanges, OnDest
|
|||||||
|
|
||||||
onChartInit(ec) {
|
onChartInit(ec) {
|
||||||
this.chartInstance = ec;
|
this.chartInstance = ec;
|
||||||
|
|
||||||
|
this.chartInstance.on('click', (e) => {
|
||||||
|
this.zone.run(() => {
|
||||||
|
if (['24h', '3d'].includes(this.timespan)) {
|
||||||
|
const url = new RelativeUrlPipe(this.stateService).transform(`/block/${e.data[2]}`);
|
||||||
|
if (e.event.event.shiftKey || e.event.event.ctrlKey || e.event.event.metaKey) {
|
||||||
|
window.open(url);
|
||||||
|
} else {
|
||||||
|
this.router.navigate([url]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
isMobile() {
|
isMobile() {
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ export type AccelerationStats = {
|
|||||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
})
|
})
|
||||||
export class AccelerationStatsComponent implements OnInit, OnChanges {
|
export class AccelerationStatsComponent implements OnInit, OnChanges {
|
||||||
@Input() timespan: '24h' | '1m' | '1y' | 'all' = '1y';
|
@Input() timespan: '24h' | '3d' | '1w' | '1m' | 'all' = '1w';
|
||||||
accelerationStats$: Observable<AccelerationStats>;
|
accelerationStats$: Observable<AccelerationStats>;
|
||||||
blocksInPeriod: number = 7 * 144;
|
blocksInPeriod: number = 7 * 144;
|
||||||
|
|
||||||
@@ -38,11 +38,14 @@ export class AccelerationStatsComponent implements OnInit, OnChanges {
|
|||||||
case '24h':
|
case '24h':
|
||||||
this.blocksInPeriod = 144;
|
this.blocksInPeriod = 144;
|
||||||
break;
|
break;
|
||||||
case '1m':
|
case '3d':
|
||||||
this.blocksInPeriod = 30.5 * 144;
|
this.blocksInPeriod = 3 * 144;
|
||||||
break;
|
break;
|
||||||
case '1y':
|
case '1w':
|
||||||
this.blocksInPeriod = 30.5 * 144 * 365;
|
this.blocksInPeriod = 7 * 144;
|
||||||
|
break;
|
||||||
|
case '1m':
|
||||||
|
this.blocksInPeriod = 30 * 144;
|
||||||
break;
|
break;
|
||||||
case 'all':
|
case 'all':
|
||||||
this.blocksInPeriod = Infinity;
|
this.blocksInPeriod = Infinity;
|
||||||
|
|||||||
@@ -26,12 +26,12 @@
|
|||||||
@case ('24h') {
|
@case ('24h') {
|
||||||
<span style="font-size: xx-small" i18n="mining.1-day">(1 day)</span>
|
<span style="font-size: xx-small" i18n="mining.1-day">(1 day)</span>
|
||||||
}
|
}
|
||||||
|
@case ('1w') {
|
||||||
|
<span style="font-size: xx-small" i18n="mining.1-week">(1 week)</span>
|
||||||
|
}
|
||||||
@case ('1m') {
|
@case ('1m') {
|
||||||
<span style="font-size: xx-small" i18n="mining.1-month">(1 month)</span>
|
<span style="font-size: xx-small" i18n="mining.1-month">(1 month)</span>
|
||||||
}
|
}
|
||||||
@case ('1y') {
|
|
||||||
<span style="font-size: xx-small" i18n="mining.1-year">(1 year)</span>
|
|
||||||
}
|
|
||||||
@case ('all') {
|
@case ('all') {
|
||||||
<span style="font-size: xx-small" i18n="mining.all-time">(all time)</span>
|
<span style="font-size: xx-small" i18n="mining.all-time">(all time)</span>
|
||||||
}
|
}
|
||||||
@@ -45,12 +45,12 @@
|
|||||||
<a href="" (click)="setTimespan('24h')" class="toggler-option"
|
<a href="" (click)="setTimespan('24h')" class="toggler-option"
|
||||||
[ngClass]="{'inactive': timespan === '24h'}"><small>24h</small></a>
|
[ngClass]="{'inactive': timespan === '24h'}"><small>24h</small></a>
|
||||||
<span style="color: #ffffff66; font-size: 8px"> | </span>
|
<span style="color: #ffffff66; font-size: 8px"> | </span>
|
||||||
|
<a href="" (click)="setTimespan('1w')" class="toggler-option"
|
||||||
|
[ngClass]="{'inactive': timespan === '1w'}"><small>1w</small></a>
|
||||||
|
<span style="color: #ffffff66; font-size: 8px"> | </span>
|
||||||
<a href="" (click)="setTimespan('1m')" class="toggler-option"
|
<a href="" (click)="setTimespan('1m')" class="toggler-option"
|
||||||
[ngClass]="{'inactive': timespan === '1m'}"><small>1m</small></a>
|
[ngClass]="{'inactive': timespan === '1m'}"><small>1m</small></a>
|
||||||
<span style="color: #ffffff66; font-size: 8px"> | </span>
|
<span style="color: #ffffff66; font-size: 8px"> | </span>
|
||||||
<a href="" (click)="setTimespan('1y')" class="toggler-option"
|
|
||||||
[ngClass]="{'inactive': timespan === '1y'}"><small>1y</small></a>
|
|
||||||
<span style="color: #ffffff66; font-size: 8px"> | </span>
|
|
||||||
<a href="" (click)="setTimespan('all')" class="toggler-option"
|
<a href="" (click)="setTimespan('all')" class="toggler-option"
|
||||||
[ngClass]="{'inactive': timespan === 'all'}"><small>all</small></a>
|
[ngClass]="{'inactive': timespan === 'all'}"><small>all</small></a>
|
||||||
</div>
|
</div>
|
||||||
@@ -79,15 +79,13 @@
|
|||||||
<div class="col" style="margin-bottom: 1.47rem">
|
<div class="col" style="margin-bottom: 1.47rem">
|
||||||
<div class="card graph-card">
|
<div class="card graph-card">
|
||||||
<div class="card-body pl-2 pr-2">
|
<div class="card-body pl-2 pr-2">
|
||||||
<h5 class="card-title" i18n="acceleration.historical-trend">Historical Trend</h5>
|
<h5 class="card-title" i18n="acceleration.total-bid-boost">Total Bid Boost</h5>
|
||||||
<div class="mempool-graph">
|
<div class="mempool-graph">
|
||||||
<app-acceleration-fees-graph
|
<app-acceleration-fees-graph
|
||||||
[height]="graphHeight"
|
[height]="graphHeight"
|
||||||
[attr.data-cy]="'acceleration-fees'"
|
[attr.data-cy]="'acceleration-fees'"
|
||||||
[widget]=true
|
[widget]=true
|
||||||
[period]="timespan"
|
[period]="timespan"
|
||||||
[right]="80"
|
|
||||||
[left]="50"
|
|
||||||
></app-acceleration-fees-graph>
|
></app-acceleration-fees-graph>
|
||||||
</div>
|
</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>
|
<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>
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ export class AcceleratorDashboardComponent implements OnInit, OnDestroy {
|
|||||||
webGlEnabled = true;
|
webGlEnabled = true;
|
||||||
seen: Set<string> = new Set();
|
seen: Set<string> = new Set();
|
||||||
firstLoad = true;
|
firstLoad = true;
|
||||||
timespan: '24h' | '1m' | '1y' | 'all' = '1y';
|
timespan: '24h' | '3d' | '1w' | '1m' | 'all' = '1w';
|
||||||
|
|
||||||
accelerationDeltaSubscription: Subscription;
|
accelerationDeltaSubscription: Subscription;
|
||||||
|
|
||||||
|
|||||||
@@ -8,8 +8,10 @@ import { SinglePoolStats } from '../../../interfaces/node-api.interface';
|
|||||||
|
|
||||||
type MerkleCellType = ' ' | '┬' | '├' | '└' | '│' | '─' | 'leaf';
|
type MerkleCellType = ' ' | '┬' | '├' | '└' | '│' | '─' | 'leaf';
|
||||||
|
|
||||||
|
|
||||||
interface TaggedStratumJob extends StratumJob {
|
interface TaggedStratumJob extends StratumJob {
|
||||||
tag: string;
|
tag: string;
|
||||||
|
merkleBranchIds: string[];
|
||||||
}
|
}
|
||||||
|
|
||||||
interface MerkleCell {
|
interface MerkleCell {
|
||||||
@@ -46,6 +48,18 @@ function parseTag(scriptSig: string): string {
|
|||||||
return (ascii.match(/\/.*\//)?.[0] || ascii).trim();
|
return (ascii.match(/\/.*\//)?.[0] || ascii).trim();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getMerkleBranchIds(merkleBranches: string[], numBranches: number): string[] {
|
||||||
|
let lastHash = '';
|
||||||
|
const ids: string[] = [];
|
||||||
|
for (let i = 0; i < numBranches; i++) {
|
||||||
|
if (merkleBranches[i]) {
|
||||||
|
lastHash = merkleBranches[i];
|
||||||
|
}
|
||||||
|
ids.push(`${i}-${lastHash}`);
|
||||||
|
}
|
||||||
|
return ids;
|
||||||
|
}
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-stratum-list',
|
selector: 'app-stratum-list',
|
||||||
templateUrl: './stratum-list.component.html',
|
templateUrl: './stratum-list.component.html',
|
||||||
@@ -81,16 +95,15 @@ export class StratumList implements OnInit, OnDestroy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
processJobs(rawJobs: Record<string, StratumJob>): PoolRow[] {
|
processJobs(rawJobs: Record<string, StratumJob>): PoolRow[] {
|
||||||
|
const numBranches = Math.max(...Object.values(rawJobs).map(job => job.merkleBranches.length));
|
||||||
const jobs: Record<string, TaggedStratumJob> = {};
|
const jobs: Record<string, TaggedStratumJob> = {};
|
||||||
for (const [id, job] of Object.entries(rawJobs)) {
|
for (const [id, job] of Object.entries(rawJobs)) {
|
||||||
jobs[id] = { ...job, tag: parseTag(job.scriptsig) };
|
jobs[id] = { ...job, tag: parseTag(job.scriptsig), merkleBranchIds: getMerkleBranchIds(job.merkleBranches, numBranches) };
|
||||||
}
|
}
|
||||||
if (Object.keys(jobs).length === 0) {
|
if (Object.keys(jobs).length === 0) {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
const numBranches = Math.max(...Object.values(jobs).map(job => job.merkleBranches.length));
|
|
||||||
|
|
||||||
let trees: MerkleTree[] = Object.keys(jobs).map(job => ({
|
let trees: MerkleTree[] = Object.keys(jobs).map(job => ({
|
||||||
job,
|
job,
|
||||||
size: 1,
|
size: 1,
|
||||||
@@ -100,12 +113,13 @@ export class StratumList implements OnInit, OnDestroy {
|
|||||||
for (let col = numBranches - 1; col >= 0; col--) {
|
for (let col = numBranches - 1; col >= 0; col--) {
|
||||||
const groups: Record<string, MerkleTree[]> = {};
|
const groups: Record<string, MerkleTree[]> = {};
|
||||||
for (const tree of trees) {
|
for (const tree of trees) {
|
||||||
const hash = jobs[tree.job].merkleBranches[col];
|
const branchId = jobs[tree.job].merkleBranchIds[col];
|
||||||
if (!groups[hash]) {
|
if (!groups[branchId]) {
|
||||||
groups[hash] = [];
|
groups[branchId] = [];
|
||||||
}
|
}
|
||||||
groups[hash].push(tree);
|
groups[branchId].push(tree);
|
||||||
}
|
}
|
||||||
|
|
||||||
trees = Object.values(groups).map(group => ({
|
trees = Object.values(groups).map(group => ({
|
||||||
hash: jobs[group[0].job].merkleBranches[col],
|
hash: jobs[group[0].job].merkleBranches[col],
|
||||||
job: group[0].job,
|
job: group[0].job,
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import { faFilter, faAngleDown, faAngleUp, faAngleRight, faAngleLeft, faBolt, fa
|
|||||||
faFileAlt, faRedoAlt, faArrowAltCircleRight, faExternalLinkAlt, faBook, faListUl, faDownload, faQrcode, faArrowRightArrowLeft, faArrowsRotate, faCircleLeft,
|
faFileAlt, faRedoAlt, faArrowAltCircleRight, faExternalLinkAlt, faBook, faListUl, faDownload, faQrcode, faArrowRightArrowLeft, faArrowsRotate, faCircleLeft,
|
||||||
faFastForward, faWallet, faUserClock, faWrench, faUserFriends, faQuestionCircle, faHistory, faSignOutAlt, faKey, faSuitcase, faIdCardAlt, faNetworkWired, faUserCheck,
|
faFastForward, faWallet, faUserClock, faWrench, faUserFriends, faQuestionCircle, faHistory, faSignOutAlt, faKey, faSuitcase, faIdCardAlt, faNetworkWired, faUserCheck,
|
||||||
faCircleCheck, faUserCircle, faCheck, faRocket, faScaleBalanced, faHourglassStart, faHourglassHalf, faHourglassEnd, faWandMagicSparkles, faFaucetDrip, faTimeline,
|
faCircleCheck, faUserCircle, faCheck, faRocket, faScaleBalanced, faHourglassStart, faHourglassHalf, faHourglassEnd, faWandMagicSparkles, faFaucetDrip, faTimeline,
|
||||||
faCircleXmark, faCalendarCheck, faMoneyBillTrendUp, faRobot } from '@fortawesome/free-solid-svg-icons';
|
faCircleXmark, faCalendarCheck, faMoneyBillTrendUp, faRobot, faShareNodes } from '@fortawesome/free-solid-svg-icons';
|
||||||
import { InfiniteScrollModule } from 'ngx-infinite-scroll';
|
import { InfiniteScrollModule } from 'ngx-infinite-scroll';
|
||||||
import { MenuComponent } from '@components/menu/menu.component';
|
import { MenuComponent } from '@components/menu/menu.component';
|
||||||
import { PreviewTitleComponent } from '@components/master-page-preview/preview-title.component';
|
import { PreviewTitleComponent } from '@components/master-page-preview/preview-title.component';
|
||||||
@@ -459,5 +459,6 @@ export class SharedModule {
|
|||||||
library.addIcons(faCalendarCheck);
|
library.addIcons(faCalendarCheck);
|
||||||
library.addIcons(faMoneyBillTrendUp);
|
library.addIcons(faMoneyBillTrendUp);
|
||||||
library.addIcons(faRobot);
|
library.addIcons(faRobot);
|
||||||
|
library.addIcons(faShareNodes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -154,5 +154,9 @@
|
|||||||
"WALLETS": {
|
"WALLETS": {
|
||||||
"ENABLED": true,
|
"ENABLED": true,
|
||||||
"WALLETS": ["BITB", "3350"]
|
"WALLETS": ["BITB", "3350"]
|
||||||
|
},
|
||||||
|
"STRATUM": {
|
||||||
|
"ENABLED": true,
|
||||||
|
"API": "http://127.0.0.1:81/api/v1/stratum/ws"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,8 +4,7 @@
|
|||||||
"TESTNET4_ENABLED": true,
|
"TESTNET4_ENABLED": true,
|
||||||
"LIQUID_ENABLED": false,
|
"LIQUID_ENABLED": false,
|
||||||
"LIQUID_TESTNET_ENABLED": false,
|
"LIQUID_TESTNET_ENABLED": false,
|
||||||
"BISQ_ENABLED": true,
|
"STRATUM_ENABLED": true,
|
||||||
"BISQ_SEPARATE_BACKEND": true,
|
|
||||||
"SIGNET_ENABLED": true,
|
"SIGNET_ENABLED": true,
|
||||||
"MEMPOOL_WEBSITE_URL": "https://mempool.space",
|
"MEMPOOL_WEBSITE_URL": "https://mempool.space",
|
||||||
"LIQUID_WEBSITE_URL": "https://liquid.network",
|
"LIQUID_WEBSITE_URL": "https://liquid.network",
|
||||||
|
|||||||
Reference in New Issue
Block a user