Merge branch 'master' into alt-tx-unfurls
This commit is contained in:
@@ -10,7 +10,7 @@
|
||||
<ng-template #blocksPlural let-i i18n="shared.blocks">{{ i }} <span class="shared-block">blocks</span></ng-template>
|
||||
<ng-template #blocksSingular let-i i18n="shared.block">{{ i }} <span class="shared-block">block</span></ng-template>
|
||||
</div>
|
||||
<div class="symbol"><app-time-until [time]="epochData.remainingTime" [fastRender]="true"></app-time-until></div>
|
||||
<div class="symbol"><app-time-until [time]="epochData.estimatedRetargetDate" [fastRender]="true"></app-time-until></div>
|
||||
</div>
|
||||
<div class="item">
|
||||
<h5 class="card-title" i18n="difficulty-box.estimate">Estimate</h5>
|
||||
|
||||
@@ -11,7 +11,7 @@ interface EpochProgress {
|
||||
newDifficultyHeight: number;
|
||||
colorAdjustments: string;
|
||||
colorPreviousAdjustments: string;
|
||||
remainingTime: number;
|
||||
estimatedRetargetDate: number;
|
||||
previousRetarget: number;
|
||||
blocksUntilHalving: number;
|
||||
timeUntilHalving: number;
|
||||
@@ -74,7 +74,7 @@ export class DifficultyComponent implements OnInit {
|
||||
colorAdjustments,
|
||||
colorPreviousAdjustments,
|
||||
newDifficultyHeight: da.nextRetargetHeight,
|
||||
remainingTime: da.remainingTime,
|
||||
estimatedRetargetDate: da.estimatedRetargetDate,
|
||||
previousRetarget: da.previousRetarget,
|
||||
blocksUntilHalving,
|
||||
timeUntilHalving,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<form [formGroup]="searchForm" (submit)="searchForm.valid && search()" novalidate>
|
||||
<div class="d-flex">
|
||||
<div class="search-box-container mr-2">
|
||||
<input (focus)="focus$.next($any($event).target.value)" (click)="click$.next($any($event).target.value)" formControlName="searchText" type="text" class="form-control" i18n-placeholder="search-form.searchbar-placeholder" placeholder="TXID, block height, hash or address">
|
||||
<input (focus)="focus$.next($any($event).target.value)" (click)="click$.next($any($event).target.value)" formControlName="searchText" type="text" class="form-control" i18n-placeholder="search-form.searchbar-placeholder" placeholder="Search the full Bitcoin ecosystem">
|
||||
|
||||
<app-search-results #searchResults [results]="typeAhead$ | async" [searchTerm]="searchForm.get('searchText').value" (selectedResult)="selectedResult($event)"></app-search-results>
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
<div class="col">
|
||||
<table class="table table-borderless smaller-text table-sm table-tx-vin">
|
||||
<tbody>
|
||||
<ng-template ngFor let-vin [ngForOf]="tx['@vinLimit'] ? ((tx.vin.length > rowLimit) ? tx.vin.slice(0, rowLimit - 2) : tx.vin.slice(0, rowLimit)) : tx.vin" [ngForTrackBy]="trackByIndexFn">
|
||||
<ng-template ngFor let-vin let-vindex="index" [ngForOf]="tx['@vinLimit'] ? ((tx.vin.length > rowLimit) ? tx.vin.slice(0, rowLimit - 2) : tx.vin.slice(0, rowLimit)) : tx.vin" [ngForTrackBy]="trackByIndexFn">
|
||||
<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 !== ''
|
||||
@@ -77,7 +77,7 @@
|
||||
{{ vin.prevout.scriptpubkey_type?.toUpperCase() }}
|
||||
</ng-template>
|
||||
<div>
|
||||
<app-address-labels [vin]="vin" [channel]="channels && channels.inputs[i] || null"></app-address-labels>
|
||||
<app-address-labels [vin]="vin" [channel]="tx._channels && tx._channels.inputs[vindex] || null"></app-address-labels>
|
||||
</div>
|
||||
</ng-template>
|
||||
</ng-container>
|
||||
@@ -172,7 +172,7 @@
|
||||
</span>
|
||||
</a>
|
||||
<div>
|
||||
<app-address-labels [vout]="vout" [channel]="channels && channels.outputs[i] && channels.outputs[i].transaction_vout === vindex ? channels.outputs[i] : null"></app-address-labels>
|
||||
<app-address-labels [vout]="vout" [channel]="tx._channels && tx._channels.outputs[vindex] ? tx._channels.outputs[vindex] : null"></app-address-labels>
|
||||
</div>
|
||||
<ng-template #scriptpubkey_type>
|
||||
<ng-template [ngIf]="vout.pegout" [ngIfElse]="defaultscriptpubkey_type">
|
||||
@@ -212,15 +212,15 @@
|
||||
</ng-template>
|
||||
</td>
|
||||
<td class="arrow-td">
|
||||
<span *ngIf="!outspends[i] || vout.scriptpubkey_type === 'op_return' || vout.scriptpubkey_type === 'fee' ; else outspend" class="grey">
|
||||
<span *ngIf="!tx._outspends || 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[i][vindex] || !outspends[i][vindex].spent; else spent" class="green">
|
||||
<span *ngIf="!tx._outspends[vindex] || !tx._outspends[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[i][vindex].txid else outputNoTxId" [routerLink]="['/tx/' | relativeUrl, outspends[i][vindex].txid]" class="red">
|
||||
<a *ngIf="tx._outspends[vindex].txid else outputNoTxId" [routerLink]="['/tx/' | relativeUrl, tx._outspends[vindex].txid]" class="red">
|
||||
<fa-icon [icon]="['fas', 'arrow-alt-circle-right']" [fixedWidth]="true"></fa-icon>
|
||||
</a>
|
||||
<ng-template #outputNoTxId>
|
||||
|
||||
@@ -27,7 +27,6 @@ export class TransactionsListComponent implements OnInit, OnChanges {
|
||||
@Input() outputIndex: number;
|
||||
@Input() address: string = '';
|
||||
@Input() rowLimit = 12;
|
||||
@Input() channels: { inputs: any[], outputs: any[] };
|
||||
|
||||
@Output() loadMore = new EventEmitter();
|
||||
|
||||
@@ -36,8 +35,8 @@ export class TransactionsListComponent implements OnInit, OnChanges {
|
||||
refreshOutspends$: ReplaySubject<string[]> = new ReplaySubject();
|
||||
refreshChannels$: ReplaySubject<string[]> = new ReplaySubject();
|
||||
showDetails$ = new BehaviorSubject<boolean>(false);
|
||||
outspends: Outspend[][] = [];
|
||||
assetsMinimal: any;
|
||||
transactionsLength: number = 0;
|
||||
|
||||
constructor(
|
||||
public stateService: StateService,
|
||||
@@ -47,7 +46,7 @@ export class TransactionsListComponent implements OnInit, OnChanges {
|
||||
private ref: ChangeDetectorRef,
|
||||
) { }
|
||||
|
||||
ngOnInit() {
|
||||
ngOnInit(): void {
|
||||
this.latestBlock$ = this.stateService.blocks$.pipe(map(([block]) => block));
|
||||
this.stateService.networkChanged$.subscribe((network) => this.network = network);
|
||||
|
||||
@@ -62,14 +61,17 @@ export class TransactionsListComponent implements OnInit, OnChanges {
|
||||
.pipe(
|
||||
switchMap((txIds) => this.apiService.getOutspendsBatched$(txIds)),
|
||||
tap((outspends: Outspend[][]) => {
|
||||
this.outspends = this.outspends.concat(outspends);
|
||||
const transactions = this.transactions.filter((tx) => !tx._outspends);
|
||||
outspends.forEach((outspend, i) => {
|
||||
transactions[i]._outspends = outspend;
|
||||
});
|
||||
}),
|
||||
),
|
||||
this.stateService.utxoSpent$
|
||||
.pipe(
|
||||
tap((utxoSpent) => {
|
||||
for (const i in utxoSpent) {
|
||||
this.outspends[0][i] = {
|
||||
this.transactions[0]._outspends[i] = {
|
||||
spent: true,
|
||||
txid: utxoSpent[i].txid,
|
||||
vin: utxoSpent[i].vin,
|
||||
@@ -81,21 +83,23 @@ export class TransactionsListComponent implements OnInit, OnChanges {
|
||||
.pipe(
|
||||
filter(() => this.stateService.env.LIGHTNING),
|
||||
switchMap((txIds) => this.apiService.getChannelByTxIds$(txIds)),
|
||||
map((channels) => {
|
||||
this.channels = channels;
|
||||
tap((channels) => {
|
||||
const transactions = this.transactions.filter((tx) => !tx._channels);
|
||||
channels.forEach((channel, i) => {
|
||||
transactions[i]._channels = channel;
|
||||
});
|
||||
}),
|
||||
)
|
||||
,
|
||||
).subscribe(() => this.ref.markForCheck());
|
||||
}
|
||||
|
||||
ngOnChanges() {
|
||||
ngOnChanges(): void {
|
||||
if (!this.transactions || !this.transactions.length) {
|
||||
return;
|
||||
}
|
||||
if (this.paginated) {
|
||||
this.outspends = [];
|
||||
}
|
||||
|
||||
this.transactionsLength = this.transactions.length;
|
||||
if (this.outputIndex) {
|
||||
setTimeout(() => {
|
||||
const assetBoxElements = document.getElementsByClassName('assetBox');
|
||||
@@ -105,10 +109,10 @@ export class TransactionsListComponent implements OnInit, OnChanges {
|
||||
}, 10);
|
||||
}
|
||||
|
||||
this.transactions.forEach((tx, i) => {
|
||||
this.transactions.forEach((tx) => {
|
||||
tx['@voutLimit'] = true;
|
||||
tx['@vinLimit'] = true;
|
||||
if (this.outspends[i]) {
|
||||
if (tx['addressValue'] !== undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -126,14 +130,19 @@ export class TransactionsListComponent implements OnInit, OnChanges {
|
||||
tx['addressValue'] = addressIn - addressOut;
|
||||
}
|
||||
});
|
||||
const txIds = this.transactions.map((tx) => tx.txid);
|
||||
this.refreshOutspends$.next(txIds);
|
||||
if (!this.channels) {
|
||||
this.refreshChannels$.next(txIds);
|
||||
const txIds = this.transactions.filter((tx) => !tx._outspends).map((tx) => tx.txid);
|
||||
if (txIds.length) {
|
||||
this.refreshOutspends$.next(txIds);
|
||||
}
|
||||
if (this.stateService.env.LIGHTNING) {
|
||||
const txIds = this.transactions.filter((tx) => !tx._channels).map((tx) => tx.txid);
|
||||
if (txIds.length) {
|
||||
this.refreshChannels$.next(txIds);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onScroll() {
|
||||
onScroll(): void {
|
||||
const scrollHeight = document.body.scrollHeight;
|
||||
const scrollTop = document.documentElement.scrollTop;
|
||||
if (scrollHeight > 0){
|
||||
@@ -148,11 +157,11 @@ export class TransactionsListComponent implements OnInit, OnChanges {
|
||||
return tx.vout.some((v: any) => v.value === undefined);
|
||||
}
|
||||
|
||||
getTotalTxOutput(tx: Transaction) {
|
||||
getTotalTxOutput(tx: Transaction): number {
|
||||
return tx.vout.map((v: Vout) => v.value || 0).reduce((a: number, b: number) => a + b);
|
||||
}
|
||||
|
||||
switchCurrency() {
|
||||
switchCurrency(): void {
|
||||
if (this.network === 'liquid' || this.network === 'liquidtestnet') {
|
||||
return;
|
||||
}
|
||||
@@ -164,7 +173,7 @@ export class TransactionsListComponent implements OnInit, OnChanges {
|
||||
return tx.txid + tx.status.confirmed;
|
||||
}
|
||||
|
||||
trackByIndexFn(index: number) {
|
||||
trackByIndexFn(index: number): number {
|
||||
return index;
|
||||
}
|
||||
|
||||
@@ -177,7 +186,7 @@ export class TransactionsListComponent implements OnInit, OnChanges {
|
||||
return Math.pow(base, exponent);
|
||||
}
|
||||
|
||||
toggleDetails() {
|
||||
toggleDetails(): void {
|
||||
if (this.showDetails$.value === true) {
|
||||
this.showDetails$.next(false);
|
||||
} else {
|
||||
@@ -185,7 +194,7 @@ export class TransactionsListComponent implements OnInit, OnChanges {
|
||||
}
|
||||
}
|
||||
|
||||
loadMoreInputs(tx: Transaction) {
|
||||
loadMoreInputs(tx: Transaction): void {
|
||||
tx['@vinLimit'] = false;
|
||||
|
||||
this.electrsApiService.getTransaction$(tx.txid)
|
||||
@@ -196,7 +205,7 @@ export class TransactionsListComponent implements OnInit, OnChanges {
|
||||
});
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
ngOnDestroy(): void {
|
||||
this.outspendsSubscription.unsubscribe();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user