Merge branch 'natsee/liquid-federation-audit' into natsee/liquid-audit-dashboard

This commit is contained in:
natsee
2024-01-25 15:22:47 +01:00
83 changed files with 23198 additions and 9943 deletions

View File

@@ -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 Source 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$()

View File

@@ -405,7 +405,7 @@
<div class="copyright">
<div class="title">
Copyright &copy; 2019-2023<br>
Copyright &copy; 2019-2024<br>
Mempool Space K.K.<br>
and other shadowy super-coders
</div>
@@ -422,7 +422,7 @@
Trademark Notice<br>
</div>
<p>
The Mempool Open Source Project&reg;, Mempool Accelerator&trade;, Mempool Enterprise&reg;, Mempool Liquidity&trade;, mempool.space&reg;, Be your own explorer&trade;, Explore the full Bitcoin ecosystem&trade;, Mempool Goggles&trade;, the mempool logo, the mempool Square logo, the mempool Blocks logo, the mempool Blocks 3 | 2 logo, the mempool.space Vertical Logo, and the mempool.space Horizontal logo are either registered trademarks or trademarks of Mempool Space K.K in Japan, the United States, and/or other countries.
The Mempool Open Source Project&reg;, Mempool Accelerator&trade;, Mempool Enterprise&reg;, Mempool Liquidity&trade;, mempool.space&reg;, Be your own explorer&trade;, Explore the full Bitcoin ecosystem&reg;, Mempool Goggles&trade;, the mempool logo, the mempool Square logo, the mempool Blocks logo, the mempool Blocks 3 | 2 logo, the mempool.space Vertical Logo, and the mempool.space Horizontal logo are either registered trademarks or trademarks of Mempool Space K.K in Japan, the United States, and/or other countries.
</p>
<p>
While our software is available under an open source software license, the copyright license does not include an implied right or license to use our trademarks. See our <a href="https://mempool.space/trademark-policy">Trademark Policy and Guidelines</a> for more details, published on &lt;https://mempool.space/trademark-policy&gt;.

View File

@@ -66,7 +66,7 @@ export class AccelerationFeesGraphComponent implements OnInit, OnDestroy {
}
ngOnInit(): void {
this.seoService.setTitle($localize`:@@6c453b11fd7bd159ae30bc381f367bc736d86909:Acceleration Fees`);
this.seoService.setTitle($localize`:@@bcf34abc2d9ed8f45a2f65dd464c46694e9a181e:Acceleration Fees`);
this.isLoading = true;
if (this.widget) {
this.miningWindowPreference = '1m';

View File

@@ -17,7 +17,7 @@
</div>
</div>
<div class="item">
<h5 class="card-title" i18n="accelerator.success-rate">Success rate</h5>
<h5 class="card-title" i18n="accelerator.success-rate">Success Rate</h5>
<div class="card-text">
<div>{{ stats.successRate.toFixed(2) }} %</div>
<div class="symbol" i18n="accelerator.mined-next-block">mined</div>
@@ -43,7 +43,7 @@
</div>
</div>
<div class="item">
<h5 class="card-title" i18n="accelerator.success-rate">Success rate</h5>
<h5 class="card-title" i18n="accelerator.success-rate">Success Rate</h5>
<div class="card-text">
<div class="skeleton-loader"></div>
<div class="skeleton-loader"></div>

View File

@@ -7,7 +7,7 @@
<!-- pending stats -->
<div class="col">
<div class="main-title">
<span [attr.data-cy]="'pending-accelerations'" i18n="accelerator.pending-accelerations">Active accelerations</span>
<span [attr.data-cy]="'pending-accelerations'" i18n="accelerator.pending-accelerations">Active Accelerations</span>
</div>
<div class="card-wrapper">
<div class="card">
@@ -69,7 +69,7 @@
<div class="card list-card">
<div class="card-body">
<div class="title-link">
<h5 class="card-title d-inline" i18n="dashboard.recent-accelerations">Active Accelerations</h5>
<h5 class="card-title d-inline" i18n="accelerator.pending-accelerations">Active Accelerations</h5>
</div>
<app-accelerations-list [attr.data-cy]="'pending-accelerations'" [widget]=true [pending]="true" [accelerations$]="pendingAccelerations$"></app-accelerations-list>
</div>

View File

@@ -17,7 +17,7 @@
</div>
</div>
<div class="item">
<h5 class="card-title" i18n="accelerator.total-vsize">Total vsize</h5>
<h5 class="card-title" i18n="accelerator.total-vsize">Total Vsize</h5>
<div class="card-text">
<div [innerHTML]="'&lrm;' + (stats.totalVsize * 4 | vbytes: 2)"></div>
<div class="symbol">{{ (stats.totalVsize / 1_000_000 * 100).toFixed(2) }}% <span i18n="accelerator.percent-of-next-block"> of next block</span></div>
@@ -43,7 +43,7 @@
</div>
</div>
<div class="item">
<h5 class="card-title" i18n="accelerator.total-vsize">Total vsize</h5>
<h5 class="card-title" i18n="accelerator.total-vsize">Total Vsize</h5>
<div class="card-text">
<div class="skeleton-loader"></div>
<div class="skeleton-loader"></div>

View File

@@ -18,7 +18,7 @@
<h5>{{ group.label }}</h5>
<div class="filter-group">
<ng-container *ngFor="let filter of group.filters;">
<button class="btn filter-tag" [class.selected]="filterFlags[filter.key]" (click)="toggleFilter(filter.key)">{{ filter.label }}</button>
<button *ngIf="!disabledFilters[filter.key]" class="btn filter-tag" [class.selected]="filterFlags[filter.key]" (click)="toggleFilter(filter.key)">{{ filter.label }}</button>
</ng-container>
</div>
</ng-container>

View File

@@ -1,5 +1,7 @@
import { Component, EventEmitter, Output, HostListener, Input, ChangeDetectorRef, OnChanges, SimpleChanges } from '@angular/core';
import { Component, EventEmitter, Output, HostListener, Input, ChangeDetectorRef, OnChanges, SimpleChanges, OnInit, OnDestroy } from '@angular/core';
import { FilterGroups, TransactionFilters } from '../../shared/filters.utils';
import { StateService } from '../../services/state.service';
import { Subscription } from 'rxjs';
@Component({
@@ -7,24 +9,48 @@ import { FilterGroups, TransactionFilters } from '../../shared/filters.utils';
templateUrl: './block-filters.component.html',
styleUrls: ['./block-filters.component.scss'],
})
export class BlockFiltersComponent implements OnChanges {
export class BlockFiltersComponent implements OnInit, OnChanges, OnDestroy {
@Input() cssWidth: number = 800;
@Input() excludeFilters: string[] = [];
@Output() onFilterChanged: EventEmitter<bigint | null> = new EventEmitter();
filterSubscription: Subscription;
filters = TransactionFilters;
filterGroups = FilterGroups;
disabledFilters: { [key: string]: boolean } = {};
activeFilters: string[] = [];
filterFlags: { [key: string]: boolean } = {};
menuOpen: boolean = false;
constructor(
private stateService: StateService,
private cd: ChangeDetectorRef,
) {}
ngOnInit(): void {
this.filterSubscription = this.stateService.activeGoggles$.subscribe((activeFilters: string[]) => {
for (const key of Object.keys(this.filterFlags)) {
this.filterFlags[key] = false;
}
for (const key of activeFilters) {
this.filterFlags[key] = !this.disabledFilters[key];
}
this.activeFilters = [...activeFilters.filter(key => !this.disabledFilters[key])];
this.onFilterChanged.emit(this.getBooleanFlags());
});
}
ngOnChanges(changes: SimpleChanges): void {
if (changes.cssWidth) {
this.cd.markForCheck();
}
if (changes.excludeFilters) {
this.disabledFilters = {};
this.excludeFilters.forEach(filter => {
this.disabledFilters[filter] = true;
});
}
}
toggleFilter(key): void {
@@ -46,7 +72,9 @@ export class BlockFiltersComponent implements OnChanges {
// remove active filter
this.activeFilters = this.activeFilters.filter(f => f != key);
}
this.onFilterChanged.emit(this.getBooleanFlags());
const booleanFlags = this.getBooleanFlags();
this.onFilterChanged.emit(booleanFlags);
this.stateService.activeGoggles$.next([...this.activeFilters]);
}
getBooleanFlags(): bigint | null {
@@ -67,4 +95,8 @@ export class BlockFiltersComponent implements OnChanges {
}
return true;
}
ngOnDestroy(): void {
this.filterSubscription.unsubscribe();
}
}

View File

@@ -13,6 +13,6 @@
[auditEnabled]="auditHighlighting"
[blockConversion]="blockConversion"
></app-block-overview-tooltip>
<app-block-filters *ngIf="showFilters" [cssWidth]="cssWidth" (onFilterChanged)="setFilterFlags($event)"></app-block-filters>
<app-block-filters *ngIf="showFilters && filtersAvailable" [excludeFilters]="excludeFilters" [cssWidth]="cssWidth" (onFilterChanged)="setFilterFlags($event)"></app-block-filters>
</div>
</div>

View File

@@ -40,6 +40,7 @@ export class BlockOverviewGraphComponent implements AfterViewInit, OnDestroy, On
@Input() unavailable: boolean = false;
@Input() auditHighlighting: boolean = false;
@Input() showFilters: boolean = false;
@Input() excludeFilters: string[] = [];
@Input() filterFlags: bigint | null = null;
@Input() blockConversion: Price;
@Input() overrideColors: ((tx: TxView) => Color) | null = null;
@@ -71,6 +72,8 @@ export class BlockOverviewGraphComponent implements AfterViewInit, OnDestroy, On
searchText: string;
searchSubscription: Subscription;
filtersAvailable: boolean = true;
activeFilterFlags: bigint | null = null;
constructor(
readonly ngZone: NgZone,
@@ -110,16 +113,19 @@ export class BlockOverviewGraphComponent implements AfterViewInit, OnDestroy, On
if (changes.overrideColor && this.scene) {
this.scene.setColorFunction(this.overrideColors);
}
if ((changes.filterFlags || changes.showFilters) && this.scene) {
this.setFilterFlags(this.filterFlags);
if ((changes.filterFlags || changes.showFilters)) {
this.setFilterFlags();
}
}
setFilterFlags(flags: bigint | null): void {
if (flags != null) {
this.scene.setColorFunction(this.getFilterColorFunction(flags));
} else {
this.scene.setColorFunction(this.overrideColors);
setFilterFlags(flags?: bigint | null): void {
this.activeFilterFlags = this.filterFlags || flags || null;
if (this.scene) {
if (flags != null) {
this.scene.setColorFunction(this.getFilterColorFunction(flags));
} else {
this.scene.setColorFunction(this.overrideColors);
}
}
this.start();
}
@@ -150,6 +156,7 @@ export class BlockOverviewGraphComponent implements AfterViewInit, OnDestroy, On
// initialize the scene without any entry transition
setup(transactions: TransactionStripped[]): void {
this.filtersAvailable = transactions.reduce((flagSet, tx) => flagSet || tx.flags > 0, false);
if (this.scene) {
this.scene.setup(transactions);
this.readyNextFrame = true;
@@ -260,7 +267,7 @@ export class BlockOverviewGraphComponent implements AfterViewInit, OnDestroy, On
this.scene = new BlockScene({ width: this.displayWidth, height: this.displayHeight, resolution: this.resolution,
blockLimit: this.blockLimit, orientation: this.orientation, flip: this.flip, vertexArray: this.vertexArray,
highlighting: this.auditHighlighting, animationDuration: this.animationDuration, animationOffset: this.animationOffset,
colorFunction: this.overrideColors });
colorFunction: this.getColorFunction() });
this.start();
}
}
@@ -504,6 +511,16 @@ export class BlockOverviewGraphComponent implements AfterViewInit, OnDestroy, On
this.txHoverEvent.emit(hoverId);
}
getColorFunction(): ((tx: TxView) => Color) {
if (this.filterFlags) {
return this.getFilterColorFunction(this.filterFlags);
} else if (this.activeFilterFlags) {
return this.getFilterColorFunction(this.activeFilterFlags);
} else {
return this.overrideColors;
}
}
getFilterColorFunction(flags: bigint): ((tx: TxView) => Color) {
return (tx: TxView) => {
if ((tx.bigintFlags & flags) === flags) {

View File

@@ -59,7 +59,7 @@
<td [innerHTML]="'&lrm;' + (block.weight | wuBytes: 2)"></td>
</tr>
<tr *ngIf="auditAvailable">
<td><ng-container i18n="latest-blocks.health">Health</ng-container>&nbsp;<a class="info-link" [routerLink]="['/docs/faq' | relativeUrl ]" fragment="what-is-block-health"><fa-icon [icon]="['fas', 'info-circle']" [fixedWidth]="true"></fa-icon></a></td>
<td><ng-container i18n="latest-blocks.health">Health</ng-container><a class="info-link" [routerLink]="['/docs/faq' | relativeUrl ]" fragment="what-is-block-health"><fa-icon [icon]="['fas', 'info-circle']" [fixedWidth]="true"></fa-icon></a></td>
<td>
<span
class="health-badge badge"
@@ -115,6 +115,8 @@
[orientation]="'top'"
[flip]="false"
[blockConversion]="blockConversion"
[showFilters]="true"
[excludeFilters]="['replacement']"
(txClickEvent)="onTxClick($event)"
></app-block-overview-graph>
<ng-container *ngTemplateOutlet="emptyBlockInfo"></ng-container>
@@ -229,7 +231,8 @@
<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"
(txClickEvent)="onTxClick($event)" (txHoverEvent)="onTxHover($event)" [unavailable]="!isMobile && !showAudit"></app-block-overview-graph>
(txClickEvent)="onTxClick($event)" (txHoverEvent)="onTxHover($event)" [unavailable]="!isMobile && !showAudit"
[showFilters]="true" [excludeFilters]="['replacement']"></app-block-overview-graph>
<ng-container *ngIf="!isMobile || mode !== 'actual'; else emptyBlockInfo"></ng-container>
</div>
<ng-container *ngIf="network !== 'liquid'">
@@ -239,11 +242,12 @@
</ng-container>
</div>
<div class="col-sm" *ngIf="!isMobile">
<h3 class="block-subtitle actual" *ngIf="!isMobile"><ng-container i18n="block.actual-block">Actual Block</ng-container> <a class="info-link" [routerLink]="['/docs/faq' | relativeUrl ]" fragment="how-do-block-audits-work"><fa-icon [icon]="['fas', 'info-circle']" [fixedWidth]="true"></fa-icon></a></h3>
<h3 class="block-subtitle actual" *ngIf="!isMobile"><ng-container i18n="block.actual-block">Actual Block</ng-container><a class="info-link" [routerLink]="['/docs/faq' | relativeUrl ]" fragment="how-do-block-audits-work"><fa-icon [icon]="['fas', 'info-circle']" [fixedWidth]="true"></fa-icon></a></h3>
<div class="block-graph-wrapper">
<app-block-overview-graph #blockGraphActual [isLoading]="isLoadingOverview" [resolution]="86"
[blockLimit]="stateService.blockVSize" [orientation]="'top'" [flip]="false" [mirrorTxid]="hoverTx" mode="mined" [auditHighlighting]="showAudit"
(txClickEvent)="onTxClick($event)" (txHoverEvent)="onTxHover($event)" [unavailable]="isMobile && !showAudit"></app-block-overview-graph>
(txClickEvent)="onTxClick($event)" (txHoverEvent)="onTxHover($event)" [unavailable]="isMobile && !showAudit"
[showFilters]="true" [excludeFilters]="['replacement']"></app-block-overview-graph>
<ng-container *ngTemplateOutlet="emptyBlockInfo"></ng-container>
</div>
<ng-container *ngIf="network !== 'liquid'">

View File

@@ -53,7 +53,7 @@
<a class="nav-link" [routerLink]="['/' | relativeUrl]" (click)="collapse()"><fa-icon [icon]="['fas', 'tachometer-alt']" [fixedWidth]="true" i18n-title="master-page.dashboard" title="Dashboard"></fa-icon></a>
</li>
<li class="nav-item" routerLinkActive="active" [routerLinkActiveOptions]="{exact: true}" id="btn-home" *ngIf="stateService.env.ACCELERATOR">
<a class="nav-link" [routerLink]="['/acceleration' | relativeUrl]" (click)="collapse()"><fa-icon [icon]="['fas', 'rocket']" [fixedWidth]="true" i18n-title="master-page.acceleration-dashboard" title="Acceleration Dashboard"></fa-icon></a>
<a class="nav-link" [routerLink]="['/acceleration' | relativeUrl]" (click)="collapse()"><fa-icon [icon]="['fas', 'rocket']" [fixedWidth]="true" i18n-title="master-page.accelerator-dashboard" title="Accelerator Dashboard"></fa-icon></a>
</li>
<li class="nav-item" routerLinkActive="active" [routerLinkActiveOptions]="{exact: true}" id="btn-pools" *ngIf="stateService.env.MINING_DASHBOARD">
<a class="nav-link" [routerLink]="['/mining' | relativeUrl]" (click)="collapse()"><fa-icon [icon]="['fas', 'hammer']" [fixedWidth]="true" i18n-title="mining.mining-dashboard" title="Mining Dashboard"></fa-icon></a>

View File

@@ -1,15 +1,11 @@
:host ::ng-deep {
.dropdown-item {
white-space: nowrap;
width: calc(100% - 34px);
}
.dropdown-menu {
width: calc(100% - 34px);
}
@media (min-width: 768px) {
.dropdown-item {
width: 410px;
}
.dropdown-menu {
width: 410px;
}

View File

@@ -170,6 +170,7 @@ export class SearchFormComponent implements OnInit {
addresses: [],
nodes: [],
channels: [],
liquidAsset: [],
};
}
@@ -187,6 +188,7 @@ export class SearchFormComponent implements OnInit {
const matchesBlockHash = this.regexBlockhash.test(searchText);
let matchesAddress = !matchesTxId && this.regexAddress.test(searchText);
const otherNetworks = findOtherNetworks(searchText, this.network as any || 'mainnet', this.env);
const liquidAsset = this.assets ? (this.assets[searchText] || []) : [];
// Add B prefix to addresses in Bisq network
if (!matchesAddress && this.network === 'bisq' && getRegex('address', 'mainnet').test(searchText)) {
@@ -211,6 +213,7 @@ export class SearchFormComponent implements OnInit {
otherNetworks: otherNetworks,
nodes: lightningResults.nodes,
channels: lightningResults.channels,
liquidAsset: liquidAsset,
};
})
);
@@ -259,16 +262,16 @@ export class SearchFormComponent implements OnInit {
} else if (this.regexTransaction.test(searchText)) {
const matches = this.regexTransaction.exec(searchText);
if (this.network === 'liquid' || this.network === 'liquidtestnet') {
if (this.assets[matches[1]]) {
this.navigate('/assets/asset/', matches[1]);
if (this.assets[matches[0]]) {
this.navigate('/assets/asset/', matches[0]);
}
this.electrsApiService.getAsset$(matches[1])
this.electrsApiService.getAsset$(matches[0])
.subscribe(
() => { this.navigate('/assets/asset/', matches[1]); },
() => { this.navigate('/assets/asset/', matches[0]); },
() => {
this.electrsApiService.getBlock$(matches[1])
this.electrsApiService.getBlock$(matches[0])
.subscribe(
(block) => { this.navigate('/block/', matches[1], { state: { data: { block } } }); },
(block) => { this.navigate('/block/', matches[0], { state: { data: { block } } }); },
() => { this.navigate('/tx/', matches[0]); });
}
);

View File

@@ -1,6 +1,6 @@
<div class="dropdown-menu show" *ngIf="results" [hidden]="!results.hashQuickMatch && !results.otherNetworks.length && !results.addresses.length && !results.nodes.length && !results.channels.length">
<div class="dropdown-menu show" *ngIf="results" [hidden]="!results.hashQuickMatch && !results.otherNetworks.length && !results.addresses.length && !results.nodes.length && !results.channels.length && !results.liquidAsset.length">
<ng-template [ngIf]="results.blockHeight">
<div class="card-title" i18n="search.bitcoin-block-height">Bitcoin Block Height</div>
<div class="card-title" i18n="search.bitcoin-block-height">{{ networkName }} Block Height</div>
<button (click)="clickItem(0)" [class.active]="0 === activeIdx" type="button" role="option" class="dropdown-item">
<ng-container *ngTemplateOutlet="goTo; context: { $implicit: results.searchText }"></ng-container>
</button>
@@ -17,20 +17,20 @@
<ng-container *ngTemplateOutlet="goTo; context: { $implicit: results.searchText }"></ng-container>
</button>
</ng-template>
<ng-template [ngIf]="results.txId">
<div class="card-title" i18n="search.bitcoin-transaction">Bitcoin Transaction</div>
<ng-template [ngIf]="results.txId && !results.liquidAsset.length">
<div class="card-title" i18n="search.bitcoin-transaction">{{ networkName }} Transaction</div>
<button (click)="clickItem(0)" [class.active]="0 === activeIdx" type="button" role="option" class="dropdown-item">
<ng-container *ngTemplateOutlet="goTo; context: { $implicit: results.searchText | shortenString : 13 }"></ng-container>
</button>
</ng-template>
<ng-template [ngIf]="results.address">
<div class="card-title" i18n="search.bitcoin-address">Bitcoin Address</div>
<div class="card-title" i18n="search.bitcoin-address">{{ networkName }} Address</div>
<button (click)="clickItem(0)" [class.active]="0 === activeIdx" type="button" role="option" class="dropdown-item">
<ng-container *ngTemplateOutlet="goTo; context: { $implicit: results.searchText | shortenString : isMobile ? 20 : 30 }"></ng-container>
<ng-container *ngTemplateOutlet="goTo; context: { $implicit: results.searchText | shortenString : isMobile ? 17 : 30 }"></ng-container>
</button>
</ng-template>
<ng-template [ngIf]="results.blockHash">
<div class="card-title" i18n="search.bitcoin-block">Bitcoin Block</div>
<div class="card-title" i18n="search.bitcoin-block">{{ networkName }} Block</div>
<button (click)="clickItem(0)" [class.active]="0 === activeIdx" type="button" role="option" class="dropdown-item">
<ng-container *ngTemplateOutlet="goTo; context: { $implicit: results.searchText | shortenString : 13 }"></ng-container>
</button>
@@ -39,12 +39,12 @@
<div class="card-title danger" i18n="search.other-networks">Other Network Address</div>
<ng-template ngFor [ngForOf]="results.otherNetworks" let-otherNetwork let-i="index">
<button (click)="clickItem(results.hashQuickMatch + i)" [class.active]="(results.hashQuickMatch + i) === activeIdx" [class.inactive]="!otherNetwork.isNetworkAvailable" type="button" role="option" class="dropdown-item">
<ng-container *ngTemplateOutlet="goTo; context: { $implicit: otherNetwork.address| shortenString : isMobile ? 20 : 25 }"></ng-container>&nbsp;<b>({{ otherNetwork.network.charAt(0).toUpperCase() + otherNetwork.network.slice(1) }})</b>
<ng-container *ngTemplateOutlet="goTo; context: { $implicit: otherNetwork.address| shortenString : isMobile ? 12 : 20 }"></ng-container>&nbsp;<b>({{ otherNetwork.network.charAt(0).toUpperCase() + otherNetwork.network.slice(1) }})</b>
</button>
</ng-template>
</ng-template>
<ng-template [ngIf]="results.addresses.length">
<div class="card-title" i18n="search.bitcoin-addresses">Bitcoin Addresses</div>
<div class="card-title" i18n="search.bitcoin-addresses">{{ networkName }} Addresses</div>
<ng-template ngFor [ngForOf]="results.addresses" let-address let-i="index">
<button (click)="clickItem(results.hashQuickMatch + results.otherNetworks.length + i)" [class.active]="(results.hashQuickMatch + results.otherNetworks.length + i) === activeIdx" type="button" role="option" class="dropdown-item">
<ngb-highlight [result]="address | shortenString : isMobile ? 25 : 36" [term]="results.searchText"></ngb-highlight>
@@ -67,6 +67,12 @@
</button>
</ng-template>
</ng-template>
<ng-template [ngIf]="results.liquidAsset.length">
<div class="card-title" i18n="search.liquid-asset">Liquid Asset</div>
<button (click)="clickItem(0)" [class.active]="0 === activeIdx" type="button" role="option" class="dropdown-item">
<ng-container *ngTemplateOutlet="goTo; context: { $implicit: results.searchText | shortenString : 11 }"></ng-container>&nbsp;<b>({{ results.liquidAsset[1] }})</b>
</button>
</ng-template>
</div>
<ng-template #goTo let-x i18n="search.go-to">Go to "{{ x }}"</ng-template>

View File

@@ -10,15 +10,20 @@ export class SearchResultsComponent implements OnChanges {
@Input() results: any = {};
@Output() selectedResult = new EventEmitter();
isMobile = (window.innerWidth <= 767.98);
isMobile = (window.innerWidth <= 1150);
resultsFlattened = [];
activeIdx = 0;
focusFirst = true;
networkName = '';
constructor(
public stateService: StateService,
) { }
ngOnInit() {
this.networkName = this.stateService.network.charAt(0).toUpperCase() + this.stateService.network.slice(1);
}
ngOnChanges() {
this.activeIdx = 0;
if (this.results) {

View File

@@ -315,7 +315,7 @@
<p>Also, if you are using our Marks in a way described in the sections "Uses for Which We Are Granting a License," you must include the following trademark attribution at the foot of the webpage where you have used the Mark (or, if in a book, on the credits page), on any packaging or labeling, and on advertising or marketing materials:</p>
<p>"The Mempool Open Source Project&reg;, Mempool Accelerator&trade;, Mempool Enterprise&reg;, Mempool Liquidity&trade;, mempool.space&reg;, Be your own explorer&trade;, Explore the full Bitcoin ecosystem&trade;, Mempool Goggles&trade;, the mempool logo;, the mempool Square logo;, the mempool Blocks logo;, the mempool Blocks 3 | 2 logo;, the mempool.space Vertical Logo;, and the mempool.space Horizontal logo are either registered trademarks or trademarks of Mempool Space K.K in Japan, the United States, and/or other countries, and are used with permission. Mempool Space K.K. has no affiliation with and does not sponsor or endorse the information provided herein."</p>
<p>"The Mempool Open Source Project&reg;, Mempool Accelerator&trade;, Mempool Enterprise&reg;, Mempool Liquidity&trade;, mempool.space&reg;, Be your own explorer&trade;, Explore the full Bitcoin ecosystem&reg;, Mempool Goggles&trade;, the mempool logo;, the mempool Square logo;, the mempool Blocks logo;, the mempool Blocks 3 | 2 logo;, the mempool.space Vertical Logo;, and the mempool.space Horizontal logo are either registered trademarks or trademarks of Mempool Space K.K in Japan, the United States, and/or other countries, and are used with permission. Mempool Space K.K. has no affiliation with and does not sponsor or endorse the information provided herein."</p>
<li>What to Do When You See Abuse</li>
<br>

View File

@@ -299,7 +299,7 @@
<td [innerHTML]="'&lrm;' + (tx.weight / 4 | vbytes: 2)"></td>
</tr>
<tr *ngIf="adjustedVsize != null">
<td i18n="transaction.adjusted-vsize|Transaction Adjusted VSize">Adjusted vsize
<td><ng-container i18n="transaction.adjusted-vsize|Transaction Adjusted VSize">Adjusted vsize</ng-container>
<a class="info-link" [routerLink]="['/docs/faq/' | relativeUrl]" fragment="what-is-adjusted-vsize">
<fa-icon [icon]="['fas', 'info-circle']" [fixedWidth]="true"></fa-icon>
</a>
@@ -325,7 +325,7 @@
<td [innerHTML]="'&lrm;' + (tx.locktime | number)"></td>
</tr>
<tr *ngIf="sigops != null">
<td i18n="transaction.sigops|Transaction Sigops">Sigops
<td><ng-container i18n="transaction.sigops|Transaction Sigops">Sigops</ng-container>
<a class="info-link" [routerLink]="['/docs/faq/' | relativeUrl]" fragment="what-are-sigops">
<fa-icon [icon]="['fas', 'info-circle']" [fixedWidth]="true"></fa-icon>
</a>

View File

@@ -27,6 +27,8 @@ export interface WebsocketResponse {
fees?: Recommendedfees;
'track-tx'?: string;
'track-address'?: string;
'track-addresses'?: string[];
'track-scriptpubkeys'?: string[];
'track-asset'?: string;
'track-mempool-block'?: number;
'track-rbf'?: string;

View File

@@ -40,6 +40,7 @@ export class CacheService {
this.stateService.networkChanged$.subscribe((network) => {
this.network = network;
this.resetBlockCache();
this.txCache = {};
});
}

View File

@@ -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 Source Project.';
baseDescription = 'Explore the full Bitcoin ecosystem&reg; with The Mempool Open Source Project&reg;.';
canonicalLink: HTMLElement = document.getElementById('canonical');

View File

@@ -150,6 +150,8 @@ export class StateService {
searchFocus$: Subject<boolean> = new Subject<boolean>();
menuOpen$: BehaviorSubject<boolean> = new BehaviorSubject(false);
activeGoggles$: BehaviorSubject<string[]> = new BehaviorSubject([]);
constructor(
@Inject(PLATFORM_ID) private platformId: any,
@Inject(LOCALE_ID) private locale: string,

View File

@@ -9,7 +9,7 @@
</div>
<p class="explore-tagline-mobile">
<ng-container i18n="@@7deec1c1520f06170e1f8e8ddfbe4532312f638f">Explore the full Bitcoin ecosystem</ng-container>
<ng-template [ngIf]="locale.substr(0, 2) === 'en'"> &trade;</ng-template>
<ng-template [ngIf]="locale.substr(0, 2) === 'en'">&reg;</ng-template>
</p>
<div class="site-options language-selector d-flex justify-content-center align-items-center" [class]="{'services': isServicesPage}">
<div class="selector">
@@ -32,7 +32,7 @@
</a>
<p class="explore-tagline-desktop">
<ng-container i18n="@@7deec1c1520f06170e1f8e8ddfbe4532312f638f">Explore the full Bitcoin ecosystem</ng-container>
<ng-template [ngIf]="locale.substr(0, 2) === 'en'"> &trade;</ng-template>
<ng-template [ngIf]="locale.substr(0, 2) === 'en'">&reg;</ng-template>
</p>
</div>
</div>

View File

@@ -7,16 +7,16 @@
<script src="/resources/config.js"></script>
<base href="/">
<meta name="description" content="Explore the full Bitcoin ecosystem with The Mempool Open Project. See Bisq market prices, trading activity, and more.">
<meta name="description" content="Explore the full Bitcoin ecosystem with The Mempool Open Source Project&reg;. See Bisq market prices, trading activity, and more.">
<meta property="og:image" content="https://bisq.markets/resources/bisq/bisq-markets-preview.png" />
<meta property="og:image:type" content="image/jpeg" />
<meta property="og:description" content="Explore the full Bitcoin ecosystem with The Mempool Open Project. See Bisq market prices, trading activity, and more." />
<meta property="og:description" content="Explore the full Bitcoin ecosystem with The Mempool Open Source Project&reg;. See Bisq market prices, trading activity, and more." />
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:site" content="https://bisq.markets/">
<meta name="twitter:creator" content="@bisq_network">
<meta name="twitter:title" content="The Mempool Open Source Project®">
<meta name="twitter:description" content="Explore the full Bitcoin ecosystem with The Mempool Open Project. See Bisq market prices, trading activity, and more." />
<meta name="twitter:description" content="Explore the full Bitcoin ecosystem with The Mempool Open Source Project&reg;. See Bisq market prices, trading activity, and more." />
<meta name="twitter:image:src" content="https://bisq.markets/resources/bisq/bisq-markets-preview.png" />
<meta name="twitter:domain" content="bisq.markets">

View File

@@ -7,17 +7,17 @@
<script src="/resources/config.js"></script>
<base href="/">
<meta name="description" content="Explore the full Bitcoin ecosystem with The Mempool Open Project. See Liquid transactions & assets, get network info, and more.">
<meta name="description" content="Explore the full Bitcoin ecosystem with The Mempool Open Source Project&reg;. See Liquid transactions & assets, get network info, and more.">
<meta property="og:image" content="https://liquid.network/resources/liquid/liquid-network-preview.png" />
<meta property="og:image:type" content="image/png" />
<meta property="og:image:width" content="1000" />
<meta property="og:image:height" content="500" />
<meta property="og:description" content="Explore the full Bitcoin ecosystem with The Mempool Open Project. See Liquid transactions & assets, get network info, and more." />
<meta property="og:description" content="Explore the full Bitcoin ecosystem with The Mempool Open Source Project&reg;. See Liquid transactions & assets, get network info, and more." />
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:site" content="@mempool">
<meta name="twitter:creator" content="@mempool">
<meta name="twitter:title" content="The Mempool Open Source Project®">
<meta name="twitter:description" content="Explore the full Bitcoin ecosystem with The Mempool Open Project. See Liquid transactions & assets, get network info, and more." />
<meta name="twitter:description" content="Explore the full Bitcoin ecosystem with The Mempool Open Source Project&reg;. See Liquid transactions & assets, get network info, and more." />
<meta name="twitter:image:src" content="https://liquid.network/resources/liquid/liquid-network-preview.png" />
<meta name="twitter:domain" content="liquid.network">

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

View File

@@ -1661,6 +1661,10 @@
<context context-type="sourcefile">src/app/components/acceleration/acceleration-fees-graph/acceleration-fees-graph.component.html</context>
<context context-type="linenumber">6</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/acceleration/acceleration-fees-graph/acceleration-fees-graph.component.ts</context>
<context context-type="linenumber">69</context>
</context-group>
<note priority="1" from="description">accelerator.acceleration-fees</note>
</trans-unit>
<trans-unit id="bdb8bbb38e4ca3c73e19dc4167fbe4aec316f818" datatype="html">
@@ -1679,25 +1683,6 @@
</context-group>
<note priority="1" from="description">acceleration.total-bid-boost</note>
</trans-unit>
<trans-unit id="6c453b11fd7bd159ae30bc381f367bc736d86909" datatype="html">
<source>Acceleration Fees</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/acceleration/acceleration-fees-graph/acceleration-fees-graph.component.ts</context>
<context context-type="linenumber">69</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/block-fees-graph/block-fees-graph.component.html</context>
<context context-type="linenumber">6</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/block-fees-graph/block-fees-graph.component.ts</context>
<context context-type="linenumber">67</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/graphs/graphs.component.html</context>
<context context-type="linenumber">19</context>
</context-group>
</trans-unit>
<trans-unit id="4793828002882320882" datatype="html">
<source>At block: <x id="PH" equiv-text="data[0].data[2]"/></source>
<context-group purpose="location">
@@ -1777,8 +1762,8 @@
<note priority="1" from="description">BTC</note>
<note priority="1" from="meaning">shared.btc</note>
</trans-unit>
<trans-unit id="4e0fbac5ba55cf78f1accbaf9c871fb23b4b67d9" datatype="html">
<source>Success rate</source>
<trans-unit id="599dec71fe5c264d05012c7f64080d6347c1dc49" datatype="html">
<source>Success Rate</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/acceleration/acceleration-stats/acceleration-stats.component.html</context>
<context context-type="linenumber">20</context>
@@ -1941,12 +1926,16 @@
</context-group>
<note priority="1" from="description">accelerations.no-accelerations</note>
</trans-unit>
<trans-unit id="8adc22d4ccfd987ce3e2c1c86d0ccae17d281328" datatype="html">
<source>Active accelerations</source>
<trans-unit id="e51c45c636401f8bb3bd8cfd1ed5a3c9810c5fa8" datatype="html">
<source>Active Accelerations</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/acceleration/accelerator-dashboard/accelerator-dashboard.component.html</context>
<context context-type="linenumber">10</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/acceleration/accelerator-dashboard/accelerator-dashboard.component.html</context>
<context context-type="linenumber">72</context>
</context-group>
<note priority="1" from="description">accelerator.pending-accelerations</note>
</trans-unit>
<trans-unit id="41a9456b7e195dfc4df3d67b09940bda160882af" datatype="html">
@@ -1965,14 +1954,6 @@
</context-group>
<note priority="1" from="description">mining.144-blocks</note>
</trans-unit>
<trans-unit id="e51c45c636401f8bb3bd8cfd1ed5a3c9810c5fa8" datatype="html">
<source>Active Accelerations</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/acceleration/accelerator-dashboard/accelerator-dashboard.component.html</context>
<context context-type="linenumber">72</context>
</context-group>
<note priority="1" from="description">dashboard.recent-accelerations</note>
</trans-unit>
<trans-unit id="f0ae1220633178276128371f3965fb53d63581d4" datatype="html">
<source>Recent Accelerations</source>
<context-group purpose="location">
@@ -2020,8 +2001,8 @@
</context-group>
<note priority="1" from="description">accelerator.average-max-bid</note>
</trans-unit>
<trans-unit id="62be8da2e6a219a43d83a1887e55dc0ae1be155b" datatype="html">
<source>Total vsize</source>
<trans-unit id="16fedee43f919b6a0992f32aeec5d6938e8d6b76" datatype="html">
<source>Total Vsize</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/acceleration/pending-stats/pending-stats.component.html</context>
<context context-type="linenumber">20</context>
@@ -2563,6 +2544,22 @@
<context context-type="linenumber">73</context>
</context-group>
</trans-unit>
<trans-unit id="6c453b11fd7bd159ae30bc381f367bc736d86909" datatype="html">
<source>Block Fees</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/block-fees-graph/block-fees-graph.component.html</context>
<context context-type="linenumber">6</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/block-fees-graph/block-fees-graph.component.ts</context>
<context context-type="linenumber">67</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/graphs/graphs.component.html</context>
<context context-type="linenumber">19</context>
</context-group>
<note priority="1" from="description">mining.block-fees</note>
</trans-unit>
<trans-unit id="meta.description.bitcoin.graphs.block-fees" datatype="html">
<source>See the average mining fees earned per Bitcoin block visualized in BTC and USD over time.</source>
<context-group purpose="location">
@@ -4268,13 +4265,13 @@
</context-group>
<note priority="1" from="description">master-page.graphs</note>
</trans-unit>
<trans-unit id="2efef6dfa1c2d2d8fa05b337eccf3e0006af1e94" datatype="html">
<source>Acceleration Dashboard</source>
<trans-unit id="6b867dc61c6a92f3229f1950f9f2d414790cce95" datatype="html">
<source>Accelerator Dashboard</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/master-page/master-page.component.html</context>
<context context-type="linenumber">56</context>
</context-group>
<note priority="1" from="description">master-page.acceleration-dashboard</note>
<note priority="1" from="description">master-page.accelerator-dashboard</note>
</trans-unit>
<trans-unit id="142e923d3b04186ac6ba23387265d22a2fa404e0" datatype="html">
<source>Lightning Explorer</source>
@@ -5547,11 +5544,11 @@
</context-group>
<note priority="1" from="description">show-diagram</note>
</trans-unit>
<trans-unit id="9ad256cfb48e88f5bc56243641c992d53461f482" datatype="html">
<source>Adjusted vsize <x id="START_LINK" ctype="x-a" equiv-text="&lt;a class=&quot;info-link&quot; [routerLink]=&quot;[&apos;/docs/faq/&apos; | relativeUrl]&quot; fragment=&quot;what-is-adjusted-vsize&quot;&gt;"/><x id="START_TAG_FA_ICON" ctype="x-fa_icon" equiv-text="&lt;fa-icon [icon]=&quot;[&apos;fas&apos;, &apos;info-circle&apos;]&quot; [fixedWidth]=&quot;true&quot;&gt;"/><x id="CLOSE_TAG_FA_ICON" ctype="x-fa_icon"/><x id="CLOSE_LINK" ctype="x-a" equiv-text="&lt;/a&gt;"/></source>
<trans-unit id="a8a4dd861f790141e19f773153cf42b5d0b0e6b6" datatype="html">
<source>Adjusted vsize</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/transaction/transaction.component.html</context>
<context context-type="linenumber">302,306</context>
<context context-type="linenumber">302</context>
</context-group>
<note priority="1" from="description">Transaction Adjusted VSize</note>
<note priority="1" from="meaning">transaction.adjusted-vsize</note>
@@ -5564,11 +5561,11 @@
</context-group>
<note priority="1" from="description">transaction.locktime</note>
</trans-unit>
<trans-unit id="c93f5659ea1b4a8c59a8e4710cbcdb62b37206b0" datatype="html">
<source>Sigops <x id="START_LINK" ctype="x-a" equiv-text="&lt;a class=&quot;info-link&quot; [routerLink]=&quot;[&apos;/docs/faq/&apos; | relativeUrl]&quot; fragment=&quot;what-are-sigops&quot;&gt;"/><x id="START_TAG_FA_ICON" ctype="x-fa_icon" equiv-text="&lt;fa-icon [icon]=&quot;[&apos;fas&apos;, &apos;info-circle&apos;]&quot; [fixedWidth]=&quot;true&quot;&gt;"/><x id="CLOSE_TAG_FA_ICON" ctype="x-fa_icon"/><x id="CLOSE_LINK" ctype="x-a" equiv-text="&lt;/a&gt;"/></source>
<trans-unit id="3dd65e8fa7035988a691aadcb583862c2a9e336a" datatype="html">
<source>Sigops</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/transaction/transaction.component.html</context>
<context context-type="linenumber">328,332</context>
<context context-type="linenumber">328</context>
</context-group>
<note priority="1" from="description">Transaction Sigops</note>
<note priority="1" from="meaning">transaction.sigops</note>

File diff suppressed because it is too large Load Diff

View File

@@ -1194,4 +1194,5 @@ app-global-footer {
.info-link fa-icon {
color: rgba(255, 255, 255, 0.4);
margin-left: 5px;
}

View File

@@ -22,7 +22,7 @@ var PATH;
if (process.argv[2]) {
PATH = process.argv[2];
PATH += PATH.endsWith("/") ? "" : "/"
PATH = path.normalize(PATH);
PATH = path.resolve(path.normalize(PATH));
console.log(`[sync-assets] using PATH ${PATH}`);
if (!fs.existsSync(PATH)){
console.log(`${LOG_TAG} ${PATH} does not exist, creating`);
@@ -110,7 +110,7 @@ function downloadMiningPoolLogos$() {
}
let downloadedCount = 0;
for (const poolLogo of poolLogos) {
const filePath = PATH + `mining-pools/${poolLogo.name}`;
const filePath = `${PATH}/mining-pools/${poolLogo.name}`;
if (fs.existsSync(filePath)) {
const localHash = getLocalHash(filePath);
if (verbose) {
@@ -124,7 +124,7 @@ function downloadMiningPoolLogos$() {
}
} else {
console.log(`${LOG_TAG} ${poolLogo.name} is missing, downloading...`);
const miningPoolsDir = PATH + `mining-pools/`;
const miningPoolsDir = `${PATH}/mining-pools/`;
if (!fs.existsSync(miningPoolsDir)){
fs.mkdirSync(miningPoolsDir, { recursive: true });
}
@@ -179,7 +179,7 @@ function downloadPromoVideoSubtiles$() {
}
let downloadedCount = 0;
for (const language of videoLanguages) {
const filePath = PATH + `promo-video/${language.name}`;
const filePath = `${PATH}/promo-video/${language.name}`;
if (fs.existsSync(filePath)) {
if (verbose) {
console.log(`${LOG_TAG} ${language.name} remote promo video hash ${language.sha}`);
@@ -193,7 +193,7 @@ function downloadPromoVideoSubtiles$() {
}
} else {
console.log(`${LOG_TAG} ${language.name} is missing, downloading`);
const promoVideosDir = PATH + `promo-video/`;
const promoVideosDir = `${PATH}/promo-video/`;
if (!fs.existsSync(promoVideosDir)){
fs.mkdirSync(promoVideosDir, { recursive: true });
}
@@ -250,7 +250,7 @@ function downloadPromoVideo$() {
if (item.name !== 'promo.mp4') {
continue;
}
const filePath = PATH + `promo-video/mempool-promo.mp4`;
const filePath = `${PATH}/promo-video/mempool-promo.mp4`;
if (fs.existsSync(filePath)) {
const localHash = getLocalHash(filePath);
@@ -288,16 +288,16 @@ if (configContent.BASE_MODULE && configContent.BASE_MODULE === 'liquid') {
const testnetAssetsMinimalJsonUrl = 'https://raw.githubusercontent.com/Blockstream/asset_registry_testnet_db/master/index.minimal.json';
console.log(`${LOG_TAG} Downloading assets`);
download(PATH + 'assets.json', assetsJsonUrl);
download(`${PATH}/assets.json`, assetsJsonUrl);
console.log(`${LOG_TAG} Downloading assets minimal`);
download(PATH + 'assets.minimal.json', assetsMinimalJsonUrl);
download(`${PATH}/assets.minimal.json`, assetsMinimalJsonUrl);
console.log(`${LOG_TAG} Downloading testnet assets`);
download(PATH + 'assets-testnet.json', testnetAssetsJsonUrl);
download(`${PATH}/assets-testnet.json`, testnetAssetsJsonUrl);
console.log(`${LOG_TAG} Downloading testnet assets minimal`);
download(PATH + 'assets-testnet.minimal.json', testnetAssetsMinimalJsonUrl);
download(`${PATH}/assets-testnet.minimal.json`, testnetAssetsMinimalJsonUrl);
} else {
if (verbose) {
console.log(`${LOG_TAG} BASE_MODULE is not set to Liquid (${configContent.BASE_MODULE}), skipping downloading assets`);