Merge branch 'master' into mononaut/utxo-chart-colors
This commit is contained in:
		
						commit
						92de208414
					
				| @ -369,7 +369,7 @@ class MempoolBlocks { | ||||
|     const lastBlockIndex = blocks.length - 1; | ||||
|     let hasBlockStack = blocks.length >= 8; | ||||
|     let stackWeight; | ||||
|     let feeStatsCalculator: OnlineFeeStatsCalculator | void; | ||||
|     let feeStatsCalculator: OnlineFeeStatsCalculator | null = null; | ||||
|     if (hasBlockStack) { | ||||
|       if (blockWeights && blockWeights[7] !== null) { | ||||
|         stackWeight = blockWeights[7]; | ||||
| @ -380,28 +380,36 @@ class MempoolBlocks { | ||||
|       feeStatsCalculator = new OnlineFeeStatsCalculator(stackWeight, 0.5, [10, 20, 30, 40, 50, 60, 70, 80, 90]); | ||||
|     } | ||||
| 
 | ||||
|     const ancestors: Ancestor[] = []; | ||||
|     const descendants: Ancestor[] = []; | ||||
|     let ancestor: MempoolTransactionExtended | ||||
|     for (const cluster of clusters) { | ||||
|       for (const memberTxid of cluster) { | ||||
|         const mempoolTx = mempool[memberTxid]; | ||||
|         if (mempoolTx) { | ||||
|           const ancestors: Ancestor[] = []; | ||||
|           const descendants: Ancestor[] = []; | ||||
|           // ugly micro-optimization to avoid allocating new arrays
 | ||||
|           ancestors.length = 0; | ||||
|           descendants.length = 0; | ||||
|           let matched = false; | ||||
|           cluster.forEach(txid => { | ||||
|             ancestor = mempool[txid]; | ||||
|             if (txid === memberTxid) { | ||||
|               matched = true; | ||||
|             } else { | ||||
|               if (!mempool[txid]) { | ||||
|               if (!ancestor) { | ||||
|                 console.log('txid missing from mempool! ', txid, candidates?.txs[txid]); | ||||
|                 return; | ||||
|               } | ||||
|               const relative = { | ||||
|                 txid: txid, | ||||
|                 fee: mempool[txid].fee, | ||||
|                 weight: (mempool[txid].adjustedVsize * 4), | ||||
|                 fee: ancestor.fee, | ||||
|                 weight: (ancestor.adjustedVsize * 4), | ||||
|               }; | ||||
|               if (matched) { | ||||
|                 descendants.push(relative); | ||||
|                 mempoolTx.lastBoosted = Math.max(mempoolTx.lastBoosted || 0, mempool[txid].firstSeen || 0); | ||||
|                 if (!mempoolTx.lastBoosted || (ancestor.firstSeen && ancestor.firstSeen > mempoolTx.lastBoosted)) { | ||||
|                   mempoolTx.lastBoosted = ancestor.firstSeen; | ||||
|                 } | ||||
|               } else { | ||||
|                 ancestors.push(relative); | ||||
|               } | ||||
| @ -410,7 +418,20 @@ class MempoolBlocks { | ||||
|           if (mempoolTx.ancestors?.length !== ancestors.length || mempoolTx.descendants?.length !== descendants.length) { | ||||
|             mempoolTx.cpfpDirty = true; | ||||
|           } | ||||
|           Object.assign(mempoolTx, {ancestors, descendants, bestDescendant: null, cpfpChecked: true}); | ||||
|           // ugly micro-optimization to avoid allocating new arrays or objects
 | ||||
|           if (mempoolTx.ancestors) { | ||||
|             mempoolTx.ancestors.length = 0; | ||||
|           } else { | ||||
|             mempoolTx.ancestors = []; | ||||
|           } | ||||
|           if (mempoolTx.descendants) { | ||||
|             mempoolTx.descendants.length = 0; | ||||
|           } else { | ||||
|             mempoolTx.descendants = []; | ||||
|           } | ||||
|           mempoolTx.ancestors.push(...ancestors); | ||||
|           mempoolTx.descendants.push(...descendants); | ||||
|           mempoolTx.cpfpChecked = true; | ||||
|         } | ||||
|       } | ||||
|     } | ||||
| @ -420,7 +441,10 @@ class MempoolBlocks { | ||||
|     const sizeLimit = (config.MEMPOOL.BLOCK_WEIGHT_UNITS / 4) * 1.2; | ||||
|     // update this thread's mempool with the results
 | ||||
|     let mempoolTx: MempoolTransactionExtended; | ||||
|     const mempoolBlocks: MempoolBlockWithTransactions[] = blocks.map((block, blockIndex) => { | ||||
|     let acceleration: Acceleration; | ||||
|     const mempoolBlocks: MempoolBlockWithTransactions[] = []; | ||||
|     for (let blockIndex = 0; blockIndex < blocks.length; blockIndex++) { | ||||
|       const block = blocks[blockIndex]; | ||||
|       let totalSize = 0; | ||||
|       let totalVsize = 0; | ||||
|       let totalWeight = 0; | ||||
| @ -436,7 +460,8 @@ class MempoolBlocks { | ||||
|         } | ||||
|       } | ||||
| 
 | ||||
|       for (const txid of block) { | ||||
|       for (let i = 0; i < block.length; i++) { | ||||
|         const txid = block[i]; | ||||
|         if (txid) { | ||||
|           mempoolTx = mempool[txid]; | ||||
|           // save position in projected blocks
 | ||||
| @ -445,30 +470,37 @@ class MempoolBlocks { | ||||
|             vsize: totalVsize + (mempoolTx.vsize / 2), | ||||
|           }; | ||||
| 
 | ||||
|           const acceleration = accelerations[txid]; | ||||
|           if (isAcceleratedBy[txid] || (acceleration && (!accelerationPool || acceleration.pools.includes(accelerationPool)))) { | ||||
|             if (!mempoolTx.acceleration) { | ||||
|               mempoolTx.cpfpDirty = true; | ||||
|             } | ||||
|             mempoolTx.acceleration = true; | ||||
|             mempoolTx.acceleratedBy = isAcceleratedBy[txid] || acceleration?.pools; | ||||
|             mempoolTx.acceleratedAt = acceleration?.added; | ||||
|             mempoolTx.feeDelta = acceleration?.feeDelta; | ||||
|             for (const ancestor of mempoolTx.ancestors || []) { | ||||
|               if (!mempool[ancestor.txid].acceleration) { | ||||
|                 mempool[ancestor.txid].cpfpDirty = true; | ||||
|           if (txid in accelerations) { | ||||
|             acceleration = accelerations[txid]; | ||||
|             if (isAcceleratedBy[txid] || (acceleration && (!accelerationPool || acceleration.pools.includes(accelerationPool)))) { | ||||
|               if (!mempoolTx.acceleration) { | ||||
|                 mempoolTx.cpfpDirty = true; | ||||
|               } | ||||
|               mempoolTx.acceleration = true; | ||||
|               mempoolTx.acceleratedBy = isAcceleratedBy[txid] || acceleration?.pools; | ||||
|               mempoolTx.acceleratedAt = acceleration?.added; | ||||
|               mempoolTx.feeDelta = acceleration?.feeDelta; | ||||
|               for (const ancestor of mempoolTx.ancestors || []) { | ||||
|                 if (!mempool[ancestor.txid].acceleration) { | ||||
|                   mempool[ancestor.txid].cpfpDirty = true; | ||||
|                 } | ||||
|                 mempool[ancestor.txid].acceleration = true; | ||||
|                 mempool[ancestor.txid].acceleratedBy = mempoolTx.acceleratedBy; | ||||
|                 mempool[ancestor.txid].acceleratedAt = mempoolTx.acceleratedAt; | ||||
|                 mempool[ancestor.txid].feeDelta = mempoolTx.feeDelta; | ||||
|                 isAcceleratedBy[ancestor.txid] = mempoolTx.acceleratedBy; | ||||
|               } | ||||
|             } else { | ||||
|               if (mempoolTx.acceleration) { | ||||
|                 mempoolTx.cpfpDirty = true; | ||||
|                 delete mempoolTx.acceleration; | ||||
|               } | ||||
|               mempool[ancestor.txid].acceleration = true; | ||||
|               mempool[ancestor.txid].acceleratedBy = mempoolTx.acceleratedBy; | ||||
|               mempool[ancestor.txid].acceleratedAt = mempoolTx.acceleratedAt; | ||||
|               mempool[ancestor.txid].feeDelta = mempoolTx.feeDelta; | ||||
|               isAcceleratedBy[ancestor.txid] = mempoolTx.acceleratedBy; | ||||
|             } | ||||
|           } else { | ||||
|             if (mempoolTx.acceleration) { | ||||
|               mempoolTx.cpfpDirty = true; | ||||
|               delete mempoolTx.acceleration; | ||||
|             } | ||||
|             delete mempoolTx.acceleration; | ||||
|           } | ||||
| 
 | ||||
|           // online calculation of stack-of-blocks fee stats
 | ||||
| @ -486,7 +518,7 @@ class MempoolBlocks { | ||||
|           } | ||||
|         } | ||||
|       } | ||||
|       return this.dataToMempoolBlocks( | ||||
|       mempoolBlocks[blockIndex] = this.dataToMempoolBlocks( | ||||
|         block, | ||||
|         transactions, | ||||
|         totalSize, | ||||
| @ -494,7 +526,7 @@ class MempoolBlocks { | ||||
|         totalFees, | ||||
|         (hasBlockStack && blockIndex === lastBlockIndex && feeStatsCalculator) ? feeStatsCalculator.getRawFeeStats() : undefined, | ||||
|       ); | ||||
|     }); | ||||
|     }; | ||||
| 
 | ||||
|     if (saveResults) { | ||||
|       const deltas = this.calculateMempoolDeltas(this.mempoolBlocks, mempoolBlocks); | ||||
|  | ||||
| @ -12,7 +12,7 @@ | ||||
|           </p> | ||||
|         </div> | ||||
|         <div class="spacer"></div> | ||||
|         <span class="fee">{{ bar.class === 'tx' ? '' : '+' }}{{ bar.fee | number }} <span class="symbol" i18n="shared.sat|sat">sat</span></span> | ||||
|         <span class="fee">{{ bar.class === 'tx' ? '' : '+' }}{{ bar.fee | number }} <span class="symbol" i18n="shared.sats">sats</span></span> | ||||
|         <div class="spacer"></div> | ||||
|         <div class="spacer"></div> | ||||
|       </div> | ||||
|  | ||||
| @ -21,14 +21,14 @@ | ||||
|       </tr> | ||||
|       <tr *ngIf="accelerationInfo.fee"> | ||||
|         <td class="label" i18n="transaction.fee|Transaction fee">Fee</td> | ||||
|         <td class="value">{{ accelerationInfo.fee | number }} <span class="symbol" i18n="shared.sat|sat">sat</span></td> | ||||
|         <td class="value">{{ accelerationInfo.fee | number }} <span class="symbol" i18n="shared.sats">sats</span></td> | ||||
|       </tr> | ||||
|       <tr *ngIf="accelerationInfo.bidBoost >= 0 || accelerationInfo.feeDelta"> | ||||
|         <td class="label" i18n="transaction.out-of-band-fees">Out-of-band fees</td> | ||||
|         @if (accelerationInfo.status === 'accelerated') { | ||||
|           <td class="value oobFees">{{ accelerationInfo.feeDelta | number }} <span class="symbol" i18n="shared.sat|sat">sat</span></td> | ||||
|           <td class="value oobFees">{{ accelerationInfo.feeDelta | number }} <span class="symbol" i18n="shared.sats">sats</span></td> | ||||
|         } @else { | ||||
|           <td class="value oobFees">{{ accelerationInfo.bidBoost | number }} <span class="symbol" i18n="shared.sat|sat">sat</span></td> | ||||
|           <td class="value oobFees">{{ accelerationInfo.bidBoost | number }} <span class="symbol" i18n="shared.sats">sats</span></td> | ||||
|         } | ||||
|       </tr> | ||||
|       <tr *ngIf="accelerationInfo.fee && accelerationInfo.weight"> | ||||
|  | ||||
| @ -264,7 +264,7 @@ export class AccelerationFeesGraphComponent implements OnInit, OnChanges, OnDest | ||||
|           type: 'bar', | ||||
|           barWidth: '90%', | ||||
|           large: true, | ||||
|           barMinHeight: 1, | ||||
|           barMinHeight: 3, | ||||
|         }, | ||||
|       ], | ||||
|       dataZoom: (this.widget || data.length === 0 )? undefined : [{ | ||||
|  | ||||
| @ -33,7 +33,7 @@ | ||||
|               <app-fee-rate [fee]="acceleration.effectiveFee" [weight]="acceleration.effectiveVsize * 4"></app-fee-rate> | ||||
|             </td> | ||||
|             <td class="bid text-right"> | ||||
|               {{ (acceleration.feeDelta) | number }} <span class="symbol" i18n="shared.sat|sat">sat</span> | ||||
|               {{ (acceleration.feeDelta) | number }} <span class="symbol" i18n="shared.sats">sats</span> | ||||
|             </td> | ||||
|             <td class="time text-right"> | ||||
|               <app-time kind="since" [time]="acceleration.added" [fastRender]="true" [showTooltip]="true"></app-time> | ||||
| @ -41,7 +41,7 @@ | ||||
|           </ng-container> | ||||
|           <ng-container *ngIf="!pending"> | ||||
|             <td *ngIf="acceleration.boost != null" class="fee text-right"> | ||||
|               {{ acceleration.boost | number }} <span class="symbol" i18n="shared.sat|sat">sat</span> | ||||
|               {{ acceleration.boost | number }} <span class="symbol" i18n="shared.sats">sats</span> | ||||
|             </td> | ||||
|             <td *ngIf="acceleration.boost == null" class="fee text-right"> | ||||
|               ~ | ||||
|  | ||||
| @ -10,10 +10,10 @@ | ||||
|       </td> | ||||
|       <td class="field-value" [class]="chartPositionLeft ? 'chart-left' : ''"> | ||||
|         <div class="effective-fee-container"> | ||||
|           @if (accelerationInfo?.acceleratedFeeRate && (!tx.effectiveFeePerVsize || accelerationInfo.acceleratedFeeRate >= tx.effectiveFeePerVsize)) { | ||||
|           @if (accelerationInfo?.acceleratedFeeRate && (!effectiveFeeRate || accelerationInfo.acceleratedFeeRate >= effectiveFeeRate)) { | ||||
|             <app-fee-rate class="oobFees" [fee]="accelerationInfo.acceleratedFeeRate"></app-fee-rate> | ||||
|           } @else { | ||||
|             <app-fee-rate class="oobFees" [fee]="tx.effectiveFeePerVsize"></app-fee-rate> | ||||
|             <app-fee-rate class="oobFees" [fee]="effectiveFeeRate"></app-fee-rate> | ||||
|           } | ||||
|         </div> | ||||
|       </td> | ||||
|  | ||||
| @ -1,4 +1,4 @@ | ||||
| import { Component, ChangeDetectionStrategy, Input, Output, OnChanges, SimpleChanges, EventEmitter } from '@angular/core'; | ||||
| import { Component, ChangeDetectionStrategy, Input, Output, OnChanges, SimpleChanges, EventEmitter, ChangeDetectorRef } from '@angular/core'; | ||||
| import { Transaction } from '../../../interfaces/electrs.interface'; | ||||
| import { Acceleration, SinglePoolStats } from '../../../interfaces/node-api.interface'; | ||||
| import { EChartsOption, PieSeriesOption } from '../../../graphs/echarts'; | ||||
| @ -23,7 +23,8 @@ function toRGB({r,g,b}): string { | ||||
|   changeDetection: ChangeDetectionStrategy.OnPush, | ||||
| }) | ||||
| export class ActiveAccelerationBox implements OnChanges { | ||||
|   @Input() tx: Transaction; | ||||
|   @Input() acceleratedBy?: number[]; | ||||
|   @Input() effectiveFeeRate?: number; | ||||
|   @Input() accelerationInfo: Acceleration; | ||||
|   @Input() miningStats: MiningStats; | ||||
|   @Input() pools: number[]; | ||||
| @ -41,10 +42,12 @@ export class ActiveAccelerationBox implements OnChanges { | ||||
|   timespan = ''; | ||||
|   chartInstance: any = undefined; | ||||
| 
 | ||||
|   constructor() {} | ||||
|   constructor( | ||||
|     private cd: ChangeDetectorRef, | ||||
|   ) {} | ||||
| 
 | ||||
|   ngOnChanges(changes: SimpleChanges): void { | ||||
|     const pools = this.pools || this.accelerationInfo?.pools || this.tx.acceleratedBy; | ||||
|     const pools = this.pools || this.accelerationInfo?.pools || this.acceleratedBy; | ||||
|     if (pools && this.miningStats) { | ||||
|       this.prepareChartOptions(pools); | ||||
|     } | ||||
| @ -132,6 +135,7 @@ export class ActiveAccelerationBox implements OnChanges { | ||||
|         } | ||||
|       ] | ||||
|     }; | ||||
|     this.cd.markForCheck(); | ||||
|   } | ||||
| 
 | ||||
|   onChartInit(ec) { | ||||
|  | ||||
| @ -1,7 +1,7 @@ | ||||
| <div [formGroup]="amountForm" class="text-small text-center"> | ||||
|     <select formControlName="mode" class="custom-select custom-select-sm form-control-secondary form-control mx-auto" style="width: 70px;" (change)="changeMode()"> | ||||
|         <option value="btc" i18n="shared.btc|BTC">BTC</option> | ||||
|         <option value="sats" i18n="shared.sat|sat">sat</option> | ||||
|         <option value="sats" i18n="shared.sats">sats</option> | ||||
|         <option value="fiat" i18n="shared.fiat|Fiat">Fiat</option> | ||||
|     </select> | ||||
| </div> | ||||
|  | ||||
| @ -40,7 +40,7 @@ | ||||
|       </tr> | ||||
|       <tr> | ||||
|         <td class="label" i18n="transaction.fee|Transaction fee">Fee</td> | ||||
|         <td class="value">{{ fee | number }} <span class="symbol" i18n="shared.sat|sat">sat</span>   <span class="fiat"><app-fiat [blockConversion]="blockConversion" [value]="fee"></app-fiat></span> | ||||
|         <td class="value">{{ fee | number }} <span class="symbol" i18n="shared.sats">sats</span>   <span class="fiat"><app-fiat [blockConversion]="blockConversion" [value]="fee"></app-fiat></span> | ||||
|       </tr> | ||||
|       <tr> | ||||
|         <td class="label" i18n="transaction.fee-rate|Transaction fee rate">Fee rate</td> | ||||
|  | ||||
| @ -19,7 +19,7 @@ | ||||
|       </tr> | ||||
|       <tr> | ||||
|         <td class="td-width" i18n="transaction.fee|Transaction fee">Fee</td> | ||||
|         <td>{{ rbfInfo.tx.fee | number }} <span class="symbol" i18n="shared.sat|sat">sat</span></td> | ||||
|         <td>{{ rbfInfo.tx.fee | number }} <span class="symbol" i18n="shared.sats">sats</span></td> | ||||
|       </tr> | ||||
|       <tr *only-vsize> | ||||
|         <td class="td-width" i18n="transaction.vsize|Transaction Virtual Size">Virtual size</td> | ||||
|  | ||||
| @ -21,7 +21,7 @@ | ||||
|       </ng-template> | ||||
|     </span> | ||||
|     <span class="field col-sm-4 text-center"><ng-container *ngIf="transactionTime > 0">‎{{ transactionTime * 1000 | date:'yyyy-MM-dd HH:mm' }}</ng-container></span> | ||||
|     <span class="field col-sm-4 text-right"><span class="label" i18n="transaction.fee|Transaction fee">Fee</span> {{ tx.fee | number }} <span class="symbol" i18n="shared.sat|sat">sat</span></span> | ||||
|     <span class="field col-sm-4 text-right"><span class="label" i18n="transaction.fee|Transaction fee">Fee</span> {{ tx.fee | number }} <span class="symbol" i18n="shared.sats">sats</span></span> | ||||
|   </div> | ||||
| 
 | ||||
| 
 | ||||
|  | ||||
| @ -606,9 +606,9 @@ | ||||
|   @if (!isLoadingTx) { | ||||
|     <tr> | ||||
|       <td class="td-width" i18n="transaction.fee|Transaction fee">Fee</td> | ||||
|       <td class="text-wrap">{{ tx.fee | number }} <span class="symbol" i18n="shared.sat|sat">sat</span> | ||||
|       <td class="text-wrap">{{ tx.fee | number }} <span class="symbol" i18n="shared.sats">sats</span> | ||||
|         @if (accelerationInfo?.bidBoost ?? tx.feeDelta > 0) { | ||||
|           <span class="oobFees" i18n-ngbTooltip="Acceleration Fees" ngbTooltip="Acceleration fees paid out-of-band"> +{{ accelerationInfo?.bidBoost ?? tx.feeDelta | number }} </span><span class="symbol" i18n="shared.sat|sat">sat</span> | ||||
|           <span class="oobFees" i18n-ngbTooltip="Acceleration Fees" ngbTooltip="Acceleration fees paid out-of-band"> +{{ accelerationInfo?.bidBoost ?? tx.feeDelta | number }} </span><span class="symbol" i18n="shared.sats">sats</span> | ||||
|         } | ||||
|         <span class="fiat"><app-fiat [blockConversion]="tx.price" [value]="tx.fee + ((accelerationInfo?.bidBoost ?? tx.feeDelta) || 0)"></app-fiat></span> | ||||
|       </td> | ||||
| @ -670,7 +670,7 @@ | ||||
| <ng-template #acceleratingRow> | ||||
|   <tr> | ||||
|     <td rowspan="2" colspan="2" style="padding: 0;"> | ||||
|       <app-active-acceleration-box [tx]="tx" [accelerationInfo]="accelerationInfo" [miningStats]="miningStats" [hasCpfp]="hasCpfp" (toggleCpfp)="showCpfpDetails = !showCpfpDetails" [chartPositionLeft]="isMobile"></app-active-acceleration-box> | ||||
|       <app-active-acceleration-box [acceleratedBy]="tx.acceleratedBy" [effectiveFeeRate]="tx.effectiveFeePerVsize" [accelerationInfo]="accelerationInfo" [miningStats]="miningStats" [hasCpfp]="hasCpfp" (toggleCpfp)="showCpfpDetails = !showCpfpDetails" [chartPositionLeft]="isMobile"></app-active-acceleration-box> | ||||
|     </td> | ||||
|   </tr> | ||||
|   <tr></tr> | ||||
|  | ||||
| @ -321,7 +321,7 @@ | ||||
|       <div class="float-left mt-2-5" *ngIf="!transactionPage && !tx.vin[0].is_coinbase && tx.fee !== -1"> | ||||
|         <app-fee-rate [fee]="tx.fee" [weight]="tx.weight"></app-fee-rate> | ||||
|         <span class="d-none d-sm-inline-block"> – {{ tx.fee | number }} <span class="symbol" | ||||
|             i18n="shared.sat|sat">sat</span> <span class="fiat"><app-fiat [blockConversion]="tx.price" [value]="tx.fee"></app-fiat></span></span> | ||||
|             i18n="shared.sats">sats</span> <span class="fiat"><app-fiat [blockConversion]="tx.price" [value]="tx.fee"></app-fiat></span></span> | ||||
|       </div> | ||||
|       <div class="float-left mt-2-5 grey-info-text" *ngIf="tx.fee === -1" i18n="transactions-list.load-to-reveal-fee-info">Show more inputs to reveal fee data</div> | ||||
| 
 | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user