Merge branch 'master' into feature/mining-dashboard-skeleton
This commit is contained in:
		
						commit
						593e82d8f4
					
				| @ -332,11 +332,18 @@ class WebsocketHandler { | ||||
|       } | ||||
| 
 | ||||
|       if (client['track-tx']) { | ||||
|         const utxoSpent = newTransactions.some((tx) => { | ||||
|           return tx.vin.some((vin) => vin.txid === client['track-tx']); | ||||
|         }); | ||||
|         if (utxoSpent) { | ||||
|           response['utxoSpent'] = true; | ||||
|         const outspends: object = {}; | ||||
|         newTransactions.forEach((tx) => tx.vin.forEach((vin, i) => { | ||||
|           if (vin.txid === client['track-tx']) { | ||||
|             outspends[vin.vout] = { | ||||
|               vin: i, | ||||
|               txid: tx.txid, | ||||
|             }; | ||||
|           } | ||||
|         })); | ||||
| 
 | ||||
|         if (Object.keys(outspends).length) { | ||||
|           response['utxoSpent'] = outspends; | ||||
|         } | ||||
| 
 | ||||
|         if (rbfTransactions[client['track-tx']]) { | ||||
| @ -414,7 +421,6 @@ class WebsocketHandler { | ||||
|       } | ||||
| 
 | ||||
|       if (client['track-tx'] && txIds.indexOf(client['track-tx']) > -1) { | ||||
|         client['track-tx'] = null; | ||||
|         response['txConfirmed'] = true; | ||||
|       } | ||||
| 
 | ||||
|  | ||||
| @ -186,16 +186,16 @@ | ||||
|                     <app-amount [satoshis]="vout.value"></app-amount> | ||||
|                   </ng-template> | ||||
|                 </td> | ||||
|                 <td class="arrow-td" *ngIf="{ value: (outspends$ | async) } as outspends"> | ||||
|                   <span *ngIf="!outspends.value || !outspends.value[i] || vout.scriptpubkey_type === 'op_return' || vout.scriptpubkey_type === 'fee' ; else outspend" class="grey"> | ||||
|                 <td class="arrow-td"> | ||||
|                   <span *ngIf="!outspends[i] || vout.scriptpubkey_type === 'op_return' || vout.scriptpubkey_type === 'fee' ; else outspend" class="grey"> | ||||
|                     <fa-icon [icon]="['fas', 'arrow-alt-circle-right']" [fixedWidth]="true"></fa-icon> | ||||
|                   </span> | ||||
|                   <ng-template #outspend> | ||||
|                     <span *ngIf="!outspends.value[i][vindex] || !outspends.value[i][vindex].spent; else spent" class="green"> | ||||
|                     <span *ngIf="!outspends[i][vindex] || !outspends[i][vindex].spent; else spent" class="green"> | ||||
|                       <fa-icon [icon]="['fas', 'arrow-alt-circle-right']" [fixedWidth]="true"></fa-icon> | ||||
|                     </span> | ||||
|                     <ng-template #spent> | ||||
|                       <a *ngIf="outspends.value[i][vindex].txid else outputNoTxId" [routerLink]="['/tx/' | relativeUrl, outspends.value[i][vindex].txid]" class="red"> | ||||
|                       <a *ngIf="outspends[i][vindex].txid else outputNoTxId" [routerLink]="['/tx/' | relativeUrl, outspends[i][vindex].txid]" class="red"> | ||||
|                         <fa-icon [icon]="['fas', 'arrow-alt-circle-right']" [fixedWidth]="true"></fa-icon> | ||||
|                       </a> | ||||
|                       <ng-template #outputNoTxId> | ||||
|  | ||||
| @ -1,11 +1,11 @@ | ||||
| import { Component, OnInit, Input, ChangeDetectionStrategy, OnChanges, Output, EventEmitter } from '@angular/core'; | ||||
| import { Component, OnInit, Input, ChangeDetectionStrategy, OnChanges, Output, EventEmitter, ChangeDetectorRef } from '@angular/core'; | ||||
| import { StateService } from '../../services/state.service'; | ||||
| import { Observable, forkJoin, ReplaySubject, BehaviorSubject, merge } from 'rxjs'; | ||||
| import { Observable, forkJoin, ReplaySubject, BehaviorSubject, merge, of, Subject, Subscription } from 'rxjs'; | ||||
| import { Outspend, Transaction } from '../../interfaces/electrs.interface'; | ||||
| import { ElectrsApiService } from '../../services/electrs-api.service'; | ||||
| import { environment } from 'src/environments/environment'; | ||||
| import { AssetsService } from 'src/app/services/assets.service'; | ||||
| import { map, share, switchMap } from 'rxjs/operators'; | ||||
| import { map, share, switchMap, tap } from 'rxjs/operators'; | ||||
| import { BlockExtended } from 'src/app/interfaces/node-api.interface'; | ||||
| 
 | ||||
| @Component({ | ||||
| @ -27,41 +27,18 @@ export class TransactionsListComponent implements OnInit, OnChanges { | ||||
|   @Output() loadMore = new EventEmitter(); | ||||
| 
 | ||||
|   latestBlock$: Observable<BlockExtended>; | ||||
|   outspends$: Observable<Outspend[]>; | ||||
|   outspendsSubscription: Subscription; | ||||
|   refreshOutspends$: ReplaySubject<object> = new ReplaySubject(); | ||||
|   showDetails$ = new BehaviorSubject<boolean>(false); | ||||
|   _outspends: Outspend[] = []; | ||||
|   outspends: Outspend[][] = []; | ||||
|   assetsMinimal: any; | ||||
| 
 | ||||
|   constructor( | ||||
|     public stateService: StateService, | ||||
|     private electrsApiService: ElectrsApiService, | ||||
|     private assetsService: AssetsService, | ||||
|   ) { | ||||
|     this.outspends$ = merge( | ||||
|       this.refreshOutspends$, | ||||
|       this.stateService.utxoSpent$ | ||||
|         .pipe( | ||||
|           map(() => { | ||||
|             this._outspends = []; | ||||
|             return { 0: this.electrsApiService.getOutspends$(this.transactions[0].txid) }; | ||||
|           }), | ||||
|         ) | ||||
|     ).pipe( | ||||
|       switchMap((observableObject) => forkJoin(observableObject)), | ||||
|       map((outspends: any) => { | ||||
|         const newOutspends = []; | ||||
|         for (const i in outspends) { | ||||
|           if (outspends.hasOwnProperty(i)) { | ||||
|             newOutspends.push(outspends[i]); | ||||
|           } | ||||
|         } | ||||
|         this._outspends = this._outspends.concat(newOutspends); | ||||
|         return this._outspends; | ||||
|       }), | ||||
|       share(), | ||||
|     ); | ||||
|   } | ||||
|     private ref: ChangeDetectorRef, | ||||
|   ) { } | ||||
| 
 | ||||
|   ngOnInit() { | ||||
|     this.latestBlock$ = this.stateService.blocks$.pipe(map(([block]) => block)); | ||||
| @ -72,6 +49,34 @@ export class TransactionsListComponent implements OnInit, OnChanges { | ||||
|         this.assetsMinimal = assets; | ||||
|       }); | ||||
|     } | ||||
| 
 | ||||
|     this.outspendsSubscription = merge( | ||||
|       this.refreshOutspends$ | ||||
|         .pipe( | ||||
|           switchMap((observableObject) => forkJoin(observableObject)), | ||||
|           map((outspends: any) => { | ||||
|             const newOutspends: Outspend[] = []; | ||||
|             for (const i in outspends) { | ||||
|               if (outspends.hasOwnProperty(i)) { | ||||
|                 newOutspends.push(outspends[i]); | ||||
|               } | ||||
|             } | ||||
|             this.outspends = this.outspends.concat(newOutspends); | ||||
|           }), | ||||
|         ), | ||||
|       this.stateService.utxoSpent$ | ||||
|         .pipe( | ||||
|           map((utxoSpent) => { | ||||
|             for (const i in utxoSpent) { | ||||
|               this.outspends[0][i] = { | ||||
|                 spent: true, | ||||
|                 txid: utxoSpent[i].txid, | ||||
|                 vin: utxoSpent[i].vin, | ||||
|               }; | ||||
|             } | ||||
|           }), | ||||
|         ) | ||||
|     ).subscribe(() => this.ref.markForCheck()); | ||||
|   } | ||||
| 
 | ||||
|   ngOnChanges() { | ||||
| @ -90,7 +95,7 @@ export class TransactionsListComponent implements OnInit, OnChanges { | ||||
|     this.transactions.forEach((tx, i) => { | ||||
|       tx['@voutLimit'] = true; | ||||
|       tx['@vinLimit'] = true; | ||||
|       if (this._outspends[i]) { | ||||
|       if (this.outspends[i]) { | ||||
|         return; | ||||
|       } | ||||
|       observableObject[i] = this.electrsApiService.getOutspends$(tx.txid); | ||||
| @ -149,4 +154,8 @@ export class TransactionsListComponent implements OnInit, OnChanges { | ||||
|       this.showDetails$.next(true); | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   ngOnDestroy() { | ||||
|     this.outspendsSubscription.unsubscribe(); | ||||
|   } | ||||
| } | ||||
|  | ||||
| @ -16,7 +16,7 @@ export interface WebsocketResponse { | ||||
|   data?: string[]; | ||||
|   tx?: Transaction; | ||||
|   rbfTransaction?: Transaction; | ||||
|   utxoSpent?: boolean; | ||||
|   utxoSpent?: object; | ||||
|   transactions?: TransactionStripped[]; | ||||
|   loadingIndicators?: ILoadingIndicators; | ||||
|   backendInfo?: IBackendInfo; | ||||
|  | ||||
| @ -81,7 +81,7 @@ export class StateService { | ||||
|   mempoolInfo$ = new ReplaySubject<MempoolInfo>(1); | ||||
|   mempoolBlocks$ = new ReplaySubject<MempoolBlock[]>(1); | ||||
|   txReplaced$ = new Subject<Transaction>(); | ||||
|   utxoSpent$ = new Subject<null>(); | ||||
|   utxoSpent$ = new Subject<object>(); | ||||
|   mempoolTransactions$ = new Subject<Transaction>(); | ||||
|   blockTransactions$ = new Subject<Transaction>(); | ||||
|   isLoadingWebSocket$ = new ReplaySubject<boolean>(1); | ||||
|  | ||||
| @ -252,7 +252,7 @@ export class WebsocketService { | ||||
|     } | ||||
| 
 | ||||
|     if (response.utxoSpent) { | ||||
|       this.stateService.utxoSpent$.next(); | ||||
|       this.stateService.utxoSpent$.next(response.utxoSpent); | ||||
|     } | ||||
| 
 | ||||
|     if (response.backendInfo) { | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user