Skip to content

Commit

Permalink
Merge pull request #223 from sotatek-dev/develop
Browse files Browse the repository at this point in the history
Develop
  • Loading branch information
Sotatek-TanHoang authored Dec 27, 2024
2 parents ead0e5c + 3ac9e23 commit 62ef258
Show file tree
Hide file tree
Showing 9 changed files with 209 additions and 0 deletions.
86 changes: 86 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@
"passport": "^0.7.0",
"passport-jwt": "^4.0.1",
"pg": "^8.11.3",
"redis": "^4.7.0",
"reflect-metadata": "^0.1.13",
"rxjs": "^7.8.1",
"typeorm": "^0.3.17",
Expand Down
2 changes: 2 additions & 0 deletions src/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { CustomAuthorizationHeaderMiddleware } from './shared/middleware/custom-
import { LoggerHttpRequestMiddleware } from './shared/middleware/logger-http-request.middleware.js';
import { LoggingModule } from './shared/modules/logger/logger.module.js';
import { QueueModule } from './shared/modules/queue/queue.module.js';
import { RedisModule } from './shared/modules/redis/redis.module.js';
import { Web3Module } from './shared/modules/web3/web3.module.js';
import { isDevelopmentEnvironment } from './shared/utils/util.js';

Expand All @@ -21,6 +22,7 @@ const modules = [
DatabaseModule,
ScheduleModule.forRoot(),
LoggingModule,
RedisModule,
GuardModule,
Web3Module,
QueueModule,
Expand Down
9 changes: 9 additions & 0 deletions src/modules/users/dto/estimate-bridge-request.dto.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { ENetworkName } from '../../../constants/blockchain.constant.js';
import { StringField } from '../../../shared/decorators/field.decorator.js';

export class EstimateBridgeRequestDto {
@StringField({
enum: ENetworkName,
})
receivedNetwork: ENetworkName;
}
10 changes: 10 additions & 0 deletions src/modules/users/dto/user-response.dto.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { ApiProperty } from '@nestjs/swagger';

import { ENetworkName } from '../../../constants/blockchain.constant.js';

export class GetProfileResponseDto {
@ApiProperty()
id: number;
Expand Down Expand Up @@ -69,3 +71,11 @@ export class GetProofOfAssetsResponseDto {
@ApiProperty({ example: '2345' })
totalWethInCirculation: string;
}

export class EstimateBridgeResponseDto {
@ApiProperty()
receivedNetwork: ENetworkName;

@ApiProperty({ description: 'time to wait in seconds' })
completeTimeEstimated: number;
}
11 changes: 11 additions & 0 deletions src/modules/users/users.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@ import { ApiOkResponse, ApiTags } from '@nestjs/swagger';

import { ETableName } from '../../constants/entity.constant.js';
import { GuardPublic } from '../../guards/guard.decorator.js';
import { EstimateBridgeRequestDto } from './dto/estimate-bridge-request.dto.js';
import { GetHistoryOfUserDto, GetHistoryOfUserResponseDto } from './dto/history-response.dto.js';
import { GetProtocolFeeBodyDto } from './dto/user-request.dto.js';
import {
EstimateBridgeResponseDto,
GetListTokenPairResponseDto,
GetProofOfAssetsResponseDto,
GetProtocolFeeResponseDto,
Expand Down Expand Up @@ -58,4 +60,13 @@ export class UsersController {
getProofOfAssets() {
return this.userService.getProofOfAssets();
}

@Get('estimate')
@GuardPublic()
@ApiOkResponse({
type: EstimateBridgeResponseDto,
})
estimateBridgeTime(@Query() dto: EstimateBridgeRequestDto) {
return this.userService.estimateBridgeTime(dto.receivedNetwork);
}
}
20 changes: 20 additions & 0 deletions src/modules/users/users.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { TokenPriceRepository } from '../../database/repositories/token-price.re
import { UserRepository } from '../../database/repositories/user.repository.js';
import { httpBadRequest, httpNotFound } from '../../shared/exceptions/http-exeption.js';
import { LoggerService } from '../../shared/modules/logger/logger.service.js';
import { RedisClientService } from '../../shared/modules/redis/redis-client.service.js';
import { addDecimal } from '../../shared/utils/bignumber.js';
import { UpdateCommonConfigBodyDto } from './dto/common-config-request.dto.js';
import { GetHistoryDto, GetHistoryOfUserDto } from './dto/history-response.dto.js';
Expand All @@ -31,6 +32,7 @@ export class UsersService {
private readonly loggerService: LoggerService,
private readonly tokenPriceRepository: TokenPriceRepository,
private readonly tokenPairRepostitory: TokenPairRepository,
private readonly redisClientService: RedisClientService,
) {}
private readonly logger = this.loggerService.getLogger('USER_SERVICE');
async getProfile(userId: number) {
Expand Down Expand Up @@ -131,4 +133,22 @@ export class UsersService {
totalWethInCirculation,
};
}
calcWaitingTime(receivedNetwork: ENetworkName, currentPendingTx: number): number {
const receivedNetworkEstWaiting = {
[ENetworkName.MINA]: 10 * 60 * currentPendingTx,
[ENetworkName.ETH]: 10 * currentPendingTx,
};
// total waiting tx * time_process_each + crawler delays from both lock and unlock
return receivedNetworkEstWaiting[receivedNetwork] + 60 + 60 * 15;
}
async estimateBridgeTime(receivedNetwork: ENetworkName) {
const result = {
receivedNetwork,
completeTimeEstimated: this.calcWaitingTime(
receivedNetwork,
await this.redisClientService.getCountWaitingTx(receivedNetwork),
),
};
return result;
}
}
60 changes: 60 additions & 0 deletions src/shared/modules/redis/redis-client.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import { Injectable, OnModuleDestroy, OnModuleInit } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { createClient, RedisClientType } from 'redis';

import { ENetworkName } from '../../../constants/blockchain.constant.js';
import { EEnvKey } from '../../../constants/env.constant.js';

@Injectable()
export class RedisClientService implements OnModuleInit, OnModuleDestroy {
private client: RedisClientType;
constructor(private readonly configService: ConfigService) {
this.client = createClient({
url: `redis://${configService.get(EEnvKey.REDIS_HOST)}:${configService.get(EEnvKey.REDIS_PORT)}`,
});
}
async onModuleInit() {
await this.client.connect();
}
async onModuleDestroy() {
await this.client.disconnect();
}
// noti
// public async getCurrentNotificationCount(address: string): Promise<number> {
// const res = await this.client.get(`not_count_${address}`);
// return Number(res).valueOf();
// }
// public async incrNotificationCount(address: string): Promise<number> {
// return this.client.incr(`not_count_${address}`);
// }

// public async resetNotificationCount(address: string) {
// return this.client.set(`not_count_${address}`, 0);
// }
// estimate bridge time
async getCountWaitingTx(network: ENetworkName): Promise<number> {
const res = await this.client.get(`waiting_tx_${network}`);
return Number(res).valueOf();
}
public async initCountWaitingTx(network: ENetworkName, initValue: number) {
return this.client.set(`waiting_tx_${network}`, initValue);
}
public async incrCountWaitingTx(network: ENetworkName): Promise<number> {
return this.client.incr(`waiting_tx_${network}`);
}

public async decrCountWaitingTx(network: ENetworkName) {
return this.client.eval(`
local key='waiting_tx_${network}'
local current_value = tonumber(redis.call('GET', key) or 0)
if current_value == 0 then
return current_value
else
-- Decrement the value by 1
local new_value = current_value - 1
redis.call('SET', key, new_value)
return new_value
end
`);
}
}
10 changes: 10 additions & 0 deletions src/shared/modules/redis/redis.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { Global, Module } from '@nestjs/common';

import { RedisClientService } from './redis-client.service.js';

@Global()
@Module({
providers: [RedisClientService],
exports: [RedisClientService],
})
export class RedisModule {}

0 comments on commit 62ef258

Please sign in to comment.