From bca35600ff2a18dc9f0c5a08093cab0349818627 Mon Sep 17 00:00:00 2001 From: wiz Date: Tue, 4 Apr 2023 20:18:46 +0900 Subject: [PATCH 001/242] ops: Fix installer creation of CLN folders --- production/install | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/production/install b/production/install index 27c4dbd14..b97ef16d1 100755 --- a/production/install +++ b/production/install @@ -1312,8 +1312,13 @@ case $OS in osSudo "${ROOT_USER}" pw usermod ${MEMPOOL_USER} -G "${CLN_GROUP}" osSudo "${ROOT_USER}" chsh -s `which zsh` "${CLN_USER}" echo "export PATH=$PATH:$HOME/.local/bin" >> "${CLN_HOME}/.zshrc" - osSudo "${ROOT_USER}" mkdir -p "${CLN_HOME}/.lightning/{bitcoin,signet,testnet}" - osSudo "${ROOT_USER}" chmod 750 "${CLN_HOME}" "${CLN_HOME}/.lightning" "${CLN_HOME}/.lightning/{bitcoin,signet,testnet}" + osSudo "${ROOT_USER}" mkdir -p "${CLN_HOME}/.lightning/bitcoin" + osSudo "${ROOT_USER}" mkdir -p "${CLN_HOME}/.lightning/signet" + osSudo "${ROOT_USER}" mkdir -p "${CLN_HOME}/.lightning/testnet" + osSudo "${ROOT_USER}" chmod 750 "${CLN_HOME}" "${CLN_HOME}/.lightning" + osSudo "${ROOT_USER}" chmod 750 "${CLN_HOME}" "${CLN_HOME}/.lightning/bitcoin" + osSudo "${ROOT_USER}" chmod 750 "${CLN_HOME}" "${CLN_HOME}/.lightning/signet" + osSudo "${ROOT_USER}" chmod 750 "${CLN_HOME}" "${CLN_HOME}/.lightning/testnet" osSudo "${ROOT_USER}" chown -R "${CLN_USER}:${CLN_GROUP}" "${CLN_HOME}" echo "[*] Creating symlink to .bitcoin folder" osSudo "${CLN_USER}" ln -s "${BITCOIN_HOME}/.bitcoin" "${CLN_HOME}/.bitcoin" From 6602bddb2b8e040d313f5bd7a19433e315a1c993 Mon Sep 17 00:00:00 2001 From: Mononaut Date: Fri, 7 Apr 2023 03:25:02 +0900 Subject: [PATCH 002/242] Fit mempool block skeleton loaders to screen --- .../mempool-blocks.component.ts | 23 ++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/frontend/src/app/components/mempool-blocks/mempool-blocks.component.ts b/frontend/src/app/components/mempool-blocks/mempool-blocks.component.ts index 1b647fc53..ab0a7fd08 100644 --- a/frontend/src/app/components/mempool-blocks/mempool-blocks.component.ts +++ b/frontend/src/app/components/mempool-blocks/mempool-blocks.component.ts @@ -97,7 +97,7 @@ export class MempoolBlocksComponent implements OnInit, OnDestroy { this.mempoolEmptyBlocks.forEach((b) => { this.mempoolEmptyBlockStyles.push(this.getStyleForMempoolEmptyBlock(b.index)); }); - this.reduceMempoolBlocksToFitScreen(this.mempoolEmptyBlocks); + this.reduceEmptyBlocksToFitScreen(this.mempoolEmptyBlocks); this.mempoolBlocks.map(() => { this.updateMempoolBlockStyles(); @@ -225,12 +225,33 @@ export class MempoolBlocksComponent implements OnInit, OnDestroy { @HostListener('window:resize', ['$event']) onResize(): void { this.animateEntry = false; + this.reduceEmptyBlocksToFitScreen(this.mempoolEmptyBlocks); } trackByFn(index: number, block: MempoolBlock) { return (block.isStack) ? `stack-${block.index}` : block.index; } + reduceEmptyBlocksToFitScreen(blocks: MempoolBlock[]): MempoolBlock[] { + const innerWidth = this.stateService.env.BASE_MODULE !== 'liquid' && window.innerWidth <= 767.98 ? window.innerWidth : window.innerWidth / 2; + const blocksAmount = Math.min(this.stateService.env.MEMPOOL_BLOCKS_AMOUNT, Math.floor(innerWidth / (this.blockWidth + this.blockPadding))); + while (blocks.length < blocksAmount) { + blocks.push({ + blockSize: 0, + blockVSize: 0, + feeRange: [], + index: blocks.length, + medianFee: 0, + nTx: 0, + totalFees: 0 + }); + } + while (blocks.length > blocksAmount) { + blocks.pop(); + } + return blocks; + } + reduceMempoolBlocksToFitScreen(blocks: MempoolBlock[]): MempoolBlock[] { const innerWidth = this.stateService.env.BASE_MODULE !== 'liquid' && window.innerWidth <= 767.98 ? window.innerWidth : window.innerWidth / 2; const blocksAmount = Math.min(this.stateService.env.MEMPOOL_BLOCKS_AMOUNT, Math.floor(innerWidth / (this.blockWidth + this.blockPadding))); From d7333ec8584a31a23dabac17b5464042ca473868 Mon Sep 17 00:00:00 2001 From: Mononaut Date: Wed, 3 May 2023 14:59:27 -0600 Subject: [PATCH 003/242] display fee box skeleton while mempool not in sync --- .../app/components/fees-box/fees-box.component.html | 2 +- .../app/components/fees-box/fees-box.component.ts | 13 +++++++++---- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/frontend/src/app/components/fees-box/fees-box.component.html b/frontend/src/app/components/fees-box/fees-box.component.html index b56663571..1aea85429 100644 --- a/frontend/src/app/components/fees-box/fees-box.component.html +++ b/frontend/src/app/components/fees-box/fees-box.component.html @@ -1,4 +1,4 @@ -
+
No Priority diff --git a/frontend/src/app/components/fees-box/fees-box.component.ts b/frontend/src/app/components/fees-box/fees-box.component.ts index 48098db7b..4f9772b22 100644 --- a/frontend/src/app/components/fees-box/fees-box.component.ts +++ b/frontend/src/app/components/fees-box/fees-box.component.ts @@ -1,9 +1,9 @@ import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core'; import { StateService } from '../../services/state.service'; -import { Observable } from 'rxjs'; +import { Observable, combineLatest } from 'rxjs'; import { Recommendedfees } from '../../interfaces/websocket.interface'; import { feeLevels, mempoolFeeColors } from '../../app.constants'; -import { tap } from 'rxjs/operators'; +import { map, startWith, tap } from 'rxjs/operators'; @Component({ selector: 'app-fees-box', @@ -12,7 +12,7 @@ import { tap } from 'rxjs/operators'; changeDetection: ChangeDetectionStrategy.OnPush, }) export class FeesBoxComponent implements OnInit { - isLoadingWebSocket$: Observable; + isLoading$: Observable; recommendedFees$: Observable; gradient = 'linear-gradient(to right, #2e324e, #2e324e)'; noPriority = '#2e324e'; @@ -22,7 +22,12 @@ export class FeesBoxComponent implements OnInit { ) { } ngOnInit(): void { - this.isLoadingWebSocket$ = this.stateService.isLoadingWebSocket$; + this.isLoading$ = combineLatest( + this.stateService.isLoadingWebSocket$.pipe(startWith(false)), + this.stateService.loadingIndicators$.pipe(startWith({ mempool: 0 })), + ).pipe(map(([socket, indicators]) => { + return socket || (indicators.mempool != null && indicators.mempool !== 100); + })); this.recommendedFees$ = this.stateService.recommendedFees$ .pipe( tap((fees) => { From 4b20ea7232b45fbe7bd029f42e8dde7ff33d8152 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vojt=C4=9Bch=20Strnad?= <43024885+vostrnad@users.noreply.github.com> Date: Thu, 11 May 2023 00:10:57 +0200 Subject: [PATCH 004/242] Accept the CLA for @vostrnad --- contributors/vostrnad.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 contributors/vostrnad.txt diff --git a/contributors/vostrnad.txt b/contributors/vostrnad.txt new file mode 100644 index 000000000..6b295c715 --- /dev/null +++ b/contributors/vostrnad.txt @@ -0,0 +1,3 @@ +I hereby accept the terms of the Contributor License Agreement in the CONTRIBUTING.md file of the mempool/mempool git repository as of January 25, 2022. + +Signed: vostrnad From be53cd8b4849579a1900394e1dda6b52962d1ce0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vojt=C4=9Bch=20Strnad?= <43024885+vostrnad@users.noreply.github.com> Date: Thu, 11 May 2023 00:11:23 +0200 Subject: [PATCH 005/242] Display empty witness items --- .../transactions-list/transactions-list.component.html | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/frontend/src/app/components/transactions-list/transactions-list.component.html b/frontend/src/app/components/transactions-list/transactions-list.component.html index 71eeb4aa1..0d195f2ff 100644 --- a/frontend/src/app/components/transactions-list/transactions-list.component.html +++ b/frontend/src/app/components/transactions-list/transactions-list.component.html @@ -114,7 +114,12 @@

- {{ witness }} + + {{ witness }} + + + <empty> +

... From 3d1cd3193a35efae0d1ace86f8a3e48e065820a9 Mon Sep 17 00:00:00 2001 From: Mononaut Date: Wed, 10 May 2023 12:59:05 -0600 Subject: [PATCH 006/242] online calculation of stack-of-n-blocks fee statistics --- backend/src/api/common.ts | 118 +++++++++++++++++++++++++++++- backend/src/api/mempool-blocks.ts | 53 +++++++++++--- backend/src/mempool.interfaces.ts | 5 ++ 3 files changed, 166 insertions(+), 10 deletions(-) diff --git a/backend/src/api/common.ts b/backend/src/api/common.ts index b044e2866..fc952d6a8 100644 --- a/backend/src/api/common.ts +++ b/backend/src/api/common.ts @@ -1,4 +1,4 @@ -import { Ancestor, CpfpInfo, CpfpSummary, EffectiveFeeStats, MempoolBlockWithTransactions, TransactionExtended, TransactionStripped } from '../mempool.interfaces'; +import { Ancestor, CpfpInfo, CpfpSummary, EffectiveFeeStats, MempoolBlockWithTransactions, TransactionExtended, TransactionStripped, WorkingEffectiveFeeStats } from '../mempool.interfaces'; import config from '../config'; import { NodeSocket } from '../repositories/NodesSocketsRepository'; import { isIP } from 'net'; @@ -442,3 +442,119 @@ export class Common { return sortedDistribution[Math.floor((sortedDistribution.length - 1) * (n / 100))]; } } + +/** + * Class to calculate average fee rates of a list of transactions + * at certain weight percentiles, in a single pass + * + * init with: + * maxWeight - the total weight to measure percentiles relative to (e.g. 4MW for a single block) + * percentileBandWidth - how many weight units to average over for each percentile (as a % of maxWeight) + * percentiles - an array of weight percentiles to compute, in % + * + * then call .processNext(tx) for each transaction, in descending order + * + * retrieve the final results with .getFeeStats() + */ +export class OnlineFeeStatsCalculator { + private maxWeight: number; + private percentiles = [10,25,50,75,90]; + + private bandWidthPercent = 2; + private bandWidth: number = 0; + private bandIndex = 0; + private leftBound = 0; + private rightBound = 0; + private inBand = false; + private totalBandFee = 0; + private totalBandWeight = 0; + private minBandRate = Infinity; + private maxBandRate = 0; + + private feeRange: { avg: number, min: number, max: number }[] = []; + private totalWeight: number = 0; + + constructor (maxWeight: number, percentileBandWidth?: number, percentiles?: number[]) { + this.maxWeight = maxWeight; + if (percentiles && percentiles.length) { + this.percentiles = percentiles; + } + if (percentileBandWidth != null) { + this.bandWidthPercent = percentileBandWidth; + } + this.bandWidth = this.maxWeight * (this.bandWidthPercent / 100); + // add min/max percentiles aligned to the ends of the range + this.percentiles.unshift(this.bandWidthPercent / 2); + this.percentiles.push(100 - (this.bandWidthPercent / 2)); + this.setNextBounds(); + } + + processNext(tx: { weight: number, fee: number, effectiveFeePerVsize?: number, feePerVsize?: number, rate?: number, txid: string }): void { + let left = this.totalWeight; + const right = this.totalWeight + tx.weight; + if (!this.inBand && right <= this.leftBound) { + this.totalWeight += tx.weight; + return; + } + + while (left < right) { + if (right > this.leftBound) { + this.inBand = true; + const txRate = (tx.rate || tx.effectiveFeePerVsize || tx.feePerVsize || 0); + const weight = Math.min(right, this.rightBound) - Math.max(left, this.leftBound); + this.totalBandFee += (txRate * weight); + this.totalBandWeight += weight; + this.maxBandRate = Math.max(this.maxBandRate, txRate); + this.minBandRate = Math.min(this.minBandRate, txRate); + } + left = Math.min(right, this.rightBound); + + if (left >= this.rightBound) { + this.inBand = false; + const avgBandFeeRate = this.totalBandWeight ? (this.totalBandFee / this.totalBandWeight) : 0; + this.feeRange.unshift({ avg: avgBandFeeRate, min: this.minBandRate, max: this.maxBandRate }); + this.bandIndex++; + this.setNextBounds(); + this.totalBandFee = 0; + this.totalBandWeight = 0; + this.minBandRate = Infinity; + this.maxBandRate = 0; + } + } + this.totalWeight += tx.weight; + } + + private setNextBounds(): void { + const nextPercentile = this.percentiles[this.bandIndex]; + if (nextPercentile != null) { + this.leftBound = ((nextPercentile / 100) * this.maxWeight) - (this.bandWidth / 2); + this.rightBound = this.leftBound + this.bandWidth; + } else { + this.leftBound = Infinity; + this.rightBound = Infinity; + } + } + + getRawFeeStats(): WorkingEffectiveFeeStats { + if (this.totalBandWeight > 0) { + const avgBandFeeRate = this.totalBandWeight ? (this.totalBandFee / this.totalBandWeight) : 0; + this.feeRange.unshift({ avg: avgBandFeeRate, min: this.minBandRate, max: this.maxBandRate }); + } + while (this.feeRange.length < this.percentiles.length) { + this.feeRange.unshift({ avg: 0, min: 0, max: 0 }); + } + return { + minFee: this.feeRange[0].min, + medianFee: this.feeRange[Math.floor(this.feeRange.length / 2)].avg, + maxFee: this.feeRange[this.feeRange.length - 1].max, + feeRange: this.feeRange.map(f => f.avg), + }; + } + + getFeeStats(): EffectiveFeeStats { + const stats = this.getRawFeeStats(); + stats.feeRange[0] = stats.minFee; + stats.feeRange[stats.feeRange.length - 1] = stats.maxFee; + return stats; + } +} diff --git a/backend/src/api/mempool-blocks.ts b/backend/src/api/mempool-blocks.ts index 62717ed7e..803b7e56e 100644 --- a/backend/src/api/mempool-blocks.ts +++ b/backend/src/api/mempool-blocks.ts @@ -1,6 +1,6 @@ import logger from '../logger'; -import { MempoolBlock, TransactionExtended, TransactionStripped, MempoolBlockWithTransactions, MempoolBlockDelta, Ancestor, CompactThreadTransaction } from '../mempool.interfaces'; -import { Common } from './common'; +import { MempoolBlock, TransactionExtended, TransactionStripped, MempoolBlockWithTransactions, MempoolBlockDelta, Ancestor, CompactThreadTransaction, EffectiveFeeStats } from '../mempool.interfaces'; +import { Common, OnlineFeeStatsCalculator } from './common'; import config from '../config'; import { Worker } from 'worker_threads'; import path from 'path'; @@ -104,6 +104,8 @@ class MempoolBlocks { private calculateMempoolBlocks(transactionsSorted: TransactionExtended[]): MempoolBlockWithTransactions[] { const mempoolBlocks: MempoolBlockWithTransactions[] = []; + let feeStatsCalculator: OnlineFeeStatsCalculator = new OnlineFeeStatsCalculator(config.MEMPOOL.BLOCK_WEIGHT_UNITS); + let onlineStats = false; let blockSize = 0; let blockWeight = 0; let blockVsize = 0; @@ -111,7 +113,7 @@ class MempoolBlocks { const sizeLimit = (config.MEMPOOL.BLOCK_WEIGHT_UNITS / 4) * 1.2; let transactionIds: string[] = []; let transactions: TransactionExtended[] = []; - transactionsSorted.forEach((tx) => { + transactionsSorted.forEach((tx, index) => { if (blockWeight + tx.weight <= config.MEMPOOL.BLOCK_WEIGHT_UNITS || mempoolBlocks.length === config.MEMPOOL.MEMPOOL_BLOCKS_AMOUNT - 1) { tx.position = { @@ -126,6 +128,9 @@ class MempoolBlocks { transactions.push(tx); } transactionIds.push(tx.txid); + if (onlineStats) { + feeStatsCalculator.processNext(tx); + } } else { mempoolBlocks.push(this.dataToMempoolBlocks(transactionIds, transactions, blockSize, blockWeight, blockFees)); blockVsize = 0; @@ -133,6 +138,16 @@ class MempoolBlocks { block: mempoolBlocks.length, vsize: blockVsize + (tx.vsize / 2), }; + + if (mempoolBlocks.length === config.MEMPOOL.MEMPOOL_BLOCKS_AMOUNT - 1) { + const stackWeight = transactionsSorted.slice(index).reduce((total, tx) => total + (tx.weight || 0), 0); + if (stackWeight > config.MEMPOOL.BLOCK_WEIGHT_UNITS) { + onlineStats = true; + feeStatsCalculator = new OnlineFeeStatsCalculator(stackWeight, 0.5); + feeStatsCalculator.processNext(tx); + } + } + blockVsize += tx.vsize; blockWeight = tx.weight; blockSize = tx.size; @@ -142,7 +157,8 @@ class MempoolBlocks { } }); if (transactions.length) { - mempoolBlocks.push(this.dataToMempoolBlocks(transactionIds, transactions, blockSize, blockWeight, blockFees)); + const feeStats = onlineStats ? feeStatsCalculator.getRawFeeStats() : undefined; + mempoolBlocks.push(this.dataToMempoolBlocks(transactionIds, transactions, blockSize, blockWeight, blockFees, feeStats)); } return mempoolBlocks; @@ -310,7 +326,16 @@ class MempoolBlocks { } } - const readyBlocks: { transactionIds, transactions, totalSize, totalWeight, totalFees }[] = []; + let hasBlockStack = blocks.length >= 8; + let stackWeight; + let feeStatsCalculator: OnlineFeeStatsCalculator | void; + if (hasBlockStack) { + stackWeight = blocks[blocks.length - 1].reduce((total, tx) => total + (mempool[tx]?.weight || 0), 0); + hasBlockStack = stackWeight > config.MEMPOOL.BLOCK_WEIGHT_UNITS; + feeStatsCalculator = new OnlineFeeStatsCalculator(stackWeight, 0.5); + } + + const readyBlocks: { transactionIds, transactions, totalSize, totalWeight, totalFees, feeStats }[] = []; const sizeLimit = (config.MEMPOOL.BLOCK_WEIGHT_UNITS / 4) * 1.2; // update this thread's mempool with the results for (let blockIndex = 0; blockIndex < blocks.length; blockIndex++) { @@ -333,6 +358,11 @@ class MempoolBlocks { }; mempoolTx.cpfpChecked = true; + // online calculation of stack-of-blocks fee stats + if (hasBlockStack && blockIndex === blocks.length - 1 && feeStatsCalculator) { + feeStatsCalculator.processNext(mempoolTx); + } + totalSize += mempoolTx.size; totalVsize += mempoolTx.vsize; totalWeight += mempoolTx.weight; @@ -348,7 +378,8 @@ class MempoolBlocks { transactions, totalSize, totalWeight, - totalFees + totalFees, + feeStats: (hasBlockStack && blockIndex === blocks.length - 1 && feeStatsCalculator) ? feeStatsCalculator.getRawFeeStats() : undefined, }); } @@ -382,7 +413,9 @@ class MempoolBlocks { } } - const mempoolBlocks = readyBlocks.map(b => this.dataToMempoolBlocks(b.transactionIds, b.transactions, b.totalSize, b.totalWeight, b.totalFees)); + const mempoolBlocks = readyBlocks.map((b, index) => { + return this.dataToMempoolBlocks(b.transactionIds, b.transactions, b.totalSize, b.totalWeight, b.totalFees, b.feeStats); + }); if (saveResults) { const deltas = this.calculateMempoolDeltas(this.mempoolBlocks, mempoolBlocks); @@ -393,8 +426,10 @@ class MempoolBlocks { return mempoolBlocks; } - private dataToMempoolBlocks(transactionIds: string[], transactions: TransactionExtended[], totalSize: number, totalWeight: number, totalFees: number): MempoolBlockWithTransactions { - const feeStats = Common.calcEffectiveFeeStatistics(transactions); + private dataToMempoolBlocks(transactionIds: string[], transactions: TransactionExtended[], totalSize: number, totalWeight: number, totalFees: number, feeStats?: EffectiveFeeStats ): MempoolBlockWithTransactions { + if (!feeStats) { + feeStats = Common.calcEffectiveFeeStatistics(transactions); + } return { blockSize: totalSize, blockVSize: (totalWeight / 4), // fractional vsize to avoid rounding errors diff --git a/backend/src/mempool.interfaces.ts b/backend/src/mempool.interfaces.ts index ab4c4cd25..7204c174e 100644 --- a/backend/src/mempool.interfaces.ts +++ b/backend/src/mempool.interfaces.ts @@ -237,6 +237,11 @@ export interface EffectiveFeeStats { feeRange: number[]; // 2nd, 10th, 25th, 50th, 75th, 90th, 98th percentiles } +export interface WorkingEffectiveFeeStats extends EffectiveFeeStats { + minFee: number; + maxFee: number; +} + export interface CpfpSummary { transactions: TransactionExtended[]; clusters: { root: string, height: number, txs: Ancestor[], effectiveFeePerVsize: number }[]; From abbaee0274a48edd8a96a9c30b3a966dbbbf03cd Mon Sep 17 00:00:00 2001 From: Mononaut Date: Wed, 10 May 2023 19:57:58 -0600 Subject: [PATCH 007/242] Fix txids interpreted as addresses in search --- .../src/app/components/search-form/search-form.component.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frontend/src/app/components/search-form/search-form.component.ts b/frontend/src/app/components/search-form/search-form.component.ts index af5ccc654..422cb2f45 100644 --- a/frontend/src/app/components/search-form/search-form.component.ts +++ b/frontend/src/app/components/search-form/search-form.component.ts @@ -153,7 +153,7 @@ export class SearchFormComponent implements OnInit { const matchesBlockHeight = this.regexBlockheight.test(searchText); const matchesTxId = this.regexTransaction.test(searchText) && !this.regexBlockhash.test(searchText); const matchesBlockHash = this.regexBlockhash.test(searchText); - const matchesAddress = this.regexAddress.test(searchText); + const matchesAddress = !matchesTxId && this.regexAddress.test(searchText); if (matchesAddress && this.network === 'bisq') { searchText = 'B' + searchText; @@ -198,7 +198,7 @@ export class SearchFormComponent implements OnInit { const searchText = result || this.searchForm.value.searchText.trim(); if (searchText) { this.isSearching = true; - if (this.regexAddress.test(searchText)) { + if (!this.regexTransaction.test(searchText) && this.regexAddress.test(searchText)) { this.navigate('/address/', searchText); } else if (this.regexBlockhash.test(searchText) || this.regexBlockheight.test(searchText)) { this.navigate('/block/', searchText); From 7bb34fe090a395779c8d62f305e9d1bd62b3758e Mon Sep 17 00:00:00 2001 From: nymkappa <1612910616@pm.me> Date: Thu, 11 May 2023 14:30:57 +0200 Subject: [PATCH 008/242] [mempool graph] show horizontal guide line --- .../mempool-graph/mempool-graph.component.ts | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/frontend/src/app/components/mempool-graph/mempool-graph.component.ts b/frontend/src/app/components/mempool-graph/mempool-graph.component.ts index cc53f425d..416b8f538 100644 --- a/frontend/src/app/components/mempool-graph/mempool-graph.component.ts +++ b/frontend/src/app/components/mempool-graph/mempool-graph.component.ts @@ -181,7 +181,7 @@ export class MempoolGraphComponent implements OnInit, OnChanges { alwaysShowContent: false, position: (pos, params, el, elRect, size) => { const positions = { top: (this.template === 'advanced') ? 0 : -30 }; - positions[['left', 'right'][+(pos[0] < size.viewSize[0] / 2)]] = 60; + positions[['left', 'right'][+(pos[0] < size.viewSize[0] / 2)]] = 100; return positions; }, extraCssText: `width: ${(this.template === 'advanced') ? '275px' : '200px'}; @@ -189,10 +189,19 @@ export class MempoolGraphComponent implements OnInit, OnChanges { border: none; box-shadow: none;`, axisPointer: { - type: 'line', + type: 'cross', + label: { + formatter: (params: any) => { + if (params.axisDimension === 'y') { + return this.vbytesPipe.transform(params.value, 2, 'vB', 'MvB', true) + } else { + return formatterXAxis(this.locale, this.windowPreference, params.value); + } + } + } }, formatter: (params: any) => { - const axisValueLabel: string = formatterXAxis(this.locale, this.windowPreference, params[0].axisValue); + const axisValueLabel: string = formatterXAxis(this.locale, this.windowPreference, params[0].axisValue); const { totalValue, totalValueArray } = this.getTotalValues(params); const itemFormatted = []; let totalParcial = 0; From e5bef55d479b6fd46a8bdc4f8887cd7f6780aae1 Mon Sep 17 00:00:00 2001 From: Mononaut Date: Thu, 11 May 2023 08:57:12 -0600 Subject: [PATCH 009/242] Fix RBF timestamps to always use seconds --- backend/src/api/rbf-cache.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/backend/src/api/rbf-cache.ts b/backend/src/api/rbf-cache.ts index 6c5afc146..d8fb8656c 100644 --- a/backend/src/api/rbf-cache.ts +++ b/backend/src/api/rbf-cache.ts @@ -36,7 +36,7 @@ class RbfCache { } const newTx = Common.stripTransaction(newTxExtended) as RbfTransaction; - const newTime = newTxExtended.firstSeen || Date.now(); + const newTime = newTxExtended.firstSeen || (Date.now() / 1000); newTx.rbf = newTxExtended.vin.some((v) => v.sequence < 0xfffffffe); this.txs.set(newTx.txid, newTxExtended); @@ -59,7 +59,7 @@ class RbfCache { } } } else { - const replacedTime = replacedTxExtended.firstSeen || Date.now(); + const replacedTime = replacedTxExtended.firstSeen || (Date.now() / 1000); replacedTrees.push({ tx: replacedTx, time: replacedTime, @@ -74,7 +74,7 @@ class RbfCache { const treeId = replacedTrees[0].tx.txid; const newTree = { tx: newTx, - time: newTxExtended.firstSeen || Date.now(), + time: newTime, fullRbf, replaces: replacedTrees }; From 107746feecb473c6d99a1f853f4dc3ada98a0f01 Mon Sep 17 00:00:00 2001 From: softsimon Date: Thu, 11 May 2023 11:38:57 -0500 Subject: [PATCH 010/242] Global footer fixes --- .../bisq-main-dashboard.component.html | 2 -- .../master-page/master-page.component.html | 4 ++-- .../master-page/master-page.component.ts | 11 +++++++++-- .../global-footer.component.html | 19 +++++++++---------- .../global-footer/global-footer.component.ts | 4 ---- 5 files changed, 20 insertions(+), 20 deletions(-) diff --git a/frontend/src/app/bisq/bisq-main-dashboard/bisq-main-dashboard.component.html b/frontend/src/app/bisq/bisq-main-dashboard/bisq-main-dashboard.component.html index eab0537c7..4b2dc59c6 100644 --- a/frontend/src/app/bisq/bisq-main-dashboard/bisq-main-dashboard.component.html +++ b/frontend/src/app/bisq/bisq-main-dashboard/bisq-main-dashboard.component.html @@ -105,8 +105,6 @@
- -
diff --git a/frontend/src/app/components/master-page/master-page.component.html b/frontend/src/app/components/master-page/master-page.component.html index 6da59197c..0258a8e07 100644 --- a/frontend/src/app/components/master-page/master-page.component.html +++ b/frontend/src/app/components/master-page/master-page.component.html @@ -17,7 +17,7 @@ -