Add address transactions widget

This commit is contained in:
Mononaut 2024-04-26 19:16:09 +00:00
parent ccb27dbdb9
commit 139c384e97
No known key found for this signature in database
GPG Key ID: A3F058E41374C04E
6 changed files with 41 additions and 12 deletions

@ -32,7 +32,10 @@
"component": "blocks"
},
{
"component": "transactions"
"component": "addressTransactions",
"props": {
"address": "32ixEdVJWo3kmvJGMTZq5jAQVZZeuwnqzo"
}
}
]
}

@ -1,8 +1,8 @@
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, Inject, Input, LOCALE_ID, OnChanges, SimpleChanges } from '@angular/core';
import { echarts, EChartsOption } from '../../graphs/echarts';
import { of } from 'rxjs';
import { Observable, of } from 'rxjs';
import { catchError } from 'rxjs/operators';
import { ChainStats } from '../../interfaces/electrs.interface';
import { AddressTxSummary, ChainStats } from '../../interfaces/electrs.interface';
import { ElectrsApiService } from '../../services/electrs-api.service';
import { AmountShortenerPipe } from '../../shared/pipes/amount-shortener.pipe';
import { Router } from '@angular/router';
@ -36,6 +36,7 @@ export class AddressGraphComponent implements OnChanges {
@Input() address: string;
@Input() isPubkey: boolean = false;
@Input() stats: ChainStats;
@Input() addressSummary$: Observable<AddressTxSummary[]> | null;
@Input() period: '1d' | '3d' | '1w' | '1m' | '6m' | '1y' | 'all' = 'all';
@Input() height: number = 200;
@Input() right: number | string = 10;
@ -69,14 +70,14 @@ export class AddressGraphComponent implements OnChanges {
if (!this.address || !this.stats) {
return;
}
(this.isPubkey
(this.addressSummary$ || (this.isPubkey
? this.electrsApiService.getScriptHashSummary$((this.address.length === 66 ? '21' : '41') + this.address + 'ac')
: this.electrsApiService.getAddressSummary$(this.address)).pipe(
catchError(e => {
this.error = `Failed to fetch address balance history: ${e?.status || ''} ${e?.statusText || 'unknown error'}`;
return of(null);
}),
).subscribe(addressSummary => {
)).subscribe(addressSummary => {
if (addressSummary) {
this.error = null;
this.prepareChartOptions(addressSummary);

@ -2,7 +2,7 @@ import { ChangeDetectionStrategy, ChangeDetectorRef, Component, Input, OnChanges
import { StateService } from '../../services/state.service';
import { Address, AddressTxSummary } from '../../interfaces/electrs.interface';
import { ElectrsApiService } from '../../services/electrs-api.service';
import { catchError, of } from 'rxjs';
import { Observable, catchError, of } from 'rxjs';
@Component({
selector: 'app-balance-widget',
@ -13,6 +13,7 @@ import { catchError, of } from 'rxjs';
export class BalanceWidgetComponent implements OnInit, OnChanges {
@Input() address: string;
@Input() addressInfo: Address;
@Input() addressSummary$: Observable<AddressTxSummary[]> | null;
@Input() isPubkey: boolean = false;
isLoading: boolean = true;
@ -36,14 +37,14 @@ export class BalanceWidgetComponent implements OnInit, OnChanges {
if (!this.address || !this.addressInfo) {
return;
}
(this.isPubkey
(this.addressSummary$ || (this.isPubkey
? this.electrsApiService.getScriptHashSummary$((this.address.length === 66 ? '21' : '41') + this.address + 'ac')
: this.electrsApiService.getAddressSummary$(this.address)).pipe(
catchError(e => {
this.error = `Failed to fetch address balance history: ${e?.status || ''} ${e?.statusText || 'unknown error'}`;
return of(null);
}),
).subscribe(addressSummary => {
)).subscribe(addressSummary => {
if (addressSummary) {
this.error = null;
this.calculateStats(addressSummary);

@ -226,7 +226,7 @@
@case ('balance') {
<div class="col card-wrapper">
<div class="main-title" i18n="dashboard.treasury">Treasury</div>
<app-balance-widget [address]="widget.props.address" [addressInfo]="address"></app-balance-widget>
<app-balance-widget [address]="widget.props.address" [addressSummary$]="addressSummary$" [addressInfo]="address"></app-balance-widget>
</div>
}
@case ('address') {
@ -234,7 +234,17 @@
<div class="card graph-card">
<div class="card-body">
<h5 class="card-title mb-4" i18n="dashboard.balance-history">Balance History</h5>
<app-address-graph [address]="widget.props.address" [period]="widget.props.period || 'all'" [stats]="address?.chain_stats" [widget]="true" [height]="graphHeight"></app-address-graph>
<app-address-graph [address]="widget.props.address" [addressSummary$]="addressSummary$" [period]="widget.props.period || 'all'" [stats]="address?.chain_stats" [widget]="true" [height]="graphHeight"></app-address-graph>
</div>
</div>
</div>
}
@case ('addressTransactions') {
<div class="col" style="max-height: 410px">
<div class="card">
<div class="card-body">
<h5 class="card-title" i18n="dashboard.treasury-transactions">Treasury Transactions</h5>
<app-address-transactions-widget [address]="widget.props.address" [addressSummary$]="addressSummary$" [addressInfo]="address"></app-address-transactions-widget>
</div>
</div>
</div>

@ -1,6 +1,6 @@
import { AfterViewInit, ChangeDetectionStrategy, Component, HostListener, Inject, OnDestroy, OnInit, PLATFORM_ID } from '@angular/core';
import { combineLatest, merge, Observable, of, Subject, Subscription } from 'rxjs';
import { catchError, filter, map, scan, shareReplay, switchMap, tap } from 'rxjs/operators';
import { catchError, filter, map, scan, share, shareReplay, switchMap, tap } from 'rxjs/operators';
import { BlockExtended, OptimizedMempoolStats, TransactionStripped } from '../../interfaces/node-api.interface';
import { MempoolInfo, ReplacementInfo } from '../../interfaces/websocket.interface';
import { ApiService } from '../../services/api.service';
@ -9,7 +9,7 @@ import { WebsocketService } from '../../services/websocket.service';
import { SeoService } from '../../services/seo.service';
import { ActiveFilter, FilterMode, GradientMode, toFlags } from '../../shared/filters.utils';
import { detectWebGL } from '../../shared/graphs.utils';
import { Address } from '../../interfaces/electrs.interface';
import { Address, AddressTxSummary } from '../../interfaces/electrs.interface';
import { ElectrsApiService } from '../../services/electrs-api.service';
interface MempoolBlocksData {
@ -61,6 +61,7 @@ export class CustomDashboardComponent implements OnInit, OnDestroy, AfterViewIni
widgets;
addressSubscription: Subscription;
addressSummary$: Observable<AddressTxSummary[]>;
address: Address;
goggleResolution = 82;
@ -298,6 +299,16 @@ export class CustomDashboardComponent implements OnInit, OnDestroy, AfterViewIni
this.websocketService.startTrackAddress(address.address);
this.address = address;
});
this.addressSummary$ = (
addressString.match(/04[a-fA-F0-9]{128}|(02|03)[a-fA-F0-9]{64}/)
? this.electrsApiService.getScriptHashSummary$((addressString.length === 66 ? '21' : '41') + addressString + 'ac')
: this.electrsApiService.getAddressSummary$(addressString)).pipe(
catchError(e => {
return of(null);
}),
share(),
);
}
}

@ -66,6 +66,7 @@ import { DifficultyComponent } from '../components/difficulty/difficulty.compone
import { DifficultyTooltipComponent } from '../components/difficulty/difficulty-tooltip.component';
import { DifficultyMiningComponent } from '../components/difficulty-mining/difficulty-mining.component';
import { BalanceWidgetComponent } from '../components/balance-widget/balance-widget.component';
import { AddressTransactionsWidgetComponent } from '../components/address-transactions-widget/address-transactions-widget.component';
import { RbfTimelineComponent } from '../components/rbf-timeline/rbf-timeline.component';
import { RbfTimelineTooltipComponent } from '../components/rbf-timeline/rbf-timeline-tooltip.component';
import { PushTransactionComponent } from '../components/push-transaction/push-transaction.component';
@ -175,6 +176,7 @@ import { OnlyVsizeDirective, OnlyWeightDirective } from './components/weight-dir
DifficultyMiningComponent,
DifficultyTooltipComponent,
BalanceWidgetComponent,
AddressTransactionsWidgetComponent,
RbfTimelineComponent,
RbfTimelineTooltipComponent,
PushTransactionComponent,
@ -312,6 +314,7 @@ import { OnlyVsizeDirective, OnlyWeightDirective } from './components/weight-dir
DifficultyMiningComponent,
DifficultyTooltipComponent,
BalanceWidgetComponent,
AddressTransactionsWidgetComponent,
RbfTimelineComponent,
RbfTimelineTooltipComponent,
PushTransactionComponent,