UNPKG

@lodestar/api

Version:

A Typescript REST client for the Ethereum Consensus API

48 lines 2.38 kB
import { getEventSource } from "../../utils/client/eventSource.js"; import { stringifyQuery, urlJoin } from "../../utils/client/format.js"; import { ApiResponse } from "../../utils/client/response.js"; import { getDefinitions, getEventSerdes } from "../routes/events.js"; /** * REST HTTP client for events routes */ export function getClient(config, baseUrl) { const definitions = getDefinitions(config); const eventSerdes = getEventSerdes(config); return { eventstream: async ({ topics, signal, onEvent, onError, onClose, }) => { const query = stringifyQuery({ topics }); const url = `${urlJoin(baseUrl, definitions.eventstream.url)}?${query}`; const EventSource = await getEventSource(); const eventSource = new EventSource(url); const close = () => { eventSource.close(); onClose?.(); signal.removeEventListener("abort", close); }; signal.addEventListener("abort", close, { once: true }); for (const topic of topics) { eventSource.addEventListener(topic, (event) => { const message = eventSerdes.fromJson(topic, JSON.parse(event.data)); onEvent({ type: topic, message }); }); } // EventSource will try to reconnect always on all errors // `eventSource.onerror` events are informative but don't indicate the EventSource closed // The only way to abort the connection from the client is via eventSource.close() eventSource.onerror = function onerror(err) { const errEs = err; // Ignore noisy errors due to beacon node being offline if (!/ECONNREFUSED|EAI_AGAIN/.test(errEs.message ?? "")) { // If there is no message it likely indicates that the server closed the connection onError?.(new Error(errEs.message ?? "Server closed connection")); } // Consider 400 and 500 status errors unrecoverable, close the eventsource if (errEs.status === 400 || errEs.status === 500) { close(); } }; return new ApiResponse(definitions.eventstream); }, }; } //# sourceMappingURL=events.js.map