Merge branch 'master' into hunicus/docs-links-alignment

This commit is contained in:
hunicus
2024-04-01 19:06:18 +09:00
committed by GitHub
51 changed files with 7271 additions and 7325 deletions

View File

@@ -1,5 +1,5 @@
<div class="grid-align" [style.gridTemplateColumns]="'repeat(auto-fit, ' + resolution + 'px)'">
<div class="graph-alignment" [class.grid-align]="!autofit" [style.gridTemplateColumns]="'repeat(auto-fit, ' + resolution + 'px)'">
<div class="block-overview-graph">
<canvas *browserOnly class="block-overview-canvas" [class.clickable]="!!hoverTx" #blockCanvas></canvas>
<div class="loader-wrapper" [class.hidden]="(!isLoading || disableSpinner) && !unavailable">

View File

@@ -22,9 +22,12 @@
}
}
.grid-align {
.graph-alignment {
position: relative;
width: 100%;
}
.grid-align {
display: grid;
grid-template-columns: repeat(auto-fit, 75px);
justify-content: center;

View File

@@ -32,6 +32,7 @@ const unmatchedAuditColors = {
export class BlockOverviewGraphComponent implements AfterViewInit, OnDestroy, OnChanges {
@Input() isLoading: boolean;
@Input() resolution: number;
@Input() autofit: boolean = false;
@Input() blockLimit: number;
@Input() orientation = 'left';
@Input() flip = true;
@@ -206,6 +207,10 @@ export class BlockOverviewGraphComponent implements AfterViewInit, OnDestroy, On
update(add: TransactionStripped[], remove: string[], change: { txid: string, rate: number | undefined, acc: boolean | undefined }[], direction: string = 'left', resetLayout: boolean = false): void {
if (this.scene) {
add = add.filter(tx => !this.scene.txs[tx.txid]);
remove = remove.filter(txid => this.scene.txs[txid]);
change = change.filter(tx => this.scene.txs[tx.txid]);
this.scene.update(add, remove, change, direction, resetLayout);
this.start();
this.updateSearchHighlight();

View File

@@ -70,8 +70,9 @@
<div class="col-sm chart-container">
<app-block-overview-graph
#blockGraph
[autofit]="true"
[isLoading]="false"
[resolution]="80"
[resolution]="86"
[blockLimit]="stateService.blockVSize"
[orientation]="'top'"
[flip]="false"

View File

@@ -97,7 +97,7 @@
<div class="difficulty-stats">
<div class="item">
<div class="card-text bigger">
<app-btc [satoshis]="312500000"></app-btc>
<app-btc [satoshis]="nextSubsidy"></app-btc>
</div>
<div class="symbol">
<span i18n="difficulty-box.new-subsidy">New subsidy</span>

View File

@@ -62,6 +62,7 @@ export class DifficultyComponent implements OnInit {
expectedIndex: number;
difference: number;
shapes: DiffShape[];
nextSubsidy: number;
tooltipPosition = { x: 0, y: 0 };
hoverSection: DiffShape | void;
@@ -106,6 +107,7 @@ export class DifficultyComponent implements OnInit {
const newEpochStart = Math.floor(this.stateService.latestBlockHeight / EPOCH_BLOCK_LENGTH) * EPOCH_BLOCK_LENGTH;
const newExpectedHeight = Math.floor(newEpochStart + da.expectedBlocks);
this.now = new Date().getTime();
this.nextSubsidy = getNextBlockSubsidy(maxHeight);
if (blocksUntilHalving < da.remainingBlocks && !this.userSelectedMode) {
this.mode = 'halving';
@@ -233,3 +235,16 @@ export class DifficultyComponent implements OnInit {
this.hoverSection = null;
}
}
function getNextBlockSubsidy(height: number): number {
const halvings = Math.floor(height / 210_000) + 1;
// Force block reward to zero when right shift is undefined.
if (halvings >= 64) {
return 0;
}
let subsidy = BigInt(50 * 100_000_000);
// Subsidy is cut in half every 210,000 blocks which will occur approximately every 4 years.
subsidy >>= BigInt(halvings);
return Number(subsidy);
}

View File

@@ -66,7 +66,7 @@ export class FeeDistributionGraphComponent implements OnInit, OnChanges, OnDestr
return;
}
const samples = [];
const txs = this.transactions.filter(tx => !tx.acc).map(tx => { return { vsize: tx.vsize, rate: tx.rate || (tx.fee / tx.vsize) }; }).sort((a, b) => { return b.rate - a.rate; });
const txs = this.transactions.map(tx => { return { vsize: tx.vsize, rate: tx.rate || (tx.fee / tx.vsize) }; }).sort((a, b) => { return b.rate - a.rate; });
const maxBlockVSize = this.stateService.env.BLOCK_WEIGHT_UNITS / 4;
const sampleInterval = maxBlockVSize / this.numSamples;
let cumVSize = 0;

View File

@@ -265,8 +265,8 @@ export class IncomingTransactionsGraphComponent implements OnInit, OnChanges, On
type: 'value',
axisLabel: {
fontSize: 11,
formatter: (value) => {
return this.weightMode ? value * 4 : value;
formatter: (value): string => {
return this.weightMode ? (value * 4).toString() : value.toString();
}
},
splitLine: {

View File

@@ -20,10 +20,12 @@
-
<app-fee-rate [fee]="projectedBlock.feeRange[projectedBlock.feeRange.length - 1]" rounding="1.0-0" unitClass=""></app-fee-rate>
</div>
<div *ngIf="showMiningInfo" class="block-size">
<div *ngIf="showMiningInfo$ | async; else noMiningInfo" class="block-size">
<app-amount [attr.data-cy]="'mempool-block-' + i + '-total-fees'" [satoshis]="projectedBlock.totalFees" digitsInfo="1.2-3" [noFiat]="true"></app-amount>
</div>
<div *ngIf="!showMiningInfo" class="block-size" [innerHTML]="'&lrm;' + (projectedBlock.blockSize | bytes: 2)"></div>
<ng-template #noMiningInfo>
<div class="block-size" [innerHTML]="'&lrm;' + (projectedBlock.blockSize | bytes: 2)"></div>
</ng-template>
<div [attr.data-cy]="'mempool-block-' + i + '-transaction-count'" class="transaction-count">
<ng-container *ngTemplateOutlet="projectedBlock.nTx === 1 ? transactionsSingular : transactionsPlural; context: {$implicit: projectedBlock.nTx | number}"></ng-container>
<ng-template #transactionsSingular let-i i18n="shared.transaction-count.singular">{{ i }} transaction</ng-template>

View File

@@ -1,5 +1,5 @@
import { Component, OnInit, OnDestroy, ChangeDetectionStrategy, ChangeDetectorRef, HostListener, Input, OnChanges, SimpleChanges, Output, EventEmitter } from '@angular/core';
import { Subscription, Observable, of, combineLatest } from 'rxjs';
import { Subscription, Observable, of, combineLatest, BehaviorSubject } from 'rxjs';
import { MempoolBlock } from '../../interfaces/websocket.interface';
import { StateService } from '../../services/state.service';
import { Router } from '@angular/router';
@@ -42,6 +42,7 @@ export class MempoolBlocksComponent implements OnInit, OnChanges, OnDestroy {
mempoolBlocks$: Observable<MempoolBlock[]>;
difficultyAdjustments$: Observable<DifficultyAdjustment>;
loadingBlocks$: Observable<boolean>;
showMiningInfo$: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
blocksSubscription: Subscription;
mempoolBlocksFull: MempoolBlock[] = [];
@@ -57,10 +58,8 @@ export class MempoolBlocksComponent implements OnInit, OnChanges, OnDestroy {
network = '';
now = new Date().getTime();
timeOffset = 0;
showMiningInfo = false;
timeLtrSubscription: Subscription;
timeLtr: boolean;
showMiningInfoSubscription: Subscription;
animateEntry: boolean = false;
blockOffset: number = 155;
@@ -98,10 +97,7 @@ export class MempoolBlocksComponent implements OnInit, OnChanges, OnDestroy {
this.widthChange.emit(this.mempoolWidth);
if (['', 'testnet', 'signet'].includes(this.stateService.network)) {
this.showMiningInfoSubscription = this.stateService.showMiningInfo$.subscribe((showMiningInfo) => {
this.showMiningInfo = showMiningInfo;
this.cd.markForCheck();
});
this.showMiningInfo$ = this.stateService.showMiningInfo$;
}
this.timeLtrSubscription = this.stateService.timeLtr.subscribe((ltr) => {
@@ -267,7 +263,6 @@ export class MempoolBlocksComponent implements OnInit, OnChanges, OnDestroy {
this.chainTipSubscription.unsubscribe();
this.keySubscription.unsubscribe();
this.isTabHiddenSubscription.unsubscribe();
this.showMiningInfoSubscription.unsubscribe();
clearTimeout(this.resetTransitionTimeout);
}

View File

@@ -411,7 +411,6 @@ export class MempoolGraphComponent implements OnInit, OnChanges {
padding: [20, 0, 0, 0],
},
type: 'time',
boundaryGap: false,
axisLine: { onZero: true },
axisLabel: {
margin: 20,

View File

@@ -6,7 +6,7 @@
<span class="menu-click text-nowrap ellipsis">
<strong>
<span *ngIf="user.username.includes('@'); else usernamenospace">{{ user.username }}</span>
<ng-template #usernamenospace>@{{ user.username }}</ng-template>
<ng-template #usernamenospace>&#64;{{ user.username }}</ng-template>
</strong>
</span>
<span class="badge mr-1 badge-og" *ngIf="user.ogRank">

View File

@@ -24,7 +24,7 @@ export class StartComponent implements OnInit, AfterViewChecked, OnDestroy {
timeLtrSubscription: Subscription;
timeLtr: boolean = this.stateService.timeLtr.value;
chainTipSubscription: Subscription;
chainTip: number = 100;
chainTip: number = -1;
tipIsSet: boolean = false;
lastMark: MarkBlockState;
markBlockSubscription: Subscription;

View File

@@ -326,7 +326,7 @@
<br>
<p>If you have any questions about this Policy, would like to speak with us about the use of our Marks in ways not described in the Policy, or see any abuse of our Marks, please email us at &lt;legal@mempool.space&gt;</p>
<p>If you have any questions about this Policy, would like to speak with us about the use of our Marks in ways not described in the Policy, or see any abuse of our Marks, please email us at &lt;legal&#64;mempool.space&gt;</p>
</ol>

View File

@@ -1,13 +1,16 @@
import { ChangeDetectionStrategy, Component, Input, Output, EventEmitter, NgZone, OnInit } from '@angular/core';
import { SeoService } from '../../services/seo.service';
import { ApiService } from '../../services/api.service';
import { delay, Observable, switchMap, tap, zip } from 'rxjs';
import { delay, Observable, of, switchMap, tap, zip } from 'rxjs';
import { AssetsService } from '../../services/assets.service';
import { ActivatedRoute, ParamMap, Router } from '@angular/router';
import { RelativeUrlPipe } from '../../shared/pipes/relative-url/relative-url.pipe';
import { StateService } from '../../services/state.service';
import { EChartsOption, echarts } from '../../graphs/echarts';
import { isMobile } from '../../shared/common.utils';
import { AmountShortenerPipe } from '../../shared/pipes/amount-shortener.pipe';
import { getFlagEmoji } from '../../shared/common.utils';
import { lerpColor } from '../../shared/graphs.utils';
@Component({
selector: 'app-nodes-channels-map',
@@ -50,6 +53,7 @@ export class NodesChannelsMap implements OnInit {
private router: Router,
private zone: NgZone,
private activatedRoute: ActivatedRoute,
private amountShortenerPipe: AmountShortenerPipe,
) {
}
@@ -86,10 +90,12 @@ export class NodesChannelsMap implements OnInit {
return zip(
this.assetsService.getWorldMapJson$,
this.style !== 'channelpage' ? this.apiService.getChannelsGeo$(params.get('public_key') ?? undefined, this.style) : [''],
[params.get('public_key') ?? undefined]
[params.get('public_key') ?? undefined],
this.style === 'widget' ? of(undefined) : this.apiService.getWorldNodes$(),
).pipe(tap((data) => {
echarts.registerMap('world', data[0]);
let maxLiquidity = data[3]?.maxLiquidity;
const channelsLoc = [];
const nodes = [];
const nodesPubkeys = {};
@@ -197,13 +203,24 @@ export class NodesChannelsMap implements OnInit {
this.zoom = -0.05 * distance + 8;
}
this.prepareChartOptions(nodes, channelsLoc);
if (data[3]) {
for (const node of nodes) {
const foundNode = data[3].nodes.find((n) => n[2] === node[3]);
if (foundNode) {
node.push(foundNode[4], foundNode[5], foundNode[6]?.en, foundNode[7]);
maxLiquidity = Math.max(maxLiquidity ?? 0, foundNode[4]);
}
}
}
maxLiquidity = Math.max(1, maxLiquidity);
this.prepareChartOptions(nodes, channelsLoc, maxLiquidity);
}));
})
);
}
prepareChartOptions(nodes, channels) {
prepareChartOptions(nodes, channels, maxLiquidity) {
let title: object;
if (channels.length === 0) {
if (!this.placeholder) {
@@ -267,7 +284,12 @@ export class NodesChannelsMap implements OnInit {
data: nodes,
coordinateSystem: 'geo',
geoIndex: 0,
symbolSize: this.nodeSize,
symbolSize: (params) => {
if (maxLiquidity) {
return 10 * Math.pow(params[5] / maxLiquidity, 0.2) + 3;
}
return this.nodeSize;
},
tooltip: {
show: true,
backgroundColor: 'rgba(17, 19, 31, 1)',
@@ -281,11 +303,25 @@ export class NodesChannelsMap implements OnInit {
formatter: (value) => {
const data = value.data;
const alias = data[4].length > 0 ? data[4] : data[3].slice(0, 20);
return `<b style="color: white">${alias}</b>`;
}
const liquidity = data[5] >= 100000000 ?
`${this.amountShortenerPipe.transform(data[5] / 100000000)} BTC` :
`${this.amountShortenerPipe.transform(data[5], 2)} sats`;
return `
<b style="color: white">${alias}</b><br>
${liquidity}<br>` +
$localize`:@@205c1b86ac1cc419c4d0cca51fdde418c4ffdc20:${data[6]}:INTERPOLATION: channels` + `<br>
${getFlagEmoji(data[8])} ${data[7]}
`;
},
},
itemStyle: {
color: 'white',
color: (params) => {
if (!maxLiquidity) {
return 'white';
}
return `${lerpColor('#1E88E5', '#D81B60', Math.pow(params.data[5] / maxLiquidity, 0.2))}`;
},
opacity: 1,
borderColor: 'black',
borderWidth: 0,
@@ -361,8 +397,6 @@ export class NodesChannelsMap implements OnInit {
}
chartOptions.series[0].itemStyle.borderWidth = nodeBorder;
chartOptions.series[0].symbolSize += e.zoom > 1 ? speed * 15 : -speed * 15;
chartOptions.series[0].symbolSize = Math.max(4, Math.min(7, chartOptions.series[0].symbolSize));
chartOptions.series[1].lineStyle.opacity += e.zoom > 1 ? speed : -speed;
chartOptions.series[1].lineStyle.width += e.zoom > 1 ? speed : -speed;

View File

@@ -1,8 +1,8 @@
import { Inject, Injectable, PLATFORM_ID } from '@angular/core';
import { Inject, Injectable, PLATFORM_ID, makeStateKey, TransferState } from '@angular/core';
import { HttpInterceptor, HttpEvent, HttpRequest, HttpHandler, HttpResponse, HttpErrorResponse, HttpHeaders } from '@angular/common/http';
import { Observable, of } from 'rxjs';
import { catchError, tap } from 'rxjs/operators';
import { TransferState, makeStateKey } from '@angular/platform-browser';
import { isPlatformBrowser } from '@angular/common';
@Injectable()

View File

@@ -7,5 +7,5 @@ if (environment.production) {
enableProdMode();
}
export { AppServerModule } from './app/app.server.module';
export { AppServerModule } from './app/app.module.server';
export { renderModule } from '@angular/platform-server';