New base code for mempool blockchain explorerer

This commit is contained in:
Simon Lindh
2020-02-16 22:15:07 +07:00
committed by wiz
parent d296239f54
commit 43f41b8aab
204 changed files with 6959 additions and 14341 deletions

View File

@@ -0,0 +1,43 @@
<table class="table table-borderless">
<thead>
<th style="width: 120px;">Height</th>
<th class="d-none d-md-block" style="width: 300px;">Timestamp</th>
<th style="width: 200px;">Mined</th>
<th style="width: 150px;">Transactions</th>
<th style="width: 175px;">Size</th>
<th class="d-none d-md-block">Filled</th>
</thead>
<tbody>
<tr *ngFor="let block of blocks; let i= index; trackBy: trackByBlock">
<td><a [routerLink]="['./block', block.id]" [state]="{ data: { block: block } }">#{{ block.height }}</a></td>
<td class="d-none d-md-block">{{ block.timestamp * 1000 | date:'yyyy-MM-dd HH:mm' }}</td>
<td>{{ block.timestamp | timeSince : trigger }} ago</td>
<td>{{ block.tx_count }}</td>
<td>{{ block.size | bytes: 2 }}</td>
<td class="d-none d-md-block">
<div class="progress position-relative">
<div class="progress-bar bg-success" role="progressbar" [ngStyle]="{'width': (block.weight / 4000000)*100 + '%' }"></div>
</div>
</td>
</tr>
<ng-template [ngIf]="isLoading">
<tr *ngFor="let item of [1,2,3,4,5,6,7,8,9,10]">
<td><span class="skeleton-loader"></span></td>
<td><span class="skeleton-loader"></span></td>
<td><span class="skeleton-loader"></span></td>
<td><span class="skeleton-loader"></span></td>
<td><span class="skeleton-loader"></span></td>
<td><span class="skeleton-loader"></span></td>
</tr>
</ng-template>
</tbody>
</table>
<div class="text-center">
<ng-template [ngIf]="isLoading">
<div class="spinner-border"></div>
<br><br>
</ng-template>
<br>
<button *ngIf="blocks.length" [disabled]="isLoading" type="button" class="btn btn-primary" (click)="loadMore()">Load more</button>
</div>

View File

@@ -0,0 +1,25 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { LatestBlocksComponent } from './latest-blocks.component';
describe('LatestBlocksComponent', () => {
let component: LatestBlocksComponent;
let fixture: ComponentFixture<LatestBlocksComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ LatestBlocksComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(LatestBlocksComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@@ -0,0 +1,78 @@
import { Component, OnInit, OnDestroy } from '@angular/core';
import { ElectrsApiService } from '../../services/electrs-api.service';
import { StateService } from '../../services/state.service';
import { Block } from '../../interfaces/electrs.interface';
import { Subscription } from 'rxjs';
@Component({
selector: 'app-latest-blocks',
templateUrl: './latest-blocks.component.html',
styleUrls: ['./latest-blocks.component.scss'],
})
export class LatestBlocksComponent implements OnInit, OnDestroy {
blocks: any[] = [];
blockSubscription: Subscription;
isLoading = true;
interval: any;
trigger = 0;
constructor(
private electrsApiService: ElectrsApiService,
private stateService: StateService,
) { }
ngOnInit() {
this.blockSubscription = this.stateService.blocks$
.subscribe((block) => {
if (block === null || !this.blocks.length) {
return;
}
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.loadInitialBlocks();
this.interval = window.setInterval(() => this.trigger++, 1000 * 60);
}
ngOnDestroy() {
clearInterval(this.interval);
this.blockSubscription.unsubscribe();
}
loadInitialBlocks() {
this.electrsApiService.listBlocks$()
.subscribe((blocks) => {
this.blocks = blocks;
this.isLoading = false;
});
}
loadMore() {
this.isLoading = true;
this.electrsApiService.listBlocks$(this.blocks[this.blocks.length - 1].height - 1)
.subscribe((blocks) => {
this.blocks = this.blocks.concat(blocks);
this.isLoading = false;
});
}
trackByBlock(index: number, block: Block) {
return block.height;
}
}