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/api/controllers/RoutesController.ts b/src/api/controllers/RoutesController.ts new file mode 100644 index 0000000..5546457 --- /dev/null +++ b/src/api/controllers/RoutesController.ts @@ -0,0 +1,30 @@ +/* +The Licensed Work is (c) 2024 Sygma +SPDX-License-Identifier: LGPL-3.0-only +*/ +import type { FastifyReply, FastifyRequest } from "fastify"; +import type { DataSource } from "typeorm"; + +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 routesResult = await this.routesService.findRoutes({}); + await reply.status(200).send(routesResult); + } catch (error) { + logger.error("Error occurred when fetching routes", 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/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..1266b61 --- /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; + } +} 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[] 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;