mirror of
https://github.com/mempool/mempool.git
synced 2025-03-26 17:51:45 +01:00
parent
d662292afb
commit
20c7ee98e7
@ -72,6 +72,14 @@ class WebsocketHandler {
|
||||
}
|
||||
}
|
||||
|
||||
if (parsedMessage && parsedMessage['track-asset']) {
|
||||
if (/^[a-fA-F0-9]{64}$/.test(parsedMessage['track-asset'])) {
|
||||
client['track-asset'] = parsedMessage['track-asset'];
|
||||
} else {
|
||||
client['track-asset'] = null;
|
||||
}
|
||||
}
|
||||
|
||||
if (parsedMessage.action === 'init') {
|
||||
const _blocks = blocks.getBlocks();
|
||||
if (!_blocks) {
|
||||
@ -155,24 +163,24 @@ class WebsocketHandler {
|
||||
}
|
||||
}
|
||||
|
||||
// Send all new incoming transactions related to tracked address
|
||||
if (client['track-address']) {
|
||||
// Send all new incoming transactions related to tracked asset
|
||||
if (client['track-asset']) {
|
||||
const foundTransactions: TransactionExtended[] = [];
|
||||
|
||||
newTransactions.forEach((tx) => {
|
||||
const someVin = tx.vin.some((vin) => !!vin.prevout && vin.prevout.scriptpubkey_address === client['track-address']);
|
||||
const someVin = tx.vin.some((vin) => !!vin.issuance && vin.issuance.asset_id === client['track-asset']);
|
||||
if (someVin) {
|
||||
foundTransactions.push(tx);
|
||||
return;
|
||||
}
|
||||
const someVout = tx.vout.some((vout) => vout.scriptpubkey_address === client['track-address']);
|
||||
const someVout = tx.vout.some((vout) => !!vout.asset && vout.asset === client['track-asset']);
|
||||
if (someVout) {
|
||||
foundTransactions.push(tx);
|
||||
}
|
||||
});
|
||||
|
||||
if (foundTransactions.length) {
|
||||
response['address-transactions'] = foundTransactions;
|
||||
response['asset-transactions'] = foundTransactions;
|
||||
}
|
||||
}
|
||||
|
||||
@ -213,7 +221,34 @@ class WebsocketHandler {
|
||||
foundTransactions.push(tx);
|
||||
return;
|
||||
}
|
||||
if (tx.vout && tx.vout.some((vout) => vout.scriptpubkey_address === client['track-address'])) {
|
||||
if (tx.vout && tx.vout.some((vout) => !!vout.asset && vout.asset === client['track-asset'])) {
|
||||
foundTransactions.push(tx);
|
||||
}
|
||||
});
|
||||
|
||||
if (foundTransactions.length) {
|
||||
foundTransactions.forEach((tx) => {
|
||||
tx.status = {
|
||||
confirmed: true,
|
||||
block_height: block.height,
|
||||
block_hash: block.id,
|
||||
block_time: block.timestamp,
|
||||
};
|
||||
});
|
||||
|
||||
response['asset-block-transactions'] = foundTransactions;
|
||||
}
|
||||
}
|
||||
|
||||
if (client['track-asset']) {
|
||||
const foundTransactions: TransactionExtended[] = [];
|
||||
|
||||
transactions.forEach((tx) => {
|
||||
if (tx.vin && tx.vin.some((vin) => !!vin.issuance && vin.issuance.asset_id === client['track-asset'])) {
|
||||
foundTransactions.push(tx);
|
||||
return;
|
||||
}
|
||||
if (tx.vout && tx.vout.some((vout) => !!vout.asset && vout.asset === client['track-asset'])) {
|
||||
foundTransactions.push(tx);
|
||||
}
|
||||
});
|
||||
|
@ -56,6 +56,20 @@ export interface Vin {
|
||||
sequence: any;
|
||||
witness?: string[];
|
||||
inner_witnessscript_asm?: string;
|
||||
|
||||
issuance?: Issuance;
|
||||
}
|
||||
|
||||
interface Issuance {
|
||||
asset_id: string;
|
||||
is_reissuance: string;
|
||||
asset_blinding_nonce: string;
|
||||
asset_entropy: string;
|
||||
contract_hash: string;
|
||||
assetamount?: number;
|
||||
assetamountcommitment?: string;
|
||||
tokenamount?: number;
|
||||
tokenamountcommitment?: string;
|
||||
}
|
||||
|
||||
export interface Vout {
|
||||
@ -64,6 +78,8 @@ export interface Vout {
|
||||
scriptpubkey_type: string;
|
||||
scriptpubkey_address: string;
|
||||
value: number;
|
||||
|
||||
asset?: string;
|
||||
}
|
||||
|
||||
export interface Status {
|
||||
|
@ -7,7 +7,7 @@
|
||||
<ng-template [ngIf]="!isLoading && !error">
|
||||
<table class="table table-borderless table-striped">
|
||||
<thead>
|
||||
<th style="td-name">Name</th>
|
||||
<th class="td-name">Name</th>
|
||||
<th>Ticker</th>
|
||||
<th class="d-none d-md-block">Issuer domain</th>
|
||||
<th>Asset ID</th>
|
||||
|
@ -20,7 +20,11 @@ export class AssetsComponent implements OnInit {
|
||||
) { }
|
||||
|
||||
ngOnInit() {
|
||||
this.assetsService.getAssetsJson$()
|
||||
setTimeout(() => this.getAssets());
|
||||
}
|
||||
|
||||
getAssets() {
|
||||
this.assetsService.getAssetsJson$
|
||||
.subscribe((assets) => {
|
||||
this.assets = Object.values(assets);
|
||||
this.assets.push({
|
||||
@ -36,6 +40,6 @@ export class AssetsComponent implements OnInit {
|
||||
this.error = error;
|
||||
this.isLoading = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -15,7 +15,7 @@
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<table class="table table-borderless table-striped">
|
||||
<tbody>
|
||||
<tbody *ngIf="network !== 'liquid'">
|
||||
<tr>
|
||||
<td>Total received</td>
|
||||
<td>{{ receieved / 100000000 | number: '1.8-8' }} <ng-template [ngIf]="network === 'liquid'">L-</ng-template>BTC</td>
|
||||
@ -29,6 +29,20 @@
|
||||
<td>{{ (receieved - sent) / 100000000 | number: '1.8-8' }} <ng-template [ngIf]="network === 'liquid'">L-</ng-template>BTC (<app-fiat [value]="receieved - sent"></app-fiat>)</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
<tbody *ngIf="network === 'liquid'">
|
||||
<tr>
|
||||
<td>Total received</td>
|
||||
<td>Confidential</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Total sent</td>
|
||||
<td>Confidential</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Balance</td>
|
||||
<td>Confidential</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="col qrcode-col">
|
||||
|
@ -84,7 +84,7 @@ export class AssetComponent implements OnInit, OnDestroy {
|
||||
console.log(err);
|
||||
return of(null);
|
||||
})
|
||||
), this.assetsService.assetsMinimal$])
|
||||
), this.assetsService.getAssetsMinimalJson$])
|
||||
.pipe(
|
||||
take(1)
|
||||
);
|
||||
@ -141,7 +141,7 @@ export class AssetComponent implements OnInit, OnDestroy {
|
||||
this.isLoadingAsset = false;
|
||||
});
|
||||
|
||||
this.stateService.mempoolTransactions$
|
||||
this.stateService.assetTransactions$
|
||||
.subscribe((transaction) => {
|
||||
if (this.transactions.some((t) => t.txid === transaction.txid)) {
|
||||
return;
|
||||
@ -151,22 +151,7 @@ export class AssetComponent implements OnInit, OnDestroy {
|
||||
this.transactions = this.transactions.slice();
|
||||
this.txCount++;
|
||||
|
||||
// if (transaction.vout.some((vout) => vout.scriptpubkey_asset === this.asset.asset)) {
|
||||
// this.audioService.playSound('cha-ching');
|
||||
// } else {
|
||||
// this.audioService.playSound('chime');
|
||||
// }
|
||||
|
||||
// transaction.vin.forEach((vin) => {
|
||||
// if (vin.prevout.scriptpubkey_asset === this.asset.asset) {
|
||||
// this.sent += vin.prevout.value;
|
||||
// }
|
||||
// });
|
||||
// transaction.vout.forEach((vout) => {
|
||||
// if (vout.scriptpubkey_asset === this.asset.asset) {
|
||||
// this.receieved += vout.value;
|
||||
// }
|
||||
// });
|
||||
this.audioService.playSound('chime');
|
||||
});
|
||||
|
||||
this.stateService.blockTransactions$
|
||||
|
@ -1,5 +1,5 @@
|
||||
<span #buttonWrapper [attr.data-tlite]="'Copied!'" style="position: relative;">
|
||||
<button #btn class="btn btn-sm btn-link pt-0" style="line-height: 1;" [attr.data-clipboard-text]="text">
|
||||
<button #btn class="btn btn-sm btn-link pt-0" style="line-height: 0.9;" [attr.data-clipboard-text]="text">
|
||||
<img src="./resources/clippy.svg" width="13">
|
||||
</button>
|
||||
</span>
|
@ -31,10 +31,12 @@ export class SearchFormComponent implements OnInit {
|
||||
this.searchForm = this.formBuilder.group({
|
||||
searchText: ['', Validators.required],
|
||||
});
|
||||
this.assetsService.assetsMinimal$
|
||||
.subscribe((assets) => {
|
||||
this.assets = assets;
|
||||
});
|
||||
if (this.network === 'liquid') {
|
||||
this.assetsService.getAssetsMinimalJson$
|
||||
.subscribe((assets) => {
|
||||
this.assets = assets;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
search() {
|
||||
|
@ -29,7 +29,7 @@
|
||||
</td>
|
||||
<td>
|
||||
<div [ngSwitch]="true">
|
||||
<ng-container *ngSwitchCase="vin.is_coinbase">Coinbase (Newly Generated Coins)</ng-container>
|
||||
<ng-container *ngSwitchCase="vin.is_coinbase">Coinbase<ng-template [ngIf]="network !== 'liquid'"> (Newly Generated Coins)</ng-template></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 }}">
|
||||
|
@ -35,9 +35,11 @@ export class TransactionsListComponent implements OnInit, OnChanges {
|
||||
|
||||
ngOnInit() {
|
||||
this.latestBlock$ = this.stateService.blocks$;
|
||||
this.assetsService.assetsMinimal$.subscribe((assets) => {
|
||||
this.assetsMinimal = assets;
|
||||
});
|
||||
if (this.network === 'liquid') {
|
||||
this.assetsService.getAssetsMinimalJson$.subscribe((assets) => {
|
||||
this.assetsMinimal = assets;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
ngOnChanges() {
|
||||
|
@ -38,6 +38,19 @@ export interface Vin {
|
||||
witness?: string[];
|
||||
inner_witnessscript_asm?: string;
|
||||
is_pegin?: boolean;
|
||||
issuance?: Issuance;
|
||||
}
|
||||
|
||||
interface Issuance {
|
||||
asset_id: string;
|
||||
is_reissuance: string;
|
||||
asset_blinding_nonce: string;
|
||||
asset_entropy: string;
|
||||
contract_hash: string;
|
||||
assetamount?: number;
|
||||
assetamountcommitment?: string;
|
||||
tokenamount?: number;
|
||||
tokenamountcommitment?: string;
|
||||
}
|
||||
|
||||
export interface Vout {
|
||||
|
@ -1,7 +1,8 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
import { ReplaySubject } from 'rxjs';
|
||||
import { ReplaySubject, Observable } from 'rxjs';
|
||||
import { environment } from 'src/environments/environment';
|
||||
import { shareReplay } from 'rxjs/operators';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
@ -9,24 +10,13 @@ import { environment } from 'src/environments/environment';
|
||||
export class AssetsService {
|
||||
network = environment.network;
|
||||
|
||||
assetsMinimal$ = new ReplaySubject<any>(1);
|
||||
getAssetsJson$: Observable<any>;
|
||||
getAssetsMinimalJson$: Observable<any>;
|
||||
|
||||
constructor(
|
||||
private httpClient: HttpClient,
|
||||
) {
|
||||
if (this.network === 'liquid') {
|
||||
this.getAssetsMinimalJson$();
|
||||
}
|
||||
}
|
||||
|
||||
getAssetsMinimalJson$() {
|
||||
this.httpClient.get('/resources/assets.minimal.json')
|
||||
.subscribe((data) => {
|
||||
this.assetsMinimal$.next(data);
|
||||
});
|
||||
}
|
||||
|
||||
getAssetsJson$() {
|
||||
return this.httpClient.get('/resources/assets.json');
|
||||
this.getAssetsJson$ = this.httpClient.get('/resources/assets.json').pipe(shareReplay());
|
||||
this.getAssetsMinimalJson$ = this.httpClient.get('/resources/assets.minimal.json').pipe(shareReplay());
|
||||
}
|
||||
}
|
||||
|
@ -21,6 +21,7 @@ export class StateService {
|
||||
mempoolBlocks$ = new ReplaySubject<MempoolBlock[]>(1);
|
||||
txConfirmed$ = new Subject<Block>();
|
||||
mempoolTransactions$ = new Subject<Transaction>();
|
||||
assetTransactions$ = new Subject<Transaction>();
|
||||
blockTransactions$ = new Subject<Transaction>();
|
||||
|
||||
live2Chart$ = new Subject<OptimizedMempoolStats>();
|
||||
|
@ -96,6 +96,18 @@ export class WebsocketService {
|
||||
});
|
||||
}
|
||||
|
||||
if (response['asset-transactions']) {
|
||||
response['asset-transactions'].forEach((assetTransaction: Transaction) => {
|
||||
this.stateService.assetTransactions$.next(assetTransaction);
|
||||
});
|
||||
}
|
||||
|
||||
if (response['asset-block-transactions']) {
|
||||
response['asset-block-transactions'].forEach((addressTransaction: Transaction) => {
|
||||
this.stateService.blockTransactions$.next(addressTransaction);
|
||||
});
|
||||
}
|
||||
|
||||
if (response['live-2h-chart']) {
|
||||
this.stateService.live2Chart$.next(response['live-2h-chart']);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user