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 637eaee1d..9851b9bd0 100644 --- a/frontend/src/app/components/accelerate-preview/accelerate-preview.component.html +++ b/frontend/src/app/components/accelerate-preview/accelerate-preview.component.html @@ -14,7 +14,6 @@ -@if (!processingPayment) {

- @if (paymentType !== 'cashapp') { -
How much more are you willing to pay?
-
-
- Choose the maximum extra transaction fee you're willing to pay to get into the next block. -
-
-
- - - -
+
How much more are you willing to pay?
+
+
+ Choose the maximum extra transaction fee you're willing to pay to get into the next block. +
+
+
+ + +
- } +
Acceleration summary
@@ -93,51 +90,27 @@ - @if (paymentType === 'cashapp') { - - - - - - - - - - - - - } @else { - - - - - - - - - - - - - } + + + + + + + + + + + + @@ -169,75 +142,53 @@ - @if (paymentType === 'cashapp') { - - - - - - - - - } @else { - - - - - - - - - - - - - - - - - - - - - - - - } + + + + + + + + + + + + + + + + + + + + + + + @@ -256,7 +207,7 @@ - + @@ -279,25 +230,13 @@ -
+
- - @if (!hideCashApp && paymentType === 'cashapp') { -
-
-
Accelerate for with
-
-
- Loading -
-
-
- }
@@ -307,9 +246,5 @@

-} -@else if (!showSuccess && !error) { -
Processing payment...
-} If your tx is accelerated to ~{{ i | number : '1.0-0' }} sat/vB \ No newline at end of file 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 1f73ea9b2..289d4b034 100644 --- a/frontend/src/app/components/accelerate-preview/accelerate-preview.component.scss +++ b/frontend/src/app/components/accelerate-preview/accelerate-preview.component.scss @@ -110,60 +110,3 @@ .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; - } - } - - @media (max-width: 400px) { - width: calc(100% + 1.5rem); - margin: 0 -0.75rem; - &.sticky-top, &.sticky-bottom { - width: calc(100vw - 30px); - } - } -} - -.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 ec36107a4..eaa995683 100644 --- a/frontend/src/app/components/accelerate-preview/accelerate-preview.component.ts +++ b/frontend/src/app/components/accelerate-preview/accelerate-preview.component.ts @@ -43,9 +43,6 @@ export class AcceleratePreviewComponent implements OnInit, OnDestroy, OnChanges @Input() tx: Transaction | undefined; @Input() scrollEvent: boolean; - @ViewChild('cashappCTA') - cashappCTA: ElementRef; - math = Math; error = ''; showSuccess = false; @@ -63,22 +60,9 @@ export class AcceleratePreviewComponent implements OnInit, OnDestroy, OnChanges selectFeeRateIndex = 1; isMobile: boolean = window.innerWidth <= 767.98; user: any = undefined; - stickyCTA: string = 'non-stick'; maxRateOptions: RateOption[] = []; - // Cashapp payment - paymentType: 'bitcoin' | 'cashapp' = 'bitcoin'; - cashAppSubscription: Subscription; - conversionsSubscription: Subscription; - cashappSubmit: any; - payments: any; - showSpinner = false; - square: any; - cashAppPay: any; - hideCashApp = false; - processingPayment = false; - constructor( public stateService: StateService, private servicesApiService: ServicesApiServices, @@ -86,132 +70,91 @@ export class AcceleratePreviewComponent implements OnInit, OnDestroy, OnChanges private audioService: AudioService, private cd: ChangeDetectorRef ) { - const urlParams = new URLSearchParams(window.location.search); - if (urlParams.get('cash_request_id')) { - this.processingPayment = true; - this.scrollToPreviewWithTimeout('successAlert', 'center'); - } - - if (this.stateService.ref === 'https://cash.app/') { - this.paymentType = 'cashapp'; - this.insertSquare(); - } else { - this.paymentType = 'bitcoin'; - } } ngOnDestroy(): void { if (this.estimateSubscription) { this.estimateSubscription.unsubscribe(); } - if (this.cashAppPay) { - this.cashAppPay.destroy(); - } } ngOnInit() { this.accelerationUUID = window.crypto.randomUUID(); - if (this.stateService.ref === 'https://cash.app/') { - this.paymentType = 'cashapp'; - } else { - this.paymentType = 'bitcoin'; - } } ngOnChanges(changes: SimpleChanges): void { - if (changes.scrollEvent && this.paymentType !== 'cashapp' && this.stateService.ref !== 'https://cash.app/') { + if (changes.scrollEvent) { this.scrollToPreview('acceleratePreviewAnchor', 'start'); } } ngAfterViewInit() { - this.onScroll(); - - if (this.paymentType === 'cashapp') { - this.showSpinner = true; - } - this.user = this.storageService.getAuth()?.user ?? null; - this.servicesApiService.setupSquare$().subscribe(ids => { - this.square = { - appId: ids.squareAppId, - locationId: ids.squareLocationId - }; - this.estimateSubscription = this.servicesApiService.estimate$(this.tx.txid).pipe( - tap((response) => { - if (response.status === 204) { - this.estimate = undefined; + this.estimateSubscription = this.servicesApiService.estimate$(this.tx.txid).pipe( + tap((response) => { + if (response.status === 204) { + this.estimate = undefined; + this.error = `cannot_accelerate_tx`; + this.scrollToPreviewWithTimeout('mempoolError', 'center'); + this.estimateSubscription.unsubscribe(); + } else { + this.estimate = response.body; + if (!this.estimate) { this.error = `cannot_accelerate_tx`; this.scrollToPreviewWithTimeout('mempoolError', 'center'); this.estimateSubscription.unsubscribe(); - } else { - this.estimate = response.body; - if (!this.estimate) { - this.error = `cannot_accelerate_tx`; + } + + if (this.estimate.hasAccess === true && this.estimate.userBalance <= 0) { + if (this.isLoggedIn()) { + this.error = `not_enough_balance`; this.scrollToPreviewWithTimeout('mempoolError', 'center'); - this.estimateSubscription.unsubscribe(); - } - - if (this.paymentType === 'cashapp') { - this.estimate.userBalance = 999999999; - this.estimate.enoughBalance = true; - } - - if (this.estimate.hasAccess === true && this.estimate.userBalance <= 0) { - if (this.isLoggedIn()) { - this.error = `not_enough_balance`; - this.scrollToPreviewWithTimeout('mempoolError', 'center'); - } - } - - this.hasAncestors = this.estimate.txSummary.ancestorCount > 1; - - // Make min extra fee at least 50% of the current tx fee - this.minExtraCost = nextRoundNumber(Math.max(this.estimate.cost * 2, this.estimate.txSummary.effectiveFee)); - - this.maxRateOptions = [1, 2, 4].map((multiplier, index) => { - return { - fee: this.minExtraCost * multiplier, - rate: (this.estimate.txSummary.effectiveFee + (this.minExtraCost * multiplier)) / this.estimate.txSummary.effectiveVsize, - index, - }; - }); - - this.minBidAllowed = this.minExtraCost * MIN_BID_RATIO; - this.defaultBid = this.minExtraCost * DEFAULT_BID_RATIO; - this.maxBidAllowed = this.minExtraCost * MAX_BID_RATIO; - - this.userBid = this.defaultBid; - if (this.userBid < this.minBidAllowed) { - this.userBid = this.minBidAllowed; - } else if (this.userBid > this.maxBidAllowed) { - this.userBid = this.maxBidAllowed; - } - this.maxCost = this.userBid + this.estimate.mempoolBaseFee + this.estimate.vsizeFee; - - if (!this.error) { - if (this.paymentType === 'cashapp') { - this.setupSquare(); - } else { - this.scrollToPreview('acceleratePreviewAnchor', 'start'); - } - - setTimeout(() => { - this.onScroll(); - }, 100); } } - }), - catchError((response) => { - this.estimate = undefined; - this.error = response.error; - this.scrollToPreviewWithTimeout('mempoolError', 'center'); - this.estimateSubscription.unsubscribe(); - return of(null); - }) - ).subscribe(); - }); + + this.hasAncestors = this.estimate.txSummary.ancestorCount > 1; + + // Make min extra fee at least 50% of the current tx fee + this.minExtraCost = nextRoundNumber(Math.max(this.estimate.cost * 2, this.estimate.txSummary.effectiveFee)); + + this.maxRateOptions = [1, 2, 4].map((multiplier, index) => { + return { + fee: this.minExtraCost * multiplier, + rate: (this.estimate.txSummary.effectiveFee + (this.minExtraCost * multiplier)) / this.estimate.txSummary.effectiveVsize, + index, + }; + }); + + this.minBidAllowed = this.minExtraCost * MIN_BID_RATIO; + this.defaultBid = this.minExtraCost * DEFAULT_BID_RATIO; + this.maxBidAllowed = this.minExtraCost * MAX_BID_RATIO; + + this.userBid = this.defaultBid; + if (this.userBid < this.minBidAllowed) { + this.userBid = this.minBidAllowed; + } else if (this.userBid > this.maxBidAllowed) { + this.userBid = this.maxBidAllowed; + } + this.maxCost = this.userBid + this.estimate.mempoolBaseFee + this.estimate.vsizeFee; + + if (!this.error) { + this.scrollToPreview('acceleratePreviewAnchor', 'start'); + + setTimeout(() => { + this.onScroll(); + }, 100); + } + } + }), + catchError((response) => { + this.estimate = undefined; + this.error = response.error; + this.scrollToPreviewWithTimeout('mempoolError', 'center'); + this.estimateSubscription.unsubscribe(); + return of(null); + }) + ).subscribe(); } /** @@ -284,155 +227,14 @@ export class AcceleratePreviewComponent implements OnInit, OnDestroy, OnChanges this.isMobile = window.innerWidth <= 767.98; } - /** - * CashApp payment - */ - setupSquare() { - const init = () => { - this.initSquare(); - }; - - //@ts-ignore - if (!window.Square) { - console.warn('Square.js failed to load properly. Retrying in 1 second.'); - setTimeout(init, 1000); - } else { - init(); - } - } - - async initSquare(): Promise { - try { - //@ts-ignore - this.payments = window.Square.payments(this.square.appId, this.square.locationId) - await this.requestCashAppPayment(); - } catch (e) { - console.error(e); - this.error = 'Error loading Square Payments'; - return; - } - } - - async requestCashAppPayment() { - if (this.cashAppSubscription) { - this.cashAppSubscription.unsubscribe(); - } - if (this.conversionsSubscription) { - this.conversionsSubscription.unsubscribe(); - } - this.hideCashApp = false; - - - this.conversionsSubscription = this.stateService.conversions$.subscribe( - async (conversions) => { - if (this.cashAppPay) { - this.cashAppPay.destroy(); - } - - const redirectHostname = document.location.hostname === 'localhost' ? 'http://localhost:4200': 'https://mempool.space'; - const maxCostUsd = this.maxCost / 100_000_000 * conversions.USD; - const paymentRequest = this.payments.paymentRequest({ - countryCode: 'US', - currencyCode: 'USD', - total: { - amount: maxCostUsd.toString(), - label: 'Total', - pending: true, - productUrl: `${redirectHostname}/tx/${this.tx.txid}`, - }, - button: { shape: 'semiround', size: 'small', theme: 'light'} - }); - this.cashAppPay = await this.payments.cashAppPay(paymentRequest, { - redirectURL: `${redirectHostname}/tx/${this.tx.txid}?acceleration=false`, - referenceId: `accelerator-${this.tx.txid.substring(0, 15)}-${Math.round(new Date().getTime() / 1000)}`, - button: { shape: 'semiround', size: 'small', theme: 'light'} - }); - const renderPromise = this.cashAppPay.CashAppPayInstance.render('#cash-app-pay', { button: { theme: 'light', size: 'small', shape: 'semiround' }, manage: false }); - this.showSpinner = false; - - const that = this; - this.cashAppPay.addEventListener('ontokenization', function (event) { - that.processingPayment = true; - that.scrollToPreviewWithTimeout('successAlert', 'center'); - const { tokenResult, error } = event.detail; - if (error) { - this.error = error; - } else if (tokenResult.status === 'OK') { - that.hideCashApp = true; - - that.accelerationSubscription = that.servicesApiService.accelerateWithCashApp$( - that.tx.txid, - tokenResult.token, - tokenResult.details.cashAppPay.cashtag, - tokenResult.details.cashAppPay.referenceId, - that.accelerationUUID - ).subscribe({ - next: () => { - that.audioService.playSound('ascend-chime-cartoon'); - that.showSuccess = true; - that.estimateSubscription.unsubscribe(); - }, - error: (response) => { - if (response.status === 403 && response.error === 'not_available') { - that.error = 'waitlisted'; - } else { - that.error = response.error; - } - that.scrollToPreviewWithTimeout('mempoolError', 'center'); - } - }); - } - }); - - this.cashappSubmit = await renderPromise; - } - ); - } - - insertSquare(): void { - let statsUrl = 'https://sandbox.web.squarecdn.com/v1/square.js'; - if (document.location.hostname === 'mempool-staging.fmt.mempool.space' || - document.location.hostname === 'mempool-staging.va1.mempool.space' || - document.location.hostname === 'mempool-staging.fra.mempool.space' || - document.location.hostname === 'mempool-staging.tk7.mempool.space' || - document.location.hostname === 'mempool.space') { - statsUrl = 'https://web.squarecdn.com/v1/square.js'; - } - - (function() { - const d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0]; - // @ts-ignore - 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.estimate && !this.cashappCTA?.nativeElement) { + if (this.estimate) { setTimeout(() => { this.onScroll(); }, 200); return; } - 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 6b40ca083..da8164e16 100644 --- a/frontend/src/app/components/transaction/transaction.component.html +++ b/frontend/src/app/components/transaction/transaction.component.html @@ -80,9 +80,6 @@

Accelerate

- @if (!(isMobile && paymentType === 'cashapp')) { - - }
@@ -537,16 +534,13 @@ } @else if (this.mempoolPosition.block >= 7) { In several hours (or more) - @if (!(isMobile && paymentType === 'cashapp') && acceleratorAvailable && accelerateCtaType === 'button' && !tx?.acceleration) { - Accelerate - } } @else if (network === 'liquid' || network === 'liquidtestnet') { } @else { - @if (!(isMobile && paymentType === 'cashapp') && !tx.acceleration && acceleratorAvailable && accelerateCtaType === 'button' && !tx?.acceleration) { + @if (!isMobile && !tx.acceleration && acceleratorAvailable && accelerateCtaType === 'button' && !tx?.acceleration) { Accelerate } diff --git a/frontend/src/app/components/transaction/transaction.component.scss b/frontend/src/app/components/transaction/transaction.component.scss index 375b5c4e0..80caa6003 100644 --- a/frontend/src/app/components/transaction/transaction.component.scss +++ b/frontend/src/app/components/transaction/transaction.component.scss @@ -311,13 +311,6 @@ } } -.accelerateFullSize { - width: 100%; - height: 100%; - padding: 0.5rem 0.25rem; - background-color: #653b9c; -} - .goggles-icon { display: block; width: 2.2em; diff --git a/frontend/src/app/components/transaction/transaction.component.ts b/frontend/src/app/components/transaction/transaction.component.ts index aec2c47c8..9abb57654 100644 --- a/frontend/src/app/components/transaction/transaction.component.ts +++ b/frontend/src/app/components/transaction/transaction.component.ts @@ -119,7 +119,6 @@ export class TransactionComponent implements OnInit, AfterViewInit, OnDestroy { flowEnabled: boolean; tooltipPosition: { x: number, y: number }; isMobile: boolean; - paymentType: 'bitcoin' | 'cashapp' = 'bitcoin'; firstLoad = true; featuresEnabled: boolean; @@ -158,11 +157,6 @@ 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']);
Boost rate - {{ maxRateOptions[selectFeeRateIndex].rate | number : '1.0-0' }} - sat/vB
- Boost fee - - {{ maxRateOptions[selectFeeRateIndex].fee | number }} - - sats - -
Next block market rate - {{ estimate.targetFeeRate | number : '1.0-0' }} - sat/vB
- Estimated extra fee required - - {{ math.max(0, estimate.nextBlockFee - estimate.txSummary.effectiveFee) | number }} - - sats - -
Next block market rate + {{ estimate.targetFeeRate | number : '1.0-0' }} + sat/vB
+ Estimated extra fee required + + {{ math.max(0, estimate.nextBlockFee - estimate.txSummary.effectiveFee) | number }} + + sats + +
- Total cost - - - {{ maxCost | number }} - - - sats - - - -
- Estimated acceleration cost - - - {{ estimate.cost + estimate.mempoolBaseFee + estimate.vsizeFee | number }} - - - sats - -
- -
- Maximum acceleration cost - - - {{ maxCost | number }} - - - sats - - - -
- -
+ Estimated acceleration cost + + + {{ estimate.cost + estimate.mempoolBaseFee + estimate.vsizeFee | number }} + + + sats + +
+ +
+ Maximum acceleration cost + + + {{ maxCost | number }} + + + sats + + + +
+ +