mirror of
https://github.com/mempool/mempool.git
synced 2025-02-23 14:40:38 +01:00
Merge pull request #4965 from mempool/nymkappa/remove-prepaid-tx
[accelerator] remove simple mode from tx page
This commit is contained in:
commit
ebe54d47d8
6 changed files with 145 additions and 484 deletions
|
@ -14,7 +14,6 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
@if (!processingPayment) {
|
||||
<div class="accelerate-cols">
|
||||
<ng-container *ngIf="!isMobile">
|
||||
<app-accelerate-fee-graph
|
||||
|
@ -66,26 +65,24 @@
|
|||
</div>
|
||||
</div>
|
||||
<br>
|
||||
@if (paymentType !== 'cashapp') {
|
||||
<h5 i18n="accelerator.pay-how-much">How much more are you willing to pay?</h5>
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<small class="form-text text-muted mb-2" i18n="accelerator.transaction-fee-description">Choose the maximum extra transaction fee you're willing to pay to get into the next block.</small>
|
||||
<div class="form-group">
|
||||
<div class="fee-card">
|
||||
<div class="d-flex mb-0">
|
||||
<ng-container *ngFor="let option of maxRateOptions">
|
||||
<button type="button" class="btn btn-primary flex-grow-1 btn-border btn-sm feerate" [class]="{active: selectFeeRateIndex === option.index}" (click)="setUserBid(option)">
|
||||
<span class="fee">{{ option.fee + estimate.mempoolBaseFee + estimate.vsizeFee | number }} <span class="symbol" i18n="shared.sats">sats</span></span>
|
||||
<span class="rate">~<app-fee-rate [fee]="option.rate" rounding="1.0-0"></app-fee-rate></span>
|
||||
</button>
|
||||
</ng-container>
|
||||
</div>
|
||||
<h5 i18n="accelerator.pay-how-much">How much more are you willing to pay?</h5>
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<small class="form-text text-muted mb-2" i18n="accelerator.transaction-fee-description">Choose the maximum extra transaction fee you're willing to pay to get into the next block.</small>
|
||||
<div class="form-group">
|
||||
<div class="fee-card">
|
||||
<div class="d-flex mb-0">
|
||||
<ng-container *ngFor="let option of maxRateOptions">
|
||||
<button type="button" class="btn btn-primary flex-grow-1 btn-border btn-sm feerate" [class]="{active: selectFeeRateIndex === option.index}" (click)="setUserBid(option)">
|
||||
<span class="fee">{{ option.fee + estimate.mempoolBaseFee + estimate.vsizeFee | number }} <span class="symbol" i18n="shared.sats">sats</span></span>
|
||||
<span class="rate">~<app-fee-rate [fee]="option.rate" rounding="1.0-0"></app-fee-rate></span>
|
||||
</button>
|
||||
</ng-container>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
<h5>Acceleration summary</h5>
|
||||
<div class="row mb-3">
|
||||
|
@ -93,51 +90,27 @@
|
|||
<table class="table table-borderless table-border table-dark table-accelerator">
|
||||
<tbody>
|
||||
<!-- ESTIMATED FEE -->
|
||||
@if (paymentType === 'cashapp') {
|
||||
<ng-container>
|
||||
<tr class="group-first">
|
||||
<td class="item" i18n="accelerator.boost-rate">Boost rate</td>
|
||||
<td class="amt" style="font-size: 16px">
|
||||
{{ maxRateOptions[selectFeeRateIndex].rate | number : '1.0-0' }}
|
||||
</td>
|
||||
<td class="units"><span class="symbol" i18n="shared.sat-vbyte|sat/vB">sat/vB</span></td>
|
||||
</tr>
|
||||
<tr class="info">
|
||||
<td class="info">
|
||||
<i><small i18n="accelerator.estimated-extra-fee-required">Boost fee</small></i>
|
||||
</td>
|
||||
<td class="amt">
|
||||
{{ maxRateOptions[selectFeeRateIndex].fee | number }}
|
||||
</td>
|
||||
<td class="units">
|
||||
<span class="symbol" i18n="shared.sats">sats</span>
|
||||
<span class="fiat ml-1"><app-fiat [value]="maxRateOptions[selectFeeRateIndex].fee"></app-fiat></span>
|
||||
</td>
|
||||
</tr>
|
||||
</ng-container>
|
||||
} @else {
|
||||
<ng-container>
|
||||
<tr class="group-first">
|
||||
<td class="item" i18n="accelerator.next-block-rate">Next block market rate</td>
|
||||
<td class="amt" style="font-size: 16px">
|
||||
{{ estimate.targetFeeRate | number : '1.0-0' }}
|
||||
</td>
|
||||
<td class="units"><span class="symbol" i18n="shared.sat-vbyte|sat/vB">sat/vB</span></td>
|
||||
</tr>
|
||||
<tr class="info">
|
||||
<td class="info">
|
||||
<i><small i18n="accelerator.estimated-extra-fee-required">Estimated extra fee required</small></i>
|
||||
</td>
|
||||
<td class="amt">
|
||||
{{ math.max(0, estimate.nextBlockFee - estimate.txSummary.effectiveFee) | number }}
|
||||
</td>
|
||||
<td class="units">
|
||||
<span class="symbol" i18n="shared.sats">sats</span>
|
||||
<span class="fiat ml-1"><app-fiat [value]="math.max(0, estimate.nextBlockFee - estimate.txSummary.effectiveFee)"></app-fiat></span>
|
||||
</td>
|
||||
</tr>
|
||||
</ng-container>
|
||||
}
|
||||
<ng-container>
|
||||
<tr class="group-first">
|
||||
<td class="item" i18n="accelerator.next-block-rate">Next block market rate</td>
|
||||
<td class="amt" style="font-size: 16px">
|
||||
{{ estimate.targetFeeRate | number : '1.0-0' }}
|
||||
</td>
|
||||
<td class="units"><span class="symbol" i18n="shared.sat-vbyte|sat/vB">sat/vB</span></td>
|
||||
</tr>
|
||||
<tr class="info">
|
||||
<td class="info">
|
||||
<i><small i18n="accelerator.estimated-extra-fee-required">Estimated extra fee required</small></i>
|
||||
</td>
|
||||
<td class="amt">
|
||||
{{ math.max(0, estimate.nextBlockFee - estimate.txSummary.effectiveFee) | number }}
|
||||
</td>
|
||||
<td class="units">
|
||||
<span class="symbol" i18n="shared.sats">sats</span>
|
||||
<span class="fiat ml-1"><app-fiat [value]="math.max(0, estimate.nextBlockFee - estimate.txSummary.effectiveFee)"></app-fiat></span>
|
||||
</td>
|
||||
</tr>
|
||||
</ng-container>
|
||||
|
||||
<!-- MEMPOOL BASE FEE -->
|
||||
<tr>
|
||||
|
@ -169,75 +142,53 @@
|
|||
</tr>
|
||||
|
||||
|
||||
@if (paymentType === 'cashapp') {
|
||||
<!-- FIXED COST -->
|
||||
<ng-container>
|
||||
<tr class="group-first group-last" style="border-top: 1px solid lightgrey; border-collapse: collapse;">
|
||||
<td class="item">
|
||||
<b style="background-color: #105fb0;" class="p-1 pl-0" i18n="accelerator.total-cost">Total cost</b>
|
||||
</td>
|
||||
<td class="amt">
|
||||
<span style="background-color: #105fb0" class="p-1 pl-0">
|
||||
{{ maxCost | number }}
|
||||
</span>
|
||||
</td>
|
||||
<td class="units">
|
||||
<span class="symbol" i18n="shared.sats">sats</span>
|
||||
<span class="fiat ml-1">
|
||||
<app-fiat [value]="maxCost" [colorClass]="'green-color'"></app-fiat>
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
</ng-container>
|
||||
} @else {
|
||||
<!-- NEXT BLOCK ESTIMATE -->
|
||||
<ng-container>
|
||||
<tr class="group-first" style="border-top: 1px dashed grey; border-collapse: collapse;">
|
||||
<td class="item">
|
||||
<b style="background-color: #5E35B1" class="p-1 pl-0" i18n="accelerator.estimated-cost">Estimated acceleration cost</b>
|
||||
</td>
|
||||
<td class="amt">
|
||||
<span style="background-color: #5E35B1" class="p-1 pl-0">
|
||||
{{ estimate.cost + estimate.mempoolBaseFee + estimate.vsizeFee | number }}
|
||||
</span>
|
||||
</td>
|
||||
<td class="units">
|
||||
<span class="symbol" i18n="shared.sats">sats</span>
|
||||
<span class="fiat ml-1"><app-fiat [value]="estimate.cost + estimate.mempoolBaseFee + estimate.vsizeFee"></app-fiat></span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="info group-last" style="border-bottom: 1px solid lightgrey">
|
||||
<td class="info" colspan=3>
|
||||
<i><small><ng-container *ngTemplateOutlet="acceleratedTo; context: {$implicit: estimate.targetFeeRate }"></ng-container></small></i>
|
||||
</td>
|
||||
</tr>
|
||||
</ng-container>
|
||||
|
||||
<!-- MAX COST -->
|
||||
<ng-container>
|
||||
<tr class="group-first">
|
||||
<td class="item">
|
||||
<b style="background-color: var(--primary);" class="p-1 pl-0" i18n="accelerator.maximum-cost">Maximum acceleration cost</b>
|
||||
</td>
|
||||
<td class="amt">
|
||||
<span style="background-color: var(--primary)" class="p-1 pl-0">
|
||||
{{ maxCost | number }}
|
||||
</span>
|
||||
</td>
|
||||
<td class="units">
|
||||
<span class="symbol" i18n="shared.sats">sats</span>
|
||||
<span class="fiat ml-1">
|
||||
<app-fiat [value]="maxCost" [colorClass]="estimate.userBalance < maxCost ? 'red-color' : 'green-color'"></app-fiat>
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="info group-last">
|
||||
<td class="info" colspan=3>
|
||||
<i><small><ng-container *ngTemplateOutlet="acceleratedTo; context: {$implicit: (estimate.txSummary.effectiveFee + userBid) / estimate.txSummary.effectiveVsize }"></ng-container></small></i>
|
||||
</td>
|
||||
</tr>
|
||||
</ng-container>
|
||||
}
|
||||
<!-- NEXT BLOCK ESTIMATE -->
|
||||
<ng-container>
|
||||
<tr class="group-first" style="border-top: 1px dashed grey; border-collapse: collapse;">
|
||||
<td class="item">
|
||||
<b style="background-color: #5E35B1" class="p-1 pl-0" i18n="accelerator.estimated-cost">Estimated acceleration cost</b>
|
||||
</td>
|
||||
<td class="amt">
|
||||
<span style="background-color: #5E35B1" class="p-1 pl-0">
|
||||
{{ estimate.cost + estimate.mempoolBaseFee + estimate.vsizeFee | number }}
|
||||
</span>
|
||||
</td>
|
||||
<td class="units">
|
||||
<span class="symbol" i18n="shared.sats">sats</span>
|
||||
<span class="fiat ml-1"><app-fiat [value]="estimate.cost + estimate.mempoolBaseFee + estimate.vsizeFee"></app-fiat></span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="info group-last" style="border-bottom: 1px solid lightgrey">
|
||||
<td class="info" colspan=3>
|
||||
<i><small><ng-container *ngTemplateOutlet="acceleratedTo; context: {$implicit: estimate.targetFeeRate }"></ng-container></small></i>
|
||||
</td>
|
||||
</tr>
|
||||
</ng-container>
|
||||
|
||||
<!-- MAX COST -->
|
||||
<ng-container>
|
||||
<tr class="group-first">
|
||||
<td class="item">
|
||||
<b style="background-color: var(--primary);" class="p-1 pl-0" i18n="accelerator.maximum-cost">Maximum acceleration cost</b>
|
||||
</td>
|
||||
<td class="amt">
|
||||
<span style="background-color: var(--primary)" class="p-1 pl-0">
|
||||
{{ maxCost | number }}
|
||||
</span>
|
||||
</td>
|
||||
<td class="units">
|
||||
<span class="symbol" i18n="shared.sats">sats</span>
|
||||
<span class="fiat ml-1">
|
||||
<app-fiat [value]="maxCost" [colorClass]="estimate.userBalance < maxCost ? 'red-color' : 'green-color'"></app-fiat>
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="info group-last">
|
||||
<td class="info" colspan=3>
|
||||
<i><small><ng-container *ngTemplateOutlet="acceleratedTo; context: {$implicit: (estimate.txSummary.effectiveFee + userBid) / estimate.txSummary.effectiveVsize }"></ng-container></small></i>
|
||||
</td>
|
||||
</tr>
|
||||
</ng-container>
|
||||
|
||||
<!-- USER BALANCE -->
|
||||
<ng-container *ngIf="isLoggedIn() && estimate.userBalance < maxCost">
|
||||
|
@ -256,7 +207,7 @@
|
|||
</ng-container>
|
||||
|
||||
<!-- LOGIN CTA -->
|
||||
<ng-container *ngIf="stateService.isMempoolSpaceBuild && !isLoggedIn() && paymentType === 'bitcoin'">
|
||||
<ng-container *ngIf="stateService.isMempoolSpaceBuild && !isLoggedIn()">
|
||||
<tr class="group-first group-last" style="border-top: 1px dashed grey">
|
||||
<td class="item"></td>
|
||||
<td class="amt"></td>
|
||||
|
@ -279,25 +230,13 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-3" *ngIf="isLoggedIn() && paymentType === 'bitcoin'">
|
||||
<div class="row mb-3" *ngIf="isLoggedIn()">
|
||||
<div class="col">
|
||||
<div class="d-flex justify-content-end" *ngIf="user && estimate.hasAccess">
|
||||
<button class="btn btn-sm btn-primary btn-success" style="width: 150px" (click)="accelerate()" i18n="transaction.accelerate|Accelerate button label">Accelerate</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@if (!hideCashApp && paymentType === 'cashapp') {
|
||||
<div #cashappCTA class="cashapp-placeholder {{ stickyCTA }}"></div>
|
||||
<div class="d-flex justify-content-center align-items-center cashapp-cta {{ stickyCTA }}" (click)="submitCashappPay()">
|
||||
<div [style]="showSpinner ? 'opacity: 0' : 'opacity: 1'" class="p-2">Accelerate for <app-fiat [value]="maxCost" [colorClass]="estimate.userBalance < maxCost ? 'red-color' : 'green-color'"></app-fiat> with</div>
|
||||
<div id="cash-app-pay" style="max-width: 320px" [style]="showSpinner ? 'opacity: 0' : 'opacity: 1'"></div>
|
||||
<div *ngIf="showSpinner" class="d-flex align-items-center">
|
||||
<span class="mr-2">Loading</span>
|
||||
<div class="spinner-border text-light" style="width: 25px; height: 25px"></div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
</div>
|
||||
</ng-container>
|
||||
|
@ -307,9 +246,5 @@
|
|||
<div class="skeleton-loader"></div>
|
||||
<br>
|
||||
</ng-template>
|
||||
}
|
||||
@else if (!showSuccess && !error) {
|
||||
<div class="alert alert-info">Processing payment...</div>
|
||||
}
|
||||
|
||||
<ng-template #acceleratedTo let-i i18n="accelerator.accelerated-to-description">If your tx is accelerated to ~{{ i | number : '1.0-0' }} sat/vB</ng-template>
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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<void> {
|
||||
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';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -80,9 +80,6 @@
|
|||
<div class="title float-left">
|
||||
<h2 i18n="transaction.accelerate|Accelerate button label">Accelerate</h2>
|
||||
</div>
|
||||
@if (!(isMobile && paymentType === 'cashapp')) {
|
||||
<button type="button" class="btn btn-outline-info accelerator-toggle btn-sm float-right" (click)="showAccelerationSummary = false" i18n="hide-accelerator">Hide accelerator</button>
|
||||
}
|
||||
<div class="clearfix"></div>
|
||||
|
||||
<div class="box">
|
||||
|
@ -537,16 +534,13 @@
|
|||
} @else if (this.mempoolPosition.block >= 7) {
|
||||
<span [class]="(acceleratorAvailable && accelerateCtaType === 'button') ? 'etaDeepMempool d-flex justify-content-end align-items-center' : ''">
|
||||
<span i18n="transaction.eta.in-several-hours|Transaction ETA in several hours or more">In several hours (or more)</span>
|
||||
@if (!(isMobile && paymentType === 'cashapp') && acceleratorAvailable && accelerateCtaType === 'button' && !tx?.acceleration) {
|
||||
<a [href]="'/services/accelerator/accelerate?txid=' + tx.txid" class="btn btn-sm accelerateDeepMempool btn-small-height" i18n="transaction.accelerate|Accelerate button label" (click)="onAccelerateClicked()">Accelerate</a>
|
||||
}
|
||||
</span>
|
||||
} @else if (network === 'liquid' || network === 'liquidtestnet') {
|
||||
<app-time kind="until" [time]="(60 * 1000 * this.mempoolPosition.block) + now" [fastRender]="false" [fixedRender]="true"></app-time>
|
||||
} @else {
|
||||
<span class="eta justify-content-end" [class]="(acceleratorAvailable && accelerateCtaType === 'button') ? 'd-flex align-items-center' : ''">
|
||||
<app-time kind="until" *ngIf="(da$ | async) as da;" [time]="da.adjustedTimeAvg * (this.mempoolPosition.block + 1) + now + da.timeOffset" [fastRender]="false" [fixedRender]="true"></app-time>
|
||||
@if (!(isMobile && paymentType === 'cashapp') && !tx.acceleration && acceleratorAvailable && accelerateCtaType === 'button' && !tx?.acceleration) {
|
||||
@if (!isMobile && !tx.acceleration && acceleratorAvailable && accelerateCtaType === 'button' && !tx?.acceleration) {
|
||||
<a [href]="'/services/accelerator/accelerate?txid=' + tx.txid" class="btn btn-sm accelerate btn-small-height" i18n="transaction.accelerate|Accelerate button label" (click)="onAccelerateClicked()">Accelerate</a>
|
||||
}
|
||||
</span>
|
||||
|
|
|
@ -311,13 +311,6 @@
|
|||
}
|
||||
}
|
||||
|
||||
.accelerateFullSize {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
padding: 0.5rem 0.25rem;
|
||||
background-color: #653b9c;
|
||||
}
|
||||
|
||||
.goggles-icon {
|
||||
display: block;
|
||||
width: 2.2em;
|
||||
|
|
|
@ -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']);
|
||||
|
|
Loading…
Add table
Reference in a new issue