Merge branch 'master' into hunicus/bird-x

This commit is contained in:
hunicus
2024-05-13 05:25:54 +09:00
committed by GitHub
110 changed files with 1834 additions and 659 deletions

View File

@@ -168,6 +168,10 @@ let routes: Routes = [
path: 'testnet',
loadChildren: () => import('./previews.module').then(m => m.PreviewsModule)
},
{
path: 'testnet4',
loadChildren: () => import('./previews.module').then(m => m.PreviewsModule)
},
{
path: 'signet',
loadChildren: () => import('./previews.module').then(m => m.PreviewsModule)

View File

@@ -11,7 +11,8 @@
.main-title {
position: relative;
color: #ffffff91;
color: var(--fg);
opacity: var(--opacity);
margin-top: -13px;
font-size: 10px;
text-transform: uppercase;

View File

@@ -60,7 +60,8 @@
.main-title {
position: relative;
color: #ffffff91;
color: var(--fg);
opacity: var(--opacity);
margin-top: -13px;
font-size: 10px;
text-transform: uppercase;

View File

@@ -148,7 +148,7 @@ export class AcceleratorDashboardComponent implements OnInit, OnDestroy {
} else {
const rate = tx.fee / tx.vsize; // color by simple single-tx fee rate
const feeLevelIndex = feeLevels.findIndex((feeLvl) => Math.max(1, rate) < feeLvl) - 1;
return this.theme.theme === 'contrast' ? contrastColors[feeLevelIndex] || contrastColors[contrastColors.length - 1] : normalColors[feeLevelIndex] || normalColors[normalColors.length - 1];
return this.theme.theme === 'contrast' || this.theme.theme === 'bukele' ? contrastColors[feeLevelIndex] || contrastColors[contrastColors.length - 1] : normalColors[feeLevelIndex] || normalColors[normalColors.length - 1];
}
}

View File

@@ -11,7 +11,8 @@
.main-title {
position: relative;
color: #ffffff91;
color: var(--fg);
opacity: var(--opacity);
margin-top: -13px;
font-size: 10px;
text-transform: uppercase;

View File

@@ -73,7 +73,7 @@ export class AddressGraphComponent implements OnChanges, OnDestroy {
if (!this.address || !this.stats) {
return;
}
if (changes.address || changes.isPubkey || changes.addressSummary$) {
if (changes.address || changes.isPubkey || changes.addressSummary$ || changes.stats) {
if (this.subscription) {
this.subscription.unsubscribe();
}
@@ -248,7 +248,9 @@ export class AddressGraphComponent implements OnChanges, OnDestroy {
}
ngOnDestroy(): void {
this.subscription.unsubscribe();
if (this.subscription) {
this.subscription.unsubscribe();
}
}
isMobile() {

View File

@@ -3,7 +3,7 @@
}
.qr-wrapper {
background-color: var(--fg);
background-color: #fff;
padding: 10px;
padding-bottom: 5px;
display: inline-block;

View File

@@ -1,5 +1,5 @@
.qr-wrapper {
background-color: var(--fg);
background-color: #fff;
padding: 10px;
padding-bottom: 5px;
display: inline-block;

View File

@@ -1,5 +1,5 @@
.qr-wrapper {
background-color: var(--fg);
background-color: #fff;
padding: 10px;
padding-bottom: 5px;
display: inline-block;

View File

@@ -57,8 +57,9 @@ export class BalanceWidgetComponent implements OnInit, OnChanges {
calculateStats(summary: AddressTxSummary[]): void {
let weekTotal = 0;
let monthTotal = 0;
const weekAgo = (Date.now() / 1000) - (60 * 60 * 24 * 7);
const monthAgo = (Date.now() / 1000) - (60 * 60 * 24 * 30);
const weekAgo = (new Date(new Date().setHours(0, 0, 0, 0) - (7 * 24 * 60 * 60 * 1000)).getTime()) / 1000;
const monthAgo = (new Date(new Date().setHours(0, 0, 0, 0) - (30 * 24 * 60 * 60 * 1000)).getTime()) / 1000;
for (let i = 0; i < summary.length && summary[i].time >= monthAgo; i++) {
monthTotal += summary[i].value;
if (summary[i].time >= weekAgo) {

View File

@@ -11,7 +11,8 @@
.main-title {
position: relative;
color: #ffffff91;
color: var(--fg);
opacity: var(--opacity);
margin-top: -13px;
font-size: 10px;
text-transform: uppercase;

View File

@@ -11,7 +11,8 @@
.main-title {
position: relative;
color: #ffffff91;
color: var(--fg);
opacity: var(--opacity);
margin-top: -13px;
font-size: 10px;
text-transform: uppercase;

View File

@@ -11,7 +11,8 @@
.main-title {
position: relative;
color: #ffffff91;
color: var(--fg);
opacity: var(--opacity);
margin-top: -13px;
font-size: 10px;
text-transform: uppercase;

View File

@@ -651,13 +651,13 @@ export class BlockOverviewGraphComponent implements AfterViewInit, OnDestroy, On
getFilterColorFunction(flags: bigint, gradient: 'fee' | 'age'): ((tx: TxView) => Color) {
return (tx: TxView) => {
if ((this.filterMode === 'and' && (tx.bigintFlags & flags) === flags) || (this.filterMode === 'or' && (flags === 0n || (tx.bigintFlags & flags) > 0n))) {
if (this.themeService.theme !== 'contrast') {
if (this.themeService.theme !== 'contrast' && this.themeService.theme !== 'bukele') {
return (gradient === 'age') ? ageColorFunction(tx, defaultColors.fee, defaultAuditColors, this.relativeTime || (Date.now() / 1000)) : defaultColorFunction(tx, defaultColors.fee, defaultAuditColors, this.relativeTime || (Date.now() / 1000));
} else {
return (gradient === 'age') ? ageColorFunction(tx, contrastColors.fee, contrastAuditColors, this.relativeTime || (Date.now() / 1000)) : contrastColorFunction(tx, contrastColors.fee, contrastAuditColors, this.relativeTime || (Date.now() / 1000));
}
} else {
if (this.themeService.theme !== 'contrast') {
if (this.themeService.theme !== 'contrast' && this.themeService.theme !== 'bukele') {
return (gradient === 'age') ? { r: 1, g: 1, b: 1, a: 0.05 } : defaultColorFunction(
tx,
defaultColors.unmatchedfee,

View File

@@ -69,7 +69,7 @@ export default class BlockScene {
}
setColorFunction(colorFunction: ((tx: TxView) => Color) | null): void {
this.theme.theme === 'contrast' ? this.getColor = colorFunction || contrastColorFunction : this.getColor = colorFunction || defaultColorFunction;
this.theme.theme === 'contrast' || this.theme.theme === 'bukele' ? this.getColor = colorFunction || contrastColorFunction : this.getColor = colorFunction || defaultColorFunction;
this.updateAllColors();
}
@@ -246,7 +246,7 @@ export default class BlockScene {
this.flip = flip;
this.vertexArray = vertexArray;
this.highlightingEnabled = highlighting;
theme.theme === 'contrast' ? this.getColor = colorFunction || contrastColorFunction : this.getColor = colorFunction || defaultColorFunction;
theme.theme === 'contrast' || theme.theme === 'bukele' ? this.getColor = colorFunction || contrastColorFunction : this.getColor = colorFunction || defaultColorFunction;
this.theme = theme;
this.scene = {

View File

@@ -177,7 +177,7 @@ export function ageColorFunction(
return auditColors.accelerated;
}
const color = theme !== 'contrast' ? defaultColorFunction(tx, colors, auditColors, relativeTime) : contrastColorFunction(tx, colors, auditColors, relativeTime);
const color = theme !== 'contrast' && theme !== 'bukele' ? defaultColorFunction(tx, colors, auditColors, relativeTime) : contrastColorFunction(tx, colors, auditColors, relativeTime);
const ageLevel = (!tx.time ? 0 : (0.8 * Math.tanh((1 / 15) * Math.log2((Math.max(1, 0.6 * ((relativeTime - tx.time) - 60)))))));
return {

View File

@@ -1,6 +1,6 @@
.block-overview-tooltip {
position: absolute;
background: rgba(#11131f, 0.95);
background: color-mix(in srgb, var(--active-bg) 95%, transparent);
border-radius: 4px;
box-shadow: 1px 1px 10px rgba(0,0,0,0.5);
color: var(--tooltip-grey);
@@ -30,7 +30,7 @@ th, td {
}
.badge.badge-accelerated {
background-color: var(--tertiary);
background-color: #653b9c;
box-shadow: #ad7de57f 0px 0px 12px -2px;
color: white;
animation: acceleratePulse 1s infinite;
@@ -71,7 +71,7 @@ th, td {
}
@keyframes acceleratePulse {
0% { background-color: var(--tertiary); box-shadow: #ad7de57f 0px 0px 12px -2px; }
0% { background-color: #653b9c; box-shadow: #ad7de57f 0px 0px 12px -2px; }
50% { background-color: #8457bb; box-shadow: #ad7de5 0px 0px 18px -2px;}
100% { background-color: var(--tertiary); box-shadow: #ad7de57f 0px 0px 12px -2px; }
100% { background-color: #653b9c; box-shadow: #ad7de57f 0px 0px 12px -2px; }
}

View File

@@ -11,7 +11,8 @@
.main-title {
position: relative;
color: #ffffff91;
color: var(--fg);
opacity: var(--opacity);
margin-top: -13px;
font-size: 10px;
text-transform: uppercase;

View File

@@ -11,7 +11,8 @@
.main-title {
position: relative;
color: #ffffff91;
color: var(--fg);
opacity: var(--opacity);
margin-top: -13px;
font-size: 10px;
text-transform: uppercase;

View File

@@ -63,7 +63,7 @@
.fee-span {
font-size: 11px;
margin-bottom: 5px;
color: #fff000;
color: var(--yellow);
}
.transaction-count {
@@ -130,7 +130,7 @@
height: 0;
border-left: calc(var(--block-size) * 0.3) solid transparent;
border-right: calc(var(--block-size) * 0.3) solid transparent;
border-bottom: calc(var(--block-size) * 0.3) solid #FFF;
border-bottom: calc(var(--block-size) * 0.3) solid var(--fg);
}
.flashing {

View File

@@ -350,7 +350,7 @@ export class BlockchainBlocksComponent implements OnInit, OnChanges, OnDestroy {
return {
left: addLeft + this.blockOffset * index + 'px',
background: `repeating-linear-gradient(
#2d3348,
var(--secondary),
var(--secondary) ${greenBackgroundHeight}%,
${this.gradientColors[this.network][0]} ${Math.max(greenBackgroundHeight, 0)}%,
${this.gradientColors[this.network][1]} 100%
@@ -362,7 +362,7 @@ export class BlockchainBlocksComponent implements OnInit, OnChanges, OnDestroy {
convertStyleForLoadingBlock(style) {
return {
...style,
background: "#2d3348",
background: "var(--secondary)",
};
}
@@ -371,7 +371,7 @@ export class BlockchainBlocksComponent implements OnInit, OnChanges, OnDestroy {
return {
left: addLeft + (this.blockOffset * index) + 'px',
background: "#2d3348",
background: "var(--secondary)",
};
}

View File

@@ -54,7 +54,7 @@
}
.time-toggle {
color: white;
color: var(--fg);
font-size: 0.8rem;
position: absolute;
bottom: -1.8em;
@@ -68,7 +68,7 @@
}
.block-display-toggle {
color: white;
color: var(--fg);
font-size: 0.8rem;
position: absolute;
bottom: 15.8em;

View File

@@ -32,12 +32,12 @@ export class ClockComponent implements OnInit {
limitHeight: number;
gradientColors = {
'': ['#9339f4', '#105fb0'],
liquid: ['#116761', '#183550'],
'liquidtestnet': ['#494a4a', '#272e46'],
testnet: ['#1d486f', '#183550'],
testnet4: ['#1d486f', '#183550'],
signet: ['#6f1d5d', '#471850'],
'': ['var(--mainnet-alt)', 'var(--primary)'],
liquid: ['var(--liquid)', 'var(--testnet-alt)'],
'liquidtestnet': ['var(--liquidtestnet)', 'var(--liquidtestnet-alt)'],
testnet: ['var(--testnet)', 'var(--testnet-alt)'],
testnet4: ['var(--testnet)', 'var(--testnet-alt)'],
signet: ['var(--signet)', 'var(--signet-alt)'],
};
constructor(
@@ -100,8 +100,8 @@ export class ClockComponent implements OnInit {
return {
background: `repeating-linear-gradient(
#2d3348,
#2d3348 ${greenBackgroundHeight}%,
var(--secondary),
var(--secondary) ${greenBackgroundHeight}%,
${this.gradientColors[''][0]} ${Math.max(greenBackgroundHeight, 0)}%,
${this.gradientColors[''][1]} 100%
)`,

View File

@@ -4,7 +4,7 @@
@for (widget of widgets; track widget.component) {
@switch (widget.component) {
@case ('fees') {
<div class="col card-wrapper">
<div class="col card-wrapper" [style.order]="isMobile && widget.mobileOrder || 8">
<div class="main-title" i18n="fees-box.transaction-fees">Transaction Fees</div>
<div class="card">
<div class="card-body less-padding">
@@ -14,12 +14,12 @@
</div>
}
@case ('difficulty') {
<div class="col">
<div class="col" [style.order]="isMobile && widget.mobileOrder || 8">
<app-difficulty></app-difficulty>
</div>
}
@case ('goggles') {
<div class="col">
<div class="col" [style.order]="isMobile && widget.mobileOrder || 8">
<div class="card graph-card">
<div class="card-body pl-lg-3 pr-lg-3 pl-2 pr-2">
<a class="title-link mb-0" style="margin-top: -2px" href="" [routerLink]="['/mempool-block/0' | relativeUrl]">
@@ -48,7 +48,7 @@
</div>
}
@case ('incoming') {
<div class="col">
<div class="col" [style.order]="isMobile && widget.mobileOrder || 8">
<div class="card graph-card">
<div class="card-body">
<ng-container *ngTemplateOutlet="mempoolTable; context: { $implicit: mempoolInfoData }"></ng-container>
@@ -93,7 +93,7 @@
</ng-template>
}
@case ('replacements') {
<div class="col" style="max-height: 410px">
<div class="col" style="max-height: 410px" [style.order]="isMobile && widget.mobileOrder || 8">
<div class="card">
<div class="card-body">
<a class="title-link" href="" [routerLink]="['/rbf' | relativeUrl]">
@@ -140,7 +140,7 @@
</ng-template>
}
@case ('blocks') {
<div class="col" style="max-height: 410px">
<div class="col" style="max-height: 410px" [style.order]="isMobile && widget.mobileOrder || 8">
<div class="card">
<div class="card-body">
<a class="title-link" href="" [routerLink]="['/blocks' | relativeUrl]">
@@ -184,7 +184,7 @@
</ng-template>
}
@case ('transactions') {
<div class="col" style="max-height: 410px">
<div class="col" style="max-height: 410px" [style.order]="isMobile && widget.mobileOrder || 8">
<div class="card">
<div class="card-body">
<h5 class="card-title" i18n="dashboard.recent-transactions">Recent Transactions</h5>
@@ -224,13 +224,13 @@
</ng-template>
}
@case ('balance') {
<div class="col card-wrapper">
<div class="col card-wrapper" [style.order]="isMobile && widget.mobileOrder || 8">
<div class="main-title" i18n="dashboard.treasury">Treasury</div>
<app-balance-widget [address]="widget.props.address" [addressSummary$]="addressSummary$" [addressInfo]="address"></app-balance-widget>
</div>
}
@case ('address') {
<div class="col" style="max-height: 410px">
<div class="col" style="max-height: 410px" [style.order]="isMobile && widget.mobileOrder || 8">
<div class="card graph-card">
<div class="card-body">
<a class="title-link" href="" [routerLink]="[('/address/' + widget.props.address) | relativeUrl]">
@@ -238,13 +238,13 @@
<span>&nbsp;</span>
<fa-icon [icon]="['fas', 'external-link-alt']" [fixedWidth]="true" style="vertical-align: text-top; font-size: 13px; color: var(--title-fg)"></fa-icon>
</a>
<app-address-graph [address]="widget.props.address" [addressSummary$]="addressSummary$" [period]="widget.props.period || 'all'" [stats]="address?.chain_stats" [widget]="true" [height]="graphHeight"></app-address-graph>
<app-address-graph [address]="widget.props.address" [addressSummary$]="addressSummary$" [period]="widget.props.period || 'all'" [stats]="address ? address.chain_stats : null" [widget]="true" [height]="graphHeight"></app-address-graph>
</div>
</div>
</div>
}
@case ('addressTransactions') {
<div class="col" style="max-height: 410px">
<div class="col" style="max-height: 410px" [style.order]="isMobile && widget.mobileOrder || 8">
<div class="card">
<div class="card-body">
<a class="title-link" href="" [routerLink]="[('/address/' + widget.props.address) | relativeUrl]">
@@ -257,6 +257,22 @@
</div>
</div>
}
@case ('twitter') {
<div class="col" style="min-height:410px" [style.order]="isMobile && widget.mobileOrder || 8">
<div class="card graph-card">
<div class="card-body pl-lg-3 pr-lg-3 pl-2 pr-2 d-flex flex-column">
<a class="title-link" [href]="'https://x.com/' + widget.props?.handle" target="_blank">
<h5 class="card-title d-inline" i18n="dashboard.x-timeline">X Timeline</h5>
<span>&nbsp;</span>
<fa-icon [icon]="['fas', 'external-link-alt']" [fixedWidth]="true" style="vertical-align: text-top; font-size: 13px; color: var(--title-fg)"></fa-icon>
</a>
@defer {
<app-twitter-widget [handle]="widget.props?.handle" style="flex-grow: 1"></app-twitter-widget>
}
</div>
</div>
</div>
}
}
}
</div>

View File

@@ -1,4 +1,4 @@
import { AfterViewInit, ChangeDetectionStrategy, Component, HostListener, Inject, OnDestroy, OnInit, PLATFORM_ID } from '@angular/core';
import { AfterViewInit, ChangeDetectionStrategy, ChangeDetectorRef, Component, HostListener, Inject, OnDestroy, OnInit, PLATFORM_ID } from '@angular/core';
import { combineLatest, merge, Observable, of, Subject, Subscription } from 'rxjs';
import { catchError, filter, map, scan, share, shareReplay, startWith, switchMap, tap } from 'rxjs/operators';
import { BlockExtended, OptimizedMempoolStats, TransactionStripped } from '../../interfaces/node-api.interface';
@@ -57,6 +57,7 @@ export class CustomDashboardComponent implements OnInit, OnDestroy, AfterViewIni
incomingGraphHeight: number = 300;
graphHeight: number = 300;
webGlEnabled = true;
isMobile: boolean = window.innerWidth <= 767.98;
widgets;
@@ -85,6 +86,7 @@ export class CustomDashboardComponent implements OnInit, OnDestroy, AfterViewIni
private electrsApiService: ElectrsApiService,
private websocketService: WebsocketService,
private seoService: SeoService,
private cd: ChangeDetectorRef,
@Inject(PLATFORM_ID) private platformId: Object,
) {
this.webGlEnabled = this.stateService.isBrowser && detectWebGL();
@@ -230,8 +232,10 @@ export class CustomDashboardComponent implements OnInit, OnDestroy, AfterViewIni
this.stateService.live2Chart$
.pipe(
scan((acc, stats) => {
const now = Date.now() / 1000;
const start = now - (2 * 60 * 60);
acc.unshift(stats);
acc = acc.slice(0, 120);
acc = acc.filter(p => p.added >= start);
return acc;
}, (mempoolStats || []))
),
@@ -283,8 +287,8 @@ export class CustomDashboardComponent implements OnInit, OnDestroy, AfterViewIni
startAddressSubscription(): void {
if (this.stateService.env.customize && this.stateService.env.customize.dashboard.widgets.some(w => w.props?.address)) {
const address = this.stateService.env.customize.dashboard.widgets.find(w => w.props?.address).props.address;
const addressString = (/^[A-Z]{2,5}1[AC-HJ-NP-Z02-9]{8,100}|04[a-fA-F0-9]{128}|(02|03)[a-fA-F0-9]{64}$/.test(address)) ? address.toLowerCase() : address;
let addressString = this.stateService.env.customize.dashboard.widgets.find(w => w.props?.address).props.address;
addressString = (/^[A-Z]{2,5}1[AC-HJ-NP-Z02-9]{8,100}|04[a-fA-F0-9]{128}|(02|03)[a-fA-F0-9]{64}$/.test(addressString)) ? addressString.toLowerCase() : addressString;
this.addressSubscription = (
addressString.match(/04[a-fA-F0-9]{128}|(02|03)[a-fA-F0-9]{64}/)
@@ -299,6 +303,7 @@ export class CustomDashboardComponent implements OnInit, OnDestroy, AfterViewIni
).subscribe((address: Address) => {
this.websocketService.startTrackAddress(address.address);
this.address = address;
this.cd.markForCheck();
});
this.addressSummary$ = (
@@ -368,5 +373,6 @@ export class CustomDashboardComponent implements OnInit, OnDestroy, AfterViewIni
this.goggleResolution = 86;
this.graphHeight = 310;
}
this.isMobile = window.innerWidth <= 767.98;
}
}

View File

@@ -119,7 +119,8 @@
.main-title {
position: relative;
color: #ffffff91;
color: var(--fg);
opacity: var(--opacity);
margin-top: -13px;
font-size: 10px;
text-transform: uppercase;

View File

@@ -1,9 +1,9 @@
.difficulty-tooltip {
position: fixed;
background: rgba(#11131f, 0.95);
background: color-mix(in srgb, var(--active-bg) 95%, transparent);
border-radius: 4px;
box-shadow: 1px 1px 10px rgba(0,0,0,0.5);
color: #b1b1b1;
color: var(--tooltip-grey);
padding: 10px 15px;
text-align: left;
pointer-events: none;

View File

@@ -15,8 +15,8 @@
<svg #epochSvg class="epoch-blocks" height="22px" width="100%" viewBox="0 0 224 9" shape-rendering="crispEdges" preserveAspectRatio="none">
<defs>
<linearGradient id="diff-gradient" x1="0%" y1="0%" x2="100%" y2="0%" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#105fb0" />
<stop offset="100%" stop-color="#9339f4" />
<stop offset="0%" stop-color="var(--primary)" />
<stop offset="100%" stop-color="var(--mainnet-alt)" />
</linearGradient>
<linearGradient id="diff-hover-gradient" x1="0%" y1="0%" x2="100%" y2="0%" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#2486eb" />

View File

@@ -128,7 +128,8 @@
.main-title {
position: relative;
color: #ffffff91;
color: var(--fg);
opacity: var(--opacity);
margin-top: -13px;
font-size: 10px;
text-transform: uppercase;
@@ -223,7 +224,7 @@
height: 100%;
}
.background {
background: linear-gradient(to right, var(--primary), #9339f4);
background: linear-gradient(to right, var(--primary), var(--mainnet-alt));
left: 0;
right: 0;
}

View File

@@ -79,7 +79,7 @@
display: flex;
flex-direction: row;
transition: background-color 1s;
color: var(--color-fg);
color: #fff;
&.priority {
@media (767px < width < 992px), (width < 576px) {
width: 100%;

View File

@@ -16,8 +16,8 @@ export class FeesBoxComponent implements OnInit, OnDestroy {
isLoading$: Observable<boolean>;
recommendedFees$: Observable<Recommendedfees>;
themeSubscription: Subscription;
gradient = 'linear-gradient(to right, #2e324e, #2e324e)';
noPriority = '#2e324e';
gradient = 'linear-gradient(to right, var(--skeleton-bg), var(--skeleton-bg))';
noPriority = 'var(--skeleton-bg)';
fees: Recommendedfees;
constructor(

View File

@@ -11,7 +11,8 @@
.main-title {
position: relative;
color: #ffffff91;
color: var(--fg);
opacity: var(--opacity);
margin-top: -13px;
font-size: 10px;
text-transform: uppercase;

View File

@@ -11,7 +11,8 @@
.main-title {
position: relative;
color: #ffffff91;
color: var(--fg);
opacity: var(--opacity);
margin-top: -13px;
font-size: 10px;
text-transform: uppercase;

View File

@@ -66,7 +66,7 @@ export class IncomingTransactionsGraphComponent implements OnInit, OnChanges, On
if (!this.data) {
return;
}
this.windowPreference = this.windowPreferenceOverride ? this.windowPreferenceOverride : this.storageService.getValue('graphWindowPreference');
this.windowPreference = (this.windowPreferenceOverride ? this.windowPreferenceOverride : this.storageService.getValue('graphWindowPreference')) || '2h';
const windowSize = Math.max(10, Math.floor(this.data.series[0].length / 8));
this.MA = this.calculateMA(this.data.series[0], windowSize);
if (this.outlierCappingEnabled === true) {
@@ -216,22 +216,19 @@ export class IncomingTransactionsGraphComponent implements OnInit, OnChanges, On
type: 'line',
},
formatter: (params: any) => {
const axisValueLabel: string = formatterXAxis(this.locale, this.windowPreference, params[0].axisValue);
const bestItem = params.reduce((best, item) => {
return (item.seriesName === 'data' && (!best || best.value[1] < item.value[1])) ? item : best;
}, null);
const axisValueLabel: string = formatterXAxis(this.locale, this.windowPreference, bestItem.axisValue);
const colorSpan = (color: string) => `<span class="indicator" style="background-color: ` + color + `"></span>`;
let itemFormatted = '<div class="title">' + axisValueLabel + '</div>';
params.map((item: any, index: number) => {
//Do no include MA in tooltip legend!
if (item.seriesName !== 'MA') {
if (index < 26) {
itemFormatted += `<div class="item">
<div class="indicator-container">${colorSpan(item.color)}</div>
if (bestItem) {
itemFormatted += `<div class="item">
<div class="indicator-container">${colorSpan(bestItem.color)}</div>
<div class="grow"></div>
<div class="value">${formatNumber(item.value[1], this.locale, '1.0-0')}<span class="symbol">vB/s</span></div>
<div class="value">${formatNumber(bestItem.value[1], this.locale, '1.0-0')}<span class="symbol">vB/s</span></div>
</div>`;
}
}
});
}
return `<div class="tx-wrapper-tooltip-chart ${(this.template === 'advanced') ? 'tx-wrapper-tooltip-chart-advanced' : ''}"
style="width: ${(this.windowPreference === '2h' || this.template === 'widget') ? '125px' : '215px'}">${itemFormatted}</div>`;
}

View File

@@ -4,6 +4,7 @@
top: 0;
width: 100%;
z-index: 100;
background-color: var(--bg);
}
li.nav-item.active {
@@ -17,7 +18,7 @@ fa-icon {
.navbar {
z-index: 100;
min-height: 64px;
background-color: var(--bg);
background-color: var(--nav-bg);
}
li.nav-item {
@@ -48,7 +49,7 @@ li.nav-item {
}
.navbar-nav {
background: var(--navbar-bg);
background: var(--nav-bg);
bottom: 0;
box-shadow: 0px 0px 15px 0px #000;
flex-direction: row;

View File

@@ -6,7 +6,7 @@
<img [src]="enterpriseInfo.img" class="subdomain_logo" [class]="{'rounded': enterpriseInfo.rounded_corner}">
}
@if (enterpriseInfo?.header_img) {
<img *ngIf="enterpriseInfo.header_img" [src]="enterpriseInfo?.header_img" alt="enterpriseInfo.title" height="36px">
<img *ngIf="enterpriseInfo.header_img" [src]="enterpriseInfo?.header_img" alt="enterpriseInfo.title" height="60px" class="mr-3">
} @else {
<app-svg-images *ngIf="!officialMempoolSpace" name="mempoolSpace" viewBox="0 0 500 126" width="500" height="126" class="mempool-logo" style="width: 200px; height: 50px"></app-svg-images>
<app-svg-images *ngIf="officialMempoolSpace" name="officialMempoolSpace" style="width: 200px; height: 50px" width="500" height="126" viewBox="0 0 500 126"></app-svg-images>

View File

@@ -5,6 +5,7 @@
max-width: 1200px;
max-height: 600px;
padding-top: 80px;
background: var(--nav-bg);
header {
position: absolute;
@@ -18,7 +19,7 @@
flex-direction: row;
justify-content: space-between;
align-items: center;
background: var(--stat-box-bg);
background: var(--nav-bg);
text-align: start;
font-size: 1.8em;
}

View File

@@ -17,16 +17,16 @@
<!-- Large screen -->
<a class="navbar-brand d-none d-md-flex" [ngClass]="{'dual-logos': subdomain}" [routerLink]="['/' | relativeUrl]" (click)="brandClick($event)">
<ng-template [ngIf]="subdomain && enterpriseInfo">
<div class="subdomain_container">
<img [src]="enterpriseInfo.img || '/api/v1/services/enterprise/images/' + subdomain + '/logo?imageMd5=' + enterpriseInfo.imageMd5" class="subdomain_logo" [class]="{'rounded': enterpriseInfo.rounded_corner}">
</div>
<div class="vertical-line"></div>
</ng-template>
<ng-container *ngIf="{ val: connectionState$ | async } as connectionState">
@if (enterpriseInfo?.header_img) {
<img [src]="enterpriseInfo?.header_img" alt="enterpriseInfo.title" height="36px">
<img [src]="enterpriseInfo?.header_img" alt="enterpriseInfo.title" height="48px" class="mr-3">
} @else {
<ng-template [ngIf]="subdomain && enterpriseInfo">
<div class="subdomain_container">
<img [src]="enterpriseInfo.img || '/api/v1/services/enterprise/images/' + subdomain + '/logo?imageMd5=' + enterpriseInfo.imageMd5" class="subdomain_logo" [class]="{'rounded': enterpriseInfo.rounded_corner}">
</div>
<div class="vertical-line"></div>
</ng-template>
<app-svg-images *ngIf="!officialMempoolSpace" name="mempoolSpace" viewBox="0 0 500 126" class="mempool-logo" [ngStyle]="{'opacity': connectionState.val === 2 ? 1 : 0.5 }"></app-svg-images>
<app-svg-images *ngIf="officialMempoolSpace" name="officialMempoolSpace" viewBox="0 0 500 126"></app-svg-images>
}
@@ -38,24 +38,28 @@
</a>
<!-- Mobile -->
<a class="navbar-brand d-flex d-md-none justify-content-center" [ngClass]="{'dual-logos': subdomain, 'mr-0': subdomain}" [routerLink]="['/' | relativeUrl]" (click)="brandClick($event)">
<ng-template [ngIf]="subdomain && enterpriseInfo">
<div class="subdomain_container">
<img [src]="enterpriseInfo.img || '/api/v1/services/enterprise/images/' + subdomain + '/logo?imageMd5=' + enterpriseInfo.imageMd5" class="subdomain_logo" [class]="{'rounded': enterpriseInfo.rounded_corner}">
</div>
<div class="vertical-line"></div>
</ng-template>
<ng-container *ngIf="{ val: connectionState$ | async } as connectionState">
@if (enterpriseInfo?.header_img) {
<img [src]="enterpriseInfo?.header_img" alt="enterpriseInfo.title" height="36px">
} @else {
<app-svg-images *ngIf="!officialMempoolSpace" name="mempoolSpace" viewBox="0 0 500 126" class="mempool-logo" [ngStyle]="{'opacity': connectionState.val === 2 ? 1 : 0.5 }"></app-svg-images>
<app-svg-images *ngIf="officialMempoolSpace" name="officialMempoolSpace" viewBox="0 0 500 126"></app-svg-images>
}
<div class="connection-badge">
<div class="badge badge-warning" *ngIf="connectionState.val === 0" i18n="master-page.offline">Offline</div>
<div class="badge badge-warning" *ngIf="connectionState.val === 1" i18n="master-page.reconnecting">Reconnecting...</div>
</div>
</ng-container>
@if (enterpriseInfo?.header_img) {
<img [src]="enterpriseInfo?.header_img" alt="enterpriseInfo.title" height="42px">
} @else {
<ng-template [ngIf]="subdomain && enterpriseInfo">
<div class="subdomain_container">
<img [src]="enterpriseInfo.img || '/api/v1/services/enterprise/images/' + subdomain + '/logo?imageMd5=' + enterpriseInfo.imageMd5" class="subdomain_logo" [class]="{'rounded': enterpriseInfo.rounded_corner}">
</div>
<div class="vertical-line"></div>
</ng-template>
<ng-container *ngIf="{ val: connectionState$ | async } as connectionState">
@if (enterpriseInfo?.header_img) {
<img [src]="enterpriseInfo?.header_img" alt="enterpriseInfo.title" height="36px">
} @else {
<app-svg-images *ngIf="!officialMempoolSpace" name="mempoolSpace" viewBox="0 0 500 126" class="mempool-logo" [ngStyle]="{'opacity': connectionState.val === 2 ? 1 : 0.5 }"></app-svg-images>
<app-svg-images *ngIf="officialMempoolSpace" name="officialMempoolSpace" viewBox="0 0 500 126"></app-svg-images>
}
<div class="connection-badge">
<div class="badge badge-warning" *ngIf="connectionState.val === 0" i18n="master-page.offline">Offline</div>
<div class="badge badge-warning" *ngIf="connectionState.val === 1" i18n="master-page.reconnecting">Reconnecting...</div>
</div>
</ng-container>
}
</a>
<div (window:resize)="onResize()" ngbDropdown class="dropdown-container" *ngIf="env.TESTNET_ENABLED || env.TESTNET4_ENABLED || env.SIGNET_ENABLED || env.LIQUID_ENABLED || env.LIQUID_TESTNET_ENABLED">

View File

@@ -3,6 +3,7 @@
position: -webkit-sticky;
top: 0;
width: 100%;
background-color: var(--bg);
z-index: 100;
}
@@ -18,7 +19,7 @@ fa-icon {
z-index: 100;
min-height: 64px;
width: 100%;
background-color: var(--bg);
background-color: var(--nav-bg);
}
li.nav-item {
@@ -59,7 +60,7 @@ li.nav-item {
}
.navbar-nav {
background: var(--navbar-bg);
background: var(--nav-bg);
bottom: 0;
box-shadow: 0px 0px 15px 0px #000;
flex-direction: row;

View File

@@ -56,7 +56,7 @@
.fee-span {
font-size: 11px;
margin-bottom: 5px;
color: #fff000;
color: var(--yellow);
}
.transaction-count {
@@ -119,7 +119,7 @@
height: 0;
border-left: calc(var(--block-size) * 0.3) solid transparent;
border-right: calc(var(--block-size) * 0.3) solid transparent;
border-bottom: calc(var(--block-size) * 0.3) solid #FFF;
border-bottom: calc(var(--block-size) * 0.3) solid var(--fg);
}
.blockLink {

View File

@@ -77,7 +77,7 @@ export class MempoolGraphComponent implements OnInit, OnChanges {
}
this.isWidget = this.template === 'widget';
this.showCount = !this.isWidget && !this.hideCount;
this.windowPreference = this.windowPreferenceOverride ? this.windowPreferenceOverride : this.storageService.getValue('graphWindowPreference');
this.windowPreference = (this.windowPreferenceOverride ? this.windowPreferenceOverride : this.storageService.getValue('graphWindowPreference')) || '2h';
this.mempoolVsizeFeesData = this.handleNewMempoolData(this.data.concat([]));
this.mountFeeChart();
}
@@ -256,11 +256,17 @@ export class MempoolGraphComponent implements OnInit, OnChanges {
const itemFormatted = [];
let sum = 0;
let progressPercentageText = '';
let countItem;
let items = this.inverted ? [...params].reverse() : params;
if (items[items.length - 1].seriesName === 'count') {
countItem = items.pop();
}
const unfilteredItems = this.inverted ? [...params].reverse() : params;
const countItem = unfilteredItems.find(p => p.seriesName === 'count');
const usedSeries = {};
const items = unfilteredItems.filter(p => {
if (usedSeries[p.seriesName] || p.seriesName === 'count') {
return false;
}
usedSeries[p.seriesName] = true;
return true;
});
items.map((item: any, index: number) => {
sum += item.value[1];
const progressPercentage = (item.value[1] / totalValue) * 100;

View File

@@ -63,7 +63,8 @@
.main-title {
position: relative;
color: #ffffff91;
color: var(--fg);
opacity: var(--opacity);
margin-top: -13px;
font-size: 10px;
text-transform: uppercase;

View File

@@ -1,10 +1,10 @@
.rbf-tooltip {
position: fixed;
z-index: 3;
background: rgba(#11131f, 0.95);
background: color-mix(in srgb, var(--active-bg) 95%, transparent);
border-radius: 4px;
box-shadow: 1px 1px 10px rgba(0,0,0,0.5);
color: #b1b1b1;
color: var(--tooltip-grey);
display: flex;
flex-direction: column;
justify-content: space-between;

View File

@@ -159,7 +159,7 @@
&.selected {
.shape-border {
background: #9339f4;
background: var(--mainnet-alt);
}
}
@@ -183,7 +183,7 @@
width: calc(1em + 16px);
.shape {
border: solid 4px #9339f4;
border: solid 4px var(--mainnet-alt);
}
&:hover {

View File

@@ -71,7 +71,9 @@ export class TelevisionComponent implements OnInit, OnDestroy {
mempoolStats = newStats;
} else if (['2h', '24h'].includes(this.fragment)) {
mempoolStats.unshift(newStats[0]);
mempoolStats = mempoolStats.slice(0, mempoolStats.length - 1);
const now = Date.now() / 1000;
const start = now - (this.fragment === '2h' ? (2 * 60 * 60) : (24 * 60 * 60) );
mempoolStats = mempoolStats.filter(p => p.added >= start);
}
return mempoolStats;
})

View File

@@ -11,7 +11,7 @@
<div class="text-left">
<p *ngIf="officialMempoolSpace">The <a href="https://mempool.space/">mempool.space</a> website, the <a href="https://liquid.network/">liquid.network</a> website, their associated API services, and related network and server infrastructure (collectively, the "Website") are operated by Mempool Space K.K. in Japan ("Mempool", "We", or "Us") and self-hosted from <a href="https://bgp.tools/as/142052#connectivity">AS142052</a>.</p>
<p *ngIf="officialMempoolSpace">The <a href="https://mempool.space/">mempool.space</a> website, the <a href="https://liquid.network/">liquid.network</a> website, the <a href="https://bitcoin.gob.sv/">bitcoin.gob.sv</a> website, their associated API services, and related network and server infrastructure (collectively, the "Website") are operated by Mempool Space K.K. in Japan ("Mempool", "We", or "Us") and self-hosted from <a href="https://bgp.tools/as/142052#connectivity">AS142052</a>.</p>
<p *ngIf="!officialMempoolSpace">This website and its API service (collectively, the "Website") are operated by a member of the Bitcoin community ("We" or "Us"). Mempool Space K.K. in Japan ("Mempool") has no affiliation with the operator of this Website, and does not sponsor or endorse the information provided herein.</p>

View File

@@ -11,7 +11,7 @@ import { Subscription } from 'rxjs';
})
export class ThemeSelectorComponent implements OnInit {
themeForm: UntypedFormGroup;
themes = ['default', 'contrast', 'wiz'];
themes = ['default', 'contrast', 'wiz', 'bukele'];
themeSubscription: Subscription;
constructor(

View File

@@ -1,9 +1,26 @@
<div class="mobile-wrapper">
<div class="mobile-container">
<div class="panel">
<div class="field nav-header">
<app-svg-images name="officialMempoolSpace" style="width: 144px; height: 36px" width="500" height="126" viewBox="0 0 500 126"></app-svg-images>
<div [ngSwitch]="network" class="network-label">
<div class="nav-header">
@if (enterpriseInfo?.header_img) {
<a class="d-flex" [routerLink]="['/' | relativeUrl]">
<img *ngIf="enterpriseInfo.header_img" [src]="enterpriseInfo?.header_img" alt="enterpriseInfo.title" height="42px">
</a>
} @else if (enterpriseInfo?.img || enterpriseInfo?.imageMd5) {
<a [routerLink]="['/' | relativeUrl]">
<img [src]="enterpriseInfo.img || '/api/v1/services/enterprise/images/' + enterpriseInfo.name + '/logo?imageMd5=' + enterpriseInfo.imageMd5" class="subdomain_logo" [class]="{'rounded': enterpriseInfo.rounded_corner}">
</a>
<div class="vertical-line"></div>
}
@if (!enterpriseInfo?.header_img) {
<a [routerLink]="['/' | relativeUrl]">
<app-svg-images *ngIf="!officialMempoolSpace" name="mempoolSpace" style="width: 144px; height: 36px" viewBox="0 0 500 126" width="500" height="126" class="mempool-logo"></app-svg-images>
<app-svg-images *ngIf="officialMempoolSpace" name="officialMempoolSpace" style="width: 144px; height: 36px" width="500" height="126" viewBox="0 0 500 126"></app-svg-images>
</a>
}
@if (enterpriseInfo?.header_img || (!enterpriseInfo?.img && !enterpriseInfo?.imageMd5)) {
<div [ngSwitch]="network" class="network-label" [class.hide-name]="enterpriseInfo?.header_img">
<span *ngSwitchCase="'signet'" class="network signet"><span class="name">Bitcoin Signet</span><app-svg-images name="signet" width="35" height="35" viewBox="0 0 65 65" style="display: inline-block" class="mainnet ml-2"></app-svg-images></span>
<span *ngSwitchCase="'testnet'" class="network testnet"><span class="name">Bitcoin Testnet3</span><app-svg-images name="testnet" width="35" height="35" viewBox="0 0 65 65" style="display: inline-block" class="mainnet ml-2"></app-svg-images></span>
<span *ngSwitchCase="'testnet4'" class="network testnet"><span class="name">Bitcoin Testnet4</span><app-svg-images name="testnet4" width="35" height="35" viewBox="0 0 65 65" style="display: inline-block" class="mainnet ml-2"></app-svg-images></span>
@@ -11,6 +28,7 @@
<span *ngSwitchCase="'liquidtestnet'" class="network liquidtestnet"><span class="name">Liquid Testnet</span><app-svg-images name="liquidtestnet" width="35" height="35" viewBox="0 0 125 125" style="display: inline-block" class="mainnet ml-2"></app-svg-images></span>
<span *ngSwitchDefault class="network mainnet"><span class="name">Bitcoin</span><app-svg-images name="bitcoin" width="35" height="35" viewBox="0 0 65 65" style="display: inline-block" class="mainnet ml-2"></app-svg-images></span>
</div>
}
</div>
<div class="field">
<div class="label" i18n="shared.transaction">Transaction</div>

View File

@@ -40,7 +40,14 @@
}
.nav-header {
display: flex;
flex-direction: row;
flex-wrap: nowrap;
width: 100%;
max-width: 100%;
padding: 1em;
position: relative;
background: var(--nav-bg);
box-shadow: 0 -5px 15px #000;
z-index: 100;
align-items: center;
@@ -53,6 +60,40 @@
flex-direction: row;
align-items: center;
}
&.hide-name .name {
display: none;
}
}
.subdomain_logo {
height: 35px;
overflow: clip;
max-width: 140px;
margin: auto;
align-self: center;
.rounded {
border-radius: 5px;
}
}
.subdomain_container {
max-width: 140px;
text-align: center;
align-self: center;
}
.vertical-line {
border-left: 1px solid #444;
height: 30px;
margin-left: 10px;
margin-right: 10px;
margin-top: 3px;
}
.logo-holder {
display: flex;
flex-direction: row;
}
}

View File

@@ -113,6 +113,10 @@ export class TrackerComponent implements OnInit, OnDestroy {
scrollIntoAccelPreview = false;
auditEnabled: boolean = this.stateService.env.AUDIT && this.stateService.env.BASE_MODULE === 'mempool' && this.stateService.env.MINING_DASHBOARD === true;
enterpriseInfo: any;
enterpriseInfo$: Subscription;
officialMempoolSpace = this.stateService.env.OFFICIAL_MEMPOOL_SPACE;
constructor(
private route: ActivatedRoute,
private electrsApiService: ElectrsApiService,
@@ -152,6 +156,10 @@ export class TrackerComponent implements OnInit, OnDestroy {
this.enterpriseService.page();
this.enterpriseInfo$ = this.enterpriseService.info$.subscribe(info => {
this.enterpriseInfo = info;
});
this.websocketService.want(['blocks', 'mempool-blocks']);
this.stateService.networkChanged$.subscribe(
(network) => {
@@ -702,6 +710,7 @@ export class TrackerComponent implements OnInit, OnDestroy {
this.blocksSubscription.unsubscribe();
this.miningSubscription?.unsubscribe();
this.currencyChangeSubscription?.unsubscribe();
this.enterpriseInfo$?.unsubscribe();
this.leaveTransaction();
}
}

View File

@@ -103,7 +103,8 @@ td.amount.large {
margin-top: 10px;
}
.assetBox {
background-color: #653b9c90;
background: color-mix(in srgb, var(--tertiary) 56%, transparent);
}
.details-container {

View File

@@ -0,0 +1,16 @@
@if (loading) {
<div class="spinner-wrapper">
<div class="ml-2 spinner-border text-light" style="width: 25px; height: 25px"></div>
</div>
} @else if (error) {
<div class="error-wrapper">
<span>failed to load X timeline</span>
</div>
}
<iframe id="twitter-widget-0" scrolling="no" frameborder="0" allowtransparency="true" allowfullscreen="true"
title="Twitter Timeline"
[src]="iframeSrc"
style="position: static; visibility: visible; width: 100%; height: 100%; display: block; flex-grow: 1;"
(load)="onReady()"
></iframe>

View File

@@ -0,0 +1,10 @@
.spinner-wrapper, .error-wrapper {
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
display: flex;
justify-content: center;
align-items: center;
}

View File

@@ -0,0 +1,71 @@
import { Component, Input, ChangeDetectionStrategy, SecurityContext, SimpleChanges, OnChanges } from '@angular/core';
import { LanguageService } from '../../services/language.service';
import { DomSanitizer, SafeResourceUrl } from '@angular/platform-browser';
@Component({
selector: 'app-twitter-widget',
templateUrl: './twitter-widget.component.html',
styleUrls: ['./twitter-widget.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class TwitterWidgetComponent implements OnChanges {
@Input() handle: string;
@Input() width = 300;
@Input() height = 400;
loading: boolean = true;
error: boolean = false;
lang: string = 'en';
iframeSrc: SafeResourceUrl;
constructor(
private languageService: LanguageService,
public sanitizer: DomSanitizer,
) {
this.lang = this.languageService.getLanguage();
this.setIframeSrc();
}
ngOnChanges(changes: SimpleChanges): void {
if (changes.handle) {
this.setIframeSrc();
}
}
setIframeSrc(): void {
if (this.handle) {
this.iframeSrc = this.sanitizer.bypassSecurityTrustResourceUrl(this.sanitizer.sanitize(SecurityContext.URL,
`https://syndication.twitter.com/srv/timeline-profile/screen-name/${this.handle}?creatorScreenName=mempool`
+ '&dnt=true'
+ '&embedId=twitter-widget-0'
+ '&features=eyJ0ZndfdGltZWxpbmVfgbGlzdCI6eyJidWNrZXQiOltdLCJ2ZXJzaW9uIjpudWxsfSwidGZ3X2ZvbGxvd2VyX2NvdW50X3N1bnNldCI6eyJidWNrZXQiOnRydWUsInZlcnNpb24iOm51bGx9LCJ0ZndfdHdlZXRfZWRpdF9iYWNrZW5kIjp7ImJ1Y2tldCI6Im9uIiwidmVyc2lvbiI6bnVsbH0sInRmd19yZWZzcmNfc2Vzc2lvbiI6eyJidWNrZXQiOiJvbiIsInZlcnNpb24iOm51bGx9LCJ0ZndfZm9zbnJfc29mdF9pbnRlcnZlbnRpb25zX2VuYWJsZWQiOnsiYnVja2V0Ijoib24iLCJ2ZXJzaW9uIjpudWxsfSwidGZ3X21peGVkX21lZGlhXzE1ODk3Ijp7ImJ1Y2tldCI6InRyZWF0bWVudCIsInZlcnNpb24iOm51bGx9LCJ0ZndfZXhwZXJpbWVudHNfY29va2llX2V4cGlyYXRpb24iOnsiYnVja2V0IjoxMjA5NjAwLCJ2ZXJzaW9uIjpudWxsfSwidGZ3X3Nob3dfYmlyZHdhdGNoX3Bpdm90c19lbmFibGVkIjp7ImJ1Y2tldCI6Im9uIiwidmVyc2lvbiI6bnVsbH0sInRmd19kdXBsaWNhdGVfc2NyaWJlc190b19zZXR0aW5ncyI6eyJidWNrZXQiOiJvbiIsInZlcnNpb24iOm51bGx9LCJ0ZndfdXNlX3Byb2ZpbGVfaW1hZ2Vfc2hhcGVfZW5hYmxlZCI6eyJidWNrZXQiOiJvbiIsInZlcnNpb24iOm51bGx9LCJ0ZndfdmlkZW9faGxzX2R5bmFtaWNfbWFuaWZlc3RzXzE1MDgyIjp7ImJ1Y2tldCI6InRydWVfYml0cmF0ZSIsInZlcnNpb24iOm51bGx9LCJ0ZndfbGVnYWN5X3RpbWVsaW5lX3N1bnNldCI6eyJidWNrZXQiOnRydWUsInZlcnNpb24iOm51bGx9LCJ0ZndfdHdlZXRfZWRpdF9mcm9udGVuZCI6eyJidWNrZXQiOiJvbiIsInZlcnNpb24iOm51bGx9fQ%3D%3D'
+ '&frame=false'
+ '&hideBorder=true'
+ '&hideFooter=false'
+ '&hideHeader=true'
+ '&hideScrollBar=false'
+ `&lang=${this.lang}`
+ '&maxHeight=500px'
+ '&origin=https%3A%2F%2Fmempool.space%2F'
// + '&sessionId=88f6d661d0dcca99c43c0a590f6a3e61c89226a9'
+ '&showHeader=false'
+ '&showReplies=false'
+ '&siteScreenName=mempool'
+ '&theme=dark'
+ '&transparent=true'
+ '&widgetsVersion=2615f7e52b7e0%3A1702314776716'
));
}
}
onReady(): void {
this.loading = false;
this.error = false;
}
onFailed(): void {
this.loading = false;
this.error = true;
}
}

View File

@@ -1,6 +1,6 @@
.bowtie-graph-tooltip {
position: absolute;
background: rgba(#11131f, 0.95);
background: color-mix(in srgb, var(--active-bg) 95%, transparent);
border-radius: 4px;
box-shadow: 1px 1px 10px rgba(0,0,0,0.5);
color: var(--tooltip-grey);

View File

@@ -84,7 +84,7 @@ export class TxBowtieGraphComponent implements OnInit, OnChanges {
refreshOutspends$: ReplaySubject<string> = new ReplaySubject();
gradientColors = {
'': ['#9339f4', '#105fb0', '#9339f400'],
'': ['var(--mainnet-alt)', 'var(--primary)', 'color-mix(in srgb, var(--mainnet-alt) 1%, transparent)'],
// liquid: ['#116761', '#183550'],
liquid: ['#09a197', '#0f62af', '#09a19700'],
// 'liquidtestnet': ['#494a4a', '#272e46'],
@@ -96,7 +96,7 @@ export class TxBowtieGraphComponent implements OnInit, OnChanges {
signet: ['#d24fc8', '#a84fd2', '#d24fc800'],
};
gradient: string[] = ['#105fb0', '#105fb0'];
gradient: string[] = ['var(--primary)', 'var(--primary)'];
constructor(
private router: Router,

View File

@@ -301,7 +301,8 @@
.main-title {
position: relative;
color: #ffffff91;
color: var(--fg);
opacity: var(--opacity);
margin-top: -13px;
font-size: 10px;
text-transform: uppercase;
@@ -435,7 +436,8 @@
.in-progress-message {
position: relative;
color: #ffffff91;
color: var(--fg);
opacity: var(--opacity);
margin-top: 20px;
text-align: center;
padding-bottom: 3px;

View File

@@ -231,8 +231,10 @@ export class DashboardComponent implements OnInit, OnDestroy, AfterViewInit {
this.stateService.live2Chart$
.pipe(
scan((acc, stats) => {
const now = Date.now() / 1000;
const start = now - (2 * 60 * 60);
acc.unshift(stats);
acc = acc.slice(0, 120);
acc = acc.filter(p => p.added >= start);
return acc;
}, (mempoolStats || []))
),

View File

@@ -66,7 +66,8 @@
.main-title {
position: relative;
color: #ffffff91;
color: var(--fg);
opacity: var(--opacity);
margin-top: -13px;
font-size: 10px;
text-transform: uppercase;

View File

@@ -11,7 +11,8 @@
.main-title {
position: relative;
color: #ffffff91;
color: var(--fg);
opacity: var(--opacity);
margin-top: -13px;
font-size: 10px;
text-transform: uppercase;

View File

@@ -11,7 +11,8 @@
.main-title {
position: relative;
color: #ffffff91;
color: var(--fg);
opacity: var(--opacity);
margin-top: -13px;
font-size: 10px;
text-transform: uppercase;

View File

@@ -27,12 +27,15 @@ export interface Customization {
name: string;
site_id?: number;
title: string;
img: string;
img?: string;
header_img?: string;
footer_img?: string;
rounded_corner: boolean;
},
dashboard: {
widgets: {
component: string;
mobileOrder?: number;
props: { [key: string]: any };
}[];
};

View File

@@ -17,14 +17,14 @@ export class ThemeService {
private storageService: StorageService,
private stateService: StateService,
) {
const theme = this.storageService.getValue('theme-preference') || this.stateService.env.customize?.theme || 'default';
const theme = this.stateService.env.customize?.theme || this.storageService.getValue('theme-preference') || 'default';
this.apply(theme);
}
apply(theme) {
this.theme = theme;
if (theme !== 'default') {
theme === 'contrast' ? this.mempoolFeeColors = contrastMempoolFeeColors : this.mempoolFeeColors = defaultMempoolFeeColors;
theme === 'contrast' || theme === 'bukele' ? this.mempoolFeeColors = contrastMempoolFeeColors : this.mempoolFeeColors = defaultMempoolFeeColors;
try {
if (!this.style) {
this.style = document.createElement('link');
@@ -44,7 +44,9 @@ export class ThemeService {
this.style = null;
}
}
this.storageService.setValue('theme-preference', theme);
if (!this.stateService.env.customize?.theme) {
this.storageService.setValue('theme-preference', theme);
}
this.themeChanged$.next(this.theme);
}
}

View File

@@ -4,13 +4,19 @@
<div class="row main" [class]="{'services': isServicesPage}">
<div class="col-md-12 branding mt-2">
<div class="main-logo" [class]="{'services': isServicesPage}">
<app-svg-images *ngIf="officialMempoolSpace" name="officialMempoolSpace" viewBox="0 0 500 126"></app-svg-images>
<app-svg-images *ngIf="!officialMempoolSpace" name="mempoolSpace" viewBox="0 0 500 126"></app-svg-images>
@if (enterpriseInfo?.footer_img) {
<img [src]="enterpriseInfo?.footer_img" alt="enterpriseInfo.title" height="60px" class="mr-3">
} @else {
<app-svg-images *ngIf="officialMempoolSpace" name="officialMempoolSpace" viewBox="0 0 500 126"></app-svg-images>
<app-svg-images *ngIf="!officialMempoolSpace" name="mempoolSpace" viewBox="0 0 500 126"></app-svg-images>
}
</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'">&reg;</ng-template>
</p>
@if (!enterpriseInfo?.footer_img) {
<p class="explore-tagline-mobile">
<ng-container i18n="@@7deec1c1520f06170e1f8e8ddfbe4532312f638f">Explore the full Bitcoin ecosystem</ng-container>
<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">
<app-language-selector></app-language-selector>
@@ -21,25 +27,31 @@
<div class="selector">
<app-rate-unit-selector></app-rate-unit-selector>
</div>
<div class="selector d-none d-sm-flex">
<app-theme-selector></app-theme-selector>
</div>
@if (!env.customize?.theme) {
<div class="selector d-none d-sm-flex">
<app-theme-selector></app-theme-selector>
</div>
}
<a *ngIf="stateService.isMempoolSpaceBuild" class="btn btn-purple sponsor d-none d-sm-flex justify-content-center" [routerLink]="['/login' | relativeUrl]">
<span *ngIf="loggedIn" i18n="shared.my-account" class="nowrap">My Account</span>
<span *ngIf="!loggedIn" i18n="shared.sign-in" class="nowrap">Sign In</span>
</a>
</div>
<div class="selector d-flex d-sm-none justify-content-center ml-auto mr-auto mt-0">
<app-theme-selector></app-theme-selector>
</div>
<a *ngIf="stateService.isMempoolSpaceBuild" class="btn btn-purple sponsor d-flex d-sm-none justify-content-center ml-auto mr-auto mt-0 mb-2" [routerLink]="['/login' | relativeUrl]">
<span *ngIf="loggedIn" i18n="shared.my-account" class="nowrap">My Account</span>
<span *ngIf="!loggedIn" i18n="shared.sign-in" class="nowrap">Sign In</span>
</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'">&reg;</ng-template>
</p>
@if (!env.customize?.theme) {
<div class="selector d-flex d-sm-none justify-content-center ml-auto mr-auto mt-0">
<app-theme-selector></app-theme-selector>
</div>
}
@if (!enterpriseInfo?.footer_img) {
<a *ngIf="stateService.isMempoolSpaceBuild" class="btn btn-purple sponsor d-flex d-sm-none justify-content-center ml-auto mr-auto mt-0 mb-2" [routerLink]="['/login' | relativeUrl]">
<span *ngIf="loggedIn" i18n="shared.my-account" class="nowrap">My Account</span>
<span *ngIf="!loggedIn" i18n="shared.sign-in" class="nowrap">Sign In</span>
</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'">&reg;</ng-template>
</p>
}
</div>
</div>
<div class="row col-md-12 link-tree" [class]="{'services': isServicesPage}">

View File

@@ -1,4 +1,4 @@
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, OnInit, Inject, LOCALE_ID, HostListener } from '@angular/core';
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, OnInit, Inject, LOCALE_ID, HostListener, OnDestroy } from '@angular/core';
import { Router, ActivatedRoute } from '@angular/router';
import { Observable, merge, of, Subject, Subscription } from 'rxjs';
import { tap, takeUntil } from 'rxjs/operators';
@@ -8,6 +8,7 @@ import { LanguageService } from '../../../services/language.service';
import { NavigationService } from '../../../services/navigation.service';
import { StorageService } from '../../../services/storage.service';
import { WebsocketService } from '../../../services/websocket.service';
import { EnterpriseService } from '../../../services/enterprise.service';
@Component({
selector: 'app-global-footer',
@@ -15,7 +16,7 @@ import { WebsocketService } from '../../../services/websocket.service';
styleUrls: ['./global-footer.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class GlobalFooterComponent implements OnInit {
export class GlobalFooterComponent implements OnInit, OnDestroy {
private destroy$: Subject<any> = new Subject<any>();
env: Env;
officialMempoolSpace = this.stateService.env.OFFICIAL_MEMPOOL_SPACE;
@@ -32,10 +33,14 @@ export class GlobalFooterComponent implements OnInit {
urlSubscription: Subscription;
isServicesPage = false;
enterpriseInfo: any;
enterpriseInfo$: Subscription;
constructor(
public stateService: StateService,
private languageService: LanguageService,
private navigationService: NavigationService,
private enterpriseService: EnterpriseService,
@Inject(LOCALE_ID) public locale: string,
private storageService: StorageService,
private route: ActivatedRoute,
@@ -54,6 +59,9 @@ export class GlobalFooterComponent implements OnInit {
this.navigationService.subnetPaths.subscribe((paths) => {
this.networkPaths = paths;
});
this.enterpriseInfo$ = this.enterpriseService.info$.subscribe(info => {
this.enterpriseInfo = info;
});
this.network$ = merge(of(''), this.stateService.networkChanged$).pipe(
tap((network: string) => {
return network;
@@ -73,6 +81,9 @@ export class GlobalFooterComponent implements OnInit {
this.destroy$.next(true);
this.destroy$.complete();
this.urlSubscription.unsubscribe();
if (this.enterpriseInfo$) {
this.enterpriseInfo$.unsubscribe();
}
}
networkLink(network) {

View File

@@ -1,6 +1,14 @@
<div class="container p-lg-0 pb-0" style="max-width: 100%; margin-top: 7px" *ngIf="storageService.getValue('hideWarning') !== 'hidden'">
<div class="alert alert-danger mb-0 text-center">
<div class="message-container" i18n="warning-testnet">This is a test network. Coins have no value.</div>
<div class="message-container">
<span i18n="warning-testnet">This is a test network. Coins have no value.</span>
@if (stateService.network === 'testnet') {
<span i18n="testnet3-deprecated">Testnet3 is deprecated, and will soon be replaced by <a href="/testnet4">Testnet4</a></span>
}
@if (stateService.network === 'testnet4') {
<span i18n="testnet4-not-finalized">Testnet4 is not yet finalized, and may be reset at anytime.</span>
}
</div>
<button type="button" class="close" (click)="dismissWarning()">
<span aria-hidden="true">&times;</span>
</button>

View File

@@ -7,10 +7,12 @@
display: flex;
justify-content: center;
align-items: flex-start;
}
.message-container {
display: flex;
flex-direction: column;
margin-left: auto;
}

View File

@@ -1,5 +1,6 @@
import { ChangeDetectionStrategy, Component } from '@angular/core';
import { StorageService } from '../../../services/storage.service';
import { StateService } from '../../../services/state.service';
@Component({
selector: 'app-testnet-alert',
@@ -11,6 +12,7 @@ export class TestnetAlertComponent {
constructor(
public storageService: StorageService,
public stateService: StateService,
) { }
dismissWarning(): void {

View File

@@ -113,6 +113,7 @@ import { ClockComponent } from '../components/clock/clock.component';
import { CalculatorComponent } from '../components/calculator/calculator.component';
import { BitcoinsatoshisPipe } from '../shared/pipes/bitcoinsatoshis.pipe';
import { HttpErrorComponent } from '../shared/components/http-error/http-error.component';
import { TwitterWidgetComponent } from '../components/twitter-widget/twitter-widget.component';
import { OnlyVsizeDirective, OnlyWeightDirective } from './components/weight-directives/weight-directives';
@@ -226,6 +227,7 @@ import { OnlyVsizeDirective, OnlyWeightDirective } from './components/weight-dir
AccelerateCheckout,
PendingStatsComponent,
HttpErrorComponent,
TwitterWidgetComponent,
],
imports: [
CommonModule,
@@ -354,6 +356,7 @@ import { OnlyVsizeDirective, OnlyWeightDirective } from './components/weight-dir
AccelerateCheckout,
PendingStatsComponent,
HttpErrorComponent,
TwitterWidgetComponent,
MempoolBlockOverviewComponent,
ClockchainComponent,

View File

@@ -3,30 +3,30 @@
<head>
<meta charset="utf-8">
<title>Oficina Nacional del Bitcoin - Bitcoin Explorer</title>
<title>National Bitcoin Office of El Salvador</title>
<script src="/resources/config.js"></script>
<script src="/resources/customize.js"></script>
<base href="/">
<meta name="description" content="Explore the full Bitcoin ecosystem with The Mempool Open Source Project®. See the real-time status of your transactions, get network info, and more." />
<meta property="og:image" content="https://mempool.space/resources/sv/onbtc-preview.jpg" />
<meta name="description" content="The National Bitcoin Office (ONBTC) of El Salvador under President @nayibbukele" />
<meta property="og:image" content="https://mempool.space/resources/onbtc/onbtc-preview.jpg" />
<meta property="og:image:type" content="image/jpeg" />
<meta property="og:image:width" content="2000" />
<meta property="og:image:height" content="1000" />
<meta property="og:description" content="Explore the full Bitcoin ecosystem with The Mempool Open Source Project®. See the real-time status of your transactions, get network info, and more." />
<meta property="og:description" content="The National Bitcoin Office (ONBTC) of El Salvador under President @nayibbukele" />
<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="Oficina Nacional del Bitcoin - Bitcoin Explorer">
<meta name="twitter:description" content="Explore the full Bitcoin ecosystem with The Mempool Open Source Project®. See the real-time status of your transactions, get network info, and more." />
<meta name="twitter:image" content="https://mempool.space/resources/sv/onbtc-preview.jpg" />
<meta name="twitter:title" content="National Bitcoin Office of El Salvador">
<meta name="twitter:description" content="The National Bitcoin Office (ONBTC) of El Salvador under President @nayibbukele" />
<meta name="twitter:image" content="https://mempool.space/resources/onbtc/onbtc-preview.jpg" />
<meta name="twitter:domain" content="bitcoin.gob.sv">
<link rel="apple-touch-icon" sizes="180x180" href="/resources/sv/favicons/apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="32x32" href="/resources/sv/favicons/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="/resources/sv/favicons/favicon-16x16.png">
<link rel="manifest" href="/resources/sv/favicons/site.webmanifest">
<link rel="shortcut icon" href="/resources/sv/favicons/favicon.ico">
<link rel="apple-touch-icon" sizes="180x180" href="/resources/onbtc/favicons/apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="32x32" href="/resources/onbtc/favicons/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="/resources/onbtc/favicons/favicon-16x16.png">
<link rel="manifest" href="/resources/onbtc/favicons/site.webmanifest">
<link rel="shortcut icon" href="/resources/onbtc/favicons/favicon.ico">
<link id="canonical" rel="canonical" href="https://bitcoin.gob.sv">
<meta name="apple-mobile-web-app-capable" content="yes">

View File

@@ -1,37 +1,12 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="159.7426"
height="162.47015"
viewBox="0 0 42.26523 42.986894"
version="1.1"
id="svg5"
sodipodi:docname="elsalvador.svg"
inkscape:version="1.2.2 (b0a84865, 2022-12-01)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
id="elsalvador"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<sodipodi:namedview
id="namedview469"
pagecolor="#ffffff"
bordercolor="#000000"
borderopacity="0.25"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
showgrid="false"
inkscape:zoom="2.8463012"
inkscape:cx="21.606989"
inkscape:cy="67.982966"
inkscape:window-width="1728"
inkscape:window-height="1051"
inkscape:window-x="0"
inkscape:window-y="38"
inkscape:window-maximized="1"
inkscape:current-layer="svg5" />
<defs
id="defs2">
<clipPath

Before

Width:  |  Height:  |  Size: 80 KiB

After

Width:  |  Height:  |  Size: 80 KiB

View File

@@ -1,118 +1,44 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
width="166.66856mm"
height="27.910412mm"
viewBox="0 0 166.66856 27.910412"
width="73.044792mm"
height="27.902231mm"
viewBox="0 0 73.04479 27.902231"
version="1.1"
id="svg5"
sodipodi:docname="onbtc.svg"
inkscape:version="1.2.2 (b0a84865, 2022-12-01)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
id="onbtc"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<sodipodi:namedview
id="namedview188"
pagecolor="#ffffff"
bordercolor="#000000"
borderopacity="0.25"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:document-units="mm"
showgrid="false"
inkscape:zoom="1.9192657"
inkscape:cx="243.84326"
inkscape:cy="52.88481"
inkscape:window-width="1728"
inkscape:window-height="1051"
inkscape:window-x="0"
inkscape:window-y="38"
inkscape:window-maximized="1"
inkscape:current-layer="text1855" />
<defs
id="defs2" />
<g
aria-label="OFICINA NACIONAL DEL BITCOIN"
aria-label="BITCOIN OFFICE"
id="text1855"
style="fill:#d2d2d2;stroke-width:3.37609;stroke-linecap:square"
transform="translate(-15.744428,-40.187266)">
transform="translate(-15.744428,-40.187135)">
<path
d="m 28.492368,45.40464 c 0,-3.039246 -2.735322,-5.217373 -5.92653,-5.217373 -3.596442,0 -6.179801,2.380743 -6.179801,5.740798 0,3.157439 2.785976,5.284912 6.095377,5.284912 3.275632,0 6.010954,-2.397628 6.010954,-5.808337 z m -1.587162,0.557195 c 0,2.397627 -1.317007,4.829024 -4.069213,4.829024 -2.718437,0 -4.862794,-2.22878 -4.862794,-5.386219 0,-2.026164 1.181929,-4.795255 4.153636,-4.795255 2.785976,0 4.778371,2.211895 4.778371,5.35245 z"
id="path415" />
d="m 17.787525,49.237549 c 0,1.063761 -0.270162,1.384578 -1.65474,1.384578 h -0.388357 v 0.320817 h 6.179946 c 2.718501,0 3.647182,-1.874246 3.647182,-3.208169 0,-1.317038 -0.928681,-2.347029 -2.51588,-2.819812 v -0.03377 c 1.131301,-0.202621 1.924901,-1.097532 1.924901,-2.059982 0,-0.810485 -0.337702,-1.384578 -1.029991,-1.874246 -0.607864,-0.439013 -1.908016,-0.658519 -3.393905,-0.658519 -0.320817,0 -1.604084,0.01689 -2.532765,0.05065 -0.489668,0.01689 -1.65474,0.08443 -2.127522,0.101311 v 0.320817 h 0.590978 c 1.181957,0 1.300153,0.506553 1.300153,1.469003 z m 1.401463,-8.577631 c 0.422127,-0.01688 1.114417,-0.05065 1.485889,-0.05065 2.076867,0 2.786041,1.080646 2.786041,2.262603 0,1.317038 -0.810485,1.958672 -2.431454,1.958672 h -1.840476 z m 0,4.491436 h 1.823591 c 1.975556,0 2.971777,1.333923 2.971777,2.634076 0,1.317038 -0.641634,2.701616 -2.870467,2.701616 -1.418348,0 -1.924901,-0.455898 -1.924901,-1.739165 z" />
<path
d="m 37.390604,43.935671 h -0.28704 c -0.05065,0.726042 -0.354579,1.080621 -0.979313,1.080621 h -3.34317 v -3.967905 h 3.208093 c 1.046851,0 1.384545,0.405233 1.40143,1.384545 h 0.28704 v -1.992394 h -7.564346 v 0.320809 c 1.181929,0.01689 1.266352,0.506541 1.266352,1.587162 v 6.618803 c 0,1.36766 -0.185731,1.587161 -1.232583,1.6547 v 0.32081 h 4.102982 v -0.32081 c -1.266352,0 -1.468968,-0.354579 -1.468968,-1.300122 v -3.697749 h 3.123669 c 0.810466,0 1.165045,0.303924 1.198814,1.283237 h 0.28704 z"
id="path417" />
d="m 31.329346,50.622127 c -1.165072,0 -1.435233,-0.337702 -1.435233,-1.333923 v -7.159282 c 0,-1.131302 0.371472,-1.367693 1.435233,-1.367693 v -0.320817 h -4.103079 v 0.320817 c 0.945565,0.05065 1.266382,0.303931 1.266382,1.215727 v 7.193052 c 0,1.131302 -0.219506,1.401463 -1.266382,1.452119 v 0.320817 h 4.103079 z" />
<path
d="m 43.215796,50.622012 c -1.165044,0 -1.435199,-0.337694 -1.435199,-1.333891 v -7.159113 c 0,-1.131275 0.371463,-1.367661 1.435199,-1.367661 v -0.320809 h -4.102982 v 0.320809 c 0.945543,0.05065 1.266353,0.303925 1.266353,1.215698 v 7.192883 c 0,1.131275 -0.219501,1.40143 -1.266353,1.452084 v 0.32081 h 4.102982 z"
id="path419" />
d="m 38.505484,41.048275 h 2.938008 c 0.675404,0 0.979335,0.388358 1.232612,1.874246 h 0.303932 l -0.270162,-2.735386 h -0.320817 c -0.03377,0.202621 -0.287046,0.253277 -0.523438,0.253277 h -8.121733 c -0.118195,0 -0.236391,-0.01689 -0.337702,-0.05066 -0.10131,-0.03377 -0.168851,-0.10131 -0.185736,-0.202621 h -0.320817 l -0.270161,2.735386 h 0.303932 c 0.253276,-1.485888 0.557208,-1.874246 1.232612,-1.874246 h 2.938007 v 8.341239 c 0,0.911796 -0.303932,1.232613 -1.333923,1.232613 H 35.14535 v 0.320817 h 5.318806 v -0.320817 h -0.624749 c -1.029991,0 -1.333923,-0.320817 -1.333923,-1.232613 z" />
<path
d="m 55.18702,43.209629 -0.151963,-2.448282 h -0.25327 c -0.03377,0.05065 -0.118193,0.101308 -0.303925,0.101308 -0.523426,0 -1.435199,-0.675388 -3.562672,-0.675388 -3.528902,0 -6.061607,2.363858 -6.061607,5.63949 0,3.12367 2.465166,5.38622 5.89276,5.38622 1.992395,0 2.735322,-0.60785 3.815943,-0.455887 0.405233,-0.658504 0.861119,-1.705355 1.080621,-2.465167 h -0.32081 c -1.148159,2.043049 -2.785975,2.498936 -4.119867,2.498936 -2.566474,0 -4.761485,-2.245665 -4.761485,-5.301796 0,-2.83663 1.756009,-4.879678 4.575754,-4.879678 1.840432,0 3.292516,1.029966 3.849711,2.600244 z"
id="path421" />
d="m 54.732034,43.209568 -0.151966,-2.448339 h -0.253277 c -0.03377,0.05065 -0.118196,0.10131 -0.303932,0.10131 -0.523438,0 -1.435233,-0.675404 -3.562756,-0.675404 -3.528985,0 -6.06175,2.363914 -6.06175,5.639623 0,3.123744 2.465224,5.386347 5.892899,5.386347 1.992442,0 2.735387,-0.607863 3.816033,-0.455898 0.405242,-0.658518 0.86114,-1.705395 1.080646,-2.465224 h -0.320817 c -1.148186,2.043097 -2.786041,2.498995 -4.119964,2.498995 -2.566535,0 -4.761598,-2.245719 -4.761598,-5.301922 0,-2.836696 1.75605,-4.879793 4.575862,-4.879793 1.840476,0 3.292594,1.029991 3.849803,2.600305 z" />
<path
d="m 61.147288,50.622012 c -1.165044,0 -1.435199,-0.337694 -1.435199,-1.333891 v -7.159113 c 0,-1.131275 0.371463,-1.367661 1.435199,-1.367661 v -0.320809 h -4.102982 v 0.320809 c 0.945543,0.05065 1.266352,0.303925 1.266352,1.215698 v 7.192883 c 0,1.131275 -0.219501,1.40143 -1.266352,1.452084 v 0.32081 h 4.102982 z"
id="path423" />
d="m 68.83106,45.404631 c 0,-3.039318 -2.735386,-5.217496 -5.92667,-5.217496 -3.596526,0 -6.179946,2.380799 -6.179946,5.740934 0,3.157514 2.786041,5.285036 6.095521,5.285036 3.275709,0 6.011095,-2.397684 6.011095,-5.808474 z m -1.587199,0.557208 c 0,2.397684 -1.317038,4.829139 -4.069309,4.829139 -2.718501,0 -4.862909,-2.228833 -4.862909,-5.386347 0,-2.026212 1.181957,-4.795368 4.153735,-4.795368 2.786041,0 4.778483,2.211948 4.778483,5.352576 z" />
<path
d="m 73.810786,51.061014 v -9.421663 c 0,-0.658503 0.270155,-0.878004 1.536508,-0.878004 v -0.320809 h -3.95102 v 0.320809 c 1.350776,0.03377 1.654701,0.219501 1.654701,1.249468 v 6.720111 l -7.952694,-8.290388 h -2.650899 v 0.320809 c 0.590965,0.01689 1.029967,0.151962 1.418315,0.422117 v 8.307273 c 0,0.776696 -0.337694,1.131275 -1.384545,1.131275 h -0.06754 v 0.32081 h 3.917251 v -0.32081 c -1.4352,0 -1.705355,-0.25327 -1.705355,-1.468969 v -7.243536 l 8.746275,9.151507 z"
id="path425" />
d="m 74.588877,50.622127 c -1.165072,0 -1.435233,-0.337702 -1.435233,-1.333923 v -7.159282 c 0,-1.131302 0.371472,-1.367693 1.435233,-1.367693 v -0.320817 h -4.103079 v 0.320817 c 0.945565,0.05065 1.266382,0.303931 1.266382,1.215727 v 7.193052 c 0,1.131302 -0.219506,1.401463 -1.266382,1.452119 v 0.320817 h 4.103079 z" />
<path
d="m 82.776557,46.282644 1.131275,3.073016 c 0.06754,0.168847 0.185732,0.422117 0.185732,0.692272 0,0.472772 -0.354579,0.57408 -1.317007,0.57408 h -0.439002 v 0.32081 h 4.643293 v -0.32081 c -0.844235,0 -1.198814,-0.168847 -1.536508,-1.063736 l -3.528902,-9.371009 h -1.468969 l 0.151962,0.371464 -3.073016,8.391696 c -0.54031,1.468969 -0.726042,1.6547 -1.823547,1.671585 v 0.32081 h 3.900366 v -0.32081 h -0.270156 c -0.928658,0 -1.36766,-0.168847 -1.36766,-0.624734 0,-0.236386 0.219501,-0.742927 0.337694,-1.063736 l 0.979312,-2.650898 z m -0.28704,-0.742927 h -2.921053 l 1.4352,-3.934135 z"
id="path427" />
d="m 87.252675,51.061139 v -9.421885 c 0,-0.658519 0.270161,-0.878025 1.536544,-0.878025 v -0.320817 h -3.951114 v 0.320817 c 1.350808,0.03377 1.65474,0.219506 1.65474,1.249497 v 6.72027 l -7.952882,-8.290584 h -2.65096 v 0.320817 c 0.590978,0.01689 1.029991,0.151966 1.418348,0.422127 v 8.307469 c 0,0.776715 -0.337702,1.131302 -1.384578,1.131302 h -0.06754 v 0.320817 h 3.917343 v -0.320817 c -1.435234,0 -1.705395,-0.253277 -1.705395,-1.469004 v -7.243708 l 8.746481,9.151724 z" />
<path
d="m 103.6629,51.061014 v -9.421663 c 0,-0.658503 0.27015,-0.878004 1.53651,-0.878004 v -0.320809 h -3.95102 v 0.320809 c 1.35077,0.03377 1.6547,0.219501 1.6547,1.249468 v 6.720111 l -7.952698,-8.290388 h -2.650898 v 0.320809 c 0.590965,0.01689 1.029967,0.151962 1.418315,0.422117 v 8.307273 c 0,0.776696 -0.337694,1.131275 -1.384545,1.131275 h -0.06754 v 0.32081 h 3.91725 v -0.32081 c -1.435199,0 -1.705354,-0.25327 -1.705354,-1.468969 v -7.243536 l 8.74628,9.151507 z"
id="path429" />
d="m 27.851044,62.280894 c 0,-3.039318 -2.735386,-5.217496 -5.92667,-5.217496 -3.596526,0 -6.179946,2.380799 -6.179946,5.740934 0,3.157513 2.786041,5.285036 6.095521,5.285036 3.275709,0 6.011095,-2.397684 6.011095,-5.808474 z m -1.587199,0.557208 c 0,2.397684 -1.317038,4.829138 -4.069309,4.829138 -2.718501,0 -4.862909,-2.228833 -4.862909,-5.386346 0,-2.026212 1.181957,-4.795369 4.153735,-4.795369 2.786041,0 4.778483,2.211948 4.778483,5.352577 z" />
<path
d="m 112.62867,46.282644 1.13127,3.073016 c 0.0675,0.168847 0.18574,0.422117 0.18574,0.692272 0,0.472772 -0.35458,0.57408 -1.31701,0.57408 h -0.439 v 0.32081 h 4.64329 v -0.32081 c -0.84424,0 -1.19881,-0.168847 -1.53651,-1.063736 l -3.5289,-9.371009 h -1.46897 l 0.15196,0.371464 -3.07301,8.391696 c -0.54031,1.468969 -0.72604,1.6547 -1.82355,1.671585 v 0.32081 h 3.90037 v -0.32081 h -0.27016 c -0.92866,0 -1.36766,-0.168847 -1.36766,-0.624734 0,-0.236386 0.2195,-0.742927 0.33769,-1.063736 l 0.97932,-2.650898 z m -0.28704,-0.742927 h -2.92105 l 1.4352,-3.934135 z"
id="path431" />
d="m 36.749491,60.81189 h -0.287047 c -0.05065,0.726059 -0.354587,1.080646 -0.979336,1.080646 h -3.343249 v -3.967998 h 3.208168 c 1.046877,0 1.384579,0.405242 1.401464,1.384578 h 0.287046 v -1.992442 h -7.564524 v 0.320817 c 1.181957,0.01689 1.266382,0.506553 1.266382,1.5872 v 6.618959 c 0,1.367693 -0.185736,1.587199 -1.232612,1.654739 v 0.320817 h 4.103079 v -0.320817 c -1.266382,0 -1.469003,-0.354587 -1.469003,-1.300152 V 62.5004 h 3.123743 c 0.810485,0 1.165072,0.303932 1.198842,1.283267 h 0.287047 z" />
<path
d="m 127.45339,43.209629 -0.15196,-2.448282 h -0.25327 c -0.0338,0.05065 -0.1182,0.101308 -0.30393,0.101308 -0.52342,0 -1.4352,-0.675388 -3.56267,-0.675388 -3.5289,0 -6.06161,2.363858 -6.06161,5.63949 0,3.12367 2.46517,5.38622 5.89276,5.38622 1.9924,0 2.73533,-0.60785 3.81595,-0.455887 0.40523,-0.658504 0.86112,-1.705355 1.08062,-2.465167 h -0.32081 c -1.14816,2.043049 -2.78598,2.498936 -4.11987,2.498936 -2.56647,0 -4.76148,-2.245665 -4.76148,-5.301796 0,-2.83663 1.756,-4.879678 4.57575,-4.879678 1.84043,0 3.29252,1.029966 3.84971,2.600244 z"
id="path433" />
d="m 45.715447,60.81189 h -0.287046 c -0.05066,0.726059 -0.354587,1.080646 -0.979336,1.080646 h -3.34325 v -3.967998 h 3.208169 c 1.046876,0 1.384578,0.405242 1.401463,1.384578 h 0.287047 V 57.316674 H 38.43797 v 0.320817 c 1.181956,0.01689 1.266382,0.506553 1.266382,1.5872 v 6.618959 c 0,1.367693 -0.185736,1.587199 -1.232612,1.654739 v 0.320817 h 4.103079 v -0.320817 c -1.266383,0 -1.469004,-0.354587 -1.469004,-1.300152 V 62.5004 h 3.123744 c 0.810484,0 1.165071,0.303932 1.198842,1.283267 h 0.287046 z" />
<path
d="m 133.41366,50.622012 c -1.16505,0 -1.4352,-0.337694 -1.4352,-1.333891 v -7.159113 c 0,-1.131275 0.37146,-1.367661 1.4352,-1.367661 v -0.320809 h -4.10299 v 0.320809 c 0.94555,0.05065 1.26636,0.303925 1.26636,1.215698 v 7.192883 c 0,1.131275 -0.2195,1.40143 -1.26636,1.452084 v 0.32081 h 4.10299 z"
id="path435" />
d="m 51.540777,67.498389 c -1.165072,0 -1.435234,-0.337702 -1.435234,-1.333923 v -7.159282 c 0,-1.131301 0.371472,-1.367693 1.435234,-1.367693 v -0.320817 h -4.10308 v 0.320817 c 0.945566,0.05066 1.266383,0.303932 1.266383,1.215727 v 7.193053 c 0,1.131301 -0.219506,1.401463 -1.266383,1.452118 v 0.320817 h 4.10308 z" />
<path
d="m 147.17466,45.40464 c 0,-3.039246 -2.73532,-5.217373 -5.92653,-5.217373 -3.59644,0 -6.1798,2.380743 -6.1798,5.740798 0,3.157439 2.78597,5.284912 6.09537,5.284912 3.27564,0 6.01096,-2.397628 6.01096,-5.808337 z m -1.58717,0.557195 c 0,2.397627 -1.317,4.829024 -4.06921,4.829024 -2.71843,0 -4.86279,-2.22878 -4.86279,-5.386219 0,-2.026164 1.18193,-4.795255 4.15363,-4.795255 2.78598,0 4.77837,2.211895 4.77837,5.35245 z"
id="path437" />
d="m 63.512285,60.085831 -0.151966,-2.44834 h -0.253276 c -0.03377,0.05066 -0.118196,0.101311 -0.303932,0.101311 -0.523438,0 -1.435234,-0.675404 -3.562756,-0.675404 -3.528986,0 -6.061751,2.363914 -6.061751,5.639623 0,3.123744 2.465225,5.386347 5.8929,5.386347 1.992442,0 2.735386,-0.607864 3.816032,-0.455898 0.405243,-0.658519 0.86114,-1.705395 1.080647,-2.465224 h -0.320817 c -1.148187,2.043097 -2.786042,2.498994 -4.119964,2.498994 -2.566535,0 -4.761598,-2.245718 -4.761598,-5.301921 0,-2.836697 1.75605,-4.879794 4.575862,-4.879794 1.840475,0 3.292594,1.029991 3.849802,2.600306 z" />
<path
d="m 159.97326,51.061014 v -9.421663 c 0,-0.658503 0.27016,-0.878004 1.53651,-0.878004 v -0.320809 h -3.95102 v 0.320809 c 1.35078,0.03377 1.6547,0.219501 1.6547,1.249468 v 6.720111 l -7.95269,-8.290388 h -2.6509 v 0.320809 c 0.59096,0.01689 1.02996,0.151962 1.41831,0.422117 v 8.307273 c 0,0.776696 -0.33769,1.131275 -1.38454,1.131275 h -0.0675 v 0.32081 h 3.91725 v -0.32081 c -1.4352,0 -1.70536,-0.25327 -1.70536,-1.468969 v -7.243536 l 8.74628,9.151507 z"
id="path439" />
<path
d="m 168.93903,46.282644 1.13127,3.073016 c 0.0675,0.168847 0.18573,0.422117 0.18573,0.692272 0,0.472772 -0.35458,0.57408 -1.317,0.57408 h -0.43901 v 0.32081 h 4.6433 v -0.32081 c -0.84424,0 -1.19882,-0.168847 -1.53651,-1.063736 l -3.5289,-9.371009 h -1.46897 l 0.15196,0.371464 -3.07302,8.391696 c -0.54031,1.468969 -0.72604,1.6547 -1.82354,1.671585 v 0.32081 h 3.90036 v -0.32081 h -0.27015 c -0.92866,0 -1.36766,-0.168847 -1.36766,-0.624734 0,-0.236386 0.2195,-0.742927 0.33769,-1.063736 l 0.97931,-2.650898 z m -0.28704,-0.742927 h -2.92106 l 1.4352,-3.934135 z"
id="path441" />
<path
d="m 182.413,48.477655 h -0.30393 c -1.06373,1.468969 -1.36766,1.857317 -2.36386,1.857317 h -2.48205 c -0.48965,0 -0.67538,-0.168847 -0.67538,-0.624734 v -7.783847 c 0,-1.046851 0.28704,-1.165044 1.38454,-1.165044 h 0.62474 v -0.320809 h -4.98099 v 0.320809 h 0.23638 c 1.06374,0 1.3339,0.371463 1.3339,1.266352 v 7.479923 c 0,0.86112 -0.28704,1.11439 -1.06374,1.11439 h -0.5572 v 0.32081 h 7.54747 z"
id="path443" />
<path
d="m 17.36535,66.27413 c 0,0.979312 -0.422118,1.232583 -1.333892,1.232583 h -0.287039 v 0.320809 h 5.403104 c 4.271829,0 6.247339,-3.056131 6.247339,-5.60572 0,-2.785976 -1.97551,-5.048526 -6.433071,-5.048526 -0.878004,0 -1.907971,0.01689 -2.83663,0.05065 -0.928658,0.03377 -1.756009,0.06754 -2.380742,0.101308 v 0.32081 h 0.337694 c 0.996197,0 1.283237,0.270155 1.283237,1.36766 z m 1.40143,-8.712506 c 0.202616,-0.01688 0.658503,-0.06754 1.350776,-0.06754 2.363858,0 3.562672,0.590965 4.339368,1.367661 0.996197,0.996198 1.350776,2.380743 1.350776,3.630211 0,1.739124 -0.776696,3.039246 -1.40143,3.647095 -1.046851,1.046852 -1.992395,1.367661 -4.254945,1.367661 -1.333891,0 -1.384545,-0.236386 -1.384545,-0.928659 z"
id="path445" />
<path
d="m 36.157993,60.820371 h -0.320809 c -0.08442,0.979313 -0.371464,1.266353 -0.979313,1.266353 H 31.83551 v -4.153636 h 3.562672 c 0.607849,0 1.029966,0.303924 1.249468,1.739124 h 0.303924 L 36.816497,57.325238 H 28.71184 v 0.32081 h 0.371464 c 1.131275,0 1.350776,0.405233 1.350776,1.350776 v 7.125343 c 0,1.013083 -0.236386,1.384546 -1.587162,1.384546 h -0.472772 v 0.320809 h 8.965776 l 0.270155,-2.51582 h -0.303924 c -0.422118,1.452084 -0.776696,1.907971 -1.958625,1.907971 h -2.600244 c -0.624734,0 -0.911774,-0.151962 -0.911774,-0.928658 v -3.596442 h 2.853514 c 0.692273,0 1.013082,0.135078 1.14816,1.333892 h 0.320809 z"
id="path447" />
<path
d="m 47.53828,65.362356 h -0.303925 c -1.063736,1.468969 -1.367661,1.857317 -2.363858,1.857317 h -2.482051 c -0.489656,0 -0.675388,-0.168847 -0.675388,-0.624734 v -7.783847 c 0,-1.046851 0.28704,-1.165044 1.384545,-1.165044 h 0.624734 v -0.32081 h -4.980986 v 0.32081 h 0.236385 c 1.063737,0 1.333892,0.371463 1.333892,1.266352 v 7.479923 c 0,0.861119 -0.28704,1.11439 -1.063736,1.11439 h -0.557195 v 0.320809 h 7.547461 z"
id="path449" />
<path
d="m 54.410318,66.122167 c 0,1.063737 -0.270155,1.384546 -1.6547,1.384546 H 52.36727 v 0.320809 h 6.1798 c 2.718437,0 3.647095,-1.874202 3.647095,-3.208093 0,-1.317007 -0.928658,-2.346973 -2.51582,-2.819745 v -0.03377 c 1.131275,-0.202617 1.924856,-1.097506 1.924856,-2.059934 0,-0.810465 -0.337694,-1.384545 -1.029967,-1.874202 -0.607849,-0.439002 -1.907971,-0.658503 -3.393825,-0.658503 -0.320809,0 -1.604046,0.01689 -2.532705,0.05065 -0.489656,0.01688 -1.654701,0.08442 -2.127472,0.101308 v 0.32081 h 0.590964 c 1.181929,0 1.300122,0.506541 1.300122,1.468969 z m 1.40143,-8.577427 c 0.422118,-0.01688 1.114391,-0.05065 1.485854,-0.05065 2.076818,0 2.785976,1.080621 2.785976,2.26255 0,1.317007 -0.810466,1.958626 -2.431397,1.958626 h -1.840433 z m 0,4.49133 h 1.823548 c 1.97551,0 2.971707,1.333891 2.971707,2.634013 0,1.317007 -0.641618,2.701552 -2.870399,2.701552 -1.418315,0 -1.924856,-0.455887 -1.924856,-1.739124 z"
id="path451" />
<path
d="m 67.951819,67.506713 c -1.165044,0 -1.435199,-0.337694 -1.435199,-1.333891 v -7.159114 c 0,-1.131274 0.371463,-1.36766 1.435199,-1.36766 v -0.32081 h -4.102982 v 0.32081 c 0.945543,0.05065 1.266353,0.303924 1.266353,1.215698 v 7.192883 c 0,1.131275 -0.219502,1.40143 -1.266353,1.452084 v 0.320809 h 4.102982 z"
id="path453" />
<path
d="m 75.127789,57.933088 h 2.937938 c 0.675388,0 0.979313,0.388348 1.232584,1.874201 h 0.303924 L 79.33208,57.071968 h -0.320809 c -0.03377,0.202616 -0.28704,0.25327 -0.523426,0.25327 h -8.121541 c -0.118193,0 -0.236386,-0.01688 -0.337694,-0.05065 -0.101308,-0.03377 -0.168847,-0.101308 -0.185732,-0.202616 h -0.320809 l -0.270155,2.735321 h 0.303924 c 0.253271,-1.485853 0.557195,-1.874201 1.232583,-1.874201 h 2.937938 v 8.341042 c 0,0.911774 -0.303924,1.232583 -1.333891,1.232583 h -0.624734 v 0.320809 h 5.318681 v -0.320809 h -0.624734 c -1.029967,0 -1.333892,-0.320809 -1.333892,-1.232583 z"
id="path455" />
<path
d="m 91.353956,60.094329 -0.151962,-2.448281 h -0.25327 c -0.03377,0.05065 -0.118193,0.101308 -0.303925,0.101308 -0.523426,0 -1.4352,-0.675388 -3.562672,-0.675388 -3.528902,0 -6.061607,2.363858 -6.061607,5.63949 0,3.12367 2.465166,5.386219 5.89276,5.386219 1.992395,0 2.735322,-0.607849 3.815943,-0.455886 0.405232,-0.658504 0.861119,-1.705355 1.08062,-2.465167 h -0.320809 c -1.14816,2.043049 -2.785976,2.498936 -4.119867,2.498936 -2.566474,0 -4.761486,-2.245665 -4.761486,-5.301796 0,-2.83663 1.756009,-4.879679 4.575754,-4.879679 1.840433,0 3.292517,1.029967 3.849712,2.600244 z"
id="path457" />
<path
d="m 105.45265,62.28934 c 0,-3.039246 -2.73532,-5.217372 -5.926531,-5.217372 -3.596441,0 -6.1798,2.380743 -6.1798,5.740798 0,3.157439 2.785975,5.284911 6.095376,5.284911 3.275635,0 6.010955,-2.397627 6.010955,-5.808337 z m -1.58716,0.557196 c 0,2.397627 -1.31701,4.829024 -4.069216,4.829024 -2.718437,0 -4.862794,-2.228781 -4.862794,-5.38622 0,-2.026164 1.181929,-4.795255 4.153637,-4.795255 2.785973,0 4.778373,2.211896 4.778373,5.352451 z"
id="path459" />
<path
d="m 111.21033,67.506713 c -1.16504,0 -1.4352,-0.337694 -1.4352,-1.333891 v -7.159114 c 0,-1.131274 0.37147,-1.36766 1.4352,-1.36766 v -0.32081 h -4.10298 v 0.32081 c 0.94554,0.05065 1.26635,0.303924 1.26635,1.215698 v 7.192883 c 0,1.131275 -0.2195,1.40143 -1.26635,1.452084 v 0.320809 h 4.10298 z"
id="path461" />
<path
d="m 123.87383,67.945715 v -9.421663 c 0,-0.658503 0.27015,-0.878004 1.53651,-0.878004 v -0.32081 h -3.95102 v 0.32081 c 1.35077,0.03377 1.6547,0.219501 1.6547,1.249468 v 6.72011 l -7.9527,-8.290388 h -2.6509 v 0.32081 c 0.59097,0.01688 1.02997,0.151962 1.41832,0.422117 v 8.307273 c 0,0.776696 -0.33769,1.131275 -1.38455,1.131275 h -0.0675 v 0.320809 h 3.91726 v -0.320809 c -1.4352,0 -1.70536,-0.253271 -1.70536,-1.468969 v -7.243537 l 8.74628,9.151508 z"
id="path463" />
d="m 72.444469,60.81189 h -0.320817 c -0.08443,0.979336 -0.371472,1.266382 -0.979335,1.266382 h -3.022433 v -4.153734 h 3.562756 c 0.607863,0 1.029991,0.303932 1.249497,1.739165 h 0.303932 L 73.102988,57.316674 H 64.99814 v 0.320817 h 0.371473 c 1.131301,0 1.350808,0.405243 1.350808,1.350808 v 7.125512 c 0,1.013106 -0.236392,1.384578 -1.5872,1.384578 h -0.472783 v 0.320817 h 8.965988 l 0.270162,-2.51588 h -0.303932 c -0.422127,1.452119 -0.776715,1.908017 -1.958671,1.908017 h -2.600306 c -0.624748,0 -0.911795,-0.151966 -0.911795,-0.928681 v -3.596526 h 2.853582 c 0.692289,0 1.013106,0.135081 1.148186,1.333923 h 0.320817 z" />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 7.3 KiB

View File

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 19 KiB

View File

Before

Width:  |  Height:  |  Size: 66 KiB

After

Width:  |  Height:  |  Size: 66 KiB

View File

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 18 KiB

View File

Before

Width:  |  Height:  |  Size: 756 B

After

Width:  |  Height:  |  Size: 756 B

View File

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 340 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 82 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 80 KiB

View File

@@ -3,6 +3,7 @@ $bg: #1d1f31;
$active-bg: #11131f;
$hover-bg: #12131e;
$fg: #fff;
$nav-bg: $bg;
$title-fg: #4a68b9;
$taproot: #eba814;
@@ -64,7 +65,7 @@ $dropdown-link-active-bg: $active-bg;
--active-bg: #{$active-bg};
--hover-bg: #{$hover-bg};
--fg: #{$fg};
--color-fg: #ffffff;
--nav-bg: #{$nav-bg};
--title-fg: #{$title-fg};
--primary: #{$primary};
@@ -72,7 +73,11 @@ $dropdown-link-active-bg: $active-bg;
--tertiary: #{$tertiary};
--success: #{$success};
--info: #{$info};
--link-color: #{$link-color};
--link-hover-color: #{$link-hover-color};
--icon: #f1f1f1;
--skeleton-bg: #2e324e;
--skeleton-bg-light: #5d6182;
--box-bg: #24273e;
--stat-box-bg: #181b2d;
@@ -81,6 +86,7 @@ $dropdown-link-active-bg: $active-bg;
--transparent-fg: #ffffff66;
--fade-out-box-bg-start: rgba(36, 39, 62, 0);
--fade-out-box-bg-end: rgba(36, 39, 62, 1);
--opacity: 0.57;
--testnet: #1d486f;
--signet: #6f1d5d;
@@ -98,10 +104,15 @@ $dropdown-link-active-bg: $active-bg;
--green: #3bcc49;
--red: #dc3545;
--yellow: #ffd800;
--yellow: #fff000;
--grey: #6c757d;
--tooltip-grey: #b1b1b1;
--orange: #b86d12;
--search-button: #4d2d77;
--search-button-border: #472a6e;
--search-button-focus: #533180;
--search-button-shadow: #7c58ab80;
}
html, body {
@@ -171,13 +182,13 @@ main {
}
.form-control {
color: #fff;
color: var(--fg);
background-color: var(--secondary);
border: 1px solid rgba(17, 19, 31, 0.2);
}
.form-control:focus {
color: #fff;
color: var(--fg);
background-color: var(--secondary);
}
@@ -188,25 +199,25 @@ main {
.btn-purple:not(:disabled):not(.disabled):active, .btn-purple:not(:disabled):not(.disabled).active, .show > .btn-purple.dropdown-toggle {
color: #fff;
background-color: #4d2d77;
border-color: #472a6e;
background-color: var(--search-button);
border-color: var(--search-button-border);
}
.btn-purple:focus, .btn-purple.focus {
color: #fff;
background-color: #533180;
border-color: #4d2d77;
box-shadow: 0 0 0 0.2rem rgb(124 88 171 / 50%);
background-color: var(--search-button-focus);
border-color: var(--search-button);
box-shadow: 0 0 0 0.2rem var(--search-button-shadow);
}
.btn-purple:hover {
color: #fff;
background-color: #533180;
border-color: #4d2d77;
background-color: var(--search-button-focus);
border-color: var(--search-button);
}
.form-control.form-control-secondary {
color: var(--fg);
color: #fff;
background-color: var(--secondary);
border: 1px solid var(--secondary);
}
@@ -229,11 +240,11 @@ main {
position: relative;
animation: progress 2s ease-in-out infinite;
background: #2e324e no-repeat;
background: var(--skeleton-bg) no-repeat;
background-image: linear-gradient(
90deg,
rgba(255, 255, 255, 0),
#5d6182,
var(--skeleton-bg-light),
rgba(255, 255, 255, 0)
);
background-size: 200px 100%;
@@ -271,14 +282,14 @@ main {
.progress-text {
span {
color: var(--fg) !important;
color: #fff !important;
}
}
.block-size, .blocks-container {
.symbol {
font-size: 16px;
color: var(--fg) !important;
color: #fff !important;
}
}
@@ -418,18 +429,18 @@ html:lang(ru) .card-title {
font-size: 12px;
font-weight: 700;
margin-bottom: 2px;
color: var(--fg);
color: #fff;
.total-value {
float: right;
}
}
.active {
color: yellow !important;
color: var(--yellow) !important;
.value,
.total-partial {
color: yellow !important;
color: var(--yellow) !important;
.symbol {
color: yellow !important;
color: var(--yellow) !important;
}
}
}
@@ -477,7 +488,7 @@ html:lang(ru) .card-title {
.total-label {
width: 100%;
text-align: left;
color: var(--fg);
color: #fff;
margin-top: 5px;
font-size: 14px;
span {
@@ -728,19 +739,19 @@ h1, h2, h3 {
}
.progress-mempool {
background: repeating-linear-gradient(to right, $secondary, $secondary 0%, $primary 0%, var(--mainnet-alt) 100%);
background: repeating-linear-gradient(to right, var(--secondary), var(--secondary) 0%, var(--primary) 0%, var(--mainnet-alt) 100%);
}
.progress-mempool.testnet {
background: repeating-linear-gradient(to right, $secondary, $secondary 0%, var(--testnet) 0%, var(--testnet-alt) 100%);
background: repeating-linear-gradient(to right, var(--secondary), var(--secondary) 0%, var(--testnet) 0%, var(--testnet-alt) 100%);
}
.progress-mempool.signet {
background: repeating-linear-gradient(to right, $secondary, $secondary 0%, var(--signet) 0%, var(--signet-alt) 100%);
background: repeating-linear-gradient(to right, var(--secondary), var(--secondary) 0%, var(--signet) 0%, var(--signet-alt) 100%);
}
.progress-mempool.liquid {
background: repeating-linear-gradient(to right, $secondary, $secondary 0%, var(--liquid) 0%, var(--testnet-alt) 100%);
background: repeating-linear-gradient(to right, var(--secondary), var(--secondary) 0%, var(--liquid) 0%, var(--testnet-alt) 100%);
}
.progress-dark {
@@ -752,11 +763,11 @@ h1, h2, h3 {
}
.progress-light {
background-color: #2e324e;
background-color: var(--skeleton-bg);
}
.progress.progress-health {
background: repeating-linear-gradient(to right, $secondary, $secondary 0%, $primary 0%, $success 100%);
background: repeating-linear-gradient(to right, var(--secondary), var(--secondary) 0%, var(--primary) 0%, $success 100%);
justify-content: flex-end;
}
@@ -769,7 +780,7 @@ h1, h2, h3 {
}
.alert-mempool {
color: var(--fg);
color: #fff;
background-color: var(--tertiary);
border-color: var(--alert-bg);
width: 100%;
@@ -1137,7 +1148,7 @@ th {
display: block;
width: 100%;
padding: 1rem 2rem;
color: var(--fg);
color: #fff;
font-weight: bold;
&:focus, &:hover, &:active {
text-decoration: none;
@@ -1221,7 +1232,7 @@ th {
}
.blink-bg {
color: var(--fg);
color: #fff;
background: repeating-linear-gradient($taproot-dark, $taproot-dark 0.163525%, $taproot-light 100%) !important;
animation: shadowyBackground 1s infinite;
box-shadow: -10px -15px 75px rgba($taproot, 1);
@@ -1244,7 +1255,7 @@ app-master-page, app-liquid-master-page {
display: flex;
flex-direction: column;
min-height: 100vh;
padding-bottom: 60px;
padding-bottom: 56px;
@media (min-width: 992px) {
padding-bottom: 0px;
}
@@ -1268,12 +1279,36 @@ app-global-footer {
.dropdown-menu {
background-color: var(--bg);
color: var(--fg);
.dropdown-item:hover, .dropdown-item:focus {
background-color: var(--active-bg);
color: var(--fg);
}
}
.btn-secondary {
background-color: var(--secondary);
border-color: var(--secondary);
}
a {
color: var(--link-color);
&:hover {
color: var(--link-hover-color);
}
}
.badge-primary {
color: var(--fg);
background-color: var(--primary);
}
.badge-info {
background-color: var(--info);
}
.btn-primary {
color: var(--fg);
background-color: var(--primary);
border-color: var(--primary);
}

View File

@@ -0,0 +1,139 @@
/* Theme */
$bg: #11131f;
$active-bg: #000000;
$hover-bg: #12131e;
$fg: #d2d2d2;
$nav-bg: #111e60;
$title-fg: #2055e3;
$taproot: #eba814;
$taproot-light: #d5a90a;
$taproot-dark: #9d7c05;
/* Bootstrap */
$body-bg: $bg;
$body-color: $fg;
$gray-800: $bg;
$gray-700: $fg;
$nav-tabs-link-active-bg: $active-bg;
$primary: #007cfa;
$secondary: #272f4e;
$tertiary: #ff9900;
$success: #0aab2f;
$info: #00ddff;
$h5-font-size: 1.15rem !default;
$pagination-bg: $body-bg;
$pagination-border-color: $gray-800;
$pagination-disabled-bg: $fg;
$pagination-disabled-border-color: $bg;
$pagination-active-color: $fg;
$pagination-active-bg: $tertiary;
$pagination-hover-bg: $hover-bg;
$pagination-hover-border-color: $bg;
$pagination-disabled-bg: $bg;
$custom-select-indicator-color: $fg;
.input-group-text {
background-color: #1c2031 !important;
border: 1px solid #20263e !important;
}
$link-color: $info;
$link-decoration: none !default;
$link-hover-color: darken($link-color, 15%) !default;
$link-hover-decoration: underline !default;
$dropdown-bg: $bg;
$dropdown-link-color: $fg;
$dropdown-link-hover-color: $fg;
$dropdown-link-hover-bg: $active-bg;
$dropdown-link-active-color: $fg;
$dropdown-link-active-bg: $active-bg;
:root {
--bg: #{$bg};
--active-bg: #{$active-bg};
--hover-bg: #{$hover-bg};
--fg: #{$fg};
--nav-bg: #{$nav-bg};
--title-fg: #{$title-fg};
--primary: #{$primary};
--secondary: #{$secondary};
--tertiary: #{$tertiary};
--success: #{$success};
--info: #{$info};
--link-color: #{$link-color};
--link-hover-color: #{$link-hover-color};
--icon: #d2d2d2;
--skeleton-bg: #2e324e;
--skeleton-bg-light: #5d6182;
--box-bg: #171c2a;
--stat-box-bg: #0b1018;
--alert-bg: #3a1c61;
--transparent-fg: #ffffffbb;
--fade-out-box-bg-start: rgba(23, 28, 42, 0);
--fade-out-box-bg-end: rgba(23, 28, 42, 1);
--opacity: 0.9;
--testnet: #1d486f;
--signet: #6f1d5d;
--liquid: #116761;
--liquidtestnet: #494a4a;
--mainnet-alt: #9339f4;
--testnet-alt: #183550;
--signet-alt: #471850;
--liquidtestnet-alt: #272e46;
--taproot: #eba814;
--taproot-light: #d5a90a;
--taproot-dark: #9d7c05;
--green: #83fd00;
--red: #ff3d00;
--yellow: #fff000;
--grey: #7e7e7e;
--tooltip-grey: #b1b1b1;
--orange: #ff9f00;
--search-button: #d5a90a;
--search-button-border: #d5a90a;
--search-button-focus: #eba814;
--search-button-shadow: #eba814;
}
.navbar {
--secondary: #041437;
}
.nav-item.active, .btn-purple {
--icon: white;
}
.btn-purple:not(:disabled):not(.disabled):active, .btn-purple:not(:disabled):not(.disabled).active, .show > .btn-purple.dropdown-toggle {
color: #fff;
background-color: var(--search-button);
border-color: var(--search-button-border);
}
.btn-purple:focus, .btn-purple.focus {
color: #fff;
background-color: var(--search-button-focus);
border-color: var(--search-button);
box-shadow: 0 0 0 0.2rem var(--search-button-shadow);
}
.btn-purple:hover {
color: #fff;
background-color: var(--search-button-focus);
border-color: var(--search-button);
}

View File

@@ -3,6 +3,7 @@ $bg: #11131f;
$active-bg: #000000;
$hover-bg: #12131e;
$fg: #fff;
$nav-bg: $bg;
$title-fg: #2055e3;
$taproot: #eba814;
@@ -21,7 +22,7 @@ $primary: #007cfa;
$secondary: #272f4e;
$tertiary: #6225b2;
$success: #0aab2f;
$info: #10e0ff;
$info: #00ddff;
$h5-font-size: 1.15rem !default;
@@ -61,7 +62,7 @@ $dropdown-link-active-bg: $active-bg;
--active-bg: #{$active-bg};
--hover-bg: #{$hover-bg};
--fg: #{$fg};
--color-fg: #fff;
--nav-bg: #{$nav-bg};
--title-fg: #{$title-fg};
--primary: #{$primary};
@@ -69,15 +70,19 @@ $dropdown-link-active-bg: $active-bg;
--tertiary: #{$tertiary};
--success: #{$success};
--info: #{$info};
--link-color: #{$link-color};
--link-hover-color: #{$link-hover-color};
--icon: #f1f1f1;
--skeleton-bg: #2e324e;
--skeleton-bg-light: #5d6182;
--box-bg: #171c2a;
--stat-box-bg: #0b1018;
--alert-bg: #3a1c61;
--navbar-bg: #212121;
--transparent-fg: #ffffffbb;
--fade-out-box-bg-start: rgba(23, 28, 42, 0);
--fade-out-box-bg-end: rgba(23, 28, 42, 1);
--opacity: 0.9;
--testnet: #1d486f;
--signet: #6f1d5d;
@@ -95,8 +100,13 @@ $dropdown-link-active-bg: $active-bg;
--green: #83fd00;
--red: #ff3d00;
--yellow: #ffcc00;
--yellow: #fff000;
--grey: #7e7e7e;
--tooltip-grey: #b1b1b1;
--orange: #ff9f00;
--search-button: #4d2d77;
--search-button-border: #472a6e;
--search-button-focus: #533180;
--search-button-shadow: #7c58ab80;
}

View File

@@ -3,6 +3,7 @@ $bg: #11131f;
$active-bg: #000000;
$hover-bg: #12131e;
$fg: #fff;
$nav-bg: $bg;
$title-fg: #2055e3;
$taproot: #eba814;
@@ -21,7 +22,7 @@ $primary: #007cfa;
$secondary: #272f4e;
$tertiary: #6225b2;
$success: #0aab2f;
$info: #10e0ff;
$info: #00ddff;
$h5-font-size: 1.15rem !default;
@@ -61,7 +62,7 @@ $dropdown-link-active-bg: $active-bg;
--active-bg: #{$active-bg};
--hover-bg: #{$hover-bg};
--fg: #{$fg};
--color-fg: #fff;
--nav-bg: #{$nav-bg};
--title-fg: #{$title-fg};
--primary: #{$primary};
@@ -69,15 +70,19 @@ $dropdown-link-active-bg: $active-bg;
--tertiary: #{$tertiary};
--success: #{$success};
--info: #{$info};
--link-color: #{$link-color};
--link-hover-color: #{$link-hover-color};
--icon: #f1f1f1;
--skeleton-bg: #2e324e;
--skeleton-bg-light: #5d6182;
--box-bg: #171c2a;
--stat-box-bg: #0b1018;
--alert-bg: #3a1c61;
--navbar-bg: #212121;
--transparent-fg: #ffffffbb;
--fade-out-box-bg-start: rgba(23, 28, 42, 0);
--fade-out-box-bg-end: rgba(23, 28, 42, 1);
--opacity: 0.57;
--testnet: #1d486f;
--signet: #6f1d5d;
@@ -95,8 +100,13 @@ $dropdown-link-active-bg: $active-bg;
--green: #83fd00;
--red: #ff3d00;
--yellow: #ffcc00;
--yellow: #fff000;
--grey: #7e7e7e;
--tooltip-grey: #b1b1b1;
--orange: #ff9f00;
--search-button: #4d2d77;
--search-button-border: #472a6e;
--search-button-focus: #533180;
--search-button-shadow: #7c58ab80;
}