// server.mjs
import express from "express";
import {
init,
getKeyring,
getGuardianAddress,
inferenceCompute,
getApi,
scanForBlockEvent,
fetchAndDecodeExtrinsic,
} from "@palliora.org/chainsdk";
init({ pallioraWs: process.env.PALLIORA_WS ?? "wss://staging.manas-rpc.palliora.org" });
const keyring = await getKeyring();
const account = keyring.addFromUri("//Bob"); // dev-only, replace for real use
const app = express();
app.use(express.json());
app.post("/v1/chat/completions", async (req, res) => {
try {
const { model, messages } = req.body;
const guardians = (await getGuardianAddress()).slice(0, 3).map((g) => g.address);
const result = await inferenceCompute(
{
input: JSON.stringify({ model, messages, stream: false }),
guardians,
fee: { amount: 0.05, computeRate: 0.00002 },
deadline: 0,
},
account,
);
const api = await getApi();
const match = await scanForBlockEvent(
api,
{
predicate: async (block, _event, phase) => {
if (!block || !phase.isApplyExtrinsic) return false;
const ext = block.block.extrinsics[phase.asApplyExtrinsic.toNumber()];
if (ext?.method?.section?.toLowerCase() !== "compute" || ext?.method?.method?.toLowerCase() !== "result") {
return false;
}
const emitted = "0x" + Array.from(ext.method.args[0]).map((b) => ("0" + (b & 0xff).toString(16)).slice(-2)).join("");
return emitted === result.agreementId;
},
},
result.blockNumber + 1,
300,
);
const { decoded } = await fetchAndDecodeExtrinsic(match.blockNumber, match.extrinsicIndex ?? 0);
const answer = new TextDecoder().decode(
Buffer.from(decoded.method.args.contract.compute.input.Inline.data.slice(2), "hex"),
);
res.json({
id: result.agreementId,
object: "chat.completion",
model,
choices: [{ index: 0, message: { role: "assistant", content: answer }, finish_reason: "stop" }],
});
} catch (err) {
res.status(500).json({ error: err.message });
}
});
app.listen(3000, () => console.log("Listening on :3000"));