Merge branch 'master' into mononaut/block-page-layouts
This commit is contained in:
@@ -77,6 +77,8 @@ export class BlockOverviewGraphComponent implements AfterViewInit, OnDestroy, On
|
||||
cancelAnimationFrame(this.animationFrameRequest);
|
||||
clearTimeout(this.animationHeartBeat);
|
||||
}
|
||||
this.canvas.nativeElement.removeEventListener('webglcontextlost', this.handleContextLost);
|
||||
this.canvas.nativeElement.removeEventListener('webglcontextrestored', this.handleContextRestored);
|
||||
}
|
||||
|
||||
clear(direction): void {
|
||||
|
||||
@@ -53,13 +53,13 @@
|
||||
<td i18n="block.miner">Miner</td>
|
||||
<td *ngIf="stateService.env.MINING_DASHBOARD">
|
||||
<a [attr.data-cy]="'block-details-miner-badge'" placement="bottom" [routerLink]="['/mining/pool' | relativeUrl, block?.extras.pool.slug]" class="badge"
|
||||
[class]="block?.extras.pool.name === 'Unknown' ? 'badge-secondary' : 'badge-primary'">
|
||||
[class]="!block?.extras.pool.name || block?.extras.pool.name === 'Unknown' ? 'badge-secondary' : 'badge-primary'">
|
||||
{{ block?.extras.pool.name }}
|
||||
</a>
|
||||
</td>
|
||||
<td *ngIf="!stateService.env.MINING_DASHBOARD && stateService.env.BASE_MODULE === 'mempool'">
|
||||
<span [attr.data-cy]="'block-details-miner-badge'" placement="bottom" class="badge"
|
||||
[class]="block?.extras.pool.name === 'Unknown' ? 'badge-secondary' : 'badge-primary'">
|
||||
[class]="!block?.extras.pool.name || block?.extras.pool.name === 'Unknown' ? 'badge-secondary' : 'badge-primary'">
|
||||
{{ block?.extras.pool.name }}
|
||||
</span>
|
||||
</td>
|
||||
|
||||
@@ -56,3 +56,7 @@
|
||||
::ng-deep .symbol {
|
||||
font-size: 24px;
|
||||
}
|
||||
|
||||
.badge {
|
||||
transition: none;
|
||||
}
|
||||
|
||||
@@ -57,8 +57,21 @@
|
||||
<tr *ngIf="!auditDataMissing && indexingAvailable">
|
||||
<td i18n="block.health">Block health</td>
|
||||
<td>
|
||||
<span *ngIf="blockAudit?.matchRate != null">{{ blockAudit.matchRate }}%</span>
|
||||
<span *ngIf="blockAudit?.matchRate === null" i18n="unknown">Unknown</span>
|
||||
<span
|
||||
class="health-badge badge"
|
||||
[class.badge-success]="blockAudit?.matchRate >= 99"
|
||||
[class.badge-warning]="blockAudit?.matchRate >= 75 && blockAudit?.matchRate < 99"
|
||||
[class.badge-danger]="blockAudit?.matchRate < 75"
|
||||
*ngIf="blockAudit?.matchRate != null; else nullHealth"
|
||||
>{{ blockAudit?.matchRate }}%</span>
|
||||
<ng-template #nullHealth>
|
||||
<ng-container *ngIf="!isLoadingAudit; else loadingHealth">
|
||||
<span class="health-badge badge badge-secondary" i18n="unknown">Unknown</span>
|
||||
</ng-container>
|
||||
</ng-template>
|
||||
<ng-template #loadingHealth>
|
||||
<span class="skeleton-loader" style="max-width: 60px"></span>
|
||||
</ng-template>
|
||||
</td>
|
||||
</tr>
|
||||
</ng-container>
|
||||
|
||||
@@ -43,6 +43,7 @@ export class BlockComponent implements OnInit, OnDestroy {
|
||||
strippedTransactions: TransactionStripped[];
|
||||
overviewTransitionDirection: string;
|
||||
isLoadingOverview = true;
|
||||
isLoadingAudit = true;
|
||||
error: any;
|
||||
blockSubsidy: number;
|
||||
fees: number;
|
||||
@@ -297,13 +298,18 @@ export class BlockComponent implements OnInit, OnDestroy {
|
||||
this.auditSubscription = block$.pipe(
|
||||
startWith(null),
|
||||
pairwise(),
|
||||
switchMap(([prevBlock, block]) => this.apiService.getBlockAudit$(block.id)
|
||||
.pipe(
|
||||
catchError((err) => {
|
||||
this.overviewError = err;
|
||||
return of([]);
|
||||
})
|
||||
)
|
||||
switchMap(([prevBlock, block]) => {
|
||||
this.isLoadingAudit = true;
|
||||
this.blockAudit = null;
|
||||
return this.apiService.getBlockAudit$(block.id)
|
||||
.pipe(
|
||||
catchError((err) => {
|
||||
this.overviewError = err;
|
||||
this.isLoadingAudit = false;
|
||||
return of([]);
|
||||
})
|
||||
);
|
||||
}
|
||||
),
|
||||
filter((response) => response != null),
|
||||
map((response) => {
|
||||
@@ -375,12 +381,14 @@ export class BlockComponent implements OnInit, OnDestroy {
|
||||
console.log(err);
|
||||
this.error = err;
|
||||
this.isLoadingOverview = false;
|
||||
this.isLoadingAudit = false;
|
||||
return of(null);
|
||||
}),
|
||||
).subscribe((blockAudit) => {
|
||||
this.blockAudit = blockAudit;
|
||||
this.setupBlockGraphs();
|
||||
this.isLoadingOverview = false;
|
||||
this.isLoadingAudit = false;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
i18n-ngbTooltip="mining.pool-name" ngbTooltip="Pool" placement="bottom" #miningpool [disableTooltip]="!isEllipsisActive(miningpool)">Pool</th>
|
||||
<th class="timestamp" i18n="latest-blocks.timestamp" *ngIf="!widget" [class]="indexingAvailable ? '' : 'legacy'">Timestamp</th>
|
||||
<th class="mined" i18n="latest-blocks.mined" *ngIf="!widget" [class]="indexingAvailable ? '' : 'legacy'">Mined</th>
|
||||
<th *ngIf="indexingAvailable" class="health text-left" i18n="latest-blocks.health" [ngClass]="{'widget': widget, 'legacy': !indexingAvailable}"
|
||||
<th *ngIf="indexingAvailable" class="health text-right" i18n="latest-blocks.health" [ngClass]="{'widget': widget, 'legacy': !indexingAvailable}"
|
||||
i18n-ngbTooltip="latest-blocks.health" ngbTooltip="Health" placement="bottom" #health [disableTooltip]="!isEllipsisActive(health)">Health</th>
|
||||
<th *ngIf="indexingAvailable" class="reward text-right" i18n="latest-blocks.reward" [ngClass]="{'widget': widget, 'legacy': !indexingAvailable}"
|
||||
i18n-ngbTooltip="latest-blocks.reward" ngbTooltip="Reward" placement="bottom" #reward [disableTooltip]="!isEllipsisActive(reward)">Reward</th>
|
||||
@@ -46,16 +46,22 @@
|
||||
<app-time-since [time]="block.timestamp" [fastRender]="true"></app-time-since>
|
||||
</td>
|
||||
<td *ngIf="indexingAvailable" class="health text-right" [ngClass]="{'widget': widget, 'legacy': !indexingAvailable}">
|
||||
<a class="clear-link" [routerLink]="auditScores[block.id] != null ? ['/block/' | relativeUrl, block.id] : null">
|
||||
<div class="progress progress-health">
|
||||
<div class="progress-bar progress-bar-health" role="progressbar"
|
||||
[ngStyle]="{'width': (100 - (auditScores[block.id] || 0)) + '%' }"></div>
|
||||
<div class="progress-text">
|
||||
<span *ngIf="auditScores[block.id] != null;">{{ auditScores[block.id] }}%</span>
|
||||
<span *ngIf="auditScores[block.id] == null">~</span>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
<a
|
||||
class="health-badge badge"
|
||||
[class.badge-success]="auditScores[block.id] >= 99"
|
||||
[class.badge-warning]="auditScores[block.id] >= 75 && auditScores[block.id] < 99"
|
||||
[class.badge-danger]="auditScores[block.id] < 75"
|
||||
[routerLink]="auditScores[block.id] != null ? ['/block/' | relativeUrl, block.id] : null"
|
||||
*ngIf="auditScores[block.id] != null; else nullHealth"
|
||||
>{{ auditScores[block.id] }}%</a>
|
||||
<ng-template #nullHealth>
|
||||
<ng-container *ngIf="!loadingScores; else loadingHealth">
|
||||
<span class="health-badge badge badge-secondary" i18n="unknown">Unknown</span>
|
||||
</ng-container>
|
||||
</ng-template>
|
||||
<ng-template #loadingHealth>
|
||||
<span class="skeleton-loader" style="max-width: 60px"></span>
|
||||
</ng-template>
|
||||
</td>
|
||||
<td *ngIf="indexingAvailable" class="reward text-right" [ngClass]="{'widget': widget, 'legacy': !indexingAvailable}">
|
||||
<app-amount [satoshis]="block.extras.reward" [noFiat]="true" digitsInfo="1.2-2"></app-amount>
|
||||
|
||||
@@ -23,6 +23,7 @@ export class BlocksList implements OnInit, OnDestroy {
|
||||
|
||||
indexingAvailable = false;
|
||||
isLoading = true;
|
||||
loadingScores = true;
|
||||
fromBlockHeight = undefined;
|
||||
paginationMaxSize: number;
|
||||
page = 1;
|
||||
@@ -113,6 +114,7 @@ export class BlocksList implements OnInit, OnDestroy {
|
||||
if (this.indexingAvailable) {
|
||||
this.auditScoreSubscription = this.fromHeightSubject.pipe(
|
||||
switchMap((fromBlockHeight) => {
|
||||
this.loadingScores = true;
|
||||
return this.apiService.getBlockAuditScores$(this.page === 1 ? undefined : fromBlockHeight)
|
||||
.pipe(
|
||||
catchError(() => {
|
||||
@@ -124,6 +126,7 @@ export class BlocksList implements OnInit, OnDestroy {
|
||||
Object.values(scores).forEach(score => {
|
||||
this.auditScores[score.hash] = score?.matchRate != null ? score.matchRate : null;
|
||||
});
|
||||
this.loadingScores = false;
|
||||
});
|
||||
|
||||
this.latestScoreSubscription = this.stateService.blocks$.pipe(
|
||||
|
||||
@@ -91,6 +91,9 @@ export class TransactionsListComponent implements OnInit, OnChanges {
|
||||
filter(() => this.stateService.env.LIGHTNING),
|
||||
switchMap((txIds) => this.apiService.getChannelByTxIds$(txIds)),
|
||||
tap((channels) => {
|
||||
if (!this.transactions) {
|
||||
return;
|
||||
}
|
||||
const transactions = this.transactions.filter((tx) => !tx._channels);
|
||||
channels.forEach((channel, i) => {
|
||||
transactions[i]._channels = channel;
|
||||
|
||||
@@ -88,7 +88,7 @@
|
||||
<stop offset="100%" stop-color="transparent" />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<path [attr.d]="middle.path" class="line middle" [style]="middle.style"/>
|
||||
<path *ngIf="hasLine" [attr.d]="middle.path" class="line middle" [style]="middle.style"/>
|
||||
<ng-container *ngFor="let input of inputs; let i = index">
|
||||
<path *ngIf="connectors && !inputData[i].coinbase && !inputData[i].pegin"
|
||||
[attr.d]="input.connectorPath"
|
||||
@@ -106,7 +106,7 @@
|
||||
(pointerout)="onBlur($event, 'input', i);"
|
||||
(click)="onClick($event, 'input', inputData[i].index);"
|
||||
/>
|
||||
<path
|
||||
<path *ngIf="!input.zeroValue"
|
||||
[attr.d]="input.path"
|
||||
class="line {{input.class}}"
|
||||
[class.highlight]="inputIndex != null && inputData[i].index === inputIndex"
|
||||
@@ -116,6 +116,16 @@
|
||||
(pointerout)="onBlur($event, 'input', i);"
|
||||
(click)="onClick($event, 'input', inputData[i].index);"
|
||||
/>
|
||||
<path *ngIf="input.zeroValue"
|
||||
[attr.d]="input.path"
|
||||
class="line {{input.class}} zerovalue"
|
||||
[class.highlight]="inputIndex != null && inputData[i].index === inputIndex"
|
||||
[class.zerovalue]="input.zeroValue"
|
||||
[style]="input.style"
|
||||
(pointerover)="onHover($event, 'input', i);"
|
||||
(pointerout)="onBlur($event, 'input', i);"
|
||||
(click)="onClick($event, 'input', inputData[i].index);"
|
||||
/>
|
||||
</ng-container>
|
||||
<ng-container *ngFor="let output of outputs; let i = index">
|
||||
<path *ngIf="connectors && outspends[outputData[i].index]?.spent"
|
||||
|
||||
@@ -68,6 +68,7 @@ export class TxBowtieGraphComponent implements OnInit, OnChanges {
|
||||
outspends: Outspend[] = [];
|
||||
zeroValueWidth = 60;
|
||||
zeroValueThickness = 20;
|
||||
hasLine: boolean;
|
||||
|
||||
outspendsSubscription: Subscription;
|
||||
refreshOutspends$: ReplaySubject<string> = new ReplaySubject();
|
||||
@@ -162,7 +163,7 @@ export class TxBowtieGraphComponent implements OnInit, OnChanges {
|
||||
let truncatedInputs = this.tx.vin.map((v, i) => {
|
||||
return {
|
||||
type: 'input',
|
||||
value: v?.prevout?.value,
|
||||
value: v?.prevout?.value || (v?.is_coinbase && !totalValue ? 0 : undefined),
|
||||
txid: v.txid,
|
||||
vout: v.vout,
|
||||
address: v?.prevout?.scriptpubkey_address || v?.prevout?.scriptpubkey_type?.toUpperCase(),
|
||||
@@ -198,6 +199,9 @@ export class TxBowtieGraphComponent implements OnInit, OnChanges {
|
||||
path: `M ${(this.width / 2) - this.midWidth} ${(this.height / 2) + 0.5} L ${(this.width / 2) + this.midWidth} ${(this.height / 2) + 0.5}`,
|
||||
style: `stroke-width: ${this.combinedWeight + 1}; stroke: ${this.gradient[1]}`
|
||||
};
|
||||
|
||||
this.hasLine = this.inputs.reduce((line, put) => line || !put.zeroValue, false)
|
||||
&& this.outputs.reduce((line, put) => line || !put.zeroValue, false);
|
||||
}
|
||||
|
||||
calcTotalValue(tx: Transaction): number {
|
||||
@@ -278,6 +282,9 @@ export class TxBowtieGraphComponent implements OnInit, OnChanges {
|
||||
lineParams.forEach((line, i) => {
|
||||
if (xputs[i].value === 0) {
|
||||
line.outerY = lastOuter + (this.zeroValueThickness / 2);
|
||||
if (xputs.length === 1) {
|
||||
line.outerY = (this.height / 2);
|
||||
}
|
||||
lastOuter += this.zeroValueThickness + spacing;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -118,7 +118,7 @@ export class NodesNetworksChartComponent implements OnInit {
|
||||
color: 'grey',
|
||||
fontSize: 15
|
||||
},
|
||||
text: $localize`Indexing in progess`,
|
||||
text: $localize`Indexing in progress`,
|
||||
left: 'center',
|
||||
top: 'center',
|
||||
};
|
||||
|
||||
@@ -109,7 +109,7 @@ export class LightningStatisticsChartComponent implements OnInit {
|
||||
color: 'grey',
|
||||
fontSize: 15
|
||||
},
|
||||
text: $localize`Indexing in progess`,
|
||||
text: $localize`Indexing in progress`,
|
||||
left: 'center',
|
||||
top: 'center'
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user