diff --git a/backend/src/api/bitcoin/electrum-api.ts b/backend/src/api/bitcoin/electrum-api.ts
index b8bcc90d7..f63516d8a 100644
--- a/backend/src/api/bitcoin/electrum-api.ts
+++ b/backend/src/api/bitcoin/electrum-api.ts
@@ -10,6 +10,7 @@ import logger from '../../logger';
import * as ElectrumClient from '@mempool/electrum-client';
import * as sha256 from 'crypto-js/sha256';
import * as hexEnc from 'crypto-js/enc-hex';
+import loadingIndicators from '../loading-indicators';
class BitcoindElectrsApi extends BitcoinApi implements AbstractBitcoinApi {
private electrumClient: any;
@@ -121,6 +122,8 @@ class BitcoindElectrsApi extends BitcoinApi implements AbstractBitcoinApi {
}
try {
+ loadingIndicators.setProgress('address-' + address, 0);
+
const transactions: IEsploraApi.Transaction[] = [];
const history = await this.$getScriptHashHistory(addressInfo.scriptPubKey);
history.reverse();
@@ -132,16 +135,17 @@ class BitcoindElectrsApi extends BitcoinApi implements AbstractBitcoinApi {
startingIndex = pos + 1;
}
}
+ const endIndex = Math.min(startingIndex + 10, history.length);
- for (let i = startingIndex; i < Math.min(startingIndex + 10, history.length); i++) {
+ for (let i = startingIndex; i < endIndex; i++) {
const tx = await this.$getRawTransaction(history[i].tx_hash, false, true);
- if (tx) {
- transactions.push(tx);
- }
+ transactions.push(tx);
+ loadingIndicators.setProgress('address-' + address, (i + 1) / endIndex * 100);
}
return transactions;
} catch (e) {
+ loadingIndicators.setProgress('address-' + address, 100);
if (e === 'failed to get confirmed status') {
e = 'The number of transactions on this address exceeds the Electrum server limit';
}
diff --git a/backend/src/routes.ts b/backend/src/routes.ts
index d770aea8d..390d11ddd 100644
--- a/backend/src/routes.ts
+++ b/backend/src/routes.ts
@@ -16,6 +16,7 @@ import logger from './logger';
import bitcoinApi from './api/bitcoin/bitcoin-api-factory';
import transactionUtils from './api/transaction-utils';
import blocks from './api/blocks';
+import loadingIndicators from './api/loading-indicators';
class Routes {
private cache: { [date: string]: OptimizedStatistic[] } = {
@@ -553,6 +554,8 @@ class Routes {
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();
@@ -576,28 +579,35 @@ class Routes {
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.message || e);
}
}
public async getBlockTransactions(req: Request, res: Response) {
try {
+ loadingIndicators.setProgress('blocktxs-' + req.params.hash, 0);
+
const txIds = await bitcoinApi.$getTxIdsForBlock(req.params.hash);
const transactions: TransactionExtended[] = [];
const startingIndex = Math.max(0, parseInt(req.params.index, 10));
- for (let i = startingIndex; i < Math.min(startingIndex + 10, txIds.length); i++) {
+ const endIndex = Math.min(startingIndex + 10, txIds.length);
+ for (let i = startingIndex; i < endIndex; i++) {
const transaction = await transactionUtils.$getTransactionExtended(txIds[i], false, true);
if (transaction) {
transactions.push(transaction);
+ loadingIndicators.setProgress('blocktxs-' + req.params.hash, (i + 1) / endIndex * 100);
}
}
res.json(transactions);
} catch (e) {
+ loadingIndicators.setProgress('blocktxs-' + req.params.hash, 100);
res.status(500).send(e.message || e);
}
}
diff --git a/frontend/src/app/components/address/address.component.html b/frontend/src/app/components/address/address.component.html
index e5a0ffd0a..49280f471 100644
--- a/frontend/src/app/components/address/address.component.html
+++ b/frontend/src/app/components/address/address.component.html
@@ -67,6 +67,14 @@
+
+
+
+
+
+
diff --git a/frontend/src/app/components/address/address.component.ts b/frontend/src/app/components/address/address.component.ts
index f1d21d3b9..601d422d6 100644
--- a/frontend/src/app/components/address/address.component.ts
+++ b/frontend/src/app/components/address/address.component.ts
@@ -1,13 +1,13 @@
import { Component, OnInit, OnDestroy } from '@angular/core';
import { ActivatedRoute, ParamMap } from '@angular/router';
import { ElectrsApiService } from '../../services/electrs-api.service';
-import { switchMap, filter, catchError } from 'rxjs/operators';
+import { switchMap, filter, catchError, map, tap } from 'rxjs/operators';
import { Address, Transaction } from '../../interfaces/electrs.interface';
import { WebsocketService } from 'src/app/services/websocket.service';
import { StateService } from 'src/app/services/state.service';
import { AudioService } from 'src/app/services/audio.service';
import { ApiService } from 'src/app/services/api.service';
-import { of, merge, Subscription } from 'rxjs';
+import { of, merge, Subscription, Observable } from 'rxjs';
import { SeoService } from 'src/app/services/seo.service';
@Component({
@@ -25,6 +25,7 @@ export class AddressComponent implements OnInit, OnDestroy {
isLoadingTransactions = true;
error: any;
mainSubscription: Subscription;
+ addressLoadingStatus$: Observable;
totalConfirmedTxCount = 0;
loadedConfirmedTxCount = 0;
@@ -48,7 +49,13 @@ export class AddressComponent implements OnInit, OnDestroy {
ngOnInit() {
this.stateService.networkChanged$.subscribe((network) => this.network = network);
- this.websocketService.want(['blocks', 'mempool-blocks']);
+ this.websocketService.want(['blocks']);
+
+ this.addressLoadingStatus$ = this.route.paramMap
+ .pipe(
+ switchMap(() => this.stateService.loadingIndicators$),
+ map((indicators) => indicators['address-' + this.addressString] !== undefined ? indicators['address-' + this.addressString] : 0)
+ );
this.mainSubscription = this.route.paramMap
.pipe(
diff --git a/frontend/src/app/components/block/block.component.html b/frontend/src/app/components/block/block.component.html
index 8b0f852c9..85daa10bd 100644
--- a/frontend/src/app/components/block/block.component.html
+++ b/frontend/src/app/components/block/block.component.html
@@ -112,6 +112,13 @@
+
+
+
+
+
diff --git a/frontend/src/app/components/block/block.component.ts b/frontend/src/app/components/block/block.component.ts
index 3c9b3bf08..99b66de77 100644
--- a/frontend/src/app/components/block/block.component.ts
+++ b/frontend/src/app/components/block/block.component.ts
@@ -2,9 +2,9 @@ import { Component, OnInit, OnDestroy } from '@angular/core';
import { Location } from '@angular/common';
import { ActivatedRoute, ParamMap, Router } from '@angular/router';
import { ElectrsApiService } from '../../services/electrs-api.service';
-import { switchMap, tap, debounceTime, catchError } from 'rxjs/operators';
+import { switchMap, tap, debounceTime, catchError, map } from 'rxjs/operators';
import { Block, Transaction, Vout } from '../../interfaces/electrs.interface';
-import { of, Subscription } from 'rxjs';
+import { Observable, of, Subscription } from 'rxjs';
import { StateService } from '../../services/state.service';
import { SeoService } from 'src/app/services/seo.service';
import { WebsocketService } from 'src/app/services/websocket.service';
@@ -31,6 +31,7 @@ export class BlockComponent implements OnInit, OnDestroy {
coinbaseTx: Transaction;
page = 1;
itemsPerPage: number;
+ txsLoadingStatus$: Observable;
constructor(
private route: ActivatedRoute,
@@ -48,6 +49,12 @@ export class BlockComponent implements OnInit, OnDestroy {
this.network = this.stateService.network;
this.itemsPerPage = this.stateService.env.ELECTRS_ITEMS_PER_PAGE;
+ this.txsLoadingStatus$ = this.route.paramMap
+ .pipe(
+ switchMap(() => this.stateService.loadingIndicators$),
+ map((indicators) => indicators['blocktxs-' + this.blockHash] !== undefined ? indicators['blocktxs-' + this.blockHash] : 0)
+ );
+
this.subscription = this.route.paramMap
.pipe(
switchMap((params: ParamMap) => {
diff --git a/frontend/src/app/components/latest-blocks/latest-blocks.component.html b/frontend/src/app/components/latest-blocks/latest-blocks.component.html
index 5c8853158..882442ec4 100644
--- a/frontend/src/app/components/latest-blocks/latest-blocks.component.html
+++ b/frontend/src/app/components/latest-blocks/latest-blocks.component.html
@@ -33,7 +33,16 @@
|
|
-
+
+
+
+
+ |
+
+
+
diff --git a/frontend/src/app/components/latest-blocks/latest-blocks.component.ts b/frontend/src/app/components/latest-blocks/latest-blocks.component.ts
index ccc898355..eb8b8236d 100644
--- a/frontend/src/app/components/latest-blocks/latest-blocks.component.ts
+++ b/frontend/src/app/components/latest-blocks/latest-blocks.component.ts
@@ -5,6 +5,7 @@ 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',
@@ -19,6 +20,7 @@ export class LatestBlocksComponent implements OnInit, OnDestroy {
blockSubscription: Subscription;
isLoading = true;
interval: any;
+ blocksLoadingStatus$: Observable;
latestBlockHeight: number;
@@ -39,6 +41,11 @@ export class LatestBlocksComponent implements OnInit, OnDestroy {
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) {