Spaces:
Paused
Paused
Update app.py
Browse files
app.py
CHANGED
|
@@ -20,7 +20,7 @@ for module_name, pip_name in REQUIRED_PACKAGES.items():
|
|
| 20 |
print(f"✅ {pip_name} установлен!")
|
| 21 |
|
| 22 |
# ============================================
|
| 23 |
-
# 👑 TOMIRIS SPACE 23 v2.
|
| 24 |
# ============================================
|
| 25 |
import os, time, json, logging, asyncio
|
| 26 |
from typing import Dict, Any, List, Optional
|
|
@@ -37,7 +37,10 @@ logger = logging.getLogger("Space23_AnomalySentinel")
|
|
| 37 |
TRACKED_SYMBOLS = ["ETH/USD", "SOL/USD"]
|
| 38 |
HUB_URL = os.getenv("SPACE17_URL", "https://tomiris-ai-name5-5.hf.space")
|
| 39 |
ETHERSCAN_KEY = os.getenv("ETHERSCAN_KEY", "TZGVD58I2HZ9G4BBD548KX11E4JFH4J5GX")
|
| 40 |
-
SOLSCAN_KEY = os.getenv("SOLSCAN_KEY", "")
|
|
|
|
|
|
|
|
|
|
| 41 |
|
| 42 |
ETH_WHALE_WALLETS = [
|
| 43 |
"0x28C6c06298d514089D2Bd15f6A8a38c5d8d3a6B2",
|
|
@@ -89,7 +92,7 @@ if os.path.exists(ACTIVE_HISTORY_FILE):
|
|
| 89 |
else:
|
| 90 |
active_history = {}
|
| 91 |
|
| 92 |
-
# ================= ЗАГРУЗКА ДАННЫХ
|
| 93 |
async def fetch_gas_oracle() -> Dict[str, Any]:
|
| 94 |
if breaker_open("etherscan"):
|
| 95 |
return {'avg_gas': 45, 'gas_level': 'NORMAL', 'is_anomaly': False}
|
|
@@ -225,7 +228,7 @@ async def detect_anomalies(symbol: str) -> Dict[str, Any]:
|
|
| 225 |
elif score >= 30:
|
| 226 |
level, direction = "ELEVATED", "WAIT"
|
| 227 |
else:
|
| 228 |
-
level, direction = "NORMAL", "
|
| 229 |
|
| 230 |
record = {
|
| 231 |
"timestamp": datetime.now(timezone.utc).isoformat(),
|
|
@@ -238,7 +241,6 @@ async def detect_anomalies(symbol: str) -> Dict[str, Any]:
|
|
| 238 |
with open(HISTORY_FILE, 'w') as f:
|
| 239 |
json.dump(list(ANOMALY_HISTORY), f)
|
| 240 |
|
| 241 |
-
# Отправляем в Space 17 (если доступен)
|
| 242 |
try:
|
| 243 |
await http_client.post(f"{HUB_URL}/anomaly", json=record, timeout=5)
|
| 244 |
except:
|
|
@@ -260,14 +262,17 @@ async def detect_anomalies(symbol: str) -> Dict[str, Any]:
|
|
| 260 |
# ================= ОТПРАВКА В HUB =================
|
| 261 |
async def send_signal_to_hub(symbol: str, direction: str, confidence: float):
|
| 262 |
try:
|
| 263 |
-
await http_client.post(f"{HUB_URL}/signal", json={
|
| 264 |
"space": "space_23_anomaly",
|
| 265 |
"symbol": symbol,
|
| 266 |
"direction": direction,
|
| 267 |
"confidence": confidence,
|
| 268 |
"raw": json.dumps({"source": "space_23_anomaly"})
|
| 269 |
-
})
|
| 270 |
-
|
|
|
|
|
|
|
|
|
|
| 271 |
except Exception as e:
|
| 272 |
logger.error(f"Ошибка отправки в Hub: {e}")
|
| 273 |
|
|
@@ -280,7 +285,6 @@ async def get_anomaly_signal(symbol: str = "ETH/USD") -> Dict[str, Any]:
|
|
| 280 |
direction = analysis['signal']
|
| 281 |
confidence = round(analysis['anomaly_score'] / 100, 4) if analysis['anomaly_score'] > 0 else 0.0
|
| 282 |
|
| 283 |
-
# Отправка в Hub
|
| 284 |
await send_signal_to_hub(symbol, direction, confidence)
|
| 285 |
|
| 286 |
result = {
|
|
@@ -298,12 +302,27 @@ async def get_anomaly_signal(symbol: str = "ETH/USD") -> Dict[str, Any]:
|
|
| 298 |
logger.info(f"🔍 Anomaly {symbol}: {analysis['anomaly_level']} | Score={analysis['anomaly_score']}")
|
| 299 |
return result
|
| 300 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 301 |
# ================= FASTAPI =================
|
| 302 |
-
app = FastAPI(title="Tomiris Space 23 v2.
|
| 303 |
|
| 304 |
@app.on_event("startup")
|
| 305 |
async def startup():
|
| 306 |
-
|
|
|
|
| 307 |
|
| 308 |
@app.on_event("shutdown")
|
| 309 |
async def shutdown():
|
|
@@ -313,10 +332,11 @@ async def shutdown():
|
|
| 313 |
async def health():
|
| 314 |
return {
|
| 315 |
"status": "operational",
|
| 316 |
-
"version": "2.
|
|
|
|
|
|
|
| 317 |
"symbols": TRACKED_SYMBOLS,
|
| 318 |
-
"anomaly_history": len(ANOMALY_HISTORY)
|
| 319 |
-
"hub_connected": True
|
| 320 |
}
|
| 321 |
|
| 322 |
@app.get("/consilium")
|
|
@@ -353,8 +373,16 @@ async def active(chain: str = "ethereum"):
|
|
| 353 |
async def history(limit: int = 50):
|
| 354 |
return list(ANOMALY_HISTORY)[-limit:]
|
| 355 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 356 |
if __name__ == "__main__":
|
| 357 |
import uvicorn
|
| 358 |
uvicorn.run(app, host="0.0.0.0", port=7860)
|
| 359 |
|
| 360 |
-
print("🚀 SPACE 23 v2.
|
|
|
|
| 20 |
print(f"✅ {pip_name} установлен!")
|
| 21 |
|
| 22 |
# ============================================
|
| 23 |
+
# 👑 TOMIRIS SPACE 23 v2.2 — ON-CHAIN ANOMALY SENTINEL (АВТО-ОТПРАВКА)
|
| 24 |
# ============================================
|
| 25 |
import os, time, json, logging, asyncio
|
| 26 |
from typing import Dict, Any, List, Optional
|
|
|
|
| 37 |
TRACKED_SYMBOLS = ["ETH/USD", "SOL/USD"]
|
| 38 |
HUB_URL = os.getenv("SPACE17_URL", "https://tomiris-ai-name5-5.hf.space")
|
| 39 |
ETHERSCAN_KEY = os.getenv("ETHERSCAN_KEY", "TZGVD58I2HZ9G4BBD548KX11E4JFH4J5GX")
|
| 40 |
+
SOLSCAN_KEY = os.getenv("SOLSCAN_KEY", "")
|
| 41 |
+
|
| 42 |
+
# Интервал авто-отправки
|
| 43 |
+
AUTO_SEND_INTERVAL = int(os.getenv("AUTO_SEND_INTERVAL", "300"))
|
| 44 |
|
| 45 |
ETH_WHALE_WALLETS = [
|
| 46 |
"0x28C6c06298d514089D2Bd15f6A8a38c5d8d3a6B2",
|
|
|
|
| 92 |
else:
|
| 93 |
active_history = {}
|
| 94 |
|
| 95 |
+
# ================= ЗАГРУЗКА ДАННЫХ =================
|
| 96 |
async def fetch_gas_oracle() -> Dict[str, Any]:
|
| 97 |
if breaker_open("etherscan"):
|
| 98 |
return {'avg_gas': 45, 'gas_level': 'NORMAL', 'is_anomaly': False}
|
|
|
|
| 228 |
elif score >= 30:
|
| 229 |
level, direction = "ELEVATED", "WAIT"
|
| 230 |
else:
|
| 231 |
+
level, direction = "NORMAL", "LONG"
|
| 232 |
|
| 233 |
record = {
|
| 234 |
"timestamp": datetime.now(timezone.utc).isoformat(),
|
|
|
|
| 241 |
with open(HISTORY_FILE, 'w') as f:
|
| 242 |
json.dump(list(ANOMALY_HISTORY), f)
|
| 243 |
|
|
|
|
| 244 |
try:
|
| 245 |
await http_client.post(f"{HUB_URL}/anomaly", json=record, timeout=5)
|
| 246 |
except:
|
|
|
|
| 262 |
# ================= ОТПРАВКА В HUB =================
|
| 263 |
async def send_signal_to_hub(symbol: str, direction: str, confidence: float):
|
| 264 |
try:
|
| 265 |
+
resp = await http_client.post(f"{HUB_URL}/signal", json={
|
| 266 |
"space": "space_23_anomaly",
|
| 267 |
"symbol": symbol,
|
| 268 |
"direction": direction,
|
| 269 |
"confidence": confidence,
|
| 270 |
"raw": json.dumps({"source": "space_23_anomaly"})
|
| 271 |
+
}, timeout=10)
|
| 272 |
+
if resp.status_code == 200:
|
| 273 |
+
logger.info(f"📤 {symbol}: {direction} conf={confidence:.3f} отправлен в Hub")
|
| 274 |
+
else:
|
| 275 |
+
logger.warning(f"Hub вернул {resp.status_code}")
|
| 276 |
except Exception as e:
|
| 277 |
logger.error(f"Ошибка отправки в Hub: {e}")
|
| 278 |
|
|
|
|
| 285 |
direction = analysis['signal']
|
| 286 |
confidence = round(analysis['anomaly_score'] / 100, 4) if analysis['anomaly_score'] > 0 else 0.0
|
| 287 |
|
|
|
|
| 288 |
await send_signal_to_hub(symbol, direction, confidence)
|
| 289 |
|
| 290 |
result = {
|
|
|
|
| 302 |
logger.info(f"🔍 Anomaly {symbol}: {analysis['anomaly_level']} | Score={analysis['anomaly_score']}")
|
| 303 |
return result
|
| 304 |
|
| 305 |
+
# ================= АВТО-ОТПРАВКА =================
|
| 306 |
+
async def auto_send_loop():
|
| 307 |
+
logger.info(f"🔄 Авто-отправка Anomaly Sentinel запущена (интервал {AUTO_SEND_INTERVAL}с)")
|
| 308 |
+
await asyncio.sleep(30)
|
| 309 |
+
while True:
|
| 310 |
+
try:
|
| 311 |
+
for symbol in TRACKED_SYMBOLS:
|
| 312 |
+
await get_anomaly_signal(symbol)
|
| 313 |
+
await asyncio.sleep(2)
|
| 314 |
+
logger.info("✅ Anomaly Sentinel авто-отправка завершена")
|
| 315 |
+
except Exception as e:
|
| 316 |
+
logger.error(f"Ошибка авто-отправки: {e}")
|
| 317 |
+
await asyncio.sleep(AUTO_SEND_INTERVAL)
|
| 318 |
+
|
| 319 |
# ================= FASTAPI =================
|
| 320 |
+
app = FastAPI(title="Tomiris Space 23 v2.2 — On-Chain Anomaly Sentinel (Auto-Hub)")
|
| 321 |
|
| 322 |
@app.on_event("startup")
|
| 323 |
async def startup():
|
| 324 |
+
asyncio.create_task(auto_send_loop())
|
| 325 |
+
logger.info("🚀 Space 23 v2.2 запущен с авто-отправкой в Hub")
|
| 326 |
|
| 327 |
@app.on_event("shutdown")
|
| 328 |
async def shutdown():
|
|
|
|
| 332 |
async def health():
|
| 333 |
return {
|
| 334 |
"status": "operational",
|
| 335 |
+
"version": "2.2",
|
| 336 |
+
"hub_url": HUB_URL,
|
| 337 |
+
"auto_send_interval": AUTO_SEND_INTERVAL,
|
| 338 |
"symbols": TRACKED_SYMBOLS,
|
| 339 |
+
"anomaly_history": len(ANOMALY_HISTORY)
|
|
|
|
| 340 |
}
|
| 341 |
|
| 342 |
@app.get("/consilium")
|
|
|
|
| 373 |
async def history(limit: int = 50):
|
| 374 |
return list(ANOMALY_HISTORY)[-limit:]
|
| 375 |
|
| 376 |
+
@app.get("/send_now")
|
| 377 |
+
async def send_now():
|
| 378 |
+
results = {}
|
| 379 |
+
for symbol in TRACKED_SYMBOLS:
|
| 380 |
+
analysis = await get_anomaly_signal(symbol)
|
| 381 |
+
results[symbol] = analysis.get("signal", {}).get("direction", "WAIT")
|
| 382 |
+
return {"status": "sent", "results": results}
|
| 383 |
+
|
| 384 |
if __name__ == "__main__":
|
| 385 |
import uvicorn
|
| 386 |
uvicorn.run(app, host="0.0.0.0", port=7860)
|
| 387 |
|
| 388 |
+
print("🚀 SPACE 23 v2.2 — ON-CHAIN ANOMALY SENTINEL (АВТО-ОТПРАВКА) ЗАПУЩЕН!")
|