diff --git a/packages/api/src/beacon/server/events.ts b/packages/api/src/beacon/server/events.ts index 3e45b104ecb5..f687f21f874b 100644 --- a/packages/api/src/beacon/server/events.ts +++ b/packages/api/src/beacon/server/events.ts @@ -1,7 +1,7 @@ import {ChainForkConfig} from "@lodestar/config"; import {ErrorAborted} from "@lodestar/utils"; -import {Api, ReqTypes, routesData, getEventSerdes} from "../routes/events.js"; -import {ServerRoutes} from "../../utils/server/index.js"; +import {Api, ReqTypes, routesData, getEventSerdes, eventTypes} from "../routes/events.js"; +import {ApiError, ServerRoutes} from "../../utils/server/index.js"; import {ServerApi} from "../../interfaces.js"; export function getRoutes(config: ChainForkConfig, api: ServerApi): ServerRoutes { @@ -15,6 +15,13 @@ export function getRoutes(config: ChainForkConfig, api: ServerApi): ServerR id: "eventstream", handler: async (req, res) => { + const validTopics = new Set(Object.values(eventTypes)); + for (const topic of req.query.topics) { + if (!validTopics.has(topic)) { + throw new ApiError(400, `Invalid topic: ${topic}`); + } + } + const controller = new AbortController(); try { diff --git a/packages/api/src/beacon/server/index.ts b/packages/api/src/beacon/server/index.ts index 4f90ed24dee7..6c1cc9c16a4b 100644 --- a/packages/api/src/beacon/server/index.ts +++ b/packages/api/src/beacon/server/index.ts @@ -1,6 +1,6 @@ import {ChainForkConfig} from "@lodestar/config"; import {Api} from "../routes/index.js"; -import {ServerInstance, ServerRoute, RouteConfig, registerRoute} from "../../utils/server/index.js"; +import {ApiError, ServerInstance, ServerRoute, RouteConfig, registerRoute} from "../../utils/server/index.js"; import {ServerApi} from "../../interfaces.js"; import * as beacon from "./beacon.js"; @@ -13,6 +13,9 @@ import * as node from "./node.js"; import * as proof from "./proof.js"; import * as validator from "./validator.js"; +// Re-export for usage in beacon-node +export {ApiError}; + // Re-export for convenience export {RouteConfig}; diff --git a/packages/api/src/utils/server/errors.ts b/packages/api/src/utils/server/errors.ts new file mode 100644 index 000000000000..ea075678f4f6 --- /dev/null +++ b/packages/api/src/utils/server/errors.ts @@ -0,0 +1,9 @@ +import {HttpErrorCodes} from "../client/httpStatusCode.js"; + +export class ApiError extends Error { + statusCode: HttpErrorCodes; + constructor(statusCode: HttpErrorCodes, message?: string) { + super(message); + this.statusCode = statusCode; + } +} diff --git a/packages/api/src/utils/server/index.ts b/packages/api/src/utils/server/index.ts index 5a0227a01916..2e17e9ee2a6f 100644 --- a/packages/api/src/utils/server/index.ts +++ b/packages/api/src/utils/server/index.ts @@ -1,3 +1,4 @@ export * from "./genericJsonServer.js"; export * from "./registerRoute.js"; +export * from "./errors.js"; export * from "./types.js"; diff --git a/packages/beacon-node/src/api/impl/errors.ts b/packages/beacon-node/src/api/impl/errors.ts index 7169b7138295..cc877de90a7a 100644 --- a/packages/beacon-node/src/api/impl/errors.ts +++ b/packages/beacon-node/src/api/impl/errors.ts @@ -1,12 +1,6 @@ -import {HttpErrorCodes} from "@lodestar/api"; +import {ApiError} from "@lodestar/api/beacon/server"; -export class ApiError extends Error { - statusCode: HttpErrorCodes; - constructor(statusCode: HttpErrorCodes, message?: string) { - super(message); - this.statusCode = statusCode; - } -} +export {ApiError}; export class StateNotFound extends ApiError { constructor() { diff --git a/packages/beacon-node/src/api/impl/events/index.ts b/packages/beacon-node/src/api/impl/events/index.ts index 18f9ff160b3a..9f75bc0a83c5 100644 --- a/packages/beacon-node/src/api/impl/events/index.ts +++ b/packages/beacon-node/src/api/impl/events/index.ts @@ -1,19 +1,12 @@ import {routes, ServerApi} from "@lodestar/api"; import {ApiModules} from "../types.js"; -import {ApiError} from "../errors.js"; export function getEventsApi({chain}: Pick): ServerApi { - const validTopics = new Set(Object.values(routes.events.eventTypes)); - return { async eventstream(topics, signal, onEvent) { const onAbortFns: (() => void)[] = []; for (const topic of topics) { - if (!validTopics.has(topic)) { - throw new ApiError(400, `Unknown topic ${topic}`); - } - // eslint-disable-next-line @typescript-eslint/no-explicit-any const handler = (data: any): void => { // TODO: What happens if this handler throws? Does it break the other chain.emitter listeners?