|
|
import axios from 'axios'; |
|
|
|
|
|
export class ExchangeRateService { |
|
|
private cachedRate: number | null = null; |
|
|
private cacheExpiry: Date | null = null; |
|
|
private readonly CACHE_DURATION_MS = 60 * 60 * 1000; |
|
|
private readonly FALLBACK_RATE: number; |
|
|
|
|
|
constructor() { |
|
|
this.FALLBACK_RATE = parseFloat(process.env.NGN_PER_USD || '750'); |
|
|
} |
|
|
|
|
|
async getNGNToUSDRate(): Promise<number> { |
|
|
if (this.cachedRate && this.cacheExpiry && new Date() < this.cacheExpiry) { |
|
|
console.log('Using cached exchange rate:', this.cachedRate); |
|
|
return this.cachedRate; |
|
|
} |
|
|
|
|
|
try { |
|
|
const rate = await this.fetchExchangeRate(); |
|
|
this.cachedRate = rate; |
|
|
this.cacheExpiry = new Date(Date.now() + this.CACHE_DURATION_MS); |
|
|
console.log('Fetched new exchange rate:', rate); |
|
|
return rate; |
|
|
} catch (error) { |
|
|
console.error('Failed to fetch exchange rate, using fallback:', error); |
|
|
return this.FALLBACK_RATE; |
|
|
} |
|
|
} |
|
|
|
|
|
private async fetchExchangeRate(): Promise<number> { |
|
|
try { |
|
|
const response = await axios.get('https://api.exchangerate-api.com/v4/latest/USD', { |
|
|
timeout: 5000, |
|
|
}); |
|
|
const rate = response.data.rates?.NGN; |
|
|
if (rate && rate > 0) { |
|
|
return rate; |
|
|
} |
|
|
} catch (error) { |
|
|
console.warn('ExchangeRate-API failed, trying alternative...'); |
|
|
} |
|
|
|
|
|
|
|
|
const currencyApiKey = process.env.CURRENCY_API_KEY; |
|
|
if (currencyApiKey) { |
|
|
try { |
|
|
const response = await axios.get( |
|
|
`https://api.currencyapi.com/v3/latest?apikey=${currencyApiKey}¤cies=NGN&base_currency=USD`, |
|
|
{ timeout: 5000 } |
|
|
); |
|
|
const rate = response.data.data?.NGN?.value; |
|
|
if (rate && rate > 0) { |
|
|
return rate; |
|
|
} |
|
|
} catch (error) { |
|
|
console.warn('CurrencyAPI failed, trying alternative...'); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
const fixerApiKey = process.env.FIXER_API_KEY; |
|
|
if (fixerApiKey) { |
|
|
try { |
|
|
const response = await axios.get( |
|
|
`https://api.fixer.io/latest?access_key=${fixerApiKey}&base=USD&symbols=NGN`, |
|
|
{ timeout: 5000 } |
|
|
); |
|
|
const rate = response.data.rates?.NGN; |
|
|
if (rate && rate > 0) { |
|
|
return rate; |
|
|
} |
|
|
} catch (error) { |
|
|
console.warn('Fixer.io failed, using fallback...'); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
throw new Error('All exchange rate APIs failed'); |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
getFallbackRate(): number { |
|
|
return this.FALLBACK_RATE; |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
clearCache(): void { |
|
|
this.cachedRate = null; |
|
|
this.cacheExpiry = null; |
|
|
} |
|
|
} |
|
|
|
|
|
|