From 2feee1d2fd6609ba2104baf8d9dce997cde01871 Mon Sep 17 00:00:00 2001 From: jramos0 Date: Mon, 20 Jul 2026 23:18:18 -0600 Subject: [PATCH 1/7] Fix: aligned 'why is this block empty' --- frontend/src/app/components/block/block.component.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/app/components/block/block.component.html b/frontend/src/app/components/block/block.component.html index 7e5c7af72..2864cb4a5 100644 --- a/frontend/src/app/components/block/block.component.html +++ b/frontend/src/app/components/block/block.component.html @@ -110,7 +110,7 @@ -
+
Date: Sat, 1 Aug 2026 17:07:13 +0000 Subject: [PATCH 2/7] fix scheduleSingleTask --- backend/src/indexer.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/backend/src/indexer.ts b/backend/src/indexer.ts index 46256cc29..427b20d18 100644 --- a/backend/src/indexer.ts +++ b/backend/src/indexer.ts @@ -113,12 +113,11 @@ class Indexer { } } this.tasksScheduled[task] = setTimeout(async () => { + delete this.tasksScheduled[task]; try { await this.runSingleTask(task); } catch (e) { logger.err(`Unexpected error in scheduled task ${task}: ` + (e instanceof Error ? e.message : e)); - } finally { - clearTimeout(this.tasksScheduled[task]); } }, timeout); } From 31c6b72f42f90f848e6cfbd189fc0d20096ab52d Mon Sep 17 00:00:00 2001 From: nymkappa Date: Sat, 1 Aug 2026 22:06:07 +0200 Subject: [PATCH 3/7] fix code indentation --- backend/src/indexer.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/backend/src/indexer.ts b/backend/src/indexer.ts index 427b20d18..ff10d701e 100644 --- a/backend/src/indexer.ts +++ b/backend/src/indexer.ts @@ -143,7 +143,8 @@ class Indexer { latestPriceId = await PricesRepository.$getLatestPriceId(); } catch (e) { logger.debug('failed to fetch latest price id from db: ' + (e instanceof Error ? e.message : e)); - } if (priceUpdater.historyInserted === false || latestPriceId === null) { + } + if (priceUpdater.historyInserted === false || latestPriceId === null) { logger.debug(`Blocks prices indexer is waiting for the price updater to complete`, logger.tags.mining); this.scheduleSingleTask(task, 10000); } else { From 35399957178c586e11f0e25037c449099cf1c279 Mon Sep 17 00:00:00 2001 From: natsoni Date: Tue, 4 Aug 2026 10:41:21 +0200 Subject: [PATCH 4/7] Fix page jump on mobile when scrolling to footer --- .../accelerations-list/accelerations-list.component.scss | 4 ++++ .../custom-dashboard/custom-dashboard.component.scss | 2 ++ .../federation-addresses-list.component.scss | 4 ++++ .../recent-pegs-list/recent-pegs-list.component.scss | 4 ++++ .../recent-transactions-list.component.scss | 2 ++ frontend/src/app/dashboard/dashboard.component.scss | 1 + 6 files changed, 17 insertions(+) diff --git a/frontend/src/app/components/acceleration/accelerations-list/accelerations-list.component.scss b/frontend/src/app/components/acceleration/accelerations-list/accelerations-list.component.scss index 06e1ca48c..7a7d3f8d0 100644 --- a/frontend/src/app/components/acceleration/accelerations-list/accelerations-list.component.scss +++ b/frontend/src/app/components/acceleration/accelerations-list/accelerations-list.component.scss @@ -97,6 +97,10 @@ tr, td, th { } .widget { + .acceleration-list { + overflow-anchor: none; + } + .txid { width: 30%; overflow: hidden; diff --git a/frontend/src/app/components/custom-dashboard/custom-dashboard.component.scss b/frontend/src/app/components/custom-dashboard/custom-dashboard.component.scss index 4a9ffe94a..d1079621e 100644 --- a/frontend/src/app/components/custom-dashboard/custom-dashboard.component.scss +++ b/frontend/src/app/components/custom-dashboard/custom-dashboard.component.scss @@ -135,6 +135,7 @@ } .latest-transactions { + overflow-anchor: none; width: 100%; text-align: left; table-layout:fixed; @@ -223,6 +224,7 @@ } .lastest-replacements-table { + overflow-anchor: none; width: 100%; text-align: left; table-layout:fixed; diff --git a/frontend/src/app/components/liquid-reserves-audit/federation-addresses-list/federation-addresses-list.component.scss b/frontend/src/app/components/liquid-reserves-audit/federation-addresses-list/federation-addresses-list.component.scss index 33d7c8f78..ddbe1ad61 100644 --- a/frontend/src/app/components/liquid-reserves-audit/federation-addresses-list/federation-addresses-list.component.scss +++ b/frontend/src/app/components/liquid-reserves-audit/federation-addresses-list/federation-addresses-list.component.scss @@ -10,6 +10,10 @@ } } +.widget table { + overflow-anchor: none; +} + tr, td, th { border: 0px; padding-top: 0.65rem; diff --git a/frontend/src/app/components/liquid-reserves-audit/recent-pegs-list/recent-pegs-list.component.scss b/frontend/src/app/components/liquid-reserves-audit/recent-pegs-list/recent-pegs-list.component.scss index 62dd5c336..9baf129e4 100644 --- a/frontend/src/app/components/liquid-reserves-audit/recent-pegs-list/recent-pegs-list.component.scss +++ b/frontend/src/app/components/liquid-reserves-audit/recent-pegs-list/recent-pegs-list.component.scss @@ -4,6 +4,10 @@ margin-top: 13px; } +.widget table { + overflow-anchor: none; +} + tr, td, th { border: 0px; padding-top: 0.65rem; diff --git a/frontend/src/app/components/recent-transactions-list/recent-transactions-list.component.scss b/frontend/src/app/components/recent-transactions-list/recent-transactions-list.component.scss index 41622c43e..936d251a3 100644 --- a/frontend/src/app/components/recent-transactions-list/recent-transactions-list.component.scss +++ b/frontend/src/app/components/recent-transactions-list/recent-transactions-list.component.scss @@ -93,6 +93,8 @@ } .widget .latest-transactions { + overflow-anchor: none; + .table-cell-satoshis { @media (min-width: 768px) { display: none; diff --git a/frontend/src/app/dashboard/dashboard.component.scss b/frontend/src/app/dashboard/dashboard.component.scss index 0ea68475c..6c32feb4b 100644 --- a/frontend/src/app/dashboard/dashboard.component.scss +++ b/frontend/src/app/dashboard/dashboard.component.scss @@ -180,6 +180,7 @@ } .lastest-replacements-table { + overflow-anchor: none; width: 100%; text-align: left; table-layout:fixed; From e31299c4e91ff6d0dc1a51eb76aad282122e7069 Mon Sep 17 00:00:00 2001 From: Felipe Knorr Kuhn Date: Wed, 5 Aug 2026 05:54:08 +0900 Subject: [PATCH 5/7] Only sync svgs from the mining pool logos repo --- frontend/sync-assets.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/sync-assets.js b/frontend/sync-assets.js index f0797b563..a77b99795 100644 --- a/frontend/sync-assets.js +++ b/frontend/sync-assets.js @@ -230,7 +230,7 @@ const downloadMiningPoolLogos = async () => { const poolLogos = await fetchGitHubContents('/repos/mempool/mining-pool-logos/contents/', !!config.githubToken); let downloadedCount = 0; - const validFiles = poolLogos.filter(item => item.type === 'file' && item.download_url); + const validFiles = poolLogos.filter(item => item.type === 'file' && item.download_url && item.name.toLowerCase().endsWith('.svg')); for (const poolLogo of validFiles) { if (config.verbose) { From b7e81e67e2c92d9254b4f57177b3dcc1feeac42f Mon Sep 17 00:00:00 2001 From: mononaut Date: Thu, 6 Aug 2026 11:36:00 +0000 Subject: [PATCH 6/7] optimize ln nodes sockets query --- backend/src/repositories/NodesSocketsRepository.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/backend/src/repositories/NodesSocketsRepository.ts b/backend/src/repositories/NodesSocketsRepository.ts index 8ddfafe68..9e2d28549 100644 --- a/backend/src/repositories/NodesSocketsRepository.ts +++ b/backend/src/repositories/NodesSocketsRepository.ts @@ -30,12 +30,13 @@ class NodesSocketsRepository { return 0; } try { + const placeholders = addresses.map(() => '?').join(','); const query = ` DELETE FROM nodes_sockets WHERE public_key = ? - AND socket NOT IN (${addresses.map(id => `"${id}"`).join(',')}) + AND socket NOT IN (${placeholders}) `; - const [result] = await DB.query(query, [publicKey]); + const [result] = await DB.query(query, [publicKey, ...addresses]); return result.affectedRows; } catch (e) { logger.err(`Cannot delete unused sockets for ${publicKey} from db. Reason: ` + (e instanceof Error ? e.message : e)); From 71f07e310aa9b8f2f1f8e8f93787192028ca0422 Mon Sep 17 00:00:00 2001 From: mononaut Date: Sat, 8 Aug 2026 01:58:41 +0000 Subject: [PATCH 7/7] remove matomo --- .../about/about-sponsors.component.html | 4 +- .../about/about-sponsors.component.ts | 14 --- .../app/components/about/about.component.ts | 12 --- .../accelerate-checkout.component.ts | 3 - .../privacy-policy.component.html | 2 +- .../components/tracker/tracker.component.ts | 2 - .../transaction/transaction.component.ts | 3 - .../src/app/services/enterprise.service.ts | 102 ------------------ 8 files changed, 3 insertions(+), 139 deletions(-) diff --git a/frontend/src/app/components/about/about-sponsors.component.html b/frontend/src/app/components/about/about-sponsors.component.html index 9471fc78f..02189acb6 100644 --- a/frontend/src/app/components/about/about-sponsors.component.html +++ b/frontend/src/app/components/about/about-sponsors.component.html @@ -1,14 +1,14 @@

If you're an individual...

- Become a Community Sponsor + Become a Community Sponsor

If you're a business...

- Become an Enterprise Sponsor + Become an Enterprise Sponsor diff --git a/frontend/src/app/components/about/about-sponsors.component.ts b/frontend/src/app/components/about/about-sponsors.component.ts index be86a9d93..673bb207c 100644 --- a/frontend/src/app/components/about/about-sponsors.component.ts +++ b/frontend/src/app/components/about/about-sponsors.component.ts @@ -1,5 +1,4 @@ import { Component, Input } from '@angular/core'; -import { EnterpriseService } from '@app/services/enterprise.service'; @Component({ selector: 'app-about-sponsors', @@ -10,17 +9,4 @@ import { EnterpriseService } from '@app/services/enterprise.service'; export class AboutSponsorsComponent { @Input() host = 'https://mempool.space'; @Input() context = 'about'; - - constructor(private enterpriseService: EnterpriseService) { - } - - onSponsorClick(e): boolean { - this.enterpriseService.goal(5); - return true; - } - - onEnterpriseClick(e): boolean { - this.enterpriseService.goal(6); - return true; - } } diff --git a/frontend/src/app/components/about/about.component.ts b/frontend/src/app/components/about/about.component.ts index 75b4cbbe0..211f21622 100644 --- a/frontend/src/app/components/about/about.component.ts +++ b/frontend/src/app/components/about/about.component.ts @@ -10,7 +10,6 @@ import { Router, ActivatedRoute } from '@angular/router'; import { map, share, tap } from 'rxjs/operators'; import { ITranslators } from '@interfaces/node-api.interface'; import { DOCUMENT } from '@angular/common'; -import { EnterpriseService } from '@app/services/enterprise.service'; import { ThemeService } from '../../services/theme.service'; @Component({ @@ -40,7 +39,6 @@ export class AboutComponent implements OnInit { private seoService: SeoService, private ogService: OpenGraphService, public stateService: StateService, - private enterpriseService: EnterpriseService, private apiService: ApiService, private router: Router, private route: ActivatedRoute, @@ -141,16 +139,6 @@ export class AboutComponent implements OnInit { this.promoVideo.nativeElement.muted = false; } - onSponsorClick(e): boolean { - this.enterpriseService.goal(5); - return true; - } - - onEnterpriseClick(e): boolean { - this.enterpriseService.goal(6); - return true; - } - get isLightMode(): boolean { return this.loadedTheme === 'nymkappa'; } diff --git a/frontend/src/app/components/accelerate-checkout/accelerate-checkout.component.ts b/frontend/src/app/components/accelerate-checkout/accelerate-checkout.component.ts index 6f8636e96..618e52fe8 100644 --- a/frontend/src/app/components/accelerate-checkout/accelerate-checkout.component.ts +++ b/frontend/src/app/components/accelerate-checkout/accelerate-checkout.component.ts @@ -9,7 +9,6 @@ import { ETA, EtaService } from '@app/services/eta.service'; import { Transaction } from '@interfaces/electrs.interface'; import { MiningStats } from '@app/services/mining.service'; import { IAuth, AuthServiceMempool } from '@app/services/auth.service'; -import { EnterpriseService } from '@app/services/enterprise.service'; import { PartnerCodeService } from '@app/services/partner-code.service'; import { ApiService } from '@app/services/api.service'; import { isDevMode } from '@angular/core'; @@ -147,7 +146,6 @@ export class AccelerateCheckout implements OnInit, OnDestroy { private audioService: AudioService, private cd: ChangeDetectorRef, private authService: AuthServiceMempool, - private enterpriseService: EnterpriseService, private partnerCodeService: PartnerCodeService, private themeService: ThemeService, ) { @@ -236,7 +234,6 @@ export class AccelerateCheckout implements OnInit, OnDestroy { if (this._step === 'checkout') { this.insertSquare(); - this.enterpriseService.goal(8); this.scrollToElementWithTimeout('acceleratePreviewAnchor', 'start', 100); } diff --git a/frontend/src/app/components/privacy-policy/privacy-policy.component.html b/frontend/src/app/components/privacy-policy/privacy-policy.component.html index 89d5a8394..3c4c13935 100644 --- a/frontend/src/app/components/privacy-policy/privacy-policy.component.html +++ b/frontend/src/app/components/privacy-policy/privacy-policy.component.html @@ -43,7 +43,7 @@
-
  • We use a self-hosted statistics application (matomo) for analytics purposes, which collects your IP address along with the requests you make. Our matomo instance is configured to respect your privacy by redacting your IP address and other methods, and we do not share this data with any third-party. To conceal your activity from our analytics, we recommend that you use a privacy protecting browser extension that blocks matomo from being loaded.
  • +
  • We use a self-hosted statistics application for analytics purposes, which collects your IP address along with the requests you make. Our instance is configured to respect your privacy by redacting your IP address and other methods, and we do not share this data with any third-party. To conceal your activity from our analytics, we recommend that you use a privacy protecting browser extension that blocks it from being loaded.
  • diff --git a/frontend/src/app/components/tracker/tracker.component.ts b/frontend/src/app/components/tracker/tracker.component.ts index 7ad2817a7..6195161ce 100644 --- a/frontend/src/app/components/tracker/tracker.component.ts +++ b/frontend/src/app/components/tracker/tracker.component.ts @@ -167,8 +167,6 @@ export class TrackerComponent implements OnInit, OnDestroy { this.miningStats = stats; }); - this.enterpriseService.page(); - this.enterpriseInfo$ = this.enterpriseService.info$.subscribe(info => { this.enterpriseInfo = info; }); diff --git a/frontend/src/app/components/transaction/transaction.component.ts b/frontend/src/app/components/transaction/transaction.component.ts index 8c7892c37..20ac47642 100644 --- a/frontend/src/app/components/transaction/transaction.component.ts +++ b/frontend/src/app/components/transaction/transaction.component.ts @@ -35,7 +35,6 @@ import { RelativeUrlPipe } from '@app/shared/pipes/relative-url/relative-url.pip import { PriceService } from '@app/services/price.service'; import { isFeatureActive } from '@app/bitcoin.utils'; import { ServicesApiServices } from '@app/services/services-api.service'; -import { EnterpriseService } from '@app/services/enterprise.service'; import { PartnerCodeService } from '@app/services/partner-code.service'; import { ZONE_SERVICE } from '@app/injection-tokens'; import { MiningService, MiningStats } from '@app/services/mining.service'; @@ -217,7 +216,6 @@ export class TransactionComponent implements OnInit, AfterViewInit, OnDestroy { private seoService: SeoService, private priceService: PriceService, private storageService: StorageService, - private enterpriseService: EnterpriseService, private partnerCodeService: PartnerCodeService, private miningService: MiningService, private etaService: EtaService, @@ -228,7 +226,6 @@ export class TransactionComponent implements OnInit, AfterViewInit, OnDestroy { ngOnInit() { this.setupPartnerCode(); - this.enterpriseService.page(); this.isDetailsOpen = this.route.snapshot.queryParams['showDetails'] === 'true'; this.cpfpMode = this.route.snapshot.queryParams['cpfp'] === 'true'; diff --git a/frontend/src/app/services/enterprise.service.ts b/frontend/src/app/services/enterprise.service.ts index 350efa316..2dff81a20 100644 --- a/frontend/src/app/services/enterprise.service.ts +++ b/frontend/src/app/services/enterprise.service.ts @@ -3,7 +3,6 @@ import { Inject, Injectable } from '@angular/core'; import { ApiService } from '@app/services/api.service'; import { SeoService } from '@app/services/seo.service'; import { StateService } from '@app/services/state.service'; -import { ActivatedRoute } from '@angular/router'; import { BehaviorSubject } from 'rxjs'; @Injectable({ @@ -12,8 +11,6 @@ import { BehaviorSubject } from 'rxjs'; export class EnterpriseService { exclusiveHostName = '.mempool.space'; subdomain: string | null = null; - statsUrl: string; - siteId: number; info$: BehaviorSubject = new BehaviorSubject(null); constructor( @@ -21,7 +18,6 @@ export class EnterpriseService { private apiService: ApiService, private seoService: SeoService, private stateService: StateService, - private activatedRoute: ActivatedRoute, ) { const subdomain = this.stateService.env.customize?.enterprise || this.document.location.hostname.indexOf(this.exclusiveHostName) > -1 && this.document.location.hostname.split(this.exclusiveHostName)[0] || false; @@ -30,8 +26,6 @@ export class EnterpriseService { this.fetchSubdomainInfo(); this.disableSubnetworks(); this.stateService.env.ACCELERATOR = false; - } else { - this.insertMatomo(); } } @@ -51,12 +45,10 @@ export class EnterpriseService { fetchSubdomainInfo(): void { if (this.stateService.env.customize?.branding) { const info = this.stateService.env.customize?.branding; - this.insertMatomo(info.site_id); this.seoService.setEnterpriseTitle(info.title, true); this.info$.next(this.processEnterpriseInfo(info)); } else { this.apiService.getEnterpriseInfo$(this.subdomain).subscribe((info) => { - this.insertMatomo(info.site_id); this.seoService.setEnterpriseTitle(info.title); this.info$.next(this.processEnterpriseInfo(info)); }, @@ -78,98 +70,4 @@ export class EnterpriseService { logoUrl, }; } - - insertMatomo(siteId?: number): void { - let statsUrl = '//stats.mempool.space/'; - - if (!siteId) { - switch (this.document.location.hostname) { - case 'mempool.space': - statsUrl = '//stats.mempool.space/'; - siteId = 5; - break; - case 'mempool.ninja': - statsUrl = '//stats.mempool.space/'; - siteId = 4; - break; - case 'liquid.network': - siteId = 8; - statsUrl = '//stats.liquid.network/'; - break; - case 'liquid.place': - siteId = 10; - statsUrl = '//stats.liquid.network/'; - break; - default: - return; - } - } - - this.statsUrl = statsUrl; - this.siteId = siteId; - - // @ts-ignore - if (window._paq && window['Matomo']) { - window['Matomo'].addTracker(statsUrl+'m.php', siteId.toString()); - const matomo = this.getMatomo(); - matomo.setDocumentTitle(this.seoService.getTitle()); - matomo.setCustomUrl(this.getCustomUrl()); - matomo.disableCookies(); - matomo.trackPageView(); - matomo.enableLinkTracking(); - } else { - // @ts-ignore - const alreadyInitialized = !!window._paq; - // @ts-ignore - const _paq = window._paq = window._paq || []; - _paq.push(['setDocumentTitle', this.seoService.getTitle()]); - _paq.push(['setCustomUrl', this.getCustomUrl()]); - _paq.push(['disableCookies']); - _paq.push(['trackPageView']); - _paq.push(['enableLinkTracking']); - if (alreadyInitialized) { - _paq.push(['addTracker', statsUrl+'m.php', siteId.toString()]); - } else { - (function() { - _paq.push(['setTrackerUrl', statsUrl+'m.php']); - _paq.push(['setSiteId', siteId.toString()]); - const d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0]; - // @ts-ignore - g.type='text/javascript'; g.async=true; g.src=statsUrl+'m.js'; s.parentNode.insertBefore(g,s); - })(); - } - } - } - - private getMatomo() { - if (this.siteId != null) { - return window['Matomo']?.getTracker(this.statsUrl+'m.php', this.siteId); - } - } - - goal(id: number) { - // @ts-ignore - this.getMatomo()?.trackGoal(id); - } - - page() { - const matomo = this.getMatomo(); - if (matomo) { - matomo.setCustomUrl(this.getCustomUrl()); - matomo.trackPageView(); - } - } - - private getCustomUrl(): string { - let url = window.location.origin + '/'; - let route = this.activatedRoute; - while (route) { - const segment = route?.routeConfig?.path; - if (segment && segment.length) { - url += segment + '/'; - } - route = route.firstChild; - } - return url; - } }