feat: add rate limiting for CoinGecko API and global error handling
This commit is contained in:
@@ -16,24 +16,59 @@ const CURRENCY_SYMBOLS = {
|
||||
JPY: '¥'
|
||||
}
|
||||
|
||||
const CACHE_DURATION = 5 * 60 * 1000 // 5 minutes
|
||||
const CACHE_DURATION = 10 * 60 * 1000 // 10 minutes (CoinGecko free tier: 10-30 req/min)
|
||||
const MIN_REQUEST_INTERVAL = 6 * 1000 // 6 seconds between requests (max ~10/min)
|
||||
|
||||
let cachedRates = null
|
||||
let cacheTimestamp = 0
|
||||
let lastRequestTime = 0
|
||||
let pendingRequest = null
|
||||
|
||||
/**
|
||||
* Fetches current XMR rates from CoinGecko
|
||||
* Fetches current XMR rates from CoinGecko with rate limiting
|
||||
* @returns {Promise<Object>} Rates per currency (e.g. { EUR: 329.05, USD: 388.87 })
|
||||
*/
|
||||
export async function getXmrRates() {
|
||||
// Check cache
|
||||
// Return cached rates if still valid
|
||||
if (cachedRates && Date.now() - cacheTimestamp < CACHE_DURATION) {
|
||||
return cachedRates
|
||||
}
|
||||
|
||||
// If a request is already pending, wait for it
|
||||
if (pendingRequest) {
|
||||
return pendingRequest
|
||||
}
|
||||
|
||||
// Rate limiting: ensure minimum interval between requests
|
||||
const timeSinceLastRequest = Date.now() - lastRequestTime
|
||||
if (timeSinceLastRequest < MIN_REQUEST_INTERVAL && cachedRates) {
|
||||
return cachedRates
|
||||
}
|
||||
|
||||
// Create and store the pending request
|
||||
pendingRequest = fetchRates()
|
||||
|
||||
try {
|
||||
const rates = await pendingRequest
|
||||
return rates
|
||||
} finally {
|
||||
pendingRequest = null
|
||||
}
|
||||
}
|
||||
|
||||
async function fetchRates() {
|
||||
lastRequestTime = Date.now()
|
||||
|
||||
try {
|
||||
const currencies = 'eur,usd,gbp,chf,jpy'
|
||||
const response = await fetch(`${COINGECKO_API}?ids=monero&vs_currencies=${currencies}`)
|
||||
|
||||
// Handle rate limit response
|
||||
if (response.status === 429) {
|
||||
console.warn('CoinGecko rate limit hit, using cached rates')
|
||||
return cachedRates || getDefaultRates()
|
||||
}
|
||||
|
||||
const data = await response.json()
|
||||
|
||||
if (!data.monero) {
|
||||
|
||||
Reference in New Issue
Block a user