Add address transactions widget
This commit is contained in:
		
							parent
							
								
									ccb27dbdb9
								
							
						
					
					
						commit
						139c384e97
					
				| @ -32,7 +32,10 @@ | |||||||
|         "component": "blocks" |         "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 { ChangeDetectionStrategy, ChangeDetectorRef, Component, Inject, Input, LOCALE_ID, OnChanges, SimpleChanges } from '@angular/core'; | ||||||
| import { echarts, EChartsOption } from '../../graphs/echarts'; | import { echarts, EChartsOption } from '../../graphs/echarts'; | ||||||
| import { of } from 'rxjs'; | import { Observable, of } from 'rxjs'; | ||||||
| import { catchError } from 'rxjs/operators'; | 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 { ElectrsApiService } from '../../services/electrs-api.service'; | ||||||
| import { AmountShortenerPipe } from '../../shared/pipes/amount-shortener.pipe'; | import { AmountShortenerPipe } from '../../shared/pipes/amount-shortener.pipe'; | ||||||
| import { Router } from '@angular/router'; | import { Router } from '@angular/router'; | ||||||
| @ -36,6 +36,7 @@ export class AddressGraphComponent implements OnChanges { | |||||||
|   @Input() address: string; |   @Input() address: string; | ||||||
|   @Input() isPubkey: boolean = false; |   @Input() isPubkey: boolean = false; | ||||||
|   @Input() stats: ChainStats; |   @Input() stats: ChainStats; | ||||||
|  |   @Input() addressSummary$: Observable<AddressTxSummary[]> | null; | ||||||
|   @Input() period: '1d' | '3d' | '1w' | '1m' | '6m' | '1y' | 'all' = 'all'; |   @Input() period: '1d' | '3d' | '1w' | '1m' | '6m' | '1y' | 'all' = 'all'; | ||||||
|   @Input() height: number = 200; |   @Input() height: number = 200; | ||||||
|   @Input() right: number | string = 10; |   @Input() right: number | string = 10; | ||||||
| @ -69,14 +70,14 @@ export class AddressGraphComponent implements OnChanges { | |||||||
|     if (!this.address || !this.stats) { |     if (!this.address || !this.stats) { | ||||||
|       return; |       return; | ||||||
|     } |     } | ||||||
|     (this.isPubkey |     (this.addressSummary$ || (this.isPubkey | ||||||
|       ? this.electrsApiService.getScriptHashSummary$((this.address.length === 66 ? '21' : '41') + this.address + 'ac') |       ? this.electrsApiService.getScriptHashSummary$((this.address.length === 66 ? '21' : '41') + this.address + 'ac') | ||||||
|       : this.electrsApiService.getAddressSummary$(this.address)).pipe( |       : this.electrsApiService.getAddressSummary$(this.address)).pipe( | ||||||
|       catchError(e => { |       catchError(e => { | ||||||
|         this.error = `Failed to fetch address balance history: ${e?.status || ''} ${e?.statusText || 'unknown error'}`; |         this.error = `Failed to fetch address balance history: ${e?.status || ''} ${e?.statusText || 'unknown error'}`; | ||||||
|         return of(null); |         return of(null); | ||||||
|       }), |       }), | ||||||
|     ).subscribe(addressSummary => { |     )).subscribe(addressSummary => { | ||||||
|       if (addressSummary) { |       if (addressSummary) { | ||||||
|         this.error = null; |         this.error = null; | ||||||
|         this.prepareChartOptions(addressSummary); |         this.prepareChartOptions(addressSummary); | ||||||
|  | |||||||
| @ -2,7 +2,7 @@ import { ChangeDetectionStrategy, ChangeDetectorRef, Component, Input, OnChanges | |||||||
| import { StateService } from '../../services/state.service'; | import { StateService } from '../../services/state.service'; | ||||||
| import { Address, AddressTxSummary } from '../../interfaces/electrs.interface'; | import { Address, AddressTxSummary } from '../../interfaces/electrs.interface'; | ||||||
| import { ElectrsApiService } from '../../services/electrs-api.service'; | import { ElectrsApiService } from '../../services/electrs-api.service'; | ||||||
| import { catchError, of } from 'rxjs'; | import { Observable, catchError, of } from 'rxjs'; | ||||||
| 
 | 
 | ||||||
| @Component({ | @Component({ | ||||||
|   selector: 'app-balance-widget', |   selector: 'app-balance-widget', | ||||||
| @ -13,6 +13,7 @@ import { catchError, of } from 'rxjs'; | |||||||
| export class BalanceWidgetComponent implements OnInit, OnChanges { | export class BalanceWidgetComponent implements OnInit, OnChanges { | ||||||
|   @Input() address: string; |   @Input() address: string; | ||||||
|   @Input() addressInfo: Address; |   @Input() addressInfo: Address; | ||||||
|  |   @Input() addressSummary$: Observable<AddressTxSummary[]> | null; | ||||||
|   @Input() isPubkey: boolean = false; |   @Input() isPubkey: boolean = false; | ||||||
| 
 | 
 | ||||||
|   isLoading: boolean = true; |   isLoading: boolean = true; | ||||||
| @ -36,14 +37,14 @@ export class BalanceWidgetComponent implements OnInit, OnChanges { | |||||||
|     if (!this.address || !this.addressInfo) { |     if (!this.address || !this.addressInfo) { | ||||||
|       return; |       return; | ||||||
|     } |     } | ||||||
|     (this.isPubkey |     (this.addressSummary$ || (this.isPubkey | ||||||
|       ? this.electrsApiService.getScriptHashSummary$((this.address.length === 66 ? '21' : '41') + this.address + 'ac') |       ? this.electrsApiService.getScriptHashSummary$((this.address.length === 66 ? '21' : '41') + this.address + 'ac') | ||||||
|       : this.electrsApiService.getAddressSummary$(this.address)).pipe( |       : this.electrsApiService.getAddressSummary$(this.address)).pipe( | ||||||
|       catchError(e => { |       catchError(e => { | ||||||
|         this.error = `Failed to fetch address balance history: ${e?.status || ''} ${e?.statusText || 'unknown error'}`; |         this.error = `Failed to fetch address balance history: ${e?.status || ''} ${e?.statusText || 'unknown error'}`; | ||||||
|         return of(null); |         return of(null); | ||||||
|       }), |       }), | ||||||
|     ).subscribe(addressSummary => { |     )).subscribe(addressSummary => { | ||||||
|       if (addressSummary) { |       if (addressSummary) { | ||||||
|         this.error = null; |         this.error = null; | ||||||
|         this.calculateStats(addressSummary); |         this.calculateStats(addressSummary); | ||||||
|  | |||||||
| @ -226,7 +226,7 @@ | |||||||
|         @case ('balance') { |         @case ('balance') { | ||||||
|           <div class="col card-wrapper"> |           <div class="col card-wrapper"> | ||||||
|             <div class="main-title" i18n="dashboard.treasury">Treasury</div> |             <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> |           </div> | ||||||
|         } |         } | ||||||
|         @case ('address') { |         @case ('address') { | ||||||
| @ -234,7 +234,17 @@ | |||||||
|             <div class="card graph-card"> |             <div class="card graph-card"> | ||||||
|               <div class="card-body"> |               <div class="card-body"> | ||||||
|                 <h5 class="card-title mb-4" i18n="dashboard.balance-history">Balance History</h5> |                 <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> |             </div> | ||||||
|           </div> |           </div> | ||||||
|  | |||||||
| @ -1,6 +1,6 @@ | |||||||
| import { AfterViewInit, ChangeDetectionStrategy, Component, HostListener, Inject, OnDestroy, OnInit, PLATFORM_ID } from '@angular/core'; | import { AfterViewInit, ChangeDetectionStrategy, Component, HostListener, Inject, OnDestroy, OnInit, PLATFORM_ID } from '@angular/core'; | ||||||
| import { combineLatest, merge, Observable, of, Subject, Subscription } from 'rxjs'; | 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 { BlockExtended, OptimizedMempoolStats, TransactionStripped } from '../../interfaces/node-api.interface'; | ||||||
| import { MempoolInfo, ReplacementInfo } from '../../interfaces/websocket.interface'; | import { MempoolInfo, ReplacementInfo } from '../../interfaces/websocket.interface'; | ||||||
| import { ApiService } from '../../services/api.service'; | import { ApiService } from '../../services/api.service'; | ||||||
| @ -9,7 +9,7 @@ import { WebsocketService } from '../../services/websocket.service'; | |||||||
| import { SeoService } from '../../services/seo.service'; | import { SeoService } from '../../services/seo.service'; | ||||||
| import { ActiveFilter, FilterMode, GradientMode, toFlags } from '../../shared/filters.utils'; | import { ActiveFilter, FilterMode, GradientMode, toFlags } from '../../shared/filters.utils'; | ||||||
| import { detectWebGL } from '../../shared/graphs.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'; | import { ElectrsApiService } from '../../services/electrs-api.service'; | ||||||
| 
 | 
 | ||||||
| interface MempoolBlocksData { | interface MempoolBlocksData { | ||||||
| @ -61,6 +61,7 @@ export class CustomDashboardComponent implements OnInit, OnDestroy, AfterViewIni | |||||||
|   widgets; |   widgets; | ||||||
| 
 | 
 | ||||||
|   addressSubscription: Subscription; |   addressSubscription: Subscription; | ||||||
|  |   addressSummary$: Observable<AddressTxSummary[]>; | ||||||
|   address: Address; |   address: Address; | ||||||
| 
 | 
 | ||||||
|   goggleResolution = 82; |   goggleResolution = 82; | ||||||
| @ -298,6 +299,16 @@ export class CustomDashboardComponent implements OnInit, OnDestroy, AfterViewIni | |||||||
|           this.websocketService.startTrackAddress(address.address); |           this.websocketService.startTrackAddress(address.address); | ||||||
|           this.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 { DifficultyTooltipComponent } from '../components/difficulty/difficulty-tooltip.component'; | ||||||
| import { DifficultyMiningComponent } from '../components/difficulty-mining/difficulty-mining.component'; | import { DifficultyMiningComponent } from '../components/difficulty-mining/difficulty-mining.component'; | ||||||
| import { BalanceWidgetComponent } from '../components/balance-widget/balance-widget.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 { RbfTimelineComponent } from '../components/rbf-timeline/rbf-timeline.component'; | ||||||
| import { RbfTimelineTooltipComponent } from '../components/rbf-timeline/rbf-timeline-tooltip.component'; | import { RbfTimelineTooltipComponent } from '../components/rbf-timeline/rbf-timeline-tooltip.component'; | ||||||
| import { PushTransactionComponent } from '../components/push-transaction/push-transaction.component'; | import { PushTransactionComponent } from '../components/push-transaction/push-transaction.component'; | ||||||
| @ -175,6 +176,7 @@ import { OnlyVsizeDirective, OnlyWeightDirective } from './components/weight-dir | |||||||
|     DifficultyMiningComponent, |     DifficultyMiningComponent, | ||||||
|     DifficultyTooltipComponent, |     DifficultyTooltipComponent, | ||||||
|     BalanceWidgetComponent, |     BalanceWidgetComponent, | ||||||
|  |     AddressTransactionsWidgetComponent, | ||||||
|     RbfTimelineComponent, |     RbfTimelineComponent, | ||||||
|     RbfTimelineTooltipComponent, |     RbfTimelineTooltipComponent, | ||||||
|     PushTransactionComponent, |     PushTransactionComponent, | ||||||
| @ -312,6 +314,7 @@ import { OnlyVsizeDirective, OnlyWeightDirective } from './components/weight-dir | |||||||
|     DifficultyMiningComponent, |     DifficultyMiningComponent, | ||||||
|     DifficultyTooltipComponent, |     DifficultyTooltipComponent, | ||||||
|     BalanceWidgetComponent, |     BalanceWidgetComponent, | ||||||
|  |     AddressTransactionsWidgetComponent, | ||||||
|     RbfTimelineComponent, |     RbfTimelineComponent, | ||||||
|     RbfTimelineTooltipComponent, |     RbfTimelineTooltipComponent, | ||||||
|     PushTransactionComponent, |     PushTransactionComponent, | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user