File size: 4,585 Bytes
09801ca
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
/**
 * Real-Time Exchange Rate Service
 * 
 * Uses Frankfurter API (European Central Bank rates)
 * - No API key required
 * - Updates daily (official ECB rates)
 * - Free and reliable
 * 
 * API: https://api.frankfurter.app/latest
 */

// Types are defined in ./currency.ts - this module provides real-time rate fetching

// Cached rates with timestamp
let cachedRates: Record<string, number> | null = null;
let lastFetchTime: number = 0;
const CACHE_DURATION = 60 * 60 * 1000; // 1 hour cache

// Fallback static rates (Dec 2024 approximate values)
// These are used when API is unavailable
const FALLBACK_RATES: Record<string, number> = {
    USD: 1.0,
    EUR: 0.95,    // 1 USD = 0.95 EUR
    GBP: 0.79,    // 1 USD = 0.79 GBP
    INR: 84.0,    // 1 USD = 84 INR
    JPY: 149.5,   // 1 USD = 149.5 JPY
    AUD: 1.54,    // 1 USD = 1.54 AUD
    CAD: 1.35,    // 1 USD = 1.35 CAD
    CHF: 0.88,    // 1 USD = 0.88 CHF
    CNY: 7.15,    // 1 USD = 7.15 CNY
    SGD: 1.35,    // 1 USD = 1.35 SGD
};

/**
 * Fetch latest exchange rates from API
 * Returns rates relative to USD
 */
export async function fetchExchangeRates(): Promise<Record<string, number>> {
    const now = Date.now();

    // Return cached rates if still valid
    if (cachedRates && (now - lastFetchTime) < CACHE_DURATION) {
        return cachedRates;
    }

    try {
        // Frankfurter API - ECB rates, base USD
        const response = await fetch('https://api.frankfurter.app/latest?from=USD');

        if (!response.ok) {
            throw new Error(`API error: ${response.status}`);
        }

        const data = await response.json();

        // Convert to our format: how many units of X = 1 USD
        const rates: Record<string, number> = { USD: 1.0 };

        if (data.rates) {
            for (const [currency, rate] of Object.entries(data.rates)) {
                rates[currency] = rate as number;
            }
        }

        // Cache the rates
        cachedRates = rates;
        lastFetchTime = now;

        console.log('✅ Exchange rates updated from ECB:', new Date().toLocaleString());

        return rates;
    } catch (error) {
        console.warn('⚠️ Failed to fetch exchange rates, using fallback:', error);
        return FALLBACK_RATES;
    }
}

/**
 * Get current exchange rates (cached or fallback)
 */
export function getExchangeRates(): Record<string, number> {
    return cachedRates || FALLBACK_RATES;
}

/**
 * Convert currency using real-time rates
 */
export async function convertCurrencyRealtime(
    amount: number,
    fromCurrency: string,
    toCurrency: string
): Promise<number> {
    if (fromCurrency === toCurrency) return amount;

    const rates = await fetchExchangeRates();

    // Both rates are relative to USD
    const fromRate = rates[fromCurrency] || 1;
    const toRate = rates[toCurrency] || 1;

    // Convert: source -> USD -> target
    const usdAmount = amount / fromRate;  // Convert to USD
    const targetAmount = usdAmount * toRate;  // Convert from USD to target

    return targetAmount;
}

/**
 * Sync version using cached rates
 */
export function convertCurrencySync(
    amount: number,
    fromCurrency: string,
    toCurrency: string
): number {
    if (fromCurrency === toCurrency) return amount;

    const rates = getExchangeRates();

    const fromRate = rates[fromCurrency] || 1;
    const toRate = rates[toCurrency] || 1;

    const usdAmount = amount / fromRate;
    const targetAmount = usdAmount * toRate;

    return targetAmount;
}

/**
 * Initialize rates on app load
 */
export function initializeExchangeRates(): void {
    fetchExchangeRates().then(() => {
        console.log('💱 Exchange rates initialized');
    }).catch(err => {
        console.warn('Failed to initialize rates:', err);
    });
}

/**
 * Get the current rate for a specific currency pair
 */
export async function getRate(fromCurrency: string, toCurrency: string): Promise<number> {
    const rates = await fetchExchangeRates();

    if (fromCurrency === 'USD') {
        return rates[toCurrency] || 1;
    }

    if (toCurrency === 'USD') {
        return 1 / (rates[fromCurrency] || 1);
    }

    // Cross rate: FROM -> USD -> TO
    const fromToUsd = 1 / (rates[fromCurrency] || 1);
    const usdToTarget = rates[toCurrency] || 1;

    return fromToUsd * usdToTarget;
}

/**
 * Format rate for display
 */
export function formatRate(rate: number): string {
    if (rate >= 100) {
        return rate.toFixed(2);
    } else if (rate >= 1) {
        return rate.toFixed(4);
    } else {
        return rate.toFixed(6);
    }
}