From aa8a3e60c2e8a8b5ee4e4763eff1177738e2ffdd Mon Sep 17 00:00:00 2001 From: Mononaut Date: Tue, 3 Jan 2023 11:54:42 -0600 Subject: [PATCH 01/17] expose other currencies in charts APIs --- backend/src/repositories/BlocksRepository.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/src/repositories/BlocksRepository.ts b/backend/src/repositories/BlocksRepository.ts index df98719b9..355187e21 100644 --- a/backend/src/repositories/BlocksRepository.ts +++ b/backend/src/repositories/BlocksRepository.ts @@ -521,7 +521,7 @@ class BlocksRepository { CAST(AVG(blocks.height) as INT) as avgHeight, CAST(AVG(UNIX_TIMESTAMP(blockTimestamp)) as INT) as timestamp, CAST(AVG(fees) as INT) as avgFees, - prices.USD + prices.* FROM blocks JOIN blocks_prices on blocks_prices.height = blocks.height JOIN prices on prices.id = blocks_prices.price_id @@ -550,7 +550,7 @@ class BlocksRepository { CAST(AVG(blocks.height) as INT) as avgHeight, CAST(AVG(UNIX_TIMESTAMP(blockTimestamp)) as INT) as timestamp, CAST(AVG(reward) as INT) as avgRewards, - prices.USD + prices.* FROM blocks JOIN blocks_prices on blocks_prices.height = blocks.height JOIN prices on prices.id = blocks_prices.price_id From 02655d757e014aa77e2bc2d9d302ac5f8dc77582 Mon Sep 17 00:00:00 2001 From: Mononaut Date: Tue, 3 Jan 2023 11:56:54 -0600 Subject: [PATCH 02/17] Add currency preference to dashboard --- frontend/src/app/app.constants.ts | 94 +++++++++++++++++++ .../fiat-selector.component.html | 5 + .../fiat-selector.component.scss | 0 .../fiat-selector/fiat-selector.component.ts | 38 ++++++++ .../language-selector.component.html | 2 +- .../app/dashboard/dashboard.component.html | 9 +- .../app/dashboard/dashboard.component.scss | 15 +++ frontend/src/app/services/state.service.ts | 4 + frontend/src/app/shared/shared.module.ts | 3 + 9 files changed, 168 insertions(+), 2 deletions(-) create mode 100644 frontend/src/app/components/fiat-selector/fiat-selector.component.html create mode 100644 frontend/src/app/components/fiat-selector/fiat-selector.component.scss create mode 100644 frontend/src/app/components/fiat-selector/fiat-selector.component.ts diff --git a/frontend/src/app/app.constants.ts b/frontend/src/app/app.constants.ts index 47e12cfcd..0456f2647 100644 --- a/frontend/src/app/app.constants.ts +++ b/frontend/src/app/app.constants.ts @@ -157,3 +157,97 @@ export const specialBlocks = { labelEventCompleted: 'Block Subsidy has halved to 3.125 BTC per block', } }; + +export const fiatCurrencies = { + AED: { + name: 'UAE Dirham', + code: 'AED' + }, + AUD: { + name: 'Australian Dollar', + code: 'AUD', + indexed: true, + }, + BRL: { + name: 'Brazilian Real', + code: 'BRL' + }, + CAD: { + name: 'Canadian Dollar', + code: 'CAD', + indexed: true, + }, + CHF: { + name: 'Swiss Franc', + code: 'CHF', + indexed: true, + }, + EUR: { + name: 'Euro', + code: 'EUR', + indexed: true, + }, + GBP: { + name: 'Pound Sterling', + code: 'GBP', + indexed: true, + }, + HKD: { + name: 'Hong Kong Dollar', + code: 'HKD' + }, + IDR: { + name: 'Indonesian Rupiah', + code: 'IDR' + }, + JPY: { + name: 'Japanese Yen', + code: 'JPY', + indexed: true, + }, + KRW: { + name: 'Korean Won', + code: 'KRW' + }, + MYR: { + name: 'Malaysian Ringgit', + code: 'MYR' + }, + NGN: { + name: 'Nigerian Naira', + code: 'NGN' + }, + NZD: { + name: 'New Zealand Dollar', + code: 'NZD' + }, + PLN: { + name: 'Polish Złoty', + code: 'PLN' + }, + RUB: { + name: 'Russian Ruble', + code: 'RUB' + }, + SGD: { + name: 'Singapore Dollar', + code: 'SGD' + }, + TRY: { + name: 'Turkish Lira', + code: 'TRY' + }, + UAH: { + name: 'Ukrainian Hryvnia', + code: 'UAH' + }, + USD: { + name: 'US Dollar', + code: 'USD', + indexed: true, + }, + ZAR: { + name: 'South African Rand', + code: 'ZAR' + }, +}; \ No newline at end of file diff --git a/frontend/src/app/components/fiat-selector/fiat-selector.component.html b/frontend/src/app/components/fiat-selector/fiat-selector.component.html new file mode 100644 index 000000000..7fa8c0d00 --- /dev/null +++ b/frontend/src/app/components/fiat-selector/fiat-selector.component.html @@ -0,0 +1,5 @@ +
+ +
diff --git a/frontend/src/app/components/fiat-selector/fiat-selector.component.scss b/frontend/src/app/components/fiat-selector/fiat-selector.component.scss new file mode 100644 index 000000000..e69de29bb diff --git a/frontend/src/app/components/fiat-selector/fiat-selector.component.ts b/frontend/src/app/components/fiat-selector/fiat-selector.component.ts new file mode 100644 index 000000000..f967b7d77 --- /dev/null +++ b/frontend/src/app/components/fiat-selector/fiat-selector.component.ts @@ -0,0 +1,38 @@ +import { ChangeDetectionStrategy, Component, OnInit } from '@angular/core'; +import { UntypedFormBuilder, UntypedFormGroup } from '@angular/forms'; +import { StorageService } from '../../services/storage.service'; +import { fiatCurrencies } from '../../app.constants'; +import { StateService } from '../../services/state.service'; + +@Component({ + selector: 'app-fiat-selector', + templateUrl: './fiat-selector.component.html', + styleUrls: ['./fiat-selector.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class FiatSelectorComponent implements OnInit { + fiatForm: UntypedFormGroup; + currencies = fiatCurrencies; + currencyList = Object.keys(fiatCurrencies).sort(); + + constructor( + private formBuilder: UntypedFormBuilder, + private stateService: StateService, + private storageService: StorageService, + ) { } + + ngOnInit() { + this.fiatForm = this.formBuilder.group({ + fiat: ['USD'] + }); + this.stateService.fiatCurrency$.subscribe((fiat) => { + this.fiatForm.get('fiat')?.setValue(fiat); + }); + } + + changeFiat() { + const newFiat = this.fiatForm.get('fiat')?.value; + this.storageService.setValue('fiat-preference', newFiat); + this.stateService.fiatCurrency$.next(newFiat); + } +} diff --git a/frontend/src/app/components/language-selector/language-selector.component.html b/frontend/src/app/components/language-selector/language-selector.component.html index dee1e3acb..b23b2b7b7 100644 --- a/frontend/src/app/components/language-selector/language-selector.component.html +++ b/frontend/src/app/components/language-selector/language-selector.component.html @@ -1,5 +1,5 @@
-
diff --git a/frontend/src/app/dashboard/dashboard.component.html b/frontend/src/app/dashboard/dashboard.component.html index 397021048..1df7baabc 100644 --- a/frontend/src/app/dashboard/dashboard.component.html +++ b/frontend/src/app/dashboard/dashboard.component.html @@ -144,7 +144,14 @@ - +
+
+ +
+
+ +
+
Terms of Service diff --git a/frontend/src/app/dashboard/dashboard.component.scss b/frontend/src/app/dashboard/dashboard.component.scss index a7e21ba94..4a844eb52 100644 --- a/frontend/src/app/dashboard/dashboard.component.scss +++ b/frontend/src/app/dashboard/dashboard.component.scss @@ -323,4 +323,19 @@ margin-bottom: 10px; text-decoration: none; color: inherit; +} + +.pref-selectors { + display: flex; + flex-direction: row; + flex-wrap: wrap; + justify-content: center; + + .selector { + margin-left: .5em; + margin-bottom: .5em; + &:first { + margin-left: 0; + } + } } \ No newline at end of file diff --git a/frontend/src/app/services/state.service.ts b/frontend/src/app/services/state.service.ts index 091490715..02b160fe9 100644 --- a/frontend/src/app/services/state.service.ts +++ b/frontend/src/app/services/state.service.ts @@ -119,6 +119,7 @@ export class StateService { timeLtr: BehaviorSubject; hideFlow: BehaviorSubject; hideAudit: BehaviorSubject; + fiatCurrency$: BehaviorSubject; constructor( @Inject(PLATFORM_ID) private platformId: any, @@ -184,6 +185,9 @@ export class StateService { this.hideAudit.subscribe((hide) => { this.storageService.setValue('audit-preference', hide ? 'hide' : 'show'); }); + + const fiatPreference = this.storageService.getValue('fiat-preference'); + this.fiatCurrency$ = new BehaviorSubject(fiatPreference || 'USD'); } setNetworkBasedonUrl(url: string) { diff --git a/frontend/src/app/shared/shared.module.ts b/frontend/src/app/shared/shared.module.ts index d82f03493..e87107fe5 100644 --- a/frontend/src/app/shared/shared.module.ts +++ b/frontend/src/app/shared/shared.module.ts @@ -34,6 +34,7 @@ import { TxFeaturesComponent } from '../components/tx-features/tx-features.compo import { TxFeeRatingComponent } from '../components/tx-fee-rating/tx-fee-rating.component'; import { ReactiveFormsModule } from '@angular/forms'; import { LanguageSelectorComponent } from '../components/language-selector/language-selector.component'; +import { FiatSelectorComponent } from '../components/fiat-selector/fiat-selector.component'; import { ColoredPriceDirective } from './directives/colored-price.directive'; import { NoSanitizePipe } from './pipes/no-sanitize.pipe'; import { MempoolBlocksComponent } from '../components/mempool-blocks/mempool-blocks.component'; @@ -93,6 +94,7 @@ import { GeolocationComponent } from '../shared/components/geolocation/geolocati TxFeaturesComponent, TxFeeRatingComponent, LanguageSelectorComponent, + FiatSelectorComponent, ScriptpubkeyTypePipe, RelativeUrlPipe, NoSanitizePipe, @@ -199,6 +201,7 @@ import { GeolocationComponent } from '../shared/components/geolocation/geolocati TxFeaturesComponent, TxFeeRatingComponent, LanguageSelectorComponent, + FiatSelectorComponent, ScriptpubkeyTypePipe, RelativeUrlPipe, Hex2asciiPipe, From c2ff6a996ab447dae6a971205ecaa4e091724964 Mon Sep 17 00:00:00 2001 From: Mononaut Date: Tue, 3 Jan 2023 11:58:09 -0600 Subject: [PATCH 03/17] Multi-currency fiat formatting pipes & components --- frontend/src/app/app.module.ts | 2 ++ frontend/src/app/fiat/fiat.component.html | 2 +- frontend/src/app/fiat/fiat.component.ts | 20 ++++++++++--- .../app/shared/pipes/fiat-currency.pipe.ts | 28 +++++++++++++++++++ .../app/shared/pipes/fiat-shortener.pipe.ts | 22 +++++++++++---- frontend/src/app/shared/shared.module.ts | 3 ++ 6 files changed, 66 insertions(+), 11 deletions(-) create mode 100644 frontend/src/app/shared/pipes/fiat-currency.pipe.ts diff --git a/frontend/src/app/app.module.ts b/frontend/src/app/app.module.ts index b7bd1526f..f26b4a924 100644 --- a/frontend/src/app/app.module.ts +++ b/frontend/src/app/app.module.ts @@ -17,6 +17,7 @@ import { StorageService } from './services/storage.service'; import { HttpCacheInterceptor } from './services/http-cache.interceptor'; import { LanguageService } from './services/language.service'; import { FiatShortenerPipe } from './shared/pipes/fiat-shortener.pipe'; +import { FiatCurrencyPipe } from './shared/pipes/fiat-currency.pipe'; import { ShortenStringPipe } from './shared/pipes/shorten-string-pipe/shorten-string.pipe'; import { CapAddressPipe } from './shared/pipes/cap-address-pipe/cap-address-pipe'; import { AppPreloadingStrategy } from './app.preloading-strategy'; @@ -34,6 +35,7 @@ const providers = [ LanguageService, ShortenStringPipe, FiatShortenerPipe, + FiatCurrencyPipe, CapAddressPipe, AppPreloadingStrategy, { provide: HTTP_INTERCEPTORS, useClass: HttpCacheInterceptor, multi: true } diff --git a/frontend/src/app/fiat/fiat.component.html b/frontend/src/app/fiat/fiat.component.html index 19a5c8aa0..1adde8120 100644 --- a/frontend/src/app/fiat/fiat.component.html +++ b/frontend/src/app/fiat/fiat.component.html @@ -1 +1 @@ -{{ (conversions$ | async)?.USD * value / 100000000 | currency:'USD':'symbol':digitsInfo }} \ No newline at end of file +{{ (conversions$ | async)[currency] * value / 100000000 | fiatCurrency : digitsInfo : currency }} \ No newline at end of file diff --git a/frontend/src/app/fiat/fiat.component.ts b/frontend/src/app/fiat/fiat.component.ts index 9d22355d8..bc0f6a0de 100644 --- a/frontend/src/app/fiat/fiat.component.ts +++ b/frontend/src/app/fiat/fiat.component.ts @@ -1,5 +1,5 @@ -import { Component, OnInit, ChangeDetectionStrategy, Input } from '@angular/core'; -import { Observable } from 'rxjs'; +import { Component, OnInit, ChangeDetectionStrategy, Input, ChangeDetectorRef, OnDestroy } from '@angular/core'; +import { Observable, Subscription } from 'rxjs'; import { StateService } from '../services/state.service'; @Component({ @@ -8,18 +8,30 @@ import { StateService } from '../services/state.service'; styleUrls: ['./fiat.component.scss'], changeDetection: ChangeDetectionStrategy.OnPush, }) -export class FiatComponent implements OnInit { +export class FiatComponent implements OnInit, OnDestroy { conversions$: Observable; + currencySubscription: Subscription; + currency: string; @Input() value: number; @Input() digitsInfo = '1.2-2'; constructor( private stateService: StateService, - ) { } + private cd: ChangeDetectorRef, + ) { + this.currencySubscription = this.stateService.fiatCurrency$.subscribe((fiat) => { + this.currency = fiat; + this.cd.markForCheck(); + }); + } ngOnInit(): void { this.conversions$ = this.stateService.conversions$.asObservable(); } + ngOnDestroy(): void { + this.currencySubscription.unsubscribe(); + } + } diff --git a/frontend/src/app/shared/pipes/fiat-currency.pipe.ts b/frontend/src/app/shared/pipes/fiat-currency.pipe.ts new file mode 100644 index 000000000..3cd825291 --- /dev/null +++ b/frontend/src/app/shared/pipes/fiat-currency.pipe.ts @@ -0,0 +1,28 @@ +import { formatCurrency, getCurrencySymbol } from '@angular/common'; +import { Inject, LOCALE_ID, Pipe, PipeTransform } from '@angular/core'; +import { Subscription } from 'rxjs'; +import { StateService } from '../../services/state.service'; + +@Pipe({ + name: 'fiatCurrency' +}) +export class FiatCurrencyPipe implements PipeTransform { + fiatSubscription: Subscription; + currency: string; + + constructor( + @Inject(LOCALE_ID) public locale: string, + private stateService: StateService, + ) { + this.fiatSubscription = this.stateService.fiatCurrency$.subscribe((fiat) => { + this.currency = fiat; + }); + } + + transform(num: number, ...args: any[]): unknown { + const digits = args[0] || 1; + const currency = args[1] || this.currency || 'USD'; + + return new Intl.NumberFormat(this.locale, { style: 'currency', currency }).format(num); + } +} \ No newline at end of file diff --git a/frontend/src/app/shared/pipes/fiat-shortener.pipe.ts b/frontend/src/app/shared/pipes/fiat-shortener.pipe.ts index 8c534f93f..93ab5cf8f 100644 --- a/frontend/src/app/shared/pipes/fiat-shortener.pipe.ts +++ b/frontend/src/app/shared/pipes/fiat-shortener.pipe.ts @@ -1,20 +1,30 @@ import { formatCurrency, getCurrencySymbol } from '@angular/common'; import { Inject, LOCALE_ID, Pipe, PipeTransform } from '@angular/core'; +import { Subscription } from 'rxjs'; +import { StateService } from '../../services/state.service'; @Pipe({ name: 'fiatShortener' }) export class FiatShortenerPipe implements PipeTransform { + fiatSubscription: Subscription; + currency: string; + constructor( - @Inject(LOCALE_ID) public locale: string - ) {} + @Inject(LOCALE_ID) public locale: string, + private stateService: StateService, + ) { + this.fiatSubscription = this.stateService.fiatCurrency$.subscribe((fiat) => { + this.currency = fiat; + }); + } transform(num: number, ...args: any[]): unknown { const digits = args[0] || 1; - const unit = args[1] || undefined; + const currency = args[1] || this.currency || 'USD'; if (num < 1000) { - return num.toFixed(digits); + return new Intl.NumberFormat(this.locale, { style: 'currency', currency, maximumFractionDigits: 1 }).format(num); } const lookup = [ @@ -30,8 +40,8 @@ export class FiatShortenerPipe implements PipeTransform { const item = lookup.slice().reverse().find((item) => num >= item.value); let result = item ? (num / item.value).toFixed(digits).replace(rx, '$1') : '0'; - result = formatCurrency(parseInt(result, 10), this.locale, getCurrencySymbol('USD', 'narrow'), 'USD', '1.0-0'); - + result = new Intl.NumberFormat(this.locale, { style: 'currency', currency, maximumFractionDigits: 0 }).format(item ? num / item.value : 0); + return result + item.symbol; } } \ No newline at end of file diff --git a/frontend/src/app/shared/shared.module.ts b/frontend/src/app/shared/shared.module.ts index e87107fe5..fd257db85 100644 --- a/frontend/src/app/shared/shared.module.ts +++ b/frontend/src/app/shared/shared.module.ts @@ -23,6 +23,7 @@ import { RelativeUrlPipe } from './pipes/relative-url/relative-url.pipe'; import { ScriptpubkeyTypePipe } from './pipes/scriptpubkey-type-pipe/scriptpubkey-type.pipe'; import { BytesPipe } from './pipes/bytes-pipe/bytes.pipe'; import { WuBytesPipe } from './pipes/bytes-pipe/wubytes.pipe'; +import { FiatCurrencyPipe } from './pipes/fiat-currency.pipe'; import { BlockchainComponent } from '../components/blockchain/blockchain.component'; import { TimeSinceComponent } from '../components/time-since/time-since.component'; import { TimeUntilComponent } from '../components/time-until/time-until.component'; @@ -109,6 +110,7 @@ import { GeolocationComponent } from '../shared/components/geolocation/geolocati CapAddressPipe, Decimal2HexPipe, FeeRoundingPipe, + FiatCurrencyPipe, ColoredPriceDirective, BlockchainComponent, MempoolBlocksComponent, @@ -210,6 +212,7 @@ import { GeolocationComponent } from '../shared/components/geolocation/geolocati BytesPipe, VbytesPipe, WuBytesPipe, + FiatCurrencyPipe, CeilPipe, ShortenStringPipe, CapAddressPipe, From d06dcdccb496ba12f58792a9adc48492881c9150 Mon Sep 17 00:00:00 2001 From: Mononaut Date: Tue, 3 Jan 2023 11:58:51 -0600 Subject: [PATCH 04/17] Display fiat mining graphs in selected currency --- .../block-fees-graph.component.ts | 30 +++++++++++++----- .../block-rewards-graph.component.ts | 31 ++++++++++++++----- 2 files changed, 46 insertions(+), 15 deletions(-) diff --git a/frontend/src/app/components/block-fees-graph/block-fees-graph.component.ts b/frontend/src/app/components/block-fees-graph/block-fees-graph.component.ts index 0c2f228b8..42667126f 100644 --- a/frontend/src/app/components/block-fees-graph/block-fees-graph.component.ts +++ b/frontend/src/app/components/block-fees-graph/block-fees-graph.component.ts @@ -1,16 +1,19 @@ import { ChangeDetectionStrategy, Component, Inject, Input, LOCALE_ID, OnInit } from '@angular/core'; import { EChartsOption, graphic } from 'echarts'; -import { Observable } from 'rxjs'; +import { Observable, Subscription } from 'rxjs'; import { map, share, startWith, switchMap, tap } from 'rxjs/operators'; import { ApiService } from '../../services/api.service'; import { SeoService } from '../../services/seo.service'; import { formatCurrency, formatNumber, getCurrencySymbol } from '@angular/common'; import { UntypedFormBuilder, UntypedFormGroup } from '@angular/forms'; import { download, formatterXAxis, formatterXAxisLabel, formatterXAxisTimeCategory } from '../../shared/graphs.utils'; +import { StateService } from '../../services/state.service'; import { StorageService } from '../../services/storage.service'; import { MiningService } from '../../services/mining.service'; import { ActivatedRoute } from '@angular/router'; import { FiatShortenerPipe } from '../../shared/pipes/fiat-shortener.pipe'; +import { FiatCurrencyPipe } from '../../shared/pipes/fiat-currency.pipe'; +import { fiatCurrencies } from '../../app.constants'; @Component({ selector: 'app-block-fees-graph', @@ -44,6 +47,9 @@ export class BlockFeesGraphComponent implements OnInit { timespan = ''; chartInstance: any = undefined; + currencySubscription: Subscription; + currency: string; + constructor( @Inject(LOCALE_ID) public locale: string, private seoService: SeoService, @@ -51,11 +57,21 @@ export class BlockFeesGraphComponent implements OnInit { private formBuilder: UntypedFormBuilder, private storageService: StorageService, private miningService: MiningService, + private stateService: StateService, private route: ActivatedRoute, private fiatShortenerPipe: FiatShortenerPipe, + private fiatCurrencyPipe: FiatCurrencyPipe, ) { this.radioGroupForm = this.formBuilder.group({ dateSpan: '1y' }); this.radioGroupForm.controls.dateSpan.setValue('1y'); + + this.currencySubscription = this.stateService.fiatCurrency$.subscribe((fiat) => { + if (fiat && fiatCurrencies[fiat]?.indexed) { + this.currency = fiat; + } else { + this.currency = 'USD'; + } + }); } ngOnInit(): void { @@ -84,7 +100,7 @@ export class BlockFeesGraphComponent implements OnInit { tap((response) => { this.prepareChartOptions({ blockFees: response.body.map(val => [val.timestamp * 1000, val.avgFees / 100000000, val.avgHeight]), - blockFeesUSD: response.body.filter(val => val.USD > 0).map(val => [val.timestamp * 1000, val.avgFees / 100000000 * val.USD, val.avgHeight]), + blockFeesFiat: response.body.filter(val => val[this.currency] > 0).map(val => [val.timestamp * 1000, val.avgFees / 100000000 * val[this.currency], val.avgHeight]), }); this.isLoading = false; }), @@ -157,7 +173,7 @@ export class BlockFeesGraphComponent implements OnInit { if (tick.seriesIndex === 0) { tooltip += `${tick.marker} ${tick.seriesName}: ${formatNumber(tick.data[1], this.locale, '1.3-3')} BTC
`; } else if (tick.seriesIndex === 1) { - tooltip += `${tick.marker} ${tick.seriesName}: ${formatCurrency(tick.data[1], this.locale, getCurrencySymbol('USD', 'narrow'), 'USD', '1.0-0')}
`; + tooltip += `${tick.marker} ${tick.seriesName}: ${this.fiatCurrencyPipe.transform(tick.data[1], null, this.currency) }
`; } } @@ -184,7 +200,7 @@ export class BlockFeesGraphComponent implements OnInit { icon: 'roundRect', }, { - name: 'Fees USD', + name: 'Fees ' + this.currency, inactiveColor: 'rgb(110, 112, 121)', textStyle: { color: 'white', @@ -216,7 +232,7 @@ export class BlockFeesGraphComponent implements OnInit { axisLabel: { color: 'rgb(110, 112, 121)', formatter: function(val) { - return this.fiatShortenerPipe.transform(val); + return this.fiatShortenerPipe.transform(val, null, this.currency); }.bind(this) }, splitLine: { @@ -243,8 +259,8 @@ export class BlockFeesGraphComponent implements OnInit { legendHoverLink: false, zlevel: 1, yAxisIndex: 1, - name: 'Fees USD', - data: data.blockFeesUSD, + name: 'Fees ' + this.currency, + data: data.blockFeesFiat, type: 'line', smooth: 0.25, symbol: 'none', diff --git a/frontend/src/app/components/block-rewards-graph/block-rewards-graph.component.ts b/frontend/src/app/components/block-rewards-graph/block-rewards-graph.component.ts index fe80b0c97..0e5e339fa 100644 --- a/frontend/src/app/components/block-rewards-graph/block-rewards-graph.component.ts +++ b/frontend/src/app/components/block-rewards-graph/block-rewards-graph.component.ts @@ -1,16 +1,19 @@ import { ChangeDetectionStrategy, Component, Inject, Input, LOCALE_ID, OnInit } from '@angular/core'; import { EChartsOption, graphic } from 'echarts'; -import { Observable } from 'rxjs'; +import { Observable, Subscription } from 'rxjs'; import { map, share, startWith, switchMap, tap } from 'rxjs/operators'; import { ApiService } from '../../services/api.service'; import { SeoService } from '../../services/seo.service'; -import { formatCurrency, formatNumber, getCurrencySymbol } from '@angular/common'; +import { formatNumber } from '@angular/common'; import { UntypedFormBuilder, UntypedFormGroup } from '@angular/forms'; import { download, formatterXAxis, formatterXAxisLabel, formatterXAxisTimeCategory } from '../../shared/graphs.utils'; import { MiningService } from '../../services/mining.service'; +import { StateService } from '../../services/state.service'; import { StorageService } from '../../services/storage.service'; import { ActivatedRoute } from '@angular/router'; import { FiatShortenerPipe } from '../../shared/pipes/fiat-shortener.pipe'; +import { FiatCurrencyPipe } from '../../shared/pipes/fiat-currency.pipe'; +import { fiatCurrencies } from '../../app.constants'; @Component({ selector: 'app-block-rewards-graph', @@ -44,16 +47,28 @@ export class BlockRewardsGraphComponent implements OnInit { timespan = ''; chartInstance: any = undefined; + currencySubscription: Subscription; + currency: string; + constructor( @Inject(LOCALE_ID) public locale: string, private seoService: SeoService, private apiService: ApiService, private formBuilder: UntypedFormBuilder, private miningService: MiningService, + private stateService: StateService, private storageService: StorageService, private route: ActivatedRoute, private fiatShortenerPipe: FiatShortenerPipe, + private fiatCurrencyPipe: FiatCurrencyPipe, ) { + this.currencySubscription = this.stateService.fiatCurrency$.subscribe((fiat) => { + if (fiat && fiatCurrencies[fiat]?.indexed) { + this.currency = fiat; + } else { + this.currency = 'USD'; + } + }); } ngOnInit(): void { @@ -82,7 +97,7 @@ export class BlockRewardsGraphComponent implements OnInit { tap((response) => { this.prepareChartOptions({ blockRewards: response.body.map(val => [val.timestamp * 1000, val.avgRewards / 100000000, val.avgHeight]), - blockRewardsUSD: response.body.filter(val => val.USD > 0).map(val => [val.timestamp * 1000, val.avgRewards / 100000000 * val.USD, val.avgHeight]), + blockRewardsFiat: response.body.filter(val => val[this.currency] > 0).map(val => [val.timestamp * 1000, val.avgRewards / 100000000 * val[this.currency], val.avgHeight]), }); this.isLoading = false; }), @@ -157,7 +172,7 @@ export class BlockRewardsGraphComponent implements OnInit { if (tick.seriesIndex === 0) { tooltip += `${tick.marker} ${tick.seriesName}: ${formatNumber(tick.data[1], this.locale, '1.3-3')} BTC
`; } else if (tick.seriesIndex === 1) { - tooltip += `${tick.marker} ${tick.seriesName}: ${formatCurrency(tick.data[1], this.locale, getCurrencySymbol('USD', 'narrow'), 'USD', '1.0-0')}
`; + tooltip += `${tick.marker} ${tick.seriesName}: ${this.fiatCurrencyPipe.transform(tick.data[1], null, this.currency)}
`; } } @@ -184,7 +199,7 @@ export class BlockRewardsGraphComponent implements OnInit { icon: 'roundRect', }, { - name: 'Rewards USD', + name: 'Rewards ' + this.currency, inactiveColor: 'rgb(110, 112, 121)', textStyle: { color: 'white', @@ -228,7 +243,7 @@ export class BlockRewardsGraphComponent implements OnInit { axisLabel: { color: 'rgb(110, 112, 121)', formatter: function(val) { - return this.fiatShortenerPipe.transform(val); + return this.fiatShortenerPipe.transform(val, null, this.currency); }.bind(this) }, splitLine: { @@ -251,8 +266,8 @@ export class BlockRewardsGraphComponent implements OnInit { legendHoverLink: false, zlevel: 1, yAxisIndex: 1, - name: 'Rewards USD', - data: data.blockRewardsUSD, + name: 'Rewards ' + this.currency, + data: data.blockRewardsFiat, type: 'line', smooth: 0.25, symbol: 'none', From 368041e7d477dc66904314c2d9d66f0024d576a3 Mon Sep 17 00:00:00 2001 From: Mononaut Date: Mon, 16 Jan 2023 11:05:30 -0600 Subject: [PATCH 05/17] Use selected currency in app-amount component --- .../src/app/components/amount/amount.component.html | 2 +- .../src/app/components/amount/amount.component.ts | 13 +++++++++++-- frontend/src/app/fiat/fiat.component.html | 2 +- 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/frontend/src/app/components/amount/amount.component.html b/frontend/src/app/components/amount/amount.component.html index c4946ddf8..3526b554b 100644 --- a/frontend/src/app/components/amount/amount.component.html +++ b/frontend/src/app/components/amount/amount.component.html @@ -1,5 +1,5 @@ - {{ addPlus && satoshis >= 0 ? '+' : '' }}{{ conversions.USD * (satoshis / 100000000) | currency:'USD':'symbol':'1.2-2' }} + {{ addPlus && satoshis >= 0 ? '+' : '' }}{{ (conversions ? conversions[currency] : 0) * satoshis / 100000000 | fiatCurrency : digitsInfo : currency }} diff --git a/frontend/src/app/components/amount/amount.component.ts b/frontend/src/app/components/amount/amount.component.ts index f9bba4318..cfdc50468 100644 --- a/frontend/src/app/components/amount/amount.component.ts +++ b/frontend/src/app/components/amount/amount.component.ts @@ -1,4 +1,4 @@ -import { Component, OnInit, OnDestroy, Input, ChangeDetectionStrategy } from '@angular/core'; +import { Component, OnInit, OnDestroy, Input, ChangeDetectionStrategy, ChangeDetectorRef } from '@angular/core'; import { StateService } from '../../services/state.service'; import { Observable, Subscription } from 'rxjs'; @@ -10,10 +10,12 @@ import { Observable, Subscription } from 'rxjs'; }) export class AmountComponent implements OnInit, OnDestroy { conversions$: Observable; + currency: string; viewFiat$: Observable; network = ''; stateSubscription: Subscription; + currencySubscription: Subscription; @Input() satoshis: number; @Input() digitsInfo = '1.8-8'; @@ -22,7 +24,13 @@ export class AmountComponent implements OnInit, OnDestroy { constructor( private stateService: StateService, - ) { } + private cd: ChangeDetectorRef, + ) { + this.currencySubscription = this.stateService.fiatCurrency$.subscribe((fiat) => { + this.currency = fiat; + this.cd.markForCheck(); + }); + } ngOnInit() { this.viewFiat$ = this.stateService.viewFiat$.asObservable(); @@ -34,6 +42,7 @@ export class AmountComponent implements OnInit, OnDestroy { if (this.stateSubscription) { this.stateSubscription.unsubscribe(); } + this.currencySubscription.unsubscribe(); } } diff --git a/frontend/src/app/fiat/fiat.component.html b/frontend/src/app/fiat/fiat.component.html index 1adde8120..99a177cc0 100644 --- a/frontend/src/app/fiat/fiat.component.html +++ b/frontend/src/app/fiat/fiat.component.html @@ -1 +1 @@ -{{ (conversions$ | async)[currency] * value / 100000000 | fiatCurrency : digitsInfo : currency }} \ No newline at end of file +{{ (conversions ? conversions[currency] : 0) * value / 100000000 | fiatCurrency : digitsInfo : currency }} \ No newline at end of file From fddbf510841f74653e02d516eb43f10bc5626d3e Mon Sep 17 00:00:00 2001 From: nymkappa <1612910616@pm.me> Date: Wed, 15 Feb 2023 15:01:07 +0900 Subject: [PATCH 06/17] Only show supported currencies - Tweak UI --- frontend/src/app/app.constants.ts | 56 ------------------- .../fiat-selector.component.html | 4 +- .../fiat-selector/fiat-selector.component.ts | 11 +++- .../language-selector.component.html | 2 +- 4 files changed, 12 insertions(+), 61 deletions(-) diff --git a/frontend/src/app/app.constants.ts b/frontend/src/app/app.constants.ts index 0456f2647..5cc446dbf 100644 --- a/frontend/src/app/app.constants.ts +++ b/frontend/src/app/app.constants.ts @@ -159,19 +159,11 @@ export const specialBlocks = { }; export const fiatCurrencies = { - AED: { - name: 'UAE Dirham', - code: 'AED' - }, AUD: { name: 'Australian Dollar', code: 'AUD', indexed: true, }, - BRL: { - name: 'Brazilian Real', - code: 'BRL' - }, CAD: { name: 'Canadian Dollar', code: 'CAD', @@ -192,62 +184,14 @@ export const fiatCurrencies = { code: 'GBP', indexed: true, }, - HKD: { - name: 'Hong Kong Dollar', - code: 'HKD' - }, - IDR: { - name: 'Indonesian Rupiah', - code: 'IDR' - }, JPY: { name: 'Japanese Yen', code: 'JPY', indexed: true, }, - KRW: { - name: 'Korean Won', - code: 'KRW' - }, - MYR: { - name: 'Malaysian Ringgit', - code: 'MYR' - }, - NGN: { - name: 'Nigerian Naira', - code: 'NGN' - }, - NZD: { - name: 'New Zealand Dollar', - code: 'NZD' - }, - PLN: { - name: 'Polish Złoty', - code: 'PLN' - }, - RUB: { - name: 'Russian Ruble', - code: 'RUB' - }, - SGD: { - name: 'Singapore Dollar', - code: 'SGD' - }, - TRY: { - name: 'Turkish Lira', - code: 'TRY' - }, - UAH: { - name: 'Ukrainian Hryvnia', - code: 'UAH' - }, USD: { name: 'US Dollar', code: 'USD', indexed: true, }, - ZAR: { - name: 'South African Rand', - code: 'ZAR' - }, }; \ No newline at end of file diff --git a/frontend/src/app/components/fiat-selector/fiat-selector.component.html b/frontend/src/app/components/fiat-selector/fiat-selector.component.html index 7fa8c0d00..dd32b1815 100644 --- a/frontend/src/app/components/fiat-selector/fiat-selector.component.html +++ b/frontend/src/app/components/fiat-selector/fiat-selector.component.html @@ -1,5 +1,5 @@
- +
diff --git a/frontend/src/app/components/fiat-selector/fiat-selector.component.ts b/frontend/src/app/components/fiat-selector/fiat-selector.component.ts index f967b7d77..337ef11f3 100644 --- a/frontend/src/app/components/fiat-selector/fiat-selector.component.ts +++ b/frontend/src/app/components/fiat-selector/fiat-selector.component.ts @@ -12,8 +12,15 @@ import { StateService } from '../../services/state.service'; }) export class FiatSelectorComponent implements OnInit { fiatForm: UntypedFormGroup; - currencies = fiatCurrencies; - currencyList = Object.keys(fiatCurrencies).sort(); + currencies = Object.entries(fiatCurrencies).sort((a: any, b: any) => { + if (a[1].name < b[1].name) { + return -1; + } + if (a[1].name > b[1].name) { + return 1; + } + return 0; + }); constructor( private formBuilder: UntypedFormBuilder, diff --git a/frontend/src/app/components/language-selector/language-selector.component.html b/frontend/src/app/components/language-selector/language-selector.component.html index b23b2b7b7..22839441c 100644 --- a/frontend/src/app/components/language-selector/language-selector.component.html +++ b/frontend/src/app/components/language-selector/language-selector.component.html @@ -1,5 +1,5 @@
-
From 32aa7aaff11e4bfa25e2959738e0180f1cccd8f8 Mon Sep 17 00:00:00 2001 From: nymkappa <1612910616@pm.me> Date: Wed, 15 Feb 2023 16:05:14 +0900 Subject: [PATCH 07/17] Remove bisq price fetch and replace it with our in house price index --- backend/src/api/blocks.ts | 3 +- backend/src/api/fiat-conversion.ts | 123 ------------------- backend/src/api/websocket-handler.ts | 4 +- backend/src/index.ts | 8 +- backend/src/repositories/PricesRepository.ts | 32 +++-- backend/src/tasks/price-updater.ts | 59 +++++---- 6 files changed, 64 insertions(+), 165 deletions(-) delete mode 100644 backend/src/api/fiat-conversion.ts diff --git a/backend/src/api/blocks.ts b/backend/src/api/blocks.ts index 83de897ca..902f1f13b 100644 --- a/backend/src/api/blocks.ts +++ b/backend/src/api/blocks.ts @@ -17,7 +17,6 @@ import { prepareBlock } from '../utils/blocks-utils'; import BlocksRepository from '../repositories/BlocksRepository'; import HashratesRepository from '../repositories/HashratesRepository'; import indexer from '../indexer'; -import fiatConversion from './fiat-conversion'; import poolsParser from './pools-parser'; import BlocksSummariesRepository from '../repositories/BlocksSummariesRepository'; import BlocksAuditsRepository from '../repositories/BlocksAuditsRepository'; @@ -170,7 +169,7 @@ class Blocks { blockExtended.extras.reward = transactions[0].vout.reduce((acc, curr) => acc + curr.value, 0); blockExtended.extras.coinbaseTx = transactionUtils.stripCoinbaseTransaction(transactions[0]); blockExtended.extras.coinbaseRaw = blockExtended.extras.coinbaseTx.vin[0].scriptsig; - blockExtended.extras.usd = fiatConversion.getConversionRates().USD; + blockExtended.extras.usd = priceUpdater.latestPrices.USD; if (block.height === 0) { blockExtended.extras.medianFee = 0; // 50th percentiles diff --git a/backend/src/api/fiat-conversion.ts b/backend/src/api/fiat-conversion.ts deleted file mode 100644 index ffbe6a758..000000000 --- a/backend/src/api/fiat-conversion.ts +++ /dev/null @@ -1,123 +0,0 @@ -import logger from '../logger'; -import * as http from 'http'; -import * as https from 'https'; -import axios, { AxiosResponse } from 'axios'; -import { IConversionRates } from '../mempool.interfaces'; -import config from '../config'; -import backendInfo from './backend-info'; -import { SocksProxyAgent } from 'socks-proxy-agent'; - -class FiatConversion { - private debasingFiatCurrencies = ['AED', 'AUD', 'BDT', 'BHD', 'BMD', 'BRL', 'CAD', 'CHF', 'CLP', - 'CNY', 'CZK', 'DKK', 'EUR', 'GBP', 'HKD', 'HUF', 'IDR', 'ILS', 'INR', 'JPY', 'KRW', 'KWD', - 'LKR', 'MMK', 'MXN', 'MYR', 'NGN', 'NOK', 'NZD', 'PHP', 'PKR', 'PLN', 'RUB', 'SAR', 'SEK', - 'SGD', 'THB', 'TRY', 'TWD', 'UAH', 'USD', 'VND', 'ZAR']; - private conversionRates: IConversionRates = {}; - private ratesChangedCallback: ((rates: IConversionRates) => void) | undefined; - public ratesInitialized = false; // If true, it means rates are ready for use - - constructor() { - for (const fiat of this.debasingFiatCurrencies) { - this.conversionRates[fiat] = 0; - } - } - - public setProgressChangedCallback(fn: (rates: IConversionRates) => void) { - this.ratesChangedCallback = fn; - } - - public startService() { - const fiatConversionUrl = (config.SOCKS5PROXY.ENABLED === true) && (config.SOCKS5PROXY.USE_ONION === true) ? config.PRICE_DATA_SERVER.TOR_URL : config.PRICE_DATA_SERVER.CLEARNET_URL; - logger.info('Starting currency rates service'); - if (config.SOCKS5PROXY.ENABLED) { - logger.info(`Currency rates service will be queried over the Tor network using ${fiatConversionUrl}`); - } else { - logger.info(`Currency rates service will be queried over clearnet using ${config.PRICE_DATA_SERVER.CLEARNET_URL}`); - } - setInterval(this.updateCurrency.bind(this), 1000 * config.MEMPOOL.PRICE_FEED_UPDATE_INTERVAL); - this.updateCurrency(); - } - - public getConversionRates() { - return this.conversionRates; - } - - private async updateCurrency(): Promise { - type axiosOptions = { - headers: { - 'User-Agent': string - }; - timeout: number; - httpAgent?: http.Agent; - httpsAgent?: https.Agent; - } - const setDelay = (secs: number = 1): Promise => new Promise(resolve => setTimeout(() => resolve(), secs * 1000)); - const fiatConversionUrl = (config.SOCKS5PROXY.ENABLED === true) && (config.SOCKS5PROXY.USE_ONION === true) ? config.PRICE_DATA_SERVER.TOR_URL : config.PRICE_DATA_SERVER.CLEARNET_URL; - const isHTTP = (new URL(fiatConversionUrl).protocol.split(':')[0] === 'http') ? true : false; - const axiosOptions: axiosOptions = { - headers: { - 'User-Agent': (config.MEMPOOL.USER_AGENT === 'mempool') ? `mempool/v${backendInfo.getBackendInfo().version}` : `${config.MEMPOOL.USER_AGENT}` - }, - timeout: config.SOCKS5PROXY.ENABLED ? 30000 : 10000 - }; - - let retry = 0; - - while(retry < config.MEMPOOL.EXTERNAL_MAX_RETRY) { - try { - if (config.SOCKS5PROXY.ENABLED) { - let socksOptions: any = { - agentOptions: { - keepAlive: true, - }, - hostname: config.SOCKS5PROXY.HOST, - port: config.SOCKS5PROXY.PORT - }; - - if (config.SOCKS5PROXY.USERNAME && config.SOCKS5PROXY.PASSWORD) { - socksOptions.username = config.SOCKS5PROXY.USERNAME; - socksOptions.password = config.SOCKS5PROXY.PASSWORD; - } else { - // Retry with different tor circuits https://stackoverflow.com/a/64960234 - socksOptions.username = `circuit${retry}`; - } - - // Handle proxy agent for onion addresses - if (isHTTP) { - axiosOptions.httpAgent = new SocksProxyAgent(socksOptions); - } else { - axiosOptions.httpsAgent = new SocksProxyAgent(socksOptions); - } - } - - logger.debug('Querying currency rates service...'); - - const response: AxiosResponse = await axios.get(`${fiatConversionUrl}`, axiosOptions); - - if (response.statusText === 'error' || !response.data) { - throw new Error(`Could not fetch data from ${fiatConversionUrl}, Error: ${response.status}`); - } - - for (const rate of response.data.data) { - if (this.debasingFiatCurrencies.includes(rate.currencyCode) && rate.provider === 'Bisq-Aggregate') { - this.conversionRates[rate.currencyCode] = Math.round(100 * rate.price) / 100; - } - } - - this.ratesInitialized = true; - logger.debug(`USD Conversion Rate: ${this.conversionRates.USD}`); - - if (this.ratesChangedCallback) { - this.ratesChangedCallback(this.conversionRates); - } - break; - } catch (e) { - logger.err('Error updating fiat conversion rates: ' + (e instanceof Error ? e.message : e)); - await setDelay(config.MEMPOOL.EXTERNAL_RETRY_INTERVAL); - retry++; - } - } - } -} - -export default new FiatConversion(); diff --git a/backend/src/api/websocket-handler.ts b/backend/src/api/websocket-handler.ts index 599c068a6..3b6c62513 100644 --- a/backend/src/api/websocket-handler.ts +++ b/backend/src/api/websocket-handler.ts @@ -8,7 +8,6 @@ import blocks from './blocks'; import memPool from './mempool'; import backendInfo from './backend-info'; import mempoolBlocks from './mempool-blocks'; -import fiatConversion from './fiat-conversion'; import { Common } from './common'; import loadingIndicators from './loading-indicators'; import config from '../config'; @@ -20,6 +19,7 @@ import BlocksAuditsRepository from '../repositories/BlocksAuditsRepository'; import BlocksSummariesRepository from '../repositories/BlocksSummariesRepository'; import Audit from './audit'; import { deepClone } from '../utils/clone'; +import priceUpdater from '../tasks/price-updater'; class WebsocketHandler { private wss: WebSocket.Server | undefined; @@ -214,7 +214,7 @@ class WebsocketHandler { 'mempoolInfo': memPool.getMempoolInfo(), 'vBytesPerSecond': memPool.getVBytesPerSecond(), 'blocks': _blocks, - 'conversions': fiatConversion.getConversionRates(), + 'conversions': priceUpdater.latestPrices, 'mempool-blocks': mempoolBlocks.getMempoolBlocks(), 'transactions': memPool.getLatestTransactions(), 'backendInfo': backendInfo.getBackendInfo(), diff --git a/backend/src/index.ts b/backend/src/index.ts index 8371e927f..7c0d7ee48 100644 --- a/backend/src/index.ts +++ b/backend/src/index.ts @@ -10,7 +10,6 @@ import memPool from './api/mempool'; import diskCache from './api/disk-cache'; import statistics from './api/statistics/statistics'; import websocketHandler from './api/websocket-handler'; -import fiatConversion from './api/fiat-conversion'; import bisq from './api/bisq/bisq'; import bisqMarkets from './api/bisq/markets'; import logger from './logger'; @@ -36,6 +35,7 @@ import liquidRoutes from './api/liquid/liquid.routes'; import bitcoinRoutes from './api/bitcoin/bitcoin.routes'; import fundingTxFetcher from './tasks/lightning/sync-tasks/funding-tx-fetcher'; import forensicsService from './tasks/lightning/forensics.service'; +import priceUpdater from './tasks/price-updater'; class Server { private wss: WebSocket.Server | undefined; @@ -87,6 +87,8 @@ class Server { .use(express.text({ type: ['text/plain', 'application/base64'] })) ; + await priceUpdater.$initializeLatestPriceWithDb(); + this.server = http.createServer(this.app); this.wss = new WebSocket.Server({ server: this.server }); @@ -127,7 +129,7 @@ class Server { } } - fiatConversion.startService(); + priceUpdater.$run(); this.setUpHttpApiRoutes(); @@ -221,7 +223,7 @@ class Server { memPool.setAsyncMempoolChangedCallback(websocketHandler.handleMempoolChange.bind(websocketHandler)); blocks.setNewAsyncBlockCallback(websocketHandler.handleNewBlock.bind(websocketHandler)); } - fiatConversion.setProgressChangedCallback(websocketHandler.handleNewConversionRates.bind(websocketHandler)); + priceUpdater.setRatesChangedCallback(websocketHandler.handleNewConversionRates.bind(websocketHandler)); loadingIndicators.setProgressChangedCallback(websocketHandler.handleLoadingChanged.bind(websocketHandler)); } diff --git a/backend/src/repositories/PricesRepository.ts b/backend/src/repositories/PricesRepository.ts index cc79ff2a6..bc606e68b 100644 --- a/backend/src/repositories/PricesRepository.ts +++ b/backend/src/repositories/PricesRepository.ts @@ -1,12 +1,13 @@ import DB from '../database'; import logger from '../logger'; -import { Prices } from '../tasks/price-updater'; +import { IConversionRates } from '../mempool.interfaces'; +import priceUpdater from '../tasks/price-updater'; class PricesRepository { - public async $savePrices(time: number, prices: Prices): Promise { - if (prices.USD === -1) { - // Some historical price entries have not USD prices, so we just ignore them to avoid future UX issues - // As of today there are only 4 (on 2013-09-05, 2013-09-19, 2013-09-12 and 2013-09-26) so that's fine + public async $savePrices(time: number, prices: IConversionRates): Promise { + if (prices.USD === 0) { + // Some historical price entries have no USD prices, so we just ignore them to avoid future UX issues + // As of today there are only 4 (on 2013-09-05, 2013-0909, 2013-09-12 and 2013-09-26) so that's fine return; } @@ -23,22 +24,22 @@ class PricesRepository { } public async $getOldestPriceTime(): Promise { - const [oldestRow] = await DB.query(`SELECT UNIX_TIMESTAMP(time) as time from prices WHERE USD != -1 ORDER BY time LIMIT 1`); + const [oldestRow] = await DB.query(`SELECT UNIX_TIMESTAMP(time) as time from prices WHERE USD != 0 ORDER BY time LIMIT 1`); return oldestRow[0] ? oldestRow[0].time : 0; } public async $getLatestPriceId(): Promise { - const [oldestRow] = await DB.query(`SELECT id from prices WHERE USD != -1 ORDER BY time DESC LIMIT 1`); + const [oldestRow] = await DB.query(`SELECT id from prices WHERE USD != 0 ORDER BY time DESC LIMIT 1`); return oldestRow[0] ? oldestRow[0].id : null; } public async $getLatestPriceTime(): Promise { - const [oldestRow] = await DB.query(`SELECT UNIX_TIMESTAMP(time) as time from prices WHERE USD != -1 ORDER BY time DESC LIMIT 1`); + const [oldestRow] = await DB.query(`SELECT UNIX_TIMESTAMP(time) as time from prices WHERE USD != 0 ORDER BY time DESC LIMIT 1`); return oldestRow[0] ? oldestRow[0].time : 0; } public async $getPricesTimes(): Promise { - const [times]: any[] = await DB.query(`SELECT UNIX_TIMESTAMP(time) as time from prices WHERE USD != -1 ORDER BY time`); + const [times]: any[] = await DB.query(`SELECT UNIX_TIMESTAMP(time) as time from prices WHERE USD != 0 ORDER BY time`); return times.map(time => time.time); } @@ -46,6 +47,19 @@ class PricesRepository { const [times]: any[] = await DB.query(`SELECT UNIX_TIMESTAMP(time) as time, id, USD from prices ORDER BY time`); return times; } + + public async $getLatestConversionRates(): Promise { + const [rates]: any[] = await DB.query(` + SELECT USD, EUR, GBP, CAD, CHF, AUD, JPY + FROM prices + ORDER BY time DESC + LIMIT 1` + ); + if (!rates || rates.length === 0) { + return priceUpdater.getEmptyPricesObj(); + } + return rates[0]; + } } export default new PricesRepository(); diff --git a/backend/src/tasks/price-updater.ts b/backend/src/tasks/price-updater.ts index 9e7e5910a..e42c5887a 100644 --- a/backend/src/tasks/price-updater.ts +++ b/backend/src/tasks/price-updater.ts @@ -1,7 +1,8 @@ import * as fs from 'fs'; -import path from "path"; +import path from 'path'; import config from '../config'; import logger from '../logger'; +import { IConversionRates } from '../mempool.interfaces'; import PricesRepository from '../repositories/PricesRepository'; import BitfinexApi from './price-feeds/bitfinex-api'; import BitflyerApi from './price-feeds/bitflyer-api'; @@ -20,17 +21,7 @@ export interface PriceFeed { } export interface PriceHistory { - [timestamp: number]: Prices; -} - -export interface Prices { - USD: number; - EUR: number; - GBP: number; - CAD: number; - CHF: number; - AUD: number; - JPY: number; + [timestamp: number]: IConversionRates; } class PriceUpdater { @@ -40,7 +31,8 @@ class PriceUpdater { running = false; feeds: PriceFeed[] = []; currencies: string[] = ['USD', 'EUR', 'GBP', 'CAD', 'CHF', 'AUD', 'JPY']; - latestPrices: Prices; + latestPrices: IConversionRates; + private ratesChangedCallback: ((rates: IConversionRates) => void) | undefined; constructor() { this.latestPrices = this.getEmptyPricesObj(); @@ -52,18 +44,30 @@ class PriceUpdater { this.feeds.push(new GeminiApi()); } - public getEmptyPricesObj(): Prices { + public getEmptyPricesObj(): IConversionRates { return { - USD: -1, - EUR: -1, - GBP: -1, - CAD: -1, - CHF: -1, - AUD: -1, - JPY: -1, + USD: 0, + EUR: 0, + GBP: 0, + CAD: 0, + CHF: 0, + AUD: 0, + JPY: 0, }; } + public setRatesChangedCallback(fn: (rates: IConversionRates) => void) { + this.ratesChangedCallback = fn; + } + + /** + * We execute this function before the websocket initialization since + * the websocket init is not done asyncronously + */ + public async $initializeLatestPriceWithDb(): Promise { + this.latestPrices = await PricesRepository.$getLatestConversionRates(); + } + public async $run(): Promise { if (this.running === true) { return; @@ -76,10 +80,9 @@ class PriceUpdater { } try { + await this.$updatePrice(); if (this.historyInserted === false && config.DATABASE.ENABLED === true) { await this.$insertHistoricalPrices(); - } else { - await this.$updatePrice(); } } catch (e) { logger.err(`Cannot save BTC prices in db. Reason: ${e instanceof Error ? e.message : e}`, logger.tags.mining); @@ -144,6 +147,10 @@ class PriceUpdater { } } + if (this.ratesChangedCallback) { + this.ratesChangedCallback(this.latestPrices); + } + this.lastRun = new Date().getTime() / 1000; } @@ -213,7 +220,7 @@ class PriceUpdater { // Group them by timestamp and currency, for example // grouped[123456789]['USD'] = [1, 2, 3, 4]; - const grouped: Object = {}; + const grouped: any = {}; for (const historicalEntry of historicalPrices) { for (const time in historicalEntry) { if (existingPriceTimes.includes(parseInt(time, 10))) { @@ -229,7 +236,7 @@ class PriceUpdater { for (const currency of this.currencies) { const price = historicalEntry[time][currency]; if (price > 0) { - grouped[time][currency].push(parseInt(price, 10)); + grouped[time][currency].push(typeof price === 'string' ? parseInt(price, 10) : price); } } } @@ -238,7 +245,7 @@ class PriceUpdater { // Average prices and insert everything into the db let totalInserted = 0; for (const time in grouped) { - const prices: Prices = this.getEmptyPricesObj(); + const prices: IConversionRates = this.getEmptyPricesObj(); for (const currency in grouped[time]) { if (grouped[time][currency].length === 0) { continue; From 6c0dc34dd6249c1df69fc2b39e3e6c519122ec76 Mon Sep 17 00:00:00 2001 From: nymkappa <1612910616@pm.me> Date: Wed, 15 Feb 2023 16:13:10 +0900 Subject: [PATCH 08/17] Run database migration before running any business logic --- backend/src/index.ts | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/backend/src/index.ts b/backend/src/index.ts index 7c0d7ee48..cad675e27 100644 --- a/backend/src/index.ts +++ b/backend/src/index.ts @@ -78,6 +78,24 @@ class Server { async startServer(worker = false): Promise { logger.notice(`Starting Mempool Server${worker ? ' (worker)' : ''}... (${backendInfo.getShortCommitHash()})`); + if (config.DATABASE.ENABLED) { + await DB.checkDbConnection(); + try { + if (process.env.npm_config_reindex !== undefined) { // Re-index requests + const tables = process.env.npm_config_reindex.split(','); + logger.warn(`Indexed data for "${process.env.npm_config_reindex}" tables will be erased in 5 seconds (using '--reindex')`); + await Common.sleep$(5000); + await databaseMigration.$truncateIndexedData(tables); + } + await databaseMigration.$initializeOrMigrateDatabase(); + if (Common.indexingEnabled()) { + await indexer.$resetHashratesIndexingState(); + } + } catch (e) { + throw new Error(e instanceof Error ? e.message : 'Error'); + } + } + this.app .use((req: Request, res: Response, next: NextFunction) => { res.setHeader('Access-Control-Allow-Origin', '*'); @@ -99,24 +117,6 @@ class Server { diskCache.loadMempoolCache(); } - if (config.DATABASE.ENABLED) { - await DB.checkDbConnection(); - try { - if (process.env.npm_config_reindex !== undefined) { // Re-index requests - const tables = process.env.npm_config_reindex.split(','); - logger.warn(`Indexed data for "${process.env.npm_config_reindex}" tables will be erased in 5 seconds (using '--reindex')`); - await Common.sleep$(5000); - await databaseMigration.$truncateIndexedData(tables); - } - await databaseMigration.$initializeOrMigrateDatabase(); - if (Common.indexingEnabled()) { - await indexer.$resetHashratesIndexingState(); - } - } catch (e) { - throw new Error(e instanceof Error ? e.message : 'Error'); - } - } - if (config.STATISTICS.ENABLED && config.DATABASE.ENABLED && cluster.isPrimary) { statistics.startStatistics(); } From 28bd813fb8322e9b765d54203c01069fbcda0b0c Mon Sep 17 00:00:00 2001 From: nymkappa <1612910616@pm.me> Date: Wed, 15 Feb 2023 16:22:06 +0900 Subject: [PATCH 09/17] Show correct currency label in 'Latest transactions' widget --- .../app/dashboard/dashboard.component.html | 2 +- .../src/app/dashboard/dashboard.component.ts | 21 ++++++++++++------- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/frontend/src/app/dashboard/dashboard.component.html b/frontend/src/app/dashboard/dashboard.component.html index 1df7baabc..f3d96e187 100644 --- a/frontend/src/app/dashboard/dashboard.component.html +++ b/frontend/src/app/dashboard/dashboard.component.html @@ -122,7 +122,7 @@ TXID Amount - USD + {{ currency }} Fee diff --git a/frontend/src/app/dashboard/dashboard.component.ts b/frontend/src/app/dashboard/dashboard.component.ts index 45b402314..1eb305220 100644 --- a/frontend/src/app/dashboard/dashboard.component.ts +++ b/frontend/src/app/dashboard/dashboard.component.ts @@ -1,5 +1,5 @@ -import { ChangeDetectionStrategy, Component, Inject, LOCALE_ID, OnInit } from '@angular/core'; -import { combineLatest, merge, Observable, of } from 'rxjs'; +import { ChangeDetectionStrategy, Component, OnDestroy, OnInit } from '@angular/core'; +import { combineLatest, merge, Observable, of, Subscription } from 'rxjs'; import { filter, map, scan, share, switchMap, tap } from 'rxjs/operators'; import { BlockExtended, OptimizedMempoolStats } from '../interfaces/node-api.interface'; import { MempoolInfo, TransactionStripped } from '../interfaces/websocket.interface'; @@ -7,7 +7,6 @@ import { ApiService } from '../services/api.service'; import { StateService } from '../services/state.service'; import { WebsocketService } from '../services/websocket.service'; import { SeoService } from '../services/seo.service'; -import { StorageService } from '../services/storage.service'; interface MempoolBlocksData { blocks: number; @@ -32,7 +31,7 @@ interface MempoolStatsData { styleUrls: ['./dashboard.component.scss'], changeDetection: ChangeDetectionStrategy.OnPush }) -export class DashboardComponent implements OnInit { +export class DashboardComponent implements OnInit, OnDestroy { featuredAssets$: Observable; network$: Observable; mempoolBlocksData$: Observable; @@ -47,16 +46,20 @@ export class DashboardComponent implements OnInit { transactionsWeightPerSecondOptions: any; isLoadingWebSocket$: Observable; liquidPegsMonth$: Observable; + currencySubscription: Subscription; + currency: string; constructor( - @Inject(LOCALE_ID) private locale: string, public stateService: StateService, private apiService: ApiService, private websocketService: WebsocketService, - private seoService: SeoService, - private storageService: StorageService, + private seoService: SeoService ) { } + ngOnDestroy(): void { + this.currencySubscription.unsubscribe(); + } + ngOnInit(): void { this.isLoadingWebSocket$ = this.stateService.isLoadingWebSocket$; this.seoService.resetTitle(); @@ -213,6 +216,10 @@ export class DashboardComponent implements OnInit { share(), ); } + + this.currencySubscription = this.stateService.fiatCurrency$.subscribe((fiat) => { + this.currency = fiat; + }); } handleNewMempoolData(mempoolStats: OptimizedMempoolStats[]) { From 23636313263798c86537a993ca8ffb10edd3123e Mon Sep 17 00:00:00 2001 From: Mononaut Date: Sun, 12 Feb 2023 21:43:12 -0600 Subject: [PATCH 10/17] Add audit / block health config feature flag --- backend/mempool-config.sample.json | 1 + .../__fixtures__/mempool-config.template.json | 1 + backend/src/__tests__/config.test.ts | 1 + backend/src/api/blocks.ts | 8 +- backend/src/api/websocket-handler.ts | 80 ++++++++++--------- backend/src/config.ts | 2 + docker/backend/mempool-config.json | 1 + docker/backend/start.sh | 2 + docker/frontend/entrypoint.sh | 2 + frontend/mempool-frontend-config.sample.json | 1 + .../app/components/block/block.component.ts | 26 +++--- .../blocks-list/blocks-list.component.html | 6 +- .../blocks-list/blocks-list.component.ts | 4 +- .../components/graphs/graphs.component.html | 2 +- frontend/src/app/services/state.service.ts | 2 + production/mempool-config.mainnet.json | 1 + production/mempool-config.signet.json | 1 + production/mempool-config.testnet.json | 1 + .../mempool-frontend-config.mainnet.json | 3 +- 19 files changed, 88 insertions(+), 57 deletions(-) diff --git a/backend/mempool-config.sample.json b/backend/mempool-config.sample.json index 1f64214ce..f8417f0e7 100644 --- a/backend/mempool-config.sample.json +++ b/backend/mempool-config.sample.json @@ -25,6 +25,7 @@ "AUTOMATIC_BLOCK_REINDEXING": false, "POOLS_JSON_URL": "https://raw.githubusercontent.com/mempool/mining-pools/master/pools.json", "POOLS_JSON_TREE_URL": "https://api.github.com/repos/mempool/mining-pools/git/trees/master", + "AUDIT": false, "ADVANCED_GBT_AUDIT": false, "ADVANCED_GBT_MEMPOOL": false, "CPFP_INDEXING": false diff --git a/backend/src/__fixtures__/mempool-config.template.json b/backend/src/__fixtures__/mempool-config.template.json index e699c9458..f15d9c328 100644 --- a/backend/src/__fixtures__/mempool-config.template.json +++ b/backend/src/__fixtures__/mempool-config.template.json @@ -26,6 +26,7 @@ "INDEXING_BLOCKS_AMOUNT": 14, "POOLS_JSON_TREE_URL": "__POOLS_JSON_TREE_URL__", "POOLS_JSON_URL": "__POOLS_JSON_URL__", + "AUDIT": "__MEMPOOL_AUDIT__", "ADVANCED_GBT_AUDIT": "__MEMPOOL_ADVANCED_GBT_AUDIT__", "ADVANCED_GBT_MEMPOOL": "__MEMPOOL_ADVANCED_GBT_MEMPOOL__", "CPFP_INDEXING": "__MEMPOOL_CPFP_INDEXING__" diff --git a/backend/src/__tests__/config.test.ts b/backend/src/__tests__/config.test.ts index 4158d3df1..88083f479 100644 --- a/backend/src/__tests__/config.test.ts +++ b/backend/src/__tests__/config.test.ts @@ -38,6 +38,7 @@ describe('Mempool Backend Config', () => { STDOUT_LOG_MIN_PRIORITY: 'debug', POOLS_JSON_TREE_URL: 'https://api.github.com/repos/mempool/mining-pools/git/trees/master', POOLS_JSON_URL: 'https://raw.githubusercontent.com/mempool/mining-pools/master/pools.json', + AUDIT: false, ADVANCED_GBT_AUDIT: false, ADVANCED_GBT_MEMPOOL: false, CPFP_INDEXING: false, diff --git a/backend/src/api/blocks.ts b/backend/src/api/blocks.ts index 902f1f13b..84c919e5d 100644 --- a/backend/src/api/blocks.ts +++ b/backend/src/api/blocks.ts @@ -211,9 +211,11 @@ class Blocks { }; } - const auditScore = await BlocksAuditsRepository.$getBlockAuditScore(block.id); - if (auditScore != null) { - blockExtended.extras.matchRate = auditScore.matchRate; + if (config.MEMPOOL.AUDIT) { + const auditScore = await BlocksAuditsRepository.$getBlockAuditScore(block.id); + if (auditScore != null) { + blockExtended.extras.matchRate = auditScore.matchRate; + } } } diff --git a/backend/src/api/websocket-handler.ts b/backend/src/api/websocket-handler.ts index 3b6c62513..c1c3b3995 100644 --- a/backend/src/api/websocket-handler.ts +++ b/backend/src/api/websocket-handler.ts @@ -419,49 +419,51 @@ class WebsocketHandler { const _memPool = memPool.getMempool(); - let projectedBlocks; - // template calculation functions have mempool side effects, so calculate audits using - // a cloned copy of the mempool if we're running a different algorithm for mempool updates - const auditMempool = (config.MEMPOOL.ADVANCED_GBT_AUDIT === config.MEMPOOL.ADVANCED_GBT_MEMPOOL) ? _memPool : deepClone(_memPool); - if (config.MEMPOOL.ADVANCED_GBT_AUDIT) { - projectedBlocks = await mempoolBlocks.makeBlockTemplates(auditMempool, false); - } else { - projectedBlocks = mempoolBlocks.updateMempoolBlocks(auditMempool, false); - } + if (config.MEMPOOL.AUDIT) { + let projectedBlocks; + // template calculation functions have mempool side effects, so calculate audits using + // a cloned copy of the mempool if we're running a different algorithm for mempool updates + const auditMempool = (config.MEMPOOL.ADVANCED_GBT_AUDIT === config.MEMPOOL.ADVANCED_GBT_MEMPOOL) ? _memPool : deepClone(_memPool); + if (config.MEMPOOL.ADVANCED_GBT_AUDIT) { + projectedBlocks = await mempoolBlocks.makeBlockTemplates(auditMempool, false); + } else { + projectedBlocks = mempoolBlocks.updateMempoolBlocks(auditMempool, false); + } - if (Common.indexingEnabled() && memPool.isInSync()) { - const { censored, added, fresh, score } = Audit.auditBlock(transactions, projectedBlocks, auditMempool); - const matchRate = Math.round(score * 100 * 100) / 100; + if (Common.indexingEnabled() && memPool.isInSync()) { + const { censored, added, fresh, score } = Audit.auditBlock(transactions, projectedBlocks, auditMempool); + const matchRate = Math.round(score * 100 * 100) / 100; - const stripped = projectedBlocks[0]?.transactions ? projectedBlocks[0].transactions.map((tx) => { - return { - txid: tx.txid, - vsize: tx.vsize, - fee: tx.fee ? Math.round(tx.fee) : 0, - value: tx.value, - }; - }) : []; + const stripped = projectedBlocks[0]?.transactions ? projectedBlocks[0].transactions.map((tx) => { + return { + txid: tx.txid, + vsize: tx.vsize, + fee: tx.fee ? Math.round(tx.fee) : 0, + value: tx.value, + }; + }) : []; - BlocksSummariesRepository.$saveTemplate({ - height: block.height, - template: { - id: block.id, - transactions: stripped + BlocksSummariesRepository.$saveTemplate({ + height: block.height, + template: { + id: block.id, + transactions: stripped + } + }); + + BlocksAuditsRepository.$saveAudit({ + time: block.timestamp, + height: block.height, + hash: block.id, + addedTxs: added, + missingTxs: censored, + freshTxs: fresh, + matchRate: matchRate, + }); + + if (block.extras) { + block.extras.matchRate = matchRate; } - }); - - BlocksAuditsRepository.$saveAudit({ - time: block.timestamp, - height: block.height, - hash: block.id, - addedTxs: added, - missingTxs: censored, - freshTxs: fresh, - matchRate: matchRate, - }); - - if (block.extras) { - block.extras.matchRate = matchRate; } } diff --git a/backend/src/config.ts b/backend/src/config.ts index fb06c84fb..a5736996f 100644 --- a/backend/src/config.ts +++ b/backend/src/config.ts @@ -29,6 +29,7 @@ interface IConfig { AUTOMATIC_BLOCK_REINDEXING: boolean; POOLS_JSON_URL: string, POOLS_JSON_TREE_URL: string, + AUDIT: boolean; ADVANCED_GBT_AUDIT: boolean; ADVANCED_GBT_MEMPOOL: boolean; CPFP_INDEXING: boolean; @@ -150,6 +151,7 @@ const defaults: IConfig = { 'AUTOMATIC_BLOCK_REINDEXING': false, 'POOLS_JSON_URL': 'https://raw.githubusercontent.com/mempool/mining-pools/master/pools.json', 'POOLS_JSON_TREE_URL': 'https://api.github.com/repos/mempool/mining-pools/git/trees/master', + 'AUDIT': false, 'ADVANCED_GBT_AUDIT': false, 'ADVANCED_GBT_MEMPOOL': false, 'CPFP_INDEXING': false, diff --git a/docker/backend/mempool-config.json b/docker/backend/mempool-config.json index 2e3826f1d..17901acc4 100644 --- a/docker/backend/mempool-config.json +++ b/docker/backend/mempool-config.json @@ -23,6 +23,7 @@ "INDEXING_BLOCKS_AMOUNT": __MEMPOOL_INDEXING_BLOCKS_AMOUNT__, "BLOCKS_SUMMARIES_INDEXING": __MEMPOOL_BLOCKS_SUMMARIES_INDEXING__, "AUTOMATIC_BLOCK_REINDEXING": __MEMPOOL_AUTOMATIC_BLOCK_REINDEXING__, + "AUDIT": __MEMPOOL_AUDIT__, "ADVANCED_GBT_AUDIT": __MEMPOOL_ADVANCED_GBT_AUDIT__, "ADVANCED_GBT_MEMPOOL": __MEMPOOL_ADVANCED_GBT_MEMPOOL__, "CPFP_INDEXING": __MEMPOOL_CPFP_INDEXING__ diff --git a/docker/backend/start.sh b/docker/backend/start.sh index 5f33df107..e02706bce 100755 --- a/docker/backend/start.sh +++ b/docker/backend/start.sh @@ -27,6 +27,7 @@ __MEMPOOL_INDEXING_BLOCKS_AMOUNT__=${MEMPOOL_INDEXING_BLOCKS_AMOUNT:=false} __MEMPOOL_AUTOMATIC_BLOCK_REINDEXING__=${MEMPOOL_AUTOMATIC_BLOCK_REINDEXING:=false} __MEMPOOL_POOLS_JSON_URL__=${MEMPOOL_POOLS_JSON_URL:=https://raw.githubusercontent.com/mempool/mining-pools/master/pools.json} __MEMPOOL_POOLS_JSON_TREE_URL__=${MEMPOOL_POOLS_JSON_TREE_URL:=https://api.github.com/repos/mempool/mining-pools/git/trees/master} +__MEMPOOL_AUDIT__=${MEMPOOL_AUDIT:=false} __MEMPOOL_ADVANCED_GBT_AUDIT__=${MEMPOOL_ADVANCED_GBT_AUDIT:=false} __MEMPOOL_ADVANCED_GBT_MEMPOOL__=${MEMPOOL_ADVANCED_GBT_MEMPOOL:=false} __MEMPOOL_CPFP_INDEXING__=${MEMPOOL_CPFP_INDEXING:=false} @@ -139,6 +140,7 @@ sed -i "s/__MEMPOOL_INDEXING_BLOCKS_AMOUNT__/${__MEMPOOL_INDEXING_BLOCKS_AMOUNT_ sed -i "s/__MEMPOOL_AUTOMATIC_BLOCK_REINDEXING__/${__MEMPOOL_AUTOMATIC_BLOCK_REINDEXING__}/g" mempool-config.json sed -i "s!__MEMPOOL_POOLS_JSON_URL__!${__MEMPOOL_POOLS_JSON_URL__}!g" mempool-config.json sed -i "s!__MEMPOOL_POOLS_JSON_TREE_URL__!${__MEMPOOL_POOLS_JSON_TREE_URL__}!g" mempool-config.json +sed -i "s!__MEMPOOL_AUDIT__!${__MEMPOOL_AUDIT__}!g" mempool-config.json sed -i "s!__MEMPOOL_ADVANCED_GBT_MEMPOOL__!${__MEMPOOL_ADVANCED_GBT_MEMPOOL__}!g" mempool-config.json sed -i "s!__MEMPOOL_ADVANCED_GBT_AUDIT__!${__MEMPOOL_ADVANCED_GBT_AUDIT__}!g" mempool-config.json sed -i "s!__MEMPOOL_CPFP_INDEXING__!${__MEMPOOL_CPFP_INDEXING__}!g" mempool-config.json diff --git a/docker/frontend/entrypoint.sh b/docker/frontend/entrypoint.sh index 3e2210360..18cb782e9 100644 --- a/docker/frontend/entrypoint.sh +++ b/docker/frontend/entrypoint.sh @@ -31,6 +31,7 @@ __LIQUID_WEBSITE_URL__=${LIQUID_WEBSITE_URL:=https://liquid.network} __BISQ_WEBSITE_URL__=${BISQ_WEBSITE_URL:=https://bisq.markets} __MINING_DASHBOARD__=${MINING_DASHBOARD:=true} __LIGHTNING__=${LIGHTNING:=false} +__AUDIT__=${AUDIT:=false} __MAINNET_BLOCK_AUDIT_START_HEIGHT__=${MAINNET_BLOCK_AUDIT_START_HEIGHT:=0} __TESTNET_BLOCK_AUDIT_START_HEIGHT__=${TESTNET_BLOCK_AUDIT_START_HEIGHT:=0} __SIGNET_BLOCK_AUDIT_START_HEIGHT__=${SIGNET_BLOCK_AUDIT_START_HEIGHT:=0} @@ -55,6 +56,7 @@ export __LIQUID_WEBSITE_URL__ export __BISQ_WEBSITE_URL__ export __MINING_DASHBOARD__ export __LIGHTNING__ +export __AUDIT__ export __MAINNET_BLOCK_AUDIT_START_HEIGHT__ export __TESTNET_BLOCK_AUDIT_START_HEIGHT__ export __SIGNET_BLOCK_AUDIT_START_HEIGHT__ diff --git a/frontend/mempool-frontend-config.sample.json b/frontend/mempool-frontend-config.sample.json index 5c0f92acf..9035315a4 100644 --- a/frontend/mempool-frontend-config.sample.json +++ b/frontend/mempool-frontend-config.sample.json @@ -17,6 +17,7 @@ "LIQUID_WEBSITE_URL": "https://liquid.network", "BISQ_WEBSITE_URL": "https://bisq.markets", "MINING_DASHBOARD": true, + "AUDIT": false, "MAINNET_BLOCK_AUDIT_START_HEIGHT": 0, "TESTNET_BLOCK_AUDIT_START_HEIGHT": 0, "SIGNET_BLOCK_AUDIT_START_HEIGHT": 0, diff --git a/frontend/src/app/components/block/block.component.ts b/frontend/src/app/components/block/block.component.ts index f1ebfed6a..668d0af48 100644 --- a/frontend/src/app/components/block/block.component.ts +++ b/frontend/src/app/components/block/block.component.ts @@ -58,7 +58,7 @@ export class BlockComponent implements OnInit, OnDestroy { overviewError: any = null; webGlEnabled = true; indexingAvailable = false; - auditModeEnabled: boolean = !this.stateService.hideAudit.value; + auditModeEnabled: boolean = this.stateService.env.AUDIT && !this.stateService.hideAudit.value; auditAvailable = true; showAudit: boolean; isMobile = window.innerWidth <= 767.98; @@ -110,12 +110,15 @@ export class BlockComponent implements OnInit, OnDestroy { }); this.indexingAvailable = (this.stateService.env.BASE_MODULE === 'mempool' && this.stateService.env.MINING_DASHBOARD === true); - this.setAuditAvailable(this.indexingAvailable); - this.auditPrefSubscription = this.stateService.hideAudit.subscribe((hide) => { - this.auditModeEnabled = !hide; - this.showAudit = this.auditAvailable && this.auditModeEnabled; - }); + this.setAuditAvailable(this.stateService.env.AUDIT && this.indexingAvailable); + + if (this.stateService.env.AUDIT) { + this.auditPrefSubscription = this.stateService.hideAudit.subscribe((hide) => { + this.auditModeEnabled = !hide; + this.showAudit = this.auditAvailable && this.auditModeEnabled; + }); + } this.txsLoadingStatus$ = this.route.paramMap .pipe( @@ -221,7 +224,9 @@ export class BlockComponent implements OnInit, OnDestroy { setTimeout(() => { this.nextBlockSubscription = this.apiService.getBlock$(block.previousblockhash).subscribe(); this.nextBlockTxListSubscription = this.electrsApiService.getBlockTransactions$(block.previousblockhash).subscribe(); - this.apiService.getBlockAudit$(block.previousblockhash); + if (this.stateService.env.AUDIT) { + this.apiService.getBlockAudit$(block.previousblockhash); + } }, 100); } this.updateAuditAvailableFromBlockHeight(block.height); @@ -269,7 +274,7 @@ export class BlockComponent implements OnInit, OnDestroy { this.isLoadingOverview = false; }); - if (!this.indexingAvailable) { + if (!this.indexingAvailable || !this.stateService.env.AUDIT) { this.overviewSubscription = block$.pipe( startWith(null), pairwise(), @@ -300,7 +305,7 @@ export class BlockComponent implements OnInit, OnDestroy { }); } - if (this.indexingAvailable) { + if (this.indexingAvailable && this.stateService.env.AUDIT) { this.auditSubscription = block$.pipe( startWith(null), pairwise(), @@ -613,6 +618,9 @@ export class BlockComponent implements OnInit, OnDestroy { } updateAuditAvailableFromBlockHeight(blockHeight: number): void { + if (!this.stateService.env.AUDIT) { + this.setAuditAvailable(false); + } switch (this.stateService.network) { case 'testnet': if (blockHeight < this.stateService.env.TESTNET_BLOCK_AUDIT_START_HEIGHT) { diff --git a/frontend/src/app/components/blocks-list/blocks-list.component.html b/frontend/src/app/components/blocks-list/blocks-list.component.html index 424ea2ec4..46da3fa91 100644 --- a/frontend/src/app/components/blocks-list/blocks-list.component.html +++ b/frontend/src/app/components/blocks-list/blocks-list.component.html @@ -14,7 +14,7 @@ i18n-ngbTooltip="mining.pool-name" ngbTooltip="Pool" placement="bottom" #miningpool [disableTooltip]="!isEllipsisActive(miningpool)">Pool Timestamp Mined - Health Reward @@ -45,7 +45,7 @@ - + - + diff --git a/frontend/src/app/components/blocks-list/blocks-list.component.ts b/frontend/src/app/components/blocks-list/blocks-list.component.ts index 93f7814cf..1cc428be3 100644 --- a/frontend/src/app/components/blocks-list/blocks-list.component.ts +++ b/frontend/src/app/components/blocks-list/blocks-list.component.ts @@ -22,6 +22,7 @@ export class BlocksList implements OnInit, OnDestroy { latestScoreSubscription: Subscription; indexingAvailable = false; + auditAvailable = false; isLoading = true; loadingScores = true; fromBlockHeight = undefined; @@ -44,6 +45,7 @@ export class BlocksList implements OnInit, OnDestroy { ngOnInit(): void { this.indexingAvailable = (this.stateService.env.BASE_MODULE === 'mempool' && this.stateService.env.MINING_DASHBOARD === true); + this.auditAvailable = this.stateService.env.AUDIT; if (!this.widget) { this.websocketService.want(['blocks']); @@ -111,7 +113,7 @@ export class BlocksList implements OnInit, OnDestroy { }, []) ); - if (this.indexingAvailable) { + if (this.indexingAvailable && this.auditAvailable) { this.auditScoreSubscription = this.fromHeightSubject.pipe( switchMap((fromBlockHeight) => { this.loadingScores = true; diff --git a/frontend/src/app/components/graphs/graphs.component.html b/frontend/src/app/components/graphs/graphs.component.html index dd47a4ac7..af5136a38 100644 --- a/frontend/src/app/components/graphs/graphs.component.html +++ b/frontend/src/app/components/graphs/graphs.component.html @@ -22,7 +22,7 @@ i18n="mining.block-rewards">Block Rewards Block Sizes and Weights - Block Prediction Accuracy
diff --git a/frontend/src/app/services/state.service.ts b/frontend/src/app/services/state.service.ts index 02b160fe9..33de7823d 100644 --- a/frontend/src/app/services/state.service.ts +++ b/frontend/src/app/services/state.service.ts @@ -39,6 +39,7 @@ export interface Env { BISQ_WEBSITE_URL: string; MINING_DASHBOARD: boolean; LIGHTNING: boolean; + AUDIT: boolean; MAINNET_BLOCK_AUDIT_START_HEIGHT: number; TESTNET_BLOCK_AUDIT_START_HEIGHT: number; SIGNET_BLOCK_AUDIT_START_HEIGHT: number; @@ -67,6 +68,7 @@ const defaultEnv: Env = { 'BISQ_WEBSITE_URL': 'https://bisq.markets', 'MINING_DASHBOARD': true, 'LIGHTNING': false, + 'AUDIT': false, 'MAINNET_BLOCK_AUDIT_START_HEIGHT': 0, 'TESTNET_BLOCK_AUDIT_START_HEIGHT': 0, 'SIGNET_BLOCK_AUDIT_START_HEIGHT': 0, diff --git a/production/mempool-config.mainnet.json b/production/mempool-config.mainnet.json index ab2fa69c1..1258e62fb 100644 --- a/production/mempool-config.mainnet.json +++ b/production/mempool-config.mainnet.json @@ -10,6 +10,7 @@ "POLL_RATE_MS": 1000, "INDEXING_BLOCKS_AMOUNT": -1, "BLOCKS_SUMMARIES_INDEXING": true, + "AUDIT": true, "ADVANCED_GBT_AUDIT": true, "ADVANCED_GBT_MEMPOOL": false, "USE_SECOND_NODE_FOR_MINFEE": true diff --git a/production/mempool-config.signet.json b/production/mempool-config.signet.json index 313a09679..3c661c39f 100644 --- a/production/mempool-config.signet.json +++ b/production/mempool-config.signet.json @@ -7,6 +7,7 @@ "SPAWN_CLUSTER_PROCS": 0, "API_URL_PREFIX": "/api/v1/", "INDEXING_BLOCKS_AMOUNT": -1, + "AUDIT": true, "ADVANCED_GBT_AUDIT": true, "ADVANCED_GBT_MEMPOOL": false, "POLL_RATE_MS": 1000 diff --git a/production/mempool-config.testnet.json b/production/mempool-config.testnet.json index 908df7886..352529c6e 100644 --- a/production/mempool-config.testnet.json +++ b/production/mempool-config.testnet.json @@ -7,6 +7,7 @@ "SPAWN_CLUSTER_PROCS": 0, "API_URL_PREFIX": "/api/v1/", "INDEXING_BLOCKS_AMOUNT": -1, + "AUDIT": true, "ADVANCED_GBT_AUDIT": true, "ADVANCED_GBT_MEMPOOL": false, "POLL_RATE_MS": 1000 diff --git a/production/mempool-frontend-config.mainnet.json b/production/mempool-frontend-config.mainnet.json index e612c0440..5eb3d0a7d 100644 --- a/production/mempool-frontend-config.mainnet.json +++ b/production/mempool-frontend-config.mainnet.json @@ -10,5 +10,6 @@ "LIQUID_WEBSITE_URL": "https://liquid.network", "BISQ_WEBSITE_URL": "https://bisq.markets", "ITEMS_PER_PAGE": 25, - "LIGHTNING": true + "LIGHTNING": true, + "AUDIT": true } From c923a4bc2265bfce6cb04faa40df6600f18ba51e Mon Sep 17 00:00:00 2001 From: Mononaut Date: Tue, 14 Feb 2023 12:23:26 -0600 Subject: [PATCH 11/17] simplify audit availability logic --- .../app/components/block/block.component.ts | 20 +++++++++---------- .../blocks-list/blocks-list.component.html | 6 +++--- .../blocks-list/blocks-list.component.ts | 2 +- 3 files changed, 13 insertions(+), 15 deletions(-) diff --git a/frontend/src/app/components/block/block.component.ts b/frontend/src/app/components/block/block.component.ts index 668d0af48..ba5dd8cf7 100644 --- a/frontend/src/app/components/block/block.component.ts +++ b/frontend/src/app/components/block/block.component.ts @@ -57,8 +57,8 @@ export class BlockComponent implements OnInit, OnDestroy { transactionsError: any = null; overviewError: any = null; webGlEnabled = true; - indexingAvailable = false; - auditModeEnabled: boolean = this.stateService.env.AUDIT && !this.stateService.hideAudit.value; + auditSupported: boolean = this.stateService.env.AUDIT && this.stateService.env.BASE_MODULE === 'mempool' && this.stateService.env.MINING_DASHBOARD === true; + auditModeEnabled: boolean = !this.stateService.hideAudit.value; auditAvailable = true; showAudit: boolean; isMobile = window.innerWidth <= 767.98; @@ -109,11 +109,9 @@ export class BlockComponent implements OnInit, OnDestroy { this.timeLtr = !!ltr; }); - this.indexingAvailable = (this.stateService.env.BASE_MODULE === 'mempool' && this.stateService.env.MINING_DASHBOARD === true); + this.setAuditAvailable(this.auditSupported); - this.setAuditAvailable(this.stateService.env.AUDIT && this.indexingAvailable); - - if (this.stateService.env.AUDIT) { + if (this.auditSupported) { this.auditPrefSubscription = this.stateService.hideAudit.subscribe((hide) => { this.auditModeEnabled = !hide; this.showAudit = this.auditAvailable && this.auditModeEnabled; @@ -224,7 +222,7 @@ export class BlockComponent implements OnInit, OnDestroy { setTimeout(() => { this.nextBlockSubscription = this.apiService.getBlock$(block.previousblockhash).subscribe(); this.nextBlockTxListSubscription = this.electrsApiService.getBlockTransactions$(block.previousblockhash).subscribe(); - if (this.stateService.env.AUDIT) { + if (this.auditSupported) { this.apiService.getBlockAudit$(block.previousblockhash); } }, 100); @@ -274,7 +272,7 @@ export class BlockComponent implements OnInit, OnDestroy { this.isLoadingOverview = false; }); - if (!this.indexingAvailable || !this.stateService.env.AUDIT) { + if (!this.auditSupported) { this.overviewSubscription = block$.pipe( startWith(null), pairwise(), @@ -305,7 +303,7 @@ export class BlockComponent implements OnInit, OnDestroy { }); } - if (this.indexingAvailable && this.stateService.env.AUDIT) { + if (this.auditSupported) { this.auditSubscription = block$.pipe( startWith(null), pairwise(), @@ -610,7 +608,7 @@ export class BlockComponent implements OnInit, OnDestroy { setAuditAvailable(available: boolean): void { this.auditAvailable = available; - this.showAudit = this.auditAvailable && this.auditModeEnabled; + this.showAudit = this.auditAvailable && this.auditModeEnabled && this.auditSupported; } toggleAuditMode(): void { @@ -618,7 +616,7 @@ export class BlockComponent implements OnInit, OnDestroy { } updateAuditAvailableFromBlockHeight(blockHeight: number): void { - if (!this.stateService.env.AUDIT) { + if (!this.auditSupported) { this.setAuditAvailable(false); } switch (this.stateService.network) { diff --git a/frontend/src/app/components/blocks-list/blocks-list.component.html b/frontend/src/app/components/blocks-list/blocks-list.component.html index 46da3fa91..ffb5f5f88 100644 --- a/frontend/src/app/components/blocks-list/blocks-list.component.html +++ b/frontend/src/app/components/blocks-list/blocks-list.component.html @@ -14,7 +14,7 @@ i18n-ngbTooltip="mining.pool-name" ngbTooltip="Pool" placement="bottom" #miningpool [disableTooltip]="!isEllipsisActive(miningpool)">Pool Timestamp Mined - Health Reward @@ -45,7 +45,7 @@ - + - + diff --git a/frontend/src/app/components/blocks-list/blocks-list.component.ts b/frontend/src/app/components/blocks-list/blocks-list.component.ts index 1cc428be3..160e0c882 100644 --- a/frontend/src/app/components/blocks-list/blocks-list.component.ts +++ b/frontend/src/app/components/blocks-list/blocks-list.component.ts @@ -45,7 +45,7 @@ export class BlocksList implements OnInit, OnDestroy { ngOnInit(): void { this.indexingAvailable = (this.stateService.env.BASE_MODULE === 'mempool' && this.stateService.env.MINING_DASHBOARD === true); - this.auditAvailable = this.stateService.env.AUDIT; + this.auditAvailable = this.indexingAvailable && this.stateService.env.AUDIT; if (!this.widget) { this.websocketService.want(['blocks']); From 215e92d33e79276c38c2390652ec8ff3e143aee6 Mon Sep 17 00:00:00 2001 From: hunicus <93150691+hunicus@users.noreply.github.com> Date: Wed, 15 Feb 2023 01:27:43 -0500 Subject: [PATCH 12/17] Switch audit faq conditions to env.audit From OFFICIAL_MEMPOOL_SPACE. --- frontend/src/app/docs/api-docs/api-docs-data.ts | 4 ++-- frontend/src/app/docs/api-docs/api-docs-nav.component.html | 2 +- frontend/src/app/docs/api-docs/api-docs-nav.component.ts | 4 ++-- frontend/src/app/docs/api-docs/api-docs.component.html | 2 +- frontend/src/app/docs/api-docs/api-docs.component.ts | 2 ++ 5 files changed, 8 insertions(+), 6 deletions(-) diff --git a/frontend/src/app/docs/api-docs/api-docs-data.ts b/frontend/src/app/docs/api-docs/api-docs-data.ts index 5cc5ca3aa..a6e8e418f 100644 --- a/frontend/src/app/docs/api-docs/api-docs-data.ts +++ b/frontend/src/app/docs/api-docs/api-docs-data.ts @@ -8671,7 +8671,7 @@ export const faqData = [ type: "endpoint", category: "advanced", showConditions: bitcoinNetworks, - options: { officialOnly: true }, + options: { auditOnly: true }, fragment: "how-do-block-audits-work", title: "How do block audits work?", }, @@ -8679,7 +8679,7 @@ export const faqData = [ type: "endpoint", category: "advanced", showConditions: bitcoinNetworks, - options: { officialOnly: true }, + options: { auditOnly: true }, fragment: "what-is-block-health", title: "What is block health?", }, diff --git a/frontend/src/app/docs/api-docs/api-docs-nav.component.html b/frontend/src/app/docs/api-docs/api-docs-nav.component.html index 3abdc91be..0353d5fb0 100644 --- a/frontend/src/app/docs/api-docs/api-docs-nav.component.html +++ b/frontend/src/app/docs/api-docs/api-docs-nav.component.html @@ -1,4 +1,4 @@

{{ item.title }}

-
{{ item.title }} + {{ item.title }}
diff --git a/frontend/src/app/docs/api-docs/api-docs-nav.component.ts b/frontend/src/app/docs/api-docs/api-docs-nav.component.ts index ad9d0b9a5..439f20339 100644 --- a/frontend/src/app/docs/api-docs/api-docs-nav.component.ts +++ b/frontend/src/app/docs/api-docs/api-docs-nav.component.ts @@ -15,7 +15,7 @@ export class ApiDocsNavComponent implements OnInit { @Output() navLinkClickEvent: EventEmitter = new EventEmitter(); env: Env; tabData: any[]; - officialMempoolInstance: boolean; + auditEnabled: boolean; constructor( private stateService: StateService @@ -23,7 +23,7 @@ export class ApiDocsNavComponent implements OnInit { ngOnInit(): void { this.env = this.stateService.env; - this.officialMempoolInstance = this.env.OFFICIAL_MEMPOOL_SPACE; + this.auditEnabled = this.env.AUDIT; if (this.whichTab === 'rest') { this.tabData = restApiDocsData; } else if (this.whichTab === 'faq') { diff --git a/frontend/src/app/docs/api-docs/api-docs.component.html b/frontend/src/app/docs/api-docs/api-docs.component.html index c984c2b77..e9a905fab 100644 --- a/frontend/src/app/docs/api-docs/api-docs.component.html +++ b/frontend/src/app/docs/api-docs/api-docs.component.html @@ -15,7 +15,7 @@
-
+

{{ item.title }}

{{ item.title }}{{ item.category }}
diff --git a/frontend/src/app/docs/api-docs/api-docs.component.ts b/frontend/src/app/docs/api-docs/api-docs.component.ts index 0bffd5b2a..1d5eec453 100644 --- a/frontend/src/app/docs/api-docs/api-docs.component.ts +++ b/frontend/src/app/docs/api-docs/api-docs.component.ts @@ -28,6 +28,7 @@ export class ApiDocsComponent implements OnInit, AfterViewInit { wsDocs: any; screenWidth: number; officialMempoolInstance: boolean; + auditEnabled: boolean; @ViewChildren(FaqTemplateDirective) faqTemplates: QueryList; dict = {}; @@ -60,6 +61,7 @@ export class ApiDocsComponent implements OnInit, AfterViewInit { ngOnInit(): void { this.env = this.stateService.env; this.officialMempoolInstance = this.env.OFFICIAL_MEMPOOL_SPACE; + this.auditEnabled = this.env.AUDIT; this.network$ = merge(of(''), this.stateService.networkChanged$).pipe( tap((network: string) => { if (this.env.BASE_MODULE === 'mempool' && network !== '') { From 774f7630ce9cb29327c9aac192b53aed0b38586d Mon Sep 17 00:00:00 2001 From: hunicus <93150691+hunicus@users.noreply.github.com> Date: Wed, 15 Feb 2023 00:56:02 -0500 Subject: [PATCH 13/17] Remove colon from block overview table --- frontend/src/app/components/block/block.component.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frontend/src/app/components/block/block.component.html b/frontend/src/app/components/block/block.component.html index 7e30d4bbf..0fda470d6 100644 --- a/frontend/src/app/components/block/block.component.html +++ b/frontend/src/app/components/block/block.component.html @@ -143,7 +143,7 @@ - Subsidy + fees: + Subsidy + fees @@ -158,7 +158,7 @@ - Subsidy + fees: + Subsidy + fees From 3beb85dd4a217008ea1c8bcc3d640708a6b918d8 Mon Sep 17 00:00:00 2001 From: nymkappa <1612910616@pm.me> Date: Wed, 15 Feb 2023 16:41:09 +0900 Subject: [PATCH 14/17] Add footer to all dashboards --- .../mining-dashboard.component.html | 20 +++++++++++++++++++ .../mining-dashboard.component.scss | 19 ++++++++++++++++++ .../lightning-dashboard.component.html | 18 +++++++++++++++-- .../lightning-dashboard.component.scss | 19 ++++++++++++++++++ 4 files changed, 74 insertions(+), 2 deletions(-) diff --git a/frontend/src/app/components/mining-dashboard/mining-dashboard.component.html b/frontend/src/app/components/mining-dashboard/mining-dashboard.component.html index 36aec8906..1a932567c 100644 --- a/frontend/src/app/components/mining-dashboard/mining-dashboard.component.html +++ b/frontend/src/app/components/mining-dashboard/mining-dashboard.component.html @@ -74,4 +74,24 @@
+ +
+
+ +
+
+ +
+
+ + + +
+
diff --git a/frontend/src/app/components/mining-dashboard/mining-dashboard.component.scss b/frontend/src/app/components/mining-dashboard/mining-dashboard.component.scss index 303591974..218b8e04d 100644 --- a/frontend/src/app/components/mining-dashboard/mining-dashboard.component.scss +++ b/frontend/src/app/components/mining-dashboard/mining-dashboard.component.scss @@ -103,4 +103,23 @@ margin-bottom: 10px; text-decoration: none; color: inherit; +} + +.terms-of-service { + margin-top: 1rem; +} + +.pref-selectors { + display: flex; + flex-direction: row; + flex-wrap: wrap; + justify-content: center; + + .selector { + margin-left: .5em; + margin-bottom: .5em; + &:first { + margin-left: 0; + } + } } \ No newline at end of file diff --git a/frontend/src/app/lightning/lightning-dashboard/lightning-dashboard.component.html b/frontend/src/app/lightning/lightning-dashboard/lightning-dashboard.component.html index a371f474d..030019b3c 100644 --- a/frontend/src/app/lightning/lightning-dashboard/lightning-dashboard.component.html +++ b/frontend/src/app/lightning/lightning-dashboard/lightning-dashboard.component.html @@ -84,8 +84,22 @@
-
- Connect to our nodes +
+
+ +
+
+ +
+
+ +
diff --git a/frontend/src/app/lightning/lightning-dashboard/lightning-dashboard.component.scss b/frontend/src/app/lightning/lightning-dashboard/lightning-dashboard.component.scss index 303591974..218b8e04d 100644 --- a/frontend/src/app/lightning/lightning-dashboard/lightning-dashboard.component.scss +++ b/frontend/src/app/lightning/lightning-dashboard/lightning-dashboard.component.scss @@ -103,4 +103,23 @@ margin-bottom: 10px; text-decoration: none; color: inherit; +} + +.terms-of-service { + margin-top: 1rem; +} + +.pref-selectors { + display: flex; + flex-direction: row; + flex-wrap: wrap; + justify-content: center; + + .selector { + margin-left: .5em; + margin-bottom: .5em; + &:first { + margin-left: 0; + } + } } \ No newline at end of file From 5e10b75b87d43da71031718da9708f5ce0e2ef9c Mon Sep 17 00:00:00 2001 From: nymkappa <1612910616@pm.me> Date: Wed, 15 Feb 2023 17:33:30 +0900 Subject: [PATCH 15/17] Fix lightning dashboard btc/fiat UI issue --- .../channels-statistics/channels-statistics.component.html | 4 ++-- .../lightning/node-statistics/node-statistics.component.html | 5 ++--- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/frontend/src/app/lightning/channels-statistics/channels-statistics.component.html b/frontend/src/app/lightning/channels-statistics/channels-statistics.component.html index bedcc0ded..44e19b8f6 100644 --- a/frontend/src/app/lightning/channels-statistics/channels-statistics.component.html +++ b/frontend/src/app/lightning/channels-statistics/channels-statistics.component.html @@ -17,7 +17,7 @@ sats
- + @@ -63,7 +63,7 @@ sats - + diff --git a/frontend/src/app/lightning/node-statistics/node-statistics.component.html b/frontend/src/app/lightning/node-statistics/node-statistics.component.html index 74c14c8b0..97df1f546 100644 --- a/frontend/src/app/lightning/node-statistics/node-statistics.component.html +++ b/frontend/src/app/lightning/node-statistics/node-statistics.component.html @@ -5,11 +5,10 @@
- +
- - +
From 9734052477dff2e59c04c43b93576a3afb946443 Mon Sep 17 00:00:00 2001 From: nymkappa <1612910616@pm.me> Date: Wed, 15 Feb 2023 17:45:29 +0900 Subject: [PATCH 16/17] Fix database used when database disabled --- backend/src/api/pools-parser.ts | 2 +- backend/src/index.ts | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/backend/src/api/pools-parser.ts b/backend/src/api/pools-parser.ts index c3cc994a2..e37414bbe 100644 --- a/backend/src/api/pools-parser.ts +++ b/backend/src/api/pools-parser.ts @@ -127,7 +127,7 @@ class PoolsParser { if (!equals(JSON.parse(existingPool.addresses), poolObj.addresses) || !equals(JSON.parse(existingPool.regexes), poolObj.regexes)) { finalPoolDataUpdate.push(poolObj); } - } else { + } else if (config.DATABASE.ENABLED) { // Double check that if we're not just renaming a pool (same address same regex) const [poolToRename]: any[] = await DB.query(` SELECT * FROM pools diff --git a/backend/src/index.ts b/backend/src/index.ts index cad675e27..a81275066 100644 --- a/backend/src/index.ts +++ b/backend/src/index.ts @@ -105,7 +105,9 @@ class Server { .use(express.text({ type: ['text/plain', 'application/base64'] })) ; - await priceUpdater.$initializeLatestPriceWithDb(); + if (config.DATABASE.ENABLED) { + await priceUpdater.$initializeLatestPriceWithDb(); + } this.server = http.createServer(this.app); this.wss = new WebSocket.Server({ server: this.server }); From 408b0a23ce992814672d2e127446108c25ee02a9 Mon Sep 17 00:00:00 2001 From: nymkappa <1612910616@pm.me> Date: Wed, 15 Feb 2023 18:06:22 +0900 Subject: [PATCH 17/17] Disable fiat display on pools blocks and ln channel component --- frontend/src/app/components/pool/pool.component.html | 4 ++-- .../lightning/channel/channel-box/channel-box.component.html | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/frontend/src/app/components/pool/pool.component.html b/frontend/src/app/components/pool/pool.component.html index ef907215c..53982ca86 100644 --- a/frontend/src/app/components/pool/pool.component.html +++ b/frontend/src/app/components/pool/pool.component.html @@ -235,10 +235,10 @@ - + - + {{ block.tx_count | number }} diff --git a/frontend/src/app/lightning/channel/channel-box/channel-box.component.html b/frontend/src/app/lightning/channel/channel-box/channel-box.component.html index 9fe9b100b..effe6b891 100644 --- a/frontend/src/app/lightning/channel/channel-box/channel-box.component.html +++ b/frontend/src/app/lightning/channel/channel-box/channel-box.component.html @@ -7,7 +7,7 @@
-
+