From 37b7ea6702b27358d319ec8d202f9aec61426505 Mon Sep 17 00:00:00 2001 From: nymkappa Date: Fri, 20 May 2022 18:11:02 +0200 Subject: [PATCH 1/7] Merge legacy and mining /blocks components and APIs --- backend/src/api/blocks.ts | 5 +- backend/src/index.ts | 7 +- backend/src/routes.ts | 41 +---- frontend/src/app/app-routing.module.ts | 31 +--- .../blocks-list/blocks-list.component.html | 31 ++-- .../blocks-list/blocks-list.component.scss | 25 ++++ .../blocks-list/blocks-list.component.ts | 16 +- .../latest-blocks.component.html | 57 ------- .../latest-blocks.component.scss | 14 -- .../latest-blocks/latest-blocks.component.ts | 140 ------------------ frontend/src/app/services/api.service.ts | 2 +- frontend/src/app/shared/shared.module.ts | 3 - 12 files changed, 63 insertions(+), 309 deletions(-) delete mode 100644 frontend/src/app/components/latest-blocks/latest-blocks.component.html delete mode 100644 frontend/src/app/components/latest-blocks/latest-blocks.component.scss delete mode 100644 frontend/src/app/components/latest-blocks/latest-blocks.component.ts diff --git a/backend/src/api/blocks.ts b/backend/src/api/blocks.ts index 293862e93..91db74faa 100644 --- a/backend/src/api/blocks.ts +++ b/backend/src/api/blocks.ts @@ -426,10 +426,7 @@ class Blocks { return blockExtended; } - public async $getBlocksExtras(fromHeight?: number, limit: number = 15): Promise { - // Note - This API is breaking if indexing is not available. For now it is okay because we only - // use it for the mining pages, and mining pages should not be available if indexing is turned off. - // I'll need to fix it before we refactor the block(s) related pages + public async $getBlocks(fromHeight?: number, limit: number = 15): Promise { try { let currentHeight = fromHeight !== undefined ? fromHeight : this.getCurrentBlockHeight(); const returnBlocks: BlockExtended[] = []; diff --git a/backend/src/index.ts b/backend/src/index.ts index c6eab6c17..d195ff157 100644 --- a/backend/src/index.ts +++ b/backend/src/index.ts @@ -27,7 +27,6 @@ import icons from './api/liquid/icons'; import { Common } from './api/common'; import mining from './api/mining'; import HashratesRepository from './repositories/HashratesRepository'; -import BlocksRepository from './repositories/BlocksRepository'; import poolsUpdater from './tasks/pools-updater'; class Server { @@ -337,8 +336,8 @@ class Server { } this.app - .get(config.MEMPOOL.API_URL_PREFIX + 'blocks-extras', routes.getBlocksExtras) - .get(config.MEMPOOL.API_URL_PREFIX + 'blocks-extras/:height', routes.getBlocksExtras) + .get(config.MEMPOOL.API_URL_PREFIX + 'blocks', routes.getBlocks) + .get(config.MEMPOOL.API_URL_PREFIX + 'blocks/:height', routes.getBlocks) .get(config.MEMPOOL.API_URL_PREFIX + 'block/:hash', routes.getBlock); if (config.MEMPOOL.BACKEND !== 'esplora') { @@ -352,8 +351,6 @@ class Server { .get(config.MEMPOOL.API_URL_PREFIX + 'tx/:txId/status', routes.getTransactionStatus) .get(config.MEMPOOL.API_URL_PREFIX + 'tx/:txId/outspends', routes.getTransactionOutspends) .get(config.MEMPOOL.API_URL_PREFIX + 'block/:hash/header', routes.getBlockHeader) - .get(config.MEMPOOL.API_URL_PREFIX + 'blocks', routes.getBlocks) - .get(config.MEMPOOL.API_URL_PREFIX + 'blocks/:height', routes.getBlocks) .get(config.MEMPOOL.API_URL_PREFIX + 'blocks/tip/height', routes.getBlockTipHeight) .get(config.MEMPOOL.API_URL_PREFIX + 'block/:hash/txs', routes.getBlockTransactions) .get(config.MEMPOOL.API_URL_PREFIX + 'block/:hash/txs/:index', routes.getBlockTransactions) diff --git a/backend/src/routes.ts b/backend/src/routes.ts index cf28dd71d..5b762ff27 100644 --- a/backend/src/routes.ts +++ b/backend/src/routes.ts @@ -720,53 +720,16 @@ class Routes { } } - public async getBlocksExtras(req: Request, res: Response) { + public async getBlocks(req: Request, res: Response) { try { const height = req.params.height === undefined ? undefined : parseInt(req.params.height, 10); res.setHeader('Expires', new Date(Date.now() + 1000 * 60).toUTCString()); - res.json(await blocks.$getBlocksExtras(height, 15)); + res.json(await blocks.$getBlocks(height, 15)); } catch (e) { res.status(500).send(e instanceof Error ? e.message : e); } } - public async getBlocks(req: Request, res: Response) { - try { - loadingIndicators.setProgress('blocks', 0); - - const returnBlocks: IEsploraApi.Block[] = []; - const fromHeight = parseInt(req.params.height, 10) || blocks.getCurrentBlockHeight(); - - // Check if block height exist in local cache to skip the hash lookup - const blockByHeight = blocks.getBlocks().find((b) => b.height === fromHeight); - let startFromHash: string | null = null; - if (blockByHeight) { - startFromHash = blockByHeight.id; - } else { - startFromHash = await bitcoinApi.$getBlockHash(fromHeight); - } - - let nextHash = startFromHash; - for (let i = 0; i < 10 && nextHash; i++) { - const localBlock = blocks.getBlocks().find((b) => b.id === nextHash); - if (localBlock) { - returnBlocks.push(localBlock); - nextHash = localBlock.previousblockhash; - } else { - const block = await bitcoinApi.$getBlock(nextHash); - returnBlocks.push(block); - nextHash = block.previousblockhash; - } - loadingIndicators.setProgress('blocks', i / 10 * 100); - } - - res.json(returnBlocks); - } catch (e) { - loadingIndicators.setProgress('blocks', 100); - res.status(500).send(e instanceof Error ? e.message : e); - } - } - public async getBlockTransactions(req: Request, res: Response) { try { loadingIndicators.setProgress('blocktxs-' + req.params.hash, 0); diff --git a/frontend/src/app/app-routing.module.ts b/frontend/src/app/app-routing.module.ts index 672d68686..5f1124031 100644 --- a/frontend/src/app/app-routing.module.ts +++ b/frontend/src/app/app-routing.module.ts @@ -7,7 +7,6 @@ import { AddressComponent } from './components/address/address.component'; import { MasterPageComponent } from './components/master-page/master-page.component'; import { AboutComponent } from './components/about/about.component'; import { StatusViewComponent } from './components/status-view/status-view.component'; -import { LatestBlocksComponent } from './components/latest-blocks/latest-blocks.component'; import { TermsOfServiceComponent } from './components/terms-of-service/terms-of-service.component'; import { PrivacyPolicyComponent } from './components/privacy-policy/privacy-policy.component'; import { TrademarkPolicyComponent } from './components/trademark-policy/trademark-policy.component'; @@ -39,16 +38,12 @@ let routes: Routes = [ path: 'tx/push', component: PushTransactionComponent, }, - { - path: 'blocks', - component: LatestBlocksComponent, - }, { path: 'about', component: AboutComponent, }, { - path: 'mining/blocks', + path: 'blocks', component: BlocksList, }, { @@ -128,16 +123,12 @@ let routes: Routes = [ path: 'tx/push', component: PushTransactionComponent, }, - { - path: 'blocks', - component: LatestBlocksComponent, - }, { path: 'about', component: AboutComponent, }, { - path: 'mining/blocks', + path: 'blocks', component: BlocksList, }, { @@ -214,16 +205,12 @@ let routes: Routes = [ path: 'tx/push', component: PushTransactionComponent, }, - { - path: 'blocks', - component: LatestBlocksComponent, - }, { path: 'about', component: AboutComponent, }, { - path: 'mining/blocks', + path: 'blocks', component: BlocksList, }, { @@ -321,16 +308,12 @@ if (browserWindowEnv && browserWindowEnv.BASE_MODULE === 'liquid') { path: 'tx/push', component: PushTransactionComponent, }, - { - path: 'blocks', - component: LatestBlocksComponent, - }, { path: 'about', component: AboutComponent, }, { - path: 'mining/blocks', + path: 'blocks', component: BlocksList, }, { @@ -429,16 +412,12 @@ if (browserWindowEnv && browserWindowEnv.BASE_MODULE === 'liquid') { path: 'tx/push', component: PushTransactionComponent, }, - { - path: 'blocks', - component: LatestBlocksComponent, - }, { path: 'about', component: AboutComponent, }, { - path: 'mining/blocks', + path: 'blocks', component: BlocksList, }, { 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 face9452b..d5c8c2ef9 100644 --- a/frontend/src/app/components/blocks-list/blocks-list.component.html +++ b/frontend/src/app/components/blocks-list/blocks-list.component.html @@ -1,6 +1,6 @@ -
+

Blocks

@@ -8,14 +8,15 @@
- - - - - - - - + + + + + + + + + @@ -23,7 +24,7 @@ {{ block.height }} - - - - - -
HeightPoolTimestampMinedRewardFeesTXsSizeHeightPoolTimestampMinedRewardFeesTXsTransactionsSize
+ + + + + {{ block.tx_count | number }} +
diff --git a/frontend/src/app/components/blocks-list/blocks-list.component.scss b/frontend/src/app/components/blocks-list/blocks-list.component.scss index ead712be0..cea30e126 100644 --- a/frontend/src/app/components/blocks-list/blocks-list.component.scss +++ b/frontend/src/app/components/blocks-list/blocks-list.component.scss @@ -6,6 +6,9 @@ padding-left: 0px; padding-bottom: 0px; } +.container-xl.legacy { + max-width: 1140px; +} .container { max-width: 100%; @@ -58,6 +61,9 @@ tr, td, th { width: 10%; } } +.height.legacy { + width: 15%; +} .timestamp { width: 18%; @@ -65,6 +71,9 @@ tr, td, th { display: none; } } +.timestamp.legacy { + width: 20%; +} .mined { width: 13%; @@ -72,6 +81,12 @@ tr, td, th { display: none; } } +.mined.legacy { + width: 15%; + @media (max-width: 576px) { + display: table-cell; + } +} .txs { padding-right: 40px; @@ -88,6 +103,10 @@ tr, td, th { display: none; } } +.txs.legacy { + padding-right: 80px; + width: 10%; +} .fees { width: 10%; @@ -126,6 +145,12 @@ tr, td, th { display: none; } } +.size.legacy { + width: 20%; + @media (max-width: 576px) { + display: table-cell; + } +} /* Tooltip text */ .tooltip-custom { 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 b5b66b22b..f1f81d321 100644 --- a/frontend/src/app/components/blocks-list/blocks-list.component.ts +++ b/frontend/src/app/components/blocks-list/blocks-list.component.ts @@ -17,6 +17,7 @@ export class BlocksList implements OnInit { blocks$: Observable = undefined; + indexingAvailable = false; isLoading = true; fromBlockHeight = undefined; paginationMaxSize: number; @@ -35,6 +36,9 @@ export class BlocksList implements OnInit { } ngOnInit(): void { + this.indexingAvailable = (this.stateService.env.BASE_MODULE === 'mempool' && + this.stateService.env.MINING_DASHBOARD === true); + if (!this.widget) { this.websocketService.want(['blocks']); } @@ -55,17 +59,19 @@ export class BlocksList implements OnInit { this.isLoading = false; }), map(blocks => { - for (const block of blocks) { - // @ts-ignore: Need to add an extra field for the template - block.extras.pool.logo = `./resources/mining-pools/` + - block.extras.pool.name.toLowerCase().replace(' ', '').replace('.', '') + '.svg'; + if (this.indexingAvailable) { + for (const block of blocks) { + // @ts-ignore: Need to add an extra field for the template + block.extras.pool.logo = `./resources/mining-pools/` + + block.extras.pool.name.toLowerCase().replace(' ', '').replace('.', '') + '.svg'; + } } if (this.widget) { return blocks.slice(0, 6); } return blocks; }), - retryWhen(errors => errors.pipe(delayWhen(() => timer(1000)))) + retryWhen(errors => errors.pipe(delayWhen(() => timer(10000)))) ) }) ), diff --git a/frontend/src/app/components/latest-blocks/latest-blocks.component.html b/frontend/src/app/components/latest-blocks/latest-blocks.component.html deleted file mode 100644 index 297d62f48..000000000 --- a/frontend/src/app/components/latest-blocks/latest-blocks.component.html +++ /dev/null @@ -1,57 +0,0 @@ -
-

Blocks

-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
HeightTimestampMinedTransactionsSize
{{ block.height }}‎{{ block.timestamp * 1000 | date:'yyyy-MM-dd HH:mm' }}{{ block.tx_count | number }} -
-
-
-
-
-
-
-
-
- - -
- Error loading blocks -
- {{ error.error }} -
-
- -
diff --git a/frontend/src/app/components/latest-blocks/latest-blocks.component.scss b/frontend/src/app/components/latest-blocks/latest-blocks.component.scss deleted file mode 100644 index 0f2246c99..000000000 --- a/frontend/src/app/components/latest-blocks/latest-blocks.component.scss +++ /dev/null @@ -1,14 +0,0 @@ -.progress { - background-color: #2d3348; -} - -@media (min-width: 768px) { - .d-md-block { - display: table-cell !important; - } -} -@media (min-width: 992px) { - .d-lg-block { - display: table-cell !important; - } -} diff --git a/frontend/src/app/components/latest-blocks/latest-blocks.component.ts b/frontend/src/app/components/latest-blocks/latest-blocks.component.ts deleted file mode 100644 index 3d4ae91ad..000000000 --- a/frontend/src/app/components/latest-blocks/latest-blocks.component.ts +++ /dev/null @@ -1,140 +0,0 @@ -import { Component, OnInit, OnDestroy, ChangeDetectionStrategy, ChangeDetectorRef } from '@angular/core'; -import { ElectrsApiService } from '../../services/electrs-api.service'; -import { StateService } from '../../services/state.service'; -import { Block } from '../../interfaces/electrs.interface'; -import { Subscription, Observable, merge, of } from 'rxjs'; -import { SeoService } from '../../services/seo.service'; -import { WebsocketService } from 'src/app/services/websocket.service'; -import { map } from 'rxjs/operators'; - -@Component({ - selector: 'app-latest-blocks', - templateUrl: './latest-blocks.component.html', - styleUrls: ['./latest-blocks.component.scss'], - changeDetection: ChangeDetectionStrategy.OnPush -}) -export class LatestBlocksComponent implements OnInit, OnDestroy { - network$: Observable; - error: any; - blocks: any[] = []; - blockSubscription: Subscription; - isLoading = true; - interval: any; - blocksLoadingStatus$: Observable; - - latestBlockHeight: number; - - heightOfPageUntilBlocks = 150; - heightOfBlocksTableChunk = 470; - - constructor( - private electrsApiService: ElectrsApiService, - public stateService: StateService, - private seoService: SeoService, - private websocketService: WebsocketService, - private cd: ChangeDetectorRef, - ) { } - - ngOnInit() { - this.seoService.setTitle($localize`:@@8a7b4bd44c0ac71b2e72de0398b303257f7d2f54:Blocks`); - this.websocketService.want(['blocks']); - - this.network$ = merge(of(''), this.stateService.networkChanged$); - - this.blocksLoadingStatus$ = this.stateService.loadingIndicators$ - .pipe( - map((indicators) => indicators['blocks'] !== undefined ? indicators['blocks'] : 0) - ); - - this.blockSubscription = this.stateService.blocks$ - .subscribe(([block]) => { - if (block === null || !this.blocks.length) { - return; - } - - this.latestBlockHeight = block.height; - - if (block.height === this.blocks[0].height) { - return; - } - - // If we are out of sync, reload the blocks instead - if (block.height > this.blocks[0].height + 1) { - this.loadInitialBlocks(); - return; - } - - if (block.height <= this.blocks[0].height) { - return; - } - - this.blocks.pop(); - this.blocks.unshift(block); - this.cd.markForCheck(); - }); - - this.loadInitialBlocks(); - } - - ngOnDestroy() { - clearInterval(this.interval); - this.blockSubscription.unsubscribe(); - } - - loadInitialBlocks() { - this.electrsApiService.listBlocks$() - .subscribe((blocks) => { - this.blocks = blocks; - this.isLoading = false; - this.error = undefined; - - this.latestBlockHeight = blocks[0].height; - - const spaceForBlocks = window.innerHeight - this.heightOfPageUntilBlocks; - const chunks = Math.ceil(spaceForBlocks / this.heightOfBlocksTableChunk) - 1; - if (chunks > 0) { - this.loadMore(chunks); - } - this.cd.markForCheck(); - }, - (error) => { - console.log(error); - this.error = error; - this.isLoading = false; - this.cd.markForCheck(); - }); - } - - loadMore(chunks = 0) { - if (this.isLoading) { - return; - } - const height = this.blocks[this.blocks.length - 1].height - 1; - if (height < 0) { - return; - } - this.isLoading = true; - this.electrsApiService.listBlocks$(height) - .subscribe((blocks) => { - this.blocks = this.blocks.concat(blocks); - this.isLoading = false; - this.error = undefined; - - const chunksLeft = chunks - 1; - if (chunksLeft > 0) { - this.loadMore(chunksLeft); - } - this.cd.markForCheck(); - }, - (error) => { - console.log(error); - this.error = error; - this.isLoading = false; - this.cd.markForCheck(); - }); - } - - trackByBlock(index: number, block: Block) { - return block.height; - } -} diff --git a/frontend/src/app/services/api.service.ts b/frontend/src/app/services/api.service.ts index 8ef656013..7a523a7b3 100644 --- a/frontend/src/app/services/api.service.ts +++ b/frontend/src/app/services/api.service.ts @@ -149,7 +149,7 @@ export class ApiService { getBlocks$(from: number): Observable { return this.httpClient.get( - this.apiBaseUrl + this.apiBasePath + `/api/v1/blocks-extras` + + this.apiBaseUrl + this.apiBasePath + `/api/v1/blocks` + (from !== undefined ? `/${from}` : ``) ); } diff --git a/frontend/src/app/shared/shared.module.ts b/frontend/src/app/shared/shared.module.ts index 488131d84..eb0bf5b87 100644 --- a/frontend/src/app/shared/shared.module.ts +++ b/frontend/src/app/shared/shared.module.ts @@ -48,7 +48,6 @@ import { TransactionsListComponent } from '../components/transactions-list/trans import { BlockComponent } from '../components/block/block.component'; import { AddressComponent } from '../components/address/address.component'; import { SearchFormComponent } from '../components/search-form/search-form.component'; -import { LatestBlocksComponent } from '../components/latest-blocks/latest-blocks.component'; import { AddressLabelsComponent } from '../components/address-labels/address-labels.component'; import { FooterComponent } from '../components/footer/footer.component'; import { TimeSpanComponent } from '../components/time-span/time-span.component'; @@ -113,7 +112,6 @@ import { IndexingProgressComponent } from '../components/indexing-progress/index BlockComponent, TransactionsListComponent, AddressComponent, - LatestBlocksComponent, SearchFormComponent, TimeSpanComponent, AddressLabelsComponent, @@ -208,7 +206,6 @@ import { IndexingProgressComponent } from '../components/indexing-progress/index BlockComponent, TransactionsListComponent, AddressComponent, - LatestBlocksComponent, SearchFormComponent, TimeSpanComponent, AddressLabelsComponent, From 8db440f164572247a36898af9a94b3a8b8cbff61 Mon Sep 17 00:00:00 2001 From: nymkappa Date: Fri, 20 May 2022 20:24:55 +0200 Subject: [PATCH 2/7] Update cache warmer --- production/nginx-cache-warmer | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/production/nginx-cache-warmer b/production/nginx-cache-warmer index 165a97860..366a07345 100755 --- a/production/nginx-cache-warmer +++ b/production/nginx-cache-warmer @@ -4,6 +4,7 @@ slugs=(`curl -sSL https://raw.githubusercontent.com/mempool/mining-pools/master/ while true do for url in / \ + '/api/v1/blocks' \ '/api/v1/statistics/2h' \ '/api/v1/statistics/24h' \ '/api/v1/statistics/1w' \ @@ -36,7 +37,6 @@ do for url in / \ '/api/v1/mining/hashrate/pools/3y' \ '/api/v1/mining/hashrate/pools/all' \ '/api/v1/mining/reward-stats/144' \ - '/api/v1/mining/blocks-extras' \ '/api/v1/mining/blocks/fees/24h' \ '/api/v1/mining/blocks/fees/3d' \ '/api/v1/mining/blocks/fees/1w' \ From ffcfa4a659fc41b961d2ed4f31ad9d50245bfb83 Mon Sep 17 00:00:00 2001 From: nymkappa Date: Sat, 21 May 2022 08:47:49 +0200 Subject: [PATCH 3/7] Setup redirect from /mining/blocks to /blocks - Update router links --- frontend/src/app/app-routing.module.ts | 15 +++++++++++++++ .../mining-dashboard.component.html | 2 +- .../src/app/dashboard/dashboard.component.html | 2 +- 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/frontend/src/app/app-routing.module.ts b/frontend/src/app/app-routing.module.ts index 5f1124031..6951accb2 100644 --- a/frontend/src/app/app-routing.module.ts +++ b/frontend/src/app/app-routing.module.ts @@ -34,6 +34,11 @@ let routes: Routes = [ path: '', component: MasterPageComponent, children: [ + { + path: 'mining/blocks', + redirectTo: 'blocks', + pathMatch: 'full' + }, { path: 'tx/push', component: PushTransactionComponent, @@ -110,6 +115,11 @@ let routes: Routes = [ { path: 'signet', children: [ + { + path: 'mining/blocks', + redirectTo: 'blocks', + pathMatch: 'full' + }, { path: '', pathMatch: 'full', @@ -201,6 +211,11 @@ let routes: Routes = [ path: '', component: MasterPageComponent, children: [ + { + path: 'mining/blocks', + redirectTo: 'blocks', + pathMatch: 'full' + }, { path: 'tx/push', component: PushTransactionComponent, 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 6a208e5c7..fe7c08ba2 100644 --- a/frontend/src/app/components/mining-dashboard/mining-dashboard.component.html +++ b/frontend/src/app/components/mining-dashboard/mining-dashboard.component.html @@ -51,7 +51,7 @@
Latest blocks
- +
diff --git a/frontend/src/app/dashboard/dashboard.component.html b/frontend/src/app/dashboard/dashboard.component.html index 2ab42a6a0..d26b6660a 100644 --- a/frontend/src/app/dashboard/dashboard.component.html +++ b/frontend/src/app/dashboard/dashboard.component.html @@ -136,7 +136,7 @@
- +
From 2da7ec2519a72cdc55979fb551a6515a2bf88b30 Mon Sep 17 00:00:00 2001 From: nymkappa Date: Sat, 21 May 2022 08:51:36 +0200 Subject: [PATCH 4/7] Use ngClass to avoid multiple [class] conflict --- .../blocks-list/blocks-list.component.html | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) 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 d5c8c2ef9..c7c16d1f2 100644 --- a/frontend/src/app/components/blocks-list/blocks-list.component.html +++ b/frontend/src/app/components/blocks-list/blocks-list.component.html @@ -8,14 +8,14 @@
- - + + - + - - + + @@ -24,7 +24,7 @@ {{ block.height }} - - - - - - - - - - - From 88fba3f5064e0488da5bdbdbbc1d5e9e0ec67378 Mon Sep 17 00:00:00 2001 From: nymkappa Date: Mon, 23 May 2022 13:02:18 +0200 Subject: [PATCH 6/7] For non Bitcoin network, run legacy API code, but keep the same endpoint --- backend/src/index.ts | 4 +- backend/src/mempool.interfaces.ts | 2 +- backend/src/routes.ts | 44 +++++++++++++++++-- backend/src/utils/blocks-utils.ts | 2 +- .../blocks-list/blocks-list.component.ts | 8 ++-- 5 files changed, 50 insertions(+), 10 deletions(-) diff --git a/backend/src/index.ts b/backend/src/index.ts index d195ff157..09d8f7669 100644 --- a/backend/src/index.ts +++ b/backend/src/index.ts @@ -336,8 +336,8 @@ class Server { } this.app - .get(config.MEMPOOL.API_URL_PREFIX + 'blocks', routes.getBlocks) - .get(config.MEMPOOL.API_URL_PREFIX + 'blocks/:height', routes.getBlocks) + .get(config.MEMPOOL.API_URL_PREFIX + 'blocks', routes.getBlocks.bind(routes)) + .get(config.MEMPOOL.API_URL_PREFIX + 'blocks/:height', routes.getBlocks.bind(routes)) .get(config.MEMPOOL.API_URL_PREFIX + 'block/:hash', routes.getBlock); if (config.MEMPOOL.BACKEND !== 'esplora') { diff --git a/backend/src/mempool.interfaces.ts b/backend/src/mempool.interfaces.ts index 0081bd34f..60b07da1b 100644 --- a/backend/src/mempool.interfaces.ts +++ b/backend/src/mempool.interfaces.ts @@ -81,7 +81,7 @@ export interface TransactionStripped { export interface BlockExtension { totalFees?: number; - medianFee?: number; // Actually the median fee rate that we compute ourself + medianFee?: number; feeRange?: number[]; reward?: number; coinbaseTx?: TransactionMinerInfo; diff --git a/backend/src/routes.ts b/backend/src/routes.ts index 5b762ff27..fa298cc22 100644 --- a/backend/src/routes.ts +++ b/backend/src/routes.ts @@ -722,14 +722,52 @@ class Routes { public async getBlocks(req: Request, res: Response) { try { - const height = req.params.height === undefined ? undefined : parseInt(req.params.height, 10); - res.setHeader('Expires', new Date(Date.now() + 1000 * 60).toUTCString()); - res.json(await blocks.$getBlocks(height, 15)); + if (['mainnet', 'testnet', 'signet', 'regtest'].includes(config.MEMPOOL.NETWORK)) { // Bitcoin + const height = req.params.height === undefined ? undefined : parseInt(req.params.height, 10); + res.setHeader('Expires', new Date(Date.now() + 1000 * 60).toUTCString()); + res.json(await blocks.$getBlocks(height, 15)); + } else { // Liquid, Bisq + return await this.getLegacyBlocks(req, res); + } } catch (e) { res.status(500).send(e instanceof Error ? e.message : e); } } + public async getLegacyBlocks(req: Request, res: Response) { + try { + const returnBlocks: IEsploraApi.Block[] = []; + const fromHeight = parseInt(req.params.height, 10) || blocks.getCurrentBlockHeight(); + + // Check if block height exist in local cache to skip the hash lookup + const blockByHeight = blocks.getBlocks().find((b) => b.height === fromHeight); + let startFromHash: string | null = null; + if (blockByHeight) { + startFromHash = blockByHeight.id; + } else { + startFromHash = await bitcoinApi.$getBlockHash(fromHeight); + } + + let nextHash = startFromHash; + for (let i = 0; i < 10 && nextHash; i++) { + const localBlock = blocks.getBlocks().find((b) => b.id === nextHash); + if (localBlock) { + returnBlocks.push(localBlock); + nextHash = localBlock.previousblockhash; + } else { + const block = await bitcoinApi.$getBlock(nextHash); + returnBlocks.push(block); + nextHash = block.previousblockhash; + } + } + + res.setHeader('Expires', new Date(Date.now() + 1000 * 60).toUTCString()); + res.json(returnBlocks); + } catch (e) { + res.status(500).send(e instanceof Error ? e.message : e); + } + } + public async getBlockTransactions(req: Request, res: Response) { try { loadingIndicators.setProgress('blocktxs-' + req.params.hash, 0); diff --git a/backend/src/utils/blocks-utils.ts b/backend/src/utils/blocks-utils.ts index 8760a08c0..937a37448 100644 --- a/backend/src/utils/blocks-utils.ts +++ b/backend/src/utils/blocks-utils.ts @@ -15,7 +15,7 @@ export function prepareBlock(block: any): BlockExtended { weight: block.weight, previousblockhash: block.previousblockhash, extras: { - coinbaseRaw: block.coinbase_raw ?? block.extras.coinbaseRaw, + coinbaseRaw: block.coinbase_raw ?? block.extras?.coinbaseRaw, medianFee: block.medianFee ?? block.median_fee ?? block.extras?.medianFee, feeRange: block.feeRange ?? block.fee_span, reward: block.reward ?? block?.extras?.reward, 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 f1f81d321..7cca2af62 100644 --- a/frontend/src/app/components/blocks-list/blocks-list.component.ts +++ b/frontend/src/app/components/blocks-list/blocks-list.component.ts @@ -87,9 +87,11 @@ export class BlocksList implements OnInit { return blocks[0]; } this.blocksCount = Math.max(this.blocksCount, blocks[1][0].height) + 1; - // @ts-ignore: Need to add an extra field for the template - blocks[1][0].extras.pool.logo = `./resources/mining-pools/` + - blocks[1][0].extras.pool.name.toLowerCase().replace(' ', '').replace('.', '') + '.svg'; + if (this.stateService.env.MINING_DASHBOARD) { + // @ts-ignore: Need to add an extra field for the template + blocks[1][0].extras.pool.logo = `./resources/mining-pools/` + + blocks[1][0].extras.pool.name.toLowerCase().replace(' ', '').replace('.', '') + '.svg'; + } acc.unshift(blocks[1][0]); acc = acc.slice(0, this.widget ? 6 : 15); return acc; From 584fb47de7c51030e4f9dff856ed5e0feafbade0 Mon Sep 17 00:00:00 2001 From: nymkappa Date: Tue, 24 May 2022 11:19:09 +0200 Subject: [PATCH 7/7] Fix widget size mining dashboard --- .../src/app/components/blocks-list/blocks-list.component.html | 2 +- .../difficulty-adjustments-table.component.html | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) 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 1b10fe1d2..0e0f5d1e1 100644 --- a/frontend/src/app/components/blocks-list/blocks-list.component.html +++ b/frontend/src/app/components/blocks-list/blocks-list.component.html @@ -1,6 +1,6 @@ -
+

Blocks

diff --git a/frontend/src/app/components/difficulty-adjustments-table/difficulty-adjustments-table.component.html b/frontend/src/app/components/difficulty-adjustments-table/difficulty-adjustments-table.component.html index 6e80d828a..5f11c2608 100644 --- a/frontend/src/app/components/difficulty-adjustments-table/difficulty-adjustments-table.component.html +++ b/frontend/src/app/components/difficulty-adjustments-table/difficulty-adjustments-table.component.html @@ -1,4 +1,4 @@ -
+
HeightPoolHeightPool Timestamp MinedRewardReward FeesTXsTransactionsTXsTransactions Size
+ + + {{ block.tx_count | number }} From 8f57272ea0b4e81b0ff42094f6aeb82c805e0094 Mon Sep 17 00:00:00 2001 From: nymkappa Date: Mon, 23 May 2022 12:08:52 +0200 Subject: [PATCH 5/7] Fix /blocks skeleton on Liquid --- .../blocks-list/blocks-list.component.html | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) 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 c7c16d1f2..1b10fe1d2 100644 --- a/frontend/src/app/components/blocks-list/blocks-list.component.html +++ b/frontend/src/app/components/blocks-list/blocks-list.component.html @@ -21,8 +21,7 @@
- {{ block.height - }} + {{ block.height }}
@@ -61,29 +60,29 @@
+ + + + + + + +