diff --git a/frontend/src/app/components/accelerate-preview/accelerate-preview.component.html b/frontend/src/app/components/accelerate-preview/accelerate-preview.component.html
index f6c3e6ecf..65fea39a3 100644
--- a/frontend/src/app/components/accelerate-preview/accelerate-preview.component.html
+++ b/frontend/src/app/components/accelerate-preview/accelerate-preview.component.html
@@ -286,14 +286,17 @@
-
-
Accelerate with
-
-
-
Loading
-
+ @if (!hideCashApp && paymentType === 'cashapp') {
+
+
-
+ }
diff --git a/frontend/src/app/components/accelerate-preview/accelerate-preview.component.scss b/frontend/src/app/components/accelerate-preview/accelerate-preview.component.scss
index 2e2b19ee8..e9ff233ae 100644
--- a/frontend/src/app/components/accelerate-preview/accelerate-preview.component.scss
+++ b/frontend/src/app/components/accelerate-preview/accelerate-preview.component.scss
@@ -109,4 +109,53 @@
.item {
white-space: initial;
+}
+
+.cashapp-cta {
+ width: 100%;
+ height: 54px;
+ background: #653b9c;
+ position: relative;
+ bottom: initial;
+ top: initial;
+ border-radius: 3px;
+ font-size: 14px;
+ line-height: 16px;
+ text-align: center;
+ padding: 4px 6px;
+ cursor: pointer;
+ box-shadow: 0px 0px 15px 0px #000;
+
+ &.sticky-top {
+ position: fixed;
+ width: calc(100vw - 30px - 1.5rem);
+ margin: auto;
+ z-index: 50;
+ left: 0;
+ right: 0;
+ top: 102px;
+ @media (min-width: 573px) {
+ top: 62px;
+ }
+ }
+ &.sticky-bottom {
+ position: fixed;
+ width: calc(100vw - 30px - 1.5rem);
+ margin: auto;
+ z-index: 50;
+ left: 0;
+ right: 0;
+ bottom: 50px;
+ @media (min-width: 430px) {
+ bottom: 56px;
+ }
+ }
+}
+
+.cashapp-placeholder {
+ height: 54px;
+
+ &.non-stick {
+ height: 0px;
+ }
}
\ No newline at end of file
diff --git a/frontend/src/app/components/accelerate-preview/accelerate-preview.component.ts b/frontend/src/app/components/accelerate-preview/accelerate-preview.component.ts
index aee0189aa..e88337ac3 100644
--- a/frontend/src/app/components/accelerate-preview/accelerate-preview.component.ts
+++ b/frontend/src/app/components/accelerate-preview/accelerate-preview.component.ts
@@ -1,4 +1,4 @@
-import { Component, OnInit, Input, OnDestroy, OnChanges, SimpleChanges, HostListener, ChangeDetectorRef } from '@angular/core';
+import { Component, OnInit, Input, OnDestroy, OnChanges, SimpleChanges, HostListener, ChangeDetectorRef, ViewChild, ElementRef } from '@angular/core';
import { Subscription, catchError, of, tap } from 'rxjs';
import { StorageService } from '../../services/storage.service';
import { Transaction } from '../../interfaces/electrs.interface';
@@ -43,6 +43,9 @@ export class AcceleratePreviewComponent implements OnInit, OnDestroy, OnChanges
@Input() tx: Transaction | undefined;
@Input() scrollEvent: boolean;
+ @ViewChild('cashappCTA')
+ cashappCTA: ElementRef;
+
math = Math;
error = '';
showSuccess = false;
@@ -59,6 +62,7 @@ export class AcceleratePreviewComponent implements OnInit, OnDestroy, OnChanges
selectFeeRateIndex = 1;
isMobile: boolean = window.innerWidth <= 767.98;
user: any = undefined;
+ stickyCTA: string = 'non-stick';
maxRateOptions: RateOption[] = [];
@@ -66,6 +70,7 @@ export class AcceleratePreviewComponent implements OnInit, OnDestroy, OnChanges
paymentType: 'bitcoin' | 'cashapp' = 'bitcoin';
cashAppSubscription: Subscription;
conversionsSubscription: Subscription;
+ cashappSubmit: any;
payments: any;
showSpinner = false;
square: any;
@@ -96,14 +101,14 @@ export class AcceleratePreviewComponent implements OnInit, OnDestroy, OnChanges
ngOnInit() {
if (this.stateService.ref === 'https://cash.app/') {
this.paymentType = 'cashapp';
- this.stateService.ref = '';
} else {
this.paymentType = 'bitcoin';
}
+ this.onScroll();
}
ngOnChanges(changes: SimpleChanges): void {
- if (changes.scrollEvent) {
+ if (changes.scrollEvent && this.paymentType !== 'cashapp') {
this.scrollToPreview('acceleratePreviewAnchor', 'start');
}
}
@@ -173,10 +178,11 @@ export class AcceleratePreviewComponent implements OnInit, OnDestroy, OnChanges
this.maxCost = this.userBid + this.estimate.mempoolBaseFee + this.estimate.vsizeFee;
if (!this.error) {
- this.scrollToPreview('acceleratePreviewAnchor', 'start');
if (this.paymentType === 'cashapp') {
this.setupSquare();
- }
+ } else {
+ this.scrollToPreview('acceleratePreviewAnchor', 'start');
+ }
}
}
}),
@@ -310,13 +316,15 @@ export class AcceleratePreviewComponent implements OnInit, OnDestroy, OnChanges
label: 'Total',
pending: true,
productUrl: `https://mempool.space/tx/${this.tx.txid}`,
- }
+ },
+ button: { shape: 'semiround', size: 'small', theme: 'light'}
});
this.cashAppPay = await this.payments.cashAppPay(paymentRequest, {
redirectURL: `https://mempool.space/tx/${this.tx.txid}`,
referenceId: `accelerator-${this.tx.txid.substring(0, 15)}-${Math.round(new Date().getTime() / 1000)}`,
+ button: { shape: 'semiround', size: 'small', theme: 'light'}
});
- await this.cashAppPay.attach('#cash-app-pay');
+ const renderPromise = this.cashAppPay.CashAppPayInstance.render('#cash-app-pay', { button: { theme: 'light', size: 'small', shape: 'semiround' }, manage: false });
this.showSpinner = false;
const that = this;
@@ -351,6 +359,8 @@ export class AcceleratePreviewComponent implements OnInit, OnDestroy, OnChanges
});
}
});
+
+ this.cashappSubmit = await renderPromise;
}
);
}
@@ -367,4 +377,28 @@ export class AcceleratePreviewComponent implements OnInit, OnDestroy, OnChanges
g.type='text/javascript'; g.src=statsUrl; s.parentNode.insertBefore(g, s);
})();
}
+
+ submitCashappPay(): void {
+ if (this.cashappSubmit) {
+ this.cashappSubmit?.begin();
+ }
+ }
+
+ @HostListener('window:scroll', ['$event']) // for window scroll events
+ onScroll() {
+ if (!this.cashappCTA?.nativeElement || this.paymentType !== 'cashapp' || !this.isMobile) {
+ return;
+ }
+ const cta = this.cashappCTA.nativeElement;
+ const rect = cta.getBoundingClientRect();
+ const topOffset = window.innerWidth <= 572 ? 102 : 62;
+ const bottomOffset = window.innerWidth < 430 ? 50 : 56;
+ if (rect.top < topOffset) {
+ this.stickyCTA = 'sticky-top';
+ } else if (rect.top > window.innerHeight - (bottomOffset + 54)) {
+ this.stickyCTA = 'sticky-bottom';
+ } else {
+ this.stickyCTA = 'non-stick';
+ }
+ }
}
diff --git a/frontend/src/app/components/transaction/transaction.component.html b/frontend/src/app/components/transaction/transaction.component.html
index d7e8de6a6..d92a653db 100644
--- a/frontend/src/app/components/transaction/transaction.component.html
+++ b/frontend/src/app/components/transaction/transaction.component.html
@@ -80,7 +80,9 @@
@@ -409,9 +411,6 @@
} @else {
- @if (isMobile) {
-
- }
}
@if (tx?.status?.confirmed) {
@@ -533,7 +532,7 @@
} @else if (this.mempoolPosition.block >= 7) {
In several hours (or more)
- @if (!isMobile && !tx.acceleration && acceleratorAvailable && accelerateCtaType === 'button' && !tx?.acceleration) {
+ @if (!(isMobile && paymentType === 'cashapp') && !tx.acceleration && acceleratorAvailable && accelerateCtaType === 'button' && !tx?.acceleration) {
Accelerate
}
@@ -542,7 +541,7 @@
} @else {
- @if (!isMobile && !tx.acceleration && acceleratorAvailable && accelerateCtaType === 'button' && !tx?.acceleration) {
+ @if (!(isMobile && paymentType === 'cashapp') && !tx.acceleration && acceleratorAvailable && accelerateCtaType === 'button' && !tx?.acceleration) {
Accelerate
}
@@ -555,18 +554,6 @@
}
-
- @if (!isLoadingTx) {
-
-
- Accelerate
- |
-
- } @else {
-
- }
-
-
@if (!isLoadingTx) {
@if (((auditStatus && auditStatus.accelerated) || accelerationInfo || (tx && tx.acceleration)) || filters.length) {
diff --git a/frontend/src/app/components/transaction/transaction.component.ts b/frontend/src/app/components/transaction/transaction.component.ts
index ab55d706a..01f42a17f 100644
--- a/frontend/src/app/components/transaction/transaction.component.ts
+++ b/frontend/src/app/components/transaction/transaction.component.ts
@@ -117,6 +117,8 @@ export class TransactionComponent implements OnInit, AfterViewInit, OnDestroy {
flowEnabled: boolean;
tooltipPosition: { x: number, y: number };
isMobile: boolean;
+ paymentType: 'bitcoin' | 'cashapp' = 'bitcoin';
+ firstLoad = true;
featuresEnabled: boolean;
segwitEnabled: boolean;
@@ -154,6 +156,11 @@ export class TransactionComponent implements OnInit, AfterViewInit, OnDestroy {
ngOnInit() {
this.acceleratorAvailable = this.stateService.env.OFFICIAL_MEMPOOL_SPACE && this.stateService.env.ACCELERATOR && this.stateService.network === '';
+ if (this.acceleratorAvailable && this.stateService.ref === 'https://cash.app/') {
+ this.showAccelerationSummary = true;
+ this.paymentType = 'cashapp';
+ }
+
this.enterpriseService.page();
this.websocketService.want(['blocks', 'mempool-blocks']);
@@ -720,6 +727,11 @@ export class TransactionComponent implements OnInit, AfterViewInit, OnDestroy {
}
resetTransaction() {
+ if (!this.firstLoad) {
+ this.stateService.ref = '';
+ } else {
+ this.firstLoad = false;
+ }
this.error = undefined;
this.tx = null;
this.setFeatures();
@@ -814,6 +826,7 @@ export class TransactionComponent implements OnInit, AfterViewInit, OnDestroy {
}
ngOnDestroy() {
+ this.stateService.ref = '';
this.subscription.unsubscribe();
this.fetchCpfpSubscription.unsubscribe();
this.fetchRbfSubscription.unsubscribe();