Skip to content

Commit

Permalink
Merge pull request #7 from axone-protocol/feat/supply-growth-metric
Browse files Browse the repository at this point in the history
  • Loading branch information
dbatarin authored May 9, 2024
2 parents 24303ac + 6391975 commit 8121e07
Show file tree
Hide file tree
Showing 13 changed files with 76 additions and 55 deletions.
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
export enum ChangeSupplyRange {
export enum Range {
ALL = 'all',
FIVE_MIN = 'fiveMin',
HOUR = 'hour',
DAY = 'day',
WEEK = 'week',
MONTH = 'month',
THREE_MONTH = 'threeMonth',
YEAR = 'year',
}

8 changes: 0 additions & 8 deletions src/modules/price/enums/price-range.enum.ts

This file was deleted.

4 changes: 2 additions & 2 deletions src/modules/price/price.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ import { Controller, Get, Query } from '@nestjs/common';

import { Routes } from '@core/enums/routes.enum';
import { SchemaValidatePipe } from '@core/pipes/schema-validate.pipe';
import { Range } from '@core/enums/range.enum';

import { QueryParam } from './enums/query-param.enum';
import { PriceRange } from './enums/price-range.enum';
import { RangeSchema } from './schemas/range.schema';
import { PriceCache } from './services/price.cache';
import { PriceEndpoints } from './enums/price-endpoints.enum';
Expand All @@ -16,7 +16,7 @@ export class PriceController {
@Get(PriceEndpoints.HISTORICAL)
async getHistoricalPrice(
@Query(QueryParam.RANGE, new SchemaValidatePipe(RangeSchema))
range: PriceRange,
range: Range,
) {
return this.cache.getCacheByRange(range);
}
Expand Down
4 changes: 2 additions & 2 deletions src/modules/price/schemas/range.schema.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import * as Joi from 'joi';

import { PriceRange } from '../enums/price-range.enum';
import { Range } from '@core/enums/range.enum';

export const RangeSchema = Joi.string()
.valid(...Object.values(PriceRange))
.valid(Range.ALL, Range.DAY, Range.MONTH, Range.THREE_MONTH, Range.WEEK, Range.YEAR)
.required();
18 changes: 9 additions & 9 deletions src/modules/price/services/price.cache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { DBOrder } from '@core/enums/db-order.enum';

import { HistoricalPrice } from '../dtos/historical-price.dto';
import { TimeBucketDto } from '../dtos/time-bucket.dto';
import { PriceRange } from '../enums/price-range.enum';
import { Range } from '@core/enums/range.enum';

@Injectable()
export class PriceCache implements OnModuleInit {
Expand All @@ -23,7 +23,7 @@ export class PriceCache implements OnModuleInit {
await this.init();
}

async getCacheByRange(range: PriceRange): Promise<HistoricalPrice[]> {
async getCacheByRange(range: Range): Promise<HistoricalPrice[]> {
const serializedCache = await this.cacheService.get(this.createRedisKey(range));
return JSON.parse(serializedCache as string);
}
Expand Down Expand Up @@ -54,32 +54,32 @@ export class PriceCache implements OnModuleInit {

async initAllCache() {
const allBucket = await this.timeBucket(DBTimeInterval.MONTH, DBOrder.ASC);
this.cacheService.set(this.createRedisKey(PriceRange.ALL), JSON.stringify(allBucket));
this.cacheService.set(this.createRedisKey(Range.ALL), JSON.stringify(allBucket));
}

async initDayCache() {
const dayBucket = await this.timeBucket(DBTimeInterval.TWO_HOUR, DBOrder.ASC, 12);
this.cacheService.set(this.createRedisKey(PriceRange.DAY), JSON.stringify(dayBucket));
this.cacheService.set(this.createRedisKey(Range.DAY), JSON.stringify(dayBucket));
}

async initWeekCache() {
const weekBucket = await this.timeBucket(DBTimeInterval.SIX_HOUR, DBOrder.ASC, 28);
this.cacheService.set(this.createRedisKey(PriceRange.WEEK), JSON.stringify(weekBucket));
this.cacheService.set(this.createRedisKey(Range.WEEK), JSON.stringify(weekBucket));
}

async initMonthCache() {
const monthBucket = await this.timeBucket(DBTimeInterval.DAY, DBOrder.ASC, 30);
this.cacheService.set(this.createRedisKey(PriceRange.MONTH), JSON.stringify(monthBucket));
this.cacheService.set(this.createRedisKey(Range.MONTH), JSON.stringify(monthBucket));
}

async initThreeMonthCache() {
const threeMonthBucket = await this.timeBucket(DBTimeInterval.THREE_DAY, DBOrder.ASC, 30);
this.cacheService.set(this.createRedisKey(PriceRange.THREE_MONTH), JSON.stringify(threeMonthBucket));
this.cacheService.set(this.createRedisKey(Range.THREE_MONTH), JSON.stringify(threeMonthBucket));
}

async initYearCache() {
const yearBucket = await this.timeBucket(DBTimeInterval.MONTH, DBOrder.DESC, 12);
this.cacheService.set(this.createRedisKey(PriceRange.YEAR), JSON.stringify(yearBucket));
this.cacheService.set(this.createRedisKey(Range.YEAR), JSON.stringify(yearBucket));
}

async init() {
Expand All @@ -93,7 +93,7 @@ export class PriceCache implements OnModuleInit {
]);
}

private createRedisKey(range: PriceRange) {
private createRedisKey(range: Range) {
return `${this.redisPricePrefix}_${range}`;
}
}
7 changes: 0 additions & 7 deletions src/modules/supply/enums/historical-supply-range.enum.ts

This file was deleted.

1 change: 1 addition & 0 deletions src/modules/supply/enums/supply-endpoints.enum.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export enum SupplyEndpoints {
HISTORICAL = '/historical',
CHANGE = '/change',
GROWTH = '/growth',
}
4 changes: 2 additions & 2 deletions src/modules/supply/schemas/change-range.schema.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Range } from '@core/enums/range.enum';
import * as Joi from 'joi';
import { ChangeSupplyRange } from '../enums/change-supply-range.enum';

export const ChangeRangeSchema = Joi.string()
.valid(...Object.values(ChangeSupplyRange))
.valid(Range.FIVE_MIN, Range.HOUR, Range.DAY, Range.WEEK, Range.MONTH)
.required();
4 changes: 4 additions & 0 deletions src/modules/supply/schemas/growth-range.schema.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import { Range } from '@core/enums/range.enum';
import * as Joi from 'joi';

export const GrowthRangeSchema = Joi.string().valid(Range.FIVE_MIN, Range.HOUR, Range.DAY, Range.WEEK, Range.MONTH).required();
4 changes: 2 additions & 2 deletions src/modules/supply/schemas/historical-range.schema.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Range } from '@core/enums/range.enum';
import * as Joi from 'joi';
import { HistoricalSupplyRange } from '../enums/historical-supply-range.enum';

export const HistoricalRangeSchema = Joi.string()
.valid(...Object.values(HistoricalSupplyRange))
.valid(Range.ALL, Range.DAY, Range.WEEK, Range.MONTH)
.required();
14 changes: 7 additions & 7 deletions src/modules/supply/services/supply.cache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ import { DBOrder } from "@core/enums/db-order.enum";
import { DBTimeInterval } from "@core/enums/db-time-interval.enum";
import { PrismaService } from "@core/lib/prisma.service";

import { HistoricalSupplyRange } from "../enums/historical-supply-range.enum";
import { TimeBucketDto } from "../dtos/time-bucket.dto";
import { ChangeIntervalDto } from "../dtos/change-interval.dto";
import { Range } from "@core/enums/range.enum";

@Injectable()
export class SupplyCache {
Expand All @@ -23,7 +23,7 @@ export class SupplyCache {
await this.init();
}

async getCacheByRange(range: HistoricalSupplyRange): Promise<ChangeIntervalDto[]> {
async getCacheByRange(range: Range): Promise<ChangeIntervalDto[]> {
const serializedCache = await this.cacheService.get(this.createRedisKey(range));
return JSON.parse(serializedCache as string);
}
Expand Down Expand Up @@ -54,22 +54,22 @@ export class SupplyCache {

async initAllCache() {
const allBucket = await this.timeBucket(DBTimeInterval.MONTH, DBOrder.ASC);
this.cacheService.set(this.createRedisKey(HistoricalSupplyRange.ALL), JSON.stringify(allBucket));
this.cacheService.set(this.createRedisKey(Range.ALL), JSON.stringify(allBucket));
}

async initDayCache() {
const dayBucket = await this.timeBucket(DBTimeInterval.TWO_HOUR, DBOrder.ASC, 12);
this.cacheService.set(this.createRedisKey(HistoricalSupplyRange.DAY), JSON.stringify(dayBucket));
this.cacheService.set(this.createRedisKey(Range.DAY), JSON.stringify(dayBucket));
}

async initWeekCache() {
const weekBucket = await this.timeBucket(DBTimeInterval.SIX_HOUR, DBOrder.ASC, 28);
this.cacheService.set(this.createRedisKey(HistoricalSupplyRange.WEEK), JSON.stringify(weekBucket));
this.cacheService.set(this.createRedisKey(Range.WEEK), JSON.stringify(weekBucket));
}

async initMonthCache() {
const monthBucket = await this.timeBucket(DBTimeInterval.DAY, DBOrder.ASC, 30);
this.cacheService.set(this.createRedisKey(HistoricalSupplyRange.MONTH), JSON.stringify(monthBucket));
this.cacheService.set(this.createRedisKey(Range.MONTH), JSON.stringify(monthBucket));
}

async init() {
Expand All @@ -81,7 +81,7 @@ export class SupplyCache {
]);
}

private createRedisKey(range: HistoricalSupplyRange) {
private createRedisKey(range: Range) {
return `${this.redisSupplyPrefix}_${range}`;
}
}
42 changes: 31 additions & 11 deletions src/modules/supply/services/supply.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { Okp4Service } from "@core/lib/okp4/okp4.service";
import { PrismaService } from "@core/lib/prisma.service";

import { CurrentSupplyDto } from "../dtos/current-supply.dto";
import { ChangeSupplyRange } from "../enums/change-supply-range.enum";
import { Range } from "@core/enums/range.enum";

@Injectable()
export class SupplyService {
Expand Down Expand Up @@ -63,14 +63,14 @@ export class SupplyService {
return change;
}

async getSupplyChange(range: ChangeSupplyRange) {
const previousSupply = await this.getSupplyForChangeByRange(range);
async getSupplyChange(range: Range) {
const previousSupply = await this.getPastSupplyByRange(range);
const currentSupply = await this.getSupplyByOrder();
if (previousSupply && currentSupply) return Big(currentSupply.supply).minus(previousSupply.supply);
}

private async getSupplyForChangeByRange(range: ChangeSupplyRange) {
const dateByRange = this.createDateForChangeSupply(range);
private async getPastSupplyByRange(range: Range) {
const dateByRange = this.calculatePastDateByRange(range);
const supply = await this.prismaService.historicalSupply.findFirst({
where: {
time: {
Expand All @@ -89,16 +89,36 @@ export class SupplyService {
return supply;
}

private createDateForChangeSupply(range: ChangeSupplyRange): Date {
private calculatePastDateByRange(range: Range): Date {
let date = new Date();
switch (range) {
case ChangeSupplyRange.FIVE_MIN: date = new Date(date.setMinutes(date.getMinutes() - 5)); break;
case ChangeSupplyRange.HOUR: date = new Date(date.setHours(date.getHours() - 1)); break;
case ChangeSupplyRange.DAY: date = new Date(date.setDate(date.getDate() - 1)); break;
case ChangeSupplyRange.WEEK: date = new Date(date.setDate(date.getDate() - 7)); break;
case ChangeSupplyRange.MONTH: date = new Date(date.setMonth(date.getMonth() - 1)); break;
case Range.FIVE_MIN: date = new Date(date.setMinutes(date.getMinutes() - 5)); break;
case Range.HOUR: date = new Date(date.setHours(date.getHours() - 1)); break;
case Range.DAY: date = new Date(date.setDate(date.getDate() - 1)); break;
case Range.WEEK: date = new Date(date.setDate(date.getDate() - 7)); break;
case Range.MONTH: date = new Date(date.setMonth(date.getMonth() - 1)); break;
}

return date;
}

async getSupplyGrowth(range: Range) {
const pastDate = this.calculatePastDateByRange(range);
const supplyChangeByPeriod = await this.prismaService.historicalSupply.aggregate({
where: {
time: {
gte: pastDate,
}
},
_sum: {
change: true,
}
});

if (supplyChangeByPeriod._sum.change) {
return Big(supplyChangeByPeriod._sum.change).toFixed(2);
}

return 0;
}
}
16 changes: 12 additions & 4 deletions src/modules/supply/supply.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ import { SupplyCache } from "./services/supply.cache";
import { QueryParam } from "./enums/query-param.enum";
import { SchemaValidatePipe } from "@core/pipes/schema-validate.pipe";
import { HistoricalRangeSchema } from "./schemas/historical-range.schema";
import { HistoricalSupplyRange } from "./enums/historical-supply-range.enum";
import { SupplyService } from "./services/supply.service";
import { ChangeRangeSchema } from "./schemas/change-range.schema";
import { ChangeSupplyRange } from "./enums/change-supply-range.enum";
import { Range } from "@core/enums/range.enum";
import { GrowthRangeSchema } from "./schemas/growth-range.schema";

@Controller(Routes.SUPPLY)
export class SupplyController {
Expand All @@ -20,7 +20,7 @@ export class SupplyController {
@Get(SupplyEndpoints.HISTORICAL)
async getHistoricalSupply(
@Query(QueryParam.RANGE, new SchemaValidatePipe(HistoricalRangeSchema))
range: HistoricalSupplyRange,
range: Range,
) {
return this.cache.getCacheByRange(range);
}
Expand All @@ -33,8 +33,16 @@ export class SupplyController {
@Get(SupplyEndpoints.CHANGE)
async getSupplyChange(
@Query(QueryParam.RANGE, new SchemaValidatePipe(ChangeRangeSchema))
range: ChangeSupplyRange,
range: Range,
) {
return this.service.getSupplyChange(range);
}

@Get(SupplyEndpoints.GROWTH)
async getSupplyGrowth(
@Query(QueryParam.RANGE, new SchemaValidatePipe(GrowthRangeSchema))
range: Range,
) {
return this.service.getSupplyGrowth(range);
}
}

0 comments on commit 8121e07

Please sign in to comment.