diff --git a/src/api/index.ts b/src/api/index.ts index fd71773..1c01827 100644 --- a/src/api/index.ts +++ b/src/api/index.ts @@ -1,3 +1,4 @@ export { quoteHandler } from "./quote"; export { statusHandler } from "./status"; export { capabilitiesHandler } from "./capabilities"; +export { vaasHandler } from "./vaas.ts"; diff --git a/src/api/vaas.ts b/src/api/vaas.ts new file mode 100644 index 0000000..b40e65a --- /dev/null +++ b/src/api/vaas.ts @@ -0,0 +1,46 @@ +import { enabledChains } from "../chains.ts"; +import { mockWormhole } from "../mockGuardian.ts"; +import { type Request, type Response } from "express"; +import { type Hex, isHex } from "viem"; + +export const vaasHandler = async (req: Request, res: Response) => { + let txHash = req.query["txHash"]; + + if (!txHash) { + res.status(400).send("txHash is required."); + return; + } + + if (!isHex(txHash)) { + res.status(400).send("txHash must be a valid hex string."); + return; + } + + // Loop through enabledChains and try mockWormhole for each one, returning the first signed VAA + // that mockWormhole returns. + for (const chainConfig of Object.values(enabledChains)) { + try { + if (!isHex(chainConfig.coreContractAddress)) { + continue; + } + const result = await mockWormhole( + chainConfig.rpc, + txHash, + chainConfig.coreContractAddress, + "", + ); + + if (result !== undefined) { + res.status(200).json({ data: [{ vaa: result }] }); + return; + } + } catch (error) { + // Continue to next chain if this one fails + console.log(`Failed to get VAA from chain ${chainConfig.name}:`, error); + } + } + + res.status(200).json({ + data: [], + }); +}; diff --git a/src/index.ts b/src/index.ts index 9592dc3..6d3dfd0 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,7 +1,12 @@ import express from "express"; import cors from "cors"; import { overrideGuardianSet } from "./overrideGuardianSet"; -import { quoteHandler, statusHandler, capabilitiesHandler } from "./api"; +import { + quoteHandler, + statusHandler, + capabilitiesHandler, + vaasHandler, +} from "./api"; import { enabledChains } from "./chains"; import { isHex } from "viem"; @@ -25,6 +30,9 @@ app.use(express.json()); app.post("/v0/quote", quoteHandler); app.post("/v0/status/tx", statusHandler); app.get("/v0/capabilities", capabilitiesHandler); +// This endpoint is part of the Wormholescan API and isn't part of the executor API, but is useful for exposing signed +// VAAs for clients who wish to not use the Executor for relaying and prefer to relay messages themselves. +app.get("/api/v1/vaas", vaasHandler); const server = app.listen(3000, () => { console.log(`Server is running at http://localhost:3000`);