Skip to content

Commit

Permalink
feat: add min liquidity filter for tokens list API (#79)
Browse files Browse the repository at this point in the history
# What ❔

- Adds min liquidity filters for /tokens API

## Why ❔

- front-end will be able to fetch all tokens with liquidity
  • Loading branch information
Romsters authored Nov 7, 2023
1 parent 6d2a403 commit 04429f6
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 13 deletions.
4 changes: 2 additions & 2 deletions packages/api/src/token/token.controller.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,9 @@ describe("TokenController", () => {
});

it("queries tokens with the specified options", async () => {
await controller.getTokens(pagingOptions);
await controller.getTokens(pagingOptions, 1000);
expect(serviceMock.findAll).toHaveBeenCalledTimes(1);
expect(serviceMock.findAll).toHaveBeenCalledWith({ ...pagingOptions, route: "tokens" });
expect(serviceMock.findAll).toHaveBeenCalledWith({ minLiquidity: 1000 }, { ...pagingOptions, route: "tokens" });
});

it("returns the tokens", async () => {
Expand Down
27 changes: 22 additions & 5 deletions packages/api/src/token/token.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
ApiBadRequestResponse,
ApiNotFoundResponse,
ApiExcludeController,
ApiQuery,
} from "@nestjs/swagger";
import { Pagination } from "nestjs-typeorm-paginate";
import { PagingOptionsDto, PagingOptionsWithMaxItemsLimitDto } from "../common/dtos";
Expand All @@ -14,6 +15,7 @@ import { TokenService } from "./token.service";
import { TransferService } from "../transfer/transfer.service";
import { TokenDto } from "./token.dto";
import { TransferDto } from "../transfer/transfer.dto";
import { ParseLimitedIntPipe } from "../common/pipes/parseLimitedInt.pipe";
import { ParseAddressPipe, ADDRESS_REGEX_PATTERN } from "../common/pipes/parseAddress.pipe";
import { swagger } from "../config/featureFlags";
import { constants } from "../config/docs";
Expand All @@ -29,11 +31,26 @@ export class TokenController {
@Get("")
@ApiListPageOkResponse(TokenDto, { description: "Successfully returned token list" })
@ApiBadRequestResponse({ description: "Paging query params are not valid or out of range" })
public async getTokens(@Query() pagingOptions: PagingOptionsDto): Promise<Pagination<TokenDto>> {
return await this.tokenService.findAll({
...pagingOptions,
route: entityName,
});
@ApiQuery({
name: "minLiquidity",
type: "integer",
description: "Min liquidity filter",
example: 1000000,
required: false,
})
public async getTokens(
@Query() pagingOptions: PagingOptionsDto,
@Query("minLiquidity", new ParseLimitedIntPipe({ min: 0, isOptional: true })) minLiquidity?: number
): Promise<Pagination<TokenDto>> {
return await this.tokenService.findAll(
{
minLiquidity,
},
{
...pagingOptions,
route: entityName,
}
);
}

@Get(":address")
Expand Down
21 changes: 17 additions & 4 deletions packages/api/src/token/token.service.spec.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Test, TestingModule } from "@nestjs/testing";
import { mock } from "jest-mock-extended";
import { getRepositoryToken } from "@nestjs/typeorm";
import { Repository, SelectQueryBuilder } from "typeorm";
import { Repository, SelectQueryBuilder, MoreThanOrEqual } from "typeorm";
import { TokenService } from "./token.service";
import { Token, ETH_TOKEN } from "./token.entity";
import { Pagination, IPaginationMeta } from "nestjs-typeorm-paginate";
Expand Down Expand Up @@ -139,13 +139,26 @@ describe("TokenService", () => {
});

it("creates query builder with proper params", async () => {
await service.findAll(pagingOptions);
await service.findAll({}, pagingOptions);
expect(repositoryMock.createQueryBuilder).toHaveBeenCalledTimes(1);
expect(repositoryMock.createQueryBuilder).toHaveBeenCalledWith("token");
});

it("does not add liquidity filter when minLiquidity is not provided", async () => {
await service.findAll({}, pagingOptions);
expect(queryBuilderMock.where).not.toBeCalled();
});

it("adds liquidity filter when minLiquidity is provided", async () => {
await service.findAll({ minLiquidity: 1000 }, pagingOptions);
expect(queryBuilderMock.where).toBeCalledTimes(1);
expect(queryBuilderMock.where).toHaveBeenCalledWith({
liquidity: MoreThanOrEqual(1000),
});
});

it("returns tokens ordered by liquidity, blockNumber and logIndex DESC", async () => {
await service.findAll(pagingOptions);
await service.findAll({}, pagingOptions);
expect(queryBuilderMock.orderBy).toBeCalledTimes(1);
expect(queryBuilderMock.orderBy).toHaveBeenCalledWith("token.liquidity", "DESC", "NULLS LAST");
expect(queryBuilderMock.addOrderBy).toBeCalledTimes(2);
Expand All @@ -156,7 +169,7 @@ describe("TokenService", () => {
it("returns paginated result", async () => {
const paginationResult = mock<Pagination<Token, IPaginationMeta>>();
(utils.paginate as jest.Mock).mockResolvedValue(paginationResult);
const result = await service.findAll(pagingOptions);
const result = await service.findAll({}, pagingOptions);
expect(utils.paginate).toBeCalledTimes(1);
expect(utils.paginate).toBeCalledWith(queryBuilderMock, pagingOptions);
expect(result).toBe(paginationResult);
Expand Down
16 changes: 14 additions & 2 deletions packages/api/src/token/token.service.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
import { Injectable } from "@nestjs/common";
import { InjectRepository } from "@nestjs/typeorm";
import { Repository, FindOptionsSelect } from "typeorm";
import { Repository, FindOptionsSelect, MoreThanOrEqual } from "typeorm";
import { Pagination, IPaginationOptions } from "nestjs-typeorm-paginate";
import { paginate } from "../common/utils";
import { Token, ETH_TOKEN } from "./token.entity";

export interface FilterTokensOptions {
minLiquidity?: number;
}

@Injectable()
export class TokenService {
constructor(
Expand Down Expand Up @@ -34,8 +38,16 @@ export class TokenService {
return tokenExists;
}

public async findAll(paginationOptions: IPaginationOptions): Promise<Pagination<Token>> {
public async findAll(
{ minLiquidity }: FilterTokensOptions,
paginationOptions: IPaginationOptions
): Promise<Pagination<Token>> {
const queryBuilder = this.tokenRepository.createQueryBuilder("token");
if (minLiquidity > 0) {
queryBuilder.where({
liquidity: MoreThanOrEqual(minLiquidity),
});
}
queryBuilder.orderBy("token.liquidity", "DESC", "NULLS LAST");
queryBuilder.addOrderBy("token.blockNumber", "DESC");
queryBuilder.addOrderBy("token.logIndex", "DESC");
Expand Down

0 comments on commit 04429f6

Please sign in to comment.