Skip to content

Commit e72511f

Browse files
authored
feat: GET /deposits/details endpoint (#233)
This endpoint allows to retrieve a single deposit based on the `depositTxHash` and `originChainId`.
1 parent 0814abb commit e72511f

File tree

5 files changed

+101
-4
lines changed

5 files changed

+101
-4
lines changed

Diff for: src/modules/deposit/entry-point/http/controller.ts

+7-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { Controller, Get, Query } from "@nestjs/common";
22
import { ApiResponse, ApiTags } from "@nestjs/swagger";
33
import { DepositService } from "../../service";
4-
import { GetDepositsQuery, GetDepositsStatsResponse } from "./dto";
4+
import { GetDepositsQuery, GetDepositDetailsQuery, GetDepositsStatsResponse } from "./dto";
55

66
@Controller()
77
export class DepositController {
@@ -20,6 +20,12 @@ export class DepositController {
2020
return this.depositService.getDeposits(query.status, limit, offset);
2121
}
2222

23+
@Get("deposits/details")
24+
@ApiTags("deposits")
25+
getDepositsDetails(@Query() query: GetDepositDetailsQuery) {
26+
return this.depositService.getDepositDetails(query.depositTxHash, parseInt(query.originChainId));
27+
}
28+
2329
@Get("deposits/stats")
2430
@ApiTags("deposits")
2531
@ApiResponse({ type: GetDepositsStatsResponse })

Diff for: src/modules/deposit/entry-point/http/dto.ts

+14-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { ApiProperty } from "@nestjs/swagger";
22
import { Type } from "class-transformer";
3-
import { IsDateString, IsEnum, IsInt, IsOptional, IsString, Max, Min } from "class-validator";
3+
import { IsDateString, IsEnum, IsInt, IsOptional, IsString, Max, Min, IsPositive } from "class-validator";
44

55
export class GetDepositsQuery {
66
@IsOptional()
@@ -38,6 +38,19 @@ export class GetDepositsQuery {
3838
address: string;
3939
}
4040

41+
export class GetDepositDetailsQuery {
42+
@IsString()
43+
@Type(() => String)
44+
@ApiProperty({ example: "0x", required: true })
45+
depositTxHash: string;
46+
47+
@IsInt()
48+
@IsPositive()
49+
@Type(() => Number)
50+
@ApiProperty({ example: 1, required: true })
51+
originChainId: string;
52+
}
53+
4154
export class GetDepositsStatsResponse {
4255
@ApiProperty({ example: 100, description: "Total number of deposits" })
4356
totalDeposits: number;

Diff for: src/modules/deposit/exceptions.ts

+12
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,15 @@ export class InvalidAddressException extends HttpException {
1111
);
1212
}
1313
}
14+
15+
export class DepositNotFoundException extends HttpException {
16+
constructor() {
17+
super(
18+
{
19+
error: DepositNotFoundException.name,
20+
message: "Deposit not found",
21+
},
22+
HttpStatus.NOT_FOUND,
23+
);
24+
}
25+
}

Diff for: src/modules/deposit/service.ts

+11-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import {
1212
getTotalVolumeQuery,
1313
} from "./adapter/db/queries";
1414
import { AppConfig } from "../configuration/configuration.service";
15-
import { InvalidAddressException } from "./exceptions";
15+
import { InvalidAddressException, DepositNotFoundException } from "./exceptions";
1616

1717
export const DEPOSITS_STATS_CACHE_KEY = "deposits:stats";
1818

@@ -132,6 +132,16 @@ export class DepositService {
132132
};
133133
}
134134

135+
public async getDepositDetails(depositTxHash: string, sourceChainId: number) {
136+
const deposit = await this.depositRepository.findOne({ where: { depositTxHash, sourceChainId } });
137+
138+
if (!deposit) {
139+
throw new DepositNotFoundException();
140+
}
141+
142+
return deposit;
143+
}
144+
135145
public async getEtlReferralDeposits(date: string) {
136146
// delete time from date in case of datetime
137147
const parsedDate = new Date(date).toISOString().split("T")[0];

Diff for: test/deposit.e2e-spec.ts

+57-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,11 @@ import { INestApplication } from "@nestjs/common";
33
import { Test } from "@nestjs/testing";
44
import { constants, ethers } from "ethers";
55

6-
import { DepositFixture, mockManyDepositEntities } from "../src/modules/deposit/adapter/db/deposit-fixture";
6+
import {
7+
DepositFixture,
8+
mockManyDepositEntities,
9+
mockDepositEntity,
10+
} from "../src/modules/deposit/adapter/db/deposit-fixture";
711
import { ValidationPipe } from "../src/validation.pipe";
812
import { AppModule } from "../src/app.module";
913
import { RunMode } from "../src/dynamic-module";
@@ -120,6 +124,58 @@ describe("GET /deposits", () => {
120124
});
121125
});
122126

127+
describe("GET /deposits/details", () => {
128+
const depositorAddress = "0x9A8f92a830A5cB89a3816e3D267CB7791c16b04D";
129+
const depositTxHash = "0x91616c035fe2b7432d1549b9a204e29fd7cf3f5d5d9170cd418e5cc7dcc4e3a0";
130+
const sourceChainId = 1;
131+
132+
const FILLED_DEPOSIT = mockDepositEntity({
133+
status: "filled",
134+
depositorAddr: depositorAddress,
135+
sourceChainId,
136+
depositTxHash,
137+
amount: "10",
138+
filled: "10",
139+
});
140+
141+
beforeAll(async () => {
142+
await app.get(DepositFixture).insertManyDeposits([FILLED_DEPOSIT]);
143+
});
144+
145+
it("200 with for correct params", async () => {
146+
const response = await request(app.getHttpServer()).get(
147+
`/deposits/details?depositTxHash=${depositTxHash}&originChainId=${sourceChainId}`,
148+
);
149+
expect(response.status).toBe(200);
150+
expect(response.body.status).toBe("filled");
151+
});
152+
153+
it("404 for non existent depositTxHash", async () => {
154+
const response = await request(app.getHttpServer()).get(
155+
`/deposits/details?depositTxHash=0x&originChainId=${sourceChainId}`,
156+
);
157+
expect(response.status).toBe(404);
158+
});
159+
160+
it("404 for non existent originChainId", async () => {
161+
const response = await request(app.getHttpServer()).get(
162+
`/deposits/details?depositTxHash=${depositTxHash}&originChainId=10`,
163+
);
164+
expect(response.status).toBe(404);
165+
});
166+
167+
it("400 for invalid originChainId", async () => {
168+
const response = await request(app.getHttpServer()).get(
169+
`/deposits/details?depositTxHash=${depositTxHash}&originChainId=invalid`,
170+
);
171+
expect(response.status).toBe(400);
172+
});
173+
174+
afterAll(async () => {
175+
await app.get(DepositFixture).deleteAllDeposits();
176+
});
177+
});
178+
123179
describe("GET /etl/referral-deposits", () => {
124180
const date = "2022-01-01";
125181

0 commit comments

Comments
 (0)