diff --git a/backend/src/api/blocks.ts b/backend/src/api/blocks.ts index 293862e93..b9b7b3aff 100644 --- a/backend/src/api/blocks.ts +++ b/backend/src/api/blocks.ts @@ -15,6 +15,7 @@ import BitcoinApi from './bitcoin/bitcoin-api'; import { prepareBlock } from '../utils/blocks-utils'; import BlocksRepository from '../repositories/BlocksRepository'; import HashratesRepository from '../repositories/HashratesRepository'; +import indexer from '../indexer'; class Blocks { private blocks: BlockExtended[] = []; @@ -23,9 +24,6 @@ class Blocks { private lastDifficultyAdjustmentTime = 0; private previousDifficultyRetarget = 0; private newBlockCallbacks: ((block: BlockExtended, txIds: string[], transactions: TransactionExtended[]) => void)[] = []; - private blockIndexingStarted = false; - public blockIndexingCompleted = false; - public reindexFlag = false; constructor() { } @@ -197,24 +195,15 @@ class Blocks { * [INDEXING] Index all blocks metadata for the mining dashboard */ public async $generateBlockDatabase() { - if (this.blockIndexingStarted && !this.reindexFlag) { - return; - } - - this.reindexFlag = false; - const blockchainInfo = await bitcoinClient.getBlockchainInfo(); if (blockchainInfo.blocks !== blockchainInfo.headers) { // Wait for node to sync return; } - this.blockIndexingStarted = true; - this.blockIndexingCompleted = false; - try { let currentBlockHeight = blockchainInfo.blocks; - let indexingBlockAmount = config.MEMPOOL.INDEXING_BLOCKS_AMOUNT; + let indexingBlockAmount = Math.min(config.MEMPOOL.INDEXING_BLOCKS_AMOUNT, blockchainInfo.blocks); if (indexingBlockAmount <= -1) { indexingBlockAmount = currentBlockHeight + 1; } @@ -275,14 +264,14 @@ class Blocks { loadingIndicators.setProgress('block-indexing', 100); } catch (e) { logger.err('Block indexing failed. Trying again later. Reason: ' + (e instanceof Error ? e.message : e)); - this.blockIndexingStarted = false; loadingIndicators.setProgress('block-indexing', 100); return; } const chainValid = await BlocksRepository.$validateChain(); - this.reindexFlag = !chainValid; - this.blockIndexingCompleted = chainValid; + if (!chainValid) { + indexer.reindex(); + } } public async $updateBlocks() { @@ -299,6 +288,8 @@ class Blocks { logger.info(`${blockHeightTip - this.currentBlockHeight} blocks since tip. Fast forwarding to the ${config.MEMPOOL.INITIAL_BLOCKS_AMOUNT} recent blocks`); this.currentBlockHeight = blockHeightTip - config.MEMPOOL.INITIAL_BLOCKS_AMOUNT; fastForwarded = true; + logger.info(`Re-indexing skipped blocks and corresponding hashrates data`); + indexer.reindex(); // Make sure to index the skipped blocks #1619 } if (!this.lastDifficultyAdjustmentTime) { @@ -426,10 +417,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/api/mining.ts b/backend/src/api/mining.ts index 81821b6f7..8d11abfa7 100644 --- a/backend/src/api/mining.ts +++ b/backend/src/api/mining.ts @@ -4,15 +4,11 @@ import PoolsRepository from '../repositories/PoolsRepository'; import HashratesRepository from '../repositories/HashratesRepository'; import bitcoinClient from './bitcoin/bitcoin-client'; import logger from '../logger'; -import blocks from './blocks'; import { Common } from './common'; import loadingIndicators from './loading-indicators'; import { escape } from 'mysql2'; class Mining { - hashrateIndexingStarted = false; - weeklyHashrateIndexingStarted = false; - constructor() { } @@ -153,14 +149,9 @@ class Mining { * [INDEXING] Generate weekly mining pool hashrate history */ public async $generatePoolHashrateHistory(): Promise { - if (!blocks.blockIndexingCompleted || this.hashrateIndexingStarted || this.weeklyHashrateIndexingStarted) { - return; - } - const now = new Date(); try { - this.weeklyHashrateIndexingStarted = true; const lastestRunDate = await HashratesRepository.$getLatestRun('last_weekly_hashrates_indexing'); // Run only if: @@ -168,11 +159,9 @@ class Mining { // * we started a new week (around Monday midnight) const runIndexing = lastestRunDate === 0 || now.getUTCDay() === 1 && lastestRunDate !== now.getUTCDate(); if (!runIndexing) { - this.weeklyHashrateIndexingStarted = false; return; } } catch (e) { - this.weeklyHashrateIndexingStarted = false; throw e; } @@ -192,6 +181,7 @@ class Mining { const startedAt = new Date().getTime() / 1000; let timer = new Date().getTime() / 1000; + logger.debug(`Indexing weekly mining pool hashrate`); loadingIndicators.setProgress('weekly-hashrate-indexing', 0); while (toTimestamp > genesisTimestamp) { @@ -256,7 +246,6 @@ class Mining { ++indexedThisRun; ++totalIndexed; } - this.weeklyHashrateIndexingStarted = false; await HashratesRepository.$setLatestRun('last_weekly_hashrates_indexing', new Date().getUTCDate()); if (newlyIndexed > 0) { logger.info(`Indexed ${newlyIndexed} pools weekly hashrate`); @@ -264,7 +253,6 @@ class Mining { loadingIndicators.setProgress('weekly-hashrate-indexing', 100); } catch (e) { loadingIndicators.setProgress('weekly-hashrate-indexing', 100); - this.weeklyHashrateIndexingStarted = false; throw e; } } @@ -273,22 +261,14 @@ class Mining { * [INDEXING] Generate daily hashrate data */ public async $generateNetworkHashrateHistory(): Promise { - if (!blocks.blockIndexingCompleted || this.hashrateIndexingStarted) { - return; - } - try { - this.hashrateIndexingStarted = true; - // We only run this once a day around midnight const latestRunDate = await HashratesRepository.$getLatestRun('last_hashrates_indexing'); const now = new Date().getUTCDate(); if (now === latestRunDate) { - this.hashrateIndexingStarted = false; return; } } catch (e) { - this.hashrateIndexingStarted = false; throw e; } @@ -306,6 +286,7 @@ class Mining { const startedAt = new Date().getTime() / 1000; let timer = new Date().getTime() / 1000; + logger.debug(`Indexing daily network hashrate`); loadingIndicators.setProgress('daily-hashrate-indexing', 0); while (toTimestamp > genesisTimestamp) { @@ -377,14 +358,12 @@ class Mining { await HashratesRepository.$saveHashrates(hashrates); await HashratesRepository.$setLatestRun('last_hashrates_indexing', new Date().getUTCDate()); - this.hashrateIndexingStarted = false; if (newlyIndexed > 0) { logger.info(`Indexed ${newlyIndexed} day of network hashrate`); } loadingIndicators.setProgress('daily-hashrate-indexing', 100); } catch (e) { loadingIndicators.setProgress('daily-hashrate-indexing', 100); - this.hashrateIndexingStarted = false; throw e; } } diff --git a/backend/src/index.ts b/backend/src/index.ts index c6eab6c17..30c5ecf37 100644 --- a/backend/src/index.ts +++ b/backend/src/index.ts @@ -27,8 +27,8 @@ 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'; +import indexer from './indexer'; class Server { private wss: WebSocket.Server | undefined; @@ -99,7 +99,7 @@ class Server { } await databaseMigration.$initializeOrMigrateDatabase(); if (Common.indexingEnabled()) { - await this.$resetHashratesIndexingState(); + await indexer.$resetHashratesIndexingState(); } } catch (e) { throw new Error(e instanceof Error ? e.message : 'Error'); @@ -154,7 +154,7 @@ class Server { await poolsUpdater.updatePoolsJson(); await blocks.$updateBlocks(); await memPool.$updateMempool(); - this.$runIndexingWhenReady(); + indexer.$run(); setTimeout(this.runMainUpdateLoop.bind(this), config.MEMPOOL.POLL_RATE_MS); this.currentBackendRetryInterval = 5; @@ -173,29 +173,6 @@ class Server { } } - async $resetHashratesIndexingState() { - try { - await HashratesRepository.$setLatestRun('last_hashrates_indexing', 0); - await HashratesRepository.$setLatestRun('last_weekly_hashrates_indexing', 0); - } catch (e) { - logger.err(`Cannot reset hashrate indexing timestamps. Reason: ` + (e instanceof Error ? e.message : e)); - } - } - - async $runIndexingWhenReady() { - if (!Common.indexingEnabled() || mempool.hasPriority()) { - return; - } - - try { - await blocks.$generateBlockDatabase(); - await mining.$generateNetworkHashrateHistory(); - await mining.$generatePoolHashrateHistory(); - } catch (e) { - logger.err(`Indexing failed, trying again later. Reason: ` + (e instanceof Error ? e.message : e)); - } - } - setUpWebsocketHandling() { if (this.wss) { websocketHandler.setWebsocketServer(this.wss); @@ -337,8 +314,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.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') { @@ -352,8 +329,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/indexer.ts b/backend/src/indexer.ts new file mode 100644 index 000000000..7ddc2a47f --- /dev/null +++ b/backend/src/indexer.ts @@ -0,0 +1,52 @@ +import { Common } from './api/common'; +import blocks from './api/blocks'; +import mempool from './api/mempool'; +import mining from './api/mining'; +import logger from './logger'; +import HashratesRepository from './repositories/HashratesRepository'; + +class Indexer { + runIndexer = true; + indexerRunning = false; + + constructor() { + } + + public reindex() { + this.runIndexer = true; + } + + public async $run() { + if (!Common.indexingEnabled() || this.runIndexer === false || + this.indexerRunning === true || mempool.hasPriority() + ) { + return; + } + + this.runIndexer = false; + this.indexerRunning = true; + + try { + await blocks.$generateBlockDatabase(); + await this.$resetHashratesIndexingState(); + await mining.$generateNetworkHashrateHistory(); + await mining.$generatePoolHashrateHistory(); + } catch (e) { + this.reindex(); + logger.err(`Indexer failed, trying again later. Reason: ` + (e instanceof Error ? e.message : e)); + } + + this.indexerRunning = false; + } + + async $resetHashratesIndexingState() { + try { + await HashratesRepository.$setLatestRun('last_hashrates_indexing', 0); + await HashratesRepository.$setLatestRun('last_weekly_hashrates_indexing', 0); + } catch (e) { + logger.err(`Cannot reset hashrate indexing timestamps. Reason: ` + (e instanceof Error ? e.message : e)); + } + } +} + +export default new Indexer(); 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/repositories/BlocksRepository.ts b/backend/src/repositories/BlocksRepository.ts index a34f32e83..dcd5b48d1 100644 --- a/backend/src/repositories/BlocksRepository.ts +++ b/backend/src/repositories/BlocksRepository.ts @@ -475,9 +475,9 @@ class BlocksRepository { public async $getHistoricalBlockFees(div: number, interval: string | null): Promise { try { let query = `SELECT - CAST(AVG(height) as INT) as avg_height, + CAST(AVG(height) as INT) as avgHeight, CAST(AVG(UNIX_TIMESTAMP(blockTimestamp)) as INT) as timestamp, - CAST(AVG(fees) as INT) as avg_fees + CAST(AVG(fees) as INT) as avgFees FROM blocks`; if (interval !== null) { @@ -500,9 +500,9 @@ class BlocksRepository { public async $getHistoricalBlockRewards(div: number, interval: string | null): Promise { try { let query = `SELECT - CAST(AVG(height) as INT) as avg_height, + CAST(AVG(height) as INT) as avgHeight, CAST(AVG(UNIX_TIMESTAMP(blockTimestamp)) as INT) as timestamp, - CAST(AVG(reward) as INT) as avg_rewards + CAST(AVG(reward) as INT) as avgRewards FROM blocks`; if (interval !== null) { @@ -525,15 +525,15 @@ class BlocksRepository { public async $getHistoricalBlockFeeRates(div: number, interval: string | null): Promise { try { let query = `SELECT - CAST(AVG(height) as INT) as avg_height, + CAST(AVG(height) as INT) as avgHeight, CAST(AVG(UNIX_TIMESTAMP(blockTimestamp)) as INT) as timestamp, - CAST(AVG(JSON_EXTRACT(fee_span, '$[0]')) as INT) as avg_fee_0, - CAST(AVG(JSON_EXTRACT(fee_span, '$[1]')) as INT) as avg_fee_10, - CAST(AVG(JSON_EXTRACT(fee_span, '$[2]')) as INT) as avg_fee_25, - CAST(AVG(JSON_EXTRACT(fee_span, '$[3]')) as INT) as avg_fee_50, - CAST(AVG(JSON_EXTRACT(fee_span, '$[4]')) as INT) as avg_fee_75, - CAST(AVG(JSON_EXTRACT(fee_span, '$[5]')) as INT) as avg_fee_90, - CAST(AVG(JSON_EXTRACT(fee_span, '$[6]')) as INT) as avg_fee_100 + CAST(AVG(JSON_EXTRACT(fee_span, '$[0]')) as INT) as avgFee_0, + CAST(AVG(JSON_EXTRACT(fee_span, '$[1]')) as INT) as avgFee_10, + CAST(AVG(JSON_EXTRACT(fee_span, '$[2]')) as INT) as avgFee_25, + CAST(AVG(JSON_EXTRACT(fee_span, '$[3]')) as INT) as avgFee_50, + CAST(AVG(JSON_EXTRACT(fee_span, '$[4]')) as INT) as avgFee_75, + CAST(AVG(JSON_EXTRACT(fee_span, '$[5]')) as INT) as avgFee_90, + CAST(AVG(JSON_EXTRACT(fee_span, '$[6]')) as INT) as avgFee_100 FROM blocks`; if (interval !== null) { @@ -556,9 +556,9 @@ class BlocksRepository { public async $getHistoricalBlockSizes(div: number, interval: string | null): Promise { try { let query = `SELECT - CAST(AVG(height) as INT) as avg_height, + CAST(AVG(height) as INT) as avgHeight, CAST(AVG(UNIX_TIMESTAMP(blockTimestamp)) as INT) as timestamp, - CAST(AVG(size) as INT) as avg_size + CAST(AVG(size) as INT) as avgSize FROM blocks`; if (interval !== null) { @@ -581,9 +581,9 @@ class BlocksRepository { public async $getHistoricalBlockWeights(div: number, interval: string | null): Promise { try { let query = `SELECT - CAST(AVG(height) as INT) as avg_height, + CAST(AVG(height) as INT) as avgHeight, CAST(AVG(UNIX_TIMESTAMP(blockTimestamp)) as INT) as timestamp, - CAST(AVG(weight) as INT) as avg_weight + CAST(AVG(weight) as INT) as avgWeight FROM blocks`; if (interval !== null) { diff --git a/backend/src/routes.ts b/backend/src/routes.ts index cf28dd71d..fa298cc22 100644 --- a/backend/src/routes.ts +++ b/backend/src/routes.ts @@ -720,20 +720,22 @@ 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)); + 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 getBlocks(req: Request, res: Response) { + public async getLegacyBlocks(req: Request, res: Response) { try { - loadingIndicators.setProgress('blocks', 0); - const returnBlocks: IEsploraApi.Block[] = []; const fromHeight = parseInt(req.params.height, 10) || blocks.getCurrentBlockHeight(); @@ -757,16 +759,15 @@ class Routes { returnBlocks.push(block); nextHash = block.previousblockhash; } - loadingIndicators.setProgress('blocks', i / 10 * 100); } + res.setHeader('Expires', new Date(Date.now() + 1000 * 60).toUTCString()); 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/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/app-routing.module.ts b/frontend/src/app/app-routing.module.ts index 672d68686..6951accb2 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'; @@ -36,19 +35,20 @@ let routes: Routes = [ component: MasterPageComponent, children: [ { - path: 'tx/push', - component: PushTransactionComponent, + path: 'mining/blocks', + redirectTo: 'blocks', + pathMatch: 'full' }, { - path: 'blocks', - component: LatestBlocksComponent, + path: 'tx/push', + component: PushTransactionComponent, }, { path: 'about', component: AboutComponent, }, { - path: 'mining/blocks', + path: 'blocks', component: BlocksList, }, { @@ -115,6 +115,11 @@ let routes: Routes = [ { path: 'signet', children: [ + { + path: 'mining/blocks', + redirectTo: 'blocks', + pathMatch: 'full' + }, { path: '', pathMatch: 'full', @@ -128,16 +133,12 @@ let routes: Routes = [ path: 'tx/push', component: PushTransactionComponent, }, - { - path: 'blocks', - component: LatestBlocksComponent, - }, { path: 'about', component: AboutComponent, }, { - path: 'mining/blocks', + path: 'blocks', component: BlocksList, }, { @@ -211,19 +212,20 @@ let routes: Routes = [ component: MasterPageComponent, children: [ { - path: 'tx/push', - component: PushTransactionComponent, + path: 'mining/blocks', + redirectTo: 'blocks', + pathMatch: 'full' }, { - path: 'blocks', - component: LatestBlocksComponent, + path: 'tx/push', + component: PushTransactionComponent, }, { path: 'about', component: AboutComponent, }, { - path: 'mining/blocks', + path: 'blocks', component: BlocksList, }, { @@ -321,16 +323,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 +427,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/about/about.component.html b/frontend/src/app/components/about/about.component.html index 27892626c..47489457c 100644 --- a/frontend/src/app/components/about/about.component.html +++ b/frontend/src/app/components/about/about.component.html @@ -250,6 +250,10 @@ Marina + + + Schildbach + diff --git a/frontend/src/app/components/block-fee-rates-graph/block-fee-rates-graph.component.ts b/frontend/src/app/components/block-fee-rates-graph/block-fee-rates-graph.component.ts index 656a00d45..2cd421f26 100644 --- a/frontend/src/app/components/block-fee-rates-graph/block-fee-rates-graph.component.ts +++ b/frontend/src/app/components/block-fee-rates-graph/block-fee-rates-graph.component.ts @@ -89,13 +89,13 @@ export class BlockFeeRatesGraphComponent implements OnInit { }; for (const rate of data.blockFeeRates) { const timestamp = rate.timestamp * 1000; - seriesData['Min'].push([timestamp, rate.avg_fee_0, rate.avg_height]); - seriesData['10th'].push([timestamp, rate.avg_fee_10, rate.avg_height]); - seriesData['25th'].push([timestamp, rate.avg_fee_25, rate.avg_height]); - seriesData['Median'].push([timestamp, rate.avg_fee_50, rate.avg_height]); - seriesData['75th'].push([timestamp, rate.avg_fee_75, rate.avg_height]); - seriesData['90th'].push([timestamp, rate.avg_fee_90, rate.avg_height]); - seriesData['Max'].push([timestamp, rate.avg_fee_100, rate.avg_height]); + seriesData['Min'].push([timestamp, rate.avgFee_0, rate.avgHeight]); + seriesData['10th'].push([timestamp, rate.avgFee_10, rate.avgHeight]); + seriesData['25th'].push([timestamp, rate.avgFee_25, rate.avgHeight]); + seriesData['Median'].push([timestamp, rate.avgFee_50, rate.avgHeight]); + seriesData['75th'].push([timestamp, rate.avgFee_75, rate.avgHeight]); + seriesData['90th'].push([timestamp, rate.avgFee_90, rate.avgHeight]); + seriesData['Max'].push([timestamp, rate.avgFee_100, rate.avgHeight]); } // Prepare chart 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 c938b351f..185938d5d 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 @@ -71,7 +71,7 @@ export class BlockFeesGraphComponent implements OnInit { .pipe( tap((response) => { this.prepareChartOptions({ - blockFees: response.body.map(val => [val.timestamp * 1000, val.avg_fees / 100000000]), + blockFees: response.body.map(val => [val.timestamp * 1000, val.avgFees / 100000000]), }); this.isLoading = false; }), 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 48d7ec10c..24614903c 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 @@ -69,7 +69,7 @@ export class BlockRewardsGraphComponent implements OnInit { .pipe( tap((response) => { this.prepareChartOptions({ - blockRewards: response.body.map(val => [val.timestamp * 1000, val.avg_rewards / 100000000]), + blockRewards: response.body.map(val => [val.timestamp * 1000, val.avgRewards / 100000000]), }); this.isLoading = false; }), diff --git a/frontend/src/app/components/block-sizes-weights-graph/block-sizes-weights-graph.component.ts b/frontend/src/app/components/block-sizes-weights-graph/block-sizes-weights-graph.component.ts index 7c72b42ef..3255fc4af 100644 --- a/frontend/src/app/components/block-sizes-weights-graph/block-sizes-weights-graph.component.ts +++ b/frontend/src/app/components/block-sizes-weights-graph/block-sizes-weights-graph.component.ts @@ -83,8 +83,8 @@ export class BlockSizesWeightsGraphComponent implements OnInit { tap((response) => { const data = response.body; this.prepareChartOptions({ - sizes: data.sizes.map(val => [val.timestamp * 1000, val.avg_size / 1000000, val.avg_height]), - weights: data.weights.map(val => [val.timestamp * 1000, val.avg_weight / 1000000, val.avg_height]), + sizes: data.sizes.map(val => [val.timestamp * 1000, val.avgSize / 1000000, val.avgHeight]), + weights: data.weights.map(val => [val.timestamp * 1000, val.avgWeight / 1000000, val.avgHeight]), }); this.isLoading = false; }), 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..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

@@ -8,22 +8,22 @@
- - - - - - - - + + + + + + + + + - - - - - - - - - - - - - - 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..7cca2af62 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)))) ) }) ), @@ -81,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; 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 @@ -
+
HeightPoolTimestampMinedRewardFeesTXsSizeHeightPoolTimestampMinedRewardFeesTXsTransactionsSize
- {{ block.height - }} + {{ block.height }} + + + + + {{ block.tx_count | number }} +
@@ -60,29 +60,29 @@
+ + + + + + + +
diff --git a/frontend/src/app/components/graphs/graphs.component.html b/frontend/src/app/components/graphs/graphs.component.html index 6c59645ea..b02adae5e 100644 --- a/frontend/src/app/components/graphs/graphs.component.html +++ b/frontend/src/app/components/graphs/graphs.component.html @@ -1,7 +1,7 @@ -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
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/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 @@
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 @@ - + diff --git a/frontend/src/app/dashboard/dashboard.component.scss b/frontend/src/app/dashboard/dashboard.component.scss index 47fb5b757..e6ddb5f84 100644 --- a/frontend/src/app/dashboard/dashboard.component.scss +++ b/frontend/src/app/dashboard/dashboard.component.scss @@ -198,9 +198,7 @@ display: none; text-align: right; width: 20%; - @media (min-width: 376px) { - display: table-cell; - } + display: table-cell; } .table-cell-size { display: none; 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 a9823af5e..fcb60a154 100644 --- a/frontend/src/app/docs/api-docs/api-docs-data.ts +++ b/frontend/src/app/docs/api-docs/api-docs-data.ts @@ -3834,34 +3834,34 @@ export const restApiDocsData = [ curl: [`1w`], response: `[ { - "avg_height": 735644, + "avgHeight": 735644, "timestamp": 1652119111, - "avg_fees": 24212890 + "avgFees": 24212890 }, { - "avg_height": 735646, + "avgHeight": 735646, "timestamp": 1652120252, - "avg_fees": 21655996 + "avgFees": 21655996 }, { - "avg_height": 735648, + "avgHeight": 735648, "timestamp": 1652121214, - "avg_fees": 20678859 + "avgFees": 20678859 }, { - "avg_height": 735649, + "avgHeight": 735649, "timestamp": 1652121757, - "avg_fees": 21020140 + "avgFees": 21020140 }, { - "avg_height": 735650, + "avgHeight": 735650, "timestamp": 1652122367, - "avg_fees": 23064200 + "avgFees": 23064200 }, { - "avg_height": 735652, + "avgHeight": 735652, "timestamp": 1652122893, - "avg_fees": 17620723 + "avgFees": 17620723 }, ... ]` @@ -3872,14 +3872,14 @@ export const restApiDocsData = [ curl: [`1w`], response: `[ { - "avg_height": 2224253, + "avgHeight": 2224253, "timestamp": 1652346420, - "avg_fees": 211686 + "avgFees": 211686 }, { - "avg_height": 2224254, + "avgHeight": 2224254, "timestamp": 1652346850, - "avg_fees": 2565952 + "avgFees": 2565952 }, ... ]` @@ -3890,14 +3890,14 @@ export const restApiDocsData = [ curl: [`1w`], response: `[ { - "avg_height": 89978, + "avgHeight": 89978, "timestamp": 1652346573, - "avg_fees": 1071 + "avgFees": 1071 }, { - "avg_height": 89979, + "avgHeight": 89979, "timestamp": 1652346970, - "avg_fees": 1224 + "avgFees": 1224 }, ... ]` @@ -3933,29 +3933,29 @@ export const restApiDocsData = [ curl: [`1d`], response: `[ { - "avg_height": 599992, + "avgHeight": 599992, "timestamp": 1571438412, - "avg_rewards": 1260530933 + "avgRewards": 1260530933 }, { - "avg_height": 600000, + "avgHeight": 600000, "timestamp": 1571443398, - "avg_rewards": 1264314538 + "avgRewards": 1264314538 }, { - "avg_height": 725441, + "avgHeight": 725441, "timestamp": 1646139035, - "avg_rewards": 637067563 + "avgRewards": 637067563 }, { - "avg_height": 725585, + "avgHeight": 725585, "timestamp": 1646222444, - "avg_rewards": 646519104 + "avgRewards": 646519104 }, { - "avg_height": 725727, + "avgHeight": 725727, "timestamp": 1646308374, - "avg_rewards": 638709605 + "avgRewards": 638709605 }, ... ]` @@ -3966,14 +3966,14 @@ export const restApiDocsData = [ curl: [`1d`], response: `[ { - "avg_height": 12, + "avgHeight": 12, "timestamp": 1296689648, - "avg_rewards": 5000000000 + "avgRewards": 5000000000 }, { - "avg_height": 269, + "avgHeight": 269, "timestamp": 1296717674, - "avg_rewards": 5000091820 + "avgRewards": 5000091820 }, ... ]` @@ -3984,14 +3984,14 @@ export const restApiDocsData = [ curl: [`1d`], response: `[ { - "avg_height": 183, + "avgHeight": 183, "timestamp": 1598962247, - "avg_rewards": 5000000000 + "avgRewards": 5000000000 }, { - "avg_height": 576, + "avgHeight": 576, "timestamp": 1599047892, - "avg_rewards": 5000000000 + "avgRewards": 5000000000 }, ... ]` @@ -4029,37 +4029,37 @@ export const restApiDocsData = [ "oldestIndexedBlockTimestamp": 1571434851, "blockFeeRates": [ { - "avg_height": 732152, + "avgHeight": 732152, "timestamp": 1650132959, - "avg_fee_0": 1, - "avg_fee_10": 2, - "avg_fee_25": 2, - "avg_fee_50": 3, - "avg_fee_75": 4, - "avg_fee_90": 8, - "avg_fee_100": 393 + "avgFee_0": 1, + "avgFee_10": 2, + "avgFee_25": 2, + "avgFee_50": 3, + "avgFee_75": 4, + "avgFee_90": 8, + "avgFee_100": 393 }, { - "avg_height": 732158, + "avgHeight": 732158, "timestamp": 1650134432, - "avg_fee_0": 1, - "avg_fee_10": 1, - "avg_fee_25": 2, - "avg_fee_50": 4, - "avg_fee_75": 6, - "avg_fee_90": 10, - "avg_fee_100": 240 + "avgFee_0": 1, + "avgFee_10": 1, + "avgFee_25": 2, + "avgFee_50": 4, + "avgFee_75": 6, + "avgFee_90": 10, + "avgFee_100": 240 }, { - "avg_height": 732161, + "avgHeight": 732161, "timestamp": 1650135818, - "avg_fee_0": 1, - "avg_fee_10": 1, - "avg_fee_25": 1, - "avg_fee_50": 2, - "avg_fee_75": 5, - "avg_fee_90": 8, - "avg_fee_100": 251 + "avgFee_0": 1, + "avgFee_10": 1, + "avgFee_25": 1, + "avgFee_50": 2, + "avgFee_75": 5, + "avgFee_90": 8, + "avgFee_100": 251 }, ... ] @@ -4073,26 +4073,26 @@ export const restApiDocsData = [ "oldestIndexedBlockTimestamp": 1296688602, "blockFeeRates": [ { - "avg_height": 2196306, + "avgHeight": 2196306, "timestamp": 1650360168, - "avg_fee_0": 1, - "avg_fee_10": 1, - "avg_fee_25": 1, - "avg_fee_50": 1, - "avg_fee_75": 2, - "avg_fee_90": 28, - "avg_fee_100": 2644 + "avgFee_0": 1, + "avgFee_10": 1, + "avgFee_25": 1, + "avgFee_50": 1, + "avgFee_75": 2, + "avgFee_90": 28, + "avgFee_100": 2644 }, { - "avg_height": 2196308, + "avgHeight": 2196308, "timestamp": 1650361209, - "avg_fee_0": 1, - "avg_fee_10": 1, - "avg_fee_25": 1, - "avg_fee_50": 4, - "avg_fee_75": 12, - "avg_fee_90": 65, - "avg_fee_100": 102 + "avgFee_0": 1, + "avgFee_10": 1, + "avgFee_25": 1, + "avgFee_50": 4, + "avgFee_75": 12, + "avgFee_90": 65, + "avgFee_100": 102 }, ... ] @@ -4106,26 +4106,26 @@ export const restApiDocsData = [ "oldestIndexedBlockTimestamp": 1598918400, "blockFeeRates": [ { - "avg_height": 86620, + "avgHeight": 86620, "timestamp": 1650360010, - "avg_fee_0": 1, - "avg_fee_10": 1, - "avg_fee_25": 1, - "avg_fee_50": 1, - "avg_fee_75": 1, - "avg_fee_90": 1, - "avg_fee_100": 1 + "avgFee_0": 1, + "avgFee_10": 1, + "avgFee_25": 1, + "avgFee_50": 1, + "avgFee_75": 1, + "avgFee_90": 1, + "avgFee_100": 1 }, { - "avg_height": 86623, + "avgHeight": 86623, "timestamp": 1650361330, - "avg_fee_0": 1, - "avg_fee_10": 1, - "avg_fee_25": 1, - "avg_fee_50": 1, - "avg_fee_75": 1, - "avg_fee_90": 1, - "avg_fee_100": 1 + "avgFee_0": 1, + "avgFee_10": 1, + "avgFee_25": 1, + "avgFee_50": 1, + "avgFee_75": 1, + "avgFee_90": 1, + "avgFee_100": 1 }, ... ] @@ -4163,47 +4163,47 @@ export const restApiDocsData = [ response: `{ "sizes": [ { - "avg_height": 576650, + "avgHeight": 576650, "timestamp": 1558212081, - "avg_size": 1271404 + "avgSize": 1271404 }, { - "avg_height": 576715, + "avgHeight": 576715, "timestamp": 1558246272, - "avg_size": 1105893 + "avgSize": 1105893 }, { - "avg_height": 576797, + "avgHeight": 576797, "timestamp": 1558289379, - "avg_size": 1141071 + "avgSize": 1141071 }, { - "avg_height": 576885, + "avgHeight": 576885, "timestamp": 1558330184, - "avg_size": 1108166 + "avgSize": 1108166 }, ... ], "weights": [ { - "avg_height": 576650, + "avgHeight": 576650, "timestamp": 1558212081, - "avg_weight": 3994002 + "avgWeight": 3994002 }, { - "avg_height": 576715, + "avgHeight": 576715, "timestamp": 1558246272, - "avg_weight": 3756312 + "avgWeight": 3756312 }, { - "avg_height": 576797, + "avgHeight": 576797, "timestamp": 1558289379, - "avg_weight": 3719625 + "avgWeight": 3719625 }, { - "avg_height": 576885, + "avgHeight": 576885, "timestamp": 1558330184, - "avg_weight": 3631381 + "avgWeight": 3631381 }, ... ] @@ -4216,27 +4216,27 @@ export const restApiDocsData = [ response: `{ "sizes": [ { - "avg_height": 1517188, + "avgHeight": 1517188, "timestamp": 1558262730, - "avg_size": 25089 + "avgSize": 25089 }, { - "avg_height": 1517275, + "avgHeight": 1517275, "timestamp": 1558290933, - "avg_size": 21679 + "avgSize": 21679 }, ... ], "weights": [ { - "avg_height": 1517188, + "avgHeight": 1517188, "timestamp": 1558262730, - "avg_weight": 74921 + "avgWeight": 74921 }, { - "avg_height": 1517275, + "avgHeight": 1517275, "timestamp": 1558290933, - "avg_weight": 65164 + "avgWeight": 65164 }, ... ] @@ -4249,27 +4249,27 @@ export const restApiDocsData = [ response: `{ "sizes": [ { - "avg_height": 83, + "avgHeight": 83, "timestamp": 1598937527, - "avg_size": 329 + "avgSize": 329 }, { - "avg_height": 266, + "avgHeight": 266, "timestamp": 1598982991, - "avg_size": 330 + "avgSize": 330 }, ... ], "weights": [ { - "avg_height": 83, + "avgHeight": 83, "timestamp": 1598937527, - "avg_weight": 1209 + "avgWeight": 1209 }, { - "avg_height": 266, + "avgHeight": 266, "timestamp": 1598982991, - "avg_weight": 1212 + "avgWeight": 1212 }, ... ] 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, diff --git a/frontend/src/resources/profile/schildbach.svg b/frontend/src/resources/profile/schildbach.svg new file mode 100644 index 000000000..976deec88 --- /dev/null +++ b/frontend/src/resources/profile/schildbach.svg @@ -0,0 +1 @@ + \ No newline at end of file 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' \