For this guide we'll be using JavaScript and the ws library to handle the WebSocket connection.
Connect to SEDA Fast
Once you have your API key you can open a WebSocket connection to SEDA Fast. After establishing the connection, the server sends an authorized message if the API key is valid. You must wait for this message before sending execution or feed requests.
Example code:
constWebSocket=require("ws");constws=newWebSocket("wss://fast-ws.mainnet.seda.xyz/ws/v1",{headers:{Authorization:`Bearer ${process.env.SEDA_FAST_API_KEY}`},});ws.on("open",()=>console.log("π Connected"));ws.on("message",(data)=>{constmsg=JSON.parse(data.toString()); // Uncomment this line to see the full message // console.log("π¨", JSON.stringify(msg, null, 2));if (msg.method==="authorized") {console.log("β Authorized"); // Close the connection after receiving the authorized notificationws.close(1000,"closed by client");}if (msg.error) {console.error("β",msg.error.code,msg.error.message);}});ws.on("error",(e)=>console.error("β",e));ws.on("close",(code,reason)=>{console.log("π Disconnected",code?`(${code}${reason?`: ${reason}`:""})`:"");});
Executing a Single Request
Once the authorisation works it is time to execute an Oracle Program.
Understanding the Response
A successful response includes:
Key fields:
id - The JSON-rpc id of the request.
result.data.dataRequest - Details of the Oracle Program execution request (program IDs, inputs, gas limits)
result.data.dataResult.result - The hex-encoded final result from the Oracle Program
result.data.dataResult.exitCode - 0 indicates success, non-zero indicates an error
result.data.dataResult.gasUsed - Total gas consumed during execution
result.data.dataResult.drId - Unique identifier for this data request
result.data.signature - Cryptographic signature for verification
result.data.result - Convenient top-level access to the result (same as dataResult.result)
Additional fields may be included in the response depending on the parameters used. The WebSocket API supports the same parameters as the REST API. See the REST API Reference for complete details on all available parameters and response fields.
Failed Execution Error Handling
In the event that the message is valid and the request succeeds, but the execution of the Oracle Program fails, the WebSocket service sends an error response for the JSON-RPC request id with a "FailedExecutionResponse" tag.
Example failed execution response
When debugging failures, the response can include additional fields like "stderr" and "stdout" to help identify the issue (use the includeDebugInfo parameter to enable these).
WebSocket Error Handling
Any other errors, such as invalid parameters or invalid JSON have a smaller error response with a code and the error message.
Example
For a complete list of error codes and their meanings, see the Error Codes section in the WebSocket API Reference.
Managing a Feed
To receive continuous updates you can start a feed. A feed continues running and sending feed.result messages until:
The client sends feed.stop for the feed
The WebSocket connection is closed
It is similar to executing a single request:
Understanding a Feed Result
A successful response is very similar to the feed.execute response, just wrapped in another object that contains the feed id for this result:
Feed Error Handling
In the event that the execution of the Oracle Program in the feed fails, the WebSocket service sends an error response for the JSON-rpc request id. This is similar to feed.execute, just wrapped in another object that contains the feed id for this failed execution.
const WebSocket = require("ws");
const executeRequest = {
jsonrpc: "2.0",
// For this example we're using a hardcoded request ID
id: "req-1",
// The method, either "feed.execute", "feed.start", or "feed.stop"
method: "feed.execute",
// The parameters of the request. These are the same as the execute endpoint on the REST API
params: {
execProgramId: "0x568732e496819819f2effa240614b8ebe53c2492149443578e155a145e0a351e",
execInputs: "0x9b190a0000000000",
inputEncoding: "auto",
includeDebugInfo: "true",
injectLastResult: "success",
encoding: "json",
},
};
const ws = new WebSocket(WS_URL, {
headers: { Authorization: `Bearer ${process.env.SEDA_FAST_API_KEY}` },
});
ws.on("open", () => console.log("π Connected"));
ws.on("message", (data) => {
const msg = JSON.parse(data.toString());
// Uncomment this line to see the full message
// console.log("π¨", JSON.stringify(msg, null, 2));
if (msg.method === "authorized") {
console.log("β Authorized");
// When authorized immediately send an execute request
ws.send(JSON.stringify(executeRequest));
}
// We check for the same ID that we specified in the executeRequest
if (msg.id === "req-1" && msg.result !== undefined) {
const exitCode = msg.result.data.dataResult.exitCode;
console.log("π Result:", !exitCode ? "success" : "failed");
// Close the connection after receiving the result
ws.close(1000, "closed by client");
}
if (msg.error) {
console.error("β", msg.error.code, msg.error.message);
}
});
ws.on("error", (e) => console.error("β", e));
ws.on("close", (code, reason) => {
console.log("π Disconnected", code ? `(${code}${reason ? `: ${reason}` : ""})` : "");
});
const WebSocket = require("ws");
const feedStartRequest = {
jsonrpc: "2.0",
// For this example we're using a hardcoded request ID
id: "req-1",
// The method, either "feed.execute", "feed.start", or "feed.stop"
method: "feed.start",
params: {
// The parameters of the request. These are the same as the execute endpoint on the REST API
execute: {
execProgramId: "0x568732e496819819f2effa240614b8ebe53c2492149443578e155a145e0a351e",
execInputs: "0x9b190a0000000000",
inputEncoding: "auto",
includeDebugInfo: "true",
injectLastResult: "success",
encoding: "json",
},
// The update frequency of the feed in milliseconds
periodicityMs: 5000,
// The scheduling mode, see the API reference for more details
mode: "FIXED",
},
};
const ws = new WebSocket(WS_URL, {
headers: { Authorization: `Bearer ${process.env.SEDA_FAST_API_KEY}` },
});
const applicationState = {
/** Null when there is no feed, otherwise a string */
feedId: null,
/** Number of reports received */
resultsReceived: 0,
};
// Stop the feed after receiving 2 updates
const STOP_AFTER_FEED_RESULTS = 2;
ws.on("open", () => console.log("π Connected"));
ws.on("message", (data) => {
const msg = JSON.parse(data.toString());
// Uncomment this line to see the full message
// console.log("π¨", JSON.stringify(msg, null, 2));
if (msg.method === "authorized") {
console.log("β Authorized");
// When authorized immediately start the feed
ws.send(JSON.stringify(feedStartRequest));
}
// We check for the same ID that we specified in the executeRequest and store the feed id
if (msg.id === "req-1" && msg.result !== undefined && msg.result.feedId) {
applicationState.feedId = msg.result.feedId;
console.log("β Feed started:", applicationState.feedId);
}
if (msg.method === "feed.result" && msg.params?.feedId === applicationState.feedId) {
applicationState.resultsReceived += 1;
console.log(`π¬ feed.result ${applicationState.resultsReceived}/${STOP_AFTER_FEED_RESULTS}`);
if (applicationState.resultsReceived >= STOP_AFTER_FEED_RESULTS) {
console.log("π€ Sending feed.stop...");
ws.send(
JSON.stringify({
jsonrpc: "2.0",
id: "req-2",
method: "feed.stop",
params: { feedId: applicationState.feedId },
}),
);
}
}
// We check for the same ID that we specified in the feed.stop message
if (msg.id === "req-2" && msg.result !== undefined) {
console.log("β Feed stopped");
// Close the connection after receiving the response for the feed.stop request
ws.close(1000, "closed by client");
}
if (msg.error) {
console.error("β", msg.error.code, msg.error.message);
}
});
ws.on("error", (e) => console.error("β", e));
ws.on("close", (code, reason) => {
console.log("π Disconnected", code ? `(${code}${reason ? `: ${reason}` : ""})` : "");
});