Merge branch 'master' into natsoni/use-adjusted-time-avg
This commit is contained in:
@@ -1,14 +1,14 @@
|
||||
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, CurrentPegs, AuditStatus, FederationAddress, FederationUtxo, RecentPeg, PegsVolume, AccelerationInfo, TestMempoolAcceptResult } from '../interfaces/node-api.interface';
|
||||
RbfTree, BlockAudit, CurrentPegs, AuditStatus, FederationAddress, FederationUtxo, RecentPeg, PegsVolume, AccelerationInfo, TestMempoolAcceptResult, WalletAddress, SubmitPackageResult } from '../interfaces/node-api.interface';
|
||||
import { BehaviorSubject, Observable, catchError, filter, map, of, shareReplay, take, tap } from 'rxjs';
|
||||
import { StateService } from './state.service';
|
||||
import { Transaction } from '../interfaces/electrs.interface';
|
||||
import { Conversion } from './price.service';
|
||||
import { StorageService } from './storage.service';
|
||||
import { WebsocketResponse } from '../interfaces/websocket.interface';
|
||||
import { TxAuditStatus } from '../components/transaction/transaction.component';
|
||||
import { StateService } from '@app/services/state.service';
|
||||
import { Transaction } from '@interfaces/electrs.interface';
|
||||
import { Conversion } from '@app/services/price.service';
|
||||
import { StorageService } from '@app/services/storage.service';
|
||||
import { WebsocketResponse } from '@interfaces/websocket.interface';
|
||||
import { TxAuditStatus } from '@components/transaction/transaction.component';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
@@ -18,6 +18,7 @@ export class ApiService {
|
||||
private apiBasePath: string; // network path is /testnet, etc. or '' for mainnet
|
||||
|
||||
private requestCache = new Map<string, { subject: BehaviorSubject<any>, expiry: number }>;
|
||||
public blockSummaryLoaded: { [hash: string]: boolean } = {};
|
||||
public blockAuditLoaded: { [hash: string]: boolean } = {};
|
||||
|
||||
constructor(
|
||||
@@ -244,6 +245,19 @@ export class ApiService {
|
||||
return this.httpClient.post<TestMempoolAcceptResult[]>(this.apiBaseUrl + this.apiBasePath + `/api/txs/test${maxfeerate != null ? '?maxfeerate=' + maxfeerate.toFixed(8) : ''}`, rawTxs);
|
||||
}
|
||||
|
||||
submitPackage$(rawTxs: string[], maxfeerate?: number, maxburnamount?: number): Observable<SubmitPackageResult> {
|
||||
const queryParams = [];
|
||||
|
||||
if (maxfeerate) {
|
||||
queryParams.push(`maxfeerate=${maxfeerate}`);
|
||||
}
|
||||
|
||||
if (maxburnamount) {
|
||||
queryParams.push(`maxburnamount=${maxburnamount}`);
|
||||
}
|
||||
return this.httpClient.post<SubmitPackageResult>(this.apiBaseUrl + this.apiBasePath + '/api/v1/txs/package' + (queryParams.length > 0 ? `?${queryParams.join('&')}` : ''), rawTxs);
|
||||
}
|
||||
|
||||
getTransactionStatus$(txid: string): Observable<any> {
|
||||
return this.httpClient.get<any>(this.apiBaseUrl + this.apiBasePath + '/api/tx/' + txid + '/status');
|
||||
}
|
||||
@@ -305,9 +319,14 @@ export class ApiService {
|
||||
}
|
||||
|
||||
getStrippedBlockTransactions$(hash: string): Observable<TransactionStripped[]> {
|
||||
this.setBlockSummaryLoaded(hash);
|
||||
return this.httpClient.get<TransactionStripped[]>(this.apiBaseUrl + this.apiBasePath + '/api/v1/block/' + hash + '/summary');
|
||||
}
|
||||
|
||||
getStrippedBlockTransaction$(hash: string, txid: string): Observable<TransactionStripped> {
|
||||
return this.httpClient.get<TransactionStripped>(this.apiBaseUrl + this.apiBasePath + '/api/v1/block/' + hash + '/tx/' + txid + '/summary');
|
||||
}
|
||||
|
||||
getDifficultyAdjustments$(interval: string | undefined): Observable<any> {
|
||||
return this.httpClient.get<any[]>(
|
||||
this.apiBaseUrl + this.apiBasePath + `/api/v1/mining/difficulty-adjustments` +
|
||||
@@ -504,6 +523,12 @@ export class ApiService {
|
||||
);
|
||||
}
|
||||
|
||||
getWallet$(walletName: string): Observable<Record<string, WalletAddress>> {
|
||||
return this.httpClient.get<Record<string, WalletAddress>>(
|
||||
this.apiBaseUrl + this.apiBasePath + `/api/v1/wallet/${walletName}`
|
||||
);
|
||||
}
|
||||
|
||||
getAccelerationsByPool$(slug: string): Observable<AccelerationInfo[]> {
|
||||
return this.httpClient.get<AccelerationInfo[]>(
|
||||
this.apiBaseUrl + this.apiBasePath + `/api/v1/accelerations/pool/${slug}`
|
||||
@@ -548,4 +573,12 @@ export class ApiService {
|
||||
getBlockAuditLoaded(hash) {
|
||||
return this.blockAuditLoaded[hash];
|
||||
}
|
||||
|
||||
async setBlockSummaryLoaded(hash: string) {
|
||||
this.blockSummaryLoaded[hash] = true;
|
||||
}
|
||||
|
||||
getBlockSummaryLoaded(hash) {
|
||||
return this.blockSummaryLoaded[hash];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,9 +2,9 @@ import { Injectable } from '@angular/core';
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
import { Observable } from 'rxjs';
|
||||
import { map, shareReplay, switchMap } from 'rxjs/operators';
|
||||
import { StateService } from './state.service';
|
||||
import { environment } from '../../../src/environments/environment';
|
||||
import { AssetExtended } from '../interfaces/electrs.interface';
|
||||
import { StateService } from '@app/services/state.service';
|
||||
import { environment } from '@environments/environment';
|
||||
import { AssetExtended } from '@interfaces/electrs.interface';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Router } from '@angular/router';
|
||||
import { catchError, map, Observable, of, ReplaySubject, switchMap, tap } from 'rxjs';
|
||||
import { ServicesApiServices } from './services-api.service';
|
||||
import { ServicesApiServices } from '@app/services/services-api.service';
|
||||
|
||||
export interface IAuth {
|
||||
token: string;
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { firstValueFrom, Subject, Subscription} from 'rxjs';
|
||||
import { Transaction } from '../interfaces/electrs.interface';
|
||||
import { BlockExtended } from '../interfaces/node-api.interface';
|
||||
import { StateService } from './state.service';
|
||||
import { ApiService } from './api.service';
|
||||
import { Transaction } from '@interfaces/electrs.interface';
|
||||
import { BlockExtended } from '@interfaces/node-api.interface';
|
||||
import { StateService } from '@app/services/state.service';
|
||||
import { ApiService } from '@app/services/api.service';
|
||||
|
||||
const BLOCK_CACHE_SIZE = 500;
|
||||
const KEEP_RECENT_BLOCKS = 50;
|
||||
@@ -133,4 +133,4 @@ export class CacheService {
|
||||
getCachedBlock(height) {
|
||||
return this.blockCache[height];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,9 +2,9 @@ import { Injectable } from '@angular/core';
|
||||
import { HttpClient, HttpParams } from '@angular/common/http';
|
||||
import { BehaviorSubject, Observable, catchError, filter, from, of, shareReplay, switchMap, take, tap } from 'rxjs';
|
||||
import { Transaction, Address, Outspend, Recent, Asset, ScriptHash, AddressTxSummary, Utxo } from '../interfaces/electrs.interface';
|
||||
import { StateService } from './state.service';
|
||||
import { BlockExtended } from '../interfaces/node-api.interface';
|
||||
import { calcScriptHash$ } from '../bitcoin.utils';
|
||||
import { StateService } from '@app/services/state.service';
|
||||
import { BlockExtended } from '@interfaces/node-api.interface';
|
||||
import { calcScriptHash$ } from '@app/bitcoin.utils';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
@@ -142,6 +142,14 @@ export class ElectrsApiService {
|
||||
return this.httpClient.get<Transaction[]>(this.apiBaseUrl + this.apiBasePath + '/api/address/' + address + '/txs', { params });
|
||||
}
|
||||
|
||||
getAddressesTransactions$(addresses: string[], txid?: string): Observable<Transaction[]> {
|
||||
let params = new HttpParams();
|
||||
if (txid) {
|
||||
params = params.append('after_txid', txid);
|
||||
}
|
||||
return this.httpClient.get<Transaction[]>(this.apiBaseUrl + this.apiBasePath + `/api/addresses/txs?addresses=${addresses.join(',')}`, { params });
|
||||
}
|
||||
|
||||
getAddressSummary$(address: string, txid?: string): Observable<AddressTxSummary[]> {
|
||||
let params = new HttpParams();
|
||||
if (txid) {
|
||||
@@ -150,6 +158,14 @@ export class ElectrsApiService {
|
||||
return this.httpClient.get<AddressTxSummary[]>(this.apiBaseUrl + this.apiBasePath + '/api/address/' + address + '/txs/summary', { params });
|
||||
}
|
||||
|
||||
getAddressesSummary$(addresses: string[], txid?: string): Observable<AddressTxSummary[]> {
|
||||
let params = new HttpParams();
|
||||
if (txid) {
|
||||
params = params.append('after_txid', txid);
|
||||
}
|
||||
return this.httpClient.get<AddressTxSummary[]>(this.apiBaseUrl + this.apiBasePath + `/api/addresses/txs/summary?addresses=${addresses.join(',')}`, { params });
|
||||
}
|
||||
|
||||
getScriptHashTransactions$(script: string, txid?: string): Observable<Transaction[]> {
|
||||
let params = new HttpParams();
|
||||
if (txid) {
|
||||
@@ -160,6 +176,16 @@ export class ElectrsApiService {
|
||||
);
|
||||
}
|
||||
|
||||
getScriptHashesTransactions$(scripts: string[], txid?: string): Observable<Transaction[]> {
|
||||
let params = new HttpParams();
|
||||
if (txid) {
|
||||
params = params.append('after_txid', txid);
|
||||
}
|
||||
return from(Promise.all(scripts.map(script => calcScriptHash$(script)))).pipe(
|
||||
switchMap(scriptHashes => this.httpClient.get<Transaction[]>(this.apiBaseUrl + this.apiBasePath + `/api/scripthashes/txs?scripthashes=${scriptHashes.join(',')}`, { params })),
|
||||
);
|
||||
}
|
||||
|
||||
getScriptHashSummary$(script: string, txid?: string): Observable<AddressTxSummary[]> {
|
||||
let params = new HttpParams();
|
||||
if (txid) {
|
||||
@@ -180,6 +206,16 @@ export class ElectrsApiService {
|
||||
);
|
||||
}
|
||||
|
||||
getScriptHashesSummary$(scripts: string[], txid?: string): Observable<AddressTxSummary[]> {
|
||||
let params = new HttpParams();
|
||||
if (txid) {
|
||||
params = params.append('after_txid', txid);
|
||||
}
|
||||
return from(Promise.all(scripts.map(script => calcScriptHash$(script)))).pipe(
|
||||
switchMap(scriptHashes => this.httpClient.get<AddressTxSummary[]>(this.apiBaseUrl + this.apiBasePath + `/api/scripthashes/txs/summary?scripthashes=${scriptHashes.join(',')}`, { params })),
|
||||
);
|
||||
}
|
||||
|
||||
getAsset$(assetId: string): Observable<Asset> {
|
||||
return this.httpClient.get<Asset>(this.apiBaseUrl + this.apiBasePath + '/api/asset/' + assetId);
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { DOCUMENT } from '@angular/common';
|
||||
import { Inject, Injectable } from '@angular/core';
|
||||
import { ApiService } from './api.service';
|
||||
import { SeoService } from './seo.service';
|
||||
import { StateService } from './state.service';
|
||||
import { ApiService } from '@app/services/api.service';
|
||||
import { SeoService } from '@app/services/seo.service';
|
||||
import { StateService } from '@app/services/state.service';
|
||||
import { ActivatedRoute } from '@angular/router';
|
||||
import { BehaviorSubject } from 'rxjs';
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { AccelerationPosition, CpfpInfo, DifficultyAdjustment, MempoolPosition, SinglePoolStats } from '../interfaces/node-api.interface';
|
||||
import { StateService } from './state.service';
|
||||
import { MempoolBlock } from '../interfaces/websocket.interface';
|
||||
import { Transaction } from '../interfaces/electrs.interface';
|
||||
import { MiningService, MiningStats } from './mining.service';
|
||||
import { getUnacceleratedFeeRate } from '../shared/transaction.utils';
|
||||
import { AccelerationEstimate } from '../components/accelerate-checkout/accelerate-checkout.component';
|
||||
import { AccelerationPosition, CpfpInfo, DifficultyAdjustment, MempoolPosition, SinglePoolStats } from '@interfaces/node-api.interface';
|
||||
import { StateService } from '@app/services/state.service';
|
||||
import { MempoolBlock } from '@interfaces/websocket.interface';
|
||||
import { Transaction } from '@interfaces/electrs.interface';
|
||||
import { MiningService, MiningStats } from '@app/services/mining.service';
|
||||
import { getUnacceleratedFeeRate } from '@app/shared/transaction.utils';
|
||||
import { AccelerationEstimate } from '@components/accelerate-checkout/accelerate-checkout.component';
|
||||
import { Observable, combineLatest, map, of, share, shareReplay, tap } from 'rxjs';
|
||||
|
||||
export interface ETA {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { DOCUMENT, getLocaleId } from '@angular/common';
|
||||
import { LOCALE_ID, Inject, Injectable } from '@angular/core';
|
||||
import { languages } from '../app.constants';
|
||||
import { languages } from '@app/app.constants';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Observable, of } from 'rxjs';
|
||||
import { map, tap } from 'rxjs/operators';
|
||||
import { PoolsStats, SinglePoolStats } from '../interfaces/node-api.interface';
|
||||
import { ApiService } from '../services/api.service';
|
||||
import { StateService } from './state.service';
|
||||
import { StorageService } from './storage.service';
|
||||
import { PoolsStats, SinglePoolStats } from '@interfaces/node-api.interface';
|
||||
import { ApiService } from '@app/services/api.service';
|
||||
import { StateService } from '@app/services/state.service';
|
||||
import { StorageService } from '@app/services/storage.service';
|
||||
|
||||
export interface MiningUnits {
|
||||
hashrateDivider: number;
|
||||
@@ -13,6 +13,8 @@ export interface MiningUnits {
|
||||
|
||||
export interface MiningStats {
|
||||
lastEstimatedHashrate: number;
|
||||
lastEstimatedHashrate3d: number;
|
||||
lastEstimatedHashrate1w: number;
|
||||
blockCount: number;
|
||||
totalEmptyBlock: number;
|
||||
totalEmptyBlockRatio: string;
|
||||
@@ -129,6 +131,8 @@ export class MiningService {
|
||||
return {
|
||||
share: parseFloat((poolStat.blockCount / stats.blockCount * 100).toFixed(2)),
|
||||
lastEstimatedHashrate: poolStat.blockCount / stats.blockCount * stats.lastEstimatedHashrate / hashrateDivider,
|
||||
lastEstimatedHashrate3d: poolStat.blockCount / stats.blockCount * stats.lastEstimatedHashrate3d / hashrateDivider,
|
||||
lastEstimatedHashrate1w: poolStat.blockCount / stats.blockCount * stats.lastEstimatedHashrate1w / hashrateDivider,
|
||||
emptyBlockRatio: (poolStat.emptyBlocks / poolStat.blockCount * 100).toFixed(2),
|
||||
logo: `/resources/mining-pools/` + poolStat.slug + '.svg',
|
||||
...poolStat
|
||||
@@ -137,6 +141,8 @@ export class MiningService {
|
||||
|
||||
return {
|
||||
lastEstimatedHashrate: stats.lastEstimatedHashrate / hashrateDivider,
|
||||
lastEstimatedHashrate3d: stats.lastEstimatedHashrate3d / hashrateDivider,
|
||||
lastEstimatedHashrate1w: stats.lastEstimatedHashrate1w / hashrateDivider,
|
||||
blockCount: stats.blockCount,
|
||||
totalEmptyBlock: totalEmptyBlock,
|
||||
totalEmptyBlockRatio: totalEmptyBlockRatio,
|
||||
|
||||
@@ -2,8 +2,8 @@ import { Injectable } from '@angular/core';
|
||||
import { Router, NavigationEnd, ActivatedRouteSnapshot } from '@angular/router';
|
||||
import { BehaviorSubject } from 'rxjs';
|
||||
import { filter, map } from 'rxjs/operators';
|
||||
import { StateService } from './state.service';
|
||||
import { RelativeUrlPipe } from '../shared/pipes/relative-url/relative-url.pipe';
|
||||
import { StateService } from '@app/services/state.service';
|
||||
import { RelativeUrlPipe } from '@app/shared/pipes/relative-url/relative-url.pipe';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
|
||||
@@ -3,8 +3,8 @@ import { Meta } from '@angular/platform-browser';
|
||||
import { Router, ActivatedRoute, NavigationEnd } from '@angular/router';
|
||||
import { filter, map, switchMap } from 'rxjs/operators';
|
||||
import { combineLatest } from 'rxjs';
|
||||
import { StateService } from './state.service';
|
||||
import { LanguageService } from './language.service';
|
||||
import { StateService } from '@app/services/state.service';
|
||||
import { LanguageService } from '@app/services/language.service';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { catchError, forkJoin, map, Observable, of, switchMap, tap } from 'rxjs';
|
||||
import { Inscription } from '../shared/ord/inscription.utils';
|
||||
import { Transaction } from '../interfaces/electrs.interface';
|
||||
import { getNextInscriptionMark, hexToBytes, extractInscriptionData } from '../shared/ord/inscription.utils';
|
||||
import { decipherRunestone, Runestone, Etching, UNCOMMON_GOODS } from '../shared/ord/rune.utils';
|
||||
import { ElectrsApiService } from './electrs-api.service';
|
||||
import { Inscription } from '@app/shared/ord/inscription.utils';
|
||||
import { Transaction } from '@interfaces/electrs.interface';
|
||||
import { getNextInscriptionMark, hexToBytes, extractInscriptionData } from '@app/shared/ord/inscription.utils';
|
||||
import { decipherRunestone, Runestone, Etching, UNCOMMON_GOODS } from '@app/shared/ord/rune.utils';
|
||||
import { ElectrsApiService } from '@app/services/electrs-api.service';
|
||||
|
||||
|
||||
@Injectable({
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { ElectrsApiService } from '../services/electrs-api.service';
|
||||
import { Subject, debounceTime, switchMap } from 'rxjs';
|
||||
import { ApiService } from './api.service';
|
||||
import { ApiService } from '@app/services/api.service';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { map, Observable, of, share, shareReplay, tap } from 'rxjs';
|
||||
import { ApiService } from './api.service';
|
||||
import { StateService } from './state.service';
|
||||
import { ApiService } from '@app/services/api.service';
|
||||
import { StateService } from '@app/services/state.service';
|
||||
|
||||
// nodejs backend interfaces
|
||||
export interface ApiPrice {
|
||||
@@ -320,4 +320,4 @@ export class PriceService {
|
||||
return prices;
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ import { Injectable } from '@angular/core';
|
||||
import { Title, Meta } from '@angular/platform-browser';
|
||||
import { ActivatedRoute, NavigationEnd, Router } from '@angular/router';
|
||||
import { filter, map, switchMap } from 'rxjs';
|
||||
import { StateService } from './state.service';
|
||||
import { StateService } from '@app/services/state.service';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import { Router, NavigationStart } from '@angular/router';
|
||||
import { Injectable } from '@angular/core';
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
import { StateService } from './state.service';
|
||||
import { StorageService } from './storage.service';
|
||||
import { MenuGroup } from '../interfaces/services.interface';
|
||||
import { StateService } from '@app/services/state.service';
|
||||
import { StorageService } from '@app/services/storage.service';
|
||||
import { MenuGroup } from '@interfaces/services.interface';
|
||||
import { Observable, of, ReplaySubject, tap, catchError, share, filter, switchMap, map } from 'rxjs';
|
||||
import { IBackendInfo } from '../interfaces/websocket.interface';
|
||||
import { Acceleration, AccelerationHistoryParams } from '../interfaces/node-api.interface';
|
||||
import { AccelerationStats } from '../components/acceleration/acceleration-stats/acceleration-stats.component';
|
||||
import { IBackendInfo } from '@interfaces/websocket.interface';
|
||||
import { Acceleration, AccelerationHistoryParams } from '@interfaces/node-api.interface';
|
||||
import { AccelerationStats } from '@components/acceleration/acceleration-stats/acceleration-stats.component';
|
||||
|
||||
export interface IUser {
|
||||
username: string;
|
||||
@@ -131,20 +131,20 @@ export class ServicesApiServices {
|
||||
return this.httpClient.post<any>(`${this.stateService.env.SERVICES_API}/accelerator/estimate`, { txInput: txInput }, { observe: 'response' });
|
||||
}
|
||||
|
||||
accelerate$(txInput: string, userBid: number, accelerationUUID: string) {
|
||||
return this.httpClient.post<any>(`${this.stateService.env.SERVICES_API}/accelerator/accelerate`, { txInput: txInput, userBid: userBid, accelerationUUID: accelerationUUID });
|
||||
accelerate$(txInput: string, userBid: number) {
|
||||
return this.httpClient.post<any>(`${this.stateService.env.SERVICES_API}/accelerator/accelerate`, { txInput: txInput, userBid: userBid});
|
||||
}
|
||||
|
||||
accelerateWithCashApp$(txInput: string, token: string, cashtag: string, referenceId: string, accelerationUUID: string) {
|
||||
return this.httpClient.post<any>(`${this.stateService.env.SERVICES_API}/accelerator/accelerate/cashapp`, { txInput: txInput, token: token, cashtag: cashtag, referenceId: referenceId, accelerationUUID: accelerationUUID });
|
||||
accelerateWithCashApp$(txInput: string, token: string, cashtag: string, referenceId: string, userApprovedUSD: number) {
|
||||
return this.httpClient.post<any>(`${this.stateService.env.SERVICES_API}/accelerator/accelerate/cashapp`, { txInput: txInput, token: token, cashtag: cashtag, referenceId: referenceId, userApprovedUSD: userApprovedUSD });
|
||||
}
|
||||
|
||||
accelerateWithApplePay$(txInput: string, token: string, cardTag: string, referenceId: string, accelerationUUID: string) {
|
||||
return this.httpClient.post<any>(`${this.stateService.env.SERVICES_API}/accelerator/accelerate/applePay`, { txInput: txInput, cardTag: cardTag, token: token, referenceId: referenceId, accelerationUUID: accelerationUUID });
|
||||
accelerateWithApplePay$(txInput: string, token: string, cardTag: string, referenceId: string, userApprovedUSD: number) {
|
||||
return this.httpClient.post<any>(`${this.stateService.env.SERVICES_API}/accelerator/accelerate/applePay`, { txInput: txInput, cardTag: cardTag, token: token, referenceId: referenceId, userApprovedUSD: userApprovedUSD });
|
||||
}
|
||||
|
||||
accelerateWithGooglePay$(txInput: string, token: string, cardTag: string, referenceId: string, accelerationUUID: string) {
|
||||
return this.httpClient.post<any>(`${this.stateService.env.SERVICES_API}/accelerator/accelerate/googlePay`, { txInput: txInput, cardTag: cardTag, token: token, referenceId: referenceId, accelerationUUID: accelerationUUID });
|
||||
accelerateWithGooglePay$(txInput: string, token: string, verificationToken: string, cardTag: string, referenceId: string, userApprovedUSD: number) {
|
||||
return this.httpClient.post<any>(`${this.stateService.env.SERVICES_API}/accelerator/accelerate/googlePay`, { txInput: txInput, cardTag: cardTag, token: token, verificationToken: verificationToken, referenceId: referenceId, userApprovedUSD: userApprovedUSD });
|
||||
}
|
||||
|
||||
getAccelerations$(): Observable<Acceleration[]> {
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
import { Inject, Injectable, PLATFORM_ID, LOCALE_ID } from '@angular/core';
|
||||
import { ReplaySubject, BehaviorSubject, Subject, fromEvent, Observable } from 'rxjs';
|
||||
import { Transaction } from '../interfaces/electrs.interface';
|
||||
import { AccelerationDelta, HealthCheckHost, IBackendInfo, MempoolBlock, MempoolBlockUpdate, MempoolInfo, Recommendedfees, ReplacedTransaction, ReplacementInfo, isMempoolState } from '../interfaces/websocket.interface';
|
||||
import { Acceleration, AccelerationPosition, BlockExtended, CpfpInfo, DifficultyAdjustment, MempoolPosition, OptimizedMempoolStats, RbfTree, TransactionStripped } from '../interfaces/node-api.interface';
|
||||
import { AddressTxSummary, Transaction } from '@interfaces/electrs.interface';
|
||||
import { AccelerationDelta, HealthCheckHost, IBackendInfo, MempoolBlock, MempoolBlockUpdate, MempoolInfo, Recommendedfees, ReplacedTransaction, ReplacementInfo, isMempoolState } from '@interfaces/websocket.interface';
|
||||
import { Acceleration, AccelerationPosition, BlockExtended, CpfpInfo, DifficultyAdjustment, MempoolPosition, OptimizedMempoolStats, RbfTree, TransactionStripped } from '@interfaces/node-api.interface';
|
||||
import { Router, NavigationStart } from '@angular/router';
|
||||
import { isPlatformBrowser } from '@angular/common';
|
||||
import { filter, map, scan, share, shareReplay } from 'rxjs/operators';
|
||||
import { StorageService } from './storage.service';
|
||||
import { hasTouchScreen } from '../shared/pipes/bytes-pipe/utils';
|
||||
import { ActiveFilter } from '../shared/filters.utils';
|
||||
import { StorageService } from '@app/services/storage.service';
|
||||
import { hasTouchScreen } from '@app/shared/pipes/bytes-pipe/utils';
|
||||
import { ActiveFilter } from '@app/shared/filters.utils';
|
||||
|
||||
export interface MarkBlockState {
|
||||
blockHeight?: number;
|
||||
@@ -68,7 +68,12 @@ export interface Env {
|
||||
AUDIT: boolean;
|
||||
MAINNET_BLOCK_AUDIT_START_HEIGHT: number;
|
||||
TESTNET_BLOCK_AUDIT_START_HEIGHT: number;
|
||||
TESTNET4_BLOCK_AUDIT_START_HEIGHT: number;
|
||||
SIGNET_BLOCK_AUDIT_START_HEIGHT: number;
|
||||
MAINNET_TX_FIRST_SEEN_START_HEIGHT: number;
|
||||
TESTNET_TX_FIRST_SEEN_START_HEIGHT: number;
|
||||
TESTNET4_TX_FIRST_SEEN_START_HEIGHT: number;
|
||||
SIGNET_TX_FIRST_SEEN_START_HEIGHT: number;
|
||||
HISTORICAL_PRICE: boolean;
|
||||
ACCELERATOR: boolean;
|
||||
ACCELERATOR_BUTTON: boolean;
|
||||
@@ -78,6 +83,7 @@ export interface Env {
|
||||
PACKAGE_JSON_VERSION_MEMPOOL_SPACE?: string;
|
||||
SERVICES_API?: string;
|
||||
customize?: Customization;
|
||||
PROD_DOMAINS: string[];
|
||||
}
|
||||
|
||||
const defaultEnv: Env = {
|
||||
@@ -106,13 +112,19 @@ const defaultEnv: Env = {
|
||||
'AUDIT': false,
|
||||
'MAINNET_BLOCK_AUDIT_START_HEIGHT': 0,
|
||||
'TESTNET_BLOCK_AUDIT_START_HEIGHT': 0,
|
||||
'TESTNET4_BLOCK_AUDIT_START_HEIGHT': 0,
|
||||
'SIGNET_BLOCK_AUDIT_START_HEIGHT': 0,
|
||||
'MAINNET_TX_FIRST_SEEN_START_HEIGHT': 0,
|
||||
'TESTNET_TX_FIRST_SEEN_START_HEIGHT': 0,
|
||||
'TESTNET4_TX_FIRST_SEEN_START_HEIGHT': 0,
|
||||
'SIGNET_TX_FIRST_SEEN_START_HEIGHT': 0,
|
||||
'HISTORICAL_PRICE': true,
|
||||
'ACCELERATOR': false,
|
||||
'ACCELERATOR_BUTTON': true,
|
||||
'PUBLIC_ACCELERATIONS': false,
|
||||
'ADDITIONAL_CURRENCIES': false,
|
||||
'SERVICES_API': 'https://mempool.space/api/v1/services',
|
||||
'PROD_DOMAINS': [],
|
||||
};
|
||||
|
||||
@Injectable({
|
||||
@@ -159,6 +171,7 @@ export class StateService {
|
||||
mempoolRemovedTransactions$ = new Subject<Transaction>();
|
||||
multiAddressTransactions$ = new Subject<{ [address: string]: { mempool: Transaction[], confirmed: Transaction[], removed: Transaction[] }}>();
|
||||
blockTransactions$ = new Subject<Transaction>();
|
||||
walletTransactions$ = new Subject<Transaction[]>();
|
||||
isLoadingWebSocket$ = new ReplaySubject<boolean>(1);
|
||||
isLoadingMempool$ = new BehaviorSubject<boolean>(true);
|
||||
vbytesPerSecond$ = new ReplaySubject<number>(1);
|
||||
@@ -173,6 +186,7 @@ export class StateService {
|
||||
live2Chart$ = new Subject<OptimizedMempoolStats>();
|
||||
|
||||
viewAmountMode$: BehaviorSubject<'btc' | 'sats' | 'fiat'>;
|
||||
timezone$: BehaviorSubject<string>;
|
||||
connectionState$ = new BehaviorSubject<0 | 1 | 2>(2);
|
||||
isTabHidden$: Observable<boolean>;
|
||||
|
||||
@@ -205,6 +219,10 @@ export class StateService {
|
||||
const browserWindow = window || {};
|
||||
// @ts-ignore
|
||||
const browserWindowEnv = browserWindow.__env || {};
|
||||
if (browserWindowEnv.PROD_DOMAINS && typeof(browserWindowEnv.PROD_DOMAINS) === 'string') {
|
||||
browserWindowEnv.PROD_DOMAINS = browserWindowEnv.PROD_DOMAINS.split(',');
|
||||
}
|
||||
|
||||
this.env = Object.assign(defaultEnv, browserWindowEnv);
|
||||
|
||||
if (defaultEnv.BASE_MODULE !== 'mempool') {
|
||||
@@ -330,6 +348,9 @@ export class StateService {
|
||||
const viewAmountModePreference = this.storageService.getValue('view-amount-mode') as 'btc' | 'sats' | 'fiat';
|
||||
this.viewAmountMode$ = new BehaviorSubject<'btc' | 'sats' | 'fiat'>(viewAmountModePreference || 'btc');
|
||||
|
||||
const timezonePreference = this.storageService.getValue('timezone-preference');
|
||||
this.timezone$ = new BehaviorSubject<string>(timezonePreference || 'local');
|
||||
|
||||
this.backend$.subscribe(backend => {
|
||||
this.backend = backend;
|
||||
});
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Subject } from 'rxjs';
|
||||
import { defaultMempoolFeeColors, contrastMempoolFeeColors } from '../app.constants';
|
||||
import { StorageService } from './storage.service';
|
||||
import { StateService } from './state.service';
|
||||
import { defaultMempoolFeeColors, contrastMempoolFeeColors } from '@app/app.constants';
|
||||
import { StorageService } from '@app/services/storage.service';
|
||||
import { StateService } from '@app/services/state.service';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { DatePipe } from '@angular/common';
|
||||
import { dates } from '../shared/i18n/dates';
|
||||
import { dates } from '@app/shared/i18n/dates';
|
||||
|
||||
const intervals = {
|
||||
year: 31536000,
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { webSocket, WebSocketSubject } from 'rxjs/webSocket';
|
||||
import { WebsocketResponse } from '../interfaces/websocket.interface';
|
||||
import { StateService } from './state.service';
|
||||
import { Transaction } from '../interfaces/electrs.interface';
|
||||
import { WebsocketResponse } from '@interfaces/websocket.interface';
|
||||
import { StateService } from '@app/services/state.service';
|
||||
import { Transaction } from '@interfaces/electrs.interface';
|
||||
import { firstValueFrom, Subscription } from 'rxjs';
|
||||
import { ApiService } from './api.service';
|
||||
import { ApiService } from '@app/services/api.service';
|
||||
import { take } from 'rxjs/operators';
|
||||
import { TransferState, makeStateKey } from '@angular/core';
|
||||
import { CacheService } from './cache.service';
|
||||
import { uncompressDeltaChange, uncompressTx } from '../shared/common.utils';
|
||||
import { CacheService } from '@app/services/cache.service';
|
||||
import { uncompressDeltaChange, uncompressTx } from '@app/shared/common.utils';
|
||||
|
||||
const OFFLINE_RETRY_AFTER_MS = 2000;
|
||||
const OFFLINE_PING_CHECK_AFTER_MS = 30000;
|
||||
@@ -34,7 +34,10 @@ export class WebsocketService {
|
||||
private isTrackingAddress: string | false = false;
|
||||
private isTrackingAddresses: string[] | false = false;
|
||||
private isTrackingAccelerations: boolean = false;
|
||||
private isTrackingWallet: boolean = false;
|
||||
private trackingWalletName: string;
|
||||
private trackingMempoolBlock: number;
|
||||
private trackingMempoolBlockNetwork: string;
|
||||
private stoppingTrackMempoolBlock: any | null = null;
|
||||
private latestGitCommit = '';
|
||||
private onlineCheckTimeout: number;
|
||||
@@ -137,6 +140,9 @@ export class WebsocketService {
|
||||
if (this.isTrackingAccelerations) {
|
||||
this.startTrackAccelerations();
|
||||
}
|
||||
if (this.isTrackingWallet) {
|
||||
this.startTrackingWallet(this.trackingWalletName);
|
||||
}
|
||||
this.stateService.connectionState$.next(2);
|
||||
}
|
||||
|
||||
@@ -196,6 +202,18 @@ export class WebsocketService {
|
||||
this.isTrackingAddresses = false;
|
||||
}
|
||||
|
||||
startTrackingWallet(walletName: string) {
|
||||
this.websocketSubject.next({ 'track-wallet': walletName });
|
||||
this.isTrackingWallet = true;
|
||||
this.trackingWalletName = walletName;
|
||||
}
|
||||
|
||||
stopTrackingWallet() {
|
||||
this.websocketSubject.next({ 'track-wallet': 'stop' });
|
||||
this.isTrackingWallet = false;
|
||||
this.trackingWalletName = '';
|
||||
}
|
||||
|
||||
startTrackAsset(asset: string) {
|
||||
this.websocketSubject.next({ 'track-asset': asset });
|
||||
}
|
||||
@@ -209,10 +227,11 @@ export class WebsocketService {
|
||||
clearTimeout(this.stoppingTrackMempoolBlock);
|
||||
}
|
||||
// skip duplicate tracking requests
|
||||
if (force || this.trackingMempoolBlock !== block) {
|
||||
if (force || this.trackingMempoolBlock !== block || this.network !== this.trackingMempoolBlockNetwork) {
|
||||
this.websocketSubject.next({ 'track-mempool-block': block });
|
||||
this.isTrackingMempoolBlock = true;
|
||||
this.trackingMempoolBlock = block;
|
||||
this.trackingMempoolBlockNetwork = this.network;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -452,6 +471,10 @@ export class WebsocketService {
|
||||
}
|
||||
}
|
||||
|
||||
if (response['wallet-transactions']) {
|
||||
this.stateService.walletTransactions$.next(response['wallet-transactions']);
|
||||
}
|
||||
|
||||
if (response['accelerations']) {
|
||||
if (response['accelerations'].accelerations) {
|
||||
this.stateService.accelerations$.next({
|
||||
|
||||
Reference in New Issue
Block a user