const { useState, useEffect, useRef, useMemo } = React;
const BFF = window.BFF_URL || "";
// Locked fallback scores — never change
const FALLBACK = {
alice: { score: 0.2641, verdict: "rejected", mode: "Direct" },
bob: { score: 0.6703, verdict: "approved", mode: "Workflow" },
carol: { score: 0.0000, verdict: "blocked", mode: "Web3" },
};
const AGENTS_META = [
{ id: "alice", name: "Agent Alice", role: "MEV Sandwich Bot", initials: "AL",
address: "0xa11cea1a11cea1a11cea1a11cea1a11cea1a11ce" },
{ id: "bob", name: "Agent Bob", role: "Honest Arb Agent", initials: "BO",
address: "0xb0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0" },
{ id: "carol", name: "Agent Carol", role: "Unverified New Agent", initials: "CA",
address: "0xca401ca401ca401ca401ca401ca401ca401ca401" },
];
function verdictFor(score) {
if (score >= 0.5) return "approved";
if (score >= 0.1) return "rejected";
return "blocked";
}
// ---------- Animated number ----------
function useAnimatedNumber(target, duration = 900) {
const [v, setV] = useState(0);
const raf = useRef();
const start = useRef(null);
const from = useRef(0);
useEffect(() => {
cancelAnimationFrame(raf.current);
from.current = v;
start.current = null;
const step = (t) => {
if (start.current == null) start.current = t;
const p = Math.min(1, (t - start.current) / duration);
const eased = 1 - Math.pow(1 - p, 3);
setV(from.current + (target - from.current) * eased);
if (p < 1) raf.current = requestAnimationFrame(step);
};
raf.current = requestAnimationFrame(step);
return () => cancelAnimationFrame(raf.current);
}, [target]);
return v;
}
// ---------- Sparkline ----------
function Sparkline({ seed = 1, color = "#8b96a5", trend = 0 }) {
const pts = useMemo(() => {
const n = 32;
let rng = seed * 9301 + 49297;
const rand = () => { rng = (rng * 9301 + 49297) % 233280; return rng / 233280; };
const arr = [];
let y = 0.5;
for (let i = 0; i < n; i++) {
y += (rand() - 0.5) * 0.25 + trend * 0.01;
y = Math.max(0.05, Math.min(0.95, y));
arr.push(y);
}
return arr;
}, [seed, trend]);
const w = 280, h = 36;
const path = pts.map((p, i) => {
const x = (i / (pts.length - 1)) * w;
const y = h - p * h;
return `${i === 0 ? "M" : "L"}${x.toFixed(1)},${y.toFixed(1)}`;
}).join(" ");
const area = path + ` L${w},${h} L0,${h} Z`;
return (
);
}
// ---------- Agent Card ----------
function AgentCard({ meta, data, selected, onSelect }) {
const score = data?.score ?? FALLBACK[meta.id].score;
const verdict = data?.verdict ?? verdictFor(score);
const mode = (data?.mode ?? FALLBACK[meta.id].mode).toLowerCase();
const isAdversarial = meta.id === "carol";
const val = useAnimatedNumber(score);
const pct = Math.round(val * 100);
const barCls = verdict === "approved" ? "green" : verdict === "rejected" ? "red" : "gray";
const sparkColor = verdict === "approved" ? "#00c851" : verdict === "rejected" ? "#ff4444" : "#5b6675";
const trend = verdict === "approved" ? 0.8 : verdict === "rejected" ? -0.6 : 0;
return (
{isAdversarial && (
⚠️
ADVERSARIAL AGENT DETECTED
)}
Merit Score
{val.toFixed(4)}
/ 1.0000
{pct}% confidence
{verdict === "blocked" ? "—" : `ppl ${(val * 1000 | 0)}`}
{verdict.toUpperCase()}
{mode.charAt(0).toUpperCase() + mode.slice(1)}
);
}
// ---------- TEE Tab ----------
function TEETab({ attestation }) {
const [copied, setCopied] = useState(null);
const rows = [
{ key: "compute", label: "Compute Hash", val: attestation?.compute_hash || "0x7f3a9b2c1e4d8f6a3c2b1e9d5f0a4c8e" },
{ key: "storage", label: "Storage Root", val: attestation?.storage_root || "0x4e8c1a7b3f2d9e5c8a16fd0c2e7b94a1" },
{ key: "oracle", label: "Oracle Commit", val: attestation?.oracle_commit || "0x09d34df4fd5c9c75b9970e4fbe0820c2" },
];
const modeLabel = attestation?.mode || "Workflow";
const doCopy = (key, val) => {
navigator.clipboard?.writeText(val).catch(() => {});
setCopied(key);
setTimeout(() => setCopied(null), 1200);
};
return (
{rows.map((r) => (
{r.label}
● Verified
0x {r.val.slice(2, 22)}
…{r.val.slice(-6)}
doCopy(r.key, r.val)}>
{copied === r.key ? "COPIED" : "COPY"}
))}
Verified by 0G Compute TeeML · Evidence anchored on 0G Galileo
{modeLabel.toUpperCase()}
{/* Transparency badges row */}
{/* Provider badge */}
Provider: {(attestation?.provider || "unknown").length > 14
? (attestation?.provider || "unknown").slice(0, 12) + "…"
: attestation?.provider || "unknown"}
{/* Compute badge */}
Compute: {attestation?.compute_ok ? "✓" : "✗"}
{/* Storage badge */}
Storage: {attestation?.storage_ok ? "✓" : "✗"}
{/* Fallback badge - only render if fallback_reason is non-null/non-empty */}
{attestation?.fallback_reason && (
Fallback: {attestation.fallback_reason}
)}
);
}
// ---------- Workflow Tab ----------
function WorkflowTab({ agentMeta }) {
const [addr, setAddr] = useState(agentMeta?.address || "");
const [threshold, setThreshold] = useState(6500);
const [running, setRunning] = useState(false);
const [step, setStep] = useState(-1);
const [result, setResult] = useState(null);
const [log, setLog] = useState([]);
useEffect(() => { setAddr(agentMeta?.address || ""); }, [agentMeta?.id]);
const pushLog = (line, cls = "") => {
const ts = new Date().toLocaleTimeString("en-GB", { hour12: false });
setLog((l) => [...l.slice(-40), { ts, line, cls }]);
};
const run = async () => {
if (running) return;
setRunning(true); setResult(null); setStep(0); setLog([]);
pushLog(`→ Dispatching workflow for ${addr.slice(0, 10)}…`, "info");
pushLog(` threshold = ${threshold} / 10000`, "");
try {
setStep(0);
const res = await fetch(`${BFF}/kh/workflow`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ address: addr, threshold }),
});
const data = await res.json();
setTimeout(() => {
pushLog(`${data.check ? "✓" : "✗"} CHECK — on-chain identity resolved`, data.check ? "ok" : "err");
setStep(1);
}, 400);
setTimeout(() => {
pushLog(`${data.validate ? "✓" : "✗"} VALIDATE — TEE attestation ${data.validate ? "matched" : "failed"}`, data.validate ? "ok" : "err");
setStep(2);
}, 1100);
setTimeout(() => {
const zk_verified = data.zk_verify?.verified || data.zk_verify?.skipped;
pushLog(`${zk_verified ? "✓" : "✗"} ZK_VERIFY — Merkle proof ${data.zk_verify?.skipped ? "skipped (unknown agent)" : zk_verified ? "verified" : "failed"}`, zk_verified ? "ok" : "err");
if (data.zk_verify?.proof_hash) {
pushLog(` proof: ${data.zk_verify.proof_hash} · merkle_root: ${data.zk_verify.merkle_root?.slice(0, 16)}…`, "info");
}
setStep(3);
}, 1550);
setTimeout(() => {
const approved = data.execute === "OK" || (data.check && data.validate);
if (approved) {
pushLog(`✓ EXECUTE — capital access granted`, "ok");
pushLog(` mode: ${data.mode || "Workflow"} · KeeperHub relay`, "info");
setResult("approved");
} else {
pushLog(`⏳ EXECUTE — ${data.execute || "PENDING"} (below threshold or KH queued)`, "warn");
setResult(data.check && data.validate ? "approved" : "rejected");
}
setStep(-2); setRunning(false);
}, 2400);
} catch (e) {
pushLog(`✗ BFF unreachable: ${e.message}`, "err");
pushLog(` running in offline mode`, "warn");
setStep(-2); setResult("rejected"); setRunning(false);
}
};
const stepState = (i) => {
if (step === -2) {
if (i < 2) return "done";
return result === "approved" ? "done" : "fail";
}
if (step === -1) return "";
if (step === i) return "active";
if (step > i) return "done";
return "";
};
const stepIcon = (i) => {
const s = stepState(i);
if (s === "done") return "✅";
if (s === "fail") return "❌";
if (s === "active") return ▸ ;
return ◌ ;
};
return (
Pipeline
{agentMeta?.name || "—"}
{["CHECK","VALIDATE","ZK_VERIFY","EXECUTE"].map((name, i) => (
{i > 0 && →
}
{name === "ZK_VERIFY" ? "🔐 ZK VERIFY" : name}
{stepIcon(i)}
))}
{log.length === 0 && (
[idle] awaiting dispatch…
)}
{log.map((l, i) => (
[{l.ts}] {" "}
{l.line}
))}
);
}
// ---------- Live Eval Tab (Sword #1 + #4) ----------
function LiveEvalTab() {
const [addr, setAddr] = useState("");
const [running, setRunning] = useState(false);
const [elapsed, setElapsed] = useState(0);
const [result, setResult] = useState(null);
const [phase, setPhase] = useState("idle"); // idle | running | reveal | done
const timerRef = useRef(null);
const startTimer = () => {
const t0 = Date.now();
timerRef.current = setInterval(() => setElapsed(((Date.now() - t0) / 1000).toFixed(1)), 100);
};
const stopTimer = () => { clearInterval(timerRef.current); timerRef.current = null; };
const evaluate = async () => {
if (!addr.trim() || running) return;
setRunning(true); setResult(null); setPhase("running"); setElapsed(0);
startTimer();
try {
const [meritData, analyzeData] = await Promise.all([
fetch(`${BFF}/merit/${addr.trim()}`).then(r => r.json()).catch(() => null),
fetch(`${BFF}/analyze`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ address: addr.trim(), tx_history: [] }),
}).then(r => r.json()).catch(() => null),
]);
stopTimer();
setResult({ merit: meritData, analyze: analyzeData });
setPhase("reveal");
setTimeout(() => setPhase("done"), 1200);
} catch {
stopTimer(); setPhase("idle");
} finally {
setRunning(false);
}
};
const score = result?.merit?.score ?? 0;
const verdict = result?.merit?.exists === false && score === 0 ? "blocked" : verdictFor(score);
const animScore = useAnimatedNumber(phase === "done" || phase === "reveal" ? score : 0, 1100);
const gaming = result?.analyze?.gaming_detected;
const reason = result?.analyze?.reason;
const statusMsg = (s) => {
const t = parseFloat(s);
if (t < 1.5) return "Resolving on-chain identity…";
if (t < 3.5) return "Running AI sandwich analysis…";
if (t < 6) return "Verifying TEE attestation…";
return "Finalising merit score…";
};
return (
setAddr(e.target.value)}
onKeyDown={e => e.key === "Enter" && evaluate()}
disabled={running}
spellCheck={false}
/>
{running
? <>EVALUATING… >
: "▶ EVALUATE"}
{phase === "running" && (
⏱ {elapsed}s
{statusMsg(elapsed)}
)}
{(phase === "reveal" || phase === "done") && result && (
{verdict === "approved" ? "✅ APPROVED" : verdict === "rejected" ? "❌ REJECTED" : "⏸ BLOCKED"}
{animScore.toFixed(4)}
Merit Score
evaluated in {elapsed}s
AI Analysis
SWORD #4
Gemma 4 26B · Ollama
{result.analyze ? (
<>
{gaming ? "⚠ Sandwich pattern detected" : "✓ No gaming pattern found"}
{reason &&
{reason}
}
merit_penalty: {result.analyze.merit_penalty ?? 0} · mode: {result.analyze.mode}
>
) : (
AI analysis unavailable
)}
)}
{phase === "idle" && (
Enter any wallet address to run a live merit evaluation.
Try alice, bob, or{" "}
carol for demo agents.
)}
);
}
// ---------- AI Sandwich Detection Tab (Sword #4) ----------
function AIAnalysisTab({ agentMeta }) {
const [addr, setAddr] = useState(agentMeta?.address || agentMeta?.id || "");
const [running, setRunning] = useState(false);
const [result, setResult] = useState(null);
const [error, setError] = useState(null);
useEffect(() => { setAddr(agentMeta?.id || agentMeta?.address || ""); }, [agentMeta?.id]);
const analyze = async () => {
if (!addr.trim() || running) return;
setRunning(true); setResult(null); setError(null);
try {
const res = await fetch(`${BFF}/analyze`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ address: addr.trim(), tx_history: [] }),
});
const data = await res.json();
setResult(data);
} catch (e) {
setError(e.message);
} finally {
setRunning(false);
}
};
const gaming = result?.gaming_detected;
const adversarial = result?.adversarial_agent;
return (
SWORD #4 — Gemma 4 26B via Ollama detects sandwich MEV attack patterns in agent transaction history. AI classification feeds directly into the merit oracle.
powered by Gemma 4 26B · Ollama · heuristic fallback
setAddr(e.target.value)}
onKeyDown={e => e.key === "Enter" && analyze()}
placeholder="alice / bob / carol — or 0x address"
spellCheck={false}
style={{
flex: 1, background: "#0b1218", border: "1px solid var(--border)",
color: "#fff", padding: "8px 12px", borderRadius: 6,
fontFamily: "inherit", fontSize: 13
}}
/>
{running ? <>ANALYZING… > : "🤖 ANALYZE"}
{error &&
Error: {error}
}
{result && (
{gaming ? "⚠️" : "✅"}
{gaming ? "SANDWICH ATTACK DETECTED" : "NO GAMING PATTERN"}
{adversarial && (
ADVERSARIAL AGENT — ground-truth confirmed
)}
{result.reason && (
{result.reason}
)}
merit_penalty: {result.merit_penalty ?? 0}
mode: {result.mode}
address: {result.address?.slice(0, 14)}…
How it works
1. Agent tx history fetched (or demo history used for named agents)
2. Gemma 4 26B prompt: detect frontrun/backrun sandwich pairs, same-block gas manipulation
3. If Ollama unavailable → heuristic fallback (keyword + block pattern detection)
4. Result feeds into merit_penalty applied to on-chain score
)}
{!result && !running && !error && (
Try carol to see a detected sandwich attack, or bob for a clean agent.
)}
);
}
// ---------- MeritGuard Autonomous Agent Tab ----------
function MeritGuardTab({ agentLoopStatus }) {
const status = agentLoopStatus;
const running = status?.running;
const lastScan = status?.last_scan ? new Date(status.last_scan + "Z").toLocaleTimeString("en-GB", { hour12: false }) : "—";
const actions = status?.actions || [];
const flagged = status?.flagged || [];
return (
{running ? "RUNNING" : "STOPPED"}
Scans every 60s · threshold{" "}
0.30 · last scan{" "}
{lastScan}
powered by 0G Galileo · autonomous loop
{[
{ label: "Agents Monitored", value: status?.agents_checked ?? 3, color: "#5ce8ff" },
{ label: "Flagged (< 0.30)", value: flagged.length, color: flagged.length > 0 ? "#ff4444" : "#00c851" },
{ label: "KH Actions Triggered", value: actions.length, color: "#d5deea" },
].map(({ label, value, color }) => (
))}
{flagged.length > 0 && (
⚠ Flagged agents:
{flagged.join(", ")}
→ KH_EXECUTE triggered
)}
Action Log — last {Math.min(actions.length, 20)} events
{actions.length === 0 ? (
No actions yet — waiting for next scan cycle…
) : (
[...actions].reverse().slice(0, 20).map((a, i) => (
{a.at ? new Date(a.at + "Z").toLocaleTimeString("en-GB", { hour12: false }) : "—"}
{a.agent}
score=
{(a.score || 0).toFixed(4)}
→
{a.action}
{a.result?.status || (typeof a.result === "string" ? a.result : "PENDING")}
))
)}
MeritGuard autonomously monitors on-chain merit scores via{" "}
MeritCore (0G Galileo) and triggers{" "}
KeeperHub workflows for any agent below the risk threshold.
This is fully autonomous — no human intervention required.
);
}
// ---------- ZK Proof Tab (Sword #5) ----------
function ZKProofTab({ agentMeta }) {
const [threshold, setThreshold] = useState(5000);
const [running, setRunning] = useState(false);
const [result, setResult] = useState(null);
const [error, setError] = useState(null);
const agent = agentMeta?.id || "bob";
const generateProof = async () => {
setRunning(true); setResult(null); setError(null);
try {
const res = await fetch(`${BFF}/zk-proof`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ agent, threshold }),
});
const data = await res.json();
setResult(data);
} catch (e) {
setError(e.message);
} finally {
setRunning(false);
}
};
return (
SWORD #5 — Privacy-preserving merit proof: agents prove score ≥ threshold WITHOUT revealing the actual score. Cryptographic guarantee via Groth16 on BN254.
agent:
{agent}
threshold:
setThreshold(parseInt(e.target.value) || 0)}
style={{ width: 80, background: "#1a2633", border: "1px solid var(--border)", color: "#fff", padding: "4px 8px", borderRadius: 4, fontFamily: "inherit" }}
/>
{running ? "⏳ Proving…" : "🔐 Generate ZK Proof"}
{running && (
Building depth-8 Merkle tree → computing Groth16 witness → generating proof…
)}
{error &&
Error: {error}
}
{result && (
{result.success ? (
<>
✅ Proof verified on-chain ready
Public signals: merkleRoot + threshold (score stays private)
merkleRoot
{result.publicSignals?.[0]}
π_a (proof point)
{result.proof?.pi_a?.[0]?.slice(0, 40)}…
protocol
{result.proof?.protocol} · {result.proof?.curve} · gas ~{result.metadata?.verificationGas}
>
) : (
❌ Cannot prove: {result.reason}
)}
)}
);
}
// ---------- Uniswap Swap Tab (Sword #6) ----------
function UniswapSwapTab({ agentMeta }) {
const [fromToken, setFromToken] = useState("WETH");
const [toToken, setToToken] = useState("USDC");
const [amount, setAmount] = useState("0.001");
const [slippage, setSlippage] = useState(2.0);
const [loading, setLoading] = useState(false);
const [quoteResult, setQuoteResult] = useState(null);
const [executeResult, setExecuteResult] = useState(null);
const [error, setError] = useState(null);
const [rejectToast, setRejectToast] = useState(null);
const triggerRejectToast = (merit, threshold) => {
setRejectToast({ merit, threshold });
setTimeout(() => setRejectToast(null), 3500);
};
const TOKENS = {
WETH: "0x4200000000000000000000000000000000000006",
USDC: "0x036CbD53842c5426634e7929541eC2318f3dCF7e",
};
const TOKEN_DECIMALS = {
WETH: 18,
USDC: 6,
};
const toWei = (humanAmount, tokenSymbol) => {
const decimals = TOKEN_DECIMALS[tokenSymbol] || 18;
const factor = Math.pow(10, decimals);
return String(Math.floor(parseFloat(humanAmount) * factor));
};
const fromWei = (weiAmount, tokenSymbol) => {
const decimals = TOKEN_DECIMALS[tokenSymbol] || 18;
const factor = Math.pow(10, decimals);
return (parseFloat(weiAmount) / factor).toFixed(6);
};
const getQuote = async () => {
setLoading(true);
setError(null);
setQuoteResult(null);
setExecuteResult(null);
try {
const amountInWei = toWei(amount, fromToken);
const res = await fetch(`${BFF}/uniswap/swap`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
action: "quote",
address: agentMeta?.id || "bob",
from_token: TOKENS[fromToken],
to_token: TOKENS[toToken],
amount_in: amountInWei,
slippage_pct: slippage,
}),
});
const data = await res.json();
if (!res.ok) {
if (res.status === 403) {
setError(`Merit ${data.merit?.toFixed(4)} below threshold ${data.threshold} — swap blocked`);
triggerRejectToast(data.merit, data.threshold);
} else if (res.status === 400) {
setError(data.detail || "Validation error");
} else {
setError(data.error || "Quote failed");
}
setLoading(false);
return;
}
setQuoteResult(data);
} catch (e) {
setError(e.message);
} finally {
setLoading(false);
}
};
const executeSwap = async () => {
setLoading(true);
setError(null);
setExecuteResult(null);
try {
const amountInWei = toWei(amount, fromToken);
const res = await fetch(`${BFF}/uniswap/swap`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
action: "execute",
address: agentMeta?.id || "bob",
from_token: TOKENS[fromToken],
to_token: TOKENS[toToken],
amount_in: amountInWei,
slippage_pct: slippage,
}),
});
const data = await res.json();
if (!res.ok) {
if (res.status === 403) {
setError(`Merit ${data.merit?.toFixed(4)} below threshold ${data.threshold} — swap blocked`);
triggerRejectToast(data.merit, data.threshold);
} else if (res.status === 502) {
setError(`Swap reverted on-chain: ${data.reason}`);
} else if (res.status === 400) {
setError(data.detail || "Validation error");
} else {
setError(data.error || "Execution failed");
}
setLoading(false);
return;
}
setExecuteResult(data);
} catch (e) {
setError(e.message);
} finally {
setLoading(false);
}
};
return (
{rejectToast && (
403 REJECTED
merit {rejectToast.merit?.toFixed(4)} < {rejectToast.threshold} threshold
BELOW THRESHOLD · NO EXCEPTIONS
)}
SWORD #6 — Merit-gated Uniswap V3 swap on Base Sepolia. Agents with merit ≥ 0.5 can execute swaps with gas-free quote pricing and configurable slippage.
{error && (
⚠ {error}
)}
FROM TOKEN
setFromToken(e.target.value)}
style={{
width: "100%",
background: "#0b1117",
border: "1px solid var(--border)",
color: "#fff",
padding: "10px 12px",
borderRadius: 6,
fontFamily: "inherit",
cursor: "pointer",
}}
>
WETH
USDC
TO TOKEN
setToToken(e.target.value)}
style={{
width: "100%",
background: "#0b1117",
border: "1px solid var(--border)",
color: "#fff",
padding: "10px 12px",
borderRadius: 6,
fontFamily: "inherit",
cursor: "pointer",
}}
>
WETH
USDC
AMOUNT ({fromToken})
setAmount(e.target.value)}
step="0.0001"
min="0"
style={{
width: "100%",
background: "#0b1117",
border: "1px solid var(--border)",
color: "#fff",
padding: "10px 12px",
borderRadius: 6,
fontFamily: "inherit",
fontSize: 13,
}}
placeholder="0.001"
/>
SLIPPAGE (%)
setSlippage(Math.min(5, Math.max(0, parseFloat(e.target.value))))}
step="0.1"
min="0"
max="5"
style={{
width: "100%",
background: "#0b1117",
border: "1px solid var(--border)",
color: "#fff",
padding: "10px 12px",
borderRadius: 6,
fontFamily: "inherit",
fontSize: 13,
}}
placeholder="2.0"
/>
{loading ? "⏳ Loading…" : "💰 Get Quote"}
{loading ? "⏳ Executing…" : "🔄 Execute Swap"}
{quoteResult && !executeResult && (
✓ Quote Retrieved
Amount Out
{fromWei(quoteResult.amount_out, toToken)} {toToken}
Price Impact
{quoteResult.price_impact_pct.toFixed(2)}%
Pool Fee
{(quoteResult.fee_tier / 10000 * 100).toFixed(2)}%
)}
{executeResult && (
✅ Swap Confirmed
Block Number
{executeResult.block_number}
Amount Out
{fromWei(executeResult.amount_out, toToken)} {toToken}
)}
{!quoteResult && !executeResult && !error && (
Enter swap parameters and click "Get Quote" to see the price impact and execute the swap.
)}
);
}
// ---------- App ----------
// ---------- Swarm Consensus Tab (0G Track 2) ----------
function SwarmTab({ agentMeta }) {
const [loading, setLoading] = useState(false);
const [result, setResult] = useState(null);
const [error, setError] = useState(null);
const [agentList, setAgentList] = useState([]);
const [threshold, setThreshold] = useState(5000);
useEffect(() => {
fetch(`${BFF}/swarm/agents`)
.then(r => r.json())
.then(d => setAgentList(d.agents || []))
.catch(e => setError(`Swarm agents unavailable: ${e.message}`));
}, []);
const runSwarm = async () => {
setLoading(true);
setError(null);
setResult(null);
try {
const res = await fetch(`${BFF}/swarm/evaluate`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ address: agentMeta?.id || "bob", threshold }),
});
if (!res.ok) throw new Error(`HTTP ${res.status}`);
setResult(await res.json());
} catch (e) {
setError(e.message);
} finally {
setLoading(false);
}
};
const VERDICT_COLOR = { APPROVE: "#00c851", REJECT: "#ff4444", ABSTAIN: "#ffaa00" };
const VERDICT_ICON = { APPROVE: "✅", REJECT: "❌", ABSTAIN: "⚠️" };
return (
4 autonomous validator agents evaluate {agentMeta?.id || "bob"} in parallel and reach weighted consensus.
{agentList.length > 0 && (
{agentList.map(a => (
{a.healthy ? "●" : "○"} {a.agent_id}
))}
)}
Threshold
{ setThreshold(Number(e.target.value)); setResult(null); }}
style={{ flex: 1, accentColor: "var(--accent)" }} />
{(threshold / 10000).toFixed(2)}
{loading ? "⏳ Evaluating Swarm..." : "▶ Run Swarm Consensus"}
{error && (
Error: {error}
)}
{result && (
{/* Verdict banner */}
{VERDICT_ICON[result.final_verdict]}
{result.final_verdict}
consensus {(result.consensus_score * 100).toFixed(1)}% ·
dissent {(result.dissent_score * 100).toFixed(1)}% ·
{result.swarm_id}
{result.dissent_score > 0.25 && (
⚠ DISSENT
)}
{/* Agent votes */}
AGENT VOTES ({result.agent_votes.length})
{result.agent_votes.map((v, i) => (
{v.agent_id}
{v.role}
{v.reasoning}
{VERDICT_ICON[v.verdict]} {v.verdict}
{(v.confidence * 100).toFixed(0)}% conf
))}
{result.timestamp}
)}
);
}
function App() {
const [selectedId, setSelectedId] = useState("bob");
const [tab, setTab] = useState("live");
const [scores, setScores] = useState({});
const [attestation, setAttestation] = useState(null);
const [chain, setChain] = useState({ galileo: null, base: null });
const [agentLoopStatus, setAgentLoopStatus] = useState(null);
// Fetch health + scores + attestation + agent-loop status on mount + poll
useEffect(() => {
fetch(`${BFF}/health`)
.then(r => r.json())
.then(d => setChain({ galileo: d.chain?.galileo, base: d.chain?.base }))
.catch(() => {});
fetch(`${BFF}/attestation`)
.then(r => r.json())
.then(d => setAttestation(d))
.catch(() => {});
Promise.all(AGENTS_META.map(a =>
fetch(`${BFF}/merit/${a.id}`)
.then(r => r.json())
.then(d => [a.id, d])
.catch(() => [a.id, null])
)).then(results => {
const s = {};
results.forEach(([id, d]) => {
if (d) s[id] = { score: d.score, verdict: verdictFor(d.score), mode: d.mode };
});
setScores(s);
});
// Fetch agent-loop status and poll every 10 seconds
const fetchAgentLoopStatus = () => {
fetch(`${BFF}/agent-loop/status`)
.then(r => r.json())
.then(d => setAgentLoopStatus(d))
.catch(() => {});
};
fetchAgentLoopStatus();
const interval = setInterval(fetchAgentLoopStatus, 10000);
return () => clearInterval(interval);
}, []);
const selected = AGENTS_META.find(a => a.id === selectedId);
const pillCls = (ok) => ok === null ? "chain-pill" : ok ? "chain-pill" : "chain-pill offline";
const selectedScore = scores[selectedId]?.score;
const selectedColor = selectedId === "bob" ? "#00d97e" : selectedId === "alice" ? "#ff4444" : "#8b96a5";
return (
{selected && (
{selected.initials}
Active Agent
{selected.name}
merit {selectedScore !== undefined ? selectedScore.toFixed(4) : "…"}
)}
// Agents under evaluation
click a card to scope the tabs below
{AGENTS_META.map(a => (
setSelectedId(a.id)} />
))}
setTab("live")}>
⚡ Live Eval SWORD #1
setTab("tee")}>
🔐 TEE Attestation SWORD #2
setTab("wf")}>
⚡ KH Workflow SWORD #3
setTab("ai")}>
🤖 AI Analysis SWORD #4
setTab("zk")}>
🔏 ZK Proof SWORD #5
setTab("uniswap")}>
🔄 Uniswap Swap SWORD #6
{/* Force MeritGuard onto its own row so Sword #1–#6 stay together */}
setTab("mg")}
style={agentLoopStatus?.running ? { borderColor: "rgba(0,200,81,0.5)", color: "#00c851" } : {}}>
🤖 MeritGuard {agentLoopStatus?.running && ● LIVE }
setTab("swarm")}
style={tab === "swarm" ? { borderColor: "rgba(139,96,255,0.6)", color: "#8b60ff" } : {}}>
🕸 Swarm Consensus TRACK 2
{tab === "live" ?
:
tab === "tee" ?
:
tab === "wf" ?
:
tab === "ai" ?
:
tab === "zk" ?
:
tab === "uniswap" ?
:
tab === "swarm" ?
:
}
);
}
ReactDOM.createRoot(document.getElementById("root")).render( );