mirror of
https://github.com/mempool/mempool.git
synced 2025-03-26 17:51:45 +01:00
Merge branch 'master' into mononaut/handle-websocket-errors
This commit is contained in:
commit
ed07daebca
@ -80,7 +80,13 @@ class ChannelsApi {
|
||||
|
||||
public async $searchChannelsById(search: string): Promise<any[]> {
|
||||
try {
|
||||
const searchStripped = search.replace(/[^0-9x]/g, '') + '%';
|
||||
// restrict search to valid id/short_id prefix formats
|
||||
let searchStripped = search.match(/[0-9]+[0-9x]*/)?.[0] || '';
|
||||
if (!searchStripped.length) {
|
||||
return [];
|
||||
}
|
||||
// add wildcard to search by prefix
|
||||
searchStripped += '%';
|
||||
const query = `SELECT id, short_id, capacity, status FROM channels WHERE id LIKE ? OR short_id LIKE ? LIMIT 10`;
|
||||
const [rows]: any = await DB.query(query, [searchStripped, searchStripped]);
|
||||
return rows;
|
||||
|
@ -30,7 +30,7 @@ export class BisqDashboardComponent implements OnInit {
|
||||
|
||||
ngOnInit(): void {
|
||||
this.seoService.setTitle($localize`:@@meta.title.bisq.markets:Markets`);
|
||||
this.seoService.setDescription($localize`:@@meta.description.bisq.markets:Explore the full Bitcoin ecosystem with The Mempool Open Project™. See Bisq market prices, trading activity, and more.`);
|
||||
this.seoService.setDescription($localize`:@@meta.description.bisq.markets:Explore the full Bitcoin ecosystem with The Mempool Open Source Project™. See Bisq market prices, trading activity, and more.`);
|
||||
this.websocketService.want(['blocks']);
|
||||
|
||||
this.volumes$ = this.bisqApiService.getAllVolumesDay$()
|
||||
|
@ -36,14 +36,14 @@
|
||||
<div id="become-sponsor-container">
|
||||
<div class="become-sponsor community">
|
||||
<p style="font-weight: 700; font-size: 18px;">If you're an individual...</p>
|
||||
<a href="https://mempool.space/sponsor" class="btn" style="background-color: rgba(152, 88, 255, 0.75); box-shadow: 0px 0px 50px 5px rgba(152, 88, 255, 0.75)" i18n="about.community-sponsor-button">Become a Community Sponsor</a>
|
||||
<a href="https://mempool.space/sponsor" class="btn" style="background-color: rgba(152, 88, 255, 0.75); box-shadow: 0px 0px 50px 5px rgba(152, 88, 255, 0.75)" i18n="about.community-sponsor-button" (click)="onSponsorClick($event)">Become a Community Sponsor</a>
|
||||
<p class="sponsor-feature"><fa-icon [icon]="['fas', 'check']"></fa-icon> Exclusive swag</p>
|
||||
<p class="sponsor-feature"><fa-icon [icon]="['fas', 'check']"></fa-icon> Your avatar on the About page</p>
|
||||
<p class="sponsor-feature"><fa-icon [icon]="['fas', 'check']"></fa-icon> And more coming soon :)</p>
|
||||
</div>
|
||||
<div class="become-sponsor enterprise">
|
||||
<p style="font-weight: 700; font-size: 18px;">If you're a business...</p>
|
||||
<a href="https://mempool.space/enterprise" class="btn" style="background-color: rgba(152, 88, 255, 0.75); box-shadow: 0px 0px 50px 5px rgba(152, 88, 255, 0.75)" i18n="about.enterprise-sponsor-button">Become an Enterprise Sponsor</a>
|
||||
<a href="https://mempool.space/enterprise" class="btn" style="background-color: rgba(152, 88, 255, 0.75); box-shadow: 0px 0px 50px 5px rgba(152, 88, 255, 0.75)" i18n="about.enterprise-sponsor-button" (click)="onEnterpriseClick($event)">Become an Enterprise Sponsor</a>
|
||||
<p class="sponsor-feature"><fa-icon [icon]="['fas', 'check']"></fa-icon> Increased API limits</p>
|
||||
<p class="sponsor-feature"><fa-icon [icon]="['fas', 'check']"></fa-icon> Co-branded instance</p>
|
||||
<p class="sponsor-feature"><fa-icon [icon]="['fas', 'check']"></fa-icon> 99% service-level agreement</p>
|
||||
|
@ -282,6 +282,7 @@
|
||||
text-align: left;
|
||||
width: 250px;
|
||||
margin: 12px auto;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
@media (max-width: 992px) {
|
||||
|
@ -9,6 +9,7 @@ import { Router, ActivatedRoute } from '@angular/router';
|
||||
import { map, share, tap } from 'rxjs/operators';
|
||||
import { ITranslators } from '../../interfaces/node-api.interface';
|
||||
import { DOCUMENT } from '@angular/common';
|
||||
import { EnterpriseService } from '../../services/enterprise.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-about',
|
||||
@ -33,6 +34,7 @@ export class AboutComponent implements OnInit {
|
||||
private websocketService: WebsocketService,
|
||||
private seoService: SeoService,
|
||||
public stateService: StateService,
|
||||
private enterpriseService: EnterpriseService,
|
||||
private apiService: ApiService,
|
||||
private router: Router,
|
||||
private route: ActivatedRoute,
|
||||
@ -108,4 +110,14 @@ export class AboutComponent implements OnInit {
|
||||
unmutePromoVideo(): void {
|
||||
this.promoVideo.nativeElement.muted = false;
|
||||
}
|
||||
|
||||
onSponsorClick(e): boolean {
|
||||
this.enterpriseService.goal(5);
|
||||
return true;
|
||||
}
|
||||
|
||||
onEnterpriseClick(e): boolean {
|
||||
this.enterpriseService.goal(6);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -51,7 +51,7 @@
|
||||
In-band fees
|
||||
</td>
|
||||
<td style="text-align: end;">
|
||||
{{ estimate.txSummary.effectiveFee | number : '1.0-0' }} <span class="symbol" i18n="shared.sats|sats">sats</span>
|
||||
{{ estimate.txSummary.effectiveFee | number : '1.0-0' }} <span class="symbol" i18n="shared.sats">sats</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="info group-last">
|
||||
@ -76,7 +76,7 @@
|
||||
<div class="d-flex mb-0">
|
||||
<ng-container *ngFor="let option of maxRateOptions">
|
||||
<button type="button" class="btn btn-primary flex-grow-1 btn-border btn-sm feerate" [class]="{active: selectFeeRateIndex === option.index}" (click)="setUserBid(option)">
|
||||
<span class="fee">{{ option.fee + estimate.mempoolBaseFee + estimate.vsizeFee | number }} <span class="symbol" i18n="shared.sats|sats">sats</span></span>
|
||||
<span class="fee">{{ option.fee + estimate.mempoolBaseFee + estimate.vsizeFee | number }} <span class="symbol" i18n="shared.sats">sats</span></span>
|
||||
<span class="rate">~<app-fee-rate [fee]="option.rate" rounding="1.0-0"></app-fee-rate></span>
|
||||
</button>
|
||||
</ng-container>
|
||||
@ -110,7 +110,7 @@
|
||||
{{ math.max(0, estimate.nextBlockFee - estimate.txSummary.effectiveFee) | number }}
|
||||
</td>
|
||||
<td class="units">
|
||||
<span class="symbol" i18n="shared.sats|sats">sats</span>
|
||||
<span class="symbol" i18n="shared.sats">sats</span>
|
||||
<span class="fiat ml-1"><app-fiat [value]="math.max(0, estimate.nextBlockFee - estimate.txSummary.effectiveFee)"></app-fiat></span>
|
||||
</td>
|
||||
</tr>
|
||||
@ -130,7 +130,7 @@
|
||||
+{{ estimate.mempoolBaseFee | number }}
|
||||
</td>
|
||||
<td class="units">
|
||||
<span class="symbol" i18n="shared.sats|sats">sats</span>
|
||||
<span class="symbol" i18n="shared.sats">sats</span>
|
||||
<span class="fiat ml-1"><app-fiat [value]="estimate.mempoolBaseFee"></app-fiat></span>
|
||||
</td>
|
||||
</tr>
|
||||
@ -142,7 +142,7 @@
|
||||
+{{ estimate.vsizeFee | number }}
|
||||
</td>
|
||||
<td class="units">
|
||||
<span class="symbol" i18n="shared.sats|sats">sats</span>
|
||||
<span class="symbol" i18n="shared.sats">sats</span>
|
||||
<span class="fiat ml-1"><app-fiat [value]="estimate.vsizeFee"></app-fiat></span>
|
||||
</td>
|
||||
</tr>
|
||||
@ -159,7 +159,7 @@
|
||||
</span>
|
||||
</td>
|
||||
<td class="units">
|
||||
<span class="symbol" i18n="shared.sats|sats">sats</span>
|
||||
<span class="symbol" i18n="shared.sats">sats</span>
|
||||
<span class="fiat ml-1"><app-fiat [value]="estimate.cost + estimate.mempoolBaseFee + estimate.vsizeFee"></app-fiat></span>
|
||||
</td>
|
||||
</tr>
|
||||
@ -182,7 +182,7 @@
|
||||
</span>
|
||||
</td>
|
||||
<td class="units">
|
||||
<span class="symbol" i18n="shared.sats|sats">sats</span>
|
||||
<span class="symbol" i18n="shared.sats">sats</span>
|
||||
<span class="fiat ml-1">
|
||||
<app-fiat [value]="maxCost" [colorClass]="estimate.userBalance < maxCost ? 'red-color' : 'green-color'"></app-fiat>
|
||||
</span>
|
||||
@ -205,7 +205,7 @@
|
||||
{{ estimate.userBalance | number }}
|
||||
</td>
|
||||
<td class="units">
|
||||
<span class="symbol" i18n="shared.sats|sats">sats</span>
|
||||
<span class="symbol" i18n="shared.sats">sats</span>
|
||||
<span class="fiat ml-1">
|
||||
<app-fiat [value]="estimate.userBalance" [colorClass]="estimate.userBalance < maxCost ? 'red-color' : 'green-color'"></app-fiat>
|
||||
</span>
|
||||
|
@ -219,13 +219,13 @@
|
||||
<div class="box" *ngIf="!error && webGlEnabled && showAudit">
|
||||
<div class="nav nav-tabs" *ngIf="isMobile && showAudit">
|
||||
<a class="nav-link" [class.active]="mode === 'projected'"
|
||||
fragment="projected" (click)="changeMode('projected')"><ng-container i18n="block.expected">Expected</ng-container> <span class="badge badge-pill badge-warning" i18n="beta">beta</span></a>
|
||||
fragment="projected" (click)="changeMode('projected')"><ng-container i18n="block.expected">Expected</ng-container></a>
|
||||
<a class="nav-link" [class.active]="mode === 'actual'" i18n="block.actual"
|
||||
fragment="actual" (click)="changeMode('actual')">Actual</a>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm">
|
||||
<h3 class="block-subtitle" *ngIf="!isMobile"><ng-container i18n="block.expected-block">Expected Block</ng-container> <span class="badge badge-pill badge-warning beta" i18n="beta">beta</span></h3>
|
||||
<h3 class="block-subtitle" *ngIf="!isMobile"><ng-container i18n="block.expected-block">Expected Block</ng-container></h3>
|
||||
<div class="block-graph-wrapper">
|
||||
<app-block-overview-graph #blockGraphProjected [isLoading]="isLoadingOverview" [resolution]="86"
|
||||
[blockLimit]="stateService.blockVSize" [orientation]="'top'" [flip]="false" [mirrorTxid]="hoverTx" [auditHighlighting]="showAudit"
|
||||
@ -262,7 +262,7 @@
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="td-width" i18n="transaction.version">Version</td>
|
||||
<td>{{ block.version | decimal2hex }} <span *ngIf="displayTaprootStatus() && hasTaproot(block.version)" class="badge badge-success ml-1" >Taproot</span></td>
|
||||
<td>{{ block.version | decimal2hex }} <span *ngIf="displayTaprootStatus() && hasTaproot(block.version)" class="badge badge-success ml-1" i18n="tx-features.tag.taproot|Taproot">Taproot</span></td>
|
||||
</tr>
|
||||
<tr *ngIf="network !== 'liquid' && network !== 'liquidtestnet'">
|
||||
<td i18n="block.bits">Bits</td>
|
||||
|
@ -55,7 +55,9 @@ export class BlocksList implements OnInit {
|
||||
this.skeletonLines = this.widget === true ? [...Array(6).keys()] : [...Array(15).keys()];
|
||||
this.paginationMaxSize = window.matchMedia('(max-width: 670px)').matches ? 3 : 5;
|
||||
|
||||
this.seoService.setTitle($localize`:@@meta.title.blocks-list:Blocks`);
|
||||
if (!this.widget) {
|
||||
this.seoService.setTitle($localize`:@@m8a7b4bd44c0ac71b2e72de0398b303257f7d2f54:Blocks`);
|
||||
}
|
||||
if( this.stateService.network==='liquid'||this.stateService.network==='liquidtestnet' ) {
|
||||
this.seoService.setDescription($localize`:@@meta.description.liquid.blocks:See the most recent Liquid${seoDescriptionNetwork(this.stateService.network)} blocks along with basic stats such as block height, block size, and more.`);
|
||||
} else {
|
||||
|
@ -1,6 +1,6 @@
|
||||
<div class="container-xl">
|
||||
<div class="text-center">
|
||||
<h2>Calculator</h2>
|
||||
<h2 i18n="shared.calculator">Calculator</h2>
|
||||
</div>
|
||||
|
||||
<ng-container *ngIf="price$ | async; else loading">
|
||||
@ -26,7 +26,7 @@
|
||||
|
||||
<div class="input-group input-group-lg mb-1">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">sats</span>
|
||||
<span class="input-group-text" i18n="shared.sats">sats</span>
|
||||
</div>
|
||||
<input type="text" class="form-control" formControlName="satoshis" (input)="transformInput('satoshis')" (click)="selectAll($event)">
|
||||
<app-clipboard [button]="true" [text]="form.get('satoshis').value" [class]="'btn btn-lg btn-secondary ml-1'"></app-clipboard>
|
||||
@ -41,7 +41,7 @@
|
||||
<div class="bitcoin-satoshis-text">
|
||||
₿
|
||||
<span [innerHTML]="form.get('bitcoin').value | bitcoinsatoshis"></span>
|
||||
<span class="sats"> sats</span>
|
||||
<span class="sats" i18n="shared.sats">sats</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@ -38,36 +38,35 @@
|
||||
</div>
|
||||
<ng-container *ngIf="!hideStats">
|
||||
<div class="stats top left">
|
||||
<p class="label" i18n="clock.fiat-price">fiat price</p>
|
||||
<p class="label" i18n>Price</p>
|
||||
<p>
|
||||
<app-fiat [value]="100000000" digitsInfo="1.2-2" colorClass="white-color"></app-fiat>
|
||||
</p>
|
||||
</div>
|
||||
<div class="stats top right">
|
||||
<p class="label" i18n="clock.priority-rate|priority fee rate">priority rate</p>
|
||||
<p class="label" i18n="fees-box.high-priority">High Priority</p>
|
||||
<p *ngIf="recommendedFees$ | async as recommendedFees;">
|
||||
<app-fee-rate [fee]="recommendedFees.fastestFee" unitClass="" rounding="1.0-0"></app-fee-rate>
|
||||
</p>
|
||||
</div>
|
||||
<div *ngIf="mode !== 'mempool' && blocks?.length" class="stats bottom left">
|
||||
<p [innerHTML]="blocks[blockIndex].size | bytes: 2"></p>
|
||||
<p class="label" i18n="clock.block-size">block size</p>
|
||||
<p class="label" i18n="block.size">Size</p>
|
||||
</div>
|
||||
<div *ngIf="mode !== 'mempool' && blocks?.length" class="stats bottom right">
|
||||
<p class="force-wrap">
|
||||
<ng-container *ngTemplateOutlet="blocks[blockIndex].tx_count === 1 ? transactionsSingular : transactionsPlural; context: {$implicit: blocks[blockIndex].tx_count | number}"></ng-container>
|
||||
<ng-template #transactionsSingular let-i i18n="shared.transaction-count.singular">{{ i }} <span class="label">transaction</span></ng-template>
|
||||
<ng-template #transactionsPlural let-i i18n="shared.transaction-count.plural">{{ i }} <span class="label">transactions</span></ng-template>
|
||||
{{ blocks[blockIndex].tx_count | number }}
|
||||
<span class="label" i18n="dashboard.txs">Transactions</span>
|
||||
</p>
|
||||
</div>
|
||||
<ng-container *ngIf="mempoolInfo$ | async as mempoolInfo;">
|
||||
<div *ngIf="mode === 'mempool'" class="stats bottom left">
|
||||
<p [innerHTML]="mempoolInfo.usage | bytes: 0"></p>
|
||||
<p class="label" i18n="dashboard.memory-usage|Memory usage">memory usage</p>
|
||||
<p class="label" i18n="dashboard.memory-usage|Memory usage">Memory Usage</p>
|
||||
</div>
|
||||
<div *ngIf="mode === 'mempool'" class="stats bottom right">
|
||||
<p>{{ mempoolInfo.size | number }}</p>
|
||||
<p class="label" i18n="dashboard.unconfirmed|Unconfirmed count">unconfirmed</p>
|
||||
<p class="label" i18n="dashboard.unconfirmed|Unconfirmed count">Unconfirmed</p>
|
||||
</div>
|
||||
</ng-container>
|
||||
</ng-container>
|
||||
|
@ -63,6 +63,7 @@
|
||||
.label {
|
||||
font-size: calc(0.04 * var(--clock-width));
|
||||
line-height: calc(0.05 * var(--clock-width));
|
||||
text-transform: lowercase;
|
||||
}
|
||||
|
||||
&.top {
|
||||
|
@ -11,7 +11,7 @@
|
||||
<div class="progress inc-tx-progress-bar">
|
||||
<div class="progress-bar" role="progressbar" [ngStyle]="{'width': mempoolInfoData.progressWidth, 'background-color': mempoolInfoData.progressColor}"> </div>
|
||||
<div class="progress-text" *only-vsize>‎{{ mempoolInfoData.vBytesPerSecond | ceil | number }} <ng-container i18n="shared.vbytes-per-second|vB/s">vB/s</ng-container></div>
|
||||
<div class="progress-text" *only-weight>‎{{ mempoolInfoData.vBytesPerSecond * 4 | ceil | number }} <ng-container i18n="shared.weight-units-per-second|vB/s">WU/s</ng-container></div>
|
||||
<div class="progress-text" *only-weight>‎{{ mempoolInfoData.vBytesPerSecond * 4 | ceil | number }} <ng-container i18n="shared.weight-per-second|WU/s">WU/s</ng-container></div>
|
||||
</div>
|
||||
</ng-template>
|
||||
</ng-template>
|
||||
|
@ -22,7 +22,7 @@
|
||||
<a class="dropdown-item" routerLinkActive="active"
|
||||
[routerLink]="['/graphs/mining/block-sizes-weights' | relativeUrl]" i18n="mining.block-sizes-weights">Block Sizes and Weights</a>
|
||||
<a *ngIf="stateService.env.AUDIT" class="dropdown-item" routerLinkActive="active"
|
||||
[routerLink]="['/graphs/mining/block-health' | relativeUrl]" i18n="mining.block-health">Block Health</a>
|
||||
[routerLink]="['/graphs/mining/block-health' | relativeUrl]" i18n="mining.blocks-health">Block Health</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@ -249,10 +249,8 @@ export class HashrateChartComponent implements OnInit {
|
||||
for (const tick of ticks) {
|
||||
if (tick.seriesIndex === 0) { // Hashrate
|
||||
let hashrate = tick.data[1];
|
||||
if (this.isMobile()) {
|
||||
hashratePowerOfTen = selectPowerOfTen(tick.data[1]);
|
||||
hashrate = Math.round(tick.data[1] / hashratePowerOfTen.divider);
|
||||
}
|
||||
hashratePowerOfTen = selectPowerOfTen(tick.data[1]);
|
||||
hashrate = Math.round(tick.data[1] / hashratePowerOfTen.divider);
|
||||
hashrateString = `${tick.marker} ${tick.seriesName}: ${formatNumber(hashrate, this.locale, '1.0-0')} ${hashratePowerOfTen.unit}H/s<br>`;
|
||||
} else if (tick.seriesIndex === 1) { // Difficulty
|
||||
let difficultyPowerOfTen = hashratePowerOfTen;
|
||||
@ -260,18 +258,14 @@ export class HashrateChartComponent implements OnInit {
|
||||
if (difficulty === null) {
|
||||
difficultyString = `${tick.marker} ${tick.seriesName}: No data<br>`;
|
||||
} else {
|
||||
if (this.isMobile()) {
|
||||
difficultyPowerOfTen = selectPowerOfTen(tick.data[1]);
|
||||
difficulty = Math.round(tick.data[1] / difficultyPowerOfTen.divider);
|
||||
}
|
||||
difficultyPowerOfTen = selectPowerOfTen(tick.data[1]);
|
||||
difficulty = tick.data[1] / difficultyPowerOfTen.divider;
|
||||
difficultyString = `${tick.marker} ${tick.seriesName}: ${formatNumber(difficulty, this.locale, '1.2-2')} ${difficultyPowerOfTen.unit}<br>`;
|
||||
}
|
||||
} else if (tick.seriesIndex === 2) { // Hashrate MA
|
||||
let hashrate = tick.data[1];
|
||||
if (this.isMobile()) {
|
||||
hashratePowerOfTen = selectPowerOfTen(tick.data[1]);
|
||||
hashrate = Math.round(tick.data[1] / hashratePowerOfTen.divider);
|
||||
}
|
||||
hashratePowerOfTen = selectPowerOfTen(tick.data[1]);
|
||||
hashrate = Math.round(tick.data[1] / hashratePowerOfTen.divider);
|
||||
hashrateStringMA = `${tick.marker} ${tick.seriesName}: ${formatNumber(hashrate, this.locale, '1.0-0')} ${hashratePowerOfTen.unit}H/s`;
|
||||
}
|
||||
}
|
||||
|
@ -7,7 +7,7 @@
|
||||
</span>
|
||||
<a *ngIf="!userAuth" class="d-flex justify-content-center align-items-center nav-link m-0 menu-click" routerLink="/login" role="tab" (click)="onLinkClick('/login')">
|
||||
<fa-icon class="menu-click" [icon]="['fas', 'user-circle']" [fixedWidth]="true" style="font-size: 25px;margin-right: 15px;"></fa-icon>
|
||||
<span class="menu-click" style="font-size: 20px;">Sign in</span>
|
||||
<span class="menu-click" style="font-size: 20px;" i18n="shared.sign-in">Sign in</span>
|
||||
</a>
|
||||
|
||||
<ng-container *ngIf="userMenuGroups$ | async as menuGroups">
|
||||
|
@ -44,12 +44,12 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Latest blocks -->
|
||||
<!-- Recent blocks -->
|
||||
<div class="col">
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<a class="title-link" href="" [routerLink]="['/blocks' | relativeUrl]">
|
||||
<h5 class="card-title d-inline" i18n="dashboard.latest-blocks">Latest blocks</h5>
|
||||
<h5 class="card-title d-inline" i18n="dashboard.recent-blocks">Recent Blocks</h5>
|
||||
<span> </span>
|
||||
<fa-icon [icon]="['fas', 'external-link-alt']" [fixedWidth]="true" style="vertical-align: text-top; font-size: 13px; color: #4a68b9"></fa-icon>
|
||||
</a>
|
||||
|
@ -6,7 +6,7 @@
|
||||
<div class="pool-distribution" *ngIf="(miningStatsObservable$ | async) as miningStats; else loadingReward">
|
||||
<div class="item">
|
||||
<h5 class="card-title d-inline-block" i18n="mining.miners-luck" i18n-ngbTooltip="mining.miners-luck-1w"
|
||||
ngbTooltip="Pools luck (1 week)" placement="bottom" #minersluck [disableTooltip]="!isEllipsisActive(minersluck)">Pools luck</h5>
|
||||
ngbTooltip="Pools luck (1 week)" placement="bottom" #minersluck [disableTooltip]="!isEllipsisActive(minersluck)">Pools Luck</h5>
|
||||
<p class="card-text" i18n-ngbTooltip="mining.pools-luck-desc"
|
||||
ngbTooltip="The overall luck of all mining pools over the past week. A luck bigger than 100% means the average block time for the current epoch is less than 10 minutes." placement="bottom">
|
||||
{{ miningStats['minersLuck'] }}%
|
||||
@ -14,14 +14,14 @@
|
||||
</div>
|
||||
<div class="item">
|
||||
<h5 class="card-title d-inline-block" i18n="mining.miners-count" i18n-ngbTooltip="mining.miners-count-1w"
|
||||
ngbTooltip="Pools count (1w)" placement="bottom" #poolscount [disableTooltip]="!isEllipsisActive(poolscount)">Pools count</h5>
|
||||
ngbTooltip="Pools count (1w)" placement="bottom" #poolscount [disableTooltip]="!isEllipsisActive(poolscount)">Pools Count</h5>
|
||||
<p class="card-text" i18n-ngbTooltip="mining.pools-count-desc"
|
||||
ngbTooltip="How many unique pools found at least one block over the past week." placement="bottom">
|
||||
{{ miningStats.pools.length }}
|
||||
</p>
|
||||
</div>
|
||||
<div class="item">
|
||||
<h5 class="card-title d-inline-block" i18n="master-page.blocks" i18n-ngbTooltip="master-page.blocks"
|
||||
<h5 class="card-title d-inline-block" i18n="shared.blocks-1w" i18n-ngbTooltip="master-page.blocks"
|
||||
ngbTooltip="Blocks (1w)" placement="bottom" #blockscount [disableTooltip]="!isEllipsisActive(blockscount)">Blocks (1w)</h5>
|
||||
<p class="card-text" i18n-ngbTooltip="mining.blocks-count-desc"
|
||||
ngbTooltip="The number of blocks found over the past week." placement="bottom">
|
||||
@ -95,7 +95,7 @@
|
||||
<th *ngIf="auditAvailable" class="health text-right widget" i18n="latest-blocks.avg_health"
|
||||
i18n-ngbTooltip="latest-blocks.avg_health" ngbTooltip="Avg Health" placement="bottom" #health [disableTooltip]="!isEllipsisActive(health)">Avg Health</th>
|
||||
<th *ngIf="auditAvailable" class="d-none d-sm-table-cell" i18n="mining.fees-per-block">Avg Block Fees</th>
|
||||
<th class="d-none d-lg-table-cell" i18n="mining.empty-blocks">Empty blocks</th>
|
||||
<th class="d-none d-lg-table-cell" i18n="mining.empty-blocks">Empty Blocks</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody [attr.data-cy]="'pools-table'" *ngIf="(miningStatsObservable$ | async) as miningStats">
|
||||
@ -153,19 +153,19 @@
|
||||
<ng-template #loadingReward>
|
||||
<div class="pool-distribution">
|
||||
<div class="item">
|
||||
<h5 class="card-title" i18n="mining.miners-luck">Pools Luck (1w)</h5>
|
||||
<h5 class="card-title" i18n="mining.miners-luck">Pools Luck</h5>
|
||||
<p class="card-text">
|
||||
<span class="skeleton-loader skeleton-loader-big"></span>
|
||||
</p>
|
||||
</div>
|
||||
<div class="item">
|
||||
<h5 class="card-title" i18n="master-page.blocks">Blocks (1w)</h5>
|
||||
<h5 class="card-title" i18n="mining.miners-count" >Pools Count</h5>
|
||||
<p class="card-text">
|
||||
<span class="skeleton-loader skeleton-loader-big"></span>
|
||||
</p>
|
||||
</div>
|
||||
<div class="item">
|
||||
<h5 class="card-title" i18n="mining.miners-count">Pools Count (1w)</h5>
|
||||
<h5 class="card-title" i18n="shared.blocks-1w">Blocks (1w)</h5>
|
||||
<p class="card-text">
|
||||
<span class="skeleton-loader skeleton-loader-big"></span>
|
||||
</p>
|
||||
|
@ -143,7 +143,7 @@
|
||||
<table class="table table-xs table-data">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col" class="data-title text-center" style="width: 33%" i18n="24h">Blocks 24h</th>
|
||||
<th scope="col" class="data-title text-center" style="width: 33%" i18n="24h">Blocks (24h)</th>
|
||||
<th scope="col" class="data-title text-center" style="width: 33%" i18n="1w">1w</th>
|
||||
<th scope="col" class="data-title text-center" style="width: 33%" i18n="all">All</th>
|
||||
</tr>
|
||||
@ -165,7 +165,7 @@
|
||||
<table class="table table-xs table-data">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col" class="data-title text-center" style="width: 33%" i18n="24h">Blocks 24h</th>
|
||||
<th scope="col" class="data-title text-center" style="width: 33%" i18n="24h">Blocks (24h)</th>
|
||||
<th scope="col" class="data-title text-center" style="width: 33%" i18n="1w">1w</th>
|
||||
<th scope="col" class="data-title text-center" style="width: 33%" i18n="all">All</th>
|
||||
</tr>
|
||||
@ -433,7 +433,7 @@
|
||||
<table class="table table-xs table-data text-center">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col" class="data-title text-center" style="width: 33%" i18n="24h">Blocks 24h</th>
|
||||
<th scope="col" class="data-title text-center" style="width: 33%" i18n="24h">Blocks (24h)</th>
|
||||
<th scope="col" class="data-title text-center" style="width: 33%" i18n="1w">1w</th>
|
||||
<th scope="col" class="data-title text-center" style="width: 33%" i18n="all">All</th>
|
||||
</tr>
|
||||
@ -458,7 +458,7 @@
|
||||
<table class="table table-xs table-data text-center">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col" class="data-title text-center" style="width: 33%" i18n="24h">Blocks 24h</th>
|
||||
<th scope="col" class="data-title text-center" style="width: 33%" i18n="24h">Blocks (24h)</th>
|
||||
<th scope="col" class="data-title text-center" style="width: 33%" i18n="1w">1w</th>
|
||||
<th scope="col" class="data-title text-center" style="width: 33%" i18n="all">All</th>
|
||||
</tr>
|
||||
|
@ -6,11 +6,9 @@
|
||||
<form class="formRadioGroup">
|
||||
<div class="btn-group btn-group-toggle" name="radioBasic">
|
||||
<label class="btn btn-primary btn-sm" [class.active]="!fullRbf">
|
||||
<input type="radio" [value]="'All'" fragment="" [routerLink]="[]"> All
|
||||
</label>
|
||||
<input type="radio" [value]="'All'" fragment="" [routerLink]="[]"><span i18n="all">All</span></label>
|
||||
<label class="btn btn-primary btn-sm" [class.active]="fullRbf">
|
||||
<input type="radio" [value]="'Full RBF'" fragment="fullrbf" [routerLink]="[]"> Full RBF
|
||||
</label>
|
||||
<input type="radio" [value]="'Full RBF'" fragment="fullrbf" [routerLink]="[]" i18n="transaction.full-rbf">Full RBF</label>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
@ -33,7 +31,7 @@
|
||||
</div>
|
||||
|
||||
<div class="no-replacements" *ngIf="!trees?.length">
|
||||
<p i18n="rbf.no-replacements-yet">there are no replacements in the mempool yet!</p>
|
||||
<p i18n="rbf.no-replacements-yet">There are no replacements in the mempool yet!</p>
|
||||
</div>
|
||||
</ng-container>
|
||||
</div>
|
||||
|
@ -55,7 +55,7 @@ export class RbfList implements OnInit, OnDestroy {
|
||||
})
|
||||
);
|
||||
|
||||
this.seoService.setTitle($localize`:@@meta.title.rbf-list:RBF Replacements`);
|
||||
this.seoService.setTitle($localize`:@@5e3d5a82750902f159122fcca487b07f1af3141f:RBF Replacements`);
|
||||
this.seoService.setDescription($localize`:@@meta.description.rbf-list:See the most recent RBF replacements on the Bitcoin${seoDescriptionNetwork(this.stateService.network)} network, updated in real-time.`);
|
||||
}
|
||||
|
||||
|
@ -32,9 +32,9 @@
|
||||
<tr>
|
||||
<td class="td-width" i18n="transaction.status|Transaction Status">Status</td>
|
||||
<td>
|
||||
<span *ngIf="rbfInfo.tx.fullRbf" class="badge badge-info" i18n="rbfInfo-features.tag.full-rbf|Full RBF">Full RBF</span>
|
||||
<span *ngIf="rbfInfo.tx.fullRbf" class="badge badge-info" i18n="transaction.full-rbf">Full RBF</span>
|
||||
<span *ngIf="rbfInfo.tx.rbf; else rbfDisabled" class="badge badge-success" i18n="rbfInfo-features.tag.rbf|RBF">RBF</span>
|
||||
<ng-template #rbfDisabled><span class="badge badge-danger mr-1"><del i18n="rbfInfo-features.tag.rbf|RBF">RBF</del></span></ng-template>
|
||||
<ng-template #rbfDisabled><span class="badge badge-danger mr-1"><del i18n="tx-features.tag.rbf|RBF">RBF</del></span></ng-template>
|
||||
<span *ngIf="rbfInfo.tx.mined" class="badge badge-success" i18n="transaction.rbf.mined">Mined</span>
|
||||
</td>
|
||||
</tr>
|
||||
|
@ -14,7 +14,7 @@
|
||||
[class]="(stateService.env.MINING_DASHBOARD || stateService.env.LIGHTNING) ? 'mining' : 'no-menu'" (click)="saveGraphPreference()">
|
||||
<div class="small-buttons">
|
||||
<a class="btn btn-primary btn-sm mb-0" [routerLink]="['/clock/mempool/0' | relativeUrl]" style="color: white" id="btn-clock">
|
||||
<fa-icon [icon]="['fas', 'clock']" [fixedWidth]="true" i18n-title="master-page.clockview" title="Clock view"></fa-icon>
|
||||
<fa-icon [icon]="['fas', 'clock']" [fixedWidth]="true" i18n-title="master-page.clockview" i18n-title="footer.clock-mempool" title="Clock (Mempool)"></fa-icon>
|
||||
</a>
|
||||
<a *ngIf="!isMobile()" class="btn btn-primary btn-sm mb-0" [routerLink]="['/tv' | relativeUrl]" style="color: white" id="btn-tv">
|
||||
<fa-icon [icon]="['fas', 'tv']" [fixedWidth]="true" i18n-title="master-page.tvview" title="TV view"></fa-icon>
|
||||
|
@ -40,7 +40,7 @@
|
||||
<ng-container [ngSwitch]="extraData">
|
||||
<div class="opreturns" *ngSwitchCase="'coinbase'">
|
||||
<div class="opreturn-row">
|
||||
<span class="label">Coinbase</span>
|
||||
<span class="label" i18n="transactions-list.coinbase">Coinbase</span>
|
||||
<span class="message">{{ tx.vin[0].scriptsig | hex2ascii }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -519,7 +519,7 @@
|
||||
<div class="effective-fee-container">
|
||||
<app-fee-rate [fee]="tx.effectiveFeePerVsize"></app-fee-rate>
|
||||
<ng-template [ngIf]="tx?.status?.confirmed">
|
||||
<app-tx-fee-rating class="ml-2 mr-2" *ngIf="tx.fee || tx.effectiveFeePerVsize" [tx]="tx"></app-tx-fee-rating>
|
||||
<app-tx-fee-rating class="ml-2 mr-2 effective-fee-rating" *ngIf="tx.fee || tx.effectiveFeePerVsize" [tx]="tx"></app-tx-fee-rating>
|
||||
</ng-template>
|
||||
</div>
|
||||
<button *ngIf="cpfpInfo.bestDescendant || cpfpInfo.descendants?.length || cpfpInfo.ancestors?.length" type="button" class="btn btn-outline-info btn-sm btn-small-height float-right" (click)="showCpfpDetails = !showCpfpDetails">CPFP <fa-icon [icon]="['fas', 'info-circle']" [fixedWidth]="true"></fa-icon></button>
|
||||
|
@ -152,6 +152,16 @@
|
||||
@media (min-width: 768px){
|
||||
display: inline-block;
|
||||
}
|
||||
@media (max-width: 425px){
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
}
|
||||
|
||||
.effective-fee-rating {
|
||||
@media (max-width: 767px){
|
||||
margin-right: 0px !important;
|
||||
}
|
||||
}
|
||||
|
||||
.title {
|
||||
|
@ -16,7 +16,7 @@
|
||||
|
||||
<ng-template #coinbase>
|
||||
<ng-container *ngIf="line.coinbase; else pegin">
|
||||
<p>Coinbase</p>
|
||||
<p i18n="transactions-list.coinbase">Coinbase</p>
|
||||
</ng-container>
|
||||
</ng-template>
|
||||
|
||||
|
@ -76,7 +76,7 @@
|
||||
<div class="card" *ngIf="(network$ | async) !== 'liquid' && (network$ | async) !== 'liquidtestnet'; else latestBlocks">
|
||||
<div class="card-body">
|
||||
<a class="title-link" href="" [routerLink]="['/rbf' | relativeUrl]">
|
||||
<h5 class="card-title d-inline" i18n="dashboard.latest-rbf-replacements">Latest replacements</h5>
|
||||
<h5 class="card-title d-inline" i18n="dashboard.recent-rbf-replacements">Recent Replacements</h5>
|
||||
<span> </span>
|
||||
<fa-icon [icon]="['fas', 'external-link-alt']" [fixedWidth]="true" style="vertical-align: text-top; font-size: 13px; color: #4a68b9"></fa-icon>
|
||||
</a>
|
||||
@ -99,7 +99,7 @@
|
||||
<td class="table-cell-badges">
|
||||
<span *ngIf="replacement.mined" class="badge badge-success" i18n="transaction.rbf.mined">Mined</span>
|
||||
<span *ngIf="replacement.fullRbf" class="badge badge-info" i18n="transaction.full-rbf">Full RBF</span>
|
||||
<span *ngIf="!replacement.fullRbf" class="badge badge-success" i18n="transaction.rbf">RBF</span>
|
||||
<span *ngIf="!replacement.fullRbf" class="badge badge-success" i18n="tx-features.tag.rbf|RBF">RBF</span>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
@ -110,7 +110,7 @@
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<a class="title-link" href="" [routerLink]="['/blocks' | relativeUrl]">
|
||||
<h5 class="card-title d-inline" i18n="dashboard.latest-blocks">Latest blocks</h5>
|
||||
<h5 class="card-title d-inline" i18n="dashboard.recent-blocks">Recent Blocks</h5>
|
||||
<span> </span>
|
||||
<fa-icon [icon]="['fas', 'external-link-alt']" [fixedWidth]="true" style="vertical-align: text-top; font-size: 13px; color: #4a68b9"></fa-icon>
|
||||
</a>
|
||||
@ -150,7 +150,7 @@
|
||||
<div class="col" style="max-height: 410px">
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title" i18n="dashboard.latest-transactions">Latest transactions</h5>
|
||||
<h5 class="card-title" i18n="dashboard.recent-transactions">Recent Transactions</h5>
|
||||
<table class="table latest-transactions">
|
||||
<thead>
|
||||
<th class="table-cell-txid" i18n="dashboard.latest-transactions.txid">TXID</th>
|
||||
@ -233,7 +233,7 @@
|
||||
</p>
|
||||
</div>
|
||||
<div class="item bar">
|
||||
<h5 class="card-title" i18n="dashboard.memory-usage|Memory usage">Memory usage</h5>
|
||||
<h5 class="card-title" i18n="dashboard.memory-usage|Memory usage">Memory Usage</h5>
|
||||
<div class="card-text" *ngIf="(isLoadingWebSocket$ | async) === false && mempoolInfoData.value; else loadingbig">
|
||||
<div class="progress">
|
||||
<div class="progress-bar {{ mempoolInfoData.value.mempoolSizeProgress }}" role="progressbar" [ngStyle]="{'width': (mempoolInfoData.value.memPoolInfo.usage / mempoolInfoData.value.memPoolInfo.maxmempool * 100) + '%' }"> </div>
|
||||
@ -256,7 +256,7 @@
|
||||
</ng-template>
|
||||
|
||||
<ng-template #txPerSecond let-mempoolInfoData>
|
||||
<h5 class="card-title" i18n="dashboard.incoming-transactions">Incoming transactions</h5>
|
||||
<h5 class="card-title" i18n="dashboard.incoming-transactions">Incoming Transactions</h5>
|
||||
<ng-template [ngIf]="(isLoadingWebSocket$ | async) === false && mempoolInfoData.value" [ngIfElse]="loadingTransactions">
|
||||
<span *ngIf="(mempoolLoadingStatus$ | async) !== 100; else inSync">
|
||||
<span class="badge badge-pill badge-warning"><ng-container i18n="dashboard.backend-is-synchronizing">Backend is synchronizing</ng-container> ({{ mempoolLoadingStatus$ | async }}%)</span>
|
||||
|
@ -10,9 +10,9 @@
|
||||
<div class="doc-content">
|
||||
|
||||
<div id="disclaimer">
|
||||
<table *ngIf="!mobileViewport"><tr><td><app-svg-images name="warning" class="disclaimer-warning" viewBox="0 0 304 304" fill="#ffc107" width="50" height="50"></app-svg-images></td><td><p i18n="faq.big-disclaimer"><b>mempool.space merely provides data about the Bitcoin network.</b> It cannot help you with retrieving funds, wallet issues, etc.</p><p>For any such requests, you need to get in touch with the entity that helped make the transaction (wallet software, exchange company, etc).</p></td></tr></table>
|
||||
<div *ngIf="mobileViewport"><app-svg-images name="warning" class="disclaimer-warning" viewBox="0 0 304 304" fill="#ffc107" width="50" height="50"></app-svg-images><p i18n="faq.big-disclaimer"><b>mempool.space merely provides data about the Bitcoin network.</b> It cannot help you with retrieving funds, wallet issues, etc.</p><p>For any such requests, you need to get in touch with the entity that helped make the transaction (wallet software, exchange company, etc).</p></div>
|
||||
|
||||
<table *ngIf="!mobileViewport"><tr><td><app-svg-images name="warning" class="disclaimer-warning" viewBox="0 0 304 304" fill="#ffc107" width="50" height="50"></app-svg-images></td><td> <ng-container *ngTemplateOutlet="faqDisclaimer"></ng-container></td></tr></table>
|
||||
<div *ngIf="mobileViewport"><app-svg-images name="warning" class="disclaimer-warning" viewBox="0 0 304 304" fill="#ffc107" width="50" height="50"></app-svg-images><ng-container *ngTemplateOutlet="faqDisclaimer"></ng-container></div>
|
||||
<ng-template #faqDisclaimer i18n="faq.big-disclaimer"><p><b>mempool.space merely provides data about the Bitcoin network.</b> It cannot help you with retrieving funds, wallet issues, etc.</p><p>For any such requests, you need to get in touch with the entity that helped make the transaction (wallet software, exchange company, etc).</p></ng-template>
|
||||
</div>
|
||||
|
||||
<div class="doc-item-container" *ngFor="let item of faq">
|
||||
|
@ -64,10 +64,9 @@ export class DocsComponent implements OnInit {
|
||||
}
|
||||
} else {
|
||||
this.activeTab = 3;
|
||||
this.seoService.setTitle($localize`:@@meta.title.docs.websocket:Electrum RPC`);
|
||||
this.seoService.setTitle($localize`:@@meta.title.docs.electrum:Electrum RPC`);
|
||||
this.seoService.setDescription($localize`:@@meta.description.docs.electrumrpc:Documentation for our Electrum RPC interface: get instant, convenient, and reliable access to an Esplora instance.`);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
|
@ -37,7 +37,7 @@
|
||||
<thead>
|
||||
<th class="alias text-left" i18n="lightning.alias">Alias</th>
|
||||
<th class="nodedetails text-left"> </th>
|
||||
<th class="status text-left" i18n="status">Status</th>
|
||||
<th class="status text-left" i18n="transaction.status|Transaction Status">Status</th>
|
||||
<th class="feerate text-left" *ngIf="status !== 'closed'" i18n="transaction.fee-rate|Transaction fee rate">Fee rate</th>
|
||||
<th class="feerate text-left" *ngIf="status === 'closed'" i18n="channels.closing_date">Closing date</th>
|
||||
<th class="liquidity text-right" i18n="lightning.capacity">Capacity</th>
|
||||
|
@ -14,7 +14,7 @@
|
||||
<table class="table table-borderless table-striped">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Description</td>
|
||||
<td i18n>Description</td>
|
||||
<td><div class="description-text">These are the Lightning nodes operated by The Mempool Open Source Project that provide data for the mempool.space website. Connect to us!
|
||||
</div>
|
||||
</td>
|
||||
@ -70,7 +70,7 @@
|
||||
<table class="table table-borderless">
|
||||
<thead>
|
||||
<th class="alias text-left" i18n="lightning.alias">Alias</th>
|
||||
<th class="text-left">Connect</th>
|
||||
<th class="text-left" i18n="lightning.connect-to-node|Connect">Connect</th>
|
||||
<th class="city text-right d-none d-md-table-cell" i18n="lightning.location">Location</th>
|
||||
</thead>
|
||||
<tbody *ngIf="nodes$ | async as response; else skeleton">
|
||||
|
@ -49,7 +49,7 @@
|
||||
<tr *ngIf="!node.city && !node.country">
|
||||
<td i18n="lightning.location">Location</td>
|
||||
<td>
|
||||
<span>unknown</span>
|
||||
<span i18n="unknown">Unknown</span>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
@ -119,7 +119,7 @@
|
||||
</div>
|
||||
|
||||
<ng-template #featurebits let-bits="bits">
|
||||
<td i18n="lightning.features" class="text-truncate label">Features</td>
|
||||
<td i18n="transaction.features|Transaction features" class="text-truncate label">Features</td>
|
||||
<td class="d-flex justify-content-between">
|
||||
<span class="text-truncate w-90">{{ bits }}</span>
|
||||
<button type="button" class="btn btn-outline-info btn-xs" (click)="toggleFeatures()" i18n="transaction.details|Transaction Details">Details</button>
|
||||
@ -133,11 +133,11 @@
|
||||
<h5>Raw bits</h5>
|
||||
<span class="text-wrap w-100"><small>{{ node.featuresBits }}</small></span>
|
||||
</div>
|
||||
<h5>Decoded</h5>
|
||||
<h5 i18n="lightning.decoded|Decoded">Decoded</h5>
|
||||
<table class="table table-borderless table-striped table-fixed">
|
||||
<thead>
|
||||
<th style="width: 13%">Bit</th>
|
||||
<th>Name</th>
|
||||
<th i18n="lightning.as-name">Name</th>
|
||||
<th style="width: 25%; text-align: right">Required</th>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
@ -1,22 +1,28 @@
|
||||
<div class="map-wrapper" [class]="style">
|
||||
<div class="map-wrapper" [class]="style" *ngIf="style !== 'graph'">
|
||||
<ng-container *ngIf="channelsObservable | async">
|
||||
<div *ngIf="chartOptions" [class]="'full-container ' + style + (fitContainer ? ' fit-container' : '')">
|
||||
<div *ngIf="style === 'graph'" class="card-header">
|
||||
<div class="d-flex d-md-block align-items-baseline" style="margin-bottom: -5px">
|
||||
<span i18n="lightning.nodes-channels-world-map">Lightning Nodes Channels World Map</span>
|
||||
</div>
|
||||
<small style="color: #ffffff66" i18n="lightning.tor-nodes-excluded">(Tor nodes excluded)</small>
|
||||
</div>
|
||||
|
||||
<div class="chart" [class]="style" echarts [initOpts]="chartInitOptions" [options]="chartOptions"
|
||||
(chartInit)="onChartInit($event)" (chartFinished)="onChartFinished($event)">
|
||||
</div>
|
||||
|
||||
<div *ngIf="!chartOptions && style === 'nodepage'" style="padding-top: 30px"></div>
|
||||
</div>
|
||||
|
||||
<div class="text-center loading-spinner" [class]="style" *ngIf="isLoading && !disableSpinner">
|
||||
<div class="spinner-border text-light"></div>
|
||||
</div>
|
||||
</ng-container>
|
||||
</div>
|
||||
|
||||
<div class="full-container-graph" *ngIf="style === 'graph'">
|
||||
|
||||
<div class="card-header">
|
||||
<div class="d-flex d-md-block align-items-baseline" style="margin-bottom: -5px">
|
||||
<span i18n="lightning.nodes-channels-world-map">Lightning Nodes Channels World Map</span>
|
||||
</div>
|
||||
<small style="color: #ffffff66" i18n="lightning.tor-nodes-excluded">(Tor nodes excluded)</small>
|
||||
</div>
|
||||
|
||||
<div *ngIf="channelsObservable | async" class="chart-graph" echarts [initOpts]="chartInitOptions" [options]="chartOptions"
|
||||
(chartInit)="onChartInit($event)" (chartFinished)="onChartFinished($event)">
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
@ -143,3 +143,55 @@
|
||||
text-align: center;
|
||||
margin-top: 100px;
|
||||
}
|
||||
|
||||
.full-container-graph {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 0px 15px;
|
||||
width: 100%;
|
||||
height: calc(100vh - 225px);
|
||||
min-height: 400px;
|
||||
@media (min-width: 992px) {
|
||||
height: calc(100vh - 150px);
|
||||
}
|
||||
}
|
||||
.full-container-graph.widget {
|
||||
min-height: 240px;
|
||||
height: 240px;
|
||||
padding: 0px;
|
||||
}
|
||||
.full-container-graph.fit-container {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
height: 100%;
|
||||
min-height: 100px;
|
||||
|
||||
.chart {
|
||||
padding: 0;
|
||||
min-height: 100px;
|
||||
}
|
||||
}
|
||||
|
||||
.chart-graph {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
height: 100%;
|
||||
padding-top: 30px;
|
||||
padding-bottom: 20px;
|
||||
padding-right: 10px;
|
||||
@media (max-width: 992px) {
|
||||
padding-bottom: 25px;
|
||||
}
|
||||
@media (max-width: 829px) {
|
||||
padding-bottom: 50px;
|
||||
}
|
||||
@media (max-width: 767px) {
|
||||
padding-bottom: 25px;
|
||||
}
|
||||
@media (max-width: 629px) {
|
||||
padding-bottom: 55px;
|
||||
}
|
||||
@media (max-width: 567px) {
|
||||
padding-bottom: 55px;
|
||||
}
|
||||
}
|
||||
|
@ -65,6 +65,7 @@ export class NodesChannelsMap implements OnInit {
|
||||
}
|
||||
|
||||
if (this.style === 'graph') {
|
||||
this.center = [0, 5];
|
||||
this.seoService.setTitle($localize`Lightning Nodes Channels World Map`);
|
||||
this.seoService.setDescription($localize`:@@meta.description.lightning.node-map:See the channels of non-Tor Lightning network nodes visualized on a world map. Hover/tap on points on the map for node names and details.`);
|
||||
}
|
||||
@ -238,7 +239,6 @@ export class NodesChannelsMap implements OnInit {
|
||||
title: title ?? undefined,
|
||||
tooltip: {},
|
||||
geo: {
|
||||
top: 75,
|
||||
animation: false,
|
||||
silent: true,
|
||||
center: this.center,
|
||||
|
@ -3,6 +3,7 @@ import { Inject, Injectable } from '@angular/core';
|
||||
import { ApiService } from './api.service';
|
||||
import { SeoService } from './seo.service';
|
||||
import { StateService } from './state.service';
|
||||
import { ActivatedRoute } from '@angular/router';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
@ -11,12 +12,15 @@ export class EnterpriseService {
|
||||
exclusiveHostName = '.mempool.space';
|
||||
subdomain: string | null = null;
|
||||
info: object = {};
|
||||
statsUrl: string;
|
||||
siteId: number;
|
||||
|
||||
constructor(
|
||||
@Inject(DOCUMENT) private document: Document,
|
||||
private apiService: ApiService,
|
||||
private seoService: SeoService,
|
||||
private stateService: StateService,
|
||||
private activatedRoute: ActivatedRoute,
|
||||
) {
|
||||
const subdomain = this.document.location.hostname.indexOf(this.exclusiveHostName) > -1
|
||||
&& this.document.location.hostname.split(this.exclusiveHostName)[0] || false;
|
||||
@ -56,7 +60,7 @@ export class EnterpriseService {
|
||||
|
||||
insertMatomo(siteId?: number): void {
|
||||
let statsUrl = '//stats.mempool.space/';
|
||||
|
||||
|
||||
if (!siteId) {
|
||||
switch (this.document.location.hostname) {
|
||||
case 'mempool.space':
|
||||
@ -88,16 +92,63 @@ export class EnterpriseService {
|
||||
}
|
||||
}
|
||||
|
||||
this.statsUrl = statsUrl;
|
||||
this.siteId = siteId;
|
||||
|
||||
// @ts-ignore
|
||||
const _paq = window._paq = window._paq || [];
|
||||
_paq.push(['disableCookies']);
|
||||
_paq.push(['trackPageView']);
|
||||
_paq.push(['enableLinkTracking']);
|
||||
(function() {
|
||||
_paq.push(['setTrackerUrl', statsUrl+'m.php']);
|
||||
_paq.push(['setSiteId', siteId.toString()]);
|
||||
const d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0];
|
||||
g.type='text/javascript'; g.async=true; g.src=statsUrl+'m.js'; s.parentNode.insertBefore(g,s);
|
||||
})();
|
||||
if (window._paq && window['Matomo']) {
|
||||
window['Matomo'].addTracker(this.statsUrl+'m.php', this.siteId.toString());
|
||||
const matomo = this.getMatomo();
|
||||
matomo.setDocumentTitle(this.seoService.getTitle());
|
||||
matomo.setCustomUrl(this.getCustomUrl());
|
||||
matomo.disableCookies();
|
||||
matomo.trackPageView();
|
||||
matomo.enableLinkTracking();
|
||||
} else {
|
||||
// @ts-ignore
|
||||
const alreadyInitialized = !!window._paq;
|
||||
// @ts-ignore
|
||||
const _paq = window._paq = window._paq || [];
|
||||
_paq.push(['setDocumentTitle', this.seoService.getTitle()]);
|
||||
_paq.push(['setCustomUrl', this.getCustomUrl()]);
|
||||
_paq.push(['disableCookies']);
|
||||
_paq.push(['trackPageView']);
|
||||
_paq.push(['enableLinkTracking']);
|
||||
if (alreadyInitialized) {
|
||||
_paq.push(['addTracker', this.statsUrl+'m.php', this.siteId.toString()]);
|
||||
} else {
|
||||
(function() {
|
||||
_paq.push(['setTrackerUrl', this.statsUrl+'m.php']);
|
||||
_paq.push(['setSiteId', this.siteId.toString()]);
|
||||
const d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0];
|
||||
// @ts-ignore
|
||||
g.type='text/javascript'; g.async=true; g.src=statsUrl+'m.js'; s.parentNode.insertBefore(g,s);
|
||||
})();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private getMatomo() {
|
||||
if (this.siteId != null) {
|
||||
return window['Matomo']?.getTracker(this.statsUrl, this.siteId);
|
||||
}
|
||||
}
|
||||
|
||||
goal(id: number) {
|
||||
// @ts-ignore
|
||||
this.getMatomo()?.trackGoal(id);
|
||||
}
|
||||
|
||||
private getCustomUrl(): string {
|
||||
let url = window.location.origin + '/';
|
||||
let route = this.activatedRoute;
|
||||
while (route) {
|
||||
const segment = route?.routeConfig?.path;
|
||||
if (segment && segment.length) {
|
||||
url += segment + '/';
|
||||
}
|
||||
route = route.firstChild;
|
||||
}
|
||||
return url;
|
||||
}
|
||||
}
|
||||
|
@ -10,7 +10,7 @@ import { StateService } from './state.service';
|
||||
export class SeoService {
|
||||
network = '';
|
||||
baseTitle = 'mempool';
|
||||
baseDescription = 'Explore the full Bitcoin ecosystem with The Mempool Open Project™.';
|
||||
baseDescription = 'Explore the full Bitcoin ecosystem with The Mempool Open Source Project™.';
|
||||
|
||||
canonicalLink: HTMLElement = document.getElementById('canonical');
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
<ng-container *ngIf="rateUnits$ | async as units">
|
||||
<ng-container *ngIf="units !== 'wu'">{{ fee / (weight / 4) | feeRounding:rounding }} <span *ngIf="showUnit" [class]="unitClass" [style]="unitStyle">sat/vB</span></ng-container>
|
||||
<ng-container *ngIf="units === 'wu'">{{ fee / weight | feeRounding:rounding }} <span *ngIf="showUnit" [class]="unitClass" [style]="unitStyle">sat/WU</span></ng-container>
|
||||
<ng-container *ngIf="units !== 'wu'">{{ fee / (weight / 4) | feeRounding:rounding }} <span *ngIf="showUnit" [class]="unitClass" [style]="unitStyle" i18n="shared.sat-vbyte|sat/vB">sat/vB</span></ng-container>
|
||||
<ng-container *ngIf="units === 'wu'">{{ fee / weight | feeRounding:rounding }} <span *ngIf="showUnit" [class]="unitClass" [style]="unitStyle" i18n="shared.sat-weight-units|sat/WU">sat/WU</span></ng-container>
|
||||
</ng-container>
|
@ -38,45 +38,45 @@
|
||||
</div>
|
||||
<div class="row col-md-12 link-tree" [class]="{'services': isServicesPage}">
|
||||
<div class="links">
|
||||
<p class="category">Explore</p>
|
||||
<p><a [routerLink]="['/mining' | relativeUrl]">Mining Dashboard</a></p>
|
||||
<p><a *ngIf="env.LIGHTNING" [routerLink]="['/lightning' | relativeUrl]">Lightning Dashboard</a></p>
|
||||
<p><a [routerLink]="['/blocks' | relativeUrl]">Recent Blocks</a></p>
|
||||
<p class="category" i18n="footer.explore">Explore</p>
|
||||
<p><a [routerLink]="['/mining' | relativeUrl]" i18n="mining.mining-dashboard">Mining Dashboard</a></p>
|
||||
<p><a *ngIf="env.LIGHTNING" [routerLink]="['/lightning' | relativeUrl]" i18n="master-page.lightning">Lightning Explorer</a></p>
|
||||
<p><a [routerLink]="['/blocks' | relativeUrl]" i18n="dashboard.recent-blocks">Recent Blocks</a></p>
|
||||
<p><a [routerLink]="['/tx/push' | relativeUrl]" i18n="shared.broadcast-transaction|Broadcast Transaction">Broadcast Transaction</a></p>
|
||||
<p *ngIf="officialMempoolSpace"><a [routerLink]="['/lightning/group/the-mempool-open-source-project' | relativeUrl]" i18n="footer.connect-to-our-nodes">Connect to our Nodes</a></p>
|
||||
<p><a [routerLink]="['/docs/api' | relativeUrl]">API Documentation</a></p>
|
||||
<p><a [routerLink]="['/docs/api' | relativeUrl]" i18n="footer.api-documentation">API Documentation</a></p>
|
||||
</div>
|
||||
<div class="links">
|
||||
<p class="category">Learn</p>
|
||||
<p><a [routerLink]="['/docs/faq']" fragment="what-is-a-mempool">What is a mempool?</a></p>
|
||||
<p><a [routerLink]="['/docs/faq']" fragment="what-is-a-block-explorer">What is a block explorer?</a></p>
|
||||
<p><a [routerLink]="['/docs/faq']" fragment="what-is-a-mempool-explorer">What is a mempool explorer?</a></p>
|
||||
<p><a [routerLink]="['/docs/faq']" fragment="why-is-transaction-stuck-in-mempool">Why isn't my transaction confirming?</a></p>
|
||||
<p><a [routerLink]="['/docs/faq' | relativeUrl]">More FAQs ›</a></p>
|
||||
<p class="category" i18n="footer.learn">Learn</p>
|
||||
<p><a [routerLink]="['/docs/faq']" fragment="what-is-a-mempool" i18n="faq.what-is-a-mempool">What is a mempool?</a></p>
|
||||
<p><a [routerLink]="['/docs/faq']" fragment="what-is-a-block-explorer" i18n="faq.what-is-a-block-exlorer">What is a block explorer?</a></p>
|
||||
<p><a [routerLink]="['/docs/faq']" fragment="what-is-a-mempool-explorer" i18n="faq.what-is-a-mempool-exlorer">What is a mempool explorer?</a></p>
|
||||
<p><a [routerLink]="['/docs/faq']" fragment="why-is-transaction-stuck-in-mempool" i18n="faq.why-isnt-my-transaction-confirming">Why isn't my transaction confirming?</a></p>
|
||||
<p><a [routerLink]="['/docs/faq' | relativeUrl]" i18n="faq.more-faq">More FAQs »</a></p>
|
||||
</div>
|
||||
|
||||
<div class="links" *ngIf="officialMempoolSpace || env.TESTNET_ENABLED || env.SIGNET_ENABLED || env.LIQUID_ENABLED || env.LIQUID_TESTNET_ENABLED else toolBox" >
|
||||
<p class="category">Networks</p>
|
||||
<p *ngIf="(officialMempoolSpace || (env.BASE_MODULE === 'mempool')) && (currentNetwork !== '') && (currentNetwork !== 'mainnet')"><a [href]="networkLink('mainnet')">Mainnet Explorer</a></p>
|
||||
<p *ngIf="(officialMempoolSpace || (env.BASE_MODULE === 'mempool')) && (currentNetwork !== 'testnet') && env.TESTNET_ENABLED"><a [href]="networkLink('testnet')">Testnet Explorer</a></p>
|
||||
<p *ngIf="(officialMempoolSpace || (env.BASE_MODULE === 'mempool')) && (currentNetwork !== 'signet') && env.SIGNET_ENABLED"><a [href]="networkLink('signet')">Signet Explorer</a></p>
|
||||
<p *ngIf="(officialMempoolSpace || env.LIQUID_ENABLED) && (currentNetwork !== 'liquidtestnet')"><a [href]="networkLink('liquidtestnet')">Liquid Testnet Explorer</a></p>
|
||||
<p *ngIf="(officialMempoolSpace || env.LIQUID_ENABLED) && (currentNetwork !== 'liquid')"><a [href]="networkLink('liquid')">Liquid Explorer</a></p>
|
||||
<p *ngIf="(officialMempoolSpace && (currentNetwork !== 'bisq'))"><a [href]="networkLink('bisq')">Bisq Explorer</a></p>
|
||||
<p class="category" i18n="footer.networks">Networks</p>
|
||||
<p *ngIf="(officialMempoolSpace || (env.BASE_MODULE === 'mempool')) && (currentNetwork !== '') && (currentNetwork !== 'mainnet')"><a [href]="networkLink('mainnet')" i18n="footer.mainnet-explorer">Mainnet Explorer</a></p>
|
||||
<p *ngIf="(officialMempoolSpace || (env.BASE_MODULE === 'mempool')) && (currentNetwork !== 'testnet') && env.TESTNET_ENABLED"><a [href]="networkLink('testnet')" i18n="footer.testnet-explorer">Testnet Explorer</a></p>
|
||||
<p *ngIf="(officialMempoolSpace || (env.BASE_MODULE === 'mempool')) && (currentNetwork !== 'signet') && env.SIGNET_ENABLED"><a [href]="networkLink('signet')" i18n="footer.signet-explorer">Signet Explorer</a></p>
|
||||
<p *ngIf="(officialMempoolSpace || env.LIQUID_ENABLED) && (currentNetwork !== 'liquidtestnet')"><a [href]="networkLink('liquidtestnet')" i18n="footer.liquid-testnet-explorer">Liquid Testnet Explorer</a></p>
|
||||
<p *ngIf="(officialMempoolSpace || env.LIQUID_ENABLED) && (currentNetwork !== 'liquid')"><a [href]="networkLink('liquid')" i18n="footer.liquid-explorer">Liquid Explorer</a></p>
|
||||
<p *ngIf="(officialMempoolSpace && (currentNetwork !== 'bisq'))"><a [href]="networkLink('bisq')" i18n="footer.bisq-explorer">Bisq Explorer</a></p>
|
||||
</div>
|
||||
<ng-template #toolBox>
|
||||
<div class="links">
|
||||
<p class="category">Tools</p>
|
||||
<p><a [routerLink]="['/clock/mempool/0']">Clock (Mempool)</a></p>
|
||||
<p><a [routerLink]="['/clock/mined/0']">Clock (Mined)</a></p>
|
||||
<p><a [routerLink]="['/tools/calculator']">BTC/Fiat Converter</a></p>
|
||||
<p class="category" i18n="footer.tools">Tools</p>
|
||||
<p><a [routerLink]="['/clock/mempool/0']" i18n="footer.clock-mempool">Clock (Mempool)</a></p>
|
||||
<p><a [routerLink]="['/clock/mined/0']" i18n="footer.clock-mined">Clock (Mined)</a></p>
|
||||
<p><a [routerLink]="['/tools/calculator']" i18n="shared.calculator">Calculator</a></p>
|
||||
</div>
|
||||
</ng-template>
|
||||
<div class="links">
|
||||
<p class="category">Legal</p>
|
||||
<p class="category" i18n="footer.legal">Legal</p>
|
||||
<p><a [routerLink]="['/terms-of-service']" i18n="shared.terms-of-service|Terms of Service">Terms of Service</a></p>
|
||||
<p><a [routerLink]="['/privacy-policy']" i18n="shared.privacy-policy|Privacy Policy">Privacy Policy</a></p>
|
||||
<p><a [routerLink]="['/trademark-policy']">Trademark Policy</a></p>
|
||||
<p><a [routerLink]="['/trademark-policy']" i18n="shared.trademark-policy|Trademark Policy">Trademark Policy</a></p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row social-links">
|
||||
|
@ -2,12 +2,12 @@ import { Component, Input, OnInit } from "@angular/core";
|
||||
import { DomSanitizer, SafeHtml } from "@angular/platform-browser";
|
||||
|
||||
const MempoolErrors = {
|
||||
'internal_server_error': `Something went wrong, please try again later`,
|
||||
'acceleration_duplicated': `This transaction has already been accelerated.`,
|
||||
'acceleration_outbid': `Your fee delta is too low.`,
|
||||
'cannot_accelerate_tx': `Cannot accelerate this transaction.`,
|
||||
'cannot_decode_raw_tx': `Cannot decode this raw transaction.`,
|
||||
'cannot_fetch_raw_tx': `Cannot find this transaction.`,
|
||||
'database_error': `Something went wrong. Please try again later.`,
|
||||
'high_sigop_tx': `This transaction cannot be accelerated.`,
|
||||
'invalid_acceleration_request': `This acceleration request is not valid.`,
|
||||
'invalid_tx_dependencies': `This transaction dependencies are not valid.`,
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user