diff --git a/basicswap/static/js/offerstable.js b/basicswap/static/js/offerstable.js index 67a9437..1b48232 100644 --- a/basicswap/static/js/offerstable.js +++ b/basicswap/static/js/offerstable.js @@ -497,48 +497,48 @@ const CacheManager = { }, get: function(key) { - try { - const itemStr = localStorage.getItem(key); - if (!itemStr) { - return null; - } - - let item; - try { - item = JSON.parse(itemStr); - } catch (parseError) { - console.error('Failed to parse cached item:', parseError); - localStorage.removeItem(key); - return null; - } - - if (!item || typeof item.expiresAt !== 'number' || !item.hasOwnProperty('value')) { - console.warn('Invalid cache item structure for key:', key); - localStorage.removeItem(key); - return null; - } - - const now = Date.now(); - if (now < item.expiresAt) { - return { - value: item.value, - remainingTime: item.expiresAt - now - }; - } - - localStorage.removeItem(key); - return null; - - } catch (error) { - console.error("Cache retrieval error:", error); - try { - localStorage.removeItem(key); - } catch (removeError) { - console.error("Failed to remove invalid cache entry:", removeError); - } + try { + const itemStr = localStorage.getItem(key); + if (!itemStr) { return null; } - }, + + let item; + try { + item = JSON.parse(itemStr); + } catch (parseError) { + console.error('Failed to parse cached item:', parseError); + localStorage.removeItem(key); + return null; + } + + if (!item || typeof item.expiresAt !== 'number' || !Object.prototype.hasOwnProperty.call(item, 'value')) { + console.warn('Invalid cache item structure for key:', key); + localStorage.removeItem(key); + return null; + } + + const now = Date.now(); + if (now < item.expiresAt) { + return { + value: item.value, + remainingTime: item.expiresAt - now + }; + } + + localStorage.removeItem(key); + return null; + + } catch (error) { + console.error("Cache retrieval error:", error); + try { + localStorage.removeItem(key); + } catch (removeError) { + console.error("Failed to remove invalid cache entry:", removeError); + } + return null; + } +}, cleanup: function(aggressive = false) { const now = Date.now(); @@ -1001,37 +1001,6 @@ function filterAndSortData() { return filteredData; } -function getPriceWithFallback(coin, latestPrices) { - const getPriceKey = (coin) => { - const lowerCoin = coin.toLowerCase(); - if (lowerCoin === 'firo' || lowerCoin === 'zcoin') { - return 'zcoin'; - } - if (lowerCoin === 'bitcoin cash') { - return 'bitcoin-cash'; - } - if (lowerCoin === 'particl anon' || lowerCoin === 'particl blind') { - return 'particl'; - } - return coinNameToSymbol[coin] || lowerCoin; - }; - - const priceKey = getPriceKey(coin); - const livePrice = latestPrices[priceKey]?.usd; - if (livePrice !== undefined && livePrice !== null) { - return livePrice; - } - - if (window.tableRateModule) { - const fallback = window.tableRateModule.getFallbackValue(priceKey); - if (fallback !== null) { - return fallback; - } - } - - return null; -} - async function calculateProfitLoss(fromCoin, toCoin, fromAmount, toAmount, isOwnOffer) { return new Promise((resolve) => { if (!latestPrices) { @@ -1136,7 +1105,7 @@ async function fetchLatestPrices() { try { console.log('Initiating fresh price data fetch...'); const existingCache = CacheManager.get(PRICES_CACHE_KEY, true); - let fallbackData = existingCache ? existingCache.value : null; + const fallbackData = existingCache ? existingCache.value : null; const url = `${offersConfig.apiEndpoints.coinGecko}/simple/price?ids=bitcoin,bitcoin-cash,dash,dogecoin,decred,litecoin,particl,pivx,monero,zano,wownero,zcoin&vs_currencies=USD,BTC&api_key=${offersConfig.apiKeys.coinGecko}`; const response = await fetch('/json/readurl', { method: 'POST', diff --git a/basicswap/static/js/pricechart.js b/basicswap/static/js/pricechart.js index 6a50f56..dbda0b7 100644 --- a/basicswap/static/js/pricechart.js +++ b/basicswap/static/js/pricechart.js @@ -156,7 +156,7 @@ const api = { .join(','); const url = `${config.apiEndpoints.coinGecko}/simple/price?ids=${coinIds}&vs_currencies=usd,btc&include_24hr_vol=true&include_24hr_change=true&api_key=${config.apiKeys.coinGecko}`; - + const response = await api.makePostRequest(url, { 'User-Agent': 'Mozilla/5.0', 'Accept': 'application/json', @@ -283,28 +283,28 @@ const rateLimiter = { cryptocompare: 1000 }, requestQueue: {}, - + canMakeRequest: function(apiName) { const now = Date.now(); const lastRequest = this.lastRequestTime[apiName] || 0; return (now - lastRequest) >= this.minRequestInterval[apiName]; }, - + updateLastRequestTime: function(apiName) { this.lastRequestTime[apiName] = Date.now(); }, - + getWaitTime: function(apiName) { const now = Date.now(); const lastRequest = this.lastRequestTime[apiName] || 0; return Math.max(0, this.minRequestInterval[apiName] - (now - lastRequest)); }, - + queueRequest: async function(apiName, requestFn) { if (!this.requestQueue[apiName]) { this.requestQueue[apiName] = Promise.resolve(); } - + try { await this.requestQueue[apiName]; @@ -313,11 +313,11 @@ const rateLimiter = { if (waitTime > 0) { await new Promise(resolve => setTimeout(resolve, waitTime)); } - + this.updateLastRequestTime(apiName); return await requestFn(); }; - + this.requestQueue[apiName] = executeRequest(); return await this.requestQueue[apiName]; @@ -397,7 +397,7 @@ displayCoinData: (coin, data) => { if (coin === 'BTC') { btcPriceDiv.style.display = 'none'; } else { - priceBtcElement.textContent = isError ? 'N/A' : `${priceBTC.toFixed(8)}`; + priceBtcElement.textContent = isError ? 'N/A' : `${priceBTC.toFixed(8)} BTC`; btcPriceDiv.style.display = 'flex'; } } @@ -419,8 +419,9 @@ displayCoinData: (coin, data) => { } updateUI(false); } catch (error) { - updateUI(true); - } + logger.error('Failed to parse cache item:', error.message); + localStorage.removeItem(key); +} }, showLoader: () => { @@ -525,7 +526,7 @@ displayCoinData: (coin, data) => { if (price < 0.001) return price.toFixed(8); if (price < 1) return price.toFixed(4); if (price < 1000) return price.toFixed(2); - return price.toFixed(0); + return price.toFixed(1); }, setActiveContainer: (containerId) => { @@ -1002,7 +1003,6 @@ const app = { await chartModule.updateChart('BTC'); app.updateResolutionButtons('BTC'); - const chartTitle = document.getElementById('chart-title'); if (chartTitle) { chartTitle.textContent = 'Price Chart (BTC)'; @@ -1210,7 +1210,7 @@ setupEventListeners: () => { app.isRefreshing = true; ui.showLoader(); chartModule.showChartLoader(); - + try { ui.hideErrorMessage(); cache.clear(); @@ -1237,13 +1237,13 @@ setupEventListeners: () => { if (!coinData) { throw new Error(`No data received`); } - + coinData.displayName = coin.displayName || coin.symbol; ui.displayCoinData(coin.symbol, coinData); const cacheKey = `coinData_${coin.symbol}`; cache.set(cacheKey, coinData); - + } catch (coinError) { console.warn(`Failed to update ${coin.symbol}: ${coinError.message}`); failedCoins.push(coin.symbol); @@ -1270,7 +1270,7 @@ setupEventListeners: () => { let countdown = 5; ui.displayErrorMessage(`${failureMessage} (${countdown}s)`); - + const countdownInterval = setInterval(() => { countdown--; if (countdown > 0) { @@ -1468,7 +1468,7 @@ sortTable: (columnIndex) => { } }; return (parseTime(bValue) - parseTime(aValue)) * sortOrder; - + case 5: // Rate case 6: // Market +/- aValue = getSafeTextContent(a.cells[columnIndex]); @@ -1478,13 +1478,13 @@ sortTable: (columnIndex) => { aValue = parseFloat(aValue.replace(/[^\d.-]/g, '') || '0'); bValue = parseFloat(bValue.replace(/[^\d.-]/g, '') || '0'); return (aValue - bValue) * sortOrder; - + case 7: // Trade const aCell = a.cells[columnIndex]; const bCell = b.cells[columnIndex]; //console.log('aCell:', aCell ? aCell.outerHTML : 'null'); //console.log('bCell:', bCell ? bCell.outerHTML : 'null'); - + aValue = getSafeTextContent(aCell.querySelector('a')) || getSafeTextContent(aCell.querySelector('button')) || getSafeTextContent(aCell); @@ -1494,14 +1494,14 @@ sortTable: (columnIndex) => { aValue = aValue.toLowerCase(); bValue = bValue.toLowerCase(); - + //console.log(`Comparing trade actions: "${aValue}" vs "${bValue}"`); - + if (aValue === bValue) return 0; if (aValue === "swap") return -1 * sortOrder; if (bValue === "swap") return 1 * sortOrder; return aValue.localeCompare(bValue) * sortOrder; - + default: aValue = getSafeTextContent(a.cells[columnIndex]); bValue = getSafeTextContent(b.cells[columnIndex]);