diff --git a/backend/src/api/bitcoin/esplora-api.ts b/backend/src/api/bitcoin/esplora-api.ts index dda584ec4..19800cd21 100644 --- a/backend/src/api/bitcoin/esplora-api.ts +++ b/backend/src/api/bitcoin/esplora-api.ts @@ -184,7 +184,8 @@ class FailoverRouter { .catch((e) => { let fallbackHost = this.fallbackHost; if (e?.response?.status !== 404) { - logger.warn(`esplora request failed ${e?.response?.status || 500} ${host.host}${path}`); + logger.warn(`esplora request failed ${e?.response?.status} ${host.host}${path}`); + logger.warn(e instanceof Error ? e.message : e); fallbackHost = this.addFailure(host); } if (retry && e?.code === 'ECONNREFUSED' && this.multihost) { diff --git a/backend/src/api/rbf-cache.ts b/backend/src/api/rbf-cache.ts index 950e3a4e5..c573d3291 100644 --- a/backend/src/api/rbf-cache.ts +++ b/backend/src/api/rbf-cache.ts @@ -480,14 +480,16 @@ class RbfCache { }; if (config.MEMPOOL.BACKEND === 'esplora') { - const sliceLength = 10000; + const sliceLength = 250; for (let i = 0; i < Math.ceil(txids.length / sliceLength); i++) { const slice = txids.slice(i * sliceLength, (i + 1) * sliceLength); try { const txs = await bitcoinApi.$getRawTransactions(slice); + logger.debug(`fetched ${slice.length} cached rbf transactions`); processTxs(txs); + logger.debug(`processed ${slice.length} cached rbf transactions`); } catch (err) { - logger.err('failed to fetch some cached rbf transactions'); + logger.err(`failed to fetch or process ${slice.length} cached rbf transactions`); } } } else { diff --git a/frontend/src/app/components/incoming-transactions-graph/incoming-transactions-graph.component.ts b/frontend/src/app/components/incoming-transactions-graph/incoming-transactions-graph.component.ts index 1b68a5a99..667ad1e28 100644 --- a/frontend/src/app/components/incoming-transactions-graph/incoming-transactions-graph.component.ts +++ b/frontend/src/app/components/incoming-transactions-graph/incoming-transactions-graph.component.ts @@ -63,7 +63,8 @@ export class IncomingTransactionsGraphComponent implements OnInit, OnChanges, On return; } this.windowPreference = this.windowPreferenceOverride ? this.windowPreferenceOverride : this.storageService.getValue('graphWindowPreference'); - this.MA = this.calculateMA(this.data.series[0]); + const windowSize = Math.max(10, Math.floor(this.data.series[0].length / 8)); + this.MA = this.calculateMA(this.data.series[0], windowSize); this.mountChart(); } @@ -74,33 +75,22 @@ export class IncomingTransactionsGraphComponent implements OnInit, OnChanges, On this.isLoading = false; } - /// calculate the moving average of maData - calculateMA(maData): number[][] { + /// calculate the moving average of the provided data based on windowSize + calculateMA(data: number[][], windowSize: number = 100): number[][] { //update const variables that are not changed const ma: number[][] = []; let sum = 0; let i = 0; - const len = maData.length; - - //Adjust window length based on the length of the data - //5% appeared as a good amount from tests - //TODO: make this a text box in the UI - const maWindowLen = Math.ceil(len * 0.05); - - //calculate the center of the moving average window - const center = Math.floor(maWindowLen / 2); //calculate the centered moving average - for (i = center; i < len - center; i++) { - sum = 0; - //build out ma as we loop through the data - ma[i] = []; - ma[i].push(maData[i][0]); - for (let j = i - center; j <= i + center; j++) { - sum += maData[j][1]; + for (i = 0; i < data.length; i++) { + sum += data[i][1]; + if (i >= windowSize) { + sum -= data[i - windowSize][1]; + const midpoint = i - Math.floor(windowSize / 2); + const avg = sum / windowSize; + ma.push([data[midpoint][0], avg]); } - - ma[i].push(sum / maWindowLen); } //return the moving average array @@ -138,36 +128,22 @@ export class IncomingTransactionsGraphComponent implements OnInit, OnChanges, On } }], } - }, - { - zlevel: 0, - name: 'MA', - data: this.MA, - type: 'line', - smooth: false, - showSymbol: false, - symbol: 'none', - lineStyle: { - width: 1, - color: "white", - }, - markLine: { - silent: true, + }); + if (this.template !== 'widget') { + seriesGraph.push({ + zlevel: 0, + name: 'MA', + data: this.MA, + type: 'line', + smooth: false, + showSymbol: false, symbol: 'none', lineStyle: { - color: '#fff', - opacity: 1, width: 2, - }, - data: [{ - yAxis: 1667, - label: { - show: false, - color: '#ffffff', - } - }], - } - }); + color: "white", + } + }); + } this.mempoolStatsChartOption = { grid: { diff --git a/frontend/src/app/graphs/echarts.ts b/frontend/src/app/graphs/echarts.ts index 588e5e5f1..342867168 100644 --- a/frontend/src/app/graphs/echarts.ts +++ b/frontend/src/app/graphs/echarts.ts @@ -1,7 +1,7 @@ // Import tree-shakeable echarts import * as echarts from 'echarts/core'; import { LineChart, LinesChart, BarChart, TreemapChart, PieChart, ScatterChart } from 'echarts/charts'; -import { TitleComponent, TooltipComponent, GridComponent, LegendComponent, GeoComponent, DataZoomComponent, VisualMapComponent } from 'echarts/components'; +import { TitleComponent, TooltipComponent, GridComponent, LegendComponent, GeoComponent, DataZoomComponent, VisualMapComponent, MarkLineComponent } from 'echarts/components'; import { SVGRenderer, CanvasRenderer } from 'echarts/renderers'; // Typescript interfaces import { EChartsOption, TreemapSeriesOption, LineSeriesOption, PieSeriesOption } from 'echarts'; @@ -11,7 +11,7 @@ echarts.use([ SVGRenderer, CanvasRenderer, TitleComponent, TooltipComponent, GridComponent, LegendComponent, GeoComponent, DataZoomComponent, - VisualMapComponent, + VisualMapComponent, MarkLineComponent, LineChart, LinesChart, BarChart, TreemapChart, PieChart, ScatterChart ]); export { echarts, EChartsOption, TreemapSeriesOption, LineSeriesOption, PieSeriesOption }; \ No newline at end of file