diff --git a/app/apps/monitor-service/src/ethereum/ethereum.module.ts b/app/apps/monitor-service/src/ethereum/ethereum.module.ts index e3c6341..1fae74b 100644 --- a/app/apps/monitor-service/src/ethereum/ethereum.module.ts +++ b/app/apps/monitor-service/src/ethereum/ethereum.module.ts @@ -1,4 +1,4 @@ -import { EventHistoryModule } from '@app/shared_modules/event_history/event_history.module'; +import { EventHistoryModelModule } from '@app/shared_modules/event_history/event_history.module'; import { MonitorModule } from '@app/shared_modules/monitor/monitor.module'; import { ProjectModule } from '@app/shared_modules/project/project.module'; import { WebhookModule } from '@app/shared_modules/webhook/webhook.module'; @@ -32,7 +32,7 @@ import { EthereumService } from './ethereum.service'; WebhookModule, MonitorModule, ProjectModule, - EventHistoryModule, + EventHistoryModelModule, ], }) export class EthereumModule {} diff --git a/app/apps/onebox/src/main.module.ts b/app/apps/onebox/src/main.module.ts index 62e20ba..072234c 100644 --- a/app/apps/onebox/src/main.module.ts +++ b/app/apps/onebox/src/main.module.ts @@ -12,6 +12,7 @@ import { ProjectModule } from './modules/project/project.module'; import { UsersModule } from './modules/users/users.module'; import { PollingBlockService } from './polling.block/polling.block.service'; import { DeliveryModule } from './modules/delivery/delivery.module'; +import { EventHistoryModule } from './modules/event_history/event_history.module'; @Module({ imports: [ @@ -46,6 +47,7 @@ import { DeliveryModule } from './modules/delivery/delivery.module'; MonitorModule, MonitorAddressModule, DeliveryModule, + EventHistoryModule, ], providers: [GlobalService, PollingBlockService], }) diff --git a/app/apps/onebox/src/modules/event_history/dto/event_history.dto.ts b/app/apps/onebox/src/modules/event_history/dto/event_history.dto.ts new file mode 100644 index 0000000..e2109ce --- /dev/null +++ b/app/apps/onebox/src/modules/event_history/dto/event_history.dto.ts @@ -0,0 +1,127 @@ +import { + EventHistory, + WebhookCategory, + WebhookType, +} from '@app/shared_modules/event_history/schemas/event_history.schema'; +import { ApiProperty, ApiResponseProperty } from '@nestjs/swagger'; +import { Builder } from 'builder-pattern'; +import { Transform } from 'class-transformer'; +import { IsNotEmpty, Max, Min } from 'class-validator'; + +export class GetMonitorEventHistoryDto { + @ApiProperty() + @IsNotEmpty() + monitorId: string; + + // @ApiProperty({ required: false }) + // status?: 'succeeded' | 'pending' | 'failed'; + + @ApiProperty({ default: 10 }) + @Max(10) + @Min(1) + @Transform(({ value }) => parseInt(value)) + limit: number; + + @ApiProperty({ default: 0 }) + @Min(0) + @Transform(({ value }) => parseInt(value)) + offset: number; +} + +export class MonitorEventHistoryResponseDto { + @ApiResponseProperty() + eventId: string; // md5 of message exclude timestamp and confirm + + @ApiResponseProperty() + chain: string; + + @ApiResponseProperty() + monitorId: string; + + @ApiResponseProperty() + associatedAddress: string; + + @ApiResponseProperty() + hash: string; + + @ApiResponseProperty() + blockNum: number; // decimal string + + @ApiResponseProperty() + contract: { + address: string; + name: string; + symbol: string; + }; + + @ApiResponseProperty() + fromAddress: string; + + @ApiResponseProperty() + toAddress: string; + + @ApiResponseProperty() + tokenId: string; // decimal string + + @ApiResponseProperty() + tokenValue: string; // decimal string + + @ApiResponseProperty() + nativeAmount: string; // decimal string + + @ApiResponseProperty() + type: WebhookType; + + @ApiResponseProperty() + confirm: boolean; + + @ApiResponseProperty() + category: WebhookCategory; + + @ApiResponseProperty() + rawLog: { + topics: string[]; + data: string; + }; + + @ApiResponseProperty() + logIndex: number; + + @ApiResponseProperty() + txnIndex: number; + + @ApiResponseProperty() + tags: string[]; + + @ApiResponseProperty() + dateCreated: Date; + + @ApiResponseProperty() + deliveryIds: string[]; + + static from(dto: EventHistory): MonitorEventHistoryResponseDto { + return Builder() + .eventId(dto.eventId) + .chain(dto.chain) + .monitorId(dto.monitorId) + .associatedAddress(dto.associatedAddress) + .hash(dto.hash) + .blockNum(dto.blockNum) + .contract(dto.contract) + .fromAddress(dto.fromAddress) + .toAddress(dto.toAddress) + .tokenId(dto.tokenId) + .tokenValue(dto.tokenValue) + .nativeAmount(dto.nativeAmount) + .type(dto.type) + .confirm(dto.confirm) + .category(dto.category) + .rawLog(dto.rawLog) + .logIndex(dto.logIndex) + .txnIndex(dto.txnIndex) + .tags(dto.tags) + .dateCreated(dto.dateCreated) + .deliveryIds(dto.deliveryIds) + .build(); + } +} diff --git a/app/apps/onebox/src/modules/event_history/event_history.controller.ts b/app/apps/onebox/src/modules/event_history/event_history.controller.ts new file mode 100644 index 0000000..d57f9c5 --- /dev/null +++ b/app/apps/onebox/src/modules/event_history/event_history.controller.ts @@ -0,0 +1,36 @@ +import { Controller, Get, Query, Req, UseGuards } from '@nestjs/common'; +import { + ApiBearerAuth, + ApiOkResponse, + ApiOperation, + ApiTags, +} from '@nestjs/swagger'; +import { Request } from 'express'; +import { JwtAuthGuard } from '../auth/guards/jwt-auth.guard'; +import { User } from '../users/schemas/user.schema'; +import { + GetMonitorEventHistoryDto, + MonitorEventHistoryResponseDto, +} from './dto/event_history.dto'; +import { EventHistoryService } from './event_history.service'; + +@ApiTags('Monitor Event History') +@Controller('/event') +export class EventHistoryController { + constructor(private readonly eventHistoryService: EventHistoryService) {} + + @ApiOperation({ summary: 'Get Monitor Event' }) + @ApiBearerAuth('JWT') + @UseGuards(JwtAuthGuard) + @Get('') + @ApiOkResponse({ type: [MonitorEventHistoryResponseDto] }) + async getMonitorEvent( + @Req() req: Request, + @Query() body: GetMonitorEventHistoryDto, + ): Promise { + return await this.eventHistoryService.getMonitorEventHistory( + req.user as User, + body, + ); + } +} diff --git a/app/apps/onebox/src/modules/event_history/event_history.module.ts b/app/apps/onebox/src/modules/event_history/event_history.module.ts new file mode 100644 index 0000000..316b943 --- /dev/null +++ b/app/apps/onebox/src/modules/event_history/event_history.module.ts @@ -0,0 +1,12 @@ +import { EventHistoryModelModule } from '@app/shared_modules/event_history/event_history.module'; +import { Module } from '@nestjs/common'; +import { MonitorModule } from '../monitor/monitor.module'; +import { EventHistoryController } from './event_history.controller'; +import { EventHistoryService } from './event_history.service'; +@Module({ + controllers: [EventHistoryController], + providers: [EventHistoryService], + exports: [EventHistoryService], + imports: [EventHistoryModelModule, MonitorModule], +}) +export class EventHistoryModule {} diff --git a/app/apps/onebox/src/modules/event_history/event_history.service.ts b/app/apps/onebox/src/modules/event_history/event_history.service.ts new file mode 100644 index 0000000..9a66c42 --- /dev/null +++ b/app/apps/onebox/src/modules/event_history/event_history.service.ts @@ -0,0 +1,42 @@ +import { EthEventHistoryRepository } from '@app/shared_modules/event_history/repositories/event_history.repository'; +import { Inject, Injectable, Logger } from '@nestjs/common'; +import { MonitorService } from '../monitor/monitor.service'; +import { User } from '../users/schemas/user.schema'; +import { + GetMonitorEventHistoryDto, + MonitorEventHistoryResponseDto, +} from './dto/event_history.dto'; +import { MonitorNetwork } from '@app/shared_modules/monitor/schemas/monitor.schema'; +import { ErrorCode } from '@app/global/global.error'; + +@Injectable() +export class EventHistoryService { + private readonly logger = new Logger(EventHistoryService.name); + constructor( + private readonly ethEventHistoryRepository: EthEventHistoryRepository, + private readonly monitorService: MonitorService, + ) {} + + async getMonitorEventHistory( + user: User, + request: GetMonitorEventHistoryDto, + ): Promise { + const monitor = await this.monitorService.findAndAuthMonitor( + user, + request.monitorId, + ); + + if (monitor.network === MonitorNetwork.Ethereum) { + return this.ethEventHistoryRepository + .getEventHistory(monitor.monitorId, request.limit, request.offset) + .then((response) => { + return response.map((event) => + MonitorEventHistoryResponseDto.from(event), + ); + }); + } + + this.logger.error(`network ${monitor.network} not supported`); + throw ErrorCode.INTERNAL_SERVER_ERROR.asException(); + } +} diff --git a/app/libs/shared_modules/src/event_history/event_history.module.ts b/app/libs/shared_modules/src/event_history/event_history.module.ts index 405b7fe..6a17d20 100644 --- a/app/libs/shared_modules/src/event_history/event_history.module.ts +++ b/app/libs/shared_modules/src/event_history/event_history.module.ts @@ -19,4 +19,4 @@ import { EventHistoryProviders } from './event_history.provider'; BscEventHistoryRepository, ], }) -export class EventHistoryModule {} +export class EventHistoryModelModule {} diff --git a/app/libs/shared_modules/src/shared_modules.module.ts b/app/libs/shared_modules/src/shared_modules.module.ts index c83988d..769f6e7 100644 --- a/app/libs/shared_modules/src/shared_modules.module.ts +++ b/app/libs/shared_modules/src/shared_modules.module.ts @@ -3,11 +3,22 @@ import { SharedModulesService } from './shared_modules.service'; import { MonitorModule } from './monitor/monitor.module'; import { ProjectModule } from './project/project.module'; import { WebhookModule } from './webhook/webhook.module'; -import { EventHistoryModule } from './event_history/event_history.module'; +import { EventHistoryModelModule } from './event_history/event_history.module'; @Module({ - imports: [MonitorModule, ProjectModule, WebhookModule, EventHistoryModule], + imports: [ + MonitorModule, + ProjectModule, + WebhookModule, + EventHistoryModelModule, + ], providers: [SharedModulesService], - exports: [SharedModulesService, MonitorModule, ProjectModule, WebhookModule], + exports: [ + SharedModulesService, + MonitorModule, + ProjectModule, + WebhookModule, + EventHistoryModelModule, + ], }) export class SharedModulesModule {}