API Reference
WebSocket Events
Makers connect to ws://localhost:4000/ws/maker (live: wss://hyperdex.onrender.com/ws/maker) for real-time RFQ delivery. Everything below is handled for you by the maker-sdk — this page documents the wire protocol for reference.
Use the SDK: In practice you never write this by hand. Run
npm run dev <name>; the SDK connects, authenticates, signs, and replies. You only implement a MakerEngine. See Pricing Engines.Connection & Auth
Authentication is done with an Authorization: Bearer header on the WebSocket upgrade request — there is no separate auth message. A bad key is rejected during the handshake.
const ws = new WebSocket("wss://hyperdex.onrender.com/ws/maker", {
headers: { Authorization: "Bearer sk_live_xxx" },
});
ws.onmessage = ({ data }) => {
const msg = JSON.parse(data);
switch (msg.type) {
case "connected": console.log("Connected as", msg.makerName); break;
case "rfq": handleRfq(msg); break;
case "trade": onTradeConfirmed(msg); break;
case "ping": ws.send(JSON.stringify({ type: "pong" })); break;
}
};Handling an RFQ
On an rfq message, price it, build the quote, sign SHA256(XDR(quote)) with your ed25519 key, and send an rfqQuote back over the same socket (bids are not REST). Send rfqError to skip.
function handleRfq(msg) {
// msg.message: { quoteId, tokenIn, tokenOut, amountIn, takerAddress }
const amountOut = engine.getQuote(msg.message); // stroops, or null to skip
if (!amountOut) {
ws.send(JSON.stringify({ type: "rfqError",
message: { quoteId: msg.message.quoteId, reason: "no_inventory" } }));
return;
}
const quote = buildQuote({ ...msg.message, amountOut });
const signature = signQuote(quote); // SHA256(XDR(quote)) + ed25519
ws.send(JSON.stringify({ type: "rfqQuote",
message: { quoteId: msg.message.quoteId, quote, signature } }));
}Message Types
| Type | Direction | Description |
|---|---|---|
| connected | Server → Maker | Handshake accepted; includes makerName |
| error | Server → Maker | Auth or protocol error; includes a reason |
| rfq | Server → Maker | New RFQ — { quoteId, tokenIn, tokenOut, amountIn, takerAddress } |
| rfqQuote | Maker → Server | Signed sealed bid — { quoteId, quote, signature } |
| rfqError | Maker → Server | Skip this RFQ — { quoteId, reason: "no_inventory" | "rate_limit" } |
| priceLevels | Maker → Server | Resting book update (streamed ~every 3s) — { tokenIn, tokenOut, levels[] } |
| trade | Server → Maker | A won quote settled on-chain — { tradeEventId, txHash, amountIn, amountOut } |
| tradeAck | Maker → Server | Acknowledge receipt of a trade event — { tradeEventId } |
| ping / pong | Server ↔ Maker | Keepalive every 30s — respond to ping with pong or the connection drops |