mirror of
https://github.com/benjamin-wilson/public-pool.git
synced 2026-09-29 09:05:06 -07:00
Add payout modes and production switchover schema
This commit is contained in:
@@ -2,11 +2,20 @@ import { Injectable } from '@nestjs/common';
|
||||
import { InjectDataSource } from '@nestjs/typeorm';
|
||||
import { DataSource } from 'typeorm';
|
||||
|
||||
import { normalizePayoutMode, PayoutMode } from '../../types/payout-mode';
|
||||
|
||||
const HASHES_PER_DIFFICULTY = 4294967296;
|
||||
const CHART_BUCKET_SECONDS = 600;
|
||||
const CHART_WINDOW = '24 hours';
|
||||
const SITE_CHART_WINDOW = '7 days';
|
||||
|
||||
interface AcceptedShareChartFilter {
|
||||
address?: string;
|
||||
clientName?: string;
|
||||
clientId?: string;
|
||||
payoutMode?: PayoutMode;
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
export class ClientStatisticsService {
|
||||
|
||||
@@ -21,6 +30,10 @@ export class ClientStatisticsService {
|
||||
return this.getAcceptedShareChartData('', [], limit, SITE_CHART_WINDOW);
|
||||
}
|
||||
|
||||
public async getChartDataForSiteByPayoutMode(payoutMode?: PayoutMode, limit: number = 144 * 7) {
|
||||
return this.getAcceptedShareChartDataByPayoutMode({ payoutMode }, limit, SITE_CHART_WINDOW);
|
||||
}
|
||||
|
||||
public async getChartDataForAddress(address: string) {
|
||||
return this.getAcceptedShareChartData(
|
||||
'AND "address" = $1',
|
||||
@@ -30,14 +43,33 @@ export class ClientStatisticsService {
|
||||
);
|
||||
}
|
||||
|
||||
public async getChartDataForAddressByPayoutMode(address: string, payoutMode?: PayoutMode) {
|
||||
return this.getAcceptedShareChartDataByPayoutMode({ address, payoutMode }, 144, CHART_WINDOW);
|
||||
}
|
||||
|
||||
public async getHashRateForGroup(address: string, clientName: string) {
|
||||
const result = await this.dataSource.query(`
|
||||
WITH bounds AS (
|
||||
SELECT time_bucket(INTERVAL '10 minutes', NOW()) AS current_bucket
|
||||
),
|
||||
completed AS (
|
||||
SELECT COALESCE(SUM("shares"), 0) AS "creditedDifficulty"
|
||||
FROM "accepted_share_10m", bounds
|
||||
WHERE "address" = $1
|
||||
AND "clientName" = $2
|
||||
AND "bucket" > bounds.current_bucket - INTERVAL '1 hour'
|
||||
AND "bucket" < bounds.current_bucket
|
||||
),
|
||||
live AS (
|
||||
SELECT COALESCE(SUM("creditedDifficulty"), 0) AS "creditedDifficulty"
|
||||
FROM "accepted_share_entity", bounds
|
||||
WHERE "address" = $1
|
||||
AND "clientName" = $2
|
||||
AND "acceptedAt" >= bounds.current_bucket
|
||||
)
|
||||
SELECT
|
||||
COALESCE((SUM("creditedDifficulty") * ${HASHES_PER_DIFFICULTY}) / ${CHART_BUCKET_SECONDS}, 0) AS "hashRate"
|
||||
FROM "accepted_share_entity"
|
||||
WHERE "address" = $1
|
||||
AND "clientName" = $2
|
||||
AND "acceptedAt" > NOW() - INTERVAL '1 hour'
|
||||
COALESCE(((completed."creditedDifficulty" + live."creditedDifficulty") * ${HASHES_PER_DIFFICULTY}) / ${CHART_BUCKET_SECONDS}, 0) AS "hashRate"
|
||||
FROM completed, live
|
||||
`, [address, clientName]);
|
||||
|
||||
return parseFloat(result[0]?.hashRate ?? '0');
|
||||
@@ -52,6 +84,10 @@ export class ClientStatisticsService {
|
||||
);
|
||||
}
|
||||
|
||||
public async getChartDataForGroupByPayoutMode(address: string, clientName: string, payoutMode?: PayoutMode) {
|
||||
return this.getAcceptedShareChartDataByPayoutMode({ address, clientName, payoutMode }, 144, CHART_WINDOW);
|
||||
}
|
||||
|
||||
public async getChartDataForSession(clientId: string) {
|
||||
return this.getAcceptedShareChartData(
|
||||
'AND "clientId" = $1',
|
||||
@@ -61,6 +97,10 @@ export class ClientStatisticsService {
|
||||
);
|
||||
}
|
||||
|
||||
public async getChartDataForSessionByPayoutMode(clientId: string, payoutMode?: PayoutMode) {
|
||||
return this.getAcceptedShareChartDataByPayoutMode({ clientId, payoutMode }, 144, CHART_WINDOW);
|
||||
}
|
||||
|
||||
private async getAcceptedShareChartData(filterSql: string, params: unknown[], limit: number, windowSql: string) {
|
||||
const query = `
|
||||
WITH bounds AS (
|
||||
@@ -101,4 +141,80 @@ export class ClientStatisticsService {
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
private async getAcceptedShareChartDataByPayoutMode(
|
||||
filter: AcceptedShareChartFilter,
|
||||
limit: number,
|
||||
windowSql: string,
|
||||
) {
|
||||
const { whereSql, params } = this.buildModeChartWhere(filter);
|
||||
const query = `
|
||||
WITH bounds AS (
|
||||
SELECT
|
||||
NOW() - INTERVAL '${windowSql}' AS since,
|
||||
time_bucket(INTERVAL '10 minutes', NOW()) AS current_bucket
|
||||
)
|
||||
SELECT
|
||||
"label",
|
||||
"payoutMode",
|
||||
"data",
|
||||
"shares",
|
||||
"acceptedCount"
|
||||
FROM (
|
||||
SELECT
|
||||
"bucket" AS "label",
|
||||
"payoutMode",
|
||||
ROUND((SUM("shares") * ${HASHES_PER_DIFFICULTY}) / ${CHART_BUCKET_SECONDS}) AS "data",
|
||||
SUM("shares") AS "shares",
|
||||
SUM("acceptedCount") AS "acceptedCount"
|
||||
FROM "accepted_share_10m", bounds
|
||||
WHERE "bucket" > bounds.since
|
||||
AND "bucket" < bounds.current_bucket
|
||||
${whereSql}
|
||||
GROUP BY "bucket", "payoutMode"
|
||||
ORDER BY "bucket" DESC
|
||||
LIMIT ${limit * 2}
|
||||
) AS limited_rows
|
||||
ORDER BY "label", "payoutMode"
|
||||
`;
|
||||
|
||||
const result = await this.dataSource.query(query, params);
|
||||
|
||||
return result.map(res => {
|
||||
return {
|
||||
label: new Date(res.label).toISOString(),
|
||||
payoutMode: res.payoutMode,
|
||||
data: res.data,
|
||||
shares: Number(res.shares ?? 0),
|
||||
acceptedCount: Number(res.acceptedCount ?? 0),
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
private buildModeChartWhere(filter: AcceptedShareChartFilter): { whereSql: string; params: string[] } {
|
||||
const where: string[] = [];
|
||||
const params: string[] = [];
|
||||
|
||||
if (filter.address != null) {
|
||||
params.push(filter.address);
|
||||
where.push(`"address" = $${params.length}`);
|
||||
}
|
||||
if (filter.clientName != null) {
|
||||
params.push(filter.clientName);
|
||||
where.push(`"clientName" = $${params.length}`);
|
||||
}
|
||||
if (filter.clientId != null) {
|
||||
params.push(filter.clientId);
|
||||
where.push(`"clientId" = $${params.length}`);
|
||||
}
|
||||
if (filter.payoutMode != null) {
|
||||
params.push(normalizePayoutMode(filter.payoutMode));
|
||||
where.push(`"payoutMode" = $${params.length}`);
|
||||
}
|
||||
|
||||
return {
|
||||
whereSql: where.length > 0 ? `AND ${where.join(' AND ')}` : '',
|
||||
params,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user