From 96edc0aa5f4c329676419ece5de5665468c5039f Mon Sep 17 00:00:00 2001 From: cauta Date: Fri, 17 May 2024 15:34:06 +0700 Subject: [PATCH 1/2] feat: add event history api - get event by monitor and hash - get event by monitor and eventId - get event by monitor and associated address --- .../event_history/dto/event_history.dto.ts | 24 ++- .../event_history/event_history.controller.ts | 48 ++++++ .../event_history/event_history.service.ts | 162 ++++++++++++++++++ .../src/modules/monitor/dto/monitor.dto.ts | 4 +- .../repositories/event_history.repository.ts | 21 ++- 5 files changed, 250 insertions(+), 9 deletions(-) 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 index e2109ce..3ab4472 100644 --- 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 @@ -9,7 +9,7 @@ import { Transform } from 'class-transformer'; import { IsNotEmpty, Max, Min } from 'class-validator'; export class GetMonitorEventHistoryDto { - @ApiProperty() + @ApiProperty({ required: true }) @IsNotEmpty() monitorId: string; @@ -28,6 +28,28 @@ export class GetMonitorEventHistoryDto { offset: number; } +export class GetMonitorEventHistoryByAssociatedAddressDto extends GetMonitorEventHistoryDto { + @ApiProperty({ required: true }) + @IsNotEmpty() + associatedAddress: string; +} + +export class GetMonitorEventHistoryByHashDto extends GetMonitorEventHistoryDto { + @ApiProperty({ required: true }) + @IsNotEmpty() + hash: string; +} + +export class GetMonitorEventHistoryByEventIdDto { + @ApiProperty({ required: true }) + @IsNotEmpty() + monitorId: string; + + @ApiProperty({ required: true }) + @IsNotEmpty() + eventId: string; +} + export class MonitorEventHistoryResponseDto { @ApiResponseProperty() eventId: string; // md5 of message exclude timestamp and confirm 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 index d57f9c5..087427b 100644 --- a/app/apps/onebox/src/modules/event_history/event_history.controller.ts +++ b/app/apps/onebox/src/modules/event_history/event_history.controller.ts @@ -9,6 +9,9 @@ import { Request } from 'express'; import { JwtAuthGuard } from '../auth/guards/jwt-auth.guard'; import { User } from '../users/schemas/user.schema'; import { + GetMonitorEventHistoryByAssociatedAddressDto, + GetMonitorEventHistoryByEventIdDto, + GetMonitorEventHistoryByHashDto, GetMonitorEventHistoryDto, MonitorEventHistoryResponseDto, } from './dto/event_history.dto'; @@ -33,4 +36,49 @@ export class EventHistoryController { body, ); } + + @ApiOperation({ summary: 'Get Monitor Event History By Transaction Hash' }) + @ApiBearerAuth('JWT') + @UseGuards(JwtAuthGuard) + @Get('by-hash') + @ApiOkResponse({ type: [MonitorEventHistoryResponseDto] }) + async getMonitorEventHistoryByTxnHash( + @Req() req: Request, + @Query() body: GetMonitorEventHistoryByHashDto, + ): Promise { + return await this.eventHistoryService.getMonitorEventHistoryByTxnHash( + req.user as User, + body, + ); + } + + @ApiOperation({ summary: 'Get Monitor Event History By Event Id' }) + @ApiBearerAuth('JWT') + @UseGuards(JwtAuthGuard) + @Get('by-event-id') + @ApiOkResponse({ type: [MonitorEventHistoryResponseDto] }) + async getMonitorEventHistoryByEventId( + @Req() req: Request, + @Query() body: GetMonitorEventHistoryByEventIdDto, + ): Promise { + return await this.eventHistoryService.getMonitorEventHistoryByEventId( + req.user as User, + body, + ); + } + + @ApiOperation({ summary: 'Get Monitor Event History By Associated Address' }) + @ApiBearerAuth('JWT') + @UseGuards(JwtAuthGuard) + @Get('by-address') + @ApiOkResponse({ type: [MonitorEventHistoryResponseDto] }) + async getMonitorEventHistoryByAssociatedAddress( + @Req() req: Request, + @Query() body: GetMonitorEventHistoryByAssociatedAddressDto, + ): Promise { + return await this.eventHistoryService.getMonitorEventHistoryByAssociatedAddress( + req.user as User, + body, + ); + } } 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 index a4c8ff6..0543247 100644 --- a/app/apps/onebox/src/modules/event_history/event_history.service.ts +++ b/app/apps/onebox/src/modules/event_history/event_history.service.ts @@ -9,6 +9,9 @@ import { Injectable, Logger } from '@nestjs/common'; import { MonitorService } from '../monitor/monitor.service'; import { User } from '../users/schemas/user.schema'; import { + GetMonitorEventHistoryByAssociatedAddressDto, + GetMonitorEventHistoryByEventIdDto, + GetMonitorEventHistoryByHashDto, GetMonitorEventHistoryDto, MonitorEventHistoryResponseDto, } from './dto/event_history.dto'; @@ -69,4 +72,163 @@ export class EventHistoryService { this.logger.error(`network ${monitor.network} not supported`); throw ErrorCode.INTERNAL_SERVER_ERROR.asException(); } + + async getMonitorEventHistoryByTxnHash( + user: User, + request: GetMonitorEventHistoryByHashDto, + ): Promise { + const monitor = await this.monitorService.findAndAuthMonitor( + user, + request.monitorId, + ); + + if (!monitor) { + throw ErrorCode.MONITOR_NOT_FOUND.asException(); + } + if (monitor.network === MonitorNetwork.Ethereum) { + return this.ethEventHistoryRepository + .findEventHistoryByMonitorAndHash( + monitor.monitorId, + request.hash, + request.limit, + request.offset, + ) + .then((response) => { + return response.map((event) => + MonitorEventHistoryResponseDto.from(event), + ); + }); + } + if (monitor.network === MonitorNetwork.Polygon) { + return this.polygonEventHistoryRepository + .findEventHistoryByMonitorAndHash( + monitor.monitorId, + request.hash, + request.limit, + request.offset, + ) + .then((response) => { + return response.map((event) => + MonitorEventHistoryResponseDto.from(event), + ); + }); + } + + if (monitor.network === MonitorNetwork.Avalanche) { + return this.avaxEventHistoryRepository + .findEventHistoryByMonitorAndHash( + monitor.monitorId, + request.hash, + 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(); + } + + async getMonitorEventHistoryByAssociatedAddress( + user: User, + request: GetMonitorEventHistoryByAssociatedAddressDto, + ): Promise { + const monitor = await this.monitorService.findAndAuthMonitor( + user, + request.monitorId, + ); + + if (!monitor) { + throw ErrorCode.MONITOR_NOT_FOUND.asException(); + } + if (monitor.network === MonitorNetwork.Ethereum) { + return this.ethEventHistoryRepository + .findByMonitorAndAssociatedAddress( + monitor.monitorId, + request.associatedAddress, + request.limit, + request.offset, + ) + .then((response) => { + return response.map((event) => + MonitorEventHistoryResponseDto.from(event), + ); + }); + } + if (monitor.network === MonitorNetwork.Polygon) { + return this.polygonEventHistoryRepository + .findEventHistoryByMonitorAndHash( + monitor.monitorId, + request.associatedAddress, + request.limit, + request.offset, + ) + .then((response) => { + return response.map((event) => + MonitorEventHistoryResponseDto.from(event), + ); + }); + } + + if (monitor.network === MonitorNetwork.Avalanche) { + return this.avaxEventHistoryRepository + .findEventHistoryByMonitorAndHash( + monitor.monitorId, + request.associatedAddress, + 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(); + } + + async getMonitorEventHistoryByEventId( + user: User, + request: GetMonitorEventHistoryByEventIdDto, + ): Promise { + const monitor = await this.monitorService.findAndAuthMonitor( + user, + request.monitorId, + ); + + if (!monitor) { + throw ErrorCode.MONITOR_NOT_FOUND.asException(); + } + if (monitor.network === MonitorNetwork.Ethereum) { + return this.ethEventHistoryRepository + .findByEventId(request.eventId) + .then((response) => { + return MonitorEventHistoryResponseDto.from(response); + }); + } + if (monitor.network === MonitorNetwork.Polygon) { + return this.polygonEventHistoryRepository + .findByEventId(request.eventId) + .then((response) => { + return MonitorEventHistoryResponseDto.from(response); + }); + } + + if (monitor.network === MonitorNetwork.Avalanche) { + return this.avaxEventHistoryRepository + .findByEventId(request.eventId) + .then((response) => { + return MonitorEventHistoryResponseDto.from(response); + }); + } + + this.logger.error(`network ${monitor.network} not supported`); + throw ErrorCode.INTERNAL_SERVER_ERROR.asException(); + } } diff --git a/app/apps/onebox/src/modules/monitor/dto/monitor.dto.ts b/app/apps/onebox/src/modules/monitor/dto/monitor.dto.ts index 775147f..93e4d24 100644 --- a/app/apps/onebox/src/modules/monitor/dto/monitor.dto.ts +++ b/app/apps/onebox/src/modules/monitor/dto/monitor.dto.ts @@ -26,7 +26,7 @@ import { export class MonitorConditionDto { @ApiProperty({ default: true }) native: boolean; - @ApiProperty({ default: true }) + @ApiProperty({ default: false }) internal: boolean; @ApiProperty({ default: true }) erc721: boolean; @@ -104,7 +104,7 @@ export class CreateMonitorDto { @ApiProperty({ example: { native: true, - internal: true, + internal: false, erc721: true, erc20: true, specific: false, diff --git a/app/libs/shared_modules/src/event_history/repositories/event_history.repository.ts b/app/libs/shared_modules/src/event_history/repositories/event_history.repository.ts index 80a00c3..c4f0910 100644 --- a/app/libs/shared_modules/src/event_history/repositories/event_history.repository.ts +++ b/app/libs/shared_modules/src/event_history/repositories/event_history.repository.ts @@ -26,13 +26,16 @@ export class EventHistoryRepository { } async findByMonitorAndAssociatedAddress( - monitor: string, + monitorId: string, associatedAddress: string, + limit: number, + offset: number, ): Promise { - return this.model.find({ - monitorId: monitor, - associatedAddress: associatedAddress, - }); + return this.model + .find({ monitorId: monitorId, associatedAddress: associatedAddress }) + .limit(limit) + .skip(offset) + .sort({ dateCreated: -1 }); } async getEventHistory( @@ -50,8 +53,14 @@ export class EventHistoryRepository { async findEventHistoryByMonitorAndHash( monitorId: string, hash: string, + limit: number, + offset: number, ): Promise { - return this.model.find({ monitorId: monitorId, hash: hash }); + return this.model + .find({ monitorId: monitorId, hash: hash }) + .limit(limit) + .skip(offset) + .sort({ dateCreated: -1 }); } async pushConfirmDeliveryId(eventId: string, deliveryId: string) { From 8d88561bfa36600f9fd4a2a98533a4136f5a1a20 Mon Sep 17 00:00:00 2001 From: cauta Date: Fri, 17 May 2024 16:01:08 +0700 Subject: [PATCH 2/2] open support for mantle --- app/libs/global/src/global.controller.ts | 4 ++++ app/libs/utils/src/supportedChain.util.ts | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/app/libs/global/src/global.controller.ts b/app/libs/global/src/global.controller.ts index bb63bce..4890d8b 100644 --- a/app/libs/global/src/global.controller.ts +++ b/app/libs/global/src/global.controller.ts @@ -24,6 +24,10 @@ export class GlobalController { ...SupportedChain.BSC, enable: process.env.BSC_DISABLE === 'false', }, + { + ...SupportedChain.MANTLE, + enable: process.env.MANTLE_DISABLE === 'false', + }, ]; } diff --git a/app/libs/utils/src/supportedChain.util.ts b/app/libs/utils/src/supportedChain.util.ts index 99e9a31..a2fc943 100644 --- a/app/libs/utils/src/supportedChain.util.ts +++ b/app/libs/utils/src/supportedChain.util.ts @@ -49,7 +49,7 @@ export class SupportedChain { idHex: '0x2105', name: 'Base', confirmationBlock: 50, - explorer: 'https://basescan.org/', + explorer: 'https://basescan.org', nativeCurrency: 'BASE', };