@lodestar/api
Version:
A Typescript REST client for the Ethereum Consensus API
48 lines • 2.38 kB
JavaScript
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