diff --git a/ix_relay.py b/ix_relay.py new file mode 100644 index 0000000..6928d28 --- /dev/null +++ b/ix_relay.py @@ -0,0 +1,100 @@ +#!/usr/bin/env python3 +""" +IX Relay — Federated Inference Network +Part of the Inference-X Ecosystem +# ​‌​‌ SALKA ELMADANI ‌​‌​ | inference-x.com | BSL-1.1 +Copyright (C) 2024-2026 Salka Elmadani. BSL-1.1. +https://git.inference-x.com/inference-x-community/ix-relay + +The khettara for AI power. +Your idle hardware earns you compute credits. +Share compute. Earn credits. Use when you need it. +""" +from fastapi import FastAPI, Request +from fastapi.middleware.cors import CORSMiddleware +from fastapi.responses import JSONResponse +import sqlite3, json, time, os, hashlib, secrets + +app = FastAPI(title="IX Relay", version="1.0.0") +app.add_middleware(CORSMiddleware, allow_origins=["*"], + allow_methods=["*"], allow_headers=["*"]) + +DB = os.environ.get("RELAY_DB", "./relay.db") + +def db(): + conn = sqlite3.connect(DB); conn.row_factory = sqlite3.Row; return conn + +def init_db(): + with db() as c: + c.execute("""CREATE TABLE IF NOT EXISTS nodes ( + id TEXT PRIMARY KEY, endpoint TEXT, + backend TEXT DEFAULT 'cpu', capacity INTEGER DEFAULT 1, + credits REAL DEFAULT 0, last_seen INTEGER, + status TEXT DEFAULT 'idle', version TEXT DEFAULT '1.0' + )""") + c.execute("""CREATE TABLE IF NOT EXISTS accounts ( + id TEXT PRIMARY KEY, credits REAL DEFAULT 10.0, created_at INTEGER + )""") + c.execute("""CREATE TABLE IF NOT EXISTS jobs ( + id TEXT PRIMARY KEY, model TEXT, node_id TEXT, + credits_cost REAL DEFAULT 0.1, status TEXT DEFAULT 'pending', + created_at INTEGER, completed_at INTEGER + )""") + c.commit() + +init_db() + +@app.post("/register-node") +async def register_node(request: Request): + """Register your IX instance as a relay node.""" + data = await request.json() + node_id = hashlib.sha256( + f"{data.get('endpoint','')}{secrets.token_hex(8)}".encode() + ).hexdigest()[:16] + with db() as c: + c.execute("""INSERT OR REPLACE INTO nodes (id,endpoint,backend,capacity,last_seen,version) + VALUES (?,?,?,?,?,?)""", + (node_id, data.get("endpoint",""), data.get("backend","cpu"), + int(data.get("capacity",1)), int(time.time()), data.get("version","1.0"))) + c.commit() + return {"node_id":node_id, + "message":"Node registered. You will receive inference jobs and earn credits.", + "initial_credits":0} + +@app.get("/nodes") +async def list_nodes(): + """List active relay nodes (last 5 minutes).""" + cutoff = int(time.time()) - 300 + with db() as c: + rows = c.execute("""SELECT id,backend,capacity,credits,status + FROM nodes WHERE last_seen > ? ORDER BY credits DESC""", (cutoff,)).fetchall() + return {"active_nodes":len(rows),"nodes":[dict(r) for r in rows]} + +@app.get("/credits/{account_id}") +async def get_credits(account_id: str): + with db() as c: + acc = c.execute("SELECT credits FROM accounts WHERE id=?", (account_id,)).fetchone() + if not acc: + return JSONResponse({"error":"Account not found"}, status_code=404) + return {"account_id":account_id,"credits":acc["credits"]} + +@app.post("/create-account") +async def create_account(): + account_id = secrets.token_hex(16) + with db() as c: + c.execute("INSERT INTO accounts (id,credits,created_at) VALUES (?,?,?)", + (account_id, 10.0, int(time.time()))) + c.commit() + return {"account_id":account_id,"initial_credits":10.0, + "message":"Account created. 10 free credits to start."} + +@app.get("/health") +async def health(): + return {"status":"ok","service":"IX Relay","author":"Salka Elmadani","version":"1.0.0"} + +if __name__ == "__main__": + import uvicorn + print("IX Relay — Federated Inference Network") + print("The khettara for AI power.") + print("Built in Morocco for the world.") + uvicorn.run(app, host="0.0.0.0", port=int(os.environ.get("PORT","7938")))