diff --git a/README.md b/README.md
index baba805..5ccd9f1 100644
--- a/README.md
+++ b/README.md
@@ -100,10 +100,14 @@ This documentation outlines the available endpoints available.
### 3.2. Useful commands
-| Command | Description |
-|-------------------|------------------------------------------------------------------------------------------------------------------------------------------|
-| `yarn setup` | Creates an `.env` file to the `.config/` directory. |
-| `yarn start` | Runs setup and starts Docker Compose. Intended for development purposes only. |
+| Command | Description |
+|------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------|
+| `yarn setup` | Creates an `.env` file to the `.config/` directory. |
+| `yarn start` | Runs setup and starts Docker Compose. Intended for development purposes only. |
+| `yarn test` | Runs the test script that starts up the Docker Compose test configuration and runs both unit and e2e tests. E2e tests require a running API and database. |
+| `yarn test:e2e` | Runs the e2e tests (all files that are named `e2e.test.ts`). This command requires a running API at https://127.0.0.1:3000 and a database. |
+| `yarn test:unit` | Simply runs the unit tests. These are self-contained and do not require any external dependencies. |
+
[Back to top ^][table-of-contents]
diff --git a/docker-compose.test.yml b/docker-compose.test.yml
index 42329cc..7f4deef 100644
--- a/docker-compose.test.yml
+++ b/docker-compose.test.yml
@@ -20,7 +20,7 @@ services:
interval: 5s
retries: 3
start_period: 5s
- test: ["CMD", "curl", "-f", "http://127.0.0.1:${APP_PORT:-3000}/versions"]
+ test: ["CMD", "curl", "-f", "http://127.0.0.1:${APP_PORT:-3000}/api/v1/versions"]
image: plutus/api_test
networks:
- plutus_network_test
diff --git a/package.json b/package.json
index c5af59b..bf05511 100644
--- a/package.json
+++ b/package.json
@@ -33,8 +33,8 @@
"setup": "./scripts/setup.sh",
"start": "./scripts/run.sh",
"test": "./scripts/test.sh",
- "test:e2e": "jest --passWithNoTests --config=jest.config.e2e.ts",
- "test:unit": "jest --passWithNoTests --config=jest.config.unit.ts"
+ "test:e2e": "APP_VERSION=$npm_package_version jest --passWithNoTests --config=jest.config.e2e.ts",
+ "test:unit": "APP_VERSION=$npm_package_version jest --passWithNoTests --config=jest.config.unit.ts"
},
"devDependencies": {
"@commitlint/cli": "^19.1.0",
diff --git a/src/main.ts b/src/main.ts
index 15b0912..ccd331a 100644
--- a/src/main.ts
+++ b/src/main.ts
@@ -14,14 +14,13 @@ import AppModule from '@app/modules/app/module';
import type { IEnvironmentVariables, ILogLevel } from '@app/types';
// utils
+import createAPIPathPrefix from '@app/utils/createAPIPathPrefix';
import createLoggerService from '@app/utils/createLoggerService';
-import parseVersion from '@app/utils/parseVersion';
(async () => {
let app: NestApplication;
let configService: ConfigService;
let logger: LoggerService;
- let versions: string[];
try {
app = await NestFactory.create(AppModule);
@@ -30,9 +29,6 @@ import parseVersion from '@app/utils/parseVersion';
configService.get(EnvironmentVariableKeyEnum.AppName),
configService.get(EnvironmentVariableKeyEnum.LogLevel)
);
- versions = parseVersion(
- configService.get(EnvironmentVariableKeyEnum.AppVersion)
- );
// setup middleware
app.useLogger(logger);
@@ -45,7 +41,11 @@ import parseVersion from '@app/utils/parseVersion';
},
})
);
- app.setGlobalPrefix(`${APIPathEnum.API}/v${versions[0]}`);
+ app.setGlobalPrefix(
+ createAPIPathPrefix(
+ configService.get(EnvironmentVariableKeyEnum.AppVersion)
+ )
+ );
app.useGlobalPipes(new ValidationPipe()); // for validating query params
// setup open api
diff --git a/src/modules/chains/e2e.test.ts b/src/modules/chains/e2e.test.ts
index 96ab319..11eb4c9 100644
--- a/src/modules/chains/e2e.test.ts
+++ b/src/modules/chains/e2e.test.ts
@@ -8,19 +8,21 @@ import { chains } from '@app/configs';
import { APIPathEnum } from '@app/enums';
// utils
+import createAPIPathPrefix from '@app/utils/createAPIPathPrefix';
import mapChainConfigToChainResponseBody from '@app/utils/mapChainConfigToChainResponseBody';
describe(`/${APIPathEnum.Chains}`, () => {
+ const path: string = `${createAPIPathPrefix(process.env.APP_VERSION)}/${APIPathEnum.Chains}`;
let agent: Agent;
beforeAll(async () => {
- agent = request(`http://127.0.0.1:3000`);
+ agent = request(`http://127.0.0.1:${process.env.APP_PORT}`);
});
describe(`GET /${APIPathEnum.Chains}`, () => {
it('should return the chain configuration', async () => {
const response: Response = await agent
- .get(`/${APIPathEnum.Chains}`)
+ .get(`/${path}`)
.expect(HttpStatus.OK);
expect(response.body).toEqual(
diff --git a/src/modules/fee-repository/dtos/FindByIntegratorAndPageOptionsDTO.ts b/src/modules/fee-repository/dtos/FindByIntegratorAndPageOptionsDTO.ts
new file mode 100644
index 0000000..f559e6a
--- /dev/null
+++ b/src/modules/fee-repository/dtos/FindByIntegratorAndPageOptionsDTO.ts
@@ -0,0 +1,17 @@
+interface IProps {
+ integrator: string;
+ limit?: number;
+ page?: number;
+}
+
+export default class FindByIntegratorAndPageOptionsDTO {
+ public readonly integrator: string;
+ public readonly limit?: number;
+ public readonly page?: number;
+
+ constructor({ integrator, limit, page }: IProps) {
+ this.integrator = integrator;
+ this.limit = limit;
+ this.page = page;
+ }
+}
diff --git a/src/modules/fee-repository/dtos/FindByPageResultDTO.ts b/src/modules/fee-repository/dtos/FindByIntegratorAndPageResultDTO.ts
similarity index 88%
rename from src/modules/fee-repository/dtos/FindByPageResultDTO.ts
rename to src/modules/fee-repository/dtos/FindByIntegratorAndPageResultDTO.ts
index 5d6b5dd..3c7b779 100644
--- a/src/modules/fee-repository/dtos/FindByPageResultDTO.ts
+++ b/src/modules/fee-repository/dtos/FindByIntegratorAndPageResultDTO.ts
@@ -8,7 +8,7 @@ interface IProps {
total: number;
}
-export default class FindByPageResultDTO {
+export default class FindByIntegratorAndPageResultDTO {
public readonly data: IFeeDocument[];
public readonly limit: number;
public readonly page: number;
diff --git a/src/modules/fee-repository/dtos/FindByPageOptionsDTO.ts b/src/modules/fee-repository/dtos/FindByPageOptionsDTO.ts
deleted file mode 100644
index 3acfde7..0000000
--- a/src/modules/fee-repository/dtos/FindByPageOptionsDTO.ts
+++ /dev/null
@@ -1,17 +0,0 @@
-interface IProps {
- chainId: string;
- limit?: number;
- page?: number;
-}
-
-export default class FindByPageOptionsDTO {
- public readonly chainId: string;
- public readonly limit?: number;
- public readonly page?: number;
-
- constructor({ chainId, limit, page }: IProps) {
- this.chainId = chainId;
- this.limit = limit;
- this.page = page;
- }
-}
diff --git a/src/modules/fee-repository/dtos/index.ts b/src/modules/fee-repository/dtos/index.ts
index 26b9e76..e1a98ba 100644
--- a/src/modules/fee-repository/dtos/index.ts
+++ b/src/modules/fee-repository/dtos/index.ts
@@ -1,3 +1,3 @@
export { default as CreateOptionsDTO } from './CreateOptionsDTO';
-export { default as FindByPageOptionsDTO } from './FindByPageOptionsDTO';
-export { default as FindByPageResultDTO } from './FindByPageResultDTO';
+export { default as FindByIntegratorAndPageOptionsDTO } from './FindByIntegratorAndPageOptionsDTO';
+export { default as FindByIntegratorAndPageResultDTO } from './FindByIntegratorAndPageResultDTO';
diff --git a/src/modules/fee-repository/service.ts b/src/modules/fee-repository/service.ts
index 7296e5f..e8f05ad 100644
--- a/src/modules/fee-repository/service.ts
+++ b/src/modules/fee-repository/service.ts
@@ -7,8 +7,8 @@ import { FEE_PAGINATION_MAX_LIMIT } from '@app/constants';
// dtos
import {
CreateOptionsDTO,
- FindByPageOptionsDTO,
- FindByPageResultDTO,
+ FindByIntegratorAndPageOptionsDTO,
+ FindByIntegratorAndPageResultDTO,
} from './dtos';
// enums
@@ -37,16 +37,16 @@ export default class FeeRepositoryService {
return await this.model.create(dto);
}
- public async findByPage({
- chainId,
+ public async findByIntegratorAndPage({
+ integrator,
limit = FEE_PAGINATION_MAX_LIMIT,
page = 1,
- }: FindByPageOptionsDTO): Promise {
+ }: FindByIntegratorAndPageOptionsDTO): Promise {
const result: IFindByPageAggregateResult[] =
await this.model.aggregate([
{
$match: {
- chainId,
+ integrator,
},
},
{
@@ -68,11 +68,11 @@ export default class FeeRepositoryService {
},
]);
- return new FindByPageResultDTO({
+ return new FindByIntegratorAndPageResultDTO({
data: result[0].data,
limit,
page,
- total: result[0].metadata[0].total,
+ total: result[0].metadata[0]?.total || 0,
});
}
diff --git a/src/modules/fee-repository/types/IFindByPageAggregateResult.ts b/src/modules/fee-repository/types/IFindByPageAggregateResult.ts
index 0c74aaa..a6c894a 100644
--- a/src/modules/fee-repository/types/IFindByPageAggregateResult.ts
+++ b/src/modules/fee-repository/types/IFindByPageAggregateResult.ts
@@ -3,7 +3,7 @@ import type { IFeeDocument } from '@app/types';
interface IFindByPageAggregateResult {
data: IFeeDocument[];
- metadata: Record<'total', number>;
+ metadata: Record<'total', number>[];
}
export default IFindByPageAggregateResult;
diff --git a/src/modules/fees/controller.ts b/src/modules/fees/controller.ts
index 4c64442..d0f4f90 100644
--- a/src/modules/fees/controller.ts
+++ b/src/modules/fees/controller.ts
@@ -1,79 +1,67 @@
-import {
- Controller,
- Get,
- NotFoundException,
- Param,
- Query,
- Req,
-} from '@nestjs/common';
-import { ApiNotFoundResponse, ApiOkResponse } from '@nestjs/swagger';
+import { Controller, Get, Param, Query, Req } from '@nestjs/common';
+import { ConfigService } from '@nestjs/config';
+import { ApiOkResponse } from '@nestjs/swagger';
import type { Request } from 'express';
-// configs
-import { chains } from '@app/configs';
-
// constants
import { FEE_PAGINATION_MAX_LIMIT } from '@app/constants';
// dtos
-import { FindByPageResultDTO } from '@app/modules/fee-repository';
+import { FindByIntegratorAndPageResultDTO } from '@app/modules/fee-repository';
import {
- GetByChainIdOptionsDTO,
+ GetByIntegratorOptionsDTO,
GetFeesParamsDTO,
GetFeesQueryDTO,
GetFeesResponseBodyDTO,
} from './dtos';
// enums
-import { APIPathEnum } from '@app/enums';
+import { APIPathEnum, EnvironmentVariableKeyEnum } from '@app/enums';
-// services
+// providers
import Service from './service';
// types
-import type { IChainConfig } from '@app/types';
+import type { IEnvironmentVariables } from '@app/types';
// utils
-import createChainId from '@app/utils/createChainId';
+import createAPIPathPrefix from '@app/utils/createAPIPathPrefix';
@Controller(APIPathEnum.Fees)
export default class FeesController {
- constructor(private readonly service: Service) {}
+ constructor(
+ private readonly configService: ConfigService,
+ private readonly service: Service
+ ) {}
- @Get(':chainId')
+ @Get(':integrator')
@ApiOkResponse({
- description: 'Gets the fees collected for a given chain.',
+ description: 'Gets the fees collected for a given integrator.',
type: GetFeesResponseBodyDTO,
})
- @ApiNotFoundResponse({
- description: 'If the chain ID cannot be found.',
- })
- public async getByChainId(
- @Param() { chainId }: GetFeesParamsDTO,
+ public async getByIntegrator(
+ @Param() { integrator }: GetFeesParamsDTO,
@Query() query: GetFeesQueryDTO,
@Req() req: Request
): Promise {
- const chainConfig: IChainConfig | null =
- chains.find((value) => createChainId(value) === chainId) || null;
- let result: FindByPageResultDTO;
-
- if (!chainConfig) {
- throw new NotFoundException(`unknown chain "${chainId}"`);
- }
-
- result = await this.service.getByChainId(
- new GetByChainIdOptionsDTO({
- chainId,
- limit: query.limit
- ? parseInt(query.limit, 10)
- : FEE_PAGINATION_MAX_LIMIT,
- page: query.page ? parseInt(query.page, 10) : 1,
- })
- );
+ const result: FindByIntegratorAndPageResultDTO =
+ await this.service.getByIntegrator(
+ new GetByIntegratorOptionsDTO({
+ integrator,
+ limit: query.limit
+ ? parseInt(query.limit, 10)
+ : FEE_PAGINATION_MAX_LIMIT,
+ page: query.page ? parseInt(query.page, 10) : 1,
+ })
+ );
return new GetFeesResponseBodyDTO({
...result,
- nextPageURL: `${req.protocol}://${req.get('host')}/${APIPathEnum.Fees}/${chainId}?limit=${result.limit}&page=${result.page + 1}`,
+ // only show the next page url
+ nextPageURL:
+ result.total > 0 && result.page < Math.ceil(result.total / result.limit)
+ ? `${req.protocol}://${req.get('host')}/${createAPIPathPrefix(this.configService.get(EnvironmentVariableKeyEnum.AppVersion))}/${APIPathEnum.Fees}/${integrator}?limit=${result.limit}&page=${result.page + 1}`
+ : null,
});
}
}
diff --git a/src/modules/fees/dtos/GetByChainIdOptionsDTO.ts b/src/modules/fees/dtos/GetByChainIdOptionsDTO.ts
deleted file mode 100644
index ddc4139..0000000
--- a/src/modules/fees/dtos/GetByChainIdOptionsDTO.ts
+++ /dev/null
@@ -1,17 +0,0 @@
-interface IProps {
- chainId: string;
- limit: number;
- page: number;
-}
-
-export default class GetByChainIdOptionsDTO {
- public readonly chainId: string;
- public readonly limit: number;
- public readonly page: number;
-
- constructor({ chainId, limit, page }: IProps) {
- this.chainId = chainId;
- this.limit = limit;
- this.page = page;
- }
-}
diff --git a/src/modules/fees/dtos/GetByIntegratorOptionsDTO.ts b/src/modules/fees/dtos/GetByIntegratorOptionsDTO.ts
new file mode 100644
index 0000000..58be229
--- /dev/null
+++ b/src/modules/fees/dtos/GetByIntegratorOptionsDTO.ts
@@ -0,0 +1,17 @@
+interface IProps {
+ integrator: string;
+ limit: number;
+ page: number;
+}
+
+export default class GetByIntegratorOptionsDTO {
+ public readonly integrator: string;
+ public readonly limit: number;
+ public readonly page: number;
+
+ constructor({ integrator, limit, page }: IProps) {
+ this.integrator = integrator;
+ this.limit = limit;
+ this.page = page;
+ }
+}
diff --git a/src/modules/fees/dtos/GetFeesParamsDTO.ts b/src/modules/fees/dtos/GetFeesParamsDTO.ts
index 3e1e7a8..6ce885b 100644
--- a/src/modules/fees/dtos/GetFeesParamsDTO.ts
+++ b/src/modules/fees/dtos/GetFeesParamsDTO.ts
@@ -3,11 +3,10 @@ import { IsNotEmpty } from 'class-validator';
export default class GetFeesParamsDTO {
@ApiProperty({
- description:
- 'The ID of the chain. This is the concatenation of the chain namespace and reference as specified in CAIP-2.',
- example: 'eip155:137',
+ description: 'The partner that was used to collect fees.',
+ example: '0x34B7BEb5Bb4E6504dBa8843883796eF9CbDe0a38',
required: true,
})
@IsNotEmpty()
- public readonly chainId: string;
+ public readonly integrator: string;
}
diff --git a/src/modules/fees/dtos/GetFeesResponseBodyDTO.ts b/src/modules/fees/dtos/GetFeesResponseBodyDTO.ts
index 3d0f60b..6c70ba2 100644
--- a/src/modules/fees/dtos/GetFeesResponseBodyDTO.ts
+++ b/src/modules/fees/dtos/GetFeesResponseBodyDTO.ts
@@ -6,7 +6,7 @@ import type { IFeeDocument } from '@app/types';
interface IProps {
data: IFeeDocument[];
limit: number;
- nextPageURL: string;
+ nextPageURL: string | null;
page: number;
total: number;
}
@@ -23,7 +23,7 @@ export default class GetFeesResponseBodyDTO {
@ApiProperty({
description: 'The URL to the next page.',
})
- public readonly nextPageURL: string;
+ public readonly nextPageURL: string | null;
@ApiProperty({
description: 'The current page.',
})
diff --git a/src/modules/fees/dtos/index.ts b/src/modules/fees/dtos/index.ts
index 4c12b7e..cafb9f0 100644
--- a/src/modules/fees/dtos/index.ts
+++ b/src/modules/fees/dtos/index.ts
@@ -1,4 +1,4 @@
-export { default as GetByChainIdOptionsDTO } from './GetByChainIdOptionsDTO';
+export { default as GetByIntegratorOptionsDTO } from './GetByIntegratorOptionsDTO';
export { default as GetFeesParamsDTO } from './GetFeesParamsDTO';
export { default as GetFeesQueryDTO } from './GetFeesQueryDTO';
export { default as GetFeesResponseBodyDTO } from './GetFeesResponseBodyDTO';
diff --git a/src/modules/fees/e2e.test.ts b/src/modules/fees/e2e.test.ts
index 67b113e..42f32ed 100644
--- a/src/modules/fees/e2e.test.ts
+++ b/src/modules/fees/e2e.test.ts
@@ -4,17 +4,19 @@ import { agent as request, Response, Agent } from 'supertest';
// constants
import { FEE_PAGINATION_MAX_LIMIT } from '@app/constants';
+// dtos
+import { GetFeesResponseBodyDTO } from './dtos';
+
// enums
import { APIPathEnum } from '@app/enums';
// helpers
+import createAPIPathPrefix from '@app/utils/createAPIPathPrefix';
import seedDatabase from '../../../test/helpers/seedDatabase';
-// types
-import type { IGetFeesResponseBody } from './types';
-
describe(`/${APIPathEnum.Fees}`, () => {
- const chainId: string = 'eip155:137';
+ const integrator: string = '0xBB59e1AD8607F2131A9cA41673150303a2641259';
+ const path: string = `${createAPIPathPrefix(process.env.APP_VERSION)}/${APIPathEnum.Fees}`;
let agent: Agent;
beforeAll(async () => {
@@ -26,35 +28,38 @@ describe(`/${APIPathEnum.Fees}`, () => {
});
describe(`GET /${APIPathEnum.Fees}`, () => {
- it('should return empty values for an unknown chain', async () => {
- await agent
- .get(`/${APIPathEnum.Fees}/unknown`)
- .expect(HttpStatus.NOT_FOUND);
+ it('should return empty values for an unknown integrator', async () => {
+ const response: Response = await agent
+ .get(`/${path}/unknown`)
+ .expect(HttpStatus.OK);
+
+ expect((response.body as GetFeesResponseBodyDTO).data).toHaveLength(0);
+ expect((response.body as GetFeesResponseBodyDTO).nextPageURL).toBeNull();
+ expect((response.body as GetFeesResponseBodyDTO).total).toBe(0);
});
it('should return the first 25 entries without any pagination', async () => {
// arrange
// act
const response: Response = await agent
- .get(`/${APIPathEnum.Fees}/${chainId}`)
+ .get(`/${path}/${integrator}`)
.expect(HttpStatus.OK);
// assert
const nextPageURL: URL = new URL(
- (response.body as IGetFeesResponseBody).nextPageURL
+ (response.body as GetFeesResponseBodyDTO).nextPageURL
);
- expect(response.status).toBe(HttpStatus.OK);
- expect((response.body as IGetFeesResponseBody).data).toHaveLength(
+ expect((response.body as GetFeesResponseBodyDTO).data).toHaveLength(
FEE_PAGINATION_MAX_LIMIT
);
- expect((response.body as IGetFeesResponseBody).limit).toBe(
+ expect((response.body as GetFeesResponseBodyDTO).limit).toBe(
FEE_PAGINATION_MAX_LIMIT
);
expect(nextPageURL.searchParams.get('limit')).toBe(
FEE_PAGINATION_MAX_LIMIT.toString()
);
expect(nextPageURL.searchParams.get('page')).toBe('2');
- expect((response.body as IGetFeesResponseBody).page).toBe(1);
+ expect((response.body as GetFeesResponseBodyDTO).page).toBe(1);
});
it('should return the page entries and the max limit if the limit is out of bounds', async () => {
@@ -62,25 +67,24 @@ describe(`/${APIPathEnum.Fees}`, () => {
const page: number = 1;
// act
const response: Response = await agent
- .get(`/${APIPathEnum.Fees}/${chainId}?page=${page}&limit=255`)
+ .get(`/${path}/${integrator}?page=${page}&limit=255`)
.expect(HttpStatus.OK);
// assert
const nextPageURL: URL = new URL(
- (response.body as IGetFeesResponseBody).nextPageURL
+ (response.body as GetFeesResponseBodyDTO).nextPageURL
);
- expect(response.status).toBe(HttpStatus.OK);
- expect((response.body as IGetFeesResponseBody).data).toHaveLength(
+ expect((response.body as GetFeesResponseBodyDTO).data).toHaveLength(
FEE_PAGINATION_MAX_LIMIT
);
- expect((response.body as IGetFeesResponseBody).limit).toBe(
+ expect((response.body as GetFeesResponseBodyDTO).limit).toBe(
FEE_PAGINATION_MAX_LIMIT
);
expect(nextPageURL.searchParams.get('limit')).toBe(
FEE_PAGINATION_MAX_LIMIT.toString()
);
expect(nextPageURL.searchParams.get('page')).toBe((page + 1).toString());
- expect((response.body as IGetFeesResponseBody).page).toBe(page);
+ expect((response.body as GetFeesResponseBodyDTO).page).toBe(page);
});
it('should return the second page using pagination but without a limit', async () => {
@@ -88,25 +92,24 @@ describe(`/${APIPathEnum.Fees}`, () => {
const page: number = 2;
// act
const response: Response = await agent
- .get(`/${APIPathEnum.Fees}/${chainId}?page=${page}`)
+ .get(`/${path}/${integrator}?page=${page}`)
.expect(HttpStatus.OK);
// assert
const nextPageURL: URL = new URL(
- (response.body as IGetFeesResponseBody).nextPageURL
+ (response.body as GetFeesResponseBodyDTO).nextPageURL
);
- expect(response.status).toBe(HttpStatus.OK);
- expect((response.body as IGetFeesResponseBody).data).toHaveLength(
+ expect((response.body as GetFeesResponseBodyDTO).data).toHaveLength(
FEE_PAGINATION_MAX_LIMIT
);
- expect((response.body as IGetFeesResponseBody).limit).toBe(
+ expect((response.body as GetFeesResponseBodyDTO).limit).toBe(
FEE_PAGINATION_MAX_LIMIT
);
expect(nextPageURL.searchParams.get('limit')).toBe(
FEE_PAGINATION_MAX_LIMIT.toString()
);
expect(nextPageURL.searchParams.get('page')).toBe((page + 1).toString());
- expect((response.body as IGetFeesResponseBody).page).toBe(page);
+ expect((response.body as GetFeesResponseBodyDTO).page).toBe(page);
});
});
});
diff --git a/src/modules/fees/service.ts b/src/modules/fees/service.ts
index ef2db12..89bdeec 100644
--- a/src/modules/fees/service.ts
+++ b/src/modules/fees/service.ts
@@ -4,8 +4,8 @@ import { Injectable } from '@nestjs/common';
import { FEE_PAGINATION_MAX_LIMIT } from '@app/constants';
// dtos
-import { FindByPageResultDTO } from '@app/modules/fee-repository';
-import { GetByChainIdOptionsDTO } from './dtos';
+import { FindByIntegratorAndPageResultDTO } from '@app/modules/fee-repository';
+import { GetByIntegratorOptionsDTO } from './dtos';
// providers
import { FeeRepositoryService } from '@app/modules/fee-repository';
@@ -14,13 +14,13 @@ import { FeeRepositoryService } from '@app/modules/fee-repository';
export default class FeesService {
constructor(private readonly feeRepositoryService: FeeRepositoryService) {}
- public async getByChainId({
- chainId,
+ public async getByIntegrator({
+ integrator,
limit,
page,
- }: GetByChainIdOptionsDTO): Promise {
- return await this.feeRepositoryService.findByPage({
- chainId,
+ }: GetByIntegratorOptionsDTO): Promise {
+ return await this.feeRepositoryService.findByIntegratorAndPage({
+ integrator,
limit:
limit >= 0 && limit <= FEE_PAGINATION_MAX_LIMIT
? limit
diff --git a/src/modules/versions/__snapshots__/e2e.test.ts.snap b/src/modules/versions/__snapshots__/e2e.test.ts.snap
deleted file mode 100644
index 593ea30..0000000
--- a/src/modules/versions/__snapshots__/e2e.test.ts.snap
+++ /dev/null
@@ -1,16 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`/versions GET /versions should get the api info 1`] = `
-{
- "databases": [
- {
- "status": "connected",
- "type": "mongodb",
- "version": "8.2.1",
- },
- ],
- "environment": "test",
- "name": "plutus-test",
- "version": "1.0.0",
-}
-`;
diff --git a/src/modules/versions/e2e.test.ts b/src/modules/versions/e2e.test.ts
index e773240..e834c12 100644
--- a/src/modules/versions/e2e.test.ts
+++ b/src/modules/versions/e2e.test.ts
@@ -1,10 +1,17 @@
import { HttpStatus } from '@nestjs/common';
import { agent as request, Response, Agent } from 'supertest';
+// dtos
+import { VersionResponseBodyDTO } from './dtos';
+
// enums
import { APIPathEnum } from '@app/enums';
+// utils
+import createAPIPathPrefix from '@app/utils/createAPIPathPrefix';
+
describe(`/${APIPathEnum.Versions}`, () => {
+ const path: string = `${createAPIPathPrefix(process.env.APP_VERSION)}/${APIPathEnum.Versions}`;
let agent: Agent;
beforeAll(async () => {
@@ -14,10 +21,15 @@ describe(`/${APIPathEnum.Versions}`, () => {
describe(`GET /${APIPathEnum.Versions}`, () => {
it('should get the api info', async () => {
const response: Response = await agent
- .get(`/${APIPathEnum.Versions}`)
+ .get(`/${path}`)
.expect(HttpStatus.OK);
- expect(response.body).toMatchSnapshot();
+ expect((response.body as VersionResponseBodyDTO).name).toBe(
+ process.env.APP_NAME
+ );
+ expect((response.body as VersionResponseBodyDTO).version).toBe(
+ process.env.APP_VERSION
+ );
});
});
});
diff --git a/src/utils/createAPIPathPrefix/createAPIPathPrefix.ts b/src/utils/createAPIPathPrefix/createAPIPathPrefix.ts
new file mode 100644
index 0000000..002b8a7
--- /dev/null
+++ b/src/utils/createAPIPathPrefix/createAPIPathPrefix.ts
@@ -0,0 +1,13 @@
+// enums
+import { APIPathEnum } from '@app/enums';
+
+/**
+ * Convenience function to get the API prefix with the major version included.
+ * @param {string} version - the semantic version of the application.
+ * @returns {string} the API path prefix, i.e. `/api/v1`.
+ */
+export default function createAPIPathPrefix(version: string): string {
+ const [majorVersion] = version.replace(/[^\d.]/g, '').split('.');
+
+ return `${APIPathEnum.API}/v${majorVersion}`;
+}
diff --git a/src/utils/createAPIPathPrefix/index.ts b/src/utils/createAPIPathPrefix/index.ts
new file mode 100644
index 0000000..f25104b
--- /dev/null
+++ b/src/utils/createAPIPathPrefix/index.ts
@@ -0,0 +1 @@
+export { default } from './createAPIPathPrefix';
diff --git a/src/utils/parseVersion/index.ts b/src/utils/parseVersion/index.ts
deleted file mode 100644
index 9d0cc99..0000000
--- a/src/utils/parseVersion/index.ts
+++ /dev/null
@@ -1 +0,0 @@
-export { default } from './parseVersion';
diff --git a/src/utils/parseVersion/parseVersion.ts b/src/utils/parseVersion/parseVersion.ts
deleted file mode 100644
index 49797ae..0000000
--- a/src/utils/parseVersion/parseVersion.ts
+++ /dev/null
@@ -1,5 +0,0 @@
-export default function parseVersion(version: string): string[] {
- const sanitizedVersion: string = version.replace(/[^\d.]/g, '');
-
- return sanitizedVersion.split('.');
-}