mirror of
https://github.com/mempool/mempool.git
synced 2024-12-29 09:44:26 +01:00
Merge pull request #1304 from mempool/simon/highlight-address
Address page highlight and transfer value
This commit is contained in:
commit
74e8c18b9d
@ -62,7 +62,7 @@
|
|||||||
</h2>
|
</h2>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<app-transactions-list [transactions]="transactions" [showConfirmations]="true" (loadMore)="loadMore()"></app-transactions-list>
|
<app-transactions-list [transactions]="transactions" [showConfirmations]="true" [address]="address.address" (loadMore)="loadMore()"></app-transactions-list>
|
||||||
|
|
||||||
<div class="text-center">
|
<div class="text-center">
|
||||||
<ng-template [ngIf]="isLoadingTransactions">
|
<ng-template [ngIf]="isLoadingTransactions">
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
<ng-container *ngIf="!noFiat && (viewFiat$ | async) && (conversions$ | async) as conversions; else viewFiatVin">
|
<ng-container *ngIf="!noFiat && (viewFiat$ | async) && (conversions$ | async) as conversions; else viewFiatVin">
|
||||||
<span class="fiat">{{ conversions.USD * (satoshis / 100000000) | currency:'USD':'symbol':'1.2-2' }}</span>
|
<span class="fiat">{{ addPlus && satoshis >= 0 ? '+' : '' }}{{ conversions.USD * (satoshis / 100000000) | currency:'USD':'symbol':'1.2-2' }}</span>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
<ng-template #viewFiatVin>
|
<ng-template #viewFiatVin>
|
||||||
<ng-template [ngIf]="(network === 'liquid' || network === 'liquidtestnet') && (satoshis === undefined || satoshis === null)" [ngIfElse]="default">
|
<ng-template [ngIf]="(network === 'liquid' || network === 'liquidtestnet') && (satoshis === undefined || satoshis === null)" [ngIfElse]="default">
|
||||||
<span i18n="shared.confidential">Confidential</span>
|
<span i18n="shared.confidential">Confidential</span>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
<ng-template #default>
|
<ng-template #default>
|
||||||
‎{{ satoshis / 100000000 | number : digitsInfo }}
|
‎{{ addPlus && satoshis >= 0 ? '+' : '' }}{{ satoshis / 100000000 | number : digitsInfo }}
|
||||||
<span class="symbol"><ng-template [ngIf]="network === 'liquid'">L-</ng-template>
|
<span class="symbol"><ng-template [ngIf]="network === 'liquid'">L-</ng-template>
|
||||||
<ng-template [ngIf]="network === 'liquidtestnet'">tL-</ng-template>
|
<ng-template [ngIf]="network === 'liquidtestnet'">tL-</ng-template>
|
||||||
<ng-template [ngIf]="network === 'testnet'">t</ng-template>
|
<ng-template [ngIf]="network === 'testnet'">t</ng-template>
|
||||||
|
@ -18,6 +18,7 @@ export class AmountComponent implements OnInit, OnDestroy {
|
|||||||
@Input() satoshis: number;
|
@Input() satoshis: number;
|
||||||
@Input() digitsInfo = '1.8-8';
|
@Input() digitsInfo = '1.8-8';
|
||||||
@Input() noFiat = false;
|
@Input() noFiat = false;
|
||||||
|
@Input() addPlus = false;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private stateService: StateService,
|
private stateService: StateService,
|
||||||
|
@ -21,7 +21,10 @@
|
|||||||
<table class="table table-borderless smaller-text table-sm" id="table-tx-vin">
|
<table class="table table-borderless smaller-text table-sm" id="table-tx-vin">
|
||||||
<tbody>
|
<tbody>
|
||||||
<ng-template ngFor let-vin [ngForOf]="tx['@vinLimit'] ? ((tx.vin.length>12)?tx.vin.slice(0, 10): tx.vin.slice(0, 12)) : tx.vin" [ngForTrackBy]="trackByIndexFn">
|
<ng-template ngFor let-vin [ngForOf]="tx['@vinLimit'] ? ((tx.vin.length>12)?tx.vin.slice(0, 10): tx.vin.slice(0, 12)) : tx.vin" [ngForTrackBy]="trackByIndexFn">
|
||||||
<tr [ngClass]="assetsMinimal && vin.prevout && assetsMinimal[vin.prevout.asset] && !vin.is_coinbase && vin.prevout.scriptpubkey_address && tx._unblinded ? 'assetBox' : ''">
|
<tr [ngClass]="{
|
||||||
|
'assetBox': assetsMinimal && vin.prevout && assetsMinimal[vin.prevout.asset] && !vin.is_coinbase && vin.prevout.scriptpubkey_address && tx._unblinded,
|
||||||
|
'highlight': vin.prevout?.scriptpubkey_address === this.address && this.address !== ''
|
||||||
|
}">
|
||||||
<td class="arrow-td">
|
<td class="arrow-td">
|
||||||
<ng-template [ngIf]="vin.prevout === null && !vin.is_pegin" [ngIfElse]="hasPrevout">
|
<ng-template [ngIf]="vin.prevout === null && !vin.is_pegin" [ngIfElse]="hasPrevout">
|
||||||
<span class="grey">
|
<span class="grey">
|
||||||
@ -143,7 +146,10 @@
|
|||||||
<table class="table table-borderless smaller-text table-sm" id="table-tx-vout">
|
<table class="table table-borderless smaller-text table-sm" id="table-tx-vout">
|
||||||
<tbody>
|
<tbody>
|
||||||
<ng-template ngFor let-vout let-vindex="index" [ngForOf]="tx['@voutLimit'] && !outputIndex ? ((tx.vout.length > 12) ? tx.vout.slice(0, 10) : tx.vout.slice(0, 12)) : tx.vout" [ngForTrackBy]="trackByIndexFn">
|
<ng-template ngFor let-vout let-vindex="index" [ngForOf]="tx['@voutLimit'] && !outputIndex ? ((tx.vout.length > 12) ? tx.vout.slice(0, 10) : tx.vout.slice(0, 12)) : tx.vout" [ngForTrackBy]="trackByIndexFn">
|
||||||
<tr [ngClass]="assetsMinimal && assetsMinimal[vout.asset] && vout.scriptpubkey_address && tx.vin && !tx.vin[0].is_coinbase && tx._unblinded || outputIndex === vindex ? 'assetBox' : ''">
|
<tr [ngClass]="{
|
||||||
|
'assetBox': assetsMinimal && assetsMinimal[vout.asset] && vout.scriptpubkey_address && tx.vin && !tx.vin[0].is_coinbase && tx._unblinded || outputIndex === vindex,
|
||||||
|
'highlight': vout.scriptpubkey_address === this.address && this.address !== ''
|
||||||
|
}">
|
||||||
<td>
|
<td>
|
||||||
<a *ngIf="vout.scriptpubkey_address; else scriptpubkey_type" [routerLink]="['/address/' | relativeUrl, vout.scriptpubkey_address]" title="{{ vout.scriptpubkey_address }}">
|
<a *ngIf="vout.scriptpubkey_address; else scriptpubkey_type" [routerLink]="['/address/' | relativeUrl, vout.scriptpubkey_address]" title="{{ vout.scriptpubkey_address }}">
|
||||||
<span class="d-block d-lg-none">{{ vout.scriptpubkey_address | shortenString : 16 }}</span>
|
<span class="d-block d-lg-none">{{ vout.scriptpubkey_address | shortenString : 16 }}</span>
|
||||||
@ -242,13 +248,13 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div class="summary">
|
||||||
<div class="float-left mt-2-5" *ngIf="!transactionPage && !tx.vin[0].is_coinbase">
|
<div class="float-left mt-2-5" *ngIf="!transactionPage && !tx.vin[0].is_coinbase">
|
||||||
{{ 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"> – {{ 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"> – {{ tx.fee | number }} <span class="symbol" i18n="shared.sat|sat">sat</span> <span class="fiat"><app-fiat [value]="tx.fee"></app-fiat></span></span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="float-right">
|
<div class="float-right">
|
||||||
<span *ngIf="showConfirmations && latestBlock$ | async as latestBlock">
|
<ng-container *ngIf="showConfirmations && latestBlock$ | async as latestBlock">
|
||||||
<button *ngIf="tx.status.confirmed; else unconfirmedButton" type="button" class="btn btn-sm btn-success mt-2">
|
<button *ngIf="tx.status.confirmed; else unconfirmedButton" type="button" class="btn btn-sm btn-success mt-2">
|
||||||
<ng-container *ngTemplateOutlet="latestBlock.height - tx.status.block_height + 1 == 1 ? confirmationSingular : confirmationPlural; context: {$implicit: latestBlock.height - tx.status.block_height + 1}"></ng-container>
|
<ng-container *ngTemplateOutlet="latestBlock.height - tx.status.block_height + 1 == 1 ? confirmationSingular : confirmationPlural; context: {$implicit: latestBlock.height - tx.status.block_height + 1}"></ng-container>
|
||||||
<ng-template #confirmationSingular let-i i18n="shared.confirmation-count.singular|Transaction singular confirmation count">{{ i }} confirmation</ng-template>
|
<ng-template #confirmationSingular let-i i18n="shared.confirmation-count.singular|Transaction singular confirmation count">{{ i }} confirmation</ng-template>
|
||||||
@ -257,14 +263,18 @@
|
|||||||
<ng-template #unconfirmedButton>
|
<ng-template #unconfirmedButton>
|
||||||
<button type="button" class="btn btn-sm btn-danger mt-2" i18n="transaction.unconfirmed|Transaction unconfirmed state">Unconfirmed</button>
|
<button type="button" class="btn btn-sm btn-danger mt-2" i18n="transaction.unconfirmed|Transaction unconfirmed state">Unconfirmed</button>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
|
</ng-container>
|
||||||
</span>
|
<button *ngIf="address === ''; else viewingAddress" type="button" class="btn btn-sm btn-primary mt-2 ml-2" (click)="switchCurrency()">
|
||||||
<button type="button" class="btn btn-sm btn-primary mt-2" (click)="switchCurrency()">
|
|
||||||
<ng-template [ngIf]="(network === 'liquid' || network === 'liquidtestnet') && haveBlindedOutputValues(tx)" [ngIfElse]="defaultAmount" i18n="shared.confidential">Confidential</ng-template>
|
<ng-template [ngIf]="(network === 'liquid' || network === 'liquidtestnet') && haveBlindedOutputValues(tx)" [ngIfElse]="defaultAmount" i18n="shared.confidential">Confidential</ng-template>
|
||||||
<ng-template #defaultAmount>
|
<ng-template #defaultAmount>
|
||||||
<app-amount [satoshis]="getTotalTxOutput(tx)"></app-amount>
|
<app-amount [satoshis]="getTotalTxOutput(tx)"></app-amount>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
</button>
|
</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>
|
||||||
|
</button>
|
||||||
|
</ng-template>
|
||||||
</div>
|
</div>
|
||||||
<div class="clearfix"></div>
|
<div class="clearfix"></div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,10 +1,12 @@
|
|||||||
|
|
||||||
.arrow-td {
|
.arrow-td {
|
||||||
width: 20px;
|
width: 20px;
|
||||||
|
padding-top: 0;
|
||||||
|
padding-bottom: 0;
|
||||||
}
|
}
|
||||||
.green, .grey, .red {
|
.green, .grey, .red {
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
top: -2px;
|
top: 1px;
|
||||||
position: relative;
|
position: relative;
|
||||||
@media( min-width: 576px){
|
@media( min-width: 576px){
|
||||||
font-size: 19px;
|
font-size: 19px;
|
||||||
@ -119,3 +121,11 @@
|
|||||||
h2 {
|
h2 {
|
||||||
line-height: 1;
|
line-height: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.highlight {
|
||||||
|
background-color: #181b2d;
|
||||||
|
}
|
||||||
|
|
||||||
|
.summary {
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
import { Component, OnInit, Input, ChangeDetectionStrategy, OnChanges, Output, EventEmitter, ChangeDetectorRef } 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, of, Subject, Subscription } from 'rxjs';
|
import { Observable, forkJoin, ReplaySubject, BehaviorSubject, merge, Subscription } from 'rxjs';
|
||||||
import { Outspend, Transaction } from '../../interfaces/electrs.interface';
|
import { Outspend, Transaction, Vin, Vout } 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, tap } from 'rxjs/operators';
|
import { map, switchMap } from 'rxjs/operators';
|
||||||
import { BlockExtended } from 'src/app/interfaces/node-api.interface';
|
import { BlockExtended } from 'src/app/interfaces/node-api.interface';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
@ -23,6 +23,7 @@ export class TransactionsListComponent implements OnInit, OnChanges {
|
|||||||
@Input() transactionPage = false;
|
@Input() transactionPage = false;
|
||||||
@Input() errorUnblinded = false;
|
@Input() errorUnblinded = false;
|
||||||
@Input() outputIndex: number;
|
@Input() outputIndex: number;
|
||||||
|
@Input() address: string = '';
|
||||||
|
|
||||||
@Output() loadMore = new EventEmitter();
|
@Output() loadMore = new EventEmitter();
|
||||||
|
|
||||||
@ -98,6 +99,21 @@ export class TransactionsListComponent implements OnInit, OnChanges {
|
|||||||
if (this.outspends[i]) {
|
if (this.outspends[i]) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.address) {
|
||||||
|
const addressIn = tx.vout
|
||||||
|
.filter((v: Vout) => v.scriptpubkey_address === this.address)
|
||||||
|
.map((v: Vout) => v.value || 0)
|
||||||
|
.reduce((a: number, b: number) => a + b, 0);
|
||||||
|
|
||||||
|
const addressOut = tx.vin
|
||||||
|
.filter((v: Vin) => v.prevout && v.prevout.scriptpubkey_address === this.address)
|
||||||
|
.map((v: Vin) => v.prevout.value || 0)
|
||||||
|
.reduce((a: number, b: number) => a + b, 0);
|
||||||
|
|
||||||
|
tx['addressValue'] = addressIn || -addressOut;
|
||||||
|
}
|
||||||
|
|
||||||
observableObject[i] = this.electrsApiService.getOutspends$(tx.txid);
|
observableObject[i] = this.electrsApiService.getOutspends$(tx.txid);
|
||||||
});
|
});
|
||||||
this.refreshOutspends$.next(observableObject);
|
this.refreshOutspends$.next(observableObject);
|
||||||
@ -119,7 +135,7 @@ export class TransactionsListComponent implements OnInit, OnChanges {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getTotalTxOutput(tx: Transaction) {
|
getTotalTxOutput(tx: Transaction) {
|
||||||
return tx.vout.map((v: any) => v.value || 0).reduce((a: number, b: number) => a + b);
|
return tx.vout.map((v: Vout) => v.value || 0).reduce((a: number, b: number) => a + b);
|
||||||
}
|
}
|
||||||
|
|
||||||
switchCurrency() {
|
switchCurrency() {
|
||||||
|
@ -72,7 +72,7 @@ export interface Vout {
|
|||||||
scriptpubkey: string;
|
scriptpubkey: string;
|
||||||
scriptpubkey_asm: string;
|
scriptpubkey_asm: string;
|
||||||
scriptpubkey_type: string;
|
scriptpubkey_type: string;
|
||||||
scriptpubkey_address: string;
|
scriptpubkey_address?: string;
|
||||||
value: number;
|
value: number;
|
||||||
// Elements
|
// Elements
|
||||||
valuecommitment?: number;
|
valuecommitment?: number;
|
||||||
|
Loading…
Reference in New Issue
Block a user