Date: Sat, 22 Feb 2025 22:25:52 +0700
Subject: [PATCH 08/48] remove tv mode tests
---
frontend/cypress/e2e/signet/signet.spec.ts | 24 -------------------
.../cypress/e2e/testnet4/testnet4.spec.ts | 24 -------------------
2 files changed, 48 deletions(-)
diff --git a/frontend/cypress/e2e/signet/signet.spec.ts b/frontend/cypress/e2e/signet/signet.spec.ts
index 11c47d14d..ae591c6a7 100644
--- a/frontend/cypress/e2e/signet/signet.spec.ts
+++ b/frontend/cypress/e2e/signet/signet.spec.ts
@@ -60,30 +60,6 @@ describe('Signet', () => {
});
});
- describe.skip('tv mode', () => {
- it('loads the tv screen - desktop', () => {
- cy.viewport('macbook-16');
- cy.visit('/signet/graphs');
- cy.waitForSkeletonGone();
- cy.get('#btn-tv').click().then(() => {
- cy.get('.chart-holder').should('be.visible');
- cy.get('#mempool-block-0').should('be.visible');
- cy.get('.tv-only').should('not.exist');
- });
- });
-
- it('loads the tv screen - mobile', () => {
- cy.visit('/signet/graphs');
- cy.waitForSkeletonGone();
- cy.get('#btn-tv').click().then(() => {
- cy.viewport('iphone-8');
- cy.get('.chart-holder').should('be.visible');
- cy.get('.tv-only').should('not.exist');
- cy.get('#mempool-block-0').should('be.visible');
- });
- });
- });
-
it('loads the api screen', () => {
cy.visit('/signet');
cy.waitForSkeletonGone();
diff --git a/frontend/cypress/e2e/testnet4/testnet4.spec.ts b/frontend/cypress/e2e/testnet4/testnet4.spec.ts
index c67d2414b..97af0e08e 100644
--- a/frontend/cypress/e2e/testnet4/testnet4.spec.ts
+++ b/frontend/cypress/e2e/testnet4/testnet4.spec.ts
@@ -60,30 +60,6 @@ describe('Testnet4', () => {
});
});
- describe('tv mode', () => {
- it('loads the tv screen - desktop', () => {
- cy.viewport('macbook-16');
- cy.visit('/testnet4/graphs');
- cy.waitForSkeletonGone();
- cy.get('#btn-tv').click().then(() => {
- cy.wait(1000);
- cy.get('.tv-only').should('not.exist');
- cy.get('#mempool-block-0').should('be.visible');
- });
- });
-
- it('loads the tv screen - mobile', () => {
- cy.visit('/testnet4/graphs');
- cy.waitForSkeletonGone();
- cy.get('#btn-tv').click().then(() => {
- cy.viewport('iphone-6');
- cy.wait(1000);
- cy.get('.tv-only').should('not.exist');
- });
- });
- });
-
-
it('loads the api screen', () => {
cy.visit('/testnet4');
cy.waitForSkeletonGone();
From 9d711c336a51a05b55b7a7b56ec78d2ad2af2b6d Mon Sep 17 00:00:00 2001
From: nymkappa <1612910616@pm.me>
Date: Sun, 9 Mar 2025 11:42:53 +0100
Subject: [PATCH 09/48] retreive -> retrieve
---
backend/src/api/blocks.ts | 8 ++++----
backend/src/repositories/HashratesRepository.ts | 2 +-
.../accelerate-checkout/accelerate-checkout.component.ts | 6 +++---
frontend/src/app/docs/api-docs/api-docs-data.ts | 2 +-
frontend/src/app/services/services-api.service.ts | 2 +-
5 files changed, 10 insertions(+), 10 deletions(-)
diff --git a/backend/src/api/blocks.ts b/backend/src/api/blocks.ts
index 102601594..beefc825b 100644
--- a/backend/src/api/blocks.ts
+++ b/backend/src/api/blocks.ts
@@ -1469,11 +1469,11 @@ class Blocks {
if (rows && Array.isArray(rows)) {
return rows.map(r => r.definition_hash);
} else {
- logger.debug(`Unable to retreive list of blocks.definition_hash from db (no result)`);
+ logger.debug(`Unable to retrieve list of blocks.definition_hash from db (no result)`);
return null;
}
} catch (e) {
- logger.debug(`Unable to retreive list of blocks.definition_hash from db (exception: ${e})`);
+ logger.debug(`Unable to retrieve list of blocks.definition_hash from db (exception: ${e})`);
return null;
}
}
@@ -1484,11 +1484,11 @@ class Blocks {
if (rows && Array.isArray(rows)) {
return rows.map(r => r.hash);
} else {
- logger.debug(`Unable to retreive list of blocks for definition hash ${definitionHash} from db (no result)`);
+ logger.debug(`Unable to retrieve list of blocks for definition hash ${definitionHash} from db (no result)`);
return null;
}
} catch (e) {
- logger.debug(`Unable to retreive list of blocks for definition hash ${definitionHash} from db (exception: ${e})`);
+ logger.debug(`Unable to retrieve list of blocks for definition hash ${definitionHash} from db (exception: ${e})`);
return null;
}
}
diff --git a/backend/src/repositories/HashratesRepository.ts b/backend/src/repositories/HashratesRepository.ts
index ec44afebe..93aa2d53f 100644
--- a/backend/src/repositories/HashratesRepository.ts
+++ b/backend/src/repositories/HashratesRepository.ts
@@ -93,7 +93,7 @@ class HashratesRepository {
const [rows]: any[] = await DB.query(query);
return rows.map(row => row.timestamp);
} catch (e) {
- logger.err('Cannot retreive indexed weekly hashrate timestamps. Reason: ' + (e instanceof Error ? e.message : e), logger.tags.mining);
+ logger.err('Cannot retrieve indexed weekly hashrate timestamps. Reason: ' + (e instanceof Error ? e.message : e), logger.tags.mining);
throw e;
}
}
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 ac6c7f147..bf70aebd3 100644
--- a/frontend/src/app/components/accelerate-checkout/accelerate-checkout.component.ts
+++ b/frontend/src/app/components/accelerate-checkout/accelerate-checkout.component.ts
@@ -525,7 +525,7 @@ export class AccelerateCheckout implements OnInit, OnDestroy {
if (tokenResult?.status === 'OK') {
const card = tokenResult.details?.card;
if (!card || !card.brand || !card.expMonth || !card.expYear || !card.last4) {
- console.error(`Cannot retreive payment card details`);
+ console.error(`Cannot retrieve payment card details`);
this.accelerateError = 'apple_pay_no_card_details';
this.processing = false;
return;
@@ -643,7 +643,7 @@ export class AccelerateCheckout implements OnInit, OnDestroy {
if (tokenResult?.status === 'OK') {
const card = tokenResult.details?.card;
if (!card || !card.brand || !card.expMonth || !card.expYear || !card.last4) {
- console.error(`Cannot retreive payment card details`);
+ console.error(`Cannot retrieve payment card details`);
this.accelerateError = 'apple_pay_no_card_details';
this.processing = false;
return;
@@ -936,7 +936,7 @@ export class AccelerateCheckout implements OnInit, OnDestroy {
this.loadingBtcpayInvoice = true;
this.servicesApiService.generateBTCPayAcceleratorInvoice$(this.tx.txid, this.userBid).pipe(
switchMap(response => {
- return this.servicesApiService.retreiveInvoice$(response.btcpayInvoiceId);
+ return this.servicesApiService.retrieveInvoice$(response.btcpayInvoiceId);
}),
catchError(error => {
console.log(error);
diff --git a/frontend/src/app/docs/api-docs/api-docs-data.ts b/frontend/src/app/docs/api-docs/api-docs-data.ts
index c32baa3f7..5e9608bdf 100644
--- a/frontend/src/app/docs/api-docs/api-docs-data.ts
+++ b/frontend/src/app/docs/api-docs/api-docs-data.ts
@@ -11803,7 +11803,7 @@ export const restApiDocsData = [
fragment: "accelerator-cancel",
title: "POST Cancel Acceleration (Pro)",
description: {
- default: "Sends a request to cancel an acceleration in the accelerating status.
You can retreive eligible acceleration id using the history endpoint GET /api/v1/services/accelerator/history?status=accelerating."
+ default: "
Sends a request to cancel an acceleration in the accelerating status.
You can retrieve eligible acceleration id using the history endpoint GET /api/v1/services/accelerator/history?status=accelerating."
},
urlString: "/v1/services/accelerator/cancel",
showConditions: [""],
diff --git a/frontend/src/app/services/services-api.service.ts b/frontend/src/app/services/services-api.service.ts
index 59dc92358..a9550e731 100644
--- a/frontend/src/app/services/services-api.service.ts
+++ b/frontend/src/app/services/services-api.service.ts
@@ -213,7 +213,7 @@ export class ServicesApiServices {
return this.httpClient.post(`${this.stateService.env.SERVICES_API}/payments/bitcoin`, params);
}
- retreiveInvoice$(invoiceId: string): Observable {
+ retrieveInvoice$(invoiceId: string): Observable {
return this.httpClient.get(`${this.stateService.env.SERVICES_API}/payments/bitcoin/invoice?id=${invoiceId}`);
}
From 7d9e275803e90b621b4419561962086e5f41a3f2 Mon Sep 17 00:00:00 2001
From: nymkappa <1612910616@pm.me>
Date: Wed, 12 Mar 2025 14:56:15 +0100
Subject: [PATCH 10/48] [accelerator] show square receipt if available
---
.../accelerate-checkout.component.html | 19 +++++++++++++++++--
.../accelerate-checkout.component.ts | 16 ++++++++--------
2 files changed, 25 insertions(+), 10 deletions(-)
diff --git a/frontend/src/app/components/accelerate-checkout/accelerate-checkout.component.html b/frontend/src/app/components/accelerate-checkout/accelerate-checkout.component.html
index 4594fd9fc..2038d4b6c 100644
--- a/frontend/src/app/components/accelerate-checkout/accelerate-checkout.component.html
+++ b/frontend/src/app/components/accelerate-checkout/accelerate-checkout.component.html
@@ -567,14 +567,29 @@
} @else if (step === 'success') {
-
Your transaction is being accelerated!
+
+ @if (accelerationResponse) {
+ Your transaction is being accelerated!
+ } @else {
+ Transaction is already being accelerated!
+ }
+
- Your transaction has been accepted for acceleration by our mining pool partners.
+ @if (accelerationResponse) {
+ Your transaction has been accepted for acceleration by our mining pool partners.
+ } @else {
+ Transaction has already been accepted for acceleration by our mining pool partners.
+ }
+ @if (accelerationResponse?.receiptUrl) {
+
+ }
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 ac6c7f147..06d2fa4cd 100644
--- a/frontend/src/app/components/accelerate-checkout/accelerate-checkout.component.ts
+++ b/frontend/src/app/components/accelerate-checkout/accelerate-checkout.component.ts
@@ -87,6 +87,7 @@ export class AccelerateCheckout implements OnInit, OnDestroy {
math = Math;
isMobile: boolean = window.innerWidth <= 767.98;
isProdDomain = false;
+ accelerationResponse: { receiptUrl: string | null } | undefined;
private _step: CheckoutStep = 'summary';
simpleMode: boolean = true;
@@ -194,11 +195,7 @@ export class AccelerateCheckout implements OnInit, OnDestroy {
this.scrollToElement('acceleratePreviewAnchor', 'start');
}
if (changes.accelerating && this.accelerating) {
- if (this.step === 'processing' || this.step === 'paid') {
- this.moveToStep('success', true);
- } else { // Edge case where the transaction gets accelerated by someone else or on another session
- this.closeModal();
- }
+ this.moveToStep('success', true);
}
}
@@ -541,7 +538,8 @@ export class AccelerateCheckout implements OnInit, OnDestroy {
`accelerator-${this.tx.txid.substring(0, 15)}-${Math.round(new Date().getTime() / 1000)}`,
costUSD
).subscribe({
- next: () => {
+ next: (response) => {
+ this.accelerationResponse = response;
this.processing = false;
this.apiService.logAccelerationRequest$(this.tx.txid).subscribe();
this.audioService.playSound('ascend-chime-cartoon');
@@ -668,7 +666,8 @@ export class AccelerateCheckout implements OnInit, OnDestroy {
costUSD,
verificationToken.userChallenged
).subscribe({
- next: () => {
+ next: (response) => {
+ this.accelerationResponse = response;
this.processing = false;
this.apiService.logAccelerationRequest$(this.tx.txid).subscribe();
this.audioService.playSound('ascend-chime-cartoon');
@@ -777,7 +776,8 @@ export class AccelerateCheckout implements OnInit, OnDestroy {
costUSD,
verificationToken.userChallenged
).subscribe({
- next: () => {
+ next: (response) => {
+ this.accelerationResponse = response;
this.processing = false;
this.apiService.logAccelerationRequest$(this.tx.txid).subscribe();
this.audioService.playSound('ascend-chime-cartoon');
From cac404ae9bbce0c6192fddf3a99bb8c79483f134 Mon Sep 17 00:00:00 2001
From: nymkappa <1612910616@pm.me>
Date: Wed, 12 Mar 2025 15:26:44 +0100
Subject: [PATCH 11/48] [accelerator] make sure we cannot go back from
'success' step
---
.../accelerate-checkout/accelerate-checkout.component.ts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
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 06d2fa4cd..0db40af82 100644
--- a/frontend/src/app/components/accelerate-checkout/accelerate-checkout.component.ts
+++ b/frontend/src/app/components/accelerate-checkout/accelerate-checkout.component.ts
@@ -200,7 +200,7 @@ export class AccelerateCheckout implements OnInit, OnDestroy {
}
moveToStep(step: CheckoutStep, force: boolean = false): void {
- if (this.isCheckoutLocked > 0 && !force) {
+ if (this.isCheckoutLocked > 0 && !force || this.step === 'success') {
return;
}
this.processing = false;
From 1121377c7a888d8a1d12859cf9488d3db4b56249 Mon Sep 17 00:00:00 2001
From: nymkappa <1612910616@pm.me>
Date: Wed, 12 Mar 2025 15:27:00 +0100
Subject: [PATCH 12/48] [accelerator] add missing response from cashapp payment
---
.../accelerate-checkout/accelerate-checkout.component.ts | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
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 0db40af82..7fc1e88ef 100644
--- a/frontend/src/app/components/accelerate-checkout/accelerate-checkout.component.ts
+++ b/frontend/src/app/components/accelerate-checkout/accelerate-checkout.component.ts
@@ -870,7 +870,8 @@ export class AccelerateCheckout implements OnInit, OnDestroy {
tokenResult.details.cashAppPay.referenceId,
costUSD
).subscribe({
- next: () => {
+ next: (response) => {
+ this.accelerationResponse = response;
this.processing = false;
this.apiService.logAccelerationRequest$(this.tx.txid).subscribe();
this.audioService.playSound('ascend-chime-cartoon');
From 062c5ca03a0d1bf4e8678dc717b9df5b228a4955 Mon Sep 17 00:00:00 2001
From: natsoni
Date: Wed, 12 Mar 2025 16:47:31 +0100
Subject: [PATCH 13/48] Trim input data in tx preview
---
.../src/app/components/transaction/transaction-raw.component.ts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/frontend/src/app/components/transaction/transaction-raw.component.ts b/frontend/src/app/components/transaction/transaction-raw.component.ts
index 5ce170e12..f7ae4a751 100644
--- a/frontend/src/app/components/transaction/transaction-raw.component.ts
+++ b/frontend/src/app/components/transaction/transaction-raw.component.ts
@@ -82,7 +82,7 @@ export class TransactionRawComponent implements OnInit, OnDestroy {
this.resetState();
this.isLoading = true;
try {
- const { tx, hex } = decodeRawTransaction(this.pushTxForm.get('txRaw').value, this.stateService.network);
+ const { tx, hex } = decodeRawTransaction(this.pushTxForm.get('txRaw').value.trim(), this.stateService.network);
await this.fetchPrevouts(tx);
await this.fetchCpfpInfo(tx);
this.processTransaction(tx, hex);
From 4dff3adf1169d056f35acd5b3c28bb5fadbd850d Mon Sep 17 00:00:00 2001
From: natsoni
Date: Wed, 12 Mar 2025 16:49:38 +0100
Subject: [PATCH 14/48] Redirect to tx page 2 seconds after broadcast
---
.../transaction-raw.component.html | 11 ++++---
.../transaction-raw.component.scss | 8 +++++
.../transaction/transaction-raw.component.ts | 31 ++++++++++++-------
3 files changed, 34 insertions(+), 16 deletions(-)
diff --git a/frontend/src/app/components/transaction/transaction-raw.component.html b/frontend/src/app/components/transaction/transaction-raw.component.html
index 3bd8ee6d2..35701889b 100644
--- a/frontend/src/app/components/transaction/transaction-raw.component.html
+++ b/frontend/src/app/components/transaction/transaction-raw.component.html
@@ -30,7 +30,6 @@
-
@@ -40,14 +39,18 @@
-
+
-
+
This transaction is stored locally in your browser. Broadcast it to add it to the mempool.
+
+ Redirecting to transaction page...
+
-
+
+
@if (!hasPrevouts) {
diff --git a/frontend/src/app/components/transaction/transaction-raw.component.scss b/frontend/src/app/components/transaction/transaction-raw.component.scss
index 5bbe5601e..a4b386cee 100644
--- a/frontend/src/app/components/transaction/transaction-raw.component.scss
+++ b/frontend/src/app/components/transaction/transaction-raw.component.scss
@@ -191,4 +191,12 @@
.no-cursor {
cursor: default !important;
pointer-events: none;
+}
+
+.btn-broadcast {
+ margin-left: 5px;
+ @media (max-width: 567px) {
+ margin-left: 0;
+ margin-top: 5px;
+ }
}
\ No newline at end of file
diff --git a/frontend/src/app/components/transaction/transaction-raw.component.ts b/frontend/src/app/components/transaction/transaction-raw.component.ts
index f7ae4a751..2e4dd4868 100644
--- a/frontend/src/app/components/transaction/transaction-raw.component.ts
+++ b/frontend/src/app/components/transaction/transaction-raw.component.ts
@@ -3,7 +3,7 @@ import { Transaction, Vout } from '@interfaces/electrs.interface';
import { StateService } from '../../services/state.service';
import { Filter, toFilters } from '../../shared/filters.utils';
import { decodeRawTransaction, getTransactionFlags, addInnerScriptsToVin, countSigops } from '../../shared/transaction.utils';
-import { firstValueFrom, Subscription } from 'rxjs';
+import { catchError, firstValueFrom, Subscription, switchMap, tap, throwError, timer } from 'rxjs';
import { WebsocketService } from '../../services/websocket.service';
import { ActivatedRoute, Router } from '@angular/router';
import { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms';
@@ -36,6 +36,7 @@ export class TransactionRawComponent implements OnInit, OnDestroy {
isLoadingBroadcast: boolean;
errorBroadcast: string;
successBroadcast: boolean;
+ broadcastSubscription: Subscription;
isMobile: boolean;
@ViewChild('graphContainer')
@@ -207,18 +208,22 @@ export class TransactionRawComponent implements OnInit, OnDestroy {
});
}
- async postTx(): Promise
{
+ postTx(): void {
this.isLoadingBroadcast = true;
this.errorBroadcast = null;
- return new Promise((resolve, reject) => {
- this.apiService.postTransaction$(this.rawHexTransaction)
- .subscribe((result) => {
+
+ this.broadcastSubscription = this.apiService.postTransaction$(this.rawHexTransaction).pipe(
+ tap((txid: string) => {
this.isLoadingBroadcast = false;
this.successBroadcast = true;
- this.transaction.txid = result;
- resolve(result);
- },
- (error) => {
+ this.transaction.txid = txid;
+ }),
+ switchMap((txid: string) =>
+ timer(2000).pipe(
+ tap(() => this.router.navigate([this.relativeUrlPipe.transform('/tx/' + txid)])),
+ )
+ ),
+ catchError((error) => {
if (typeof error.error === 'string') {
const matchText = error.error.replace(/\\/g, '').match('"message":"(.*?)"');
this.errorBroadcast = 'Failed to broadcast transaction, reason: ' + (matchText && matchText[1] || error.error);
@@ -226,9 +231,9 @@ export class TransactionRawComponent implements OnInit, OnDestroy {
this.errorBroadcast = 'Failed to broadcast transaction, reason: ' + error.message;
}
this.isLoadingBroadcast = false;
- reject(this.error);
- });
- });
+ return throwError(() => error);
+ })
+ ).subscribe();
}
resetState() {
@@ -253,6 +258,7 @@ export class TransactionRawComponent implements OnInit, OnDestroy {
this.missingPrevouts = [];
this.stateService.markBlock$.next({});
this.mempoolBlocksSubscription?.unsubscribe();
+ this.broadcastSubscription?.unsubscribe();
}
resetForm() {
@@ -308,6 +314,7 @@ export class TransactionRawComponent implements OnInit, OnDestroy {
this.mempoolBlocksSubscription?.unsubscribe();
this.flowPrefSubscription?.unsubscribe();
this.stateService.markBlock$.next({});
+ this.broadcastSubscription?.unsubscribe();
}
}
From 00e7e726bc7084933d8e757a69e46049b0eef7bb Mon Sep 17 00:00:00 2001
From: hunicus <93150691+hunicus@users.noreply.github.com>
Date: Thu, 6 Mar 2025 10:31:10 -0500
Subject: [PATCH 15/48] Mark mempool accelerator as registered trademark
---
LICENSE | 2 +-
.../src/app/components/about/about.component.html | 2 +-
.../accelerate-checkout.component.html | 2 +-
.../privacy-policy/privacy-policy.component.html | 12 ++++++------
.../components/svg-images/svg-images.component.html | 4 ++--
.../terms-of-service/terms-of-service.component.html | 8 ++++----
.../trademark-policy/trademark-policy.component.html | 2 +-
.../transaction-details.component.html | 4 ++--
.../src/app/docs/api-docs/api-docs.component.html | 2 +-
9 files changed, 19 insertions(+), 19 deletions(-)
diff --git a/LICENSE b/LICENSE
index 1c368c00a..b6e67e523 100644
--- a/LICENSE
+++ b/LICENSE
@@ -10,7 +10,7 @@ However, this copyright license does not include an implied right or license
to use any trademarks, service marks, logos, or trade names of Mempool Space K.K.
or any other contributor to The Mempool Open Source Project.
-The Mempool Open Source Project®, Mempool Accelerator™, Mempool Enterprise®,
+The Mempool Open Source Project®, Mempool Accelerator®, Mempool Enterprise®,
Mempool Liquidity™, mempool.space®, Be your own explorer™, Explore the full
Bitcoin ecosystem™, Mempool Goggles™, the mempool Logo, the mempool Square Logo,
the mempool block visualization Logo, the mempool Blocks Logo, the mempool
diff --git a/frontend/src/app/components/about/about.component.html b/frontend/src/app/components/about/about.component.html
index 3bd8960f5..5b53e94ab 100644
--- a/frontend/src/app/components/about/about.component.html
+++ b/frontend/src/app/components/about/about.component.html
@@ -451,7 +451,7 @@
Trademark Notice
- The Mempool Open Source Project®, Mempool Accelerator™, Mempool Enterprise®, Mempool Liquidity™, mempool.space®, Be your own explorer™, Explore the full Bitcoin ecosystem®, Mempool Goggles™, the mempool Logo, the mempool Square Logo, the mempool block visualization Logo, the mempool Blocks Logo, the mempool transaction Logo, the mempool Blocks 3 | 2 Logo, the mempool research Logo, the mempool.space Vertical Logo, and the mempool.space Horizontal Logo are either registered trademarks or trademarks of Mempool Space K.K in Japan, the United States, and/or other countries.
+ The Mempool Open Source Project®, Mempool Accelerator®, Mempool Enterprise®, Mempool Liquidity™, mempool.space®, Be your own explorer™, Explore the full Bitcoin ecosystem®, Mempool Goggles™, the mempool Logo, the mempool Square Logo, the mempool block visualization Logo, the mempool Blocks Logo, the mempool transaction Logo, the mempool Blocks 3 | 2 Logo, the mempool research Logo, the mempool.space Vertical Logo, and the mempool.space Horizontal Logo are either registered trademarks or trademarks of Mempool Space K.K in Japan, the United States, and/or other countries.
While our software is available under an open source software license, the copyright license does not include an implied right or license to use our trademarks. See our Trademark Policy and Guidelines for more details, published on <https://mempool.space/trademark-policy>.
diff --git a/frontend/src/app/components/accelerate-checkout/accelerate-checkout.component.html b/frontend/src/app/components/accelerate-checkout/accelerate-checkout.component.html
index 4594fd9fc..4ac5aa24e 100644
--- a/frontend/src/app/components/accelerate-checkout/accelerate-checkout.component.html
+++ b/frontend/src/app/components/accelerate-checkout/accelerate-checkout.component.html
@@ -158,7 +158,7 @@
- | Mempool Accelerator™ fees |
+ Mempool Accelerator® fees |
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 06b09ad30..bfd6159c4 100644
--- a/frontend/src/app/components/privacy-policy/privacy-policy.component.html
+++ b/frontend/src/app/components/privacy-policy/privacy-policy.component.html
@@ -45,14 +45,14 @@
- USING MEMPOOL ACCELERATOR™
+ USING MEMPOOL ACCELERATOR®
- If you use Mempool Accelerator™ your acceleration request will be sent to us and relayed to Mempool's mining pool partners. We will store the TXID of the transactions you accelerate with us. We share this information with our mining pool partners, and publicly display accelerated transaction details on our website and APIs. No personal information or account identifiers will be shared with any third party including mining pool partners.
+ If you use Mempool Accelerator® your acceleration request will be sent to us and relayed to Mempool's mining pool partners. We will store the TXID of the transactions you accelerate with us. We share this information with our mining pool partners, and publicly display accelerated transaction details on our website and APIs. No personal information or account identifiers will be shared with any third party including mining pool partners.
- When using Mempool Accelerator™ the mempool.space privacy policy will apply: https://mempool.space/privacy-policy.
+ When using Mempool Accelerator® the mempool.space privacy policy will apply: https://mempool.space/privacy-policy.
-
+
SIGNING UP FOR AN ACCOUNT ON MEMPOOL.SPACE
@@ -67,7 +67,7 @@
If you sign up for a subscription to Mempool Enterprise™ we also collect your company name which is not shared with any third-party.
- If you sign up for an account on mempool.space and use Mempool Accelerator™ Pro your accelerated transactions will be associated with your account for the purposes of accounting.
+ If you sign up for an account on mempool.space and use Mempool Accelerator® Pro your accelerated transactions will be associated with your account for the purposes of accounting.
@@ -101,7 +101,7 @@
We aim to retain your data only as long as necessary:
- - An account is considered inactive if all of the following conditions are met: a) No login activity within the past 6 months, b) No active subscriptions associated with the account, c) No Mempool Accelerator™ Pro account credit
+ - An account is considered inactive if all of the following conditions are met: a) No login activity within the past 6 months, b) No active subscriptions associated with the account, c) No Mempool Accelerator® Pro account credit
- If an account meets the criteria for inactivity as defined above, we will automatically delete the associated account data after a period of 6 months of continuous inactivity, except in the case of payment disputes or account irregularities.
diff --git a/frontend/src/app/components/svg-images/svg-images.component.html b/frontend/src/app/components/svg-images/svg-images.component.html
index 76aa3de85..04b99dea6 100644
--- a/frontend/src/app/components/svg-images/svg-images.component.html
+++ b/frontend/src/app/components/svg-images/svg-images.component.html
@@ -137,7 +137,7 @@
-
\ No newline at end of file
+
diff --git a/frontend/src/app/components/terms-of-service/terms-of-service.component.html b/frontend/src/app/components/terms-of-service/terms-of-service.component.html
index 709605a9f..51f035436 100644
--- a/frontend/src/app/components/terms-of-service/terms-of-service.component.html
+++ b/frontend/src/app/components/terms-of-service/terms-of-service.component.html
@@ -67,9 +67,9 @@
- MEMPOOL ACCELERATOR™
+ MEMPOOL ACCELERATOR®
- Mempool Accelerator™ enables members of the Bitcoin community to submit requests for transaction prioritization.
+ Mempool Accelerator® enables members of the Bitcoin community to submit requests for transaction prioritization.
- Mempool will use reasonable commercial efforts to relay user acceleration requests to Mempool's mining pool partners, but it is at the discretion of Mempool and Mempool's mining pool partners to accept acceleration requests.
@@ -84,11 +84,11 @@
- - All acceleration payments and Mempool Accelerator™ account credit top-ups are non-refundable.
+ - All acceleration payments and Mempool Accelerator® account credit top-ups are non-refundable.
- - Mempool Accelerator™ account credit top-ups are prepayment for future accelerations and cannot be withdrawn or transferred.
+ - Mempool Accelerator® account credit top-ups are prepayment for future accelerations and cannot be withdrawn or transferred.
diff --git a/frontend/src/app/components/trademark-policy/trademark-policy.component.html b/frontend/src/app/components/trademark-policy/trademark-policy.component.html
index e12cbb8b2..f7da0a7a4 100644
--- a/frontend/src/app/components/trademark-policy/trademark-policy.component.html
+++ b/frontend/src/app/components/trademark-policy/trademark-policy.component.html
@@ -340,7 +340,7 @@
Also, if you are using our Marks in a way described in the sections "Uses for Which We Are Granting a License," you must include the following trademark attribution at the foot of the webpage where you have used the Mark (or, if in a book, on the credits page), on any packaging or labeling, and on advertising or marketing materials:
- "The Mempool Open Source Project®, Mempool Accelerator™, Mempool Enterprise®, Mempool Liquidity™, mempool.space®, Be your own explorer™, Explore the full Bitcoin ecosystem®, Mempool Goggles™, the mempool logo;, the mempool Square logo;, the mempool Blocks logo;, the mempool Blocks 3 | 2 logo;, the mempool.space Vertical Logo;, the Mempool Accelerator logo;, the Mempool Goggles logo;, and the mempool.space Horizontal logo are either registered trademarks or trademarks of Mempool Space K.K in Japan, the United States, and/or other countries, and are used with permission. Mempool Space K.K. has no affiliation with and does not sponsor or endorse the information provided herein."
+ "The Mempool Open Source Project®, Mempool Accelerator®, Mempool Enterprise®, Mempool Liquidity™, mempool.space®, Be your own explorer™, Explore the full Bitcoin ecosystem®, Mempool Goggles™, the mempool logo;, the mempool Square logo;, the mempool Blocks logo;, the mempool Blocks 3 | 2 logo;, the mempool.space Vertical Logo;, the Mempool Accelerator logo;, the Mempool Goggles logo;, and the mempool.space Horizontal logo are either registered trademarks or trademarks of Mempool Space K.K in Japan, the United States, and/or other countries, and are used with permission. Mempool Space K.K. has no affiliation with and does not sponsor or endorse the information provided herein."
- What to Do When You See Abuse
diff --git a/frontend/src/app/components/transaction/transaction-details/transaction-details.component.html b/frontend/src/app/components/transaction/transaction-details/transaction-details.component.html
index 78bba955c..819e27d89 100644
--- a/frontend/src/app/components/transaction/transaction-details/transaction-details.component.html
+++ b/frontend/src/app/components/transaction/transaction-details/transaction-details.component.html
@@ -170,7 +170,7 @@
@if (!tx?.acceleration && acceleratorAvailable && accelerateCtaType === 'button' && !showAccelerationSummary && notAcceleratedOnLoad) {
@@ -318,4 +318,4 @@
|
-
\ No newline at end of file
+
diff --git a/frontend/src/app/docs/api-docs/api-docs.component.html b/frontend/src/app/docs/api-docs/api-docs.component.html
index 75e37a3bd..d359500a0 100644
--- a/frontend/src/app/docs/api-docs/api-docs.component.html
+++ b/frontend/src/app/docs/api-docs/api-docs.component.html
@@ -219,7 +219,7 @@
- To get your transaction confirmed quicker, you will need to increase its effective feerate. If your transaction was created with RBF enabled, your stuck transaction can simply be replaced with a new one that has a higher fee. Otherwise, if you control any of the stuck transaction's outputs, you can use CPFP to increase your stuck transaction's effective feerate. If you are not sure how to do RBF or CPFP, work with the tool you used to make the transaction (wallet software, exchange company, etc). Another option to get your transaction confirmed more quickly is Mempool Accelerator™.
+ To get your transaction confirmed quicker, you will need to increase its effective feerate. If your transaction was created with RBF enabled, your stuck transaction can simply be replaced with a new one that has a higher fee. Otherwise, if you control any of the stuck transaction's outputs, you can use CPFP to increase your stuck transaction's effective feerate. If you are not sure how to do RBF or CPFP, work with the tool you used to make the transaction (wallet software, exchange company, etc). Another option to get your transaction confirmed more quickly is Mempool Accelerator®.
From e94dc67b3187ebfbaa630e43805e2f4be306803a Mon Sep 17 00:00:00 2001
From: natsoni
Date: Thu, 13 Mar 2025 15:46:11 +0100
Subject: [PATCH 16/48] Update tapscript multisig minimum size
---
frontend/src/app/shared/script.utils.ts | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/frontend/src/app/shared/script.utils.ts b/frontend/src/app/shared/script.utils.ts
index 62a7a5845..df50a4070 100644
--- a/frontend/src/app/shared/script.utils.ts
+++ b/frontend/src/app/shared/script.utils.ts
@@ -310,8 +310,10 @@ export function parseTapscriptMultisig(script: string): undefined | { m: number,
}
const ops = script.split(' ');
- // At minimum, one pubkey group (3 tokens) + m push + final opcode = 5 tokens
- if (ops.length < 5) return;
+ // At minimum, 2 pubkey group (3 tokens) + m push + final opcode = 8 tokens
+ if (ops.length < 8) {
+ return;
+ }
const finalOp = ops.pop();
if (finalOp !== 'OP_NUMEQUAL' && finalOp !== 'OP_GREATERTHANOREQUAL') {
From 188096e651f745ef8a09d4091d1eb727282a50c4 Mon Sep 17 00:00:00 2001
From: natsoni
Date: Thu, 13 Mar 2025 16:38:53 +0100
Subject: [PATCH 17/48] Add opcodes that can be used for tapscript multisig
---
frontend/src/app/shared/script.utils.ts | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/frontend/src/app/shared/script.utils.ts b/frontend/src/app/shared/script.utils.ts
index df50a4070..f0c4701db 100644
--- a/frontend/src/app/shared/script.utils.ts
+++ b/frontend/src/app/shared/script.utils.ts
@@ -316,7 +316,7 @@ export function parseTapscriptMultisig(script: string): undefined | { m: number,
}
const finalOp = ops.pop();
- if (finalOp !== 'OP_NUMEQUAL' && finalOp !== 'OP_GREATERTHANOREQUAL') {
+ if (!['OP_NUMEQUAL', 'OP_NUMEQUALVERIFY', 'OP_GREATERTHANOREQUAL', 'OP_GREATERTHAN', 'OP_EQUAL', 'OP_EQUALVERIFY'].includes(finalOp)) {
return;
}
@@ -331,6 +331,10 @@ export function parseTapscriptMultisig(script: string): undefined | { m: number,
return;
}
+ if (finalOp === 'OP_GREATERTHAN') {
+ m += 1;
+ }
+
if (ops.length % 3 !== 0) {
return;
}
From 322e81d3edcbea536274ea72110188e4f333bc40 Mon Sep 17 00:00:00 2001
From: natsoni
Date: Fri, 14 Mar 2025 14:59:15 +0100
Subject: [PATCH 18/48] Parse tapscript unanimous n-of-n multisig
---
frontend/src/app/shared/script.utils.ts | 52 +++++++++++++++++++++++++
1 file changed, 52 insertions(+)
diff --git a/frontend/src/app/shared/script.utils.ts b/frontend/src/app/shared/script.utils.ts
index f0c4701db..8453bdd63 100644
--- a/frontend/src/app/shared/script.utils.ts
+++ b/frontend/src/app/shared/script.utils.ts
@@ -256,6 +256,11 @@ export function detectScriptTemplate(type: ScriptType, script_asm: string, witne
return ScriptTemplates.multisig(tapscriptMultisig.m, tapscriptMultisig.n);
}
+ const tapscriptUnanimousMultisig = parseTapscriptUnanimousMultisig(script_asm);
+ if (tapscriptUnanimousMultisig) {
+ return ScriptTemplates.multisig(tapscriptUnanimousMultisig, tapscriptUnanimousMultisig);
+ }
+
return;
}
@@ -366,6 +371,53 @@ export function parseTapscriptMultisig(script: string): undefined | { m: number,
return { m, n };
}
+export function parseTapscriptUnanimousMultisig(script: string): undefined | number {
+ if (!script) {
+ return;
+ }
+
+ const ops = script.split(' ');
+ // At minimum, 2 pubkey group (3 tokens) = 6 tokens
+ if (ops.length < 6) {
+ return;
+ }
+
+ if (ops.length % 3 !== 0) {
+ return;
+ }
+
+ const n = ops.length / 3;
+
+ for (let i = 0; i < n; i++) {
+ const pushOp = ops.shift();
+ const pubkey = ops.shift();
+ const sigOp = ops.shift();
+
+ if (pushOp !== 'OP_PUSHBYTES_32') {
+ return;
+ }
+ if (!/^[0-9a-fA-F]{64}$/.test(pubkey)) {
+ return;
+ }
+ if (i < n - 1) {
+ if (sigOp !== 'OP_CHECKSIGVERIFY') {
+ return;
+ }
+ } else {
+ // Last opcode can be either CHECKSIG or CHECKSIGVERIFY
+ if (!(sigOp === 'OP_CHECKSIGVERIFY' || sigOp === 'OP_CHECKSIG')) {
+ return;
+ }
+ }
+ }
+
+ if (ops.length) {
+ return;
+ }
+
+ return n;
+}
+
export function getVarIntLength(n: number): number {
if (n < 0xfd) {
return 1;
From 2945e47eba9583cf2826d2ca9f159f9707eec563 Mon Sep 17 00:00:00 2001
From: nymkappa <1612910616@pm.me>
Date: Wed, 26 Mar 2025 23:05:43 +0100
Subject: [PATCH 19/48] [blocks] respect 404 error code instead of misleading
500
---
backend/src/api/bitcoin/bitcoin.routes.ts | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/backend/src/api/bitcoin/bitcoin.routes.ts b/backend/src/api/bitcoin/bitcoin.routes.ts
index 73a14ba4e..3cf2923f1 100644
--- a/backend/src/api/bitcoin/bitcoin.routes.ts
+++ b/backend/src/api/bitcoin/bitcoin.routes.ts
@@ -406,8 +406,8 @@ class BitcoinRoutes {
res.setHeader('Expires', new Date(Date.now() + 1000 * cacheDuration).toUTCString());
res.json(block);
- } catch (e) {
- handleError(req, res, 500, 'Failed to get block');
+ } catch (e: any) {
+ handleError(req, res, e?.response?.status === 404 ? 404 : 500, 'Failed to get block');
}
}
From b153d21162aea4e51ee773fe96bf24137a14bf0b Mon Sep 17 00:00:00 2001
From: Mononaut
Date: Mon, 10 Mar 2025 04:35:52 +0000
Subject: [PATCH 20/48] automatically fetch enabled wallets from services
backend
---
backend/src/api/services/wallets.ts | 33 ++++++++++++++++++++++++++
backend/src/config.ts | 2 ++
production/mempool-config.mainnet.json | 1 +
3 files changed, 36 insertions(+)
diff --git a/backend/src/api/services/wallets.ts b/backend/src/api/services/wallets.ts
index dd4d7ebc9..f498a80ad 100644
--- a/backend/src/api/services/wallets.ts
+++ b/backend/src/api/services/wallets.ts
@@ -30,6 +30,7 @@ const POLL_FREQUENCY = 5 * 60 * 1000; // 5 minutes
class WalletApi {
private wallets: Record = {};
private syncing = false;
+ private lastSync = 0;
constructor() {
this.wallets = config.WALLETS.ENABLED ? (config.WALLETS.WALLETS as string[]).reduce((acc, wallet) => {
@@ -47,7 +48,38 @@ class WalletApi {
if (!config.WALLETS.ENABLED || this.syncing) {
return;
}
+
this.syncing = true;
+
+ if (config.WALLETS.AUTO && (Date.now() - this.lastSync) > POLL_FREQUENCY) {
+ try {
+ // update list of active wallets
+ this.lastSync = Date.now();
+ const response = await axios.get(config.MEMPOOL_SERVICES.API + `/wallets`);
+ const walletList: string[] = response.data;
+ if (walletList) {
+ // create a quick lookup dictionary of active wallets
+ const newWallets: Record = Object.fromEntries(
+ walletList.map(wallet => [wallet, true])
+ );
+ for (const wallet of walletList) {
+ // don't overwrite existing wallets
+ if (!this.wallets[wallet]) {
+ this.wallets[wallet] = { name: wallet, addresses: {}, lastPoll: 0 };
+ }
+ }
+ // remove wallets that are no longer active
+ for (const wallet of Object.keys(this.wallets)) {
+ if (!newWallets[wallet]) {
+ delete this.wallets[wallet];
+ }
+ }
+ }
+ } catch (e) {
+ logger.err(`Error updating active wallets: ${(e instanceof Error ? e.message : e)}`);
+ }
+ }
+
for (const walletKey of Object.keys(this.wallets)) {
const wallet = this.wallets[walletKey];
if (wallet.lastPoll < (Date.now() - POLL_FREQUENCY)) {
@@ -72,6 +104,7 @@ class WalletApi {
}
}
}
+
this.syncing = false;
}
diff --git a/backend/src/config.ts b/backend/src/config.ts
index a1050a7d5..3fe3db2ee 100644
--- a/backend/src/config.ts
+++ b/backend/src/config.ts
@@ -164,6 +164,7 @@ interface IConfig {
},
WALLETS: {
ENABLED: boolean;
+ AUTO: boolean;
WALLETS: string[];
},
STRATUM: {
@@ -334,6 +335,7 @@ const defaults: IConfig = {
},
'WALLETS': {
'ENABLED': false,
+ 'AUTO': false,
'WALLETS': [],
},
'STRATUM': {
diff --git a/production/mempool-config.mainnet.json b/production/mempool-config.mainnet.json
index 9505601d2..87f58f916 100644
--- a/production/mempool-config.mainnet.json
+++ b/production/mempool-config.mainnet.json
@@ -159,6 +159,7 @@
},
"WALLETS": {
"ENABLED": true,
+ "AUTO": true,
"WALLETS": ["BITB", "3350"]
},
"STRATUM": {
From 072b83243e5202de0b2722855d8f66ca22031f18 Mon Sep 17 00:00:00 2001
From: Mononaut
Date: Mon, 10 Mar 2025 04:38:51 +0000
Subject: [PATCH 21/48] update custom dashboard config
---
frontend/custom-sv-config.json | 15 ++++++++-------
1 file changed, 8 insertions(+), 7 deletions(-)
diff --git a/frontend/custom-sv-config.json b/frontend/custom-sv-config.json
index dee3dab18..9a61704a2 100644
--- a/frontend/custom-sv-config.json
+++ b/frontend/custom-sv-config.json
@@ -16,10 +16,10 @@
"mobileOrder": 4
},
{
- "component": "balance",
+ "component": "walletBalance",
"mobileOrder": 1,
"props": {
- "address": "32ixEdVJWo3kmvJGMTZq5jAQVZZeuwnqzo"
+ "wallet": "ONBTC"
}
},
{
@@ -30,21 +30,22 @@
}
},
{
- "component": "address",
+ "component": "wallet",
"mobileOrder": 2,
"props": {
- "address": "32ixEdVJWo3kmvJGMTZq5jAQVZZeuwnqzo",
- "period": "1m"
+ "wallet": "ONBTC",
+ "period": "1m",
+ "label": "bitcoin.gob.sv"
}
},
{
"component": "blocks"
},
{
- "component": "addressTransactions",
+ "component": "walletTransactions",
"mobileOrder": 3,
"props": {
- "address": "32ixEdVJWo3kmvJGMTZq5jAQVZZeuwnqzo"
+ "wallet": "ONBTC"
}
}
]
From 3056454389ea80380920ef8e702089e9bb629f55 Mon Sep 17 00:00:00 2001
From: Mononaut
Date: Wed, 26 Feb 2025 04:48:22 +0000
Subject: [PATCH 22/48] Add configurable label to balance widget
---
.../address-graph/address-graph.component.ts | 22 +++++++++++++++++++
.../custom-dashboard.component.html | 4 ++--
frontend/src/app/graphs/echarts.ts | 4 ++--
3 files changed, 26 insertions(+), 4 deletions(-)
diff --git a/frontend/src/app/components/address-graph/address-graph.component.ts b/frontend/src/app/components/address-graph/address-graph.component.ts
index 2bbfd5e34..005c64e9f 100644
--- a/frontend/src/app/components/address-graph/address-graph.component.ts
+++ b/frontend/src/app/components/address-graph/address-graph.component.ts
@@ -44,6 +44,7 @@ export class AddressGraphComponent implements OnChanges, OnDestroy {
@Input() right: number | string = 10;
@Input() left: number | string = 70;
@Input() widget: boolean = false;
+ @Input() label: string = '';
@Input() defaultFiat: boolean = false;
@Input() showLegend: boolean = true;
@Input() showYAxis: boolean = true;
@@ -55,6 +56,7 @@ export class AddressGraphComponent implements OnChanges, OnDestroy {
hoverData: any[] = [];
conversions: any;
allowZoom: boolean = false;
+ labelGraphic: any;
selected = { [$localize`:@@7e69426bd97a606d8ae6026762858e6e7c86a1fd:Balance`]: true, 'Fiat': false };
@@ -85,6 +87,18 @@ export class AddressGraphComponent implements OnChanges, OnDestroy {
ngOnChanges(changes: SimpleChanges): void {
this.isLoading = true;
+ this.labelGraphic = this.label ? {
+ type: 'text',
+ right: '36px',
+ bottom: '36px',
+ z: 100,
+ silent: true,
+ style: {
+ fill: '#fff',
+ text: this.label,
+ font: '24px sans-serif'
+ }
+ } : undefined;
if (!this.addressSummary$ && (!this.address || !this.stats)) {
return;
}
@@ -205,6 +219,10 @@ export class AddressGraphComponent implements OnChanges, OnDestroy {
right: this.adjustedRight,
left: this.adjustedLeft,
},
+ graphic: this.labelGraphic ? [{
+ ...this.labelGraphic,
+ right: this.adjustedRight + 22 + 'px',
+ }] : undefined,
legend: (this.showLegend && !this.stateService.isAnyTestnet()) ? {
data: [
{
@@ -443,6 +461,10 @@ export class AddressGraphComponent implements OnChanges, OnDestroy {
right: this.adjustedRight,
left: this.adjustedLeft,
},
+ graphic: this.labelGraphic ? [{
+ ...this.labelGraphic,
+ right: this.adjustedRight + 22 + 'px',
+ }] : undefined,
legend: {
selected: this.selected,
},
diff --git a/frontend/src/app/components/custom-dashboard/custom-dashboard.component.html b/frontend/src/app/components/custom-dashboard/custom-dashboard.component.html
index 8ca1a5ac4..defb7c068 100644
--- a/frontend/src/app/components/custom-dashboard/custom-dashboard.component.html
+++ b/frontend/src/app/components/custom-dashboard/custom-dashboard.component.html
@@ -238,7 +238,7 @@
-
+
@@ -272,7 +272,7 @@
-
+
diff --git a/frontend/src/app/graphs/echarts.ts b/frontend/src/app/graphs/echarts.ts
index 67ed7e3b8..36a0517e4 100644
--- a/frontend/src/app/graphs/echarts.ts
+++ b/frontend/src/app/graphs/echarts.ts
@@ -1,7 +1,7 @@
// Import tree-shakeable echarts
import * as echarts from 'echarts/core';
import { LineChart, LinesChart, BarChart, TreemapChart, PieChart, ScatterChart, GaugeChart, CustomChart } from 'echarts/charts';
-import { TitleComponent, TooltipComponent, GridComponent, LegendComponent, GeoComponent, DataZoomComponent, VisualMapComponent, MarkLineComponent } from 'echarts/components';
+import { TitleComponent, TooltipComponent, GridComponent, LegendComponent, GeoComponent, DataZoomComponent, VisualMapComponent, MarkLineComponent, GraphicComponent } from 'echarts/components';
import { SVGRenderer, CanvasRenderer } from 'echarts/renderers';
// Typescript interfaces
import { EChartsOption, TreemapSeriesOption, LineSeriesOption, PieSeriesOption } from 'echarts';
@@ -13,6 +13,6 @@ echarts.use([
LegendComponent, GeoComponent, DataZoomComponent,
VisualMapComponent, MarkLineComponent,
LineChart, LinesChart, BarChart, TreemapChart, PieChart, ScatterChart, GaugeChart,
- CustomChart,
+ CustomChart, GraphicComponent
]);
export { echarts, EChartsOption, TreemapSeriesOption, LineSeriesOption, PieSeriesOption };
\ No newline at end of file
From fb50ea7a6d06e3a4a28db3061d8b2ba74bedafee Mon Sep 17 00:00:00 2001
From: Mononaut
Date: Tue, 4 Feb 2025 12:02:12 +0000
Subject: [PATCH 23/48] detect and warn about address poisoning attacks
---
.../transactions-list.component.html | 21 ++-
.../transactions-list.component.ts | 56 +++++++
frontend/src/app/shared/address-utils.ts | 145 ++++++++++++++++++
.../address-text/address-text.component.html | 17 ++
.../address-text/address-text.component.scss | 32 ++++
.../address-text/address-text.component.ts | 20 +++
frontend/src/app/shared/shared.module.ts | 6 +-
7 files changed, 290 insertions(+), 7 deletions(-)
create mode 100644 frontend/src/app/shared/components/address-text/address-text.component.html
create mode 100644 frontend/src/app/shared/components/address-text/address-text.component.scss
create mode 100644 frontend/src/app/shared/components/address-text/address-text.component.ts
diff --git a/frontend/src/app/components/transactions-list/transactions-list.component.html b/frontend/src/app/components/transactions-list/transactions-list.component.html
index 6f1d76538..7721298fb 100644
--- a/frontend/src/app/components/transactions-list/transactions-list.component.html
+++ b/frontend/src/app/components/transactions-list/transactions-list.component.html
@@ -16,6 +16,11 @@
|