| | |
| | |
| | |
| |
|
| |
|
| |
|
| | const API_BASE_URL = window.location.origin;
|
| |
|
| |
|
| | window.API_CONFIG = {
|
| |
|
| | baseUrl: API_BASE_URL,
|
| | apiUrl: `${API_BASE_URL}/api`,
|
| | smartApiUrl: `${API_BASE_URL}/api/smart`,
|
| |
|
| |
|
| | endpoints: {
|
| |
|
| | smart: {
|
| | market: `${API_BASE_URL}/api/smart/market`,
|
| | news: `${API_BASE_URL}/api/smart/news`,
|
| | sentiment: `${API_BASE_URL}/api/smart/sentiment`,
|
| | whaleAlerts: `${API_BASE_URL}/api/smart/whale-alerts`,
|
| | blockchain: `${API_BASE_URL}/api/smart/blockchain`,
|
| | healthReport: `${API_BASE_URL}/api/smart/health-report`,
|
| | stats: `${API_BASE_URL}/api/smart/stats`,
|
| | },
|
| |
|
| |
|
| | market: `${API_BASE_URL}/api/market`,
|
| | marketHistory: `${API_BASE_URL}/api/market/history`,
|
| | sentiment: `${API_BASE_URL}/api/sentiment/analyze`,
|
| | health: `${API_BASE_URL}/api/health`,
|
| |
|
| |
|
| | alphavantage: {
|
| | health: `${API_BASE_URL}/api/alphavantage/health`,
|
| | prices: `${API_BASE_URL}/api/alphavantage/prices`,
|
| | ohlcv: `${API_BASE_URL}/api/alphavantage/ohlcv`,
|
| | marketStatus: `${API_BASE_URL}/api/alphavantage/market-status`,
|
| | cryptoRating: `${API_BASE_URL}/api/alphavantage/crypto-rating`,
|
| | quote: `${API_BASE_URL}/api/alphavantage/quote`,
|
| | },
|
| |
|
| |
|
| | massive: {
|
| | health: `${API_BASE_URL}/api/massive/health`,
|
| | dividends: `${API_BASE_URL}/api/massive/dividends`,
|
| | splits: `${API_BASE_URL}/api/massive/splits`,
|
| | quotes: `${API_BASE_URL}/api/massive/quotes`,
|
| | trades: `${API_BASE_URL}/api/massive/trades`,
|
| | aggregates: `${API_BASE_URL}/api/massive/aggregates`,
|
| | ticker: `${API_BASE_URL}/api/massive/ticker`,
|
| | marketStatus: `${API_BASE_URL}/api/massive/market-status`,
|
| | },
|
| |
|
| |
|
| | docs: `${API_BASE_URL}/docs`,
|
| | redoc: `${API_BASE_URL}/redoc`,
|
| | },
|
| |
|
| |
|
| | features: {
|
| | useSmartFallback: true,
|
| | resourceRotation: true,
|
| | proxySupport: true,
|
| | backgroundCollection: true,
|
| | healthMonitoring: true,
|
| | autoCleanup: true,
|
| | },
|
| |
|
| |
|
| | request: {
|
| | timeout: 30000,
|
| | retries: 3,
|
| | retryDelay: 1000,
|
| | },
|
| |
|
| |
|
| | resources: {
|
| | total: '305+',
|
| | categories: {
|
| | marketData: 21,
|
| | blockExplorers: 40,
|
| | news: 15,
|
| | sentiment: 12,
|
| | whaleTracking: 9,
|
| | onchainAnalytics: 13,
|
| | rpcNodes: 24,
|
| | localBackend: 106,
|
| | corsProxies: 7,
|
| | }
|
| | }
|
| | };
|
| |
|
| | |
| | |
| |
|
| | class SmartAPIClient {
|
| | constructor(config = window.API_CONFIG) {
|
| | this.config = config;
|
| | this.authToken = this.getAuthToken();
|
| | }
|
| |
|
| | |
| | |
| |
|
| | getAuthToken() {
|
| |
|
| | let token = localStorage.getItem('hf_token');
|
| |
|
| |
|
| | if (!token) {
|
| | token = sessionStorage.getItem('hf_token');
|
| | }
|
| |
|
| |
|
| | if (!token) {
|
| | const params = new URLSearchParams(window.location.search);
|
| | token = params.get('token');
|
| | }
|
| |
|
| | return token;
|
| | }
|
| |
|
| | |
| | |
| |
|
| | setAuthToken(token) {
|
| | this.authToken = token;
|
| | localStorage.setItem('hf_token', token);
|
| | }
|
| |
|
| | |
| | |
| |
|
| | getHeaders() {
|
| | const headers = {
|
| | 'Content-Type': 'application/json',
|
| | 'Accept': 'application/json',
|
| | };
|
| |
|
| | if (this.authToken) {
|
| | headers['Authorization'] = `Bearer ${this.authToken}`;
|
| | }
|
| |
|
| | return headers;
|
| | }
|
| |
|
| | |
| | |
| |
|
| | async fetchWithRetry(url, options = {}, retries = 3) {
|
| | for (let i = 0; i < retries; i++) {
|
| | try {
|
| | const response = await fetch(url, {
|
| | ...options,
|
| | headers: {
|
| | ...this.getHeaders(),
|
| | ...options.headers,
|
| | },
|
| | timeout: this.config.request.timeout,
|
| | });
|
| |
|
| | if (!response.ok) {
|
| | throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
| | }
|
| |
|
| | return await response.json();
|
| | } catch (error) {
|
| | console.warn(`Attempt ${i + 1} failed:`, error);
|
| |
|
| | if (i === retries - 1) {
|
| | throw error;
|
| | }
|
| |
|
| |
|
| | await new Promise(resolve =>
|
| | setTimeout(resolve, this.config.request.retryDelay * (i + 1))
|
| | );
|
| | }
|
| | }
|
| | }
|
| |
|
| | |
| | |
| |
|
| | async getMarketData(limit = 100) {
|
| | try {
|
| |
|
| | return await this.fetchWithRetry(
|
| | `${this.config.endpoints.smart.market}?limit=${limit}`
|
| | );
|
| | } catch (error) {
|
| | console.error('Smart market data failed:', error);
|
| |
|
| |
|
| | try {
|
| | return await this.fetchWithRetry(
|
| | `${this.config.endpoints.market}?limit=${limit}`
|
| | );
|
| | } catch (fallbackError) {
|
| | console.error('All market data endpoints failed');
|
| | throw fallbackError;
|
| | }
|
| | }
|
| | }
|
| |
|
| | |
| | |
| |
|
| | async getNews(limit = 20) {
|
| | try {
|
| | return await this.fetchWithRetry(
|
| | `${this.config.endpoints.smart.news}?limit=${limit}`
|
| | );
|
| | } catch (error) {
|
| | console.error('Smart news failed:', error);
|
| | throw error;
|
| | }
|
| | }
|
| |
|
| | |
| | |
| |
|
| | async getSentiment(symbol = null) {
|
| | const url = symbol
|
| | ? `${this.config.endpoints.smart.sentiment}?symbol=${symbol}`
|
| | : this.config.endpoints.smart.sentiment;
|
| |
|
| | try {
|
| | return await this.fetchWithRetry(url);
|
| | } catch (error) {
|
| | console.error('Smart sentiment failed:', error);
|
| | throw error;
|
| | }
|
| | }
|
| |
|
| | |
| | |
| |
|
| | async getWhaleAlerts(limit = 20) {
|
| | try {
|
| | return await this.fetchWithRetry(
|
| | `${this.config.endpoints.smart.whaleAlerts}?limit=${limit}`
|
| | );
|
| | } catch (error) {
|
| | console.error('Smart whale alerts failed:', error);
|
| | throw error;
|
| | }
|
| | }
|
| |
|
| | |
| | |
| |
|
| | async getBlockchainData(chain = 'ethereum') {
|
| | try {
|
| | return await this.fetchWithRetry(
|
| | `${this.config.endpoints.smart.blockchain}/${chain}`
|
| | );
|
| | } catch (error) {
|
| | console.error('Smart blockchain data failed:', error);
|
| | throw error;
|
| | }
|
| | }
|
| |
|
| | |
| | |
| |
|
| | async getHealthReport() {
|
| | try {
|
| | return await this.fetchWithRetry(
|
| | this.config.endpoints.smart.healthReport
|
| | );
|
| | } catch (error) {
|
| | console.error('Health report failed:', error);
|
| | throw error;
|
| | }
|
| | }
|
| |
|
| | |
| | |
| |
|
| | async getStats() {
|
| | try {
|
| | return await this.fetchWithRetry(
|
| | this.config.endpoints.smart.stats
|
| | );
|
| | } catch (error) {
|
| | console.error('Stats failed:', error);
|
| | throw error;
|
| | }
|
| | }
|
| |
|
| | |
| | |
| |
|
| | async getAlphaVantageData(endpoint, params = {}) {
|
| | const url = new URL(endpoint);
|
| | Object.keys(params).forEach(key =>
|
| | url.searchParams.append(key, params[key])
|
| | );
|
| |
|
| | try {
|
| | return await this.fetchWithRetry(url.toString());
|
| | } catch (error) {
|
| | console.error('Alpha Vantage request failed:', error);
|
| | throw error;
|
| | }
|
| | }
|
| |
|
| | |
| | |
| |
|
| | async getMassiveData(endpoint, params = {}) {
|
| | const url = new URL(endpoint);
|
| | Object.keys(params).forEach(key =>
|
| | url.searchParams.append(key, params[key])
|
| | );
|
| |
|
| | try {
|
| | return await this.fetchWithRetry(url.toString());
|
| | } catch (error) {
|
| | console.error('Massive.com request failed:', error);
|
| | throw error;
|
| | }
|
| | }
|
| | }
|
| |
|
| |
|
| | window.apiClient = new SmartAPIClient();
|
| |
|
| |
|
| | if (typeof module !== 'undefined' && module.exports) {
|
| | module.exports = { API_CONFIG, SmartAPIClient };
|
| | }
|
| |
|
| | console.log('✅ API Configuration loaded successfully');
|
| | console.log('📊 Smart Fallback System: 305+ resources available');
|
| | console.log('🔄 Resource rotation: ENABLED');
|
| | console.log('🔒 Proxy support: ENABLED');
|
| | console.log('✨ Features:', window.API_CONFIG.features);
|
| |
|