Assets list. Native asset updates.

refs #37
This commit is contained in:
softsimon 2020-05-02 16:29:34 +07:00
parent ac9e718ef1
commit 44d19550e8
No known key found for this signature in database
GPG key ID: 488D7DCFB5A430D7
13 changed files with 217 additions and 41 deletions

View file

@ -11,6 +11,7 @@ import { StatisticsComponent } from './components/statistics/statistics.componen
import { MempoolBlockComponent } from './components/mempool-block/mempool-block.component';
import { LatestBlocksComponent } from './components/latest-blocks/latest-blocks.component';
import { AssetComponent } from './components/asset/asset.component';
import { AssetsComponent } from './assets/assets.component';
const routes: Routes = [
{
@ -37,10 +38,6 @@ const routes: Routes = [
path: 'mempool-block/:id',
component: MempoolBlockComponent
},
{
path: 'asset/:id',
component: AssetComponent
},
],
},
{
@ -56,6 +53,14 @@ const routes: Routes = [
children: [],
component: AddressComponent
},
{
path: 'asset/:id',
component: AssetComponent
},
{
path: 'assets',
component: AssetsComponent,
},
],
},
{

View file

@ -47,6 +47,7 @@ import { SeoService } from './services/seo.service';
import { MempoolGraphComponent } from './components/mempool-graph/mempool-graph.component';
import { AssetComponent } from './components/asset/asset.component';
import { ScriptpubkeyTypePipe } from './pipes/scriptpubkey-type-pipe/scriptpubkey-type.pipe';
import { AssetsComponent } from './assets/assets.component';
@NgModule({
declarations: [
@ -84,6 +85,7 @@ import { ScriptpubkeyTypePipe } from './pipes/scriptpubkey-type-pipe/scriptpubke
MempoolGraphComponent,
AssetComponent,
ScriptpubkeyTypePipe,
AssetsComponent,
],
imports: [
BrowserModule,

View file

@ -0,0 +1,61 @@
<div class="container-xl">
<h1 style="float: left;">Registered assets</h1>
<br>
<div class="clearfix"></div>
<ng-template [ngIf]="!isLoading && !error">
<table class="table table-borderless table-striped">
<thead>
<th style="td-name">Name</th>
<th>Ticker</th>
<th class="d-none d-md-block">Issuer domain</th>
<th>Asset ID</th>
<th class="d-none d-lg-block">Issuance TX</th>
</thead>
<tbody>
<tr *ngFor="let asset of assets">
<td class="td-name">{{ asset.name }}</td>
<td>{{ asset.ticker }}</td>
<td class="d-none d-md-block"><a *ngIf="asset.entity" target="_blank" href="{{ 'http://' + asset.entity.domain }}">{{ asset.entity.domain }}</a></td>
<td><a [routerLink]="['/asset/', asset.asset_id]">{{ asset.asset_id | shortenString : 13 }}</a> <app-clipboard class="d-none d-sm-inline-block" [text]="asset.asset_id"></app-clipboard></td>
<td class="d-none d-lg-block"><ng-template [ngIf]="asset.issuance_txin"><a [routerLink]="['/tx/', asset.issuance_txin.txid]">{{ asset.issuance_txin.txid | shortenString : 13 }}</a> <app-clipboard class="d-none d-sm-inline-block" [text]="asset.issuance_txin.txid"></app-clipboard></ng-template></td>
</tr>
</tbody>
</table>
</ng-template>
<ng-template [ngIf]="isLoading && !error">
<table class="table table-borderless table-striped">
<thead>
<th>Name</th>
<th>Ticker</th>
<th>Issuer domain</th>
<th>Asset ID</th>
<th>Issuance TX</th>
</thead>
<tbody>
<tr *ngFor="let dummy of [0,0,0]">
<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>
</tbody>
</table>
</ng-template>
<ng-template [ngIf]="error">
<div class="text-center">
Error loading assets data.
<br>
<i>{{ error.error }}</i>
</div>
</ng-template>
</div>
<br>

View file

@ -0,0 +1,6 @@
.td-name {
max-width: 200px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}

View file

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

View file

@ -0,0 +1,41 @@
import { Component, OnInit } from '@angular/core';
import { AssetsService } from '../services/assets.service';
import { environment } from 'src/environments/environment';
@Component({
selector: 'app-assets',
templateUrl: './assets.component.html',
styleUrls: ['./assets.component.scss']
})
export class AssetsComponent implements OnInit {
nativeAssetId = environment.nativeAssetId;
isLoading = true;
error: any;
assets: any;
constructor(
private assetsService: AssetsService,
) { }
ngOnInit() {
this.assetsService.getAssetsJson$()
.subscribe((assets) => {
this.assets = Object.values(assets);
this.assets.push({
name: 'Liquid Bitcoin',
ticker: 'L-BTC',
asset_id: this.nativeAssetId,
});
this.assets = this.assets.sort((a: any, b: any) => a.name.localeCompare(b.name));
this.isLoading = false;
},
(error) => {
console.log(error);
this.error = error;
this.isLoading = false;
});
}
}

View file

@ -24,11 +24,11 @@
<td>Precision</td>
<td>{{ assetContract[3] }}</td>
</tr>
<tr>
<tr *ngIf="!isNativeAsset">
<td>Issuer</td>
<td><a target="_blank" href="{{ 'http://' + assetContract[0] }}">{{ assetContract[0] }}</a></td>
</tr>
<tr>
<tr *ngIf="!isNativeAsset">
<td>Issuance tx</td>
<td><a [routerLink]="['/tx/', asset.issuance_txin.txid]">{{ asset.issuance_txin.txid | shortenString : 13 }}</a> <app-clipboard class="d-none d-sm-inline-block" [text]="asset.issuance_txin.txid"></app-clipboard></td>
</tr>
@ -38,17 +38,29 @@
<div class="col">
<table class="table table-borderless table-striped">
<tbody>
<tr>
<td>Circulating amount</td>
<td>{{ (asset.chain_stats.issued_amount - asset.chain_stats.burned_amount) / 100000000 | number: '1.0-' + assetContract[3] }}</td>
<tr *ngIf="isNativeAsset">
<td>Pegged in</td>
<td>{{ asset.chain_stats.peg_in_amount / 100000000 | number: '1.0-' + assetContract[3] }} {{ assetContract[1] }}</td>
</tr>
<tr>
<tr *ngIf="isNativeAsset">
<td>Pegged out</td>
<td>{{ asset.chain_stats.peg_out_amount / 100000000 | number: '1.0-' + assetContract[3] }} {{ assetContract[1] }}</td>
</tr>
<tr *ngIf="!isNativeAsset">
<td>Issued amount</td>
<td>{{ asset.chain_stats.issued_amount / 100000000 | number: '1.0-' + assetContract[3] }}</td>
<td>{{ asset.chain_stats.issued_amount / 100000000 | number: '1.0-' + assetContract[3] }} {{ assetContract[1] }}</td>
</tr>
<tr>
<td>Burned amount</td>
<td>{{ asset.chain_stats.burned_amount / 100000000 | number: '1.0-' + assetContract[3] }}</td>
<td>{{ asset.chain_stats.burned_amount / 100000000 | number: '1.0-' + assetContract[3] }} {{ assetContract[1] }}</td>
</tr>
<tr *ngIf="!isNativeAsset">
<td>Circulating amount</td>
<td>{{ (asset.chain_stats.issued_amount - asset.chain_stats.burned_amount) / 100000000 | number: '1.0-' + assetContract[3] }} {{ assetContract[1] }}</td>
</tr>
<tr *ngIf="isNativeAsset">
<td>Circulating amount</td>
<td>{{ (asset.chain_stats.peg_in_amount - asset.chain_stats.burned_amount - asset.chain_stats.peg_out_amount) / 100000000 | number: '1.0-' + assetContract[3] }} {{ assetContract[1] }}</td>
</tr>
</tbody>
</table>
@ -59,7 +71,7 @@
<br>
<h2><ng-template [ngIf]="transactions?.length">{{ (transactions?.length | number) || '?' }} of </ng-template>{{ txCount | number }} transactions</h2>
<h2><ng-template [ngIf]="transactions?.length">{{ (transactions?.length | number) || '?' }} of </ng-template>{{ txCount | number }} <ng-template [ngIf]="isNativeAsset" [ngIfElse]="defaultAsset">Peg In/Out and Burn Transactions</ng-template><ng-template #defaultAsset>In/Out and Burn Transactions</ng-template></h2>
<app-transactions-list [transactions]="transactions" [showConfirmations]="true" (loadMore)="loadMore()"></app-transactions-list>
@ -86,8 +98,7 @@
<ng-template [ngIf]="isLoadingAsset && !error">
<div class="box">
<div class="row">
<ng-template #loadingTmpl>
<div class="col">
<table class="table table-borderless table-striped">
<tbody>
@ -103,9 +114,12 @@
</tbody>
</table>
</div>
<div class="col">
</ng-template>
</div>
<div class="box">
<div class="row">
<ng-container *ngTemplateOutlet="loadingTmpl"></ng-container>
<ng-container *ngTemplateOutlet="loadingTmpl"></ng-container>
</div>
</div>

View file

@ -19,6 +19,7 @@ import { AssetsService } from 'src/app/services/assets.service';
})
export class AssetComponent implements OnInit, OnDestroy {
network = environment.network;
nativeAssetId = environment.nativeAssetId;
asset: Asset;
assetContract: any;
@ -26,6 +27,7 @@ export class AssetComponent implements OnInit, OnDestroy {
isLoadingAsset = true;
transactions: Transaction[];
isLoadingTransactions = true;
isNativeAsset = false;
error: any;
mainSubscription: Subscription;
@ -94,6 +96,8 @@ export class AssetComponent implements OnInit, OnDestroy {
switchMap(([asset, assetsData]) => {
this.asset = asset;
this.assetContract = assetsData[this.asset.asset_id];
console.log(this.assetContract);
this.isNativeAsset = asset.asset_id === this.nativeAssetId;
this.updateChainStats();
this.websocketService.startTrackAsset(asset.asset_id);
this.isLoadingAsset = false;

View file

@ -21,6 +21,9 @@
<li class="nav-item" routerLinkActive="active">
<a class="nav-link" routerLink="/tv" (click)="collapse()">TV view &nbsp;<img src="./assets/expand.png" width="15"/></a>
</li>
<li class="nav-item" routerLinkActive="active">
<a class="nav-link" routerLink="/assets" (click)="collapse()">Assets</a>
</li>
<li class="nav-item" routerLinkActive="active">
<a class="nav-link" routerLink="/contributors" (click)="collapse()">Contributors</a>
</li>

View file

@ -28,11 +28,10 @@
</ng-template>
</td>
<td>
<div>
<ng-template [ngIf]="vin.is_coinbase" [ngIfElse]="regularVin">
Coinbase (Newly Generated Coins)
</ng-template>
<ng-template #regularVin>
<div [ngSwitch]="true">
<ng-container *ngSwitchCase="vin.is_coinbase">Coinbase (Newly Generated Coins)</ng-container>
<ng-container *ngSwitchCase="vin.is_pegin">PEG IN</ng-container>
<ng-container *ngSwitchDefault>
<a [routerLink]="['/address/', vin.prevout.scriptpubkey_address]" title="{{ vin.prevout.scriptpubkey_address }}">
<span class="d-block d-lg-none">{{ vin.prevout.scriptpubkey_address | shortenString : 16 }}</span>
<span class="d-none d-lg-block">{{ vin.prevout.scriptpubkey_address | shortenString : 42 }}</span>
@ -40,7 +39,7 @@
<div>
<app-address-labels [vin]="vin"></app-address-labels>
</div>
</ng-template>
</ng-container>
</div>
</td>
<td class="text-right nowrap">
@ -66,8 +65,13 @@
<span class="d-none d-lg-block">{{ vout.scriptpubkey_address | shortenString : 42 }}</span>
</a>
<ng-template #scriptpubkey_type>
<ng-template [ngIf]="vout.pegout" [ngIfElse]="defaultscriptpubkey_type">
PEG OUT
</ng-template>
<ng-template #defaultscriptpubkey_type>
{{ vout.scriptpubkey_type | scriptpubkeyType }}
</ng-template>
</ng-template>
</td>
<td class="text-right nowrap">
<ng-template [ngIf]="vout.asset && vout.scriptpubkey_type === 'op_return' && vout.asset !== nativeAssetId" [ngIfElse]="defaultOutput">

View file

@ -37,6 +37,7 @@ export interface Vin {
sequence: any;
witness?: string[];
inner_witnessscript_asm?: string;
is_pegin?: boolean;
}
export interface Vout {
@ -45,7 +46,16 @@ export interface Vout {
scriptpubkey_type: string;
scriptpubkey_address: string;
value: number;
valuecommitment?: number;
asset?: string;
pegout?: Pegout;
}
interface Pegout {
genesis_hash: string;
scriptpubkey: string;
scriptpubkey_asm: string;
scriptpubkey_addres: string;
}
export interface Status {

View file

@ -22,8 +22,11 @@ export class AssetsService {
getAssetsMinimalJson$() {
this.httpClient.get('/assets/assets.minimal.json')
.subscribe((data) => {
console.log(data);
this.assetsMinimal$.next(data);
});
}
getAssetsJson$() {
return this.httpClient.get('/assets/assets.json');
}
}

View file

@ -17,5 +17,3 @@ console.log('Downloading assets');
download(PATH + 'assets.json', 'https://raw.githubusercontent.com/Blockstream/asset_registry_db/master/index.json');
console.log('Downloading assets minimal');
download(PATH + 'assets.minimal.json', 'https://raw.githubusercontent.com/Blockstream/asset_registry_db/master/index.minimal.json');
console.log('Downloading asset icons');
download(PATH + 'asset.icons.json', 'https://raw.githubusercontent.com/Blockstream/asset_registry_db/master/icons.json');