feat: add rate limiting for CoinGecko API and global error handling

This commit is contained in:
2026-02-04 10:57:47 +01:00
parent 28ac3e03e0
commit 9f3ff3e3cb
6 changed files with 277 additions and 3 deletions

View File

@@ -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) {