diff --git a/frontend/src/app/app.module.ts b/frontend/src/app/app.module.ts index 378ef11ed..6b7ec7f51 100644 --- a/frontend/src/app/app.module.ts +++ b/frontend/src/app/app.module.ts @@ -22,6 +22,7 @@ import { FiatCurrencyPipe } from './shared/pipes/fiat-currency.pipe'; import { ShortenStringPipe } from './shared/pipes/shorten-string-pipe/shorten-string.pipe'; import { CapAddressPipe } from './shared/pipes/cap-address-pipe/cap-address-pipe'; import { AppPreloadingStrategy } from './app.preloading-strategy'; +import { ServicesApiServices } from './services/services-api.service'; const providers = [ ElectrsApiService, @@ -40,6 +41,7 @@ const providers = [ FiatCurrencyPipe, CapAddressPipe, AppPreloadingStrategy, + ServicesApiServices, { provide: HTTP_INTERCEPTORS, useClass: HttpCacheInterceptor, multi: true } ]; diff --git a/frontend/src/app/components/accelerate-preview/accelerate-preview.component.ts b/frontend/src/app/components/accelerate-preview/accelerate-preview.component.ts index f2224841a..45e50346a 100644 --- a/frontend/src/app/components/accelerate-preview/accelerate-preview.component.ts +++ b/frontend/src/app/components/accelerate-preview/accelerate-preview.component.ts @@ -4,6 +4,7 @@ import { Subscription, catchError, of, tap } from 'rxjs'; import { StorageService } from '../../services/storage.service'; import { Transaction } from '../../interfaces/electrs.interface'; import { nextRoundNumber } from '../../shared/common.utils'; +import { ServicesApiServices } from '../../services/services-api.service'; export type AccelerationEstimate = { txSummary: TxSummary; @@ -61,7 +62,7 @@ export class AcceleratePreviewComponent implements OnInit, OnDestroy, OnChanges maxRateOptions: RateOption[] = []; constructor( - private apiService: ApiService, + private servicesApiService: ServicesApiServices, private storageService: StorageService, private cd: ChangeDetectorRef ) { } @@ -81,7 +82,7 @@ export class AcceleratePreviewComponent implements OnInit, OnDestroy, OnChanges ngOnInit() { 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) => { if (response.status === 204) { this.estimate = undefined; @@ -181,7 +182,7 @@ export class AcceleratePreviewComponent implements OnInit, OnDestroy, OnChanges if (this.accelerationSubscription) { this.accelerationSubscription.unsubscribe(); } - this.accelerationSubscription = this.apiService.accelerate$( + this.accelerationSubscription = this.servicesApiService.accelerate$( this.tx.txid, this.userBid ).subscribe({ diff --git a/frontend/src/app/components/acceleration/acceleration-fees-graph/acceleration-fees-graph.component.ts b/frontend/src/app/components/acceleration/acceleration-fees-graph/acceleration-fees-graph.component.ts index d27b10690..a51476dca 100644 --- a/frontend/src/app/components/acceleration/acceleration-fees-graph/acceleration-fees-graph.component.ts +++ b/frontend/src/app/components/acceleration/acceleration-fees-graph/acceleration-fees-graph.component.ts @@ -1,8 +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 } from 'rxjs'; -import { map, max, startWith, switchMap, tap } from 'rxjs/operators'; -import { ApiService } from '../../../services/api.service'; +import { map, startWith, switchMap, tap } from 'rxjs/operators'; import { SeoService } from '../../../services/seo.service'; import { formatNumber } from '@angular/common'; import { UntypedFormBuilder, UntypedFormGroup } from '@angular/forms'; @@ -11,6 +10,8 @@ import { StorageService } from '../../../services/storage.service'; 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', @@ -54,6 +55,7 @@ export class AccelerationFeesGraphComponent implements OnInit, OnDestroy { @Inject(LOCALE_ID) public locale: string, private seoService: SeoService, private apiService: ApiService, + private servicesApiService: ServicesApiServices, private formBuilder: UntypedFormBuilder, private storageService: StorageService, private miningService: MiningService, @@ -73,7 +75,7 @@ export class AccelerationFeesGraphComponent implements OnInit, OnDestroy { this.timespan = this.miningWindowPreference; this.statsObservable$ = combineLatest([ - (this.accelerations$ || this.apiService.getAccelerationHistory$({ timeframe: this.miningWindowPreference })), + (this.accelerations$ || this.servicesApiService.getAccelerationHistory$({ timeframe: this.miningWindowPreference })), this.apiService.getHistoricalBlockFees$(this.miningWindowPreference), ]).pipe( tap(([accelerations, blockFeesResponse]) => { @@ -101,7 +103,7 @@ export class AccelerationFeesGraphComponent implements OnInit, OnDestroy { this.isLoading = true; this.storageService.setValue('miningWindowPreference', timespan); this.timespan = timespan; - return this.apiService.getAccelerationHistory$({}); + return this.servicesApiService.getAccelerationHistory$({}); }) ), this.radioGroupForm.get('dateSpan').valueChanges.pipe( diff --git a/frontend/src/app/components/acceleration/accelerations-list/accelerations-list.component.ts b/frontend/src/app/components/acceleration/accelerations-list/accelerations-list.component.ts index ddd89d31c..d53de7c1d 100644 --- a/frontend/src/app/components/acceleration/accelerations-list/accelerations-list.component.ts +++ b/frontend/src/app/components/acceleration/accelerations-list/accelerations-list.component.ts @@ -1,9 +1,9 @@ import { Component, OnInit, ChangeDetectionStrategy, Input, ChangeDetectorRef } from '@angular/core'; import { Observable, catchError, of, switchMap, tap } from 'rxjs'; import { Acceleration, BlockExtended } from '../../../interfaces/node-api.interface'; -import { ApiService } from '../../../services/api.service'; import { StateService } from '../../../services/state.service'; import { WebsocketService } from '../../../services/websocket.service'; +import { ServicesApiServices } from '../../../services/services-api.service'; @Component({ selector: 'app-accelerations-list', @@ -26,7 +26,7 @@ export class AccelerationsListComponent implements OnInit { skeletonLines: number[] = []; constructor( - private apiService: ApiService, + private servicesApiService: ServicesApiServices, private websocketService: WebsocketService, public stateService: StateService, private cd: ChangeDetectorRef, @@ -41,7 +41,7 @@ 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.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( switchMap(accelerations => { if (this.pending) { diff --git a/frontend/src/app/components/acceleration/accelerator-dashboard/accelerator-dashboard.component.ts b/frontend/src/app/components/acceleration/accelerator-dashboard/accelerator-dashboard.component.ts index 79a77a600..baeacf3cd 100644 --- a/frontend/src/app/components/acceleration/accelerator-dashboard/accelerator-dashboard.component.ts +++ b/frontend/src/app/components/acceleration/accelerator-dashboard/accelerator-dashboard.component.ts @@ -3,12 +3,12 @@ import { SeoService } from '../../../services/seo.service'; import { WebsocketService } from '../../../services/websocket.service'; import { Acceleration, BlockExtended } from '../../../interfaces/node-api.interface'; import { StateService } from '../../../services/state.service'; -import { Observable, Subject, catchError, combineLatest, distinctUntilChanged, interval, map, of, share, startWith, switchMap, tap } from 'rxjs'; -import { ApiService } from '../../../services/api.service'; +import { Observable, catchError, combineLatest, distinctUntilChanged, interval, map, of, share, startWith, switchMap, tap } from 'rxjs'; import { Color } from '../../block-overview-graph/sprite-types'; import { hexToColor } from '../../block-overview-graph/utils'; import TxView from '../../block-overview-graph/tx-view'; import { feeLevels, mempoolFeeColors } from '../../../app.constants'; +import { ServicesApiServices } from '../../../services/services-api.service'; const acceleratedColor: Color = hexToColor('8F5FF6'); const normalColors = mempoolFeeColors.map(hex => hexToColor(hex + '5F')); @@ -33,7 +33,7 @@ export class AcceleratorDashboardComponent implements OnInit { constructor( private seoService: SeoService, private websocketService: WebsocketService, - private apiService: ApiService, + private serviceApiServices: ServicesApiServices, private stateService: StateService, ) { this.seoService.setTitle($localize`:@@a681a4e2011bb28157689dbaa387de0dd0aa0c11:Accelerator Dashboard`); @@ -45,7 +45,7 @@ export class AcceleratorDashboardComponent implements OnInit { this.pendingAccelerations$ = interval(30000).pipe( startWith(true), switchMap(() => { - return this.apiService.getAccelerations$(); + return this.serviceApiServices.getAccelerations$(); }), catchError((e) => { return of([]); @@ -56,7 +56,7 @@ export class AcceleratorDashboardComponent implements OnInit { this.accelerations$ = this.stateService.chainTip$.pipe( distinctUntilChanged(), switchMap((chainTip) => { - return this.apiService.getAccelerationHistory$({ timeframe: '1m' }); + return this.serviceApiServices.getAccelerationHistory$({ timeframe: '1m' }); }), catchError((e) => { return of([]); diff --git a/frontend/src/app/components/acceleration/pending-stats/pending-stats.component.ts b/frontend/src/app/components/acceleration/pending-stats/pending-stats.component.ts index f344c37a0..ed7061156 100644 --- a/frontend/src/app/components/acceleration/pending-stats/pending-stats.component.ts +++ b/frontend/src/app/components/acceleration/pending-stats/pending-stats.component.ts @@ -1,8 +1,8 @@ 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 { Acceleration } from '../../../interfaces/node-api.interface'; +import { ServicesApiServices } from '../../../services/services-api.service'; @Component({ selector: 'app-pending-stats', @@ -15,11 +15,11 @@ export class PendingStatsComponent implements OnInit { public accelerationStats$: Observable; constructor( - private apiService: ApiService, + private servicesApiService: ServicesApiServices, ) { } ngOnInit(): void { - this.accelerationStats$ = (this.accelerations$ || this.apiService.getAccelerations$()).pipe( + this.accelerationStats$ = (this.accelerations$ || this.servicesApiService.getAccelerations$()).pipe( switchMap(accelerations => { let totalAccelerations = 0; let totalFeeDelta = 0; diff --git a/frontend/src/app/components/menu/menu.component.ts b/frontend/src/app/components/menu/menu.component.ts index 28ba0a1ad..e3f66ce25 100644 --- a/frontend/src/app/components/menu/menu.component.ts +++ b/frontend/src/app/components/menu/menu.component.ts @@ -1,10 +1,10 @@ import { Component, OnInit, Input, Output, EventEmitter, HostListener, OnDestroy } from '@angular/core'; import { Observable } from 'rxjs'; -import { ApiService } from '../../services/api.service'; import { MenuGroup } from '../../interfaces/services.interface'; import { StorageService } from '../../services/storage.service'; import { Router, NavigationStart } from '@angular/router'; import { StateService } from '../../services/state.service'; +import { IUser, ServicesApiServices } from '../../services/services-api.service'; @Component({ selector: 'app-menu', @@ -18,11 +18,12 @@ export class MenuComponent implements OnInit, OnDestroy { @Output() menuToggled = new EventEmitter(); userMenuGroups$: Observable | undefined; + user$: Observable; userAuth: any | undefined; isServicesPage = false; constructor( - private apiService: ApiService, + private servicesApiServices: ServicesApiServices, private storageService: StorageService, private router: Router, private stateService: StateService @@ -32,7 +33,8 @@ export class MenuComponent implements OnInit, OnDestroy { this.userAuth = this.storageService.getAuth(); 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/'); @@ -55,10 +57,10 @@ export class MenuComponent implements OnInit, OnDestroy { } logout(): void { - this.apiService.logout$().subscribe(() => { + this.servicesApiServices.logout$().subscribe(() => { this.loggedOut.emit(true); if (this.stateService.env.GIT_COMMIT_HASH_MEMPOOL_SPACE) { - this.userMenuGroups$ = this.apiService.getUserMenuGroups$(); + this.userMenuGroups$ = this.servicesApiServices.getUserMenuGroups$(); this.router.navigateByUrl('/'); } }); diff --git a/frontend/src/app/components/transaction/transaction.component.ts b/frontend/src/app/components/transaction/transaction.component.ts index ae3a950bd..c12c91eb1 100644 --- a/frontend/src/app/components/transaction/transaction.component.ts +++ b/frontend/src/app/components/transaction/transaction.component.ts @@ -7,7 +7,6 @@ import { catchError, retryWhen, delay, - map, mergeMap, tap } from 'rxjs/operators'; @@ -26,6 +25,7 @@ import { LiquidUnblinding } from './liquid-ublinding'; import { RelativeUrlPipe } from '../../shared/pipes/relative-url/relative-url.pipe'; import { Price, PriceService } from '../../services/price.service'; import { isFeatureActive } from '../../bitcoin.utils'; +import { ServicesApiServices } from '../../services/services-api.service'; @Component({ selector: 'app-transaction', @@ -113,6 +113,7 @@ export class TransactionComponent implements OnInit, AfterViewInit, OnDestroy { private websocketService: WebsocketService, private audioService: AudioService, private apiService: ApiService, + private servicesApiService: ServicesApiServices, private seoService: SeoService, private priceService: PriceService, private storageService: StorageService @@ -246,7 +247,7 @@ export class TransactionComponent implements OnInit, AfterViewInit, OnDestroy { this.accelerationInfo = null; }), switchMap((blockHash: string) => { - return this.apiService.getAccelerationHistory$({ blockHash }); + return this.servicesApiService.getAccelerationHistory$({ blockHash }); }), catchError(() => { return of(null); diff --git a/frontend/src/app/lightning/node/node.component.ts b/frontend/src/app/lightning/node/node.component.ts index 56f48bf65..cb465f0b2 100644 --- a/frontend/src/app/lightning/node/node.component.ts +++ b/frontend/src/app/lightning/node/node.component.ts @@ -1,6 +1,6 @@ import { ChangeDetectionStrategy, Component, OnInit, ChangeDetectorRef } from '@angular/core'; 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 { SeoService } from '../../services/seo.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 { ILiquidityAd, parseLiquidityAdHex } from './liquidity-ad'; import { haversineDistance, kmToMiles } from '../../../app/shared/common.utils'; +import { ServicesApiServices } from '../../services/services-api.service'; interface CustomRecord { type: string; @@ -43,6 +44,7 @@ export class NodeComponent implements OnInit { constructor( private apiService: ApiService, + private servicesApiService: ServicesApiServices, private lightningApiService: LightningApiService, private activatedRoute: ActivatedRoute, private seoService: SeoService, @@ -155,7 +157,7 @@ export class NodeComponent implements OnInit { this.nodeOwner$ = this.activatedRoute.paramMap .pipe( switchMap((params: ParamMap) => { - return this.apiService.getNodeOwner$(params.get('public_key')).pipe( + return this.servicesApiService.getNodeOwner$(params.get('public_key')).pipe( switchMap((response) => { if (response.status === 204) { return of(false); diff --git a/frontend/src/app/services/api.service.ts b/frontend/src/app/services/api.service.ts index 854d15c2a..e5048d619 100644 --- a/frontend/src/app/services/api.service.ts +++ b/frontend/src/app/services/api.service.ts @@ -1,17 +1,13 @@ import { Injectable } from '@angular/core'; import { HttpClient, HttpParams, HttpResponse } from '@angular/common/http'; import { CpfpInfo, OptimizedMempoolStats, AddressInformation, LiquidPegs, ITranslators, - PoolStat, BlockExtended, TransactionStripped, RewardStats, AuditScore, BlockSizesAndWeights, RbfTree, BlockAudit, Acceleration, AccelerationHistoryParams } from '../interfaces/node-api.interface'; + PoolStat, BlockExtended, TransactionStripped, RewardStats, AuditScore, BlockSizesAndWeights, RbfTree, BlockAudit } from '../interfaces/node-api.interface'; import { BehaviorSubject, Observable, catchError, filter, of, shareReplay, take, tap } from 'rxjs'; import { StateService } from './state.service'; -import { IBackendInfo, WebsocketResponse } from '../interfaces/websocket.interface'; -import { Outspend, Transaction } from '../interfaces/electrs.interface'; +import { Transaction } from '../interfaces/electrs.interface'; import { Conversion } from './price.service'; -import { MenuGroup } from '../interfaces/services.interface'; import { StorageService } from './storage.service'; - -// Todo - move to config.json -const SERVICES_API_PREFIX = `/api/v1/services`; +import { WebsocketResponse } from '../interfaces/websocket.interface'; @Injectable({ providedIn: 'root' @@ -38,12 +34,6 @@ export class ApiService { } 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 { @@ -378,62 +368,4 @@ export class ApiService { (timestamp ? `?timestamp=${timestamp}` : '') ); } - - /** - * Services - */ - - getNodeOwner$(publicKey: string): Observable { - let params = new HttpParams() - .set('node_public_key', publicKey); - return this.httpClient.get(`${SERVICES_API_PREFIX}/lightning/claim/current`, { params, observe: 'response' }); - } - - getUserMenuGroups$(): Observable { - const auth = this.storageService.getAuth(); - if (!auth) { - return of(null); - } - - return this.httpClient.get(`${SERVICES_API_PREFIX}/account/menu`); - } - - getUserInfo$(): Observable { - const auth = this.storageService.getAuth(); - if (!auth) { - return of(null); - } - - return this.httpClient.get(`${SERVICES_API_PREFIX}/account`); - } - - logout$(): Observable { - const auth = this.storageService.getAuth(); - if (!auth) { - return of(null); - } - - localStorage.removeItem('auth'); - return this.httpClient.post(`${SERVICES_API_PREFIX}/auth/logout`, {}); - } - - getServicesBackendInfo$(): Observable { - return this.httpClient.get(`${SERVICES_API_PREFIX}/version`); - } - - estimate$(txInput: string) { - return this.httpClient.post(`${SERVICES_API_PREFIX}/accelerator/estimate`, { txInput: txInput }, { observe: 'response' }); - } - - accelerate$(txInput: string, userBid: number) { - return this.httpClient.post(`${SERVICES_API_PREFIX}/accelerator/accelerate`, { txInput: txInput, userBid: userBid }); - } - - getAccelerations$(): Observable { - return this.httpClient.get(`${SERVICES_API_PREFIX}/accelerator/accelerations`); - } - - getAccelerationHistory$(params: AccelerationHistoryParams): Observable { - return this.httpClient.get(`${SERVICES_API_PREFIX}/accelerator/accelerations/history`, { params: { ...params } }); - } } diff --git a/frontend/src/app/services/services-api.service.ts b/frontend/src/app/services/services-api.service.ts new file mode 100644 index 000000000..1c350c37b --- /dev/null +++ b/frontend/src/app/services/services-api.service.ts @@ -0,0 +1,140 @@ +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; +} + +// 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(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 { + const auth = this.storageService.getAuth(); + if (!auth) { + return of(null); + } + + return this.httpClient.get(`${SERVICES_API_PREFIX}/account`); + } + + getNodeOwner$(publicKey: string): Observable { + let params = new HttpParams() + .set('node_public_key', publicKey); + return this.httpClient.get(`${SERVICES_API_PREFIX}/lightning/claim/current`, { params, observe: 'response' }); + } + + getUserMenuGroups$(): Observable { + const auth = this.storageService.getAuth(); + if (!auth) { + return of(null); + } + + return this.httpClient.get(`${SERVICES_API_PREFIX}/account/menu`); + } + + logout$(): Observable { + const auth = this.storageService.getAuth(); + if (!auth) { + return of(null); + } + + localStorage.removeItem('auth'); + return this.httpClient.post(`${SERVICES_API_PREFIX}/auth/logout`, {}); + } + + getServicesBackendInfo$(): Observable { + return this.httpClient.get(`${SERVICES_API_PREFIX}/version`); + } + + estimate$(txInput: string) { + return this.httpClient.post(`${SERVICES_API_PREFIX}/accelerator/estimate`, { txInput: txInput }, { observe: 'response' }); + } + + accelerate$(txInput: string, userBid: number) { + return this.httpClient.post(`${SERVICES_API_PREFIX}/accelerator/accelerate`, { txInput: txInput, userBid: userBid }); + } + + getAccelerations$(): Observable { + return this.httpClient.get(`${SERVICES_API_PREFIX}/accelerator/accelerations`); + } + + getAccelerationHistory$(params: AccelerationHistoryParams): Observable { + return this.httpClient.get(`${SERVICES_API_PREFIX}/accelerator/accelerations/history`, { params: { ...params } }); + } +}