Really-amin's picture
Upload 553 files
386790e verified
#!/usr/bin/env python3
"""
Binance Secure Client with Rotating DNS/Proxy
کلاینت امن Binance با DNS و Proxy چرخشی
"""
import httpx
import logging
from typing import Optional, Dict, List
from datetime import datetime
from backend.services.rotating_access_manager import rotating_access_manager
logger = logging.getLogger(__name__)
class BinanceSecureClient:
"""
Binance API Client با امنیت بالا
همیشه از Rotating DNS/Proxy استفاده می‌کنه
هیچ وقت مشکل دسترسی نداریم!
"""
def __init__(self):
self.base_url = "https://api.binance.com"
self.api_urls = [
"https://api.binance.com",
"https://api1.binance.com",
"https://api2.binance.com",
"https://api3.binance.com"
]
self.current_api_index = 0
def get_next_api_url(self) -> str:
"""چرخش بین URLهای مختلف Binance"""
url = self.api_urls[self.current_api_index]
self.current_api_index = (self.current_api_index + 1) % len(self.api_urls)
return url
async def get_24h_ticker(self, symbol: str = "BTCUSDT") -> Optional[Dict]:
"""
دریافت قیمت 24 ساعته با Rotating Access
Args:
symbol: نماد ارز (مثلاً BTCUSDT)
Returns:
{
"symbol": "BTCUSDT",
"lastPrice": "50000.00",
"priceChange": "500.00",
"priceChangePercent": "1.01",
...
}
"""
# استفاده از API URL چرخشی
base_url = self.get_next_api_url()
url = f"{base_url}/api/v3/ticker/24hr"
logger.info(f"📊 Getting Binance ticker for {symbol} (Secure)")
response = await rotating_access_manager.secure_fetch(
url,
params={"symbol": symbol},
use_rotating_dns=True,
use_rotating_proxy=True
)
if response and response.status_code == 200:
data = response.json()
logger.info(f"✅ Binance ticker retrieved: ${data.get('lastPrice')}")
return data
return None
async def get_price(self, symbol: str = "BTCUSDT") -> Optional[float]:
"""
دریافت قیمت فعلی (ساده)
Returns:
float: قیمت (مثلاً 50000.5)
"""
base_url = self.get_next_api_url()
url = f"{base_url}/api/v3/ticker/price"
response = await rotating_access_manager.secure_fetch(
url,
params={"symbol": symbol},
use_rotating_dns=True,
use_rotating_proxy=True
)
if response and response.status_code == 200:
data = response.json()
price = float(data.get("price", 0))
logger.info(f"✅ Binance price: {symbol} = ${price}")
return price
return None
async def get_ohlcv(
self,
symbol: str = "BTCUSDT",
interval: str = "1h",
limit: int = 100
) -> Optional[List[Dict]]:
"""
دریافت کندل‌ها (OHLCV)
Args:
symbol: نماد ارز
interval: بازه زمانی (1m, 5m, 15m, 1h, 4h, 1d)
limit: تعداد کندل
Returns:
[
{
"timestamp": 1234567890,
"open": 50000,
"high": 51000,
"low": 49000,
"close": 50500,
"volume": 12345
},
...
]
"""
base_url = self.get_next_api_url()
url = f"{base_url}/api/v3/klines"
logger.info(f"📈 Getting Binance OHLCV for {symbol} ({interval})")
response = await rotating_access_manager.secure_fetch(
url,
params={
"symbol": symbol,
"interval": interval,
"limit": limit
},
use_rotating_dns=True,
use_rotating_proxy=True
)
if response and response.status_code == 200:
data = response.json()
# تبدیل به فرمت خوانا
ohlcv = []
for candle in data:
ohlcv.append({
"timestamp": candle[0],
"open": float(candle[1]),
"high": float(candle[2]),
"low": float(candle[3]),
"close": float(candle[4]),
"volume": float(candle[5])
})
logger.info(f"✅ Got {len(ohlcv)} candles")
return ohlcv
return None
async def get_orderbook(self, symbol: str = "BTCUSDT", limit: int = 20) -> Optional[Dict]:
"""
دریافت Order Book
Returns:
{
"bids": [[price, quantity], ...],
"asks": [[price, quantity], ...],
...
}
"""
base_url = self.get_next_api_url()
url = f"{base_url}/api/v3/depth"
response = await rotating_access_manager.secure_fetch(
url,
params={"symbol": symbol, "limit": limit},
use_rotating_dns=True,
use_rotating_proxy=True
)
if response and response.status_code == 200:
data = response.json()
logger.info(f"✅ Binance orderbook retrieved")
return data
return None
async def get_exchange_info(self, symbol: Optional[str] = None) -> Optional[Dict]:
"""
دریافت اطلاعات صرافی
Args:
symbol: نماد ارز (اختیاری)
"""
base_url = self.get_next_api_url()
url = f"{base_url}/api/v3/exchangeInfo"
params = {}
if symbol:
params["symbol"] = symbol
response = await rotating_access_manager.secure_fetch(
url,
params=params if params else None,
use_rotating_dns=True,
use_rotating_proxy=True
)
if response and response.status_code == 200:
data = response.json()
logger.info(f"✅ Binance exchange info retrieved")
return data
return None
async def health_check(self) -> bool:
"""
بررسی سلامت API
Returns:
True اگر Binance در دسترس باشه
"""
base_url = self.get_next_api_url()
url = f"{base_url}/api/v3/ping"
try:
response = await rotating_access_manager.secure_fetch(
url,
use_rotating_dns=True,
use_rotating_proxy=True
)
if response and response.status_code == 200:
logger.info(f"💚 Binance health check: OK")
return True
return False
except:
return False
# Global instance
binance_secure_client = BinanceSecureClient()
__all__ = ["BinanceSecureClient", "binance_secure_client"]