Really-amin commited on
Commit
89c342d
·
verified ·
1 Parent(s): 3e2e46d

Upload 7 files

Browse files
Files changed (7) hide show
  1. .dockerignore +36 -11
  2. Dockerfile +34 -25
  3. README.md +30 -21
  4. SUMMARY.md +109 -0
  5. app.py +60 -604
  6. requirements.txt +3 -12
  7. راهنمای_نصب.md +109 -0
.dockerignore CHANGED
@@ -1,16 +1,41 @@
 
 
 
 
 
 
 
 
1
  __pycache__/
2
- *.py[cod]
3
- *$py.class
 
 
4
  *.so
 
 
5
  .env
6
- .venv
7
- env/
8
- venv/
9
- ENV/
10
- .DS_Store
11
- .git
 
 
 
 
 
12
  .gitignore
 
 
 
 
 
 
13
  *.log
14
- *.sqlite
15
- .idea/
16
- .vscode/
 
 
 
1
+ # Node modules
2
+ node_modules/
3
+ frontend/node_modules/
4
+
5
+ # Build artifacts
6
+ frontend/dist/
7
+
8
+ # Python cache
9
  __pycache__/
10
+ *.pyc
11
+ *.pyo
12
+ *.pyd
13
+ .Python
14
  *.so
15
+
16
+ # Environment files
17
  .env
18
+ .env.local
19
+ .env.*.local
20
+
21
+ # IDE
22
+ .vscode/
23
+ .idea/
24
+ *.swp
25
+ *.swo
26
+
27
+ # Git
28
+ .git/
29
  .gitignore
30
+
31
+ # OS
32
+ .DS_Store
33
+ Thumbs.db
34
+
35
+ # Logs
36
  *.log
37
+ logs/
38
+
39
+ # Testing
40
+ coverage/
41
+ .pytest_cache/
Dockerfile CHANGED
@@ -1,38 +1,47 @@
1
- FROM python:3.9-slim
 
2
 
3
- WORKDIR /code
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4
 
5
  # Install system dependencies
6
- RUN apt-get update && \
7
- apt-get install -y --no-install-recommends \
8
- build-essential \
9
- curl \
10
- git \
11
- && apt-get clean \
12
  && rm -rf /var/lib/apt/lists/*
13
 
14
- # Create necessary directories
15
- RUN mkdir -p /code/data /code/logs
16
-
17
- # Copy requirements first to leverage Docker cache
18
- COPY requirements.txt .
19
 
20
  # Install Python dependencies
21
- RUN pip install --no-cache-dir --upgrade pip && \
22
- pip install --no-cache-dir -r requirements.txt
23
-
24
- # Copy application code
25
- COPY . .
26
 
27
- # Ensure directories have correct permissions
28
- RUN chmod -R 755 /code/data /code/logs
29
 
30
- # Set environment variables
31
- ENV PYTHONPATH=/code
32
- ENV PORT=7860
33
 
34
- # Expose the port
35
  EXPOSE 7860
36
 
 
 
 
37
  # Run the application
38
- CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "7860"]
 
1
+ # Stage 1: Build Frontend
2
+ FROM node:18-slim AS frontend-builder
3
 
4
+ WORKDIR /app/frontend
5
+
6
+ # Copy frontend package files
7
+ COPY frontend/package*.json ./
8
+
9
+ # Install dependencies
10
+ RUN npm install
11
+
12
+ # Copy frontend source
13
+ COPY frontend/ ./
14
+
15
+ # Build frontend
16
+ RUN npm run build
17
+
18
+ # Stage 2: Setup Backend and Serve
19
+ FROM python:3.10-slim
20
+
21
+ WORKDIR /app
22
 
23
  # Install system dependencies
24
+ RUN apt-get update && apt-get install -y \
25
+ gcc \
 
 
 
 
26
  && rm -rf /var/lib/apt/lists/*
27
 
28
+ # Copy backend requirements
29
+ COPY backend/requirements.txt ./
 
 
 
30
 
31
  # Install Python dependencies
32
+ RUN pip install --no-cache-dir -r requirements.txt
 
 
 
 
33
 
34
+ # Copy backend code
35
+ COPY backend/ ./backend/
36
 
37
+ # Copy built frontend from previous stage
38
+ COPY --from=frontend-builder /app/frontend/dist ./frontend/dist
 
39
 
40
+ # Expose Hugging Face Space port
41
  EXPOSE 7860
42
 
43
+ # Set environment variables
44
+ ENV PYTHONUNBUFFERED=1
45
+
46
  # Run the application
47
+ CMD ["uvicorn", "backend.app:app", "--host", "0.0.0.0", "--port", "7860"]
README.md CHANGED
@@ -1,42 +1,51 @@
1
  ---
2
- title: Cryptocurrency Data API
3
  emoji: 📈
4
  colorFrom: blue
5
  colorTo: green
6
  sdk: docker
7
- app_port: 7860
8
  pinned: false
 
9
  ---
10
 
11
- # Cryptocurrency Data Source API
12
 
13
- This API provides cryptocurrency market data from various exchanges using the CCXT library.
14
 
15
  ## Features
16
 
17
- - Access to multiple cryptocurrency exchanges
18
- - OHLCV (Open, High, Low, Close, Volume) data
19
- - Easy integration with trading systems
 
 
20
 
21
  ## API Endpoints
22
 
23
- - `GET /` - API status and version
24
- - `GET /exchanges` - List all available exchanges
25
- - `GET /markets/{exchange_id}` - Get markets for a specific exchange
26
- - `GET /ohlcv/{exchange_id}/{symbol}` - Get OHLCV data for a specific market
27
- - `GET /health` - Health check endpoint
28
 
29
- ## Usage
30
 
31
- Once deployed, visit the `/docs` endpoint to see the interactive API documentation.
32
 
33
- ## Development
 
 
 
 
 
34
 
35
- Built with:
36
- - FastAPI - Modern, fast web framework
37
- - CCXT - Cryptocurrency exchange trading library
38
- - Docker - Containerization
 
 
39
 
40
- ## Deployment on Hugging Face Spaces
41
 
42
- This project is designed to be deployed as a Docker space on Hugging Face.
 
1
  ---
2
+ title: Datasourceforcryptocurrency
3
  emoji: 📈
4
  colorFrom: blue
5
  colorTo: green
6
  sdk: docker
 
7
  pinned: false
8
+ app_port: 7860
9
  ---
10
 
11
+ # Crypto Data Source & Trading System
12
 
13
+ A comprehensive cryptocurrency data source and trading platform built with FastAPI backend and React frontend.
14
 
15
  ## Features
16
 
17
+ - Real-time cryptocurrency market data
18
+ - Technical analysis indicators
19
+ - Trading signals
20
+ - Portfolio management
21
+ - Multi-exchange support via CCXT
22
 
23
  ## API Endpoints
24
 
25
+ - `GET /api/health` - Health check
26
+ - `GET /api/markets` - List available markets
27
+ - `GET /api/ticker/{symbol}` - Get ticker data for a symbol
28
+
29
+ ## Documentation
30
 
31
+ Visit `/docs` for interactive API documentation.
32
 
33
+ ## Local Development
34
 
35
+ ### Backend
36
+ ```bash
37
+ cd backend
38
+ pip install -r requirements.txt
39
+ uvicorn app:app --reload --port 8000
40
+ ```
41
 
42
+ ### Frontend
43
+ ```bash
44
+ cd frontend
45
+ npm install
46
+ npm run dev
47
+ ```
48
 
49
+ ## Deployment
50
 
51
+ This Space automatically builds and deploys on push to the main branch.
SUMMARY.md ADDED
@@ -0,0 +1,109 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # 📦 فایل‌های دانلود شده برای Hugging Face Space
2
+
3
+ ## ✅ فایل‌هایی که دانلود کردید:
4
+
5
+ ### 1️⃣ `Dockerfile`
6
+ **کاربرد**: تنظیمات Docker برای build کردن و اجرای پروژه
7
+ - Stage 1: Build کردن Frontend (React/Vite)
8
+ - Stage 2: نصب Backend (FastAPI) + کپی کردن Frontend بیلد شده
9
+ **مکان**: ریشه پروژه (root)
10
+
11
+ ---
12
+
13
+ ### 2️⃣ `app.py`
14
+ **کاربرد**: Backend اصلی FastAPI
15
+ **ویژگی‌ها**:
16
+ - ✅ Serve کردن API endpoints (مثل `/api/health`, `/api/markets`)
17
+ - ✅ Serve کردن Frontend static files
18
+ - ✅ CORS middleware برای دسترسی از همه جا
19
+ - ✅ Integration با CCXT برای دیتای کریپتو
20
+ **مکان**: `backend/app.py`
21
+
22
+ ---
23
+
24
+ ### 3️⃣ `requirements.txt`
25
+ **کاربرد**: لیست کتابخانه‌های Python
26
+ **شامل**:
27
+ - fastapi: فریمورک وب
28
+ - uvicorn: ASGI server
29
+ - ccxt: دسترسی به exchange ها
30
+ - و سایر dependencies
31
+ **مکان**: `backend/requirements.txt`
32
+
33
+ ---
34
+
35
+ ### 4️⃣ `README.md`
36
+ **کاربرد**: توضیحات و تنظیمات Hugging Face Space
37
+ **شامل**:
38
+ - Metadata برای Space (emoji, SDK, port)
39
+ - مستندات پروژه
40
+ - راهنمای استفاده
41
+ **مکان**: ریشه پروژه (root)
42
+
43
+ ---
44
+
45
+ ### 5️⃣ `.dockerignore`
46
+ **کاربرد**: فایل‌هایی که نباید در Docker build کپی بشن
47
+ **شامل**: node_modules, cache files, logs, etc.
48
+ **مکان**: ریشه پروژه (root)
49
+
50
+ ---
51
+
52
+ ### 6️⃣ `راهنمای_نصب.md`
53
+ **کاربرد**: راهنمای کامل فارسی برای بارگذاری
54
+ **شامل**:
55
+ - ساختار پوشه‌ها
56
+ - مراحل بارگذاری
57
+ - عیب‌یابی
58
+ **مکان**: فقط برای مطالعه (نیاز به آپلود نیست)
59
+
60
+ ---
61
+
62
+ ## 🎯 چطور استفاده کنم؟
63
+
64
+ ### گام 1: دانلود
65
+ همه فایل‌ها رو دانلود کن از پایین صفحه
66
+
67
+ ### گام 2: ساختار
68
+ پوشه‌های پروژه رو مطابق این ساختار بچین:
69
+ ```
70
+ Datasourceforcryptocurrency/
71
+ ├── Dockerfile
72
+ ├── README.md
73
+ ├── .dockerignore
74
+ ├── backend/
75
+ │ ├── app.py
76
+ │ └── requirements.txt
77
+ └── frontend/
78
+ └── ... (فایل‌های موجود شما)
79
+ ```
80
+
81
+ ### گام 3: آپلود
82
+ یا از Web UI Hugging Face آپلود کن یا با Git push کن
83
+
84
+ ### گام 4: منتظر بمون
85
+ Space خودش rebuild می‌شه و بعدش UI کار می‌کنه!
86
+
87
+ ---
88
+
89
+ ## ⚠️ نکات مهم:
90
+
91
+ 1. **پوشه backend**: حتماً بساز و فایل‌ها رو داخلش بذار
92
+ 2. **Frontend باید داشته باشه**: `package.json`, `vite.config.js`, `src/`
93
+ 3. **Port 7860**: حتماً این port رو استفاده کن (الزامی Hugging Face)
94
+ 4. **بعد از push**: 5-10 دقیقه صبر کن تا rebuild بشه
95
+
96
+ ---
97
+
98
+ ## 🆘 مشکل داری؟
99
+
100
+ اگر بعد از آپلود باز هم JSON می‌بینی:
101
+ 1. لاگ Build رو چک کن
102
+ 2. مطمئن شو frontend/dist ساخته شده
103
+ 3. مطمئن شو به root URL دسترسی داری (`/`) نه (`/api`)
104
+
105
+ برای کمک بیشتر، لاگ‌ها یا screenshot بفرست! 💪
106
+
107
+ ---
108
+
109
+ **آماده‌س! همه فایل‌ها پایین صفحه‌ان، دانلودشون کن و آپلود کن! 🚀**
app.py CHANGED
@@ -1,629 +1,85 @@
1
- """
2
- Crypto API Monitoring System - Main Application
3
- Production-ready FastAPI application with comprehensive monitoring and WebSocket support
4
- """
5
-
6
- import asyncio
7
- import uvicorn
8
- from datetime import datetime
9
- from contextlib import asynccontextmanager
10
-
11
- from fastapi import FastAPI, Request
12
- from fastapi.middleware.cors import CORSMiddleware
13
- from fastapi.responses import JSONResponse, HTMLResponse, FileResponse
14
  from fastapi.staticfiles import StaticFiles
 
 
 
 
 
 
15
 
16
- # Import API modules
17
- from api.endpoints import router as api_router
18
- from api.websocket import router as websocket_router, manager as ws_manager
19
- from api.pool_endpoints import router as pool_router
20
- from api.data_endpoints import router as data_router
21
-
22
- # Import new WebSocket service routers
23
- from api.ws_unified_router import router as ws_unified_router, start_all_websocket_streams
24
- from api.ws_data_services import router as ws_data_router
25
- from api.ws_monitoring_services import router as ws_monitoring_router
26
- from api.ws_integration_services import router as ws_integration_router
27
-
28
- # Import monitoring and database modules
29
- from monitoring.scheduler import task_scheduler
30
- from monitoring.rate_limiter import rate_limiter
31
- from database.db_manager import db_manager
32
- from config import config
33
- from utils.logger import setup_logger
34
-
35
- # Setup logger
36
- logger = setup_logger("main", level="INFO")
37
-
38
- # Import HF router (optional, graceful fallback)
39
- try:
40
- from backend.routers import hf_connect
41
- HF_ROUTER_AVAILABLE = True
42
- except Exception as e:
43
- logger.warning(f"HF router not available: {e}")
44
- HF_ROUTER_AVAILABLE = False
45
-
46
-
47
- # ============================================================================
48
- # Lifespan Context Manager for Startup/Shutdown Events
49
- # ============================================================================
50
-
51
- @asynccontextmanager
52
- async def lifespan(app: FastAPI):
53
- """
54
- Lifespan context manager for application startup and shutdown
55
-
56
- Handles:
57
- - Database initialization
58
- - Scheduler startup
59
- - Rate limiter configuration
60
- - WebSocket background tasks
61
- - Graceful shutdown
62
- """
63
- logger.info("=" * 80)
64
- logger.info("Starting Crypto API Monitoring System")
65
- logger.info("=" * 80)
66
-
67
- try:
68
- # ===== STARTUP SEQUENCE =====
69
-
70
- # 1. Initialize database
71
- logger.info("Initializing database...")
72
- db_manager.init_database()
73
-
74
- # Verify database health
75
- db_health = db_manager.health_check()
76
- if db_health.get('status') == 'healthy':
77
- logger.info(f"Database initialized successfully: {db_health.get('database_path')}")
78
- else:
79
- logger.error(f"Database health check failed: {db_health}")
80
-
81
- # 2. Configure rate limiters for all providers
82
- logger.info("Configuring rate limiters...")
83
- providers = config.get_all_providers()
84
-
85
- for provider in providers:
86
- if provider.rate_limit_type and provider.rate_limit_value:
87
- rate_limiter.configure_limit(
88
- provider=provider.name,
89
- limit_type=provider.rate_limit_type,
90
- limit_value=provider.rate_limit_value
91
- )
92
- logger.info(
93
- f"Configured rate limit for {provider.name}: "
94
- f"{provider.rate_limit_value} {provider.rate_limit_type}"
95
- )
96
-
97
- logger.info(f"Configured rate limiters for {len(providers)} providers")
98
-
99
- # 3. Populate database with provider configurations
100
- logger.info("Populating database with provider configurations...")
101
-
102
- for provider in providers:
103
- # Check if provider already exists in database
104
- db_provider = db_manager.get_provider(name=provider.name)
105
-
106
- if not db_provider:
107
- # Create new provider in database
108
- db_provider = db_manager.create_provider(
109
- name=provider.name,
110
- category=provider.category,
111
- endpoint_url=provider.endpoint_url,
112
- requires_key=provider.requires_key,
113
- api_key_masked=provider._mask_key() if provider.api_key else None,
114
- rate_limit_type=provider.rate_limit_type,
115
- rate_limit_value=provider.rate_limit_value,
116
- timeout_ms=provider.timeout_ms,
117
- priority_tier=provider.priority_tier
118
- )
119
-
120
- if db_provider:
121
- logger.info(f"Added provider to database: {provider.name}")
122
-
123
- # Create schedule configuration for the provider
124
- # Set interval based on category
125
- interval_map = {
126
- 'market_data': 'every_1_min',
127
- 'blockchain_explorers': 'every_5_min',
128
- 'news': 'every_10_min',
129
- 'sentiment': 'every_15_min',
130
- 'onchain_analytics': 'every_5_min',
131
- 'rpc_nodes': 'every_5_min',
132
- 'cors_proxies': 'every_30_min'
133
- }
134
-
135
- schedule_interval = interval_map.get(provider.category, 'every_5_min')
136
-
137
- schedule_config = db_manager.create_schedule_config(
138
- provider_id=db_provider.id,
139
- schedule_interval=schedule_interval,
140
- enabled=True
141
- )
142
-
143
- if schedule_config:
144
- logger.info(
145
- f"Created schedule config for {provider.name}: {schedule_interval}"
146
- )
147
-
148
- # 4. Start HF registry background refresh (if available)
149
- if HF_ROUTER_AVAILABLE:
150
- try:
151
- from backend.services.hf_registry import periodic_refresh
152
- logger.info("Starting HF registry background refresh...")
153
- asyncio.create_task(periodic_refresh())
154
- logger.info("HF registry background refresh started")
155
- except Exception as e:
156
- logger.warning(f"Could not start HF background refresh: {e}")
157
-
158
- # 5. Start WebSocket background tasks
159
- logger.info("Starting WebSocket background tasks...")
160
- await ws_manager.start_background_tasks()
161
- logger.info("WebSocket background tasks started")
162
-
163
- # 5.1 Start new WebSocket service streams
164
- logger.info("Starting WebSocket service streams...")
165
- asyncio.create_task(start_all_websocket_streams())
166
- logger.info("WebSocket service streams started")
167
-
168
- # 6. Start task scheduler
169
- logger.info("Starting task scheduler...")
170
- task_scheduler.start()
171
- logger.info("Task scheduler started successfully")
172
-
173
- # 7. Start WebSocket data broadcaster
174
- logger.info("Starting WebSocket data broadcaster...")
175
- try:
176
- from api.ws_data_broadcaster import broadcaster
177
- asyncio.create_task(broadcaster.start_broadcasting())
178
- logger.info("WebSocket data broadcaster started")
179
- except Exception as e:
180
- logger.warning(f"Could not start WebSocket data broadcaster: {e}")
181
-
182
- # Log startup summary
183
- logger.info("=" * 80)
184
- logger.info("Crypto API Monitoring System started successfully")
185
- logger.info(f"Total providers configured: {len(providers)}")
186
- logger.info(f"Database: {db_health.get('database_path')}")
187
- logger.info(f"Scheduler running: {task_scheduler.is_running()}")
188
- logger.info(f"WebSocket manager active: {ws_manager._is_running}")
189
- logger.info("=" * 80)
190
-
191
- yield # Application runs here
192
-
193
- # ===== SHUTDOWN SEQUENCE =====
194
-
195
- logger.info("=" * 80)
196
- logger.info("Shutting down Crypto API Monitoring System...")
197
- logger.info("=" * 80)
198
-
199
- # 1. Stop WebSocket data broadcaster
200
- logger.info("Stopping WebSocket data broadcaster...")
201
- try:
202
- from api.ws_data_broadcaster import broadcaster
203
- await broadcaster.stop_broadcasting()
204
- logger.info("WebSocket data broadcaster stopped")
205
- except Exception as e:
206
- logger.warning(f"Error stopping WebSocket data broadcaster: {e}")
207
-
208
- # 2. Stop task scheduler
209
- logger.info("Stopping task scheduler...")
210
- task_scheduler.stop()
211
- logger.info("Task scheduler stopped")
212
-
213
- # 3. Stop WebSocket background tasks
214
- logger.info("Stopping WebSocket background tasks...")
215
- await ws_manager.stop_background_tasks()
216
- logger.info("WebSocket background tasks stopped")
217
-
218
- # 4. Close all WebSocket connections
219
- logger.info("Closing WebSocket connections...")
220
- await ws_manager.close_all_connections()
221
- logger.info("WebSocket connections closed")
222
-
223
- logger.info("=" * 80)
224
- logger.info("Crypto API Monitoring System shut down successfully")
225
- logger.info("=" * 80)
226
-
227
- except Exception as e:
228
- logger.error(f"Error during application lifecycle: {e}", exc_info=True)
229
- raise
230
-
231
-
232
- # ============================================================================
233
- # Create FastAPI Application
234
- # ============================================================================
235
-
236
- app = FastAPI(
237
- title="Crypto API Monitoring System",
238
- description="""
239
- Comprehensive cryptocurrency API monitoring system with real-time WebSocket updates.
240
-
241
- Features:
242
- - Multi-provider API monitoring
243
- - Real-time WebSocket streaming for all services
244
- - Data collection APIs: Market data, News, Sentiment, Whale tracking, RPC nodes, On-chain analytics
245
- - Monitoring APIs: Health checks, Pool management, Scheduler status
246
- - Integration APIs: HuggingFace AI/ML, Persistence services
247
- - Subscription-based message routing
248
- - Rate limit tracking
249
- - Automated health checks
250
- - Scheduled data collection
251
- - Failure detection and alerts
252
- - Historical analytics
253
-
254
- WebSocket Endpoints:
255
- - Master: /ws, /ws/master, /ws/all
256
- - Data Collection: /ws/data, /ws/market_data, /ws/news, /ws/sentiment, /ws/whale_tracking
257
- - Monitoring: /ws/monitoring, /ws/health, /ws/pool_status, /ws/scheduler_status
258
- - Integration: /ws/integration, /ws/huggingface, /ws/ai, /ws/persistence
259
- - Legacy: /ws/live
260
- """,
261
- version="2.0.0",
262
- lifespan=lifespan,
263
- docs_url="/docs",
264
- redoc_url="/redoc"
265
- )
266
-
267
-
268
- # ============================================================================
269
- # CORS Middleware Configuration
270
- # ============================================================================
271
 
 
272
  app.add_middleware(
273
  CORSMiddleware,
274
- allow_origins=["*"], # In production, specify allowed origins
275
  allow_credentials=True,
276
  allow_methods=["*"],
277
  allow_headers=["*"],
278
  )
279
 
280
-
281
- # ============================================================================
282
- # Exception Handlers
283
- # ============================================================================
284
-
285
- @app.exception_handler(Exception)
286
- async def global_exception_handler(request: Request, exc: Exception):
287
- """
288
- Global exception handler for unhandled exceptions
289
-
290
- Args:
291
- request: Request object
292
- exc: Exception that was raised
293
-
294
- Returns:
295
- JSON error response
296
- """
297
- logger.error(f"Unhandled exception: {exc}", exc_info=True)
298
-
299
- return JSONResponse(
300
- status_code=500,
301
- content={
302
- "error": "Internal server error",
303
- "detail": str(exc),
304
- "timestamp": datetime.utcnow().isoformat()
305
- }
306
- )
307
-
308
-
309
- # ============================================================================
310
- # Include Routers
311
- # ============================================================================
312
-
313
- # Include API endpoints router
314
- app.include_router(
315
- api_router,
316
- prefix="/api",
317
- tags=["API"]
318
- )
319
-
320
- # Include WebSocket router
321
- app.include_router(
322
- websocket_router,
323
- tags=["WebSocket"]
324
- )
325
-
326
- # Include Pool Management router
327
- app.include_router(
328
- pool_router,
329
- tags=["Pool Management"]
330
- )
331
-
332
- # Include Data endpoints router (cryptocurrency data)
333
- app.include_router(
334
- data_router,
335
- tags=["Crypto Data"]
336
- )
337
-
338
- # Include HF router (if available)
339
- if HF_ROUTER_AVAILABLE:
340
- try:
341
- app.include_router(
342
- hf_connect.router,
343
- tags=["HuggingFace"]
344
- )
345
- logger.info("HF router included successfully")
346
- except Exception as e:
347
- logger.warning(f"Could not include HF router: {e}")
348
-
349
- # Include new WebSocket service routers
350
- app.include_router(
351
- ws_unified_router,
352
- tags=["WebSocket Services"]
353
- )
354
-
355
- app.include_router(
356
- ws_data_router,
357
- tags=["WebSocket - Data Collection"]
358
- )
359
-
360
- app.include_router(
361
- ws_monitoring_router,
362
- tags=["WebSocket - Monitoring"]
363
- )
364
-
365
- app.include_router(
366
- ws_integration_router,
367
- tags=["WebSocket - Integration"]
368
- )
369
-
370
- logger.info("All WebSocket service routers included successfully")
371
-
372
-
373
- # ============================================================================
374
- # Root Endpoints
375
- # ============================================================================
376
-
377
- @app.get("/", response_class=HTMLResponse, tags=["Root"])
378
- async def root():
379
- """
380
- Serve the Vidya HTML UI dashboard
381
-
382
- Returns:
383
- HTML dashboard interface
384
- """
385
- try:
386
- with open("index.html", "r", encoding="utf-8") as f:
387
- return HTMLResponse(content=f.read())
388
- except Exception as e:
389
- logger.error(f"Error serving index.html: {e}")
390
- return HTMLResponse(content=f"<h1>Error loading dashboard</h1><p>{str(e)}</p>", status_code=500)
391
-
392
-
393
- @app.get("/api-info", tags=["Root"])
394
- async def api_info():
395
- """
396
- API information and available endpoints
397
-
398
- Returns:
399
- API information and endpoint listing
400
- """
401
  return {
402
- "name": "Crypto API Monitoring System",
403
- "version": "2.0.0",
404
- "description": "Comprehensive cryptocurrency API monitoring with real-time updates",
405
  "status": "online",
406
- "timestamp": datetime.utcnow().isoformat(),
407
- "endpoints": {
408
- "documentation": {
409
- "swagger": "/docs",
410
- "redoc": "/redoc"
411
- },
412
- "health": "/health",
413
- "api": {
414
- "providers": "/api/providers",
415
- "status": "/api/status",
416
- "rate_limits": "/api/rate-limits",
417
- "logs": "/api/logs/{log_type}",
418
- "alerts": "/api/alerts",
419
- "scheduler": "/api/scheduler/status",
420
- "database": "/api/database/stats",
421
- "analytics": "/api/analytics/failures"
422
- },
423
- "websocket": {
424
- "master": {
425
- "default": "/ws",
426
- "master": "/ws/master",
427
- "all_services": "/ws/all",
428
- "stats": "/ws/stats",
429
- "services": "/ws/services",
430
- "endpoints": "/ws/endpoints"
431
- },
432
- "data_collection": {
433
- "unified": "/ws/data",
434
- "market_data": "/ws/market_data",
435
- "whale_tracking": "/ws/whale_tracking",
436
- "news": "/ws/news",
437
- "sentiment": "/ws/sentiment"
438
- },
439
- "monitoring": {
440
- "unified": "/ws/monitoring",
441
- "health": "/ws/health",
442
- "pool_status": "/ws/pool_status",
443
- "scheduler": "/ws/scheduler_status"
444
- },
445
- "integration": {
446
- "unified": "/ws/integration",
447
- "huggingface": "/ws/huggingface",
448
- "ai": "/ws/ai",
449
- "persistence": "/ws/persistence"
450
- },
451
- "legacy": {
452
- "live": "/ws/live"
453
- }
454
- }
455
- },
456
- "features": [
457
- "Multi-provider API monitoring",
458
- "Real-time WebSocket updates for all services",
459
- "Data collection WebSocket APIs (market data, news, sentiment, whale tracking, etc.)",
460
- "Monitoring WebSocket APIs (health checks, pool management, scheduler)",
461
- "Integration WebSocket APIs (HuggingFace AI, persistence)",
462
- "Rate limit tracking",
463
- "Automated health checks",
464
- "Scheduled data collection",
465
- "Failure detection and alerts",
466
- "Historical analytics",
467
- "Subscription-based message routing"
468
- ],
469
- "system_info": {
470
- "total_providers": len(config.get_all_providers()),
471
- "categories": config.get_categories(),
472
- "scheduler_running": task_scheduler.is_running(),
473
- "websocket_connections": ws_manager.get_connection_count(),
474
- "database_path": db_manager.db_path
475
- }
476
  }
477
 
478
-
479
- @app.get("/health", tags=["Health"])
480
- async def health_check():
481
- """
482
- Comprehensive health check endpoint
483
-
484
- Returns:
485
- System health status
486
- """
487
  try:
488
- # Check database health
489
- db_health = db_manager.health_check()
490
-
491
- # Get latest system metrics
492
- latest_metrics = db_manager.get_latest_system_metrics()
493
-
494
- # Check scheduler status
495
- scheduler_status = task_scheduler.is_running()
496
-
497
- # Check WebSocket status
498
- ws_status = ws_manager._is_running
499
- ws_connections = ws_manager.get_connection_count()
500
-
501
- # Determine overall health
502
- overall_health = "healthy"
503
-
504
- if db_health.get('status') != 'healthy':
505
- overall_health = "degraded"
506
-
507
- if not scheduler_status:
508
- overall_health = "degraded"
509
-
510
- if latest_metrics and latest_metrics.system_health == "critical":
511
- overall_health = "critical"
512
-
513
  return {
514
- "status": overall_health,
515
- "timestamp": datetime.utcnow().isoformat(),
516
- "components": {
517
- "database": {
518
- "status": db_health.get('status', 'unknown'),
519
- "path": db_health.get('database_path'),
520
- "size_mb": db_health.get('stats', {}).get('database_size_mb', 0)
521
- },
522
- "scheduler": {
523
- "status": "running" if scheduler_status else "stopped",
524
- "active_jobs": task_scheduler.get_job_status().get('total_jobs', 0)
525
- },
526
- "websocket": {
527
- "status": "running" if ws_status else "stopped",
528
- "active_connections": ws_connections
529
- },
530
- "providers": {
531
- "total": len(config.get_all_providers()),
532
- "online": latest_metrics.online_count if latest_metrics else 0,
533
- "degraded": latest_metrics.degraded_count if latest_metrics else 0,
534
- "offline": latest_metrics.offline_count if latest_metrics else 0
535
- }
536
- },
537
- "metrics": {
538
- "avg_response_time_ms": latest_metrics.avg_response_time_ms if latest_metrics else 0,
539
- "total_requests_hour": latest_metrics.total_requests_hour if latest_metrics else 0,
540
- "total_failures_hour": latest_metrics.total_failures_hour if latest_metrics else 0,
541
- "system_health": latest_metrics.system_health if latest_metrics else "unknown"
542
- }
543
  }
544
-
545
  except Exception as e:
546
- logger.error(f"Health check error: {e}", exc_info=True)
547
- return {
548
- "status": "unhealthy",
549
- "timestamp": datetime.utcnow().isoformat(),
550
- "error": str(e)
551
- }
552
-
553
 
554
- @app.get("/info", tags=["Root"])
555
- async def system_info():
556
- """
557
- Get detailed system information
558
-
559
- Returns:
560
- Detailed system information
561
- """
562
  try:
563
- # Get configuration stats
564
- config_stats = config.stats()
565
-
566
- # Get database stats
567
- db_stats = db_manager.get_database_stats()
568
-
569
- # Get rate limit statuses
570
- rate_limit_count = len(rate_limiter.get_all_statuses())
571
-
572
- # Get scheduler info
573
- scheduler_info = task_scheduler.get_job_status()
574
-
575
- return {
576
- "application": {
577
- "name": "Crypto API Monitoring System",
578
- "version": "2.0.0",
579
- "environment": "production"
580
- },
581
- "configuration": config_stats,
582
- "database": db_stats,
583
- "rate_limits": {
584
- "configured_providers": rate_limit_count
585
- },
586
- "scheduler": {
587
- "running": task_scheduler.is_running(),
588
- "total_jobs": scheduler_info.get('total_jobs', 0),
589
- "jobs": scheduler_info.get('jobs', [])
590
- },
591
- "websocket": {
592
- "active_connections": ws_manager.get_connection_count(),
593
- "background_tasks_running": ws_manager._is_running
594
- },
595
- "timestamp": datetime.utcnow().isoformat()
596
- }
597
-
598
  except Exception as e:
599
- logger.error(f"System info error: {e}", exc_info=True)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
600
  return {
601
- "error": str(e),
602
- "timestamp": datetime.utcnow().isoformat()
603
  }
604
 
605
-
606
- # ============================================================================
607
- # Run Application
608
- # ============================================================================
609
-
610
  if __name__ == "__main__":
611
- """
612
- Run the application with uvicorn
613
-
614
- Configuration:
615
- - Host: 0.0.0.0 (all interfaces)
616
- - Port: 7860
617
- - Log level: info
618
- - Reload: disabled (production mode)
619
- """
620
- logger.info("Starting Crypto API Monitoring System on 0.0.0.0:7860")
621
-
622
- uvicorn.run(
623
- app,
624
- host="0.0.0.0",
625
- port=7860,
626
- log_level="info",
627
- access_log=True,
628
- use_colors=True
629
- )
 
1
+ from fastapi import FastAPI
 
 
 
 
 
 
 
 
 
 
 
 
2
  from fastapi.staticfiles import StaticFiles
3
+ from fastapi.responses import FileResponse
4
+ from fastapi.middleware.cors import CORSMiddleware
5
+ import os
6
+ import ccxt
7
+ from datetime import datetime
8
+ from pathlib import Path
9
 
10
+ app = FastAPI(title="Crypto Data Source API")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11
 
12
+ # CORS middleware
13
  app.add_middleware(
14
  CORSMiddleware,
15
+ allow_origins=["*"],
16
  allow_credentials=True,
17
  allow_methods=["*"],
18
  allow_headers=["*"],
19
  )
20
 
21
+ # Health check endpoint
22
+ @app.get("/api/health")
23
+ async def health_check():
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
24
  return {
 
 
 
25
  "status": "online",
26
+ "version": "1.0.0",
27
+ "timestamp": datetime.now().isoformat(),
28
+ "ccxt_version": ccxt.__version__
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
29
  }
30
 
31
+ # Example API endpoint - Add your trading endpoints here
32
+ @app.get("/api/markets")
33
+ async def get_markets():
 
 
 
 
 
 
34
  try:
35
+ exchange = ccxt.binance()
36
+ markets = exchange.load_markets()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
37
  return {
38
+ "success": True,
39
+ "total_markets": len(markets),
40
+ "markets": list(markets.keys())[:50] # Return first 50
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
41
  }
 
42
  except Exception as e:
43
+ return {"success": False, "error": str(e)}
 
 
 
 
 
 
44
 
45
+ @app.get("/api/ticker/{symbol}")
46
+ async def get_ticker(symbol: str):
 
 
 
 
 
 
47
  try:
48
+ exchange = ccxt.binance()
49
+ ticker = exchange.fetch_ticker(symbol)
50
+ return {"success": True, "data": ticker}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
51
  except Exception as e:
52
+ return {"success": False, "error": str(e)}
53
+
54
+ # Serve static files for frontend
55
+ frontend_dist = Path("frontend/dist")
56
+
57
+ if frontend_dist.exists():
58
+ # Mount static assets (JS, CSS, images, etc.)
59
+ app.mount("/assets", StaticFiles(directory=str(frontend_dist / "assets")), name="assets")
60
+
61
+ # Catch-all route for SPA (Single Page Application)
62
+ @app.get("/{full_path:path}")
63
+ async def serve_spa(full_path: str):
64
+ # If it's an API route that doesn't exist, return 404
65
+ if full_path.startswith("api/"):
66
+ return {"error": "API endpoint not found"}, 404
67
+
68
+ # Check if the requested file exists
69
+ file_path = frontend_dist / full_path
70
+ if file_path.is_file():
71
+ return FileResponse(file_path)
72
+
73
+ # Otherwise, serve index.html (for client-side routing)
74
+ return FileResponse(frontend_dist / "index.html")
75
+ else:
76
+ @app.get("/")
77
+ async def root():
78
  return {
79
+ "message": "Frontend not built. Please build the frontend first.",
80
+ "api_docs": "/docs"
81
  }
82
 
 
 
 
 
 
83
  if __name__ == "__main__":
84
+ import uvicorn
85
+ uvicorn.run(app, host="0.0.0.0", port=7860)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
requirements.txt CHANGED
@@ -1,15 +1,6 @@
1
  fastapi==0.104.1
2
  uvicorn[standard]==0.24.0
3
- pydantic==2.5.0
4
- python-multipart==0.0.6
5
- httpx==0.25.0
6
- python-dotenv==1.0.0
7
- requests==2.31.0
8
  ccxt==4.0.107
9
- pandas==2.1.1
10
- numpy==1.26.0
11
- matplotlib==3.8.0
12
- plotly==5.18.0
13
- ta==0.10.2
14
- scikit-learn==1.3.1
15
- joblib==1.3.2
 
1
  fastapi==0.104.1
2
  uvicorn[standard]==0.24.0
 
 
 
 
 
3
  ccxt==4.0.107
4
+ python-multipart==0.0.6
5
+ pydantic==2.5.0
6
+ aiofiles==23.2.1
 
 
 
 
راهنمای_نصب.md ADDED
@@ -0,0 +1,109 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # 🚀 راهنمای نصب و بارگذاری در Hugging Face Space
2
+
3
+ ## 📁 ساختار پروژه شما باید اینطور باشه:
4
+
5
+ ```
6
+ Datasourceforcryptocurrency/
7
+ ├── Dockerfile ← فایل جدید (دانلود کردید)
8
+ ├── README.md ← فایل جدید (دانلود کردید)
9
+ ├── .dockerignore ← فایل جدید (دانلود کردید)
10
+ ├── backend/
11
+ │ ├── app.py ← فایل جدید (دانلود کردید)
12
+ │ └── requirements.txt ← فایل جدید (دانلود کردید)
13
+ └── frontend/
14
+ ├── package.json
15
+ ├── vite.config.js
16
+ ├── index.html
17
+ └── src/
18
+ └── ... (فایل‌های React شما)
19
+ ```
20
+
21
+ ## 📝 مراحل بارگذاری:
22
+
23
+ ### مرحله 1: ساختار پوشه‌ها
24
+ 1. یک پوشه جدید به اسم `backend` بسازید
25
+ 2. فایل‌های `app.py` و `requirements.txt` رو داخلش بذارید
26
+ 3. مطمئن بشید پوشه `frontend` شما همه فایل‌های React رو داره
27
+
28
+ ### مرحله 2: بررسی frontend/package.json
29
+ مطمئن بشید که این script رو داره:
30
+ ```json
31
+ {
32
+ "scripts": {
33
+ "build": "vite build",
34
+ "dev": "vite"
35
+ }
36
+ }
37
+ ```
38
+
39
+ ### مرحله 3: بررسی frontend/vite.config.js
40
+ مطمئن بشید که base config داره:
41
+ ```javascript
42
+ import { defineConfig } from 'vite'
43
+ import react from '@vitejs/plugin-react'
44
+
45
+ export default defineConfig({
46
+ plugins: [react()],
47
+ base: '/',
48
+ server: {
49
+ port: 3000
50
+ }
51
+ })
52
+ ```
53
+
54
+ ### مرحله 4: بارگذاری در Hugging Face
55
+
56
+ #### روش 1: از طریق Web UI (ساده‌تر)
57
+ 1. برو به: https://huggingface.co/spaces/Really-amin/Datasourceforcryptocurrency
58
+ 2. روی "Files" کلیک کن
59
+ 3. فایل‌ها رو یکی یکی آپلود کن:
60
+ - `Dockerfile` در root
61
+ - `README.md` در root
62
+ - `.dockerignore` در root
63
+ - `app.py` در پوشه `backend/`
64
+ - `requirements.txt` در پوشه `backend/`
65
+
66
+ #### روش 2: از طریق Git (پیشرفته‌تر)
67
+ ```bash
68
+ # 1. Clone کردن Space
69
+ git clone https://huggingface.co/spaces/Really-amin/Datasourceforcryptocurrency
70
+ cd Datasourceforcryptocurrency
71
+
72
+ # 2. کپی کردن فایل‌های جدید
73
+ # فایل‌های دانلود شده رو کپی کنید به ساختار بالا
74
+
75
+ # 3. Commit و Push
76
+ git add .
77
+ git commit -m "Fix: Add proper Docker setup with frontend serving"
78
+ git push
79
+ ```
80
+
81
+ ### مرحله 5: منتظر Build بمونید
82
+ - Space به صورت خودکار rebuild می‌شه (5-10 دقیقه)
83
+ - لاگ‌ها رو نگاه کنید تا مطمئن بشید همه چیز درست Build شده
84
+ - وقتی "Running" شد، باید UI رو ببینید نه JSON!
85
+
86
+ ## 🔧 اگر هنوز مشکل داشتید:
87
+
88
+ ### خطای Build:
89
+ - چک کنید که `frontend/package.json` و `frontend/vite.config.js` وجود داشته باشه
90
+ - چک کنید که dependencies نصب شده باشن
91
+
92
+ ### هنوز JSON نشون میده:
93
+ - لاگ Space رو بررسی کنید
94
+ - مطمئن بشید که `frontend/dist` بعد از build ساخته شده
95
+ - مطمئن بشید که به root URL دسترسی دارید نه `/api`
96
+
97
+ ### نیاز به کمک بیشتر:
98
+ - لاگ‌های Build رو بفرستید
99
+ - محتویات `frontend/package.json` رو بفرستید
100
+ - Screenshot از ساختار پوشه‌ها بفرستید
101
+
102
+ ## ✅ بعد از موفقیت:
103
+
104
+ شما باید بتونید:
105
+ - به UI دسترسی داشته باشید در: https://really-amin-datasourceforcryptocurrency.hf.space
106
+ - API docs ببینید در: https://really-amin-datasourceforcryptocurrency.hf.space/docs
107
+ - Health check کار کنه: https://really-amin-datasourceforcryptocurrency.hf.space/api/health
108
+
109
+ موفق باشید! 🚀