diff --git a/basicswap/static/js/offerstable.js b/basicswap/static/js/offerstable.js
index db64b3b..e7fad33 100644
--- a/basicswap/static/js/offerstable.js
+++ b/basicswap/static/js/offerstable.js
@@ -21,6 +21,14 @@ const PRICE_INIT_RETRIES = 3;
const PRICE_INIT_RETRY_DELAY = 2000;
const isSentOffers = window.offersTableConfig.isSentOffers;
+const offersConfig = {
+ apiEndpoints: {
+ coinGecko: 'https://api.coingecko.com/api/v3',
+ cryptoCompare: 'https://min-api.cryptocompare.com/data'
+ },
+ apiKeys: getAPIKeys()
+};
+
// MAPPING OBJECTS
const coinNameToSymbol = {
'Bitcoin': 'bitcoin',
@@ -251,7 +259,7 @@ const WebSocketManager = {
handleMessage(message) {
if (this.messageQueue.length >= this.maxQueueSize) {
- console.warn('⚠Message queue full, dropping oldest message');
+ console.warn('Message queue full, dropping oldest message');
this.messageQueue.shift();
}
@@ -260,7 +268,7 @@ const WebSocketManager = {
this.debounceTimeout = setTimeout(() => {
this.processMessageQueue();
- }, 250);
+ }, 200);
},
async processMessageQueue() {
@@ -1011,6 +1019,7 @@ async function getMarketRate(fromCoin, toCoin) {
async function fetchLatestPrices() {
const PRICES_CACHE_KEY = 'prices_coingecko';
+ const apiKeys = getAPIKeys();
const cachedData = CacheManager.get(PRICES_CACHE_KEY);
if (cachedData && cachedData.remainingTime > 60000) {
@@ -1019,10 +1028,10 @@ async function fetchLatestPrices() {
return cachedData.value;
}
- const url = `${config.apiEndpoints.coinGecko}/simple/price?ids=bitcoin,bitcoin-cash,dash,dogecoin,decred,litecoin,particl,pivx,monero,zano,wownero,zcoin&vs_currencies=USD,BTC&api_key=${config.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}`;
try {
- console.log('Fetching fresh price data...');
+ console.log('Initiating fresh price data fetch...');
const response = await fetch('/json/readurl', {
method: 'POST',
headers: {
@@ -1039,31 +1048,37 @@ async function fetchLatestPrices() {
}
const data = await response.json();
+
if (data.Error) {
+ console.error('API Error:', data.Error);
throw new Error(data.Error);
}
if (data && Object.keys(data).length > 0) {
- console.log('Fresh price data received');
-
+ console.log('Processing fresh price data...');
latestPrices = data;
-
CacheManager.set(PRICES_CACHE_KEY, data, CACHE_DURATION);
-
+ const fallbackLog = {};
Object.entries(data).forEach(([coin, prices]) => {
tableRateModule.setFallbackValue(coin, prices.usd);
+ fallbackLog[coin] = prices.usd;
});
-
+
+ //console.log('Fallback Values Set:', fallbackLog);
+
return data;
} else {
- //console.warn('Received empty price data');
+ console.warn('No price data received');
+ return null;
}
} catch (error) {
- //console.error('Error fetching prices:', error);
+ console.error('Price Fetch Error:', {
+ message: error.message,
+ name: error.name,
+ stack: error.stack
+ });
throw error;
}
-
- return latestPrices || null;
}
async function fetchOffers(manualRefresh = false) {
@@ -1312,7 +1327,6 @@ function updateClearFiltersButton() {
clearButton.classList.toggle('opacity-50', !hasFilters);
clearButton.disabled = !hasFilters;
- // Update button styles based on state
if (hasFilters) {
clearButton.classList.add('hover:bg-green-600', 'hover:text-white');
clearButton.classList.remove('cursor-not-allowed');
@@ -1323,6 +1337,19 @@ function updateClearFiltersButton() {
}
}
+function cleanupRow(row) {
+ const tooltips = row.querySelectorAll('[data-tooltip-target]');
+ const count = tooltips.length;
+ tooltips.forEach(tooltip => {
+ const tooltipId = tooltip.getAttribute('data-tooltip-target');
+ const tooltipElement = document.getElementById(tooltipId);
+ if (tooltipElement) {
+ tooltipElement.remove();
+ }
+ });
+ //console.log(`Cleaned up ${count} tooltips from row`);
+}
+
function handleNoOffersScenario() {
const formData = new FormData(filterForm);
const filters = Object.fromEntries(formData);
@@ -1332,6 +1359,11 @@ function handleNoOffersScenario() {
stopRefreshAnimation();
+ const existingRows = offersBody.querySelectorAll('tr');
+ existingRows.forEach(row => {
+ cleanupRow(row);
+ });
+
if (hasActiveFilters) {
offersBody.innerHTML = `
@@ -1355,80 +1387,96 @@ function handleNoOffersScenario() {
}
async function updateOffersTable() {
- try {
- const PRICES_CACHE_KEY = 'prices_coingecko';
- const cachedPrices = CacheManager.get(PRICES_CACHE_KEY);
+ try {
+ const PRICES_CACHE_KEY = 'prices_coingecko';
+ const cachedPrices = CacheManager.get(PRICES_CACHE_KEY);
- if (!cachedPrices || !cachedPrices.remainingTime || cachedPrices.remainingTime < 60000) {
- console.log('Fetching fresh price data...');
- const priceData = await fetchLatestPrices();
- if (priceData) {
- latestPrices = priceData;
- }
- } else {
- latestPrices = cachedPrices.value;
- }
+ if (!cachedPrices || !cachedPrices.remainingTime || cachedPrices.remainingTime < 60000) {
+ console.log('Fetching fresh price data...');
+ const priceData = await fetchLatestPrices();
+ if (priceData) {
+ latestPrices = priceData;
+ }
+ } else {
+ latestPrices = cachedPrices.value;
+ }
- const validOffers = getValidOffers();
+ const validOffers = getValidOffers();
- const startIndex = (currentPage - 1) * itemsPerPage;
- const endIndex = Math.min(startIndex + itemsPerPage, validOffers.length);
- const itemsToDisplay = validOffers.slice(startIndex, endIndex);
+ if (!isSentOffers) {
+ const networkOffersSpan = document.querySelector('a[href="/offers"] span.inline-flex.justify-center');
+ if (networkOffersSpan) {
+ networkOffersSpan.textContent = validOffers.length;
+ }
+ }
- const identityPromises = itemsToDisplay.map(offer =>
- offer.addr_from ? getIdentityData(offer.addr_from) : Promise.resolve(null)
- );
+ const startIndex = (currentPage - 1) * itemsPerPage;
+ const endIndex = Math.min(startIndex + itemsPerPage, validOffers.length);
+ const itemsToDisplay = validOffers.slice(startIndex, endIndex);
- const identities = await Promise.all(identityPromises);
+ const identityPromises = itemsToDisplay.map(offer =>
+ offer.addr_from ? getIdentityData(offer.addr_from) : Promise.resolve(null)
+ );
- if (validOffers.length === 0) {
- handleNoOffersScenario();
- return;
- }
+ const identities = await Promise.all(identityPromises);
- const totalPages = Math.max(1, Math.ceil(validOffers.length / itemsPerPage));
- currentPage = Math.min(currentPage, totalPages);
+ if (validOffers.length === 0) {
+ const existingRows = offersBody.querySelectorAll('tr');
+ existingRows.forEach(row => {
+ cleanupRow(row);
+ });
+ handleNoOffersScenario();
+ return;
+ }
- const fragment = document.createDocumentFragment();
+ const totalPages = Math.max(1, Math.ceil(validOffers.length / itemsPerPage));
+ currentPage = Math.min(currentPage, totalPages);
- itemsToDisplay.forEach((offer, index) => {
- const identity = identities[index];
- const row = createTableRow(offer, identity);
- if (row) {
- fragment.appendChild(row);
- }
- });
+ const fragment = document.createDocumentFragment();
- offersBody.innerHTML = '';
- offersBody.appendChild(fragment);
+ const existingRows = offersBody.querySelectorAll('tr');
+ existingRows.forEach(row => {
+ cleanupRow(row);
+ });
- requestAnimationFrame(() => {
- initializeFlowbiteTooltips();
- updateRowTimes();
- updatePaginationControls(totalPages);
+ itemsToDisplay.forEach((offer, index) => {
+ const identity = identities[index];
+ const row = createTableRow(offer, identity);
+ if (row) {
+ fragment.appendChild(row);
+ }
+ });
- if (tableRateModule?.initializeTable) {
- tableRateModule.initializeTable();
- }
- });
+ offersBody.textContent = '';
+ offersBody.appendChild(fragment);
- lastRefreshTime = Date.now();
- if (newEntriesCountSpan) {
- newEntriesCountSpan.textContent = validOffers.length;
- }
- if (lastRefreshTimeSpan) {
- lastRefreshTimeSpan.textContent = new Date(lastRefreshTime).toLocaleTimeString();
- }
+ requestAnimationFrame(() => {
+ initializeFlowbiteTooltips();
+ updateRowTimes();
+ updatePaginationControls(totalPages);
- } catch (error) {
- console.error('[Debug] Error in updateOffersTable:', error);
- offersBody.innerHTML = `
-
-
- An error occurred while updating the offers table. Please try again later.
- |
-
`;
- }
+ if (tableRateModule?.initializeTable) {
+ tableRateModule.initializeTable();
+ }
+ });
+
+ lastRefreshTime = Date.now();
+ if (newEntriesCountSpan) {
+ newEntriesCountSpan.textContent = validOffers.length;
+ }
+ if (lastRefreshTimeSpan) {
+ lastRefreshTimeSpan.textContent = new Date(lastRefreshTime).toLocaleTimeString();
+ }
+
+ } catch (error) {
+ console.error('[Debug] Error in updateOffersTable:', error);
+ offersBody.innerHTML = `
+
+
+ An error occurred while updating the offers table. Please try again later.
+ |
+
`;
+ }
}
async function getIdentityData(address) {
diff --git a/basicswap/static/js/pricechart.js b/basicswap/static/js/pricechart.js
index 6657819..d1712d6 100644
--- a/basicswap/static/js/pricechart.js
+++ b/basicswap/static/js/pricechart.js
@@ -38,13 +38,6 @@ const config = {
currentResolution: 'year'
};
-function getAPIKeys() {
- return {
- cryptoCompare: '{{chart_api_key}}',
- coinGecko: '{{coingecko_api_key}}'
- };
-}
-
// UTILS
const utils = {
formatNumber: (number, decimals = 2) =>
@@ -86,8 +79,9 @@ const logger = {
// API
const api = {
- makePostRequest: (url, headers = {}) => {
- return new Promise((resolve, reject) => {
+ makePostRequest: (url, headers = {}) => {
+ const apiKeys = getAPIKeys();
+ return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.open('POST', '/json/readurl');
xhr.setRequestHeader('Content-Type', 'application/json');
@@ -147,8 +141,8 @@ const api = {
.map(coin => coin.name)
.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}`;
-
- console.log(`Fetching data for multiple coins from CoinGecko: ${url}`);
+
+ //console.log(`Fetching data for multiple coins from CoinGecko: ${url}`);
try {
const data = await api.makePostRequest(url);
@@ -675,7 +669,7 @@ const chartModule = {
plugins: [chartModule.verticalLinePlugin]
});
- console.log('Chart initialized:', chartModule.chart);
+ //console.log('Chart initialized:', chartModule.chart);
},
prepareChartData: (coinSymbol, data) => {
diff --git a/basicswap/templates/offers.html b/basicswap/templates/offers.html
index 4b663de..65af777 100644
--- a/basicswap/templates/offers.html
+++ b/basicswap/templates/offers.html
@@ -11,15 +11,15 @@