mirror of
https://github.com/mempool/mempool.git
synced 2025-02-24 06:47:52 +01:00
Change federation wallet stats to include utxos count
This commit is contained in:
parent
42bd08c744
commit
346c024ddf
8 changed files with 60 additions and 62 deletions
|
@ -398,31 +398,16 @@ class ElementsParser {
|
|||
return rows;
|
||||
}
|
||||
|
||||
// Get all of the federation addresses one month ago, most balances first
|
||||
public async $getFederationAddressesOneMonthAgo(): Promise<any> {
|
||||
const query = `
|
||||
SELECT COUNT(*) AS addresses_count_one_month FROM (
|
||||
SELECT bitcoinaddress, SUM(amount) AS balance
|
||||
FROM federation_txos
|
||||
WHERE
|
||||
(blocktime < UNIX_TIMESTAMP(TIMESTAMPADD(DAY, -30, CURRENT_TIMESTAMP())))
|
||||
AND
|
||||
((unspent = 1) OR (unspent = 0 AND lasttimeupdate > UNIX_TIMESTAMP(TIMESTAMPADD(DAY, -30, CURRENT_TIMESTAMP()))))
|
||||
GROUP BY bitcoinaddress
|
||||
) AS result;`;
|
||||
// Get the total number of federation addresses
|
||||
public async $getFederationAddressesNumber(): Promise<any> {
|
||||
const query = `SELECT COUNT(DISTINCT bitcoinaddress) AS address_count FROM federation_txos WHERE unspent = 1;`;
|
||||
const [rows] = await DB.query(query);
|
||||
return rows[0];
|
||||
}
|
||||
|
||||
// Get all of the UTXOs held by the federation one month ago, most recent first
|
||||
public async $getFederationUtxosOneMonthAgo(): Promise<any> {
|
||||
const query = `
|
||||
SELECT COUNT(*) AS utxos_count_one_month FROM federation_txos
|
||||
WHERE
|
||||
(blocktime < UNIX_TIMESTAMP(TIMESTAMPADD(DAY, -30, CURRENT_TIMESTAMP())))
|
||||
AND
|
||||
((unspent = 1) OR (unspent = 0 AND lasttimeupdate > UNIX_TIMESTAMP(TIMESTAMPADD(DAY, -30, CURRENT_TIMESTAMP()))))
|
||||
ORDER BY blocktime DESC;`;
|
||||
// Get the total number of federation utxos
|
||||
public async $getFederationUtxosNumber(): Promise<any> {
|
||||
const query = `SELECT COUNT(*) AS utxo_count FROM federation_txos WHERE unspent = 1;`;
|
||||
const [rows] = await DB.query(query);
|
||||
return rows[0];
|
||||
}
|
||||
|
|
|
@ -22,9 +22,9 @@ class LiquidRoutes {
|
|||
.get(config.MEMPOOL.API_URL_PREFIX + 'liquid/reserves/month', this.$getFederationReservesByMonth)
|
||||
.get(config.MEMPOOL.API_URL_PREFIX + 'liquid/pegouts', this.$getPegOuts)
|
||||
.get(config.MEMPOOL.API_URL_PREFIX + 'liquid/reserves/addresses', this.$getFederationAddresses)
|
||||
.get(config.MEMPOOL.API_URL_PREFIX + 'liquid/reserves/addresses/previous-month', this.$getFederationAddressesOneMonthAgo)
|
||||
.get(config.MEMPOOL.API_URL_PREFIX + 'liquid/reserves/addresses/total', this.$getFederationAddressesNumber)
|
||||
.get(config.MEMPOOL.API_URL_PREFIX + 'liquid/reserves/utxos', this.$getFederationUtxos)
|
||||
.get(config.MEMPOOL.API_URL_PREFIX + 'liquid/reserves/utxos/previous-month', this.$getFederationUtxosOneMonthAgo)
|
||||
.get(config.MEMPOOL.API_URL_PREFIX + 'liquid/reserves/utxos/total', this.$getFederationUtxosNumber)
|
||||
.get(config.MEMPOOL.API_URL_PREFIX + 'liquid/reserves/status', this.$getFederationAuditStatus)
|
||||
;
|
||||
}
|
||||
|
@ -142,12 +142,12 @@ class LiquidRoutes {
|
|||
}
|
||||
}
|
||||
|
||||
private async $getFederationAddressesOneMonthAgo(req: Request, res: Response) {
|
||||
private async $getFederationAddressesNumber(req: Request, res: Response) {
|
||||
try {
|
||||
const federationAddresses = await elementsParser.$getFederationAddressesOneMonthAgo();
|
||||
const federationAddresses = await elementsParser.$getFederationAddressesNumber();
|
||||
res.header('Pragma', 'public');
|
||||
res.header('Cache-control', 'public');
|
||||
res.setHeader('Expires', new Date(Date.now() + 1000 * 60 * 60 * 24).toUTCString());
|
||||
res.setHeader('Expires', new Date(Date.now() + 1000 * 30).toUTCString());
|
||||
res.json(federationAddresses);
|
||||
} catch (e) {
|
||||
res.status(500).send(e instanceof Error ? e.message : e);
|
||||
|
@ -166,12 +166,12 @@ class LiquidRoutes {
|
|||
}
|
||||
}
|
||||
|
||||
private async $getFederationUtxosOneMonthAgo(req: Request, res: Response) {
|
||||
private async $getFederationUtxosNumber(req: Request, res: Response) {
|
||||
try {
|
||||
const federationUtxos = await elementsParser.$getFederationUtxosOneMonthAgo();
|
||||
const federationUtxos = await elementsParser.$getFederationUtxosNumber();
|
||||
res.header('Pragma', 'public');
|
||||
res.header('Cache-control', 'public');
|
||||
res.setHeader('Expires', new Date(Date.now() + 1000 * 60 * 60 * 24).toUTCString());
|
||||
res.setHeader('Expires', new Date(Date.now() + 1000 * 30).toUTCString());
|
||||
res.json(federationUtxos);
|
||||
} catch (e) {
|
||||
res.status(500).send(e instanceof Error ? e.message : e);
|
||||
|
|
|
@ -1,15 +1,12 @@
|
|||
<div *ngIf="(federationAddresses$ | async) as federationAddresses; else loadingData">
|
||||
|
||||
<div *ngIf="(federationWalletStats$ | async) as federationWalletStats; else loadingData">
|
||||
<div class="fee-estimation-container">
|
||||
<div class="item">
|
||||
<a class="title-link" [routerLink]="['/audit/wallet/addresses' | relativeUrl]">
|
||||
<h5 class="card-title"><ng-container i18n="liquid.federation-wallet">Liquid Federation Wallet</ng-container> <fa-icon [icon]="['fas', 'external-link-alt']" [fixedWidth]="true" style="font-size: 13px; color: #4a68b9"></fa-icon></h5>
|
||||
</a>
|
||||
<div class="card-text">
|
||||
<div class="fee-text">{{ federationAddresses.length }} <span i18n="shared.addresses">addresses</span></div>
|
||||
<span class="fiat" *ngIf="(federationAddressesOneMonthAgo$ | async) as federationAddressesOneMonthAgo; else loadingSkeleton" i18n-ngbTooltip="liquid.percentage-change-last-month" ngbTooltip="Percentage change past month" placement="bottom">
|
||||
<app-change [current]="federationAddresses.length" [previous]="federationAddressesOneMonthAgo.addresses_count_one_month"></app-change>
|
||||
</span>
|
||||
<div class="fee-text">{{ federationWalletStats.address_count }} <span i18n="shared.addresses">addresses</span></div>
|
||||
<div class="fiat">{{ federationWalletStats.utxo_count }} <span i18n="shared.utxos">UTXOs</span></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -30,5 +27,5 @@
|
|||
</ng-template>
|
||||
|
||||
<ng-template #loadingSkeleton>
|
||||
<div class="skeleton-loader skeleton-loader-transactions" style="margin-top: 2px; margin-bottom: 5px;"></div>
|
||||
<div class="skeleton-loader skeleton-loader-transactions" style="margin-top: 8px; margin-bottom: 8px;"></div>
|
||||
</ng-template>
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
}
|
||||
|
||||
.card-text {
|
||||
padding-top: 9px;
|
||||
font-size: 22px;
|
||||
span {
|
||||
font-size: 11px;
|
||||
|
@ -49,10 +50,6 @@
|
|||
}
|
||||
}
|
||||
|
||||
.loading-container{
|
||||
min-height: 76px;
|
||||
}
|
||||
|
||||
.card-text {
|
||||
.skeleton-loader {
|
||||
width: 100%;
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import { ChangeDetectionStrategy, Component, Input, OnInit } from '@angular/core';
|
||||
import { Observable } from 'rxjs';
|
||||
import { FederationAddress } from '../../../interfaces/node-api.interface';
|
||||
import { Observable, combineLatest, map } from 'rxjs';
|
||||
|
||||
@Component({
|
||||
selector: 'app-federation-addresses-stats',
|
||||
|
@ -9,12 +8,21 @@ import { FederationAddress } from '../../../interfaces/node-api.interface';
|
|||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class FederationAddressesStatsComponent implements OnInit {
|
||||
@Input() federationAddresses$: Observable<FederationAddress[]>;
|
||||
@Input() federationAddressesOneMonthAgo$: Observable<any>;
|
||||
@Input() federationAddressesNumber$: Observable<number>;
|
||||
@Input() federationUtxosNumber$: Observable<number>;
|
||||
federationWalletStats$: Observable<any>;
|
||||
|
||||
constructor() { }
|
||||
|
||||
ngOnInit(): void {
|
||||
this.federationWalletStats$ = combineLatest([
|
||||
this.federationAddressesNumber$,
|
||||
this.federationUtxosNumber$
|
||||
]).pipe(
|
||||
map(([address_count, utxo_count]) => {
|
||||
return { address_count, utxo_count}
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -34,7 +34,7 @@
|
|||
<div class="col" style="margin-bottom: 1.47rem">
|
||||
<div class="card smaller">
|
||||
<div class="card-body">
|
||||
<app-federation-addresses-stats [federationAddresses$]="federationAddresses$" [federationAddressesOneMonthAgo$]="federationAddressesOneMonthAgo$"></app-federation-addresses-stats>
|
||||
<app-federation-addresses-stats [federationAddressesNumber$]="federationAddressesNumber$" [federationUtxosNumber$]="federationUtxosNumber$"></app-federation-addresses-stats>
|
||||
<app-federation-addresses-list [federationAddresses$]="federationAddresses$" [widget]="true"></app-federation-addresses-list>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -22,7 +22,8 @@ export class ReservesAuditDashboardComponent implements OnInit {
|
|||
recentPegOuts$: Observable<RecentPeg[]>;
|
||||
pegsVolume$: Observable<PegsVolume[]>;
|
||||
federationAddresses$: Observable<FederationAddress[]>;
|
||||
federationAddressesOneMonthAgo$: Observable<any>;
|
||||
federationAddressesNumber$: Observable<number>;
|
||||
federationUtxosNumber$: Observable<number>;
|
||||
liquidPegsMonth$: Observable<any>;
|
||||
liquidReservesMonth$: Observable<any>;
|
||||
pegRatioGraphHeight: number = 320;
|
||||
|
@ -143,10 +144,20 @@ export class ReservesAuditDashboardComponent implements OnInit {
|
|||
share()
|
||||
);
|
||||
|
||||
this.federationAddressesOneMonthAgo$ = interval(60 * 60 * 1000)
|
||||
.pipe(
|
||||
startWith(0),
|
||||
switchMap(() => this.apiService.federationAddressesOneMonthAgo$())
|
||||
this.federationAddressesNumber$ = this.auditUpdated$.pipe(
|
||||
filter(auditUpdated => auditUpdated === true),
|
||||
throttleTime(40000),
|
||||
switchMap(_ => this.apiService.federationAddressesNumber$()),
|
||||
map(count => count.address_count),
|
||||
share()
|
||||
);
|
||||
|
||||
this.federationUtxosNumber$ = this.auditUpdated$.pipe(
|
||||
filter(auditUpdated => auditUpdated === true),
|
||||
throttleTime(40000),
|
||||
switchMap(_ => this.apiService.federationUtxosNumber$()),
|
||||
map(count => count.utxo_count),
|
||||
share()
|
||||
);
|
||||
|
||||
this.liquidPegsMonth$ = interval(60 * 60 * 1000)
|
||||
|
|
|
@ -204,12 +204,12 @@ export class ApiService {
|
|||
return this.httpClient.get<RecentPeg[]>(this.apiBaseUrl + this.apiBasePath + '/api/v1/liquid/pegouts');
|
||||
}
|
||||
|
||||
federationAddressesOneMonthAgo$(): Observable<any> {
|
||||
return this.httpClient.get<FederationAddress[]>(this.apiBaseUrl + this.apiBasePath + '/api/v1/liquid/reserves/addresses/previous-month');
|
||||
federationAddressesNumber$(): Observable<any> {
|
||||
return this.httpClient.get<any>(this.apiBaseUrl + this.apiBasePath + '/api/v1/liquid/reserves/addresses/total');
|
||||
}
|
||||
|
||||
federationUtxosOneMonthAgo$(): Observable<any> {
|
||||
return this.httpClient.get<FederationUtxo[]>(this.apiBaseUrl + this.apiBasePath + '/api/v1/liquid/reserves/utxos/previous-month');
|
||||
federationUtxosNumber$(): Observable<any> {
|
||||
return this.httpClient.get<any>(this.apiBaseUrl + this.apiBasePath + '/api/v1/liquid/reserves/utxos/total');
|
||||
}
|
||||
|
||||
listFeaturedAssets$(): Observable<any[]> {
|
||||
|
|
Loading…
Add table
Reference in a new issue