Use historical price for older blocks and transactions

This commit is contained in:
nymkappa
2023-02-21 12:36:43 +09:00
parent cfa5734f19
commit 72779c8244
16 changed files with 284 additions and 19 deletions

View File

@@ -1,7 +1,19 @@
<ng-container *ngIf="!noFiat && (viewFiat$ | async) && (conversions$ | async) as conversions; else viewFiatVin">
<span class="fiat">{{ addPlus && satoshis >= 0 ? '+' : '' }}{{ (conversions ? conversions[currency] : 0) * satoshis / 100000000 | fiatCurrency : digitsInfo : currency }}</span>
<span class="fiat" *ngIf="blockConversion; else noblockconversion">
{{ addPlus && satoshis >= 0 ? '+' : '' }}
{{
(
(blockConversion.price[currency] > 0 ? blockConversion.price[currency] : null) ??
(blockConversion.price['USD'] * blockConversion.exchangeRates['USD' + currency]) ?? 0
) * satoshis / 100000000 | fiatCurrency : digitsInfo : currency
}}
</span>
<ng-template #noblockconversion>
<span class="fiat">{{ addPlus && satoshis >= 0 ? '+' : '' }}{{ (conversions ? conversions[currency] : 0) * satoshis / 100000000 | fiatCurrency : digitsInfo : currency }}</span>
</ng-template>
</ng-container>
<ng-template #viewFiatVin>
<ng-template #viewFiatVin>
<ng-template [ngIf]="(network === 'liquid' || network === 'liquidtestnet') && (satoshis === undefined || satoshis === null)" [ngIfElse]="default">
<span i18n="shared.confidential">Confidential</span>
</ng-template>

View File

@@ -1,6 +1,7 @@
import { Component, OnInit, OnDestroy, Input, ChangeDetectionStrategy, ChangeDetectorRef } from '@angular/core';
import { StateService } from '../../services/state.service';
import { Observable, Subscription } from 'rxjs';
import { Price } from 'src/app/services/price.service';
@Component({
selector: 'app-amount',
@@ -21,6 +22,7 @@ export class AmountComponent implements OnInit, OnDestroy {
@Input() digitsInfo = '1.8-8';
@Input() noFiat = false;
@Input() addPlus = false;
@Input() blockConversion: Price;
constructor(
private stateService: StateService,

View File

@@ -124,7 +124,13 @@
</tr>
<tr *ngIf="block?.extras?.medianFee != undefined">
<td class="td-width" i18n="block.median-fee">Median fee</td>
<td>~{{ block?.extras?.medianFee | number:'1.0-0' }} <span class="symbol" i18n="shared.sat-vbyte|sat/vB">sat/vB</span> <span class="fiat"><app-fiat [value]="block?.extras?.medianFee * 140" digitsInfo="1.2-2" i18n-ngbTooltip="Transaction fee tooltip" ngbTooltip="Based on average native segwit transaction of 140 vBytes" placement="bottom"></app-fiat></span></td>
<td>~{{ block?.extras?.medianFee | number:'1.0-0' }} <span class="symbol" i18n="shared.sat-vbyte|sat/vB">sat/vB</span>
<span class="fiat">
<app-fiat [blockConversion]="blockConversion" [value]="block?.extras?.medianFee * 140" digitsInfo="1.2-2"
i18n-ngbTooltip="Transaction fee tooltip" ngbTooltip="Based on average native segwit transaction of 140 vBytes"
placement="bottom"></app-fiat>
</span>
</td>
</tr>
<ng-template [ngIf]="fees !== undefined" [ngIfElse]="loadingFees">
<tr>
@@ -132,13 +138,13 @@
<td *ngIf="network !== 'liquid' && network !== 'liquidtestnet'; else liquidTotalFees">
<app-amount [satoshis]="block.extras.totalFees" digitsInfo="1.2-3" [noFiat]="true"></app-amount>
<span class="fiat">
<app-fiat [value]="block.extras.totalFees" digitsInfo="1.0-0"></app-fiat>
<app-fiat [blockConversion]="blockConversion" [value]="block.extras.totalFees" digitsInfo="1.0-0"></app-fiat>
</span>
</td>
<ng-template #liquidTotalFees>
<td>
<app-amount [satoshis]="fees * 100000000" digitsInfo="1.2-2" [noFiat]="true"></app-amount>&nbsp; <app-fiat
[value]="fees * 100000000" digitsInfo="1.2-2"></app-fiat>
[blockConversion]="blockConversion" [value]="fees * 100000000" digitsInfo="1.2-2"></app-fiat>
</td>
</ng-template>
</tr>
@@ -147,7 +153,7 @@
<td>
<app-amount [satoshis]="block.extras.reward" digitsInfo="1.2-3" [noFiat]="true"></app-amount>
<span class="fiat">
<app-fiat [value]="(blockSubsidy + fees) * 100000000" digitsInfo="1.0-0"></app-fiat>
<app-fiat [blockConversion]="blockConversion" [value]="(blockSubsidy + fees) * 100000000" digitsInfo="1.0-0"></app-fiat>
</span>
</td>
</tr>

View File

@@ -13,6 +13,7 @@ import { BlockAudit, BlockExtended, TransactionStripped } from '../../interfaces
import { ApiService } from '../../services/api.service';
import { BlockOverviewGraphComponent } from '../../components/block-overview-graph/block-overview-graph.component';
import { detectWebGL } from '../../shared/graphs.utils';
import { PriceService, Price } from 'src/app/services/price.service';
@Component({
selector: 'app-block',
@@ -81,6 +82,9 @@ export class BlockComponent implements OnInit, OnDestroy {
timeLtr: boolean;
childChangeSubscription: Subscription;
auditPrefSubscription: Subscription;
priceSubscription: Subscription;
blockConversion: Price;
@ViewChildren('blockGraphProjected') blockGraphProjected: QueryList<BlockOverviewGraphComponent>;
@ViewChildren('blockGraphActual') blockGraphActual: QueryList<BlockOverviewGraphComponent>;
@@ -94,7 +98,8 @@ export class BlockComponent implements OnInit, OnDestroy {
private seoService: SeoService,
private websocketService: WebsocketService,
private relativeUrlPipe: RelativeUrlPipe,
private apiService: ApiService
private apiService: ApiService,
private priceService: PriceService,
) {
this.webGlEnabled = detectWebGL();
}
@@ -432,6 +437,19 @@ export class BlockComponent implements OnInit, OnDestroy {
}
}
});
if (this.priceSubscription) {
this.priceSubscription.unsubscribe();
}
this.priceSubscription = block$.pipe(
switchMap((block) => {
return this.priceService.getPrices().pipe(
tap(() => {
this.blockConversion = this.priceService.getPriceForTimestamp(block.timestamp);
})
);
})
).subscribe();
}
ngAfterViewInit(): void {

View File

@@ -469,7 +469,7 @@
<tbody>
<tr>
<td class="td-width" i18n="transaction.fee|Transaction fee">Fee</td>
<td>{{ tx.fee | number }} <span class="symbol" i18n="shared.sat|sat">sat</span> <span class="fiat"><app-fiat [value]="tx.fee"></app-fiat></span></td>
<td>{{ tx.fee | number }} <span class="symbol" i18n="shared.sat|sat">sat</span> <span class="fiat"><app-fiat [blockConversion]="blockConversion" [value]="tx.fee"></app-fiat></span></td>
</tr>
<tr>
<td i18n="transaction.fee-rate|Transaction fee rate">Fee rate</td>

View File

@@ -8,10 +8,11 @@ import {
retryWhen,
delay,
map,
mergeMap
mergeMap,
tap
} from 'rxjs/operators';
import { Transaction } from '../../interfaces/electrs.interface';
import { of, merge, Subscription, Observable, Subject, timer, combineLatest, from, throwError } from 'rxjs';
import { of, merge, Subscription, Observable, Subject, timer, from, throwError } from 'rxjs';
import { StateService } from '../../services/state.service';
import { CacheService } from '../../services/cache.service';
import { WebsocketService } from '../../services/websocket.service';
@@ -21,6 +22,7 @@ import { SeoService } from '../../services/seo.service';
import { BlockExtended, CpfpInfo } from '../../interfaces/node-api.interface';
import { LiquidUnblinding } from './liquid-ublinding';
import { RelativeUrlPipe } from '../../shared/pipes/relative-url/relative-url.pipe';
import { Price, PriceService } from 'src/app/services/price.service';
@Component({
selector: 'app-transaction',
@@ -69,7 +71,7 @@ export class TransactionComponent implements OnInit, AfterViewInit, OnDestroy {
hideFlow: boolean = this.stateService.hideFlow.value;
overrideFlowPreference: boolean = null;
flowEnabled: boolean;
blockConversion: Price;
tooltipPosition: { x: number, y: number };
@ViewChild('graphContainer')
@@ -85,7 +87,8 @@ export class TransactionComponent implements OnInit, AfterViewInit, OnDestroy {
private websocketService: WebsocketService,
private audioService: AudioService,
private apiService: ApiService,
private seoService: SeoService
private seoService: SeoService,
private priceService: PriceService,
) {}
ngOnInit() {
@@ -323,6 +326,13 @@ 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);
})
).subscribe();
setTimeout(() => { this.applyFragment(); }, 0);
},
(error) => {

View File

@@ -88,7 +88,7 @@
</ng-template>
<ng-template #defaultOutput>
<span *ngIf="vin.lazy" class="skeleton-loader"></span>
<app-amount *ngIf="vin.prevout" [satoshis]="vin.prevout.value"></app-amount>
<app-amount [blockConversion]="tx.price" *ngIf="vin.prevout" [satoshis]="vin.prevout.value"></app-amount>
</ng-template>
</td>
</tr>
@@ -216,7 +216,7 @@
</ng-template>
</ng-template>
<ng-template #defaultOutput>
<app-amount [satoshis]="vout.value"></app-amount>
<app-amount [blockConversion]="tx.price" [satoshis]="vout.value"></app-amount>
</ng-template>
</td>
<td class="arrow-td">
@@ -283,7 +283,9 @@
<div class="summary">
<div class="float-left mt-2-5" *ngIf="!transactionPage && !tx.vin[0].is_coinbase && tx.fee !== -1">
{{ tx.fee / (tx.weight / 4) | feeRounding }} <span class="symbol" i18n="shared.sat-vbyte|sat/vB">sat/vB</span> <span class="d-none d-sm-inline-block">&nbsp;&ndash; {{ tx.fee | number }} <span class="symbol" i18n="shared.sat|sat">sat</span> <span class="fiat"><app-fiat [value]="tx.fee"></app-fiat></span></span>
{{ tx.fee / (tx.weight / 4) | feeRounding }} <span class="symbol" i18n="shared.sat-vbyte|sat/vB">sat/vB</span> <span
class="d-none d-sm-inline-block">&nbsp;&ndash; {{ tx.fee | number }} <span class="symbol"
i18n="shared.sat|sat">sat</span> <span class="fiat"><app-fiat [blockConversion]="tx.price" [value]="tx.fee"></app-fiat></span></span>
</div>
<div class="float-left mt-2-5 grey-info-text" *ngIf="tx.fee === -1" i18n="transactions-list.load-to-reveal-fee-info">Show more inputs to reveal fee data</div>
@@ -301,12 +303,12 @@
<button *ngIf="address === ''; else viewingAddress" type="button" class="btn btn-sm btn-primary mt-2 ml-2" (click)="switchCurrency()">
<ng-template [ngIf]="(network === 'liquid' || network === 'liquidtestnet') && haveBlindedOutputValues(tx)" [ngIfElse]="defaultAmount" i18n="shared.confidential">Confidential</ng-template>
<ng-template #defaultAmount>
<app-amount [satoshis]="getTotalTxOutput(tx)"></app-amount>
<app-amount [blockConversion]="tx.price" [satoshis]="getTotalTxOutput(tx)"></app-amount>
</ng-template>
</button>
<ng-template #viewingAddress>
<button type="button" class="btn btn-sm mt-2 ml-2" (click)="switchCurrency()" [ngClass]="{'btn-success': tx['addressValue'] >= 0, 'btn-danger': tx['addressValue'] < 0}">
<app-amount [satoshis]="tx['addressValue']" [addPlus]="true"></app-amount>
<app-amount [blockConversion]="tx.price" [satoshis]="tx['addressValue']" [addPlus]="true"></app-amount>
</button>
</ng-template>
</div>

View File

@@ -9,6 +9,7 @@ import { AssetsService } from '../../services/assets.service';
import { filter, map, tap, switchMap } from 'rxjs/operators';
import { BlockExtended } from '../../interfaces/node-api.interface';
import { ApiService } from '../../services/api.service';
import { PriceService } from 'src/app/services/price.service';
@Component({
selector: 'app-transactions-list',
@@ -50,6 +51,7 @@ export class TransactionsListComponent implements OnInit, OnChanges {
private apiService: ApiService,
private assetsService: AssetsService,
private ref: ChangeDetectorRef,
private priceService: PriceService,
) { }
ngOnInit(): void {
@@ -147,6 +149,12 @@ export class TransactionsListComponent implements OnInit, OnChanges {
tx['addressValue'] = addressIn - addressOut;
}
this.priceService.getPrices().pipe(
tap(() => {
tx['price'] = this.priceService.getPriceForTimestamp(tx.status.block_time);
})
).subscribe();
});
const txIds = this.transactions.filter((tx) => !tx._outspends).map((tx) => tx.txid);
if (txIds.length) {