Skip to main content

Submit AI task din dApp

Exemplu complet de cum un dApp poate folosi rețeaua de mineri OmbraChain pentru a procesa task-uri AI fără să ruleze propriul GPU sau să plătească Anthropic/OpenAI direct.

Use case

DApp-ul tău (ex: "ChatBot decentralizat") vrea ca user-ii să întrebe AI fără ca tu (dev) să plătești factura. User-ul plătește direct cu OMBRA, miner-ul procesează, validatorul atestă.

Flow general

┌──────┐ submitTask ┌─────────┐
│ User │ ───────────────→ │ Mainnet │
│ │ prompt + fee │ mempool │
└──────┘ └─────────┘


┌───────────┐
│ Miner │ → procesează cu Claude/GPT/Ollama
│ (random) │
└───────────┘


┌───────────┐
│ Validator │ → atestă rezultat
└───────────┘


┌──────┐ getTask ┌───────────┐
│ User │ ←──────────────── │ Result │
└──────┘ poll/event │ on-chain │
└───────────┘

Cod complet (React)

import { useState } from "react";

export function AIChat() {
const [prompt, setPrompt] = useState("");
const [taskId, setTaskId] = useState<string | null>(null);
const [result, setResult] = useState<string | null>(null);
const [loading, setLoading] = useState(false);

async function submit() {
if (!window.ombra) return alert("Install Ombra Wallet ext.");
setLoading(true);

// 1. Connect dacă nu e deja
await window.ombra.request({ method: "ombra_connect" });

// 2. Submit task
const { taskId } = await window.ombra.request({
method: "ombra_submitTask",
params: {
prompt,
taskType: "chat",
fee: "500000", // 0.5 OMBRA
maxTokens: 2000
}
});

setTaskId(taskId);

// 3. Poll pentru rezultat (every 5s)
const interval = setInterval(async () => {
const task = await window.ombra.request({
method: "ombra_getTask",
params: { taskId }
});

if (task.status === "completed") {
setResult(task.result);
setLoading(false);
clearInterval(interval);
} else if (task.status === "failed") {
alert("Task failed: " + task.error);
setLoading(false);
clearInterval(interval);
}
}, 5000);
}

return (
<div>
<textarea
value={prompt}
onChange={(e) => setPrompt(e.target.value)}
placeholder="Întreabă orice..."
/>
<button onClick={submit} disabled={loading}>
{loading ? "Procesare..." : "Submit (0.5 OMBRA)"}
</button>
{taskId && <p>Task ID: {taskId}</p>}
{result && <pre>{result}</pre>}
</div>
);
}

Parametrii ombra_submitTask

ParametruTipRequiredDescriere
promptstringdaText-ul promptului AI
taskType"chat" | "code" | "analysis"daHint pentru routing miner
feestring (micro-OMBRA)daMin 500000 (0.5 OMBRA), recomandat 1000000+
maxTokensnumbernuCap pe output (default 4000)
modelstringnuHint preferințe model (ex: "claude-opus")

Cost real

Fee-ul tău (ex: 0.5 OMBRA) se distribuie:

Destinație%Cantitate (la 0.5 OMBRA)
Miner (cel care procesează)70%0.35 OMBRA
Burn (deflație)25%0.125 OMBRA
Validator (atestă blocul)5%0.025 OMBRA

În plus, miner-ul primește reward natural (output+thinking)/1M OMBRA — dar NU iese din buzunarul tău, e nou-emis on-chain.

Async vs sync

Pentru UX bun:

  • Polling (every 5s) e simplu dar generează request-uri inutile
  • WebSocket subscription (mai performant):
const ws = new WebSocket("wss://api.ombra-net.com/ws");
ws.send(JSON.stringify({ type: "subscribe_task", taskId }));
ws.onmessage = (event) => {
const { status, result } = JSON.parse(event.data);
if (status === "completed") setResult(result);
};

Error handling

Task-ul poate fail cu:

  • INSUFFICIENT_BALANCE — user nu are destul OMBRA
  • INVALID_PROMPT — prompt gol sau prea lung (>10K chars)
  • NO_MINERS_AVAILABLE — niciun miner online (rar)
  • TIMEOUT — niciun miner nu a răspuns în 5 minute
  • ALL_MINERS_REJECTED — output validators marcat invalid de >3 mineri
try {
await window.ombra.request({ method: "ombra_submitTask", params: { ... } });
} catch (err) {
if (err.code === "INSUFFICIENT_BALANCE") {
alert("Nu ai destul OMBRA. Top up wallet.");
} else {
console.error(err);
}
}

Best practices

  1. Verifică balance înainte de submit:

    const balance = BigInt(await window.ombra.request({ method: "ombra_balance" }));
    if (balance < 500000n) return alert("Top up wallet");
  2. Cache rezultate — task-urile identice nu se cache-uiesc on-chain (e wasteful să re-submit același prompt)

  3. Fee dinamic — pentru task-uri urgente, fee mai mare = prioritate mempool mai mare

    const urgentFee = "2000000"; // 2 OMBRA pentru priority
  4. maxTokens conservator — limitează maxTokens pentru predictabilitate cost

Vezi și