From 58b5b10c0dc40601f780220619533c91c88d9fbc Mon Sep 17 00:00:00 2001 From: Roman Petriv Date: Wed, 6 Mar 2024 12:53:28 +0200 Subject: [PATCH] feat: add transfer type filter for address transfers BFF API --- .../api/src/address/address.controller.ts | 17 ++++++++++---- .../dtos/filterAddressTransfersOptions.dto.ts | 13 +++++++++++ packages/api/src/address/dtos/index.ts | 1 + packages/api/src/common/types.ts | 2 ++ .../src/transfer/addressTransfer.entity.ts | 6 ++++- packages/api/src/transfer/transfer.service.ts | 3 ++- .../src/entities/addressTransfer.entity.ts | 6 ++++- .../1709722093204-AddAddressTransferType.ts | 23 +++++++++++++++++++ 8 files changed, 63 insertions(+), 8 deletions(-) create mode 100644 packages/api/src/address/dtos/filterAddressTransfersOptions.dto.ts create mode 100644 packages/worker/src/migrations/1709722093204-AddAddressTransferType.ts diff --git a/packages/api/src/address/address.controller.ts b/packages/api/src/address/address.controller.ts index 70f18a078c..015cb9280c 100644 --- a/packages/api/src/address/address.controller.ts +++ b/packages/api/src/address/address.controller.ts @@ -17,7 +17,7 @@ import { AddressService } from "./address.service"; import { BlockService } from "../block/block.service"; import { TransactionService } from "../transaction/transaction.service"; import { BalanceService } from "../balance/balance.service"; -import { AddressType, ContractDto, AccountDto, TokenAddressDto } from "./dtos"; +import { AddressType, ContractDto, AccountDto, TokenAddressDto, FilterAddressTransfersOptionsDto } from "./dtos"; import { LogDto } from "../log/log.dto"; import { LogService } from "../log/log.service"; import { ParseAddressPipe, ADDRESS_REGEX_PATTERN } from "../common/pipes/parseAddress.pipe"; @@ -140,19 +140,26 @@ export class AddressController { }) public async getAddressTransfers( @Param("address", new ParseAddressPipe()) address: string, + @Query() filterAddressTransferOptions: FilterAddressTransfersOptionsDto, @Query() listFilterOptions: ListFiltersDto, @Query() pagingOptions: PagingOptionsWithMaxItemsLimitDto ): Promise> { - const filterTransactionsListOptions = buildDateFilter(listFilterOptions.fromDate, listFilterOptions.toDate); + const filterTransfersListOptions = buildDateFilter(listFilterOptions.fromDate, listFilterOptions.toDate); return await this.transferService.findAll( { address, - isFeeOrRefund: false, - ...filterTransactionsListOptions, + ...filterTransfersListOptions, + ...(filterAddressTransferOptions.type + ? { + type: filterAddressTransferOptions.type, + } + : { + isFeeOrRefund: false, + }), }, { - filterOptions: listFilterOptions, + filterOptions: { ...filterAddressTransferOptions, ...listFilterOptions }, ...pagingOptions, route: `${entityName}/${address}/transfers`, } diff --git a/packages/api/src/address/dtos/filterAddressTransfersOptions.dto.ts b/packages/api/src/address/dtos/filterAddressTransfersOptions.dto.ts new file mode 100644 index 0000000000..c74c33c53b --- /dev/null +++ b/packages/api/src/address/dtos/filterAddressTransfersOptions.dto.ts @@ -0,0 +1,13 @@ +import { ApiPropertyOptional } from "@nestjs/swagger"; +import { IsOptional } from "class-validator"; +import { TransferType } from "../../transfer/transfer.entity"; + +export class FilterAddressTransfersOptionsDto { + @ApiPropertyOptional({ + description: "Transfer type to filter transfers by", + example: TransferType.Transfer, + enum: TransferType, + }) + @IsOptional() + public readonly type?: TransferType; +} diff --git a/packages/api/src/address/dtos/index.ts b/packages/api/src/address/dtos/index.ts index 9d9d6027c2..cbd3966dd4 100644 --- a/packages/api/src/address/dtos/index.ts +++ b/packages/api/src/address/dtos/index.ts @@ -1,3 +1,4 @@ export * from "./account.dto"; export * from "./baseAddress.dto"; export * from "./contract.dto"; +export * from "./filterAddressTransfersOptions.dto"; diff --git a/packages/api/src/common/types.ts b/packages/api/src/common/types.ts index 743cd580ca..4977f91f51 100644 --- a/packages/api/src/common/types.ts +++ b/packages/api/src/common/types.ts @@ -1,4 +1,5 @@ import { IPaginationOptions as NestIPaginationOptions, IPaginationMeta } from "nestjs-typeorm-paginate"; +import { TransferType } from "../transfer/transfer.entity"; interface IPaginationFilterOptions { fromDate?: string; @@ -7,6 +8,7 @@ interface IPaginationFilterOptions { address?: string; l1BatchNumber?: number; minLiquidity?: number; + type?: TransferType; } export interface IPaginationOptions extends NestIPaginationOptions { diff --git a/packages/api/src/transfer/addressTransfer.entity.ts b/packages/api/src/transfer/addressTransfer.entity.ts index 65e9677020..fad65ae22f 100644 --- a/packages/api/src/transfer/addressTransfer.entity.ts +++ b/packages/api/src/transfer/addressTransfer.entity.ts @@ -1,12 +1,13 @@ import { Entity, Column, Index, ManyToOne, JoinColumn, PrimaryColumn } from "typeorm"; import { BaseEntity } from "../common/entities/base.entity"; -import { Transfer } from "./transfer.entity"; +import { Transfer, TransferType } from "./transfer.entity"; import { TokenType } from "../token/token.entity"; import { bigIntNumberTransformer } from "../common/transformers/bigIntNumber.transformer"; import { normalizeAddressTransformer } from "../common/transformers/normalizeAddress.transformer"; @Entity({ name: "addressTransfers" }) @Index(["address", "isFeeOrRefund", "timestamp", "logIndex"]) +@Index(["address", "type", "timestamp", "logIndex"]) @Index(["address", "tokenType", "blockNumber", "logIndex"]) @Index(["address", "tokenAddress", "blockNumber", "logIndex"]) export class AddressTransfer extends BaseEntity { @@ -34,6 +35,9 @@ export class AddressTransfer extends BaseEntity { @Column({ type: "timestamp" }) public readonly timestamp: Date; + @Column({ type: "enum", enum: TransferType, default: TransferType.Transfer }) + public readonly type: TransferType; + @Column({ type: "enum", enum: TokenType, default: TokenType.ETH }) public readonly tokenType: TokenType; diff --git a/packages/api/src/transfer/transfer.service.ts b/packages/api/src/transfer/transfer.service.ts index 98ce2a2b6b..5491954d99 100644 --- a/packages/api/src/transfer/transfer.service.ts +++ b/packages/api/src/transfer/transfer.service.ts @@ -4,7 +4,7 @@ import { Repository, FindOperator, MoreThanOrEqual, LessThanOrEqual } from "type import { Pagination } from "nestjs-typeorm-paginate"; import { paginate } from "../common/utils"; import { IPaginationOptions, SortingOrder } from "../common/types"; -import { Transfer } from "./transfer.entity"; +import { Transfer, TransferType } from "./transfer.entity"; import { TokenType } from "../token/token.entity"; import { AddressTransfer } from "./addressTransfer.entity"; import { normalizeAddressTransformer } from "../common/transformers/normalizeAddress.transformer"; @@ -15,6 +15,7 @@ export interface FilterTransfersOptions { address?: string; timestamp?: FindOperator; isFeeOrRefund?: boolean; + type?: TransferType; } export interface FilterTokenTransfersOptions { diff --git a/packages/worker/src/entities/addressTransfer.entity.ts b/packages/worker/src/entities/addressTransfer.entity.ts index 22fb701c39..b6b41757a4 100644 --- a/packages/worker/src/entities/addressTransfer.entity.ts +++ b/packages/worker/src/entities/addressTransfer.entity.ts @@ -1,7 +1,7 @@ import { Entity, Column, ManyToOne, JoinColumn, Index, PrimaryColumn } from "typeorm"; import { BaseEntity } from "./base.entity"; import { Block } from "./block.entity"; -import { Transfer } from "./transfer.entity"; +import { Transfer, TransferType } from "./transfer.entity"; import { TokenType } from "./token.entity"; import { hexTransformer } from "../transformers/hex.transformer"; import { bigIntNumberTransformer } from "../transformers/bigIntNumber.transformer"; @@ -9,6 +9,7 @@ import { TransferFields } from "../dataFetcher/types"; @Entity({ name: "addressTransfers" }) @Index(["address", "isFeeOrRefund", "timestamp", "logIndex"]) +@Index(["address", "type", "timestamp", "logIndex"]) @Index(["address", "tokenAddress", "blockNumber", "logIndex"]) @Index(["address", "tokenType", "blockNumber", "logIndex"]) @Index(["address", "isInternal", "blockNumber", "logIndex"]) @@ -41,6 +42,9 @@ export class AddressTransfer extends BaseEntity { @Column({ type: "timestamp" }) public readonly timestamp: string; + @Column({ type: "enum", enum: TransferType, default: TransferType.Transfer }) + public readonly type: TransferType; + @Column({ type: "enum", enum: TokenType, default: TokenType.ETH }) public readonly tokenType: TokenType; diff --git a/packages/worker/src/migrations/1709722093204-AddAddressTransferType.ts b/packages/worker/src/migrations/1709722093204-AddAddressTransferType.ts new file mode 100644 index 0000000000..bb5f79b330 --- /dev/null +++ b/packages/worker/src/migrations/1709722093204-AddAddressTransferType.ts @@ -0,0 +1,23 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class AddAddressTransferType1709722093204 implements MigrationInterface { + name = "AddAddressTransferType1709722093204"; + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `CREATE TYPE "public"."addressTransfers_type_enum" AS ENUM('deposit', 'transfer', 'withdrawal', 'fee', 'mint', 'refund')` + ); + await queryRunner.query( + `ALTER TABLE "addressTransfers" ADD "type" "public"."addressTransfers_type_enum" NOT NULL DEFAULT 'transfer'` + ); + await queryRunner.query( + `CREATE INDEX "IDX_aa5a147f1f6a4acde1a13de594" ON "addressTransfers" ("address", "type", "timestamp", "logIndex") ` + ); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(`DROP INDEX "public"."IDX_aa5a147f1f6a4acde1a13de594"`); + await queryRunner.query(`ALTER TABLE "addressTransfers" DROP COLUMN "type"`); + await queryRunner.query(`DROP TYPE "public"."addressTransfers_type_enum"`); + } +}