Skip to content

Commit

Permalink
feat: public endpoint to verify contracts (#69)
Browse files Browse the repository at this point in the history
# What ❔

Public endpoint to verify contracts

## Checklist

<!-- Check your PR fulfills the following items. -->
<!-- For draft PRs check the boxes as you complete them. -->

- [X] PR title corresponds to the body of PR (we generate changelog
entries from PRs).
- [X] Tests for the changes have been added / updated.
- [X] Documentation comments have been added / updated.
  • Loading branch information
vasyl-ivanchuk authored and pcheremu committed Feb 15, 2024
1 parent 402969b commit 12f415d
Show file tree
Hide file tree
Showing 20 changed files with 5,208 additions and 1,717 deletions.
5,207 changes: 3,578 additions & 1,629 deletions package-lock.json

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions packages/api/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -62,12 +62,12 @@
"@typescript-eslint/parser": "^5.0.0",
"eslint-config-prettier": "^8.3.0",
"eslint-plugin-prettier": "^4.0.0",
"jest": "28.1.3",
"jest": "29.2.1",
"jest-junit": "^14.0.1",
"lint-staged": "^13.0.3",
"source-map-support": "^0.5.20",
"supertest": "^6.1.3",
"ts-jest": "28.0.8",
"ts-jest": "29.0.3",
"ts-loader": "^9.2.3",
"ts-node": "^10.0.0",
"tsconfig-paths": "4.1.0"
Expand Down
29 changes: 27 additions & 2 deletions packages/api/src/api/api.controller.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,11 @@ describe("ApiController", () => {
controller = module.get<ApiController>(ApiController);
});

describe("apiHandler", () => {
describe("apiGetHandler", () => {
it("delegates request handling to a different controller based on module and action from query string", async () => {
const request = mock<Request>();
const next = jest.fn();
await controller.apiHandler(request, next, ApiModule.Contract, ApiContractAction.GetAbi, {
await controller.apiGetHandler(request, next, ApiContractAction.GetAbi, ApiModule.Contract, {
module: ApiModule.Contract,
action: ApiContractAction.GetAbi,
address: "0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
Expand All @@ -34,6 +34,17 @@ describe("ApiController", () => {
});
});

describe("apiPostHandler", () => {
it("delegates request handling to a different controller based on module and action from body string", async () => {
const request = mock<Request>();
const next = jest.fn();
await controller.apiPostHandler(request, next, ApiContractAction.VerifySourceCode, ApiModule.Contract);

expect(request.url).toBe(`/api/${ApiModule.Contract}/${ApiContractAction.VerifySourceCode}`);
expect(next).toBeCalledTimes(1);
});
});

describe("getContractAbi", () => {
it("returns null as it is defined only to appear in docs and cannot be called", async () => {
const result = await controller.getContractAbi();
Expand All @@ -48,6 +59,20 @@ describe("ApiController", () => {
});
});

describe("verifyContractSourceCode", () => {
it("returns null as it is defined only to appear in docs and cannot be called", async () => {
const result = await controller.verifyContractSourceCode();
expect(result).toBe(null);
});
});

describe("getVerificationStatus", () => {
it("returns null as it is defined only to appear in docs and cannot be called", async () => {
const result = await controller.getVerificationStatus();
expect(result).toBe(null);
});
});

describe("getContractCreation", () => {
it("returns null as it is defined only to appear in docs and cannot be called", async () => {
const result = await controller.getContractCreation();
Expand Down
61 changes: 57 additions & 4 deletions packages/api/src/api/api.controller.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,22 @@
import { Controller, Get, Query, Req, Next, UseFilters } from "@nestjs/common";
import { ApiTags, ApiOkResponse, ApiExcludeEndpoint, ApiQuery, ApiExtraModels, ApiOperation } from "@nestjs/swagger";
import { Controller, Get, Query, Req, Next, UseFilters, Post, Body } from "@nestjs/common";
import {
ApiTags,
ApiOkResponse,
ApiExcludeEndpoint,
ApiQuery,
ApiExtraModels,
ApiOperation,
ApiBody,
} from "@nestjs/swagger";
import { Request, NextFunction } from "express";
import { PagingOptionsWithMaxItemsLimitDto } from "./dtos/common/pagingOptionsWithMaxItemsLimit.dto";
import { SortingOptionsDto } from "./dtos/common/sortingOptions.dto";
import { ContractAbiResponseDto } from "./dtos/contract/contractAbiResponse.dto";
import { ContractCreationResponseDto, ContractCreationInfoDto } from "./dtos/contract/contractCreationResponse.dto";
import { ContractSourceCodeResponseDto } from "./dtos/contract/contractSourceCodeResponse.dto";
import { VerifyContractRequestDto } from "./dtos/contract/verifyContractRequest.dto";
import { VerifyContractResponseDto } from "./dtos/contract/verifyContractResponse.dto";
import { ContractVerificationStatusResponseDto } from "./dtos/contract/contractVerificationStatusResponse.dto";
import { TransactionStatusResponseDto, TransactionStatusDto } from "./dtos/transaction/transactionStatusResponse.dto";
import { TransactionReceiptStatusResponseDto } from "./dtos/transaction/transactionReceiptStatusResponse.dto";
import { AccountTransactionDto } from "./dtos/account/accountTransaction.dto";
Expand Down Expand Up @@ -38,11 +49,11 @@ export class ApiController {
@ApiExcludeEndpoint()
@Get("api")
@UseFilters(ApiExceptionFilter)
public async apiHandler(
public async apiGetHandler(
@Req() request: Request,
@Next() next: NextFunction,
@Query("module", new ParseModulePipe()) module: ApiModule,
@Query(new ParseActionPipe()) action: string,
@Query("module", new ParseModulePipe()) module: ApiModule,
@Query() query: ApiRequestQuery
) {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
Expand All @@ -52,6 +63,19 @@ export class ApiController {
next();
}

@ApiExcludeEndpoint()
@Post("api")
@UseFilters(ApiExceptionFilter)
public async apiPostHandler(
@Req() request: Request,
@Next() next: NextFunction,
@Body(new ParseActionPipe()) action: string,
@Body("module", new ParseModulePipe()) module: ApiModule
) {
request.url = `/api/${module}/${action}`;
next();
}

@ApiTags("Contract API")
@Get("api?module=contract&action=getabi")
@ApiOperation({ summary: "Fetch the ABI for a given contract address" })
Expand Down Expand Up @@ -106,6 +130,35 @@ export class ApiController {
return null;
}

@ApiTags("Contract API")
@Post("api")
@ApiOperation({ summary: "Submits a contract source code for verification" })
@ApiBody({ type: VerifyContractRequestDto })
@ApiOkResponse({
description: "Verification ID for the submission",
type: VerifyContractResponseDto,
})
public async verifyContractSourceCode(): Promise<VerifyContractResponseDto> {
return null;
}

@ApiTags("Contract API")
@Get("api?module=contract&action=checkverifystatus")
@ApiOperation({ summary: "Check source code verification submission status" })
@ApiQuery({
name: "guid",
description: "Verification ID",
example: "44071",
required: true,
})
@ApiOkResponse({
description: "Source code verification status",
type: ContractVerificationStatusResponseDto,
})
public async getVerificationStatus(): Promise<ContractVerificationStatusResponseDto> {
return null;
}

@ApiTags("Transaction API")
@Get("api?module=transaction&action=getstatus")
@ApiOperation({ summary: "Fetch the status for a given transaction hash" })
Expand Down
Loading

0 comments on commit 12f415d

Please sign in to comment.