From e777cf5cc63e11cfe7a7621f7ebfa61d4ce2483f Mon Sep 17 00:00:00 2001 From: Vasyl Ivanchuk Date: Mon, 30 Oct 2023 19:00:19 +0200 Subject: [PATCH] feat: swagger working examples for all environments (#71) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # What ❔ Dynamic swagger constants for different environments. ## Why ❔ Right now swagger examples are hardcoded and don't work on all envs which might be confusing for users. In order to provide better developer experience we want the default examples we provide to work on all envs out of the box. ## Checklist - [X] PR title corresponds to the body of PR (we generate changelog entries from PRs). - [X] Tests for the changes have been added / updated. --- packages/api/.env.example | 1 + packages/api/nest-cli.json | 9 ++- .../api/src/address/address.controller.ts | 7 +- packages/api/src/api/api.controller.spec.ts | 14 ++++ packages/api/src/api/api.controller.ts | 80 +++++++++++++------ .../contract/verifyContractRequest.dto.ts | 6 +- .../src/config/docs/constants.mainnet.json | 10 +++ .../config/docs/constants.testnet-goerli.json | 10 +++ packages/api/src/config/docs/index.spec.ts | 68 ++++++++++++++++ packages/api/src/config/docs/index.ts | 37 +++++++++ packages/api/src/token/token.controller.ts | 5 +- .../src/transaction/transaction.controller.ts | 7 +- 12 files changed, 218 insertions(+), 36 deletions(-) create mode 100644 packages/api/src/config/docs/constants.mainnet.json create mode 100644 packages/api/src/config/docs/constants.testnet-goerli.json create mode 100644 packages/api/src/config/docs/index.spec.ts create mode 100644 packages/api/src/config/docs/index.ts diff --git a/packages/api/.env.example b/packages/api/.env.example index e9a1ce6464..ed85f208b3 100644 --- a/packages/api/.env.example +++ b/packages/api/.env.example @@ -13,3 +13,4 @@ DISABLE_BFF_API_SCHEMA_DOCS=false DISABLE_EXTERNAL_API=false DATABASE_STATEMENT_TIMEOUT_MS=90000 CONTRACT_VERIFICATION_API_URL=http://127.0.0.1:3070 +NETWORK_NAME=testnet-goerli diff --git a/packages/api/nest-cli.json b/packages/api/nest-cli.json index 256648114a..db78c9f4be 100644 --- a/packages/api/nest-cli.json +++ b/packages/api/nest-cli.json @@ -1,5 +1,10 @@ { "$schema": "https://json.schemastore.org/nest-cli", "collection": "@nestjs/schematics", - "sourceRoot": "src" -} + "sourceRoot": "src", + "compilerOptions": { + "assets": [ + "config/docs/constants.*.json" + ] + } +} \ No newline at end of file diff --git a/packages/api/src/address/address.controller.ts b/packages/api/src/address/address.controller.ts index 8b953062f5..d6b30e772e 100644 --- a/packages/api/src/address/address.controller.ts +++ b/packages/api/src/address/address.controller.ts @@ -25,6 +25,7 @@ import { ParseAddressPipe, ADDRESS_REGEX_PATTERN } from "../common/pipes/parseAd import { TransferService } from "../transfer/transfer.service"; import { TransferDto } from "../transfer/transfer.dto"; import { swagger } from "../config/featureFlags"; +import { constants } from "../config/docs"; const entityName = "address"; @@ -46,7 +47,7 @@ export class AddressController { @ApiParam({ name: "address", schema: { pattern: ADDRESS_REGEX_PATTERN }, - example: "0xd754ff5e8a6f257e162f72578a4bb0493c0681d8", + example: constants.address, description: "Valid hex address", }) @ApiExtraModels(AccountDto, ContractDto) @@ -112,7 +113,7 @@ export class AddressController { @ApiParam({ name: "address", schema: { pattern: ADDRESS_REGEX_PATTERN }, - example: "0xd754ff5e8a6f257e162f72578a4bb0493c0681d8", + example: constants.contractAddressWithLogs, description: "Valid hex address", }) @ApiListPageOkResponse(LogDto, { description: "Successfully returned address logs" }) @@ -136,7 +137,7 @@ export class AddressController { @ApiParam({ name: "address", schema: { pattern: ADDRESS_REGEX_PATTERN }, - example: "0xd754ff5e8a6f257e162f72578a4bb0493c0681d8", + example: constants.address, description: "Valid hex address", }) @ApiListPageOkResponse(TransferDto, { description: "Successfully returned address transfers" }) diff --git a/packages/api/src/api/api.controller.spec.ts b/packages/api/src/api/api.controller.spec.ts index fc2a8d7001..567eaa2876 100644 --- a/packages/api/src/api/api.controller.spec.ts +++ b/packages/api/src/api/api.controller.spec.ts @@ -122,6 +122,20 @@ describe("ApiController", () => { }); }); + describe("getInternalTransactionsByTxHash", () => { + it("returns null as it is defined only to appear in docs and cannot be called", async () => { + const result = await controller.getInternalTransactionsByTxHash( + { + page: 1, + offset: 10, + maxLimit: 10000, + }, + { sort: SortingOrder.Desc } + ); + expect(result).toBe(null); + }); + }); + describe("getAccountTokenTransfers", () => { it("returns null as it is defined only to appear in docs and cannot be called", async () => { const result = await controller.getAccountTokenTransfers( diff --git a/packages/api/src/api/api.controller.ts b/packages/api/src/api/api.controller.ts index ef950f075d..7694f04c7d 100644 --- a/packages/api/src/api/api.controller.ts +++ b/packages/api/src/api/api.controller.ts @@ -43,6 +43,7 @@ import { ParseModulePipe } from "./pipes/parseModule.pipe"; import { ParseActionPipe } from "./pipes/parseAction.pipe"; import { ApiExceptionFilter } from "./exceptionFilter"; import { LogsResponseDto, LogApiDto } from "./dtos/log/logs.dto"; +import { constants } from "../config/docs"; @Controller("") export class ApiController { @@ -82,7 +83,7 @@ export class ApiController { @ApiQuery({ name: "address", description: "The contract address that has a verified source code", - example: "0x8A63F953e19aA4Ce3ED90621EeF61E17A95c6594", + example: constants.verifiedContractAddress, required: true, }) @ApiOkResponse({ @@ -99,7 +100,7 @@ export class ApiController { @ApiQuery({ name: "address", description: "The contract address that has a verified source code", - example: "0x8A63F953e19aA4Ce3ED90621EeF61E17A95c6594", + example: constants.verifiedContractAddress, required: true, }) @ApiOkResponse({ @@ -118,7 +119,7 @@ export class ApiController { explode: false, name: "contractaddresses", description: "List of contract addresses, up to 5 at a time", - example: ["0x8A63F953e19aA4Ce3ED90621EeF61E17A95c6594", "0x0E03197d697B592E5AE49EC14E952cddc9b28e14"], + example: [constants.verifiedContractAddress, constants.verifiedContractAddress2], required: true, }) @ApiExtraModels(ContractCreationInfoDto) @@ -165,7 +166,7 @@ export class ApiController { @ApiQuery({ name: "txhash", description: "The transaction hash to check the execution status", - example: "0x04a4757cd59681b037c1e7bd2402cc45a23c66ed7497614879376719d34e020a", + example: constants.txHash, required: true, }) @ApiExtraModels(TransactionStatusDto) @@ -183,7 +184,7 @@ export class ApiController { @ApiQuery({ name: "txhash", description: "The transaction hash to check the execution status", - example: "0x04a4757cd59681b037c1e7bd2402cc45a23c66ed7497614879376719d34e020a", + example: constants.txHash, required: true, }) @ApiOkResponse({ @@ -200,7 +201,7 @@ export class ApiController { @ApiQuery({ name: "address", description: "The address to filter transactions by", - example: "0xFb7E0856e44Eff812A44A9f47733d7d55c39Aa28", + example: constants.address, required: true, }) @ApiQuery({ @@ -232,18 +233,49 @@ export class ApiController { } @ApiTags("Account API") - @Get("api?module=account&action=txlistinternal") - @ApiOperation({ summary: "Retrieve internal transactions for a given address or transaction hash" }) + @Get("api?module=account&action=txlistinternal&address=") + @ApiOperation({ summary: "Retrieve internal transactions for a given address" }) @ApiQuery({ name: "address", description: "The address to filter internal transactions by", - example: "0xFb7E0856e44Eff812A44A9f47733d7d55c39Aa28", + example: constants.addressWithInternalTx, required: false, }) + @ApiQuery({ + name: "startblock", + type: "integer", + description: "The block number to start searching for internal transactions", + example: 0, + required: false, + }) + @ApiQuery({ + name: "endblock", + type: "integer", + description: "The block number to stop searching for internal transactions", + example: 99999999, + required: false, + }) + @ApiExtraModels(AccountInternalTransactionDto) + @ApiOkResponse({ + description: "Internal transactions list", + type: AccountInternalTransactionsResponseDto, + }) + public async getAccountInternalTransactions( + // eslint-disable-next-line @typescript-eslint/no-unused-vars + @Query() pagingOptions: PagingOptionsWithMaxItemsLimitDto, + // eslint-disable-next-line @typescript-eslint/no-unused-vars + @Query() sortingOptions: SortingOptionsDto + ): Promise { + return null; + } + + @ApiTags("Account API") + @Get("api?module=account&action=txlistinternal&txhash=") + @ApiOperation({ summary: "Retrieve internal transactions for a given transaction hash" }) @ApiQuery({ name: "txhash", description: "The transaction hash to filter internal transaction by", - example: "0x04a4757cd59681b037c1e7bd2402cc45a23c66ed7497614879376719d34e020a", + example: constants.addressTxWithInternalTransfers, required: false, }) @ApiQuery({ @@ -265,7 +297,7 @@ export class ApiController { description: "Internal transactions list", type: AccountInternalTransactionsResponseDto, }) - public async getAccountInternalTransactions( + public async getInternalTransactionsByTxHash( // eslint-disable-next-line @typescript-eslint/no-unused-vars @Query() pagingOptions: PagingOptionsWithMaxItemsLimitDto, // eslint-disable-next-line @typescript-eslint/no-unused-vars @@ -280,7 +312,7 @@ export class ApiController { @ApiQuery({ name: "address", description: "The address to get Ether balance for", - example: "0xFb7E0856e44Eff812A44A9f47733d7d55c39Aa28", + example: constants.address, required: true, }) @ApiOkResponse({ @@ -299,7 +331,7 @@ export class ApiController { explode: false, name: "address", description: "List of addresses to get Ether balance for", - example: ["0xFb7E0856e44Eff812A44A9f47733d7d55c39Aa28", "0x0E03197d697B592E5AE49EC14E952cddc9b28e14"], + example: [constants.address, constants.addressWithInternalTx], required: true, }) @ApiOkResponse({ @@ -316,13 +348,13 @@ export class ApiController { @ApiQuery({ name: "address", description: "The address to get Token balance for", - example: "0xFb7E0856e44Eff812A44A9f47733d7d55c39Aa28", + example: constants.address, required: true, }) @ApiQuery({ name: "contractaddress", description: "The Token contract address to get balance for", - example: "0x0faF6df7054946141266420b43783387A78d82A9", + example: constants.tokenAddress, required: true, }) @ApiOkResponse({ @@ -339,13 +371,13 @@ export class ApiController { @ApiQuery({ name: "address", description: "The address to get transfers for", - example: "0xFb7E0856e44Eff812A44A9f47733d7d55c39Aa28", + example: constants.address, required: false, }) @ApiQuery({ name: "contractaddress", description: "The Token contract address to get transfers for", - example: "0x0faF6df7054946141266420b43783387A78d82A9", + example: constants.tokenAddress, required: false, }) @ApiQuery({ @@ -382,13 +414,13 @@ export class ApiController { @ApiQuery({ name: "address", description: "The address to get transfers for", - example: "0xFb7E0856e44Eff812A44A9f47733d7d55c39Aa28", + example: constants.address, required: false, }) @ApiQuery({ name: "contractaddress", description: "The Token contract address to get transfers for", - example: "0x0faF6df7054946141266420b43783387A78d82A9", + example: constants.tokenAddress, required: false, }) @ApiQuery({ @@ -472,7 +504,7 @@ export class ApiController { name: "blockno", type: "integer", description: "The integer block number to estimate time remaining to be mined", - example: 12697906, + example: 20697906, required: true, }) @ApiOkResponse({ @@ -490,7 +522,7 @@ export class ApiController { name: "blockno", type: "integer", description: "The integer block number to check block rewards", - example: 12697906, + example: 1500, required: true, }) @ApiOkResponse({ @@ -507,21 +539,21 @@ export class ApiController { @ApiQuery({ name: "address", description: "The address to filter logs by", - example: "0xFb7E0856e44Eff812A44A9f47733d7d55c39Aa28", + example: constants.contractAddressWithLogs, required: true, }) @ApiQuery({ name: "fromBlock", type: "integer", description: "The integer block number to start searching for logs", - example: 12878196, + example: 0, required: false, }) @ApiQuery({ name: "toBlock", type: "integer", description: "The integer block number to stop searching for logs ", - example: 12879196, + example: 99999999, required: false, }) @ApiExtraModels(LogApiDto) diff --git a/packages/api/src/api/dtos/contract/verifyContractRequest.dto.ts b/packages/api/src/api/dtos/contract/verifyContractRequest.dto.ts index 22ec017f81..ab25d00703 100644 --- a/packages/api/src/api/dtos/contract/verifyContractRequest.dto.ts +++ b/packages/api/src/api/dtos/contract/verifyContractRequest.dto.ts @@ -41,7 +41,8 @@ export class VerifyContractRequestDto { }, sources: { "contracts/HelloWorld.sol": { - content: "// SPDX-License-Identifier: UNLICENSED ..", + content: + "// SPDX-License-Identifier: UNLICENSED\n// Specifies the version of Solidity, using semantic versioning.\n// Learn more: https://solidity.readthedocs.io/en/v0.5.10/layout-of-source-files.html#pragma\npragma solidity >=0.7.3;\n\n// Defines a contract named `HelloWorld`.\n// A contract is a collection of functions and data (its state). Once deployed, a contract resides at a specific address on the Ethereum blockchain. Learn more: https://solidity.readthedocs.io/en/v0.5.10/structure-of-a-contract.html\ncontract HelloWorld {\n\n //Emitted when update function is called\n //Smart contract events are a way for your contract to communicate that something happened on the blockchain to your app front-end, which can be 'listening' for certain events and take action when they happen.\n event UpdatedMessages(string oldStr, string newStr);\n\n // Declares a state variable `message` of type `string`.\n // State variables are variables whose values are permanently stored in contract storage. The keyword `public` makes variables accessible from outside a contract and creates a function that other contracts or clients can call to access the value.\n string public message;\n\n // Similar to many class-based object-oriented languages, a constructor is a special function that is only executed upon contract creation.\n // Constructors are used to initialize the contract's data. Learn more:https://solidity.readthedocs.io/en/v0.5.10/contracts.html#constructors\n constructor(string memory initMessage) {\n\n // Accepts a string argument `initMessage` and sets the value into the contract's `message` storage variable).\n message = initMessage;\n }\n\n // A public function that accepts a string argument and updates the `message` storage variable.\n function update(string memory newMessage) public {\n string memory oldMsg = message;\n message = newMessage;\n emit UpdatedMessages(oldMsg, newMessage);\n }\n}", }, }, }, @@ -125,7 +126,8 @@ export class VerifyContractRequestDto { @ApiProperty({ name: "constructorArguements", description: "Contract constructor arguments", - example: "0x94869207468657265210000000000000000000000000000000000000000000000", + example: + "0x000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000094869207468657265210000000000000000000000000000000000000000000000", required: false, }) @IsOptional() diff --git a/packages/api/src/config/docs/constants.mainnet.json b/packages/api/src/config/docs/constants.mainnet.json new file mode 100644 index 0000000000..ce002c0988 --- /dev/null +++ b/packages/api/src/config/docs/constants.mainnet.json @@ -0,0 +1,10 @@ +{ + "verifiedContractAddress": "0x2da10A1e27bF85cEdD8FFb1AbBe97e53391C0295", + "verifiedContractAddress2": "0x1fa66e2B38d0cC496ec51F81c3e05E6A6708986F", + "contractAddressWithLogs": "0x1fa66e2B38d0cC496ec51F81c3e05E6A6708986F", + "txHash": "0xbca76582802d8172fe5bf6ba9c42d675a2ceab858dff555929f2c4021bf77386", + "address": "0xd3D526A8CCA22Fe072cD1852faA4F0a6F2C21765", + "addressWithInternalTx": "0x8B021d2BeD73675F7715422C4BFcBfE759890308", + "addressTxWithInternalTransfers": "0x4683986b4d6b07aa5a8ba6c4a6aa7b1a420a0dfd944ac7128f3e4ab7bd74567c", + "tokenAddress": "0x000000000000000000000000000000000000800A" +} \ No newline at end of file diff --git a/packages/api/src/config/docs/constants.testnet-goerli.json b/packages/api/src/config/docs/constants.testnet-goerli.json new file mode 100644 index 0000000000..1f3dd3fc30 --- /dev/null +++ b/packages/api/src/config/docs/constants.testnet-goerli.json @@ -0,0 +1,10 @@ +{ + "verifiedContractAddress": "0x53E185A2FA7c9caF14A887E8E9a4862D4bd094ea", + "verifiedContractAddress2": "0xbf2A1ACE3B12b81bab4985f05E850AcFCCb416E0", + "contractAddressWithLogs": "0xbf2A1ACE3B12b81bab4985f05E850AcFCCb416E0", + "txHash": "0x3d36c6e6a3625d698ef41d20c9457a6628254c8307df54b7c887e30f7dda00c8", + "address": "0xE4ce1da467a7Ca37727eb7e19857e5167DE25966", + "addressWithInternalTx": "0xbf2A1ACE3B12b81bab4985f05E850AcFCCb416E0", + "addressTxWithInternalTransfers": "0x8a453b8dd3e095b3034dc3692663d5bf0c9883cbe6e9f9a0425a3ebf9b9360ab", + "tokenAddress": "0x000000000000000000000000000000000000800A" +} \ No newline at end of file diff --git a/packages/api/src/config/docs/index.spec.ts b/packages/api/src/config/docs/index.spec.ts new file mode 100644 index 0000000000..fc32352367 --- /dev/null +++ b/packages/api/src/config/docs/index.spec.ts @@ -0,0 +1,68 @@ +const existsSyncMock = jest.fn().mockReturnValue(false); +const readFileSyncMock = jest.fn().mockReturnValue(null); + +jest.mock("node:fs", () => ({ + existsSync: existsSyncMock, + readFileSync: readFileSyncMock, +})); + +jest.mock("../../logger", () => ({ + getLogger: () => ({ error: jest.fn() }), +})); + +describe("constants", () => { + const env = process.env; + const defaultConstants = { + address: "0xFb7E0856e44Eff812A44A9f47733d7d55c39Aa28", + addressTxWithInternalTransfers: "0x04a4757cd59681b037c1e7bd2402cc45a23c66ed7497614879376719d34e020a", + addressWithInternalTx: "0x0E03197d697B592E5AE49EC14E952cddc9b28e14", + contractAddressWithLogs: "0x8A63F953e19aA4Ce3ED90621EeF61E17A95c6594", + tokenAddress: "0x0faF6df7054946141266420b43783387A78d82A9", + txHash: "0x04a4757cd59681b037c1e7bd2402cc45a23c66ed7497614879376719d34e020a", + verifiedContractAddress: "0x8A63F953e19aA4Ce3ED90621EeF61E17A95c6594", + verifiedContractAddress2: "0x0E03197d697B592E5AE49EC14E952cddc9b28e14", + }; + + beforeEach(() => { + jest.resetModules(); + }); + + afterAll(() => { + process.env = env; + }); + + it("should return default constants", async () => { + const { constants } = await import("./"); + expect(constants).toEqual(defaultConstants); + }); + + it("should return constants for the specified environment", async () => { + process.env.NETWORK_NAME = "testnet"; + const testnetConfig = { + verifiedContractAddress: "0x53E185A2FA7c9caF14A887E8E9a4862D4bd094ea", + verifiedContractAddress2: "0xbf2A1ACE3B12b81bab4985f05E850AcFCCb416E0", + contractAddressWithLogs: "0xbf2A1ACE3B12b81bab4985f05E850AcFCCb416E0", + txHash: "0x3d36c6e6a3625d698ef41d20c9457a6628254c8307df54b7c887e30f7dda00c8", + address: "0xE4ce1da467a7Ca37727eb7e19857e5167DE25966", + addressWithInternalTx: "0xbf2A1ACE3B12b81bab4985f05E850AcFCCb416E0", + addressTxWithInternalTransfers: "0x8a453b8dd3e095b3034dc3692663d5bf0c9883cbe6e9f9a0425a3ebf9b9360ab", + tokenAddress: "0x000000000000000000000000000000000000800A", + }; + + existsSyncMock.mockReturnValue(true); + readFileSyncMock.mockReturnValue(JSON.stringify(testnetConfig)); + const { constants } = await import("./"); + + expect(constants).toEqual(testnetConfig); + }); + + it("should return default constants if environment constants cannot be read", async () => { + process.env.NETWORK_NAME = "testnet"; + + existsSyncMock.mockReturnValue(true); + readFileSyncMock.mockReturnValue(new Error("Cannot read the file")); + const { constants } = await import("./"); + + expect(constants).toEqual(defaultConstants); + }); +}); diff --git a/packages/api/src/config/docs/index.ts b/packages/api/src/config/docs/index.ts new file mode 100644 index 0000000000..df2b7171da --- /dev/null +++ b/packages/api/src/config/docs/index.ts @@ -0,0 +1,37 @@ +import { config } from "dotenv"; +import * as path from "path"; +import * as fs from "node:fs"; +import { getLogger } from "../../logger"; + +config(); + +const { NETWORK_NAME } = process.env; + +const defaultDocsConstants = { + verifiedContractAddress: "0x8A63F953e19aA4Ce3ED90621EeF61E17A95c6594", + verifiedContractAddress2: "0x0E03197d697B592E5AE49EC14E952cddc9b28e14", + contractAddressWithLogs: "0x8A63F953e19aA4Ce3ED90621EeF61E17A95c6594", + txHash: "0x04a4757cd59681b037c1e7bd2402cc45a23c66ed7497614879376719d34e020a", + address: "0xFb7E0856e44Eff812A44A9f47733d7d55c39Aa28", + addressWithInternalTx: "0x0E03197d697B592E5AE49EC14E952cddc9b28e14", + addressTxWithInternalTransfers: "0x04a4757cd59681b037c1e7bd2402cc45a23c66ed7497614879376719d34e020a", + tokenAddress: "0x0faF6df7054946141266420b43783387A78d82A9", +}; +let networkDocsConstants = {}; + +if (NETWORK_NAME) { + try { + const networkConstantsFilePath = path.resolve(__dirname, `./constants.${NETWORK_NAME.toLowerCase()}.json`); + if (fs.existsSync(networkConstantsFilePath)) { + networkDocsConstants = JSON.parse(fs.readFileSync(networkConstantsFilePath, { encoding: "utf8" })); + } + } catch (error) { + const logger = getLogger(process.env.NODE_ENV, process.env.LOG_LEVEL); + logger.error(error.message, error.stack, "ConfigDocs"); + } +} + +export const constants = { + ...defaultDocsConstants, + ...networkDocsConstants, +}; diff --git a/packages/api/src/token/token.controller.ts b/packages/api/src/token/token.controller.ts index 6a17e72657..501db99a84 100644 --- a/packages/api/src/token/token.controller.ts +++ b/packages/api/src/token/token.controller.ts @@ -16,6 +16,7 @@ import { TokenDto } from "./token.dto"; import { TransferDto } from "../transfer/transfer.dto"; import { ParseAddressPipe, ADDRESS_REGEX_PATTERN } from "../common/pipes/parseAddress.pipe"; import { swagger } from "../config/featureFlags"; +import { constants } from "../config/docs"; const entityName = "tokens"; @@ -39,7 +40,7 @@ export class TokenController { @ApiParam({ name: "address", schema: { pattern: ADDRESS_REGEX_PATTERN }, - example: "0xd754ff5e8a6f257e162f72578a4bb0493c0681d8", + example: constants.tokenAddress, description: "Valid hex address", }) @ApiOkResponse({ description: "Token was returned successfully", type: TokenDto }) @@ -57,7 +58,7 @@ export class TokenController { @ApiParam({ name: "address", schema: { pattern: ADDRESS_REGEX_PATTERN }, - example: "0xd754ff5e8a6f257e162f72578a4bb0493c0681d8", + example: constants.tokenAddress, description: "Valid hex address", }) @ApiListPageOkResponse(TransferDto, { description: "Successfully returned token transfers list" }) diff --git a/packages/api/src/transaction/transaction.controller.ts b/packages/api/src/transaction/transaction.controller.ts index de59347454..087e73eecd 100644 --- a/packages/api/src/transaction/transaction.controller.ts +++ b/packages/api/src/transaction/transaction.controller.ts @@ -20,6 +20,7 @@ import { LogService } from "../log/log.service"; import { TransactionService } from "./transaction.service"; import { ParseTransactionHashPipe, TX_HASH_REGEX_PATTERN } from "../common/pipes/parseTransactionHash.pipe"; import { swagger } from "../config/featureFlags"; +import { constants } from "../config/docs"; const entityName = "transactions"; @@ -63,7 +64,7 @@ export class TransactionController { @ApiParam({ name: "transactionHash", schema: { pattern: TX_HASH_REGEX_PATTERN }, - example: "0xd99bd0a1ed5de1c258637e40f3e4e1f461375f5ca4712339031a8dade8079e88", + example: constants.txHash, description: "Valid transaction hash", }) @ApiOkResponse({ description: "Transaction was returned successfully", type: TransactionDto }) @@ -83,7 +84,7 @@ export class TransactionController { @ApiParam({ name: "transactionHash", schema: { pattern: TX_HASH_REGEX_PATTERN }, - example: "0xd99bd0a1ed5de1c258637e40f3e4e1f461375f5ca4712339031a8dade8079e88", + example: constants.txHash, description: "Valid transaction hash", }) @ApiListPageOkResponse(TransferDto, { description: "Successfully returned transaction transfers list" }) @@ -112,7 +113,7 @@ export class TransactionController { @ApiParam({ name: "transactionHash", schema: { pattern: TX_HASH_REGEX_PATTERN }, - example: "0xd99bd0a1ed5de1c258637e40f3e4e1f461375f5ca4712339031a8dade8079e88", + example: constants.txHash, description: "Valid transaction hash", }) @ApiListPageOkResponse(LogDto, { description: "Successfully returned transaction logs list" })