mirror of
https://github.com/basicswap/basicswap.git
synced 2025-05-04 11:52:18 +00:00
commit
0171ad6889
2 changed files with 64 additions and 95 deletions
basicswap/static/js
|
@ -497,48 +497,48 @@ const CacheManager = {
|
||||||
},
|
},
|
||||||
|
|
||||||
get: function(key) {
|
get: function(key) {
|
||||||
try {
|
try {
|
||||||
const itemStr = localStorage.getItem(key);
|
const itemStr = localStorage.getItem(key);
|
||||||
if (!itemStr) {
|
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);
|
|
||||||
}
|
|
||||||
return null;
|
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) {
|
cleanup: function(aggressive = false) {
|
||||||
const now = Date.now();
|
const now = Date.now();
|
||||||
|
@ -1001,37 +1001,6 @@ function filterAndSortData() {
|
||||||
return filteredData;
|
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) {
|
async function calculateProfitLoss(fromCoin, toCoin, fromAmount, toAmount, isOwnOffer) {
|
||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
if (!latestPrices) {
|
if (!latestPrices) {
|
||||||
|
@ -1136,7 +1105,7 @@ async function fetchLatestPrices() {
|
||||||
try {
|
try {
|
||||||
console.log('Initiating fresh price data fetch...');
|
console.log('Initiating fresh price data fetch...');
|
||||||
const existingCache = CacheManager.get(PRICES_CACHE_KEY, true);
|
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 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', {
|
const response = await fetch('/json/readurl', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
|
|
|
@ -156,7 +156,7 @@ const api = {
|
||||||
.join(',');
|
.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 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, {
|
const response = await api.makePostRequest(url, {
|
||||||
'User-Agent': 'Mozilla/5.0',
|
'User-Agent': 'Mozilla/5.0',
|
||||||
'Accept': 'application/json',
|
'Accept': 'application/json',
|
||||||
|
@ -283,28 +283,28 @@ const rateLimiter = {
|
||||||
cryptocompare: 1000
|
cryptocompare: 1000
|
||||||
},
|
},
|
||||||
requestQueue: {},
|
requestQueue: {},
|
||||||
|
|
||||||
canMakeRequest: function(apiName) {
|
canMakeRequest: function(apiName) {
|
||||||
const now = Date.now();
|
const now = Date.now();
|
||||||
const lastRequest = this.lastRequestTime[apiName] || 0;
|
const lastRequest = this.lastRequestTime[apiName] || 0;
|
||||||
return (now - lastRequest) >= this.minRequestInterval[apiName];
|
return (now - lastRequest) >= this.minRequestInterval[apiName];
|
||||||
},
|
},
|
||||||
|
|
||||||
updateLastRequestTime: function(apiName) {
|
updateLastRequestTime: function(apiName) {
|
||||||
this.lastRequestTime[apiName] = Date.now();
|
this.lastRequestTime[apiName] = Date.now();
|
||||||
},
|
},
|
||||||
|
|
||||||
getWaitTime: function(apiName) {
|
getWaitTime: function(apiName) {
|
||||||
const now = Date.now();
|
const now = Date.now();
|
||||||
const lastRequest = this.lastRequestTime[apiName] || 0;
|
const lastRequest = this.lastRequestTime[apiName] || 0;
|
||||||
return Math.max(0, this.minRequestInterval[apiName] - (now - lastRequest));
|
return Math.max(0, this.minRequestInterval[apiName] - (now - lastRequest));
|
||||||
},
|
},
|
||||||
|
|
||||||
queueRequest: async function(apiName, requestFn) {
|
queueRequest: async function(apiName, requestFn) {
|
||||||
if (!this.requestQueue[apiName]) {
|
if (!this.requestQueue[apiName]) {
|
||||||
this.requestQueue[apiName] = Promise.resolve();
|
this.requestQueue[apiName] = Promise.resolve();
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await this.requestQueue[apiName];
|
await this.requestQueue[apiName];
|
||||||
|
|
||||||
|
@ -313,11 +313,11 @@ const rateLimiter = {
|
||||||
if (waitTime > 0) {
|
if (waitTime > 0) {
|
||||||
await new Promise(resolve => setTimeout(resolve, waitTime));
|
await new Promise(resolve => setTimeout(resolve, waitTime));
|
||||||
}
|
}
|
||||||
|
|
||||||
this.updateLastRequestTime(apiName);
|
this.updateLastRequestTime(apiName);
|
||||||
return await requestFn();
|
return await requestFn();
|
||||||
};
|
};
|
||||||
|
|
||||||
this.requestQueue[apiName] = executeRequest();
|
this.requestQueue[apiName] = executeRequest();
|
||||||
return await this.requestQueue[apiName];
|
return await this.requestQueue[apiName];
|
||||||
|
|
||||||
|
@ -397,7 +397,7 @@ displayCoinData: (coin, data) => {
|
||||||
if (coin === 'BTC') {
|
if (coin === 'BTC') {
|
||||||
btcPriceDiv.style.display = 'none';
|
btcPriceDiv.style.display = 'none';
|
||||||
} else {
|
} else {
|
||||||
priceBtcElement.textContent = isError ? 'N/A' : `${priceBTC.toFixed(8)}`;
|
priceBtcElement.textContent = isError ? 'N/A' : `${priceBTC.toFixed(8)} BTC`;
|
||||||
btcPriceDiv.style.display = 'flex';
|
btcPriceDiv.style.display = 'flex';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -419,8 +419,9 @@ displayCoinData: (coin, data) => {
|
||||||
}
|
}
|
||||||
updateUI(false);
|
updateUI(false);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
updateUI(true);
|
logger.error('Failed to parse cache item:', error.message);
|
||||||
}
|
localStorage.removeItem(key);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
showLoader: () => {
|
showLoader: () => {
|
||||||
|
@ -525,7 +526,7 @@ displayCoinData: (coin, data) => {
|
||||||
if (price < 0.001) return price.toFixed(8);
|
if (price < 0.001) return price.toFixed(8);
|
||||||
if (price < 1) return price.toFixed(4);
|
if (price < 1) return price.toFixed(4);
|
||||||
if (price < 1000) return price.toFixed(2);
|
if (price < 1000) return price.toFixed(2);
|
||||||
return price.toFixed(0);
|
return price.toFixed(1);
|
||||||
},
|
},
|
||||||
|
|
||||||
setActiveContainer: (containerId) => {
|
setActiveContainer: (containerId) => {
|
||||||
|
@ -1002,7 +1003,6 @@ const app = {
|
||||||
await chartModule.updateChart('BTC');
|
await chartModule.updateChart('BTC');
|
||||||
app.updateResolutionButtons('BTC');
|
app.updateResolutionButtons('BTC');
|
||||||
|
|
||||||
|
|
||||||
const chartTitle = document.getElementById('chart-title');
|
const chartTitle = document.getElementById('chart-title');
|
||||||
if (chartTitle) {
|
if (chartTitle) {
|
||||||
chartTitle.textContent = 'Price Chart (BTC)';
|
chartTitle.textContent = 'Price Chart (BTC)';
|
||||||
|
@ -1210,7 +1210,7 @@ setupEventListeners: () => {
|
||||||
app.isRefreshing = true;
|
app.isRefreshing = true;
|
||||||
ui.showLoader();
|
ui.showLoader();
|
||||||
chartModule.showChartLoader();
|
chartModule.showChartLoader();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
ui.hideErrorMessage();
|
ui.hideErrorMessage();
|
||||||
cache.clear();
|
cache.clear();
|
||||||
|
@ -1237,13 +1237,13 @@ setupEventListeners: () => {
|
||||||
if (!coinData) {
|
if (!coinData) {
|
||||||
throw new Error(`No data received`);
|
throw new Error(`No data received`);
|
||||||
}
|
}
|
||||||
|
|
||||||
coinData.displayName = coin.displayName || coin.symbol;
|
coinData.displayName = coin.displayName || coin.symbol;
|
||||||
ui.displayCoinData(coin.symbol, coinData);
|
ui.displayCoinData(coin.symbol, coinData);
|
||||||
|
|
||||||
const cacheKey = `coinData_${coin.symbol}`;
|
const cacheKey = `coinData_${coin.symbol}`;
|
||||||
cache.set(cacheKey, coinData);
|
cache.set(cacheKey, coinData);
|
||||||
|
|
||||||
} catch (coinError) {
|
} catch (coinError) {
|
||||||
console.warn(`Failed to update ${coin.symbol}: ${coinError.message}`);
|
console.warn(`Failed to update ${coin.symbol}: ${coinError.message}`);
|
||||||
failedCoins.push(coin.symbol);
|
failedCoins.push(coin.symbol);
|
||||||
|
@ -1270,7 +1270,7 @@ setupEventListeners: () => {
|
||||||
|
|
||||||
let countdown = 5;
|
let countdown = 5;
|
||||||
ui.displayErrorMessage(`${failureMessage} (${countdown}s)`);
|
ui.displayErrorMessage(`${failureMessage} (${countdown}s)`);
|
||||||
|
|
||||||
const countdownInterval = setInterval(() => {
|
const countdownInterval = setInterval(() => {
|
||||||
countdown--;
|
countdown--;
|
||||||
if (countdown > 0) {
|
if (countdown > 0) {
|
||||||
|
@ -1468,7 +1468,7 @@ sortTable: (columnIndex) => {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
return (parseTime(bValue) - parseTime(aValue)) * sortOrder;
|
return (parseTime(bValue) - parseTime(aValue)) * sortOrder;
|
||||||
|
|
||||||
case 5: // Rate
|
case 5: // Rate
|
||||||
case 6: // Market +/-
|
case 6: // Market +/-
|
||||||
aValue = getSafeTextContent(a.cells[columnIndex]);
|
aValue = getSafeTextContent(a.cells[columnIndex]);
|
||||||
|
@ -1478,13 +1478,13 @@ sortTable: (columnIndex) => {
|
||||||
aValue = parseFloat(aValue.replace(/[^\d.-]/g, '') || '0');
|
aValue = parseFloat(aValue.replace(/[^\d.-]/g, '') || '0');
|
||||||
bValue = parseFloat(bValue.replace(/[^\d.-]/g, '') || '0');
|
bValue = parseFloat(bValue.replace(/[^\d.-]/g, '') || '0');
|
||||||
return (aValue - bValue) * sortOrder;
|
return (aValue - bValue) * sortOrder;
|
||||||
|
|
||||||
case 7: // Trade
|
case 7: // Trade
|
||||||
const aCell = a.cells[columnIndex];
|
const aCell = a.cells[columnIndex];
|
||||||
const bCell = b.cells[columnIndex];
|
const bCell = b.cells[columnIndex];
|
||||||
//console.log('aCell:', aCell ? aCell.outerHTML : 'null');
|
//console.log('aCell:', aCell ? aCell.outerHTML : 'null');
|
||||||
//console.log('bCell:', bCell ? bCell.outerHTML : 'null');
|
//console.log('bCell:', bCell ? bCell.outerHTML : 'null');
|
||||||
|
|
||||||
aValue = getSafeTextContent(aCell.querySelector('a')) ||
|
aValue = getSafeTextContent(aCell.querySelector('a')) ||
|
||||||
getSafeTextContent(aCell.querySelector('button')) ||
|
getSafeTextContent(aCell.querySelector('button')) ||
|
||||||
getSafeTextContent(aCell);
|
getSafeTextContent(aCell);
|
||||||
|
@ -1494,14 +1494,14 @@ sortTable: (columnIndex) => {
|
||||||
|
|
||||||
aValue = aValue.toLowerCase();
|
aValue = aValue.toLowerCase();
|
||||||
bValue = bValue.toLowerCase();
|
bValue = bValue.toLowerCase();
|
||||||
|
|
||||||
//console.log(`Comparing trade actions: "${aValue}" vs "${bValue}"`);
|
//console.log(`Comparing trade actions: "${aValue}" vs "${bValue}"`);
|
||||||
|
|
||||||
if (aValue === bValue) return 0;
|
if (aValue === bValue) return 0;
|
||||||
if (aValue === "swap") return -1 * sortOrder;
|
if (aValue === "swap") return -1 * sortOrder;
|
||||||
if (bValue === "swap") return 1 * sortOrder;
|
if (bValue === "swap") return 1 * sortOrder;
|
||||||
return aValue.localeCompare(bValue) * sortOrder;
|
return aValue.localeCompare(bValue) * sortOrder;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
aValue = getSafeTextContent(a.cells[columnIndex]);
|
aValue = getSafeTextContent(a.cells[columnIndex]);
|
||||||
bValue = getSafeTextContent(b.cells[columnIndex]);
|
bValue = getSafeTextContent(b.cells[columnIndex]);
|
||||||
|
|
Loading…
Reference in a new issue