Skip to main content

Poll task status

A TASK_SUBMIT goes through 4 states: submitted → responses_collected → validated → rewarded. Two ways to track:

  1. Polling — simple, works everywhere
  2. SSE — push notifications, lower latency, no wasted requests

Polling with timeout

import { OmbraClient } from "@ombrachain/sdk";

const client = new OmbraClient({ endpoint: "https://api.ombra-net.com" });

async function waitForTask(taskId: string, timeoutMs = 90_000): Promise<any> {
const start = Date.now();
while (Date.now() - start < timeoutMs) {
await new Promise((r) => setTimeout(r, 2_000));
const task = await client.tasks.getTask(taskId);
if (task.status === "rewarded" || task.status === "validated") {
return task; // got an answer
}
if (task.status === "failed" || task.status === "timeout") {
throw new Error(`Task ${task.status}`);
}
}
throw new Error("Polling timeout");
}

const result = await waitForTask("d00cb34e8b163a15...");
console.log("answer:", result.bestResponse);
console.log("miner:", result.bestMinerId);

SSE-driven (lower latency)

Subscribe to chain events and filter for your task's lifecycle:

async function waitForTaskSSE(taskId: string, timeoutMs = 90_000): Promise<any> {
return new Promise((resolve, reject) => {
const timeout = setTimeout(() => {
sub.close();
reject(new Error("SSE timeout"));
}, timeoutMs);

const sub = client.events.subscribeChain(async (event) => {
if (event.type !== "block") return;
for (const tx of event.data.transactions) {
if (tx.taskId !== taskId) continue;
if (tx.type === "TASK_REWARD") {
clearTimeout(timeout);
sub.close();
const final = await client.tasks.getTask(taskId);
resolve(final);
}
}
});
});
}

Hybrid (production-safe)

Polling can miss state updates between intervals. SSE alone can drop connections. Combine:

async function waitHybrid(taskId: string): Promise<any> {
return new Promise((resolve, reject) => {
let done = false;
const finish = (val: any, err?: Error) => {
if (done) return;
done = true;
sub.close();
clearInterval(poller);
err ? reject(err) : resolve(val);
};

// Path A: SSE
const sub = client.events.subscribeChain((event) => {
// ... check for TASK_REWARD as above
});

// Path B: poll every 5s as backup
const poller = setInterval(async () => {
const task = await client.tasks.getTask(taskId);
if (task.status === "rewarded") finish(task);
}, 5_000);

setTimeout(() => finish(null, new Error("timeout 90s")), 90_000);
});
}

Status meanings

StatusWhat it means
submittedIn mempool or included in a block, no responses yet
responses_collectedOne or more miners responded
validatedValidator scored responses, picked best
rewardedTASK_REWARD distributed — final state
failedValidator marked task as failed (no good response)
timeoutNo response within timeoutMs