Redo/Fix completely failed PR #3092 + add PR #3105

This commit is contained in:
nymkappa
2023-02-23 09:50:34 +09:00
parent 6e7ed29caa
commit f44eacd5d5
8 changed files with 79 additions and 73 deletions

View File

@@ -3,7 +3,7 @@
{{ addPlus && satoshis >= 0 ? '+' : '' }}
{{
(
(blockConversion.price[currency] > 0 ? blockConversion.price[currency] : null) ??
(blockConversion.price[currency] >= 0 ? blockConversion.price[currency] : null) ??
(blockConversion.price['USD'] * blockConversion.exchangeRates['USD' + currency]) ?? 0
) * satoshis / 100000000 | fiatCurrency : digitsInfo : currency
}}

View File

@@ -443,9 +443,9 @@ export class BlockComponent implements OnInit, OnDestroy {
}
this.priceSubscription = block$.pipe(
switchMap((block) => {
return this.priceService.getPrices().pipe(
tap(() => {
this.blockConversion = this.priceService.getPriceForTimestamp(block.timestamp);
return this.priceService.getBlockPrice$(block.timestamp).pipe(
tap((price) => {
this.blockConversion = price;
})
);
})

View File

@@ -327,9 +327,9 @@ export class TransactionComponent implements OnInit, AfterViewInit, OnDestroy {
this.fetchRbfHistory$.next(this.tx.txid);
}
this.priceService.getPrices().pipe(
tap(() => {
this.blockConversion = this.priceService.getPriceForTimestamp(tx.status.block_time);
this.priceService.getBlockPrice$(tx.status.block_time).pipe(
tap((price) => {
this.blockConversion = price;
})
).subscribe();

View File

@@ -6,7 +6,7 @@ import { Outspend, Transaction, Vin, Vout } from '../../interfaces/electrs.inter
import { ElectrsApiService } from '../../services/electrs-api.service';
import { environment } from '../../../environments/environment';
import { AssetsService } from '../../services/assets.service';
import { filter, map, tap, switchMap } from 'rxjs/operators';
import { filter, map, tap, switchMap, shareReplay } from 'rxjs/operators';
import { BlockExtended } from '../../interfaces/node-api.interface';
import { ApiService } from '../../services/api.service';
import { PriceService } from 'src/app/services/price.service';
@@ -150,10 +150,8 @@ export class TransactionsListComponent implements OnInit, OnChanges {
tx['addressValue'] = addressIn - addressOut;
}
this.priceService.getPrices().pipe(
tap(() => {
tx['price'] = this.priceService.getPriceForTimestamp(tx.status.block_time);
})
this.priceService.getBlockPrice$(tx.status.block_time).pipe(
tap((price) => tx['price'] = price)
).subscribe();
});
const txIds = this.transactions.filter((tx) => !tx._outspends).map((tx) => tx.txid);

View File

@@ -1,7 +1,7 @@
<span class="green-color" *ngIf="blockConversion; else noblockconversion">
{{
(
(blockConversion.price[currency] > 0 ? blockConversion.price[currency] : null) ??
(blockConversion.price[currency] >= 0 ? blockConversion.price[currency] : null) ??
(blockConversion.price['USD'] * blockConversion.exchangeRates['USD' + currency]) ?? 0
) * value / 100000000 | fiatCurrency : digitsInfo : currency
}}

View File

@@ -1,5 +1,5 @@
import { Injectable } from '@angular/core';
import { map, Observable, of, shareReplay } from 'rxjs';
import { map, Observable, of, share, shareReplay, tap } from 'rxjs';
import { ApiService } from './api.service';
// nodejs backend interfaces
@@ -40,6 +40,8 @@ export interface ConversionDict {
providedIn: 'root'
})
export class PriceService {
priceObservable$: Observable<Conversion>;
historicalPrice: ConversionDict = {
prices: null,
exchangeRates: null,
@@ -61,65 +63,53 @@ export class PriceService {
};
}
/**
* Fetch prices from the nodejs backend only once
*/
getPrices(): Observable<void> {
if (this.historicalPrice.prices) {
return of(null);
getBlockPrice$(blockTimestamp: number): Observable<Price | undefined> {
if (!this.priceObservable$) {
this.priceObservable$ = this.apiService.getHistoricalPrice$().pipe(shareReplay());
}
return this.apiService.getHistoricalPrice$().pipe(
map((conversion: Conversion) => {
if (!this.historicalPrice.prices) {
this.historicalPrice.prices = Object();
return this.priceObservable$.pipe(
map((conversion) => {
if (!blockTimestamp) {
return undefined;
}
const historicalPrice = {
prices: {},
exchangeRates: conversion.exchangeRates,
};
for (const price of conversion.prices) {
this.historicalPrice.prices[price.time] = {
historicalPrice.prices[price.time] = {
USD: price.USD, EUR: price.EUR, GBP: price.GBP, CAD: price.CAD,
CHF: price.CHF, AUD: price.AUD, JPY: price.JPY
};
}
this.historicalPrice.exchangeRates = conversion.exchangeRates;
return;
}),
shareReplay(),
);
}
/**
* Note: The first block with a price we have is block 68952 (using MtGox price history)
*
* @param blockTimestamp
*/
getPriceForTimestamp(blockTimestamp: number): Price | null {
if (!blockTimestamp) {
return undefined;
}
const priceTimestamps = Object.keys(this.historicalPrice.prices);
priceTimestamps.push(Number.MAX_SAFE_INTEGER.toString());
priceTimestamps.sort().reverse();
const priceTimestamps = Object.keys(historicalPrice.prices);
priceTimestamps.push(Number.MAX_SAFE_INTEGER.toString());
priceTimestamps.sort().reverse();
// Small trick here. Because latest blocks have higher timestamps than our
// latest price timestamp (we only insert once every hour), we have no price for them.
// Therefore we want to fallback to the websocket price by returning an undefined `price` field.
// Since historicalPrice.prices[Number.MAX_SAFE_INTEGER] does not exists
// it will return `undefined` and automatically use the websocket price.
// This way we can differenciate blocks without prices like the genesis block
// vs ones without a price (yet) like the latest blocks
// Small trick here. Because latest blocks have higher timestamps than our
// latest price timestamp (we only insert once every hour), we have no price for them.
// Therefore we want to fallback to the websocket price by returning an undefined `price` field.
// Since this.historicalPrice.prices[Number.MAX_SAFE_INTEGER] does not exists
// it will return `undefined` and automatically use the websocket price.
// This way we can differenciate blocks without prices like the genesis block
// vs ones without a price (yet) like the latest blocks
for (const t of priceTimestamps) {
const priceTimestamp = parseInt(t, 10);
if (blockTimestamp > priceTimestamp) {
return {
price: this.historicalPrice.prices[priceTimestamp],
exchangeRates: this.historicalPrice.exchangeRates,
};
}
}
return this.getEmptyPrice();
for (const t of priceTimestamps) {
const priceTimestamp = parseInt(t, 10);
if (blockTimestamp > priceTimestamp) {
return {
price: historicalPrice.prices[priceTimestamp],
exchangeRates: historicalPrice.exchangeRates,
};
}
}
return this.getEmptyPrice();
})
);
}
}