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