From 82618bda160b5319c5bc6c25ace96999278b40f9 Mon Sep 17 00:00:00 2001 From: mj52951 Date: Wed, 18 Dec 2024 10:52:10 +0100 Subject: [PATCH 1/5] chore: Add routes endpoint --- src/api/controllers/RoutesController.ts | 32 +++++++++++++++++++ src/api/routes/index.ts | 2 ++ src/api/routes/routeEntity.routes.ts | 20 ++++++++++++ src/api/schemas/index.ts | 21 ++++++++++++ src/api/schemas/routes.schema.ts | 24 ++++++++++++++ src/api/services/dataAccess/routes.service.ts | 32 +++++++++++++++++++ 6 files changed, 131 insertions(+) create mode 100644 src/api/controllers/RoutesController.ts create mode 100644 src/api/routes/routeEntity.routes.ts create mode 100644 src/api/schemas/routes.schema.ts create mode 100644 src/api/services/dataAccess/routes.service.ts diff --git a/src/api/controllers/RoutesController.ts b/src/api/controllers/RoutesController.ts new file mode 100644 index 0000000..b1de05a --- /dev/null +++ b/src/api/controllers/RoutesController.ts @@ -0,0 +1,32 @@ +/* +The Licensed Work is (c) 2024 Sygma +SPDX-License-Identifier: LGPL-3.0-only +*/ +import type { FastifyReply, FastifyRequest } from "fastify"; +import type { DataSource, FindOptionsWhere } from "typeorm"; + +import type { Route } from "../../model"; +import { logger } from "../../utils/logger"; +import { RoutesService } from "../services/dataAccess/routes.service"; + +export class RoutesController { + private routesService: RoutesService; + + constructor(dataSource: DataSource) { + this.routesService = new RoutesService(dataSource); + } + + public async getRoutes( + request: FastifyRequest, + reply: FastifyReply, + ): Promise { + try { + const where: FindOptionsWhere = {}; + const routesResult = await this.routesService.findRoutes(where); + await reply.status(200).send(routesResult); + } catch (error) { + logger.error("Error occurred when fetching transfers", error); + await reply.status(500).send({ error: "Internal server error" }); + } + } +} diff --git a/src/api/routes/index.ts b/src/api/routes/index.ts index f523559..fc8d928 100644 --- a/src/api/routes/index.ts +++ b/src/api/routes/index.ts @@ -4,8 +4,10 @@ SPDX-License-Identifier: LGPL-3.0-only */ import type { FastifyInstance } from "fastify"; +import { routeEntityRoutes } from "./routeEntity.routes"; import { transferRoutes } from "./transfers.routes"; export async function registerRoutes(server: FastifyInstance): Promise { await server.register(transferRoutes, { prefix: "/api" }); + await server.register(routeEntityRoutes, { prefix: "/api" }); } diff --git a/src/api/routes/routeEntity.routes.ts b/src/api/routes/routeEntity.routes.ts new file mode 100644 index 0000000..eb0fc8d --- /dev/null +++ b/src/api/routes/routeEntity.routes.ts @@ -0,0 +1,20 @@ +/* +The Licensed Work is (c) 2024 Sygma +SPDX-License-Identifier: LGPL-3.0-only +*/ +import type { FastifyInstance } from "fastify"; + +import { RoutesController } from "../controllers/RoutesController"; +import { routesSchema } from "../schemas/routes.schema"; + +export async function routeEntityRoutes( + server: FastifyInstance, +): Promise { + const routesController = new RoutesController(server.db); + server.get( + "/routes", + { schema: routesSchema }, + routesController.getRoutes.bind(routesController), + ); + return Promise.resolve(); +} diff --git a/src/api/schemas/index.ts b/src/api/schemas/index.ts index b93c05b..d45afd9 100644 --- a/src/api/schemas/index.ts +++ b/src/api/schemas/index.ts @@ -152,6 +152,27 @@ export const executionSchema = { }, }; +export const routeSchema = { + properties: { + id: { + type: "string", + format: "ObjectId", + example: "1ffe10e3-c16c-4fdb-a357-380accf1eb66", + }, + fromDomainID: { type: "string", example: "1" }, + fromDomain: { ...domainSchema }, + toDomainID: { type: "string", nullable: true, example: "2" }, + toDomain: { ...domainSchema }, + resourceID: { + type: "string", + format: "ObjectId", + example: + "0x0000000000000000000000000000000000000000000000000000000000000300", + }, + resource: { ...resourceSchema }, + }, +}; + export const transferSchema = { type: "object", properties: { diff --git a/src/api/schemas/routes.schema.ts b/src/api/schemas/routes.schema.ts new file mode 100644 index 0000000..412d43f --- /dev/null +++ b/src/api/schemas/routes.schema.ts @@ -0,0 +1,24 @@ +/* +The Licensed Work is (c) 2024 Sygma +SPDX-License-Identifier: LGPL-3.0-only +*/ +import { routeSchema } from "."; + +export const routesSchema = { + summary: "Get routes", + response: { + 200: { + description: "List of routes", + content: { + "application/json": { + schema: { + type: "array", + items: { + ...routeSchema, + }, + }, + }, + }, + }, + }, +}; diff --git a/src/api/services/dataAccess/routes.service.ts b/src/api/services/dataAccess/routes.service.ts new file mode 100644 index 0000000..7a19476 --- /dev/null +++ b/src/api/services/dataAccess/routes.service.ts @@ -0,0 +1,32 @@ +/* +The Licensed Work is (c) 2024 Sygma +SPDX-License-Identifier: LGPL-3.0-only +*/ +import type { DataSource, FindOptionsWhere, Repository } from "typeorm"; + +import { Route } from "../../../model"; + +export class RoutesService { + private routeRepository: Repository; + constructor(dataSource: DataSource) { + this.routeRepository = dataSource.getRepository(Route); + } + + public async findRoutes(where: FindOptionsWhere): Promise { + const routes = await this.routeRepository.find({ + where, + order: { + fromDomainID: "ASC", + toDomainID: "ASC", + resourceID: "ASC", + }, + relations: { + fromDomain: true, + toDomain: true, + // resource: true, + }, + }); + + return routes; + } +} From 0001837c343c3fd3664e294fc1ea1cde9b980124 Mon Sep 17 00:00:00 2001 From: mj52951 Date: Wed, 18 Dec 2024 10:56:05 +0100 Subject: [PATCH 2/5] Lint --- src/api/services/dataAccess/routes.service.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/api/services/dataAccess/routes.service.ts b/src/api/services/dataAccess/routes.service.ts index 7a19476..3bc66d2 100644 --- a/src/api/services/dataAccess/routes.service.ts +++ b/src/api/services/dataAccess/routes.service.ts @@ -18,7 +18,7 @@ export class RoutesService { order: { fromDomainID: "ASC", toDomainID: "ASC", - resourceID: "ASC", + resourceID: "ASC", }, relations: { fromDomain: true, From b62f264fe5f02d5ef6bed0f6dd096e2678aeb303 Mon Sep 17 00:00:00 2001 From: mj52951 Date: Thu, 19 Dec 2024 14:55:48 +0100 Subject: [PATCH 3/5] Add resource relation --- src/api/controllers/RoutesController.ts | 6 ++---- src/api/services/dataAccess/routes.service.ts | 2 +- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/src/api/controllers/RoutesController.ts b/src/api/controllers/RoutesController.ts index b1de05a..7e15da8 100644 --- a/src/api/controllers/RoutesController.ts +++ b/src/api/controllers/RoutesController.ts @@ -3,9 +3,8 @@ The Licensed Work is (c) 2024 Sygma SPDX-License-Identifier: LGPL-3.0-only */ import type { FastifyReply, FastifyRequest } from "fastify"; -import type { DataSource, FindOptionsWhere } from "typeorm"; +import type { DataSource } from "typeorm"; -import type { Route } from "../../model"; import { logger } from "../../utils/logger"; import { RoutesService } from "../services/dataAccess/routes.service"; @@ -21,8 +20,7 @@ export class RoutesController { reply: FastifyReply, ): Promise { try { - const where: FindOptionsWhere = {}; - const routesResult = await this.routesService.findRoutes(where); + const routesResult = await this.routesService.findRoutes({}); await reply.status(200).send(routesResult); } catch (error) { logger.error("Error occurred when fetching transfers", error); diff --git a/src/api/services/dataAccess/routes.service.ts b/src/api/services/dataAccess/routes.service.ts index 3bc66d2..1266b61 100644 --- a/src/api/services/dataAccess/routes.service.ts +++ b/src/api/services/dataAccess/routes.service.ts @@ -23,7 +23,7 @@ export class RoutesService { relations: { fromDomain: true, toDomain: true, - // resource: true, + resource: true, }, }); From ceb1c467bace56dde2a3aaaba0bb347400f5577e Mon Sep 17 00:00:00 2001 From: mj52951 Date: Thu, 19 Dec 2024 14:58:21 +0100 Subject: [PATCH 4/5] Make resource and domains obligatory in route --- schema.graphql | 6 +++--- src/model/generated/route.model.ts | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/schema.graphql b/schema.graphql index 8b8b562..7bc9fb3 100644 --- a/schema.graphql +++ b/schema.graphql @@ -85,12 +85,12 @@ type Fee @entity { type Route @entity @index(fields: ["fromDomainID", "toDomainID", "resourceID"], unique: true) { id: ID! fromDomainID: String - fromDomain: Domain + fromDomain: Domain! toDomainID: String - toDomain: Domain + toDomain: Domain! resourceID: String - resource: Resource + resource: Resource! transfers: [Transfer!] @derivedFrom(field: "route") } \ No newline at end of file diff --git a/src/model/generated/route.model.ts b/src/model/generated/route.model.ts index 6bd0a0f..3a5dcf5 100644 --- a/src/model/generated/route.model.ts +++ b/src/model/generated/route.model.ts @@ -23,21 +23,21 @@ export class Route { @Index_() @ManyToOne_(() => Domain, {nullable: true}) - fromDomain!: Domain | undefined | null + fromDomain!: Domain @StringColumn_({nullable: true}) toDomainID!: string | undefined | null @Index_() @ManyToOne_(() => Domain, {nullable: true}) - toDomain!: Domain | undefined | null + toDomain!: Domain @StringColumn_({nullable: true}) resourceID!: string | undefined | null @Index_() @ManyToOne_(() => Resource, {nullable: true}) - resource!: Resource | undefined | null + resource!: Resource @OneToMany_(() => Transfer, e => e.route) transfers!: Transfer[] From 927027485082bfa8b9a879bed06e2187f4b5a5bf Mon Sep 17 00:00:00 2001 From: mj52951 Date: Thu, 19 Dec 2024 15:13:24 +0100 Subject: [PATCH 5/5] Correct error message --- src/api/controllers/RoutesController.ts | 2 +- tests/e2e/indexing.spec.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/api/controllers/RoutesController.ts b/src/api/controllers/RoutesController.ts index 7e15da8..5546457 100644 --- a/src/api/controllers/RoutesController.ts +++ b/src/api/controllers/RoutesController.ts @@ -23,7 +23,7 @@ export class RoutesController { const routesResult = await this.routesService.findRoutes({}); await reply.status(200).send(routesResult); } catch (error) { - logger.error("Error occurred when fetching transfers", error); + logger.error("Error occurred when fetching routes", error); await reply.status(500).send({ error: "Internal server error" }); } } diff --git a/tests/e2e/indexing.spec.ts b/tests/e2e/indexing.spec.ts index 55631a0..5332089 100644 --- a/tests/e2e/indexing.spec.ts +++ b/tests/e2e/indexing.spec.ts @@ -65,10 +65,10 @@ describe("Indexer e2e tests", function () { const transfers: Array = await response.json(); for (const transfer of transfers) { - if (transfer.route.fromDomain?.name.toLowerCase() == Network.SUBSTRATE) { + if (transfer.route.fromDomain.name.toLowerCase() == Network.SUBSTRATE) { substrateDeposits++; } - switch (transfer.route.resource?.type) { + switch (transfer.route.resource.type) { case ResourceType.FUNGIBLE: { fungibleDeposits++; break;