import type { Plugin, PluginAPI } from "@lumeweb/interface-relay"; import { ConsensusCommitteeUpdateRequest, createDefaultClient, } from "@lumeweb/libethsync/node"; import { RPCRequestRaw } from "@lumeweb/libethsync/client"; import axios from "axios"; const EXECUTION_RPC_URL = "https://rpc.ankr.com/eth"; const CONSENSUS_RPC_URL = "http://nimbus-mainnet.commonprefix.com"; interface ExecutionRequest { method: string; params: any[]; } const executionClient = axios.create({ baseURL: EXECUTION_RPC_URL }); const plugin: Plugin = { name: "eth", async plugin(api: PluginAPI): Promise { const client = createDefaultClient(CONSENSUS_RPC_URL); await client.sync(); api.registerMethod("consensus_updates", { cacheable: false, async handler( request: ConsensusCommitteeUpdateRequest, ): Promise { if (!(request?.start && typeof request.start === "number")) { throw new Error("start required and must be a number"); } if (!(request?.count && typeof request.count === "number")) { throw new Error("count required and must be a number"); } request.count = Math.min(request.count, 50); if (!client.isSynced) { client.sync(); } const updates: Uint8Array[] = []; for (let i = 0; i < request.count; i++) { const period = request?.start + i; if (!client.store.hasUpdate(period)) { throw new Error( `update at period ${request?.start} does not exist`, ); } updates.push(client.store.getUpdate(period)); } return updates; }, }); api.registerMethod("consensus_optimistic_update", { cacheable: false, async handler(): Promise { let execInfo = await client.getLatestExecution(); if (!execInfo) { throw new Error("optimistic update not ready"); } return client.latestOptimisticUpdate; }, }); api.registerMethod("execution_request", { cacheable: false, async handler(request: RPCRequestRaw): Promise { const ret = (await executionClient.post("/", request)).data; return { ...ret, id: request.id ?? ret.id }; }, }); }, }; export default plugin;