Merge pull request #5243 from mempool/mononaut/hybrid-accelerator-polish
Accelerator polish
This commit is contained in:
		
						commit
						dfede7fe25
					
				| @ -280,31 +280,55 @@ | |||||||
|         <div class="alert alert-mempool mr-6">You are currently on the waitlist for Mempool Accelerator™</div> |         <div class="alert alert-mempool mr-6">You are currently on the waitlist for Mempool Accelerator™</div> | ||||||
|       </div> |       </div> | ||||||
| 
 | 
 | ||||||
|       <form [class.disabled]="error || showSuccess"> |       @if (!advancedEnabled) { | ||||||
|         <div class="row summary-row"> |         <form [class.disabled]="error || showSuccess"> | ||||||
|           <div> |           <div class="row"> | ||||||
|             <div class="form-group form-check mb-2"> |             <div class="col-md"> | ||||||
|               <div class="float-right"><ng-container *ngTemplateOutlet="customizeButton"></ng-container></div> |               <div class="form-group form-check mb-2"> | ||||||
|               <input type="checkbox" [checked]="armed" class="form-check-input" [class.error-shake]="misfire" id="accel" name="accel" (change)="armed = !armed; misfire = false"> |                 <input type="radio" [checked]="selectedOption === 'wait'"  class="form-check-input" id="wait" name="accel" (change)="selectedOptionChanged($event)"> | ||||||
|               <label class="form-check-label d-flex flex-column" for="accel"> |                 <label class="form-check-label d-flex flex-column" for="wait"> | ||||||
|                 <span><b>Accelerate</b> to ~{{ ((userBid + estimate.txSummary.effectiveFee) / estimate.txSummary.effectiveVsize) | number : '1.0-0' }} sat/vB</span> |                   <span class="font-weight-bold">Wait</span> | ||||||
|                 <span class="checkout-text">Confirmation expected <app-time kind="within" [time]="etaInfo.acceleratedETA" [fastRender]="false" [fixedRender]="true"></app-time><br> |                   @if (eta.blocks < 7) { | ||||||
|                   @if (!calculating) { |                     <span class="checkout-text">Confirmation expected <app-time kind="within" [time]="eta.time" [fastRender]="false" [fixedRender]="true"></app-time></span> | ||||||
|                     <app-fiat [value]="cost"></app-fiat>fee (<span><small style="font-family: monospace;">{{ cost | number }}</small> <span class="symbol" i18n="shared.sats">sats</span></span>) |  | ||||||
|                   } @else { |                   } @else { | ||||||
|                     <span class="estimating">Calculating cost...</span> |                     <span class="checkout-text"> | ||||||
|  |                       <span>Confirmation expected within several hours</span> | ||||||
|  |                     </span> | ||||||
|                   } |                   } | ||||||
|                 </span> |                 </label> | ||||||
|               </label> |               </div> | ||||||
|  |               <div class="form-group form-check mb-2"> | ||||||
|  |                 <input type="radio" [checked]="selectedOption === 'accel'"  class="form-check-input" id="accel" name="accel" (change)="selectedOptionChanged($event)"> | ||||||
|  |                 <label class="form-check-label d-flex flex-column" for="accel"> | ||||||
|  |                   <ng-container *ngTemplateOutlet="accelerateOption; context: {etaInfo}"></ng-container> | ||||||
|  |                 </label> | ||||||
|  |               </div> | ||||||
|             </div> |             </div> | ||||||
|           </div> |           </div> | ||||||
|           <div class="pie d-none d-lg-flex" *ngIf="!forceMobile"> |           <div class="row mt-2 mb-2"> | ||||||
|             <small class="form-text checkout-text mb-2" i18n="accelerator.hashrate-percentage-description">Your transaction will be prioritized by up to {{ etaInfo.hashratePercentage | number : '1.1-1' }}% of miners.</small> |             <div class="col-sm d-flex flex-row justify-content-center"> | ||||||
|             <app-active-acceleration-box [miningStats]="miningStats" [pools]="estimate.pools" [chartOnly]="true"></app-active-acceleration-box> |               <ng-container *ngTemplateOutlet="accelerateButton"></ng-container> | ||||||
|  |             </div> | ||||||
|  |           </div> | ||||||
|  |         </form> | ||||||
|  |       } @else { | ||||||
|  |         <div [class.disabled]="error || showSuccess"> | ||||||
|  |           <div class="row summary-row"> | ||||||
|  |             <div> | ||||||
|  |               <div class="mb-2"> | ||||||
|  |                 <div class="d-flex flex-column" for="accel"> | ||||||
|  |                   <ng-container *ngTemplateOutlet="accelerateOption; context: {etaInfo}"></ng-container> | ||||||
|  |                 </div> | ||||||
|  |               </div> | ||||||
|  |             </div> | ||||||
|  |             <div class="pie d-none d-lg-flex"> | ||||||
|  |               <small class="form-text checkout-text mb-2" i18n="accelerator.hashrate-percentage-description">Your transaction will be prioritized by up to {{ etaInfo.hashratePercentage | number : '1.1-1' }}% of miners.</small> | ||||||
|  |               <app-active-acceleration-box [miningStats]="miningStats" [pools]="estimate.pools" [chartOnly]="true"></app-active-acceleration-box> | ||||||
|  |             </div> | ||||||
|  |             <ng-container *ngTemplateOutlet="accelerateButton"></ng-container> | ||||||
|           </div> |           </div> | ||||||
|           <ng-container *ngTemplateOutlet="accelerateButton"></ng-container> |  | ||||||
|         </div> |         </div> | ||||||
|       </form> |       } | ||||||
|     </ng-container> |     </ng-container> | ||||||
|     <ng-template #loadingSummary> |     <ng-template #loadingSummary> | ||||||
|       <div class="row"> |       <div class="row"> | ||||||
| @ -338,18 +362,20 @@ | |||||||
|           <app-active-acceleration-box [miningStats]="miningStats" [pools]="estimate.pools" [chartOnly]="true"></app-active-acceleration-box> |           <app-active-acceleration-box [miningStats]="miningStats" [pools]="estimate.pools" [chartOnly]="true"></app-active-acceleration-box> | ||||||
|         </div> |         </div> | ||||||
|       </div> |       </div> | ||||||
|       @if (canPayWithBalance || !(canPayWithBitcoin || canPayWithCashapp)) { |       <div class="payment-area mt-2 p-2" [class.disabled]="error || showSuccess" style="font-size: 14px;"> | ||||||
|         <div class="d-flex justify-content-center" [class.grayOut]="!canPayWithBalance || error || showSuccess"> |         <div class="row text-center justify-content-center mx-2"> | ||||||
|           <button type="button" class="mt-1 btn btn-purple rounded-pill align-self-center d-flex flex-row justify-content-center align-items-center" style="width: 200px" (click)="accelerate()"> |           <p>Payment to mempool.space for acceleration of txid <a [routerLink]="'/tx/' + tx.txid" target="_blank"> {{ tx.txid.substr(0, 10) }}..{{ tx.txid.substr(-10) }}</a></p> | ||||||
|             <img src="/resources/mempool-accelerator-sparkles-light.svg" height="20" class="mr-2" style="margin-left: -10px"> |  | ||||||
|             <span>Accelerate</span> |  | ||||||
|           </button> |  | ||||||
|         </div> |         </div> | ||||||
|       } @else { |         @if (canPayWithBalance || !(canPayWithBitcoin || canPayWithCashapp)) { | ||||||
|         <div class="payment-area mt-2 p-2" [class.disabled]="error || showSuccess"> |           <div class="row"> | ||||||
|           <div class="row text-center justify-content-center mx-2" style="font-size: 14px;"> |             <div class="col-sm text-center d-flex flex-column justify-content-center align-items-center"> | ||||||
|             <p>Payment to mempool.space for acceleration of txid <a [routerLink]="'/tx/' + tx.txid" target="_blank"> {{ tx.txid.substr(0, 10) }}..{{ tx.txid.substr(-10) }}</a></p> |               <p>Your account will be debited no more than <span><small style="font-family: monospace;">{{ cost | number }}</small> <span class="symbol" i18n="shared.sats">sats</span></span></p> | ||||||
|  |               <div class="d-flex justify-content-center" [class.grayOut]="!canPayWithBalance || error || showSuccess"> | ||||||
|  |                 <ng-container *ngTemplateOutlet="accountPayButton"></ng-container> | ||||||
|  |               </div> | ||||||
|  |             </div> | ||||||
|           </div> |           </div> | ||||||
|  |         } @else { | ||||||
|           <div class="row"> |           <div class="row"> | ||||||
|             @if (canPayWithBitcoin) { |             @if (canPayWithBitcoin) { | ||||||
|               <div class="col-sm text-center d-flex flex-column justify-content-center align-items-center"> |               <div class="col-sm text-center d-flex flex-column justify-content-center align-items-center"> | ||||||
| @ -376,8 +402,8 @@ | |||||||
|               </div> |               </div> | ||||||
|             } |             } | ||||||
|           </div> |           </div> | ||||||
|         </div> |         } | ||||||
|       } |       </div> | ||||||
|     </ng-container> |     </ng-container> | ||||||
|     <ng-template #loadingCheckout> |     <ng-template #loadingCheckout> | ||||||
|       <div class="row"> |       <div class="row"> | ||||||
| @ -486,13 +512,24 @@ | |||||||
|   } |   } | ||||||
| </div> | </div> | ||||||
| 
 | 
 | ||||||
|  | <ng-template #accelerateOption let-etaInfo="etaInfo"> | ||||||
|  |   <span><b>Accelerate</b> to ~{{ ((userBid + estimate.txSummary.effectiveFee) / estimate.txSummary.effectiveVsize) | number : '1.0-0' }} sat/vB <ng-container *ngTemplateOutlet="customizeButton"></ng-container></span> | ||||||
|  |   <span class="checkout-text">Confirmation expected <app-time kind="within" [time]="etaInfo.acceleratedETA" [fastRender]="false" [fixedRender]="true"></app-time><br> | ||||||
|  |     @if (!calculating) { | ||||||
|  |       <app-fiat [value]="cost"></app-fiat>fee (<span><small style="font-family: monospace;">{{ cost | number }}</small> <span class="symbol" i18n="shared.sats">sats</span></span>) | ||||||
|  |     } @else { | ||||||
|  |       <span class="estimating">Calculating cost...</span> | ||||||
|  |     } | ||||||
|  |   </span> | ||||||
|  | </ng-template> | ||||||
|  | 
 | ||||||
| <ng-template #customizeButton> | <ng-template #customizeButton> | ||||||
|   <button type="button" *ngIf="advancedEnabled" class="btn btn-sm btn-outline-info btn-small-height ml-3" (click)="moveToStep('quote')" i18n="accelerator.customize">customize</button> |   <button type="button" *ngIf="advancedEnabled" class="btn btn-sm btn-outline-info btn-small-height ml-2" (click)="moveToStep('quote')" i18n="accelerator.customize">customize</button> | ||||||
| </ng-template> | </ng-template> | ||||||
| 
 | 
 | ||||||
| <ng-template #accelerateButton> | <ng-template #accelerateButton> | ||||||
|   @if (isLoggedIn() || canPayWithBitcoin || canPayWithCashapp) { |   @if (isLoggedIn() || canPayWithBitcoin || canPayWithCashapp) { | ||||||
|     <button type="button" class="mt-1 btn btn-purple rounded-pill align-self-center d-flex flex-row justify-content-center align-items-center" [class.grayOut]="!canPay || (!armed && step === 'summary') || calculating" style="width: 200px" (click)="accelerate()"> |     <button type="button" class="mt-1 btn btn-purple rounded-pill align-self-center d-flex flex-row justify-content-center align-items-center" [class.disabled]="!canPay || calculating || (!advancedEnabled && selectedOption !== 'accel')" style="width: 200px" (click)="moveToStep('checkout')"> | ||||||
|       <img src="/resources/mempool-accelerator-sparkles-light.svg" height="20" class="mr-2" style="margin-left: -10px"> |       <img src="/resources/mempool-accelerator-sparkles-light.svg" height="20" class="mr-2" style="margin-left: -10px"> | ||||||
|       <span>Accelerate</span> |       <span>Accelerate</span> | ||||||
|     </button> |     </button> | ||||||
| @ -502,4 +539,18 @@ | |||||||
|       <span>Coming soon</span> |       <span>Coming soon</span> | ||||||
|     </button> |     </button> | ||||||
|   } |   } | ||||||
|  | </ng-template> | ||||||
|  | 
 | ||||||
|  | <ng-template #accountPayButton> | ||||||
|  |   @if (isLoggedIn()) { | ||||||
|  |     <button type="button" class="mt-1 btn btn-purple rounded-pill align-self-center d-flex flex-row justify-content-center align-items-center" [class.disabled]="!canPay || calculating" style="width: 200px" (click)="accelerateWithMempoolAccount()"> | ||||||
|  |       <img src="/resources/mempool-accelerator-sparkles-light.svg" height="20" class="mr-2" style="margin-left: -10px"> | ||||||
|  |       <span>Pay</span> | ||||||
|  |     </button> | ||||||
|  |   } @else { | ||||||
|  |     <button type="button" class="mt-1 btn btn-purple rounded-pill align-self-center d-flex flex-row justify-content-center align-items-center disabled" style="width: 200px"> | ||||||
|  |       <img src="/resources/mempool-accelerator-sparkles-light.svg" height="20" class="mr-2" style="margin-left: -10px"> | ||||||
|  |       <span>Coming soon</span> | ||||||
|  |     </button> | ||||||
|  |   } | ||||||
| </ng-template> | </ng-template> | ||||||
| @ -189,22 +189,3 @@ | |||||||
|     flex-direction: column; |     flex-direction: column; | ||||||
|   } |   } | ||||||
| } | } | ||||||
| 
 |  | ||||||
| @keyframes box-shake { |  | ||||||
|   0% { transform: rotate(0deg); } |  | ||||||
|   10% { transform: rotate(-8deg); } |  | ||||||
|   20% { transform: rotate(8deg); } |  | ||||||
|   30% { transform: rotate(-8deg); } |  | ||||||
|   40% { transform: rotate(8deg); } |  | ||||||
|   50% { transform: rotate(-8deg); } |  | ||||||
|   60% { transform: rotate(8deg); } |  | ||||||
|   70% { transform: rotate(-8deg); } |  | ||||||
|   80% { transform: rotate(8deg); } |  | ||||||
|   90% { transform: rotate(-8deg); } |  | ||||||
|   100% { transform: rotate(0deg); } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| .error-shake { |  | ||||||
|   box-shadow: 0 0 10px 2px var(--danger); |  | ||||||
|   animation: box-shake 1.5s ease-in-out; |  | ||||||
| } |  | ||||||
| @ -62,8 +62,7 @@ export class AccelerateCheckout implements OnInit, OnDestroy { | |||||||
|   @Output() changeMode = new EventEmitter<boolean>(); |   @Output() changeMode = new EventEmitter<boolean>(); | ||||||
| 
 | 
 | ||||||
|   calculating = true; |   calculating = true; | ||||||
|   armed = false; |   selectedOption: 'wait' | 'accel'; | ||||||
|   misfire = false; |  | ||||||
|   error = ''; |   error = ''; | ||||||
|   math = Math; |   math = Math; | ||||||
|   isMobile: boolean = window.innerWidth <= 767.98; |   isMobile: boolean = window.innerWidth <= 767.98; | ||||||
| @ -150,7 +149,6 @@ export class AccelerateCheckout implements OnInit, OnDestroy { | |||||||
| 
 | 
 | ||||||
|   moveToStep(step: CheckoutStep) { |   moveToStep(step: CheckoutStep) { | ||||||
|     this._step = step; |     this._step = step; | ||||||
|     this.misfire = false; |  | ||||||
|     if (!this.estimate && ['quote', 'summary', 'checkout'].includes(this.step)) { |     if (!this.estimate && ['quote', 'summary', 'checkout'].includes(this.step)) { | ||||||
|       this.fetchEstimate(); |       this.fetchEstimate(); | ||||||
|     } |     } | ||||||
| @ -265,28 +263,13 @@ export class AccelerateCheckout implements OnInit, OnDestroy { | |||||||
|     } |     } | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   /** |  | ||||||
|    * Advanced mode acceleration button clicked |  | ||||||
|    */ |  | ||||||
|   accelerate(): void { |  | ||||||
|     if (this.canPay && !this.calculating) { |  | ||||||
|       if ((!this.armed && this.step === 'summary')) { |  | ||||||
|         this.misfire = true; |  | ||||||
|       } else { |  | ||||||
|         if (this.isLoggedIn()) { |  | ||||||
|           this.accelerateWithMempoolAccount(); |  | ||||||
|         } else { |  | ||||||
|           this.armed = true; |  | ||||||
|           this.moveToStep('checkout'); |  | ||||||
|         } |  | ||||||
|       } |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   /** |   /** | ||||||
|    * Account-based acceleration request |    * Account-based acceleration request | ||||||
|    */ |    */ | ||||||
|   accelerateWithMempoolAccount(): void { |   accelerateWithMempoolAccount(): void { | ||||||
|  |     if (!this.canPay || this.calculating) { | ||||||
|  |       return; | ||||||
|  |     } | ||||||
|     if (this.accelerationSubscription) { |     if (this.accelerationSubscription) { | ||||||
|       this.accelerationSubscription.unsubscribe(); |       this.accelerationSubscription.unsubscribe(); | ||||||
|     } |     } | ||||||
| @ -469,6 +452,13 @@ export class AccelerateCheckout implements OnInit, OnDestroy { | |||||||
|     return auth !== null; |     return auth !== null; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|  |   /** | ||||||
|  |    * UI events | ||||||
|  |    */ | ||||||
|  |   selectedOptionChanged(event) { | ||||||
|  |     this.selectedOption = event.target.id; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|   get step() { |   get step() { | ||||||
|     return this._step; |     return this._step; | ||||||
|   } |   } | ||||||
|  | |||||||
| @ -122,7 +122,7 @@ | |||||||
|         <span class="explainer"> </span> |         <span class="explainer"> </span> | ||||||
|       } @else if (showAccelerationSummary) { |       } @else if (showAccelerationSummary) { | ||||||
|         <ng-container *ngIf="(ETA$ | async) as eta;"> |         <ng-container *ngIf="(ETA$ | async) as eta;"> | ||||||
|           <app-accelerate-checkout *ngIf="(da$ | async) as da;" [cashappEnabled]="accelerationEligible" [advancedEnabled]="false" [forceMobile]="true" [tx]="tx" [miningStats]="miningStats" [eta]="eta" [scrollEvent]="scrollIntoAccelPreview" class="h-100 w-100"></app-accelerate-checkout> |           <app-accelerate-checkout *ngIf="(da$ | async) as da;" [cashappEnabled]="cashappEligible" [advancedEnabled]="false" [forceMobile]="true" [tx]="tx" [miningStats]="miningStats" [eta]="eta" [scrollEvent]="scrollIntoAccelPreview" class="h-100 w-100"></app-accelerate-checkout> | ||||||
|         </ng-container> |         </ng-container> | ||||||
|       } @else { |       } @else { | ||||||
|         @if (tx?.acceleration && !tx.status?.confirmed) { |         @if (tx?.acceleration && !tx.status?.confirmed) { | ||||||
|  | |||||||
| @ -21,7 +21,7 @@ import { AudioService } from '../../services/audio.service'; | |||||||
| import { ApiService } from '../../services/api.service'; | import { ApiService } from '../../services/api.service'; | ||||||
| import { SeoService } from '../../services/seo.service'; | import { SeoService } from '../../services/seo.service'; | ||||||
| import { seoDescriptionNetwork } from '../../shared/common.utils'; | import { seoDescriptionNetwork } from '../../shared/common.utils'; | ||||||
| import { Filter } from '../../shared/filters.utils'; | import { Filter, TransactionFlags } from '../../shared/filters.utils'; | ||||||
| import { BlockExtended, CpfpInfo, RbfTree, MempoolPosition, DifficultyAdjustment, Acceleration, AccelerationPosition } from '../../interfaces/node-api.interface'; | import { BlockExtended, CpfpInfo, RbfTree, MempoolPosition, DifficultyAdjustment, Acceleration, AccelerationPosition } from '../../interfaces/node-api.interface'; | ||||||
| import { PriceService } from '../../services/price.service'; | import { PriceService } from '../../services/price.service'; | ||||||
| import { ServicesApiServices } from '../../services/services-api.service'; | import { ServicesApiServices } from '../../services/services-api.service'; | ||||||
| @ -30,7 +30,7 @@ import { ZONE_SERVICE } from '../../injection-tokens'; | |||||||
| import { TrackerStage } from './tracker-bar.component'; | import { TrackerStage } from './tracker-bar.component'; | ||||||
| import { MiningService, MiningStats } from '../../services/mining.service'; | import { MiningService, MiningStats } from '../../services/mining.service'; | ||||||
| import { ETA, EtaService } from '../../services/eta.service'; | import { ETA, EtaService } from '../../services/eta.service'; | ||||||
| import { getUnacceleratedFeeRate } from '../../shared/transaction.utils'; | import { getTransactionFlags, getUnacceleratedFeeRate } from '../../shared/transaction.utils'; | ||||||
| 
 | 
 | ||||||
| interface Pool { | interface Pool { | ||||||
|   id: number; |   id: number; | ||||||
| @ -117,8 +117,7 @@ export class TrackerComponent implements OnInit, OnDestroy { | |||||||
|   hasEffectiveFeeRate: boolean; |   hasEffectiveFeeRate: boolean; | ||||||
|   accelerateCtaType: 'alert' | 'button' = 'button'; |   accelerateCtaType: 'alert' | 'button' = 'button'; | ||||||
|   acceleratorAvailable: boolean = this.stateService.env.ACCELERATOR && this.stateService.network === ''; |   acceleratorAvailable: boolean = this.stateService.env.ACCELERATOR && this.stateService.network === ''; | ||||||
|   accelerationEligible: boolean = false; |   eligibleForAcceleration: boolean = false; | ||||||
|   showAccelerationSummary = false; |  | ||||||
|   accelerationFlowCompleted = false; |   accelerationFlowCompleted = false; | ||||||
|   scrollIntoAccelPreview = false; |   scrollIntoAccelPreview = false; | ||||||
|   auditEnabled: boolean = this.stateService.env.AUDIT && this.stateService.env.BASE_MODULE === 'mempool' && this.stateService.env.MINING_DASHBOARD === true; |   auditEnabled: boolean = this.stateService.env.AUDIT && this.stateService.env.BASE_MODULE === 'mempool' && this.stateService.env.MINING_DASHBOARD === true; | ||||||
| @ -155,11 +154,6 @@ export class TrackerComponent implements OnInit, OnDestroy { | |||||||
|       this.miningStats = stats; |       this.miningStats = stats; | ||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
|     const urlParams = new URLSearchParams(window.location.search); |  | ||||||
|     if (urlParams.get('cash_request_id')) { |  | ||||||
|       this.showAccelerationSummary = true; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     this.enterpriseService.page(); |     this.enterpriseService.page(); | ||||||
| 
 | 
 | ||||||
|     this.enterpriseInfo$ = this.enterpriseService.info$.subscribe(info => { |     this.enterpriseInfo$ = this.enterpriseService.info$.subscribe(info => { | ||||||
| @ -267,6 +261,7 @@ export class TrackerComponent implements OnInit, OnDestroy { | |||||||
| 
 | 
 | ||||||
|       if (!this.tx) { |       if (!this.tx) { | ||||||
|         this.tx = tx; |         this.tx = tx; | ||||||
|  |         this.checkAccelerationEligibility(); | ||||||
|         this.isCached = true; |         this.isCached = true; | ||||||
|         if (tx.fee === undefined) { |         if (tx.fee === undefined) { | ||||||
|           this.tx.fee = 0; |           this.tx.fee = 0; | ||||||
| @ -385,20 +380,9 @@ export class TrackerComponent implements OnInit, OnDestroy { | |||||||
|             this.trackerStage = 'replaced'; |             this.trackerStage = 'replaced'; | ||||||
|           } |           } | ||||||
| 
 | 
 | ||||||
|           if (!this.mempoolPosition.accelerated) { |           if (this.mempoolPosition.accelerated && this.showAccelerationSummary) { | ||||||
|             if (!this.accelerationFlowCompleted && !this.showAccelerationSummary && this.mempoolPosition.block > 0) { |  | ||||||
|               this.showAccelerationSummary = true; |  | ||||||
|               this.miningService.getMiningStats('1w').subscribe(stats => { |  | ||||||
|                 this.miningStats = stats; |  | ||||||
|               }); |  | ||||||
|             } |  | ||||||
|             if (txPosition.position?.block > 0) { |  | ||||||
|               this.accelerationEligible = true; |  | ||||||
|             } |  | ||||||
|           } else if (this.showAccelerationSummary) { |  | ||||||
|             setTimeout(() => { |             setTimeout(() => { | ||||||
|               this.accelerationFlowCompleted = true; |               this.accelerationFlowCompleted = true; | ||||||
|               this.showAccelerationSummary = false; |  | ||||||
|             }, 2000); |             }, 2000); | ||||||
|           } |           } | ||||||
|         } |         } | ||||||
| @ -462,6 +446,7 @@ export class TrackerComponent implements OnInit, OnDestroy { | |||||||
|           this.seoService.clearSoft404(); |           this.seoService.clearSoft404(); | ||||||
| 
 | 
 | ||||||
|           this.tx = tx; |           this.tx = tx; | ||||||
|  |           this.checkAccelerationEligibility(); | ||||||
|           this.isCached = false; |           this.isCached = false; | ||||||
|           if (tx.fee === undefined) { |           if (tx.fee === undefined) { | ||||||
|             this.tx.fee = 0; |             this.tx.fee = 0; | ||||||
| @ -744,8 +729,9 @@ export class TrackerComponent implements OnInit, OnDestroy { | |||||||
|     } |     } | ||||||
|     this.enterpriseService.goal(8); |     this.enterpriseService.goal(8); | ||||||
|     this.accelerationFlowCompleted = false; |     this.accelerationFlowCompleted = false; | ||||||
|     this.showAccelerationSummary = true && this.acceleratorAvailable; |     if (this.showAccelerationSummary) { | ||||||
|     this.scrollIntoAccelPreview = true; |       this.scrollIntoAccelPreview = true; | ||||||
|  |     } | ||||||
|     return false; |     return false; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
| @ -753,6 +739,31 @@ export class TrackerComponent implements OnInit, OnDestroy { | |||||||
|     return this.isLoadingTx || this.loadingCachedTx || this.loadingPosition; |     return this.isLoadingTx || this.loadingCachedTx || this.loadingPosition; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|  |   checkAccelerationEligibility() { | ||||||
|  |     if (this.tx) { | ||||||
|  |       this.tx.flags = getTransactionFlags(this.tx); | ||||||
|  |       const replaceableInputs = (this.tx.flags & (TransactionFlags.sighash_none | TransactionFlags.sighash_acp)) > 0n; | ||||||
|  |       const highSigop = (this.tx.sigops * 20) > this.tx.weight; | ||||||
|  |       this.eligibleForAcceleration = !replaceableInputs && !highSigop; | ||||||
|  |     } else { | ||||||
|  |       this.eligibleForAcceleration = false; | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   get cashappEligible(): boolean { | ||||||
|  |     return this.mempoolPosition?.block > 0; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   get showAccelerationSummary(): boolean { | ||||||
|  |     return ( | ||||||
|  |       this.tx | ||||||
|  |       && !this.tx.acceleration | ||||||
|  |       && this.acceleratorAvailable | ||||||
|  |       && this.eligibleForAcceleration | ||||||
|  |       && !this.accelerationFlowCompleted | ||||||
|  |     ); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|   resetTransaction() { |   resetTransaction() { | ||||||
|     this.error = undefined; |     this.error = undefined; | ||||||
|     this.tx = null; |     this.tx = null; | ||||||
| @ -778,7 +789,7 @@ export class TrackerComponent implements OnInit, OnDestroy { | |||||||
|     this.pool = null; |     this.pool = null; | ||||||
|     this.auditStatus = null; |     this.auditStatus = null; | ||||||
|     this.accelerationPositions = null; |     this.accelerationPositions = null; | ||||||
|     this.accelerationEligible = false; |     this.eligibleForAcceleration = false; | ||||||
|     this.trackerStage = 'waiting'; |     this.trackerStage = 'waiting'; | ||||||
|     document.body.scrollTo(0, 0); |     document.body.scrollTo(0, 0); | ||||||
|     this.leaveTransaction(); |     this.leaveTransaction(); | ||||||
|  | |||||||
| @ -74,38 +74,9 @@ | |||||||
| 
 | 
 | ||||||
|   <ng-template [ngIf]="!isLoadingTx && !error"> |   <ng-template [ngIf]="!isLoadingTx && !error"> | ||||||
| 
 | 
 | ||||||
|     <!-- Accelerator --> |     <!-- CPFP Details --> | ||||||
|     <ng-container *ngIf="!tx?.status?.confirmed && showAccelerationSummary"> |  | ||||||
|       <br> |  | ||||||
|       <div class="title float-left"> |  | ||||||
|         <h2 i18n="transaction.accelerate|Accelerate button label">Accelerate</h2> |  | ||||||
|       </div> |  | ||||||
| 
 |  | ||||||
|       <button type="button" class="btn btn-outline-info flow-toggle btn-sm float-right" (click)="closeAccelerator()" i18n="hide-diagram">Hide accelerator</button> |  | ||||||
|       <button *ngIf="hasAccelerationDetails" class="btn btn-sm btn-outline-info float-right ml-2" (click)="showAccelerationDetails = !showAccelerationDetails">Details</button> |  | ||||||
| 
 |  | ||||||
|       <div class="clearfix"></div> |  | ||||||
| 
 |  | ||||||
|       <ng-container *ngIf="(ETA$ | async) as eta;"> |  | ||||||
|         <app-accelerate-checkout |  | ||||||
|           *ngIf="(da$ | async) as da;" |  | ||||||
|           [cashappEnabled]="accelerationEligible" |  | ||||||
|           [advancedEnabled]="true" |  | ||||||
|           [tx]="tx" |  | ||||||
|           [eta]="eta" |  | ||||||
|           [miningStats]="miningStats" |  | ||||||
|           [scrollEvent]="scrollIntoAccelPreview" |  | ||||||
|           [showDetails]="showAccelerationDetails" |  | ||||||
|           [noCTA]="true" |  | ||||||
|           (hasDetails)="setHasAccelerationDetails($event)" |  | ||||||
|           class="h-100 w-100" |  | ||||||
|         ></app-accelerate-checkout> |  | ||||||
|       </ng-container> |  | ||||||
|     </ng-container> |  | ||||||
| 
 |  | ||||||
|     <ng-template [ngIf]="showCpfpDetails"> |     <ng-template [ngIf]="showCpfpDetails"> | ||||||
|       <br> |       <br> | ||||||
| 
 |  | ||||||
|       <h2 class="text-left">CPFP <fa-icon [icon]="['fas', 'info-circle']" [fixedWidth]="true" size="xs"></fa-icon></h2> |       <h2 class="text-left">CPFP <fa-icon [icon]="['fas', 'info-circle']" [fixedWidth]="true" size="xs"></fa-icon></h2> | ||||||
|       <div class="box cpfp-details"> |       <div class="box cpfp-details"> | ||||||
|         <table class="table table-fixed table-borderless table-striped"> |         <table class="table table-fixed table-borderless table-striped"> | ||||||
| @ -161,6 +132,35 @@ | |||||||
|       </div> |       </div> | ||||||
|     </ng-template> |     </ng-template> | ||||||
| 
 | 
 | ||||||
|  |     <!-- Accelerator --> | ||||||
|  |     <ng-container *ngIf="!tx?.status?.confirmed && showAccelerationSummary"> | ||||||
|  |       <br> | ||||||
|  |       <div class="title float-left"> | ||||||
|  |         <h2 i18n="transaction.accelerate|Accelerate button label">Accelerate</h2> | ||||||
|  |       </div> | ||||||
|  | 
 | ||||||
|  |       <button type="button" class="btn btn-outline-info accelerator-toggle btn-sm float-right" (click)="closeAccelerator()" i18n="hide-diagram">Hide accelerator</button> | ||||||
|  |       <button *ngIf="hasAccelerationDetails" class="btn btn-sm btn-outline-info details-button float-right ml-2" (click)="showAccelerationDetails = !showAccelerationDetails">Details</button> | ||||||
|  | 
 | ||||||
|  |       <div class="clearfix"></div> | ||||||
|  | 
 | ||||||
|  |       <ng-container *ngIf="(ETA$ | async) as eta;"> | ||||||
|  |         <app-accelerate-checkout | ||||||
|  |           *ngIf="(da$ | async) as da;" | ||||||
|  |           [cashappEnabled]="cashappEligible" | ||||||
|  |           [advancedEnabled]="true" | ||||||
|  |           [tx]="tx" | ||||||
|  |           [eta]="eta" | ||||||
|  |           [miningStats]="miningStats" | ||||||
|  |           [scrollEvent]="scrollIntoAccelPreview" | ||||||
|  |           [showDetails]="showAccelerationDetails" | ||||||
|  |           [noCTA]="true" | ||||||
|  |           (hasDetails)="setHasAccelerationDetails($event)" | ||||||
|  |           class="h-100 w-100" | ||||||
|  |         ></app-accelerate-checkout> | ||||||
|  |       </ng-container> | ||||||
|  |     </ng-container> | ||||||
|  | 
 | ||||||
|     <br> |     <br> | ||||||
| 
 | 
 | ||||||
|     <ng-container *ngIf="rbfInfo"> |     <ng-container *ngIf="rbfInfo"> | ||||||
| @ -551,18 +551,18 @@ | |||||||
|         <td> |         <td> | ||||||
|           <ng-container *ngIf="(ETA$ | async) as eta; else etaSkeleton"> |           <ng-container *ngIf="(ETA$ | async) as eta; else etaSkeleton"> | ||||||
|             @if (eta.blocks >= 7) { |             @if (eta.blocks >= 7) { | ||||||
|               <span [class]="(!tx?.acceleration && acceleratorAvailable && accelerateCtaType === 'button' && !showAccelerationSummary) ? 'etaDeepMempool d-flex justify-content-end align-items-center' : ''"> |               <span [class]="(!tx?.acceleration && acceleratorAvailable && accelerateCtaType === 'button' && !showAccelerationSummary && eligibleForAcceleration) ? '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> |                 <span i18n="transaction.eta.in-several-hours|Transaction ETA in several hours or more">In several hours (or more)</span> | ||||||
|                 @if (!tx?.acceleration && acceleratorAvailable && accelerateCtaType === 'button' && !showAccelerationSummary) { |                 @if (!tx?.acceleration && acceleratorAvailable && accelerateCtaType === 'button' && !showAccelerationSummary && eligibleForAcceleration) { | ||||||
|                   <a class="btn btn-sm accelerateDeepMempool btn-small-height" i18n="transaction.accelerate|Accelerate button label" (click)="onAccelerateClicked()">Accelerate</a> |                   <a class="btn btn-sm accelerateDeepMempool btn-small-height" i18n="transaction.accelerate|Accelerate button label" (click)="onAccelerateClicked()">Accelerate</a> | ||||||
|                 } |                 } | ||||||
|               </span> |               </span> | ||||||
|             } @else if (network === 'liquid' || network === 'liquidtestnet') { |             } @else if (network === 'liquid' || network === 'liquidtestnet') { | ||||||
|               <app-time kind="until" [time]="eta.time" [fastRender]="false" [fixedRender]="true"></app-time> |               <app-time kind="until" [time]="eta.time" [fastRender]="false" [fixedRender]="true"></app-time> | ||||||
|             } @else { |             } @else { | ||||||
|               <span [class]="(!tx?.acceleration && acceleratorAvailable && accelerateCtaType === 'button' && !showAccelerationSummary) ? 'etaDeepMempool d-flex justify-content-end align-items-center' : ''"> |               <span [class]="(!tx?.acceleration && acceleratorAvailable && accelerateCtaType === 'button' && !showAccelerationSummary && eligibleForAcceleration) ? 'etaDeepMempool d-flex justify-content-end align-items-center' : ''"> | ||||||
|                 <app-time kind="until" [time]="eta.time" [fastRender]="false" [fixedRender]="true"></app-time> |                 <app-time kind="until" [time]="eta.time" [fastRender]="false" [fixedRender]="true"></app-time> | ||||||
|                 @if (!tx?.acceleration && acceleratorAvailable && accelerateCtaType === 'button' && !showAccelerationSummary) { |                 @if (!tx?.acceleration && acceleratorAvailable && accelerateCtaType === 'button' && !showAccelerationSummary && eligibleForAcceleration) { | ||||||
|                   <a class="btn btn-sm accelerateDeepMempool btn-small-height" i18n="transaction.accelerate|Accelerate button label" (click)="onAccelerateClicked()">Accelerate</a> |                   <a class="btn btn-sm accelerateDeepMempool btn-small-height" i18n="transaction.accelerate|Accelerate button label" (click)="onAccelerateClicked()">Accelerate</a> | ||||||
|                 } |                 } | ||||||
|               </span> |               </span> | ||||||
|  | |||||||
| @ -24,8 +24,8 @@ import { SeoService } from '../../services/seo.service'; | |||||||
| import { StorageService } from '../../services/storage.service'; | import { StorageService } from '../../services/storage.service'; | ||||||
| import { seoDescriptionNetwork } from '../../shared/common.utils'; | import { seoDescriptionNetwork } from '../../shared/common.utils'; | ||||||
| import { getTransactionFlags, getUnacceleratedFeeRate } from '../../shared/transaction.utils'; | import { getTransactionFlags, getUnacceleratedFeeRate } from '../../shared/transaction.utils'; | ||||||
| import { Filter, toFilters } from '../../shared/filters.utils'; | import { Filter, TransactionFlags, toFilters } from '../../shared/filters.utils'; | ||||||
| import { BlockExtended, CpfpInfo, RbfTree, MempoolPosition, DifficultyAdjustment, Acceleration, AccelerationPosition, SinglePoolStats } from '../../interfaces/node-api.interface'; | import { BlockExtended, CpfpInfo, RbfTree, MempoolPosition, DifficultyAdjustment, Acceleration, AccelerationPosition } from '../../interfaces/node-api.interface'; | ||||||
| import { LiquidUnblinding } from './liquid-ublinding'; | import { LiquidUnblinding } from './liquid-ublinding'; | ||||||
| import { RelativeUrlPipe } from '../../shared/pipes/relative-url/relative-url.pipe'; | import { RelativeUrlPipe } from '../../shared/pipes/relative-url/relative-url.pipe'; | ||||||
| import { PriceService } from '../../services/price.service'; | import { PriceService } from '../../services/price.service'; | ||||||
| @ -137,12 +137,14 @@ export class TransactionComponent implements OnInit, AfterViewInit, OnDestroy { | |||||||
|   hasEffectiveFeeRate: boolean; |   hasEffectiveFeeRate: boolean; | ||||||
|   accelerateCtaType: 'alert' | 'button' = 'button'; |   accelerateCtaType: 'alert' | 'button' = 'button'; | ||||||
|   acceleratorAvailable: boolean = this.stateService.env.ACCELERATOR && this.stateService.network === ''; |   acceleratorAvailable: boolean = this.stateService.env.ACCELERATOR && this.stateService.network === ''; | ||||||
|   showAccelerationSummary = false; |   eligibleForAcceleration: boolean = false; | ||||||
|  |   forceAccelerationSummary = false; | ||||||
|  |   hideAccelerationSummary = false; | ||||||
|  |   accelerationFlowCompleted = false; | ||||||
|   showAccelerationDetails = false; |   showAccelerationDetails = false; | ||||||
|   hasAccelerationDetails = false; |   hasAccelerationDetails = false; | ||||||
|   accelerationFlowCompleted = false; |  | ||||||
|   scrollIntoAccelPreview = false; |   scrollIntoAccelPreview = false; | ||||||
|   accelerationEligible = false; |   cashappEligible = false; | ||||||
|   auditEnabled: boolean = this.stateService.env.AUDIT && this.stateService.env.BASE_MODULE === 'mempool' && this.stateService.env.MINING_DASHBOARD === true; |   auditEnabled: boolean = this.stateService.env.AUDIT && this.stateService.env.BASE_MODULE === 'mempool' && this.stateService.env.MINING_DASHBOARD === true; | ||||||
| 
 | 
 | ||||||
|   @ViewChild('graphContainer') |   @ViewChild('graphContainer') | ||||||
| @ -173,11 +175,11 @@ export class TransactionComponent implements OnInit, AfterViewInit, OnDestroy { | |||||||
|     this.enterpriseService.page(); |     this.enterpriseService.page(); | ||||||
| 
 | 
 | ||||||
|     const urlParams = new URLSearchParams(window.location.search); |     const urlParams = new URLSearchParams(window.location.search); | ||||||
|     if (urlParams.get('cash_request_id')) { |     this.forceAccelerationSummary = !!urlParams.get('cash_request_id'); | ||||||
|       this.showAccelerationSummary = true; |  | ||||||
|     } |  | ||||||
| 
 | 
 | ||||||
|     if (!this.stateService.isLiquid) { |     this.hideAccelerationSummary = this.storageService.getValue('hide-accelerator-pref') == 'true'; | ||||||
|  | 
 | ||||||
|  |     if (!this.stateService.isLiquid()) { | ||||||
|       this.miningService.getMiningStats('1w').subscribe(stats => { |       this.miningService.getMiningStats('1w').subscribe(stats => { | ||||||
|         this.miningStats = stats; |         this.miningStats = stats; | ||||||
|       }); |       }); | ||||||
| @ -414,18 +416,17 @@ export class TransactionComponent implements OnInit, AfterViewInit, OnDestroy { | |||||||
| 
 | 
 | ||||||
|           if (this.stateService.network === '') { |           if (this.stateService.network === '') { | ||||||
|             if (!this.mempoolPosition.accelerated) { |             if (!this.mempoolPosition.accelerated) { | ||||||
|               if (!this.accelerationFlowCompleted && !this.showAccelerationSummary) { |               if (!this.accelerationFlowCompleted && !this.hideAccelerationSummary && !this.showAccelerationSummary) { | ||||||
|                 this.showAccelerationSummary = true; |  | ||||||
|                 this.miningService.getMiningStats('1w').subscribe(stats => { |                 this.miningService.getMiningStats('1w').subscribe(stats => { | ||||||
|                   this.miningStats = stats; |                   this.miningStats = stats; | ||||||
|                 }); |                 }); | ||||||
|               } |               } | ||||||
|               if (txPosition.position?.block > 0 && this.tx.weight < 4000) { |               if (txPosition.position?.block > 0 && this.tx.weight < 4000) { | ||||||
|                 this.accelerationEligible = true; |                 this.cashappEligible = true; | ||||||
|               } |               } | ||||||
|             } else if (this.showAccelerationSummary) { |             } else if (this.showAccelerationSummary) { | ||||||
|               setTimeout(() => { |               setTimeout(() => { | ||||||
|                 this.closeAccelerator(); |                 this.accelerationFlowCompleted = true; | ||||||
|               }, 2000); |               }, 2000); | ||||||
|             } |             } | ||||||
|           } |           } | ||||||
| @ -715,8 +716,7 @@ export class TransactionComponent implements OnInit, AfterViewInit, OnDestroy { | |||||||
| 
 | 
 | ||||||
|     document.location.hash = '#accelerate'; |     document.location.hash = '#accelerate'; | ||||||
|     this.enterpriseService.goal(8); |     this.enterpriseService.goal(8); | ||||||
|     this.accelerationFlowCompleted = false; |     this.openAccelerator(); | ||||||
|     this.showAccelerationSummary = this.acceleratorAvailable; |  | ||||||
|     this.scrollIntoAccelPreview = true; |     this.scrollIntoAccelPreview = true; | ||||||
|     return false; |     return false; | ||||||
|   } |   } | ||||||
| @ -778,7 +778,7 @@ export class TransactionComponent implements OnInit, AfterViewInit, OnDestroy { | |||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     if (!this.isAcceleration && this.fragmentParams.has('accelerate')) { |     if (!this.isAcceleration && this.fragmentParams.has('accelerate')) { | ||||||
|       this.onAccelerateClicked(); |       this.forceAccelerationSummary = true; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     this.txChanged$.next(true); |     this.txChanged$.next(true); | ||||||
| @ -797,10 +797,9 @@ export class TransactionComponent implements OnInit, AfterViewInit, OnDestroy { | |||||||
|     if (this.isAcceleration) { |     if (this.isAcceleration) { | ||||||
|       if (initialState) { |       if (initialState) { | ||||||
|         this.accelerationFlowCompleted = true; |         this.accelerationFlowCompleted = true; | ||||||
|         this.showAccelerationSummary = false; |  | ||||||
|       } else if (this.showAccelerationSummary) { |       } else if (this.showAccelerationSummary) { | ||||||
|         setTimeout(() => { |         setTimeout(() => { | ||||||
|           this.closeAccelerator(); |           this.accelerationFlowCompleted = true; | ||||||
|         }, 2000); |         }, 2000); | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
| @ -821,6 +820,7 @@ export class TransactionComponent implements OnInit, AfterViewInit, OnDestroy { | |||||||
|       this.rbfEnabled = !this.tx.status.confirmed || isFeatureActive(this.stateService.network, this.tx.status.block_height, 'rbf'); |       this.rbfEnabled = !this.tx.status.confirmed || isFeatureActive(this.stateService.network, this.tx.status.block_height, 'rbf'); | ||||||
|       this.tx.flags = getTransactionFlags(this.tx); |       this.tx.flags = getTransactionFlags(this.tx); | ||||||
|       this.filters = this.tx.flags ? toFilters(this.tx.flags).filter(f => f.txPage) : []; |       this.filters = this.tx.flags ? toFilters(this.tx.flags).filter(f => f.txPage) : []; | ||||||
|  |       this.checkAccelerationEligibility(); | ||||||
|     } else { |     } else { | ||||||
|       this.segwitEnabled = false; |       this.segwitEnabled = false; | ||||||
|       this.taprootEnabled = false; |       this.taprootEnabled = false; | ||||||
| @ -829,6 +829,16 @@ export class TransactionComponent implements OnInit, AfterViewInit, OnDestroy { | |||||||
|     this.featuresEnabled = this.segwitEnabled || this.taprootEnabled || this.rbfEnabled; |     this.featuresEnabled = this.segwitEnabled || this.taprootEnabled || this.rbfEnabled; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|  |   checkAccelerationEligibility() { | ||||||
|  |     if (this.tx && this.tx.flags) { | ||||||
|  |       const replaceableInputs = (this.tx.flags & (TransactionFlags.sighash_none | TransactionFlags.sighash_acp)) > 0n; | ||||||
|  |       const highSigop = (this.tx.sigops * 20) > this.tx.weight; | ||||||
|  |       this.eligibleForAcceleration = !replaceableInputs && !highSigop; | ||||||
|  |     } else { | ||||||
|  |       this.eligibleForAcceleration = false; | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|   isAuditAvailable(blockHeight: number): boolean { |   isAuditAvailable(blockHeight: number): boolean { | ||||||
|     if (!this.auditEnabled) { |     if (!this.auditEnabled) { | ||||||
|       return false; |       return false; | ||||||
| @ -873,7 +883,7 @@ export class TransactionComponent implements OnInit, AfterViewInit, OnDestroy { | |||||||
|     this.showCpfpDetails = false; |     this.showCpfpDetails = false; | ||||||
|     this.showAccelerationDetails = false; |     this.showAccelerationDetails = false; | ||||||
|     this.accelerationInfo = null; |     this.accelerationInfo = null; | ||||||
|     this.accelerationEligible = false; |     this.cashappEligible = false; | ||||||
|     this.txInBlockIndex = null; |     this.txInBlockIndex = null; | ||||||
|     this.mempoolPosition = null; |     this.mempoolPosition = null; | ||||||
|     this.pool = null; |     this.pool = null; | ||||||
| @ -882,6 +892,7 @@ export class TransactionComponent implements OnInit, AfterViewInit, OnDestroy { | |||||||
|     document.body.scrollTo(0, 0); |     document.body.scrollTo(0, 0); | ||||||
|     this.isAcceleration = false; |     this.isAcceleration = false; | ||||||
|     this.isAccelerated$.next(this.isAcceleration); |     this.isAccelerated$.next(this.isAcceleration); | ||||||
|  |     this.eligibleForAcceleration = false; | ||||||
|     this.leaveTransaction(); |     this.leaveTransaction(); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
| @ -890,11 +901,6 @@ export class TransactionComponent implements OnInit, AfterViewInit, OnDestroy { | |||||||
|     this.stateService.markBlock$.next({}); |     this.stateService.markBlock$.next({}); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   closeAccelerator(): void { |  | ||||||
|     this.accelerationFlowCompleted = true; |  | ||||||
|     this.showAccelerationSummary = false; |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   roundToOneDecimal(cpfpTx: any): number { |   roundToOneDecimal(cpfpTx: any): number { | ||||||
|     return +(cpfpTx.fee / (cpfpTx.weight / 4)).toFixed(1); |     return +(cpfpTx.fee / (cpfpTx.weight / 4)).toFixed(1); | ||||||
|   } |   } | ||||||
| @ -963,6 +969,32 @@ export class TransactionComponent implements OnInit, AfterViewInit, OnDestroy { | |||||||
|     return auth !== null; |     return auth !== null; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|  |   closeAccelerator(): void { | ||||||
|  |     document.location.hash = ''; | ||||||
|  |     this.hideAccelerationSummary = true; | ||||||
|  |     this.forceAccelerationSummary = false; | ||||||
|  |     this.storageService.setValue('hide-accelerator-pref', 'true'); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   openAccelerator(): void { | ||||||
|  |     this.accelerationFlowCompleted = false; | ||||||
|  |     this.hideAccelerationSummary = false; | ||||||
|  |     this.storageService.setValue('hide-accelerator-pref', 'false'); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   get showAccelerationSummary(): boolean { | ||||||
|  |     return ( | ||||||
|  |       this.tx | ||||||
|  |       && !this.tx.acceleration | ||||||
|  |       && this.acceleratorAvailable | ||||||
|  |       && this.eligibleForAcceleration | ||||||
|  |       && ( | ||||||
|  |         (!this.hideAccelerationSummary && !this.accelerationFlowCompleted) | ||||||
|  |         || this.forceAccelerationSummary | ||||||
|  |       ) | ||||||
|  |     ); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|   ngOnDestroy() { |   ngOnDestroy() { | ||||||
|     this.subscription.unsubscribe(); |     this.subscription.unsubscribe(); | ||||||
|     this.fetchCpfpSubscription.unsubscribe(); |     this.fetchCpfpSubscription.unsubscribe(); | ||||||
|  | |||||||
| @ -1 +0,0 @@ | |||||||
| <svg id="レイヤー_1" data-name="レイヤー 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 236.18 102.3"><defs><style>.cls-1{fill:#cedc21;}.cls-2{fill:#51b13e;}.cls-3{fill:#1e7a44;}.cls-4{fill:#fff;}</style></defs><title>btcpay3</title><path class="cls-1" d="M38.55,201.73a6,6,0,0,1-6-6V105.44a6,6,0,0,1,12,0v90.29A6,6,0,0,1,38.55,201.73Z" transform="translate(-32.55 -99.43)"/><path class="cls-2" d="M38.56,201.73A6,6,0,0,1,36,190.31l36.18-17.17L35,145.76a6,6,0,1,1,7.11-9.66l45.24,33.33a6,6,0,0,1-1,10.25L41.13,201.15A5.9,5.9,0,0,1,38.56,201.73Z" transform="translate(-32.55 -99.43)"/><path class="cls-1" d="M38.56,166.24A6,6,0,0,1,35,155.41L72.16,128,36,110.86A6,6,0,1,1,41.13,100l45.24,21.47a6,6,0,0,1,1,10.25L42.11,165.07A6,6,0,0,1,38.56,166.24Z" transform="translate(-32.55 -99.43)"/><polygon class="cls-3" points="12 38.46 12 63.84 29.21 51.16 12 38.46"/><rect class="cls-4" y="27.82" width="12" height="29.25"/><path class="cls-1" d="M44.55,105.44a6,6,0,0,0-12,0V181h12Z" transform="translate(-32.55 -99.43)"/><path class="cls-4" d="M123.92,149.86c3.84,1.09,6,4.57,6,8.93,0,6.81-4.15,10-9.82,10H107.14V132.4h11.43c5.56,0,9.87,2.65,9.87,9.56C128.44,145.44,127,148.66,123.92,149.86Zm-5.3-.89c4.1,0,7.43-1.45,7.43-7.06s-3.43-7.17-7.59-7.17h-8.88V149Zm1.3,17.41c4.15,0,7.48-2.18,7.48-7.59,0-5.82-3.79-7.58-8.52-7.58h-9.3v15.17Z" transform="translate(-32.55 -99.43)"/><path class="cls-4" d="M154.21,132.4v2.23h-10v34.14h-2.44V134.63h-10V132.4Z" transform="translate(-32.55 -99.43)"/><path class="cls-4" d="M171.3,131.88c6.19,0,11.8,3.12,13.57,10.55h-2.34c-1.66-6.08-6.55-8.32-11.28-8.32-8.57,0-13.09,7-13.09,16.47,0,10,4.52,16.37,13.14,16.37,5.1,0,9.67-2.29,11.44-9h2.33a13.6,13.6,0,0,1-13.77,11.33c-9.71,0-15.53-7.17-15.53-18.71C155.77,139.52,161.9,131.88,171.3,131.88Z" transform="translate(-32.55 -99.43)"/><path class="cls-4" d="M203.36,132.4c6.29,0,10.86,4.1,10.86,12,0,7.48-4.57,12-10.86,12H193.8v12.32h-2.39V132.4Zm0,21.66c4.63,0,8.42-3,8.42-9.66s-3.64-9.71-8.42-9.71H193.8v19.37Z" transform="translate(-32.55 -99.43)"/><path class="cls-4" d="M214.64,168.77v-.31l14.49-36.16h1.1l14.34,36.16v.31H242l-4.1-10.5H221.34l-4.1,10.5Zm15-32.16L222.17,156h14.91Z" transform="translate(-32.55 -99.43)"/><path class="cls-4" d="M266.13,132.4h2.6v.36L257.4,153.65v15.12h-2.49V153.65l-11.38-20.94v-.31h2.65l4.93,9.25,5,9.61h0l5-9.61Z" transform="translate(-32.55 -99.43)"/></svg> |  | ||||||
| Before Width: | Height: | Size: 2.3 KiB | 
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user