feat: update legal pages, add Kraken API as primary rate source, clarify listing fee
This commit is contained in:
@@ -1,10 +1,12 @@
|
||||
/**
|
||||
* Currency Service - XMR/Fiat Conversion
|
||||
*
|
||||
* Uses CoinGecko API for real-time exchange rates (CORS-friendly)
|
||||
* Primary: Kraken API (no key required, reliable)
|
||||
* Fallback: CoinGecko API
|
||||
* Supports two modes: fiat-fix and xmr-fix
|
||||
*/
|
||||
|
||||
const KRAKEN_API = 'https://api.kraken.com/0/public/Ticker'
|
||||
const COINGECKO_API = 'https://api.coingecko.com/api/v3/simple/price'
|
||||
|
||||
const CURRENCY_SYMBOLS = {
|
||||
@@ -90,25 +92,68 @@ export async function getXmrRates() {
|
||||
|
||||
async function fetchRates() {
|
||||
lastRequestTime = Date.now()
|
||||
|
||||
|
||||
// Try Kraken first, then CoinGecko as fallback
|
||||
const rates = await fetchFromKraken() || await fetchFromCoinGecko()
|
||||
|
||||
if (rates) {
|
||||
cachedRates = rates
|
||||
cacheTimestamp = Date.now()
|
||||
saveToStorage()
|
||||
return rates
|
||||
}
|
||||
|
||||
return cachedRates || getDefaultRates()
|
||||
}
|
||||
|
||||
async function fetchFromKraken() {
|
||||
try {
|
||||
const pairs = 'XMREUR,XMRUSD,XMRGBP,XMRJPY'
|
||||
const response = await fetch(`${KRAKEN_API}?pair=${pairs}`)
|
||||
if (!response.ok) return null
|
||||
|
||||
const data = await response.json()
|
||||
if (data.error?.length > 0) return null
|
||||
|
||||
const r = data.result
|
||||
const getPrice = (key) => {
|
||||
const entry = r[key]
|
||||
return entry ? parseFloat(entry.c[0]) : null
|
||||
}
|
||||
|
||||
const eur = getPrice('XXMRZEUR') || getPrice('XMREUR')
|
||||
const usd = getPrice('XXMRZUSD') || getPrice('XMRUSD')
|
||||
const gbp = getPrice('XXMRGBP') || getPrice('XMRGBP')
|
||||
const jpy = getPrice('XXMRJPY') || getPrice('XMRJPY')
|
||||
|
||||
if (!eur || !usd) return null
|
||||
|
||||
// Kraken doesn't have CHF/RUB/BRL pairs for XMR — derive from EUR
|
||||
const chf = eur * 0.97
|
||||
const rub = eur * 100
|
||||
const brl = usd * 5.5
|
||||
|
||||
return { EUR: eur, USD: usd, GBP: gbp || eur * 0.86, CHF: chf, JPY: jpy || eur * 162, RUB: rub, BRL: brl }
|
||||
} catch (e) {
|
||||
console.warn('Kraken API failed, trying CoinGecko:', e.message)
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
async function fetchFromCoinGecko() {
|
||||
try {
|
||||
const currencies = 'eur,usd,gbp,chf,jpy,rub,brl'
|
||||
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()
|
||||
console.warn('CoinGecko rate limit hit')
|
||||
return null
|
||||
}
|
||||
|
||||
|
||||
const data = await response.json()
|
||||
if (!data.monero) return null
|
||||
|
||||
if (!data.monero) {
|
||||
console.error('CoinGecko API Error: No data returned')
|
||||
return cachedRates || getDefaultRates()
|
||||
}
|
||||
|
||||
const rates = {
|
||||
return {
|
||||
EUR: data.monero.eur,
|
||||
USD: data.monero.usd,
|
||||
GBP: data.monero.gbp,
|
||||
@@ -117,16 +162,9 @@ async function fetchRates() {
|
||||
RUB: data.monero.rub,
|
||||
BRL: data.monero.brl
|
||||
}
|
||||
|
||||
// Update cache
|
||||
cachedRates = rates
|
||||
cacheTimestamp = Date.now()
|
||||
saveToStorage()
|
||||
|
||||
return rates
|
||||
} catch (error) {
|
||||
console.error('Failed to fetch XMR rates:', error)
|
||||
return cachedRates || getDefaultRates()
|
||||
} catch (e) {
|
||||
console.error('CoinGecko API failed:', e.message)
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user