Merge pull request #4509 from mempool/nymkappa/mega-branch
[Mega branch] Various fixes and improvements
This commit is contained in:
commit
1e3650594c
@ -22,6 +22,7 @@ import { FiatCurrencyPipe } from './shared/pipes/fiat-currency.pipe';
|
|||||||
import { ShortenStringPipe } from './shared/pipes/shorten-string-pipe/shorten-string.pipe';
|
import { ShortenStringPipe } from './shared/pipes/shorten-string-pipe/shorten-string.pipe';
|
||||||
import { CapAddressPipe } from './shared/pipes/cap-address-pipe/cap-address-pipe';
|
import { CapAddressPipe } from './shared/pipes/cap-address-pipe/cap-address-pipe';
|
||||||
import { AppPreloadingStrategy } from './app.preloading-strategy';
|
import { AppPreloadingStrategy } from './app.preloading-strategy';
|
||||||
|
import { ServicesApiServices } from './services/services-api.service';
|
||||||
|
|
||||||
const providers = [
|
const providers = [
|
||||||
ElectrsApiService,
|
ElectrsApiService,
|
||||||
@ -40,6 +41,7 @@ const providers = [
|
|||||||
FiatCurrencyPipe,
|
FiatCurrencyPipe,
|
||||||
CapAddressPipe,
|
CapAddressPipe,
|
||||||
AppPreloadingStrategy,
|
AppPreloadingStrategy,
|
||||||
|
ServicesApiServices,
|
||||||
{ provide: HTTP_INTERCEPTORS, useClass: HttpCacheInterceptor, multi: true }
|
{ provide: HTTP_INTERCEPTORS, useClass: HttpCacheInterceptor, multi: true }
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
<div id="become-sponsor-container">
|
<div id="become-sponsor-container">
|
||||||
<div class="become-sponsor community">
|
<div class="become-sponsor community">
|
||||||
<p style="font-weight: 700; font-size: 18px;">If you're an individual...</p>
|
<p style="font-weight: 700; font-size: 18px;">If you're an individual...</p>
|
||||||
<a href="https://mempool.space/sponsor" class="btn" style="background-color: rgba(152, 88, 255, 0.75); box-shadow: 0px 0px 50px 5px rgba(152, 88, 255, 0.75)" i18n="about.community-sponsor-button" (click)="onSponsorClick($event)">Become a Community Sponsor</a>
|
<a [href]="host + '/sponsor'" class="btn" style="background-color: rgba(152, 88, 255, 0.75); box-shadow: 0px 0px 50px 5px rgba(152, 88, 255, 0.75)" i18n="about.community-sponsor-button" (click)="onSponsorClick($event)">Become a Community Sponsor</a>
|
||||||
<p class="sponsor-feature"><fa-icon [icon]="['fas', 'check']"></fa-icon> Exclusive swag</p>
|
<p class="sponsor-feature"><fa-icon [icon]="['fas', 'check']"></fa-icon> Exclusive swag</p>
|
||||||
<p class="sponsor-feature"><fa-icon [icon]="['fas', 'check']"></fa-icon> Your avatar on the About page</p>
|
<p class="sponsor-feature"><fa-icon [icon]="['fas', 'check']"></fa-icon> Your avatar on the About page</p>
|
||||||
<p class="sponsor-feature"><fa-icon [icon]="['fas', 'check']"></fa-icon> And more coming soon :)</p>
|
<p class="sponsor-feature"><fa-icon [icon]="['fas', 'check']"></fa-icon> And more coming soon :)</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="become-sponsor enterprise">
|
<div class="become-sponsor enterprise">
|
||||||
<p style="font-weight: 700; font-size: 18px;">If you're a business...</p>
|
<p style="font-weight: 700; font-size: 18px;">If you're a business...</p>
|
||||||
<a href="https://mempool.space/enterprise" class="btn" style="background-color: rgba(152, 88, 255, 0.75); box-shadow: 0px 0px 50px 5px rgba(152, 88, 255, 0.75)" i18n="about.enterprise-sponsor-button" (click)="onEnterpriseClick($event)">Become an Enterprise Sponsor</a>
|
<a [href]="host + '/enterprise'" class="btn" style="background-color: rgba(152, 88, 255, 0.75); box-shadow: 0px 0px 50px 5px rgba(152, 88, 255, 0.75)" i18n="about.enterprise-sponsor-button" (click)="onEnterpriseClick($event)">Become an Enterprise Sponsor</a>
|
||||||
<p class="sponsor-feature"><fa-icon [icon]="['fas', 'check']"></fa-icon> Increased API limits</p>
|
<p class="sponsor-feature"><fa-icon [icon]="['fas', 'check']"></fa-icon> Increased API limits</p>
|
||||||
<p class="sponsor-feature"><fa-icon [icon]="['fas', 'check']"></fa-icon> Co-branded instance</p>
|
<p class="sponsor-feature"><fa-icon [icon]="['fas', 'check']"></fa-icon> Co-branded instance</p>
|
||||||
<p class="sponsor-feature"><fa-icon [icon]="['fas', 'check']"></fa-icon> 99% service-level agreement</p>
|
<p class="sponsor-feature"><fa-icon [icon]="['fas', 'check']"></fa-icon> 99% service-level agreement</p>
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { Component } from '@angular/core';
|
import { Component, Input } from '@angular/core';
|
||||||
import { EnterpriseService } from '../../services/enterprise.service';
|
import { EnterpriseService } from '../../services/enterprise.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
@ -7,6 +7,8 @@ import { EnterpriseService } from '../../services/enterprise.service';
|
|||||||
styleUrls: ['./about-sponsors.component.scss'],
|
styleUrls: ['./about-sponsors.component.scss'],
|
||||||
})
|
})
|
||||||
export class AboutSponsorsComponent {
|
export class AboutSponsorsComponent {
|
||||||
|
@Input() host = 'https://mempool.space';
|
||||||
|
|
||||||
constructor(private enterpriseService: EnterpriseService) {
|
constructor(private enterpriseService: EnterpriseService) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@ import { Subscription, catchError, of, tap } from 'rxjs';
|
|||||||
import { StorageService } from '../../services/storage.service';
|
import { StorageService } from '../../services/storage.service';
|
||||||
import { Transaction } from '../../interfaces/electrs.interface';
|
import { Transaction } from '../../interfaces/electrs.interface';
|
||||||
import { nextRoundNumber } from '../../shared/common.utils';
|
import { nextRoundNumber } from '../../shared/common.utils';
|
||||||
|
import { ServicesApiServices } from '../../services/services-api.service';
|
||||||
import { AudioService } from '../../services/audio.service';
|
import { AudioService } from '../../services/audio.service';
|
||||||
|
|
||||||
export type AccelerationEstimate = {
|
export type AccelerationEstimate = {
|
||||||
@ -62,7 +63,7 @@ export class AcceleratePreviewComponent implements OnInit, OnDestroy, OnChanges
|
|||||||
maxRateOptions: RateOption[] = [];
|
maxRateOptions: RateOption[] = [];
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private apiService: ApiService,
|
private servicesApiService: ServicesApiServices,
|
||||||
private storageService: StorageService,
|
private storageService: StorageService,
|
||||||
private audioService: AudioService,
|
private audioService: AudioService,
|
||||||
private cd: ChangeDetectorRef
|
private cd: ChangeDetectorRef
|
||||||
@ -83,7 +84,7 @@ export class AcceleratePreviewComponent implements OnInit, OnDestroy, OnChanges
|
|||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
this.user = this.storageService.getAuth()?.user ?? null;
|
this.user = this.storageService.getAuth()?.user ?? null;
|
||||||
|
|
||||||
this.estimateSubscription = this.apiService.estimate$(this.tx.txid).pipe(
|
this.estimateSubscription = this.servicesApiService.estimate$(this.tx.txid).pipe(
|
||||||
tap((response) => {
|
tap((response) => {
|
||||||
if (response.status === 204) {
|
if (response.status === 204) {
|
||||||
this.estimate = undefined;
|
this.estimate = undefined;
|
||||||
@ -183,7 +184,7 @@ export class AcceleratePreviewComponent implements OnInit, OnDestroy, OnChanges
|
|||||||
if (this.accelerationSubscription) {
|
if (this.accelerationSubscription) {
|
||||||
this.accelerationSubscription.unsubscribe();
|
this.accelerationSubscription.unsubscribe();
|
||||||
}
|
}
|
||||||
this.accelerationSubscription = this.apiService.accelerate$(
|
this.accelerationSubscription = this.servicesApiService.accelerate$(
|
||||||
this.tx.txid,
|
this.tx.txid,
|
||||||
this.userBid
|
this.userBid
|
||||||
).subscribe({
|
).subscribe({
|
||||||
|
@ -2,7 +2,6 @@ import { ChangeDetectionStrategy, ChangeDetectorRef, Component, Inject, Input, L
|
|||||||
import { EChartsOption, graphic } from 'echarts';
|
import { EChartsOption, graphic } from 'echarts';
|
||||||
import { Observable, Subscription, combineLatest, fromEvent } from 'rxjs';
|
import { Observable, Subscription, combineLatest, fromEvent } from 'rxjs';
|
||||||
import { map, max, startWith, switchMap, tap } from 'rxjs/operators';
|
import { map, max, startWith, switchMap, tap } from 'rxjs/operators';
|
||||||
import { ApiService } from '../../../services/api.service';
|
|
||||||
import { SeoService } from '../../../services/seo.service';
|
import { SeoService } from '../../../services/seo.service';
|
||||||
import { formatNumber } from '@angular/common';
|
import { formatNumber } from '@angular/common';
|
||||||
import { UntypedFormBuilder, UntypedFormGroup } from '@angular/forms';
|
import { UntypedFormBuilder, UntypedFormGroup } from '@angular/forms';
|
||||||
@ -11,6 +10,8 @@ import { StorageService } from '../../../services/storage.service';
|
|||||||
import { MiningService } from '../../../services/mining.service';
|
import { MiningService } from '../../../services/mining.service';
|
||||||
import { ActivatedRoute } from '@angular/router';
|
import { ActivatedRoute } from '@angular/router';
|
||||||
import { Acceleration } from '../../../interfaces/node-api.interface';
|
import { Acceleration } from '../../../interfaces/node-api.interface';
|
||||||
|
import { ServicesApiServices } from '../../../services/services-api.service';
|
||||||
|
import { ApiService } from '../../../services/api.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-acceleration-fees-graph',
|
selector: 'app-acceleration-fees-graph',
|
||||||
@ -55,6 +56,7 @@ export class AccelerationFeesGraphComponent implements OnInit, OnDestroy {
|
|||||||
@Inject(LOCALE_ID) public locale: string,
|
@Inject(LOCALE_ID) public locale: string,
|
||||||
private seoService: SeoService,
|
private seoService: SeoService,
|
||||||
private apiService: ApiService,
|
private apiService: ApiService,
|
||||||
|
private servicesApiService: ServicesApiServices,
|
||||||
private formBuilder: UntypedFormBuilder,
|
private formBuilder: UntypedFormBuilder,
|
||||||
private storageService: StorageService,
|
private storageService: StorageService,
|
||||||
private miningService: MiningService,
|
private miningService: MiningService,
|
||||||
@ -73,7 +75,7 @@ export class AccelerationFeesGraphComponent implements OnInit, OnDestroy {
|
|||||||
this.timespan = this.miningWindowPreference;
|
this.timespan = this.miningWindowPreference;
|
||||||
|
|
||||||
this.statsObservable$ = combineLatest([
|
this.statsObservable$ = combineLatest([
|
||||||
(this.accelerations$ || this.apiService.getAccelerationHistory$({ timeframe: this.miningWindowPreference })),
|
(this.accelerations$ || this.servicesApiService.getAccelerationHistory$({ timeframe: this.miningWindowPreference })),
|
||||||
this.apiService.getHistoricalBlockFees$(this.miningWindowPreference),
|
this.apiService.getHistoricalBlockFees$(this.miningWindowPreference),
|
||||||
fromEvent(window, 'resize').pipe(startWith(null)),
|
fromEvent(window, 'resize').pipe(startWith(null)),
|
||||||
]).pipe(
|
]).pipe(
|
||||||
@ -103,7 +105,7 @@ export class AccelerationFeesGraphComponent implements OnInit, OnDestroy {
|
|||||||
this.isLoading = true;
|
this.isLoading = true;
|
||||||
this.storageService.setValue('miningWindowPreference', timespan);
|
this.storageService.setValue('miningWindowPreference', timespan);
|
||||||
this.timespan = timespan;
|
this.timespan = timespan;
|
||||||
return this.apiService.getAccelerationHistory$({});
|
return this.servicesApiService.getAccelerationHistory$({});
|
||||||
})
|
})
|
||||||
),
|
),
|
||||||
this.radioGroupForm.get('dateSpan').valueChanges.pipe(
|
this.radioGroupForm.get('dateSpan').valueChanges.pipe(
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
import { Component, OnInit, ChangeDetectionStrategy, Input, ChangeDetectorRef } from '@angular/core';
|
import { Component, OnInit, ChangeDetectionStrategy, Input, ChangeDetectorRef } from '@angular/core';
|
||||||
import { Observable, catchError, of, switchMap, tap } from 'rxjs';
|
import { Observable, catchError, of, switchMap, tap } from 'rxjs';
|
||||||
import { Acceleration, BlockExtended } from '../../../interfaces/node-api.interface';
|
import { Acceleration, BlockExtended } from '../../../interfaces/node-api.interface';
|
||||||
import { ApiService } from '../../../services/api.service';
|
|
||||||
import { StateService } from '../../../services/state.service';
|
import { StateService } from '../../../services/state.service';
|
||||||
import { WebsocketService } from '../../../services/websocket.service';
|
import { WebsocketService } from '../../../services/websocket.service';
|
||||||
|
import { ServicesApiServices } from '../../../services/services-api.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-accelerations-list',
|
selector: 'app-accelerations-list',
|
||||||
@ -26,7 +26,7 @@ export class AccelerationsListComponent implements OnInit {
|
|||||||
skeletonLines: number[] = [];
|
skeletonLines: number[] = [];
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private apiService: ApiService,
|
private servicesApiService: ServicesApiServices,
|
||||||
private websocketService: WebsocketService,
|
private websocketService: WebsocketService,
|
||||||
public stateService: StateService,
|
public stateService: StateService,
|
||||||
private cd: ChangeDetectorRef,
|
private cd: ChangeDetectorRef,
|
||||||
@ -41,7 +41,7 @@ export class AccelerationsListComponent implements OnInit {
|
|||||||
this.skeletonLines = this.widget === true ? [...Array(6).keys()] : [...Array(15).keys()];
|
this.skeletonLines = this.widget === true ? [...Array(6).keys()] : [...Array(15).keys()];
|
||||||
this.paginationMaxSize = window.matchMedia('(max-width: 670px)').matches ? 3 : 5;
|
this.paginationMaxSize = window.matchMedia('(max-width: 670px)').matches ? 3 : 5;
|
||||||
|
|
||||||
const accelerationObservable$ = this.accelerations$ || (this.pending ? this.apiService.getAccelerations$() : this.apiService.getAccelerationHistory$({ timeframe: '1m' }));
|
const accelerationObservable$ = this.accelerations$ || (this.pending ? this.servicesApiService.getAccelerations$() : this.servicesApiService.getAccelerationHistory$({ timeframe: '1m' }));
|
||||||
this.accelerationList$ = accelerationObservable$.pipe(
|
this.accelerationList$ = accelerationObservable$.pipe(
|
||||||
switchMap(accelerations => {
|
switchMap(accelerations => {
|
||||||
if (this.pending) {
|
if (this.pending) {
|
||||||
|
@ -3,12 +3,12 @@ import { SeoService } from '../../../services/seo.service';
|
|||||||
import { WebsocketService } from '../../../services/websocket.service';
|
import { WebsocketService } from '../../../services/websocket.service';
|
||||||
import { Acceleration, BlockExtended } from '../../../interfaces/node-api.interface';
|
import { Acceleration, BlockExtended } from '../../../interfaces/node-api.interface';
|
||||||
import { StateService } from '../../../services/state.service';
|
import { StateService } from '../../../services/state.service';
|
||||||
import { Observable, Subject, catchError, combineLatest, distinctUntilChanged, interval, map, of, share, startWith, switchMap, tap } from 'rxjs';
|
import { Observable, catchError, combineLatest, distinctUntilChanged, interval, map, of, share, startWith, switchMap, tap } from 'rxjs';
|
||||||
import { ApiService } from '../../../services/api.service';
|
|
||||||
import { Color } from '../../block-overview-graph/sprite-types';
|
import { Color } from '../../block-overview-graph/sprite-types';
|
||||||
import { hexToColor } from '../../block-overview-graph/utils';
|
import { hexToColor } from '../../block-overview-graph/utils';
|
||||||
import TxView from '../../block-overview-graph/tx-view';
|
import TxView from '../../block-overview-graph/tx-view';
|
||||||
import { feeLevels, mempoolFeeColors } from '../../../app.constants';
|
import { feeLevels, mempoolFeeColors } from '../../../app.constants';
|
||||||
|
import { ServicesApiServices } from '../../../services/services-api.service';
|
||||||
|
|
||||||
const acceleratedColor: Color = hexToColor('8F5FF6');
|
const acceleratedColor: Color = hexToColor('8F5FF6');
|
||||||
const normalColors = mempoolFeeColors.map(hex => hexToColor(hex + '5F'));
|
const normalColors = mempoolFeeColors.map(hex => hexToColor(hex + '5F'));
|
||||||
@ -35,7 +35,7 @@ export class AcceleratorDashboardComponent implements OnInit {
|
|||||||
constructor(
|
constructor(
|
||||||
private seoService: SeoService,
|
private seoService: SeoService,
|
||||||
private websocketService: WebsocketService,
|
private websocketService: WebsocketService,
|
||||||
private apiService: ApiService,
|
private serviceApiServices: ServicesApiServices,
|
||||||
private stateService: StateService,
|
private stateService: StateService,
|
||||||
) {
|
) {
|
||||||
this.seoService.setTitle($localize`:@@a681a4e2011bb28157689dbaa387de0dd0aa0c11:Accelerator Dashboard`);
|
this.seoService.setTitle($localize`:@@a681a4e2011bb28157689dbaa387de0dd0aa0c11:Accelerator Dashboard`);
|
||||||
@ -48,7 +48,7 @@ export class AcceleratorDashboardComponent implements OnInit {
|
|||||||
this.pendingAccelerations$ = interval(30000).pipe(
|
this.pendingAccelerations$ = interval(30000).pipe(
|
||||||
startWith(true),
|
startWith(true),
|
||||||
switchMap(() => {
|
switchMap(() => {
|
||||||
return this.apiService.getAccelerations$().pipe(
|
return this.serviceApiServices.getAccelerations$().pipe(
|
||||||
catchError(() => {
|
catchError(() => {
|
||||||
return of([]);
|
return of([]);
|
||||||
}),
|
}),
|
||||||
@ -60,7 +60,7 @@ export class AcceleratorDashboardComponent implements OnInit {
|
|||||||
this.accelerations$ = this.stateService.chainTip$.pipe(
|
this.accelerations$ = this.stateService.chainTip$.pipe(
|
||||||
distinctUntilChanged(),
|
distinctUntilChanged(),
|
||||||
switchMap(() => {
|
switchMap(() => {
|
||||||
return this.apiService.getAccelerationHistory$({ timeframe: '1m' }).pipe(
|
return this.serviceApiServices.getAccelerationHistory$({ timeframe: '1m' }).pipe(
|
||||||
catchError(() => {
|
catchError(() => {
|
||||||
return of([]);
|
return of([]);
|
||||||
}),
|
}),
|
||||||
@ -71,7 +71,7 @@ export class AcceleratorDashboardComponent implements OnInit {
|
|||||||
|
|
||||||
this.minedAccelerations$ = this.accelerations$.pipe(
|
this.minedAccelerations$ = this.accelerations$.pipe(
|
||||||
map(accelerations => {
|
map(accelerations => {
|
||||||
return accelerations.filter(acc => ['mined', 'completed'].includes(acc.status));
|
return accelerations.filter(acc => ['mined', 'completed', 'failed'].includes(acc.status));
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import { ChangeDetectionStrategy, Component, Input, OnInit } from '@angular/core';
|
import { ChangeDetectionStrategy, Component, Input, OnInit } from '@angular/core';
|
||||||
import { Observable, of } from 'rxjs';
|
import { Observable, of } from 'rxjs';
|
||||||
import { switchMap } from 'rxjs/operators';
|
import { switchMap } from 'rxjs/operators';
|
||||||
import { ApiService } from '../../../services/api.service';
|
|
||||||
import { Acceleration } from '../../../interfaces/node-api.interface';
|
import { Acceleration } from '../../../interfaces/node-api.interface';
|
||||||
|
import { ServicesApiServices } from '../../../services/services-api.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-pending-stats',
|
selector: 'app-pending-stats',
|
||||||
@ -15,11 +15,11 @@ export class PendingStatsComponent implements OnInit {
|
|||||||
public accelerationStats$: Observable<any>;
|
public accelerationStats$: Observable<any>;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private apiService: ApiService,
|
private servicesApiService: ServicesApiServices,
|
||||||
) { }
|
) { }
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
this.accelerationStats$ = (this.accelerations$ || this.apiService.getAccelerations$()).pipe(
|
this.accelerationStats$ = (this.accelerations$ || this.servicesApiService.getAccelerations$()).pipe(
|
||||||
switchMap(accelerations => {
|
switchMap(accelerations => {
|
||||||
let totalAccelerations = 0;
|
let totalAccelerations = 0;
|
||||||
let totalFeeDelta = 0;
|
let totalFeeDelta = 0;
|
||||||
|
@ -10,6 +10,7 @@ import { BlockExtended, TransactionStripped } from '../../interfaces/node-api.in
|
|||||||
import { ApiService } from '../../services/api.service';
|
import { ApiService } from '../../services/api.service';
|
||||||
import { seoDescriptionNetwork } from '../../shared/common.utils';
|
import { seoDescriptionNetwork } from '../../shared/common.utils';
|
||||||
import { BlockOverviewGraphComponent } from '../../components/block-overview-graph/block-overview-graph.component';
|
import { BlockOverviewGraphComponent } from '../../components/block-overview-graph/block-overview-graph.component';
|
||||||
|
import { ServicesApiServices } from '../../services/services-api.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-block-preview',
|
selector: 'app-block-preview',
|
||||||
@ -42,7 +43,8 @@ export class BlockPreviewComponent implements OnInit, OnDestroy {
|
|||||||
public stateService: StateService,
|
public stateService: StateService,
|
||||||
private seoService: SeoService,
|
private seoService: SeoService,
|
||||||
private openGraphService: OpenGraphService,
|
private openGraphService: OpenGraphService,
|
||||||
private apiService: ApiService
|
private apiService: ApiService,
|
||||||
|
private servicesApiService: ServicesApiServices,
|
||||||
) { }
|
) { }
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
@ -134,7 +136,7 @@ export class BlockPreviewComponent implements OnInit, OnDestroy {
|
|||||||
return of(transactions);
|
return of(transactions);
|
||||||
})
|
})
|
||||||
),
|
),
|
||||||
this.stateService.env.ACCELERATOR === true && block.height > 819500 ? this.apiService.getAccelerationHistory$({ blockHash: block.id }) : of([])
|
this.stateService.env.ACCELERATOR === true && block.height > 819500 ? this.servicesApiService.getAccelerationHistory$({ blockHash: block.id }) : of([])
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
|
@ -16,6 +16,7 @@ import { detectWebGL } from '../../shared/graphs.utils';
|
|||||||
import { seoDescriptionNetwork } from '../../shared/common.utils';
|
import { seoDescriptionNetwork } from '../../shared/common.utils';
|
||||||
import { PriceService, Price } from '../../services/price.service';
|
import { PriceService, Price } from '../../services/price.service';
|
||||||
import { CacheService } from '../../services/cache.service';
|
import { CacheService } from '../../services/cache.service';
|
||||||
|
import { ServicesApiServices } from '../../services/services-api.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-block',
|
selector: 'app-block',
|
||||||
@ -103,6 +104,7 @@ export class BlockComponent implements OnInit, OnDestroy {
|
|||||||
private apiService: ApiService,
|
private apiService: ApiService,
|
||||||
private priceService: PriceService,
|
private priceService: PriceService,
|
||||||
private cacheService: CacheService,
|
private cacheService: CacheService,
|
||||||
|
private servicesApiService: ServicesApiServices,
|
||||||
) {
|
) {
|
||||||
this.webGlEnabled = detectWebGL();
|
this.webGlEnabled = detectWebGL();
|
||||||
}
|
}
|
||||||
@ -329,7 +331,7 @@ export class BlockComponent implements OnInit, OnDestroy {
|
|||||||
return of(null);
|
return of(null);
|
||||||
})
|
})
|
||||||
),
|
),
|
||||||
this.stateService.env.ACCELERATOR === true && block.height > 819500 ? this.apiService.getAccelerationHistory$({ blockHash: block.id }) : of([])
|
this.stateService.env.ACCELERATOR === true && block.height > 819500 ? this.servicesApiService.getAccelerationHistory$({ blockHash: block.id }) : of([])
|
||||||
]);
|
]);
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
@ -2,8 +2,19 @@
|
|||||||
<div class="d-flex menu-click">
|
<div class="d-flex menu-click">
|
||||||
|
|
||||||
<nav class="scrollable menu-click">
|
<nav class="scrollable menu-click">
|
||||||
<span *ngIf="userAuth" class="menu-click">
|
<span *ngIf="user$ | async as user" class="menu-click">
|
||||||
<strong class="menu-click text-nowrap ellipsis">@ {{ userAuth.user.username }}</strong>
|
<span class="menu-click text-nowrap ellipsis">
|
||||||
|
<strong>
|
||||||
|
<span *ngIf="user.username.includes('@'); else usernamenospace">{{ user.username }}</span>
|
||||||
|
<ng-template #usernamenospace>@{{ user.username }}</ng-template>
|
||||||
|
</strong>
|
||||||
|
</span>
|
||||||
|
<span class="badge mr-1 badge-og" *ngIf="user.ogRank">
|
||||||
|
OG #{{ user.ogRank }}
|
||||||
|
</span>
|
||||||
|
<span class="badge mr-1 badge-default" [class]="'badge-' + user.subscription_tag" *ngIf="user.subscription_tag !== 'free'">
|
||||||
|
{{ user.subscription_tag.toUpperCase() }}
|
||||||
|
</span>
|
||||||
</span>
|
</span>
|
||||||
<a *ngIf="!userAuth" class="d-flex justify-content-center align-items-center nav-link m-0 menu-click" routerLink="/login" role="tab" (click)="onLinkClick('/login')">
|
<a *ngIf="!userAuth" class="d-flex justify-content-center align-items-center nav-link m-0 menu-click" routerLink="/login" role="tab" (click)="onLinkClick('/login')">
|
||||||
<fa-icon class="menu-click" [icon]="['fas', 'user-circle']" [fixedWidth]="true" style="font-size: 25px;margin-right: 15px;"></fa-icon>
|
<fa-icon class="menu-click" [icon]="['fas', 'user-circle']" [fixedWidth]="true" style="font-size: 25px;margin-right: 15px;"></fa-icon>
|
||||||
|
@ -56,3 +56,35 @@
|
|||||||
@media screen and (max-height: 450px) {
|
@media screen and (max-height: 450px) {
|
||||||
.sidenav a {font-size: 18px;}
|
.sidenav a {font-size: 18px;}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.badge-default {
|
||||||
|
background-color: black;
|
||||||
|
}
|
||||||
|
|
||||||
|
.badge-og {
|
||||||
|
background-color: #4a68b9;
|
||||||
|
}
|
||||||
|
|
||||||
|
.badge-pleb {
|
||||||
|
background-color: #3ccbe3;
|
||||||
|
}
|
||||||
|
|
||||||
|
.badge-chad {
|
||||||
|
background-color: #957d0b;
|
||||||
|
}
|
||||||
|
|
||||||
|
.badge-whale {
|
||||||
|
background-color: #653b9c;
|
||||||
|
}
|
||||||
|
|
||||||
|
.badge-silver {
|
||||||
|
background-color: #95a5a6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.badge-gold {
|
||||||
|
background-color: #f1c40f;
|
||||||
|
}
|
||||||
|
|
||||||
|
.badge-platinium {
|
||||||
|
background-color: #653b9c;
|
||||||
|
}
|
@ -1,10 +1,10 @@
|
|||||||
import { Component, OnInit, Input, Output, EventEmitter, HostListener, OnDestroy } from '@angular/core';
|
import { Component, OnInit, Input, Output, EventEmitter, HostListener, OnDestroy } from '@angular/core';
|
||||||
import { Observable } from 'rxjs';
|
import { Observable } from 'rxjs';
|
||||||
import { ApiService } from '../../services/api.service';
|
|
||||||
import { MenuGroup } from '../../interfaces/services.interface';
|
import { MenuGroup } from '../../interfaces/services.interface';
|
||||||
import { StorageService } from '../../services/storage.service';
|
import { StorageService } from '../../services/storage.service';
|
||||||
import { Router, NavigationStart } from '@angular/router';
|
import { Router, NavigationStart } from '@angular/router';
|
||||||
import { StateService } from '../../services/state.service';
|
import { StateService } from '../../services/state.service';
|
||||||
|
import { IUser, ServicesApiServices } from '../../services/services-api.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-menu',
|
selector: 'app-menu',
|
||||||
@ -18,11 +18,12 @@ export class MenuComponent implements OnInit, OnDestroy {
|
|||||||
@Output() menuToggled = new EventEmitter<boolean>();
|
@Output() menuToggled = new EventEmitter<boolean>();
|
||||||
|
|
||||||
userMenuGroups$: Observable<MenuGroup[]> | undefined;
|
userMenuGroups$: Observable<MenuGroup[]> | undefined;
|
||||||
|
user$: Observable<IUser | null>;
|
||||||
userAuth: any | undefined;
|
userAuth: any | undefined;
|
||||||
isServicesPage = false;
|
isServicesPage = false;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private apiService: ApiService,
|
private servicesApiServices: ServicesApiServices,
|
||||||
private storageService: StorageService,
|
private storageService: StorageService,
|
||||||
private router: Router,
|
private router: Router,
|
||||||
private stateService: StateService
|
private stateService: StateService
|
||||||
@ -32,7 +33,8 @@ export class MenuComponent implements OnInit, OnDestroy {
|
|||||||
this.userAuth = this.storageService.getAuth();
|
this.userAuth = this.storageService.getAuth();
|
||||||
|
|
||||||
if (this.stateService.env.GIT_COMMIT_HASH_MEMPOOL_SPACE) {
|
if (this.stateService.env.GIT_COMMIT_HASH_MEMPOOL_SPACE) {
|
||||||
this.userMenuGroups$ = this.apiService.getUserMenuGroups$();
|
this.userMenuGroups$ = this.servicesApiServices.getUserMenuGroups$();
|
||||||
|
this.user$ = this.servicesApiServices.userSubject$;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.isServicesPage = this.router.url.includes('/services/');
|
this.isServicesPage = this.router.url.includes('/services/');
|
||||||
@ -55,10 +57,10 @@ export class MenuComponent implements OnInit, OnDestroy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
logout(): void {
|
logout(): void {
|
||||||
this.apiService.logout$().subscribe(() => {
|
this.servicesApiServices.logout$().subscribe(() => {
|
||||||
this.loggedOut.emit(true);
|
this.loggedOut.emit(true);
|
||||||
if (this.stateService.env.GIT_COMMIT_HASH_MEMPOOL_SPACE) {
|
if (this.stateService.env.GIT_COMMIT_HASH_MEMPOOL_SPACE) {
|
||||||
this.userMenuGroups$ = this.apiService.getUserMenuGroups$();
|
this.userMenuGroups$ = this.servicesApiServices.getUserMenuGroups$();
|
||||||
this.router.navigateByUrl('/');
|
this.router.navigateByUrl('/');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -7,7 +7,6 @@ import {
|
|||||||
catchError,
|
catchError,
|
||||||
retryWhen,
|
retryWhen,
|
||||||
delay,
|
delay,
|
||||||
map,
|
|
||||||
mergeMap,
|
mergeMap,
|
||||||
tap
|
tap
|
||||||
} from 'rxjs/operators';
|
} from 'rxjs/operators';
|
||||||
@ -26,6 +25,7 @@ import { LiquidUnblinding } from './liquid-ublinding';
|
|||||||
import { RelativeUrlPipe } from '../../shared/pipes/relative-url/relative-url.pipe';
|
import { RelativeUrlPipe } from '../../shared/pipes/relative-url/relative-url.pipe';
|
||||||
import { Price, PriceService } from '../../services/price.service';
|
import { Price, PriceService } from '../../services/price.service';
|
||||||
import { isFeatureActive } from '../../bitcoin.utils';
|
import { isFeatureActive } from '../../bitcoin.utils';
|
||||||
|
import { ServicesApiServices } from '../../services/services-api.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-transaction',
|
selector: 'app-transaction',
|
||||||
@ -113,6 +113,7 @@ export class TransactionComponent implements OnInit, AfterViewInit, OnDestroy {
|
|||||||
private websocketService: WebsocketService,
|
private websocketService: WebsocketService,
|
||||||
private audioService: AudioService,
|
private audioService: AudioService,
|
||||||
private apiService: ApiService,
|
private apiService: ApiService,
|
||||||
|
private servicesApiService: ServicesApiServices,
|
||||||
private seoService: SeoService,
|
private seoService: SeoService,
|
||||||
private priceService: PriceService,
|
private priceService: PriceService,
|
||||||
private storageService: StorageService
|
private storageService: StorageService
|
||||||
@ -247,7 +248,7 @@ export class TransactionComponent implements OnInit, AfterViewInit, OnDestroy {
|
|||||||
this.accelerationInfo = null;
|
this.accelerationInfo = null;
|
||||||
}),
|
}),
|
||||||
switchMap((blockHash: string) => {
|
switchMap((blockHash: string) => {
|
||||||
return this.apiService.getAccelerationHistory$({ blockHash });
|
return this.servicesApiService.getAccelerationHistory$({ blockHash });
|
||||||
}),
|
}),
|
||||||
catchError(() => {
|
catchError(() => {
|
||||||
return of(null);
|
return of(null);
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { ChangeDetectionStrategy, Component, OnInit, ChangeDetectorRef } from '@angular/core';
|
import { ChangeDetectionStrategy, Component, OnInit, ChangeDetectorRef } from '@angular/core';
|
||||||
import { ActivatedRoute, ParamMap } from '@angular/router';
|
import { ActivatedRoute, ParamMap } from '@angular/router';
|
||||||
import { Observable, of, EMPTY } from 'rxjs';
|
import { Observable, of } from 'rxjs';
|
||||||
import { catchError, map, switchMap, tap, share } from 'rxjs/operators';
|
import { catchError, map, switchMap, tap, share } from 'rxjs/operators';
|
||||||
import { SeoService } from '../../services/seo.service';
|
import { SeoService } from '../../services/seo.service';
|
||||||
import { ApiService } from '../../services/api.service';
|
import { ApiService } from '../../services/api.service';
|
||||||
@ -8,6 +8,7 @@ import { LightningApiService } from '../lightning-api.service';
|
|||||||
import { GeolocationData } from '../../shared/components/geolocation/geolocation.component';
|
import { GeolocationData } from '../../shared/components/geolocation/geolocation.component';
|
||||||
import { ILiquidityAd, parseLiquidityAdHex } from './liquidity-ad';
|
import { ILiquidityAd, parseLiquidityAdHex } from './liquidity-ad';
|
||||||
import { haversineDistance, kmToMiles } from '../../../app/shared/common.utils';
|
import { haversineDistance, kmToMiles } from '../../../app/shared/common.utils';
|
||||||
|
import { ServicesApiServices } from '../../services/services-api.service';
|
||||||
|
|
||||||
interface CustomRecord {
|
interface CustomRecord {
|
||||||
type: string;
|
type: string;
|
||||||
@ -43,6 +44,7 @@ export class NodeComponent implements OnInit {
|
|||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private apiService: ApiService,
|
private apiService: ApiService,
|
||||||
|
private servicesApiService: ServicesApiServices,
|
||||||
private lightningApiService: LightningApiService,
|
private lightningApiService: LightningApiService,
|
||||||
private activatedRoute: ActivatedRoute,
|
private activatedRoute: ActivatedRoute,
|
||||||
private seoService: SeoService,
|
private seoService: SeoService,
|
||||||
@ -155,7 +157,7 @@ export class NodeComponent implements OnInit {
|
|||||||
this.nodeOwner$ = this.activatedRoute.paramMap
|
this.nodeOwner$ = this.activatedRoute.paramMap
|
||||||
.pipe(
|
.pipe(
|
||||||
switchMap((params: ParamMap) => {
|
switchMap((params: ParamMap) => {
|
||||||
return this.apiService.getNodeOwner$(params.get('public_key')).pipe(
|
return this.servicesApiService.getNodeOwner$(params.get('public_key')).pipe(
|
||||||
switchMap((response) => {
|
switchMap((response) => {
|
||||||
if (response.status === 204) {
|
if (response.status === 204) {
|
||||||
return of(false);
|
return of(false);
|
||||||
|
@ -4,14 +4,10 @@ import { CpfpInfo, OptimizedMempoolStats, AddressInformation, LiquidPegs, ITrans
|
|||||||
PoolStat, BlockExtended, TransactionStripped, RewardStats, AuditScore, BlockSizesAndWeights, RbfTree, BlockAudit, Acceleration, AccelerationHistoryParams, CurrentPegs, AuditStatus, FederationAddress, FederationUtxo, RecentPeg, PegsVolume } from '../interfaces/node-api.interface';
|
PoolStat, BlockExtended, TransactionStripped, RewardStats, AuditScore, BlockSizesAndWeights, RbfTree, BlockAudit, Acceleration, AccelerationHistoryParams, CurrentPegs, AuditStatus, FederationAddress, FederationUtxo, RecentPeg, PegsVolume } from '../interfaces/node-api.interface';
|
||||||
import { BehaviorSubject, Observable, catchError, filter, of, shareReplay, take, tap } from 'rxjs';
|
import { BehaviorSubject, Observable, catchError, filter, of, shareReplay, take, tap } from 'rxjs';
|
||||||
import { StateService } from './state.service';
|
import { StateService } from './state.service';
|
||||||
import { IBackendInfo, WebsocketResponse } from '../interfaces/websocket.interface';
|
import { Transaction } from '../interfaces/electrs.interface';
|
||||||
import { Outspend, Transaction } from '../interfaces/electrs.interface';
|
|
||||||
import { Conversion } from './price.service';
|
import { Conversion } from './price.service';
|
||||||
import { MenuGroup } from '../interfaces/services.interface';
|
|
||||||
import { StorageService } from './storage.service';
|
import { StorageService } from './storage.service';
|
||||||
|
import { WebsocketResponse } from '../interfaces/websocket.interface';
|
||||||
// Todo - move to config.json
|
|
||||||
const SERVICES_API_PREFIX = `/api/v1/services`;
|
|
||||||
|
|
||||||
@Injectable({
|
@Injectable({
|
||||||
providedIn: 'root'
|
providedIn: 'root'
|
||||||
@ -38,12 +34,6 @@ export class ApiService {
|
|||||||
}
|
}
|
||||||
this.apiBasePath = network ? '/' + network : '';
|
this.apiBasePath = network ? '/' + network : '';
|
||||||
});
|
});
|
||||||
|
|
||||||
if (this.stateService.env.GIT_COMMIT_HASH_MEMPOOL_SPACE) {
|
|
||||||
this.getServicesBackendInfo$().subscribe(version => {
|
|
||||||
this.stateService.servicesBackendInfo$.next(version);
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private generateCacheKey(functionName: string, params: any[]): string {
|
private generateCacheKey(functionName: string, params: any[]): string {
|
||||||
@ -418,62 +408,4 @@ export class ApiService {
|
|||||||
(timestamp ? `?timestamp=${timestamp}` : '')
|
(timestamp ? `?timestamp=${timestamp}` : '')
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Services
|
|
||||||
*/
|
|
||||||
|
|
||||||
getNodeOwner$(publicKey: string): Observable<any> {
|
|
||||||
let params = new HttpParams()
|
|
||||||
.set('node_public_key', publicKey);
|
|
||||||
return this.httpClient.get<any>(`${SERVICES_API_PREFIX}/lightning/claim/current`, { params, observe: 'response' });
|
|
||||||
}
|
|
||||||
|
|
||||||
getUserMenuGroups$(): Observable<MenuGroup[]> {
|
|
||||||
const auth = this.storageService.getAuth();
|
|
||||||
if (!auth) {
|
|
||||||
return of(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.httpClient.get<MenuGroup[]>(`${SERVICES_API_PREFIX}/account/menu`);
|
|
||||||
}
|
|
||||||
|
|
||||||
getUserInfo$(): Observable<any> {
|
|
||||||
const auth = this.storageService.getAuth();
|
|
||||||
if (!auth) {
|
|
||||||
return of(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.httpClient.get<any>(`${SERVICES_API_PREFIX}/account`);
|
|
||||||
}
|
|
||||||
|
|
||||||
logout$(): Observable<any> {
|
|
||||||
const auth = this.storageService.getAuth();
|
|
||||||
if (!auth) {
|
|
||||||
return of(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
localStorage.removeItem('auth');
|
|
||||||
return this.httpClient.post(`${SERVICES_API_PREFIX}/auth/logout`, {});
|
|
||||||
}
|
|
||||||
|
|
||||||
getServicesBackendInfo$(): Observable<IBackendInfo> {
|
|
||||||
return this.httpClient.get<IBackendInfo>(`${SERVICES_API_PREFIX}/version`);
|
|
||||||
}
|
|
||||||
|
|
||||||
estimate$(txInput: string) {
|
|
||||||
return this.httpClient.post<any>(`${SERVICES_API_PREFIX}/accelerator/estimate`, { txInput: txInput }, { observe: 'response' });
|
|
||||||
}
|
|
||||||
|
|
||||||
accelerate$(txInput: string, userBid: number) {
|
|
||||||
return this.httpClient.post<any>(`${SERVICES_API_PREFIX}/accelerator/accelerate`, { txInput: txInput, userBid: userBid });
|
|
||||||
}
|
|
||||||
|
|
||||||
getAccelerations$(): Observable<Acceleration[]> {
|
|
||||||
return this.httpClient.get<Acceleration[]>(`${SERVICES_API_PREFIX}/accelerator/accelerations`);
|
|
||||||
}
|
|
||||||
|
|
||||||
getAccelerationHistory$(params: AccelerationHistoryParams): Observable<Acceleration[]> {
|
|
||||||
return this.httpClient.get<Acceleration[]>(`${SERVICES_API_PREFIX}/accelerator/accelerations/history`, { params: { ...params } });
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
141
frontend/src/app/services/services-api.service.ts
Normal file
141
frontend/src/app/services/services-api.service.ts
Normal file
@ -0,0 +1,141 @@
|
|||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import { HttpClient, HttpParams } from '@angular/common/http';
|
||||||
|
import { StateService } from './state.service';
|
||||||
|
import { StorageService } from './storage.service';
|
||||||
|
import { MenuGroup } from '../interfaces/services.interface';
|
||||||
|
import { Observable, of, ReplaySubject, tap, catchError, share } from 'rxjs';
|
||||||
|
import { IBackendInfo } from '../interfaces/websocket.interface';
|
||||||
|
import { Acceleration, AccelerationHistoryParams } from '../interfaces/node-api.interface';
|
||||||
|
|
||||||
|
export type ProductType = 'enterprise' | 'community' | 'mining_pool' | 'custom';
|
||||||
|
export interface IUser {
|
||||||
|
username: string;
|
||||||
|
email: string | null;
|
||||||
|
passwordIsSet: boolean;
|
||||||
|
snsId: string;
|
||||||
|
type: ProductType;
|
||||||
|
subscription_tag: string;
|
||||||
|
status: 'pending' | 'verified' | 'disabled';
|
||||||
|
features: string | null;
|
||||||
|
fullName: string | null;
|
||||||
|
countryCode: string | null;
|
||||||
|
imageMd5: string;
|
||||||
|
ogRank: number | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Todo - move to config.json
|
||||||
|
const SERVICES_API_PREFIX = `/api/v1/services`;
|
||||||
|
|
||||||
|
@Injectable({
|
||||||
|
providedIn: 'root'
|
||||||
|
})
|
||||||
|
export class ServicesApiServices {
|
||||||
|
private apiBaseUrl: string; // base URL is protocol, hostname, and port
|
||||||
|
private apiBasePath: string; // network path is /testnet, etc. or '' for mainnet
|
||||||
|
|
||||||
|
userSubject$ = new ReplaySubject<IUser | null>(1);
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private httpClient: HttpClient,
|
||||||
|
private stateService: StateService,
|
||||||
|
private storageService: StorageService
|
||||||
|
) {
|
||||||
|
this.apiBaseUrl = ''; // use relative URL by default
|
||||||
|
if (!stateService.isBrowser) { // except when inside AU SSR process
|
||||||
|
this.apiBaseUrl = this.stateService.env.NGINX_PROTOCOL + '://' + this.stateService.env.NGINX_HOSTNAME + ':' + this.stateService.env.NGINX_PORT;
|
||||||
|
}
|
||||||
|
this.apiBasePath = ''; // assume mainnet by default
|
||||||
|
this.stateService.networkChanged$.subscribe((network) => {
|
||||||
|
if (network === 'bisq' && !this.stateService.env.BISQ_SEPARATE_BACKEND) {
|
||||||
|
network = '';
|
||||||
|
}
|
||||||
|
this.apiBasePath = network ? '/' + network : '';
|
||||||
|
});
|
||||||
|
|
||||||
|
if (this.stateService.env.GIT_COMMIT_HASH_MEMPOOL_SPACE) {
|
||||||
|
this.getServicesBackendInfo$().subscribe(version => {
|
||||||
|
this.stateService.servicesBackendInfo$.next(version);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
this.getUserInfo$().subscribe();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Do not call directly, userSubject$ instead
|
||||||
|
*/
|
||||||
|
private getUserInfo$() {
|
||||||
|
return this.getUserInfoApi$().pipe(
|
||||||
|
tap((user) => {
|
||||||
|
this.userSubject$.next(user);
|
||||||
|
}),
|
||||||
|
catchError((e) => {
|
||||||
|
if (e.error === 'User does not exists') {
|
||||||
|
this.userSubject$.next(null);
|
||||||
|
this.logout$().subscribe();
|
||||||
|
return of(null);
|
||||||
|
}
|
||||||
|
this.userSubject$.next(null);
|
||||||
|
return of(null);
|
||||||
|
}),
|
||||||
|
share(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Do not call directly, userSubject$ instead
|
||||||
|
*/
|
||||||
|
private getUserInfoApi$(): Observable<any> {
|
||||||
|
const auth = this.storageService.getAuth();
|
||||||
|
if (!auth) {
|
||||||
|
return of(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.httpClient.get<any>(`${SERVICES_API_PREFIX}/account`);
|
||||||
|
}
|
||||||
|
|
||||||
|
getNodeOwner$(publicKey: string): Observable<any> {
|
||||||
|
let params = new HttpParams()
|
||||||
|
.set('node_public_key', publicKey);
|
||||||
|
return this.httpClient.get<any>(`${SERVICES_API_PREFIX}/lightning/claim/current`, { params, observe: 'response' });
|
||||||
|
}
|
||||||
|
|
||||||
|
getUserMenuGroups$(): Observable<MenuGroup[]> {
|
||||||
|
const auth = this.storageService.getAuth();
|
||||||
|
if (!auth) {
|
||||||
|
return of(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.httpClient.get<MenuGroup[]>(`${SERVICES_API_PREFIX}/account/menu`);
|
||||||
|
}
|
||||||
|
|
||||||
|
logout$(): Observable<any> {
|
||||||
|
const auth = this.storageService.getAuth();
|
||||||
|
if (!auth) {
|
||||||
|
return of(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
localStorage.removeItem('auth');
|
||||||
|
return this.httpClient.post(`${SERVICES_API_PREFIX}/auth/logout`, {});
|
||||||
|
}
|
||||||
|
|
||||||
|
getServicesBackendInfo$(): Observable<IBackendInfo> {
|
||||||
|
return this.httpClient.get<IBackendInfo>(`${SERVICES_API_PREFIX}/version`);
|
||||||
|
}
|
||||||
|
|
||||||
|
estimate$(txInput: string) {
|
||||||
|
return this.httpClient.post<any>(`${SERVICES_API_PREFIX}/accelerator/estimate`, { txInput: txInput }, { observe: 'response' });
|
||||||
|
}
|
||||||
|
|
||||||
|
accelerate$(txInput: string, userBid: number) {
|
||||||
|
return this.httpClient.post<any>(`${SERVICES_API_PREFIX}/accelerator/accelerate`, { txInput: txInput, userBid: userBid });
|
||||||
|
}
|
||||||
|
|
||||||
|
getAccelerations$(): Observable<Acceleration[]> {
|
||||||
|
return this.httpClient.get<Acceleration[]>(`${SERVICES_API_PREFIX}/accelerator/accelerations`);
|
||||||
|
}
|
||||||
|
|
||||||
|
getAccelerationHistory$(params: AccelerationHistoryParams): Observable<Acceleration[]> {
|
||||||
|
return this.httpClient.get<Acceleration[]>(`${SERVICES_API_PREFIX}/accelerator/accelerations/history`, { params: { ...params } });
|
||||||
|
}
|
||||||
|
}
|
@ -94,7 +94,7 @@
|
|||||||
<div class="col-sm-12">
|
<div class="col-sm-12">
|
||||||
<p *ngIf="officialMempoolSpace">
|
<p *ngIf="officialMempoolSpace">
|
||||||
<span>{{ (backendInfo$ | async)?.hostname }} (v{{ (backendInfo$ | async )?.version }}) [<a target="_blank" href="https://github.com/mempool/mempool/commit/{{ (backendInfo$ | async )?.gitCommit | slice:0:8 }}">{{ (backendInfo$ | async )?.gitCommit | slice:0:8 }}</a>]</span>
|
<span>{{ (backendInfo$ | async)?.hostname }} (v{{ (backendInfo$ | async )?.version }}) [<a target="_blank" href="https://github.com/mempool/mempool/commit/{{ (backendInfo$ | async )?.gitCommit | slice:0:8 }}">{{ (backendInfo$ | async )?.gitCommit | slice:0:8 }}</a>]</span>
|
||||||
<span *ngIf="stateService.env.GIT_COMMIT_HASH_MEMPOOL_SPACE"> - (v{{ (servicesBackendInfo$ | async )?.version }}) [{{ (servicesBackendInfo$ | async )?.gitCommit | slice:0:8 }}]</span>
|
<span *ngIf="stateService.env.GIT_COMMIT_HASH_MEMPOOL_SPACE">[{{ (servicesBackendInfo$ | async )?.gitCommit | slice:0:8 }}]</span>
|
||||||
</p>
|
</p>
|
||||||
<p *ngIf="!officialMempoolSpace">v{{ packetJsonVersion }} [<a target="_blank" href="https://github.com/mempool/mempool/commit/{{ frontendGitCommitHash }}">{{ frontendGitCommitHash }}</a>]</p>
|
<p *ngIf="!officialMempoolSpace">v{{ packetJsonVersion }} [<a target="_blank" href="https://github.com/mempool/mempool/commit/{{ frontendGitCommitHash }}">{{ frontendGitCommitHash }}</a>]</p>
|
||||||
</div>
|
</div>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user