Spaces:
Sleeping
Sleeping
| """ | |
| API Configuration Loader | |
| Loads all API sources from all_apis_merged_2025.json | |
| """ | |
| import json | |
| import re | |
| from typing import Dict, List, Any | |
| class APILoader: | |
| def __init__(self, config_file='all_apis_merged_2025.json'): | |
| self.config_file = config_file | |
| self.apis = {} | |
| self.keys = {} | |
| self.cors_proxies = [] | |
| self.load_config() | |
| def load_config(self): | |
| """Load and parse the comprehensive API configuration""" | |
| try: | |
| with open(self.config_file, 'r', encoding='utf-8') as f: | |
| data = json.load(f) | |
| # Extract API keys from raw content | |
| self.extract_keys(data) | |
| # Extract CORS proxies | |
| self.extract_cors_proxies(data) | |
| # Build API registry | |
| self.build_api_registry(data) | |
| print(f"✓ Loaded {len(self.apis)} API sources") | |
| print(f"✓ Found {len(self.keys)} API keys") | |
| print(f"✓ Configured {len(self.cors_proxies)} CORS proxies") | |
| except Exception as e: | |
| print(f"✗ Error loading config: {e}") | |
| self.load_defaults() | |
| def extract_keys(self, data): | |
| """Extract API keys from configuration""" | |
| content = str(data) | |
| # Known key patterns | |
| key_patterns = { | |
| 'TronScan': r'TronScan[:\s]+([a-f0-9-]{36})', | |
| 'BscScan': r'BscScan[:\s]+([A-Z0-9]{34})', | |
| 'Etherscan': r'Etherscan[:\s]+([A-Z0-9]{34})', | |
| 'Etherscan_2': r'Etherscan_2[:\s]+([A-Z0-9]{34})', | |
| 'CoinMarketCap': r'CoinMarketCap[:\s]+([a-f0-9-]{36})', | |
| 'CoinMarketCap_2': r'CoinMarketCap_2[:\s]+([a-f0-9-]{36})', | |
| 'CryptoCompare': r'CryptoCompare[:\s]+([a-f0-9]{40})', | |
| } | |
| for name, pattern in key_patterns.items(): | |
| match = re.search(pattern, content) | |
| if match: | |
| self.keys[name] = match.group(1) | |
| def extract_cors_proxies(self, data): | |
| """Extract CORS proxy URLs""" | |
| self.cors_proxies = [ | |
| 'https://api.allorigins.win/get?url=', | |
| 'https://proxy.cors.sh/', | |
| 'https://proxy.corsfix.com/?url=', | |
| 'https://api.codetabs.com/v1/proxy?quest=', | |
| 'https://thingproxy.freeboard.io/fetch/' | |
| ] | |
| def build_api_registry(self, data): | |
| """Build comprehensive API registry""" | |
| # Market Data APIs | |
| self.apis['CoinGecko'] = { | |
| 'name': 'CoinGecko', | |
| 'category': 'market_data', | |
| 'url': 'https://api.coingecko.com/api/v3/ping', | |
| 'test_field': 'gecko_says', | |
| 'key': None, | |
| 'priority': 1 | |
| } | |
| self.apis['CoinGecko_Price'] = { | |
| 'name': 'CoinGecko Price', | |
| 'category': 'market_data', | |
| 'url': 'https://api.coingecko.com/api/v3/simple/price?ids=bitcoin&vs_currencies=usd', | |
| 'test_field': 'bitcoin', | |
| 'key': None, | |
| 'priority': 1 | |
| } | |
| self.apis['Binance'] = { | |
| 'name': 'Binance', | |
| 'category': 'market_data', | |
| 'url': 'https://api.binance.com/api/v3/ping', | |
| 'test_field': None, | |
| 'key': None, | |
| 'priority': 1 | |
| } | |
| self.apis['Binance_Price'] = { | |
| 'name': 'Binance BTCUSDT', | |
| 'category': 'market_data', | |
| 'url': 'https://api.binance.com/api/v3/ticker/24hr?symbol=BTCUSDT', | |
| 'test_field': 'symbol', | |
| 'key': None, | |
| 'priority': 1 | |
| } | |
| self.apis['CoinCap'] = { | |
| 'name': 'CoinCap', | |
| 'category': 'market_data', | |
| 'url': 'https://api.coincap.io/v2/assets/bitcoin', | |
| 'test_field': 'data', | |
| 'key': None, | |
| 'priority': 2 | |
| } | |
| self.apis['Coinpaprika'] = { | |
| 'name': 'Coinpaprika', | |
| 'category': 'market_data', | |
| 'url': 'https://api.coinpaprika.com/v1/tickers/btc-bitcoin', | |
| 'test_field': 'id', | |
| 'key': None, | |
| 'priority': 2 | |
| } | |
| self.apis['CoinLore'] = { | |
| 'name': 'CoinLore', | |
| 'category': 'market_data', | |
| 'url': 'https://api.coinlore.net/api/ticker/?id=90', | |
| 'test_field': None, | |
| 'key': None, | |
| 'priority': 2 | |
| } | |
| # Sentiment APIs | |
| self.apis['Alternative.me'] = { | |
| 'name': 'Alternative.me', | |
| 'category': 'sentiment', | |
| 'url': 'https://api.alternative.me/fng/', | |
| 'test_field': 'data', | |
| 'key': None, | |
| 'priority': 1 | |
| } | |
| # News APIs | |
| self.apis['CryptoPanic'] = { | |
| 'name': 'CryptoPanic', | |
| 'category': 'news', | |
| 'url': 'https://cryptopanic.com/api/v1/posts/?public=true', | |
| 'test_field': 'results', | |
| 'key': None, | |
| 'priority': 1 | |
| } | |
| self.apis['Reddit_Crypto'] = { | |
| 'name': 'Reddit Crypto', | |
| 'category': 'news', | |
| 'url': 'https://www.reddit.com/r/CryptoCurrency/hot.json?limit=5', | |
| 'test_field': 'data', | |
| 'key': None, | |
| 'priority': 2 | |
| } | |
| # Block Explorers (with keys) | |
| if 'Etherscan' in self.keys: | |
| self.apis['Etherscan'] = { | |
| 'name': 'Etherscan', | |
| 'category': 'blockchain_explorers', | |
| 'url': f'https://api.etherscan.io/api?module=stats&action=ethsupply&apikey={self.keys["Etherscan"]}', | |
| 'test_field': 'result', | |
| 'key': self.keys['Etherscan'], | |
| 'priority': 1 | |
| } | |
| if 'BscScan' in self.keys: | |
| self.apis['BscScan'] = { | |
| 'name': 'BscScan', | |
| 'category': 'blockchain_explorers', | |
| 'url': f'https://api.bscscan.com/api?module=stats&action=bnbsupply&apikey={self.keys["BscScan"]}', | |
| 'test_field': 'result', | |
| 'key': self.keys['BscScan'], | |
| 'priority': 1 | |
| } | |
| if 'TronScan' in self.keys: | |
| self.apis['TronScan'] = { | |
| 'name': 'TronScan', | |
| 'category': 'blockchain_explorers', | |
| 'url': 'https://apilist.tronscanapi.com/api/system/status', | |
| 'test_field': None, | |
| 'key': self.keys['TronScan'], | |
| 'priority': 1 | |
| } | |
| # Additional free APIs | |
| self.apis['Blockchair_BTC'] = { | |
| 'name': 'Blockchair Bitcoin', | |
| 'category': 'blockchain_explorers', | |
| 'url': 'https://api.blockchair.com/bitcoin/stats', | |
| 'test_field': 'data', | |
| 'key': None, | |
| 'priority': 2 | |
| } | |
| self.apis['Blockchain.info'] = { | |
| 'name': 'Blockchain.info', | |
| 'category': 'blockchain_explorers', | |
| 'url': 'https://blockchain.info/latestblock', | |
| 'test_field': 'height', | |
| 'key': None, | |
| 'priority': 2 | |
| } | |
| # RPC Nodes | |
| self.apis['Ankr_ETH'] = { | |
| 'name': 'Ankr Ethereum', | |
| 'category': 'rpc_nodes', | |
| 'url': 'https://rpc.ankr.com/eth', | |
| 'test_field': None, | |
| 'key': None, | |
| 'priority': 2, | |
| 'method': 'POST' | |
| } | |
| self.apis['Cloudflare_ETH'] = { | |
| 'name': 'Cloudflare ETH', | |
| 'category': 'rpc_nodes', | |
| 'url': 'https://cloudflare-eth.com', | |
| 'test_field': None, | |
| 'key': None, | |
| 'priority': 2, | |
| 'method': 'POST' | |
| } | |
| # DeFi APIs | |
| self.apis['1inch'] = { | |
| 'name': '1inch', | |
| 'category': 'defi', | |
| 'url': 'https://api.1inch.io/v5.0/1/healthcheck', | |
| 'test_field': None, | |
| 'key': None, | |
| 'priority': 2 | |
| } | |
| # Additional market data | |
| self.apis['Messari'] = { | |
| 'name': 'Messari', | |
| 'category': 'market_data', | |
| 'url': 'https://data.messari.io/api/v1/assets/bitcoin/metrics', | |
| 'test_field': 'data', | |
| 'key': None, | |
| 'priority': 2 | |
| } | |
| self.apis['CoinDesk'] = { | |
| 'name': 'CoinDesk', | |
| 'category': 'market_data', | |
| 'url': 'https://api.coindesk.com/v1/bpi/currentprice.json', | |
| 'test_field': 'bpi', | |
| 'key': None, | |
| 'priority': 2 | |
| } | |
| def load_defaults(self): | |
| """Load minimal default configuration if file loading fails""" | |
| self.apis = { | |
| 'CoinGecko': { | |
| 'name': 'CoinGecko', | |
| 'category': 'market_data', | |
| 'url': 'https://api.coingecko.com/api/v3/ping', | |
| 'test_field': 'gecko_says', | |
| 'key': None, | |
| 'priority': 1 | |
| }, | |
| 'Binance': { | |
| 'name': 'Binance', | |
| 'category': 'market_data', | |
| 'url': 'https://api.binance.com/api/v3/ping', | |
| 'test_field': None, | |
| 'key': None, | |
| 'priority': 1 | |
| } | |
| } | |
| def get_all_apis(self) -> Dict[str, Dict[str, Any]]: | |
| """Get all configured APIs""" | |
| return self.apis | |
| def get_apis_by_category(self, category: str) -> Dict[str, Dict[str, Any]]: | |
| """Get APIs filtered by category""" | |
| return {k: v for k, v in self.apis.items() if v['category'] == category} | |
| def get_categories(self) -> List[str]: | |
| """Get all unique categories""" | |
| return list(set(api['category'] for api in self.apis.values())) | |
| def add_custom_api(self, name: str, url: str, category: str, test_field: str = None): | |
| """Add a custom API source""" | |
| self.apis[name] = { | |
| 'name': name, | |
| 'category': category, | |
| 'url': url, | |
| 'test_field': test_field, | |
| 'key': None, | |
| 'priority': 3 | |
| } | |
| return True | |
| def remove_api(self, name: str): | |
| """Remove an API source""" | |
| if name in self.apis: | |
| del self.apis[name] | |
| return True | |
| return False | |
| # Global instance | |
| api_loader = APILoader() | |