mirror of
https://github.com/basicswap/basicswap.git
synced 2025-11-05 10:28:10 +01:00
js: eslints
This commit is contained in:
@@ -97,7 +97,7 @@ const EventManager = {
|
|||||||
|
|
||||||
add(element, type, handler, options = false) {
|
add(element, type, handler, options = false) {
|
||||||
if (!element) return null;
|
if (!element) return null;
|
||||||
|
|
||||||
if (!this.listeners.has(element)) {
|
if (!this.listeners.has(element)) {
|
||||||
this.listeners.set(element, new Map());
|
this.listeners.set(element, new Map());
|
||||||
}
|
}
|
||||||
@@ -116,7 +116,7 @@ const EventManager = {
|
|||||||
|
|
||||||
remove(element, type, handler, options = false) {
|
remove(element, type, handler, options = false) {
|
||||||
if (!element) return;
|
if (!element) return;
|
||||||
|
|
||||||
const elementListeners = this.listeners.get(element);
|
const elementListeners = this.listeners.get(element);
|
||||||
if (!elementListeners) return;
|
if (!elementListeners) return;
|
||||||
|
|
||||||
@@ -140,7 +140,7 @@ const EventManager = {
|
|||||||
|
|
||||||
removeAll(element) {
|
removeAll(element) {
|
||||||
if (!element) return;
|
if (!element) return;
|
||||||
|
|
||||||
const elementListeners = this.listeners.get(element);
|
const elementListeners = this.listeners.get(element);
|
||||||
if (!elementListeners) return;
|
if (!elementListeners) return;
|
||||||
|
|
||||||
@@ -167,7 +167,7 @@ const EventManager = {
|
|||||||
|
|
||||||
function cleanup() {
|
function cleanup() {
|
||||||
//console.log('Starting comprehensive cleanup process for bids table');
|
//console.log('Starting comprehensive cleanup process for bids table');
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (searchTimeout) {
|
if (searchTimeout) {
|
||||||
clearTimeout(searchTimeout);
|
clearTimeout(searchTimeout);
|
||||||
@@ -184,7 +184,7 @@ function cleanup() {
|
|||||||
|
|
||||||
cleanupTooltips();
|
cleanupTooltips();
|
||||||
forceTooltipDOMCleanup();
|
forceTooltipDOMCleanup();
|
||||||
|
|
||||||
if (window.TooltipManager) {
|
if (window.TooltipManager) {
|
||||||
window.TooltipManager.cleanup();
|
window.TooltipManager.cleanup();
|
||||||
}
|
}
|
||||||
@@ -237,12 +237,12 @@ function cleanup() {
|
|||||||
sent: [],
|
sent: [],
|
||||||
received: []
|
received: []
|
||||||
};
|
};
|
||||||
|
|
||||||
state.currentPage = {
|
state.currentPage = {
|
||||||
sent: 1,
|
sent: 1,
|
||||||
received: 1
|
received: 1
|
||||||
};
|
};
|
||||||
|
|
||||||
state.isLoading = false;
|
state.isLoading = false;
|
||||||
state.isRefreshing = false;
|
state.isRefreshing = false;
|
||||||
state.wsConnected = false;
|
state.wsConnected = false;
|
||||||
@@ -310,7 +310,7 @@ CleanupManager.addListener(document, 'visibilitychange', () => {
|
|||||||
if (window.TooltipManager && typeof window.TooltipManager.cleanup === 'function') {
|
if (window.TooltipManager && typeof window.TooltipManager.cleanup === 'function') {
|
||||||
window.TooltipManager.cleanup();
|
window.TooltipManager.cleanup();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Run memory optimization
|
// Run memory optimization
|
||||||
if (window.MemoryManager) {
|
if (window.MemoryManager) {
|
||||||
MemoryManager.forceCleanup();
|
MemoryManager.forceCleanup();
|
||||||
@@ -326,7 +326,7 @@ CleanupManager.addListener(document, 'visibilitychange', () => {
|
|||||||
const lastUpdateTime = state.lastRefresh || 0;
|
const lastUpdateTime = state.lastRefresh || 0;
|
||||||
const now = Date.now();
|
const now = Date.now();
|
||||||
const refreshInterval = 5 * 60 * 1000; // 5 minutes
|
const refreshInterval = 5 * 60 * 1000; // 5 minutes
|
||||||
|
|
||||||
if (now - lastUpdateTime > refreshInterval) {
|
if (now - lastUpdateTime > refreshInterval) {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
updateBidsTable();
|
updateBidsTable();
|
||||||
@@ -366,7 +366,7 @@ function cleanupRow(row) {
|
|||||||
|
|
||||||
function optimizeMemoryUsage() {
|
function optimizeMemoryUsage() {
|
||||||
const MAX_BIDS_IN_MEMORY = 500;
|
const MAX_BIDS_IN_MEMORY = 500;
|
||||||
|
|
||||||
['sent', 'received'].forEach(type => {
|
['sent', 'received'].forEach(type => {
|
||||||
if (state.data[type] && state.data[type].length > MAX_BIDS_IN_MEMORY) {
|
if (state.data[type] && state.data[type].length > MAX_BIDS_IN_MEMORY) {
|
||||||
console.log(`Trimming ${type} bids data from ${state.data[type].length} to ${MAX_BIDS_IN_MEMORY}`);
|
console.log(`Trimming ${type} bids data from ${state.data[type].length} to ${MAX_BIDS_IN_MEMORY}`);
|
||||||
@@ -581,7 +581,7 @@ function filterAndSortData(bids) {
|
|||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.warn('Error accessing identity for search:', e);
|
console.warn('Error accessing identity for search:', e);
|
||||||
}
|
}
|
||||||
|
|
||||||
const matchesLabel = label.toLowerCase().includes(searchStr);
|
const matchesLabel = label.toLowerCase().includes(searchStr);
|
||||||
|
|
||||||
let matchesDisplayedLabel = false;
|
let matchesDisplayedLabel = false;
|
||||||
@@ -589,7 +589,7 @@ function filterAndSortData(bids) {
|
|||||||
try {
|
try {
|
||||||
const tableId = state.currentTab === 'sent' ? 'sent' : 'received';
|
const tableId = state.currentTab === 'sent' ? 'sent' : 'received';
|
||||||
const cells = document.querySelectorAll(`#${tableId} a[href^="/identity/"]`);
|
const cells = document.querySelectorAll(`#${tableId} a[href^="/identity/"]`);
|
||||||
|
|
||||||
for (const cell of cells) {
|
for (const cell of cells) {
|
||||||
|
|
||||||
const href = cell.getAttribute('href');
|
const href = cell.getAttribute('href');
|
||||||
@@ -607,7 +607,7 @@ function filterAndSortData(bids) {
|
|||||||
console.warn('Error checking displayed labels:', e);
|
console.warn('Error checking displayed labels:', e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(matchesBidId || matchesIdentity || matchesLabel || matchesDisplayedLabel)) {
|
if (!(matchesBidId || matchesIdentity || matchesLabel || matchesDisplayedLabel)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -627,7 +627,7 @@ async function preloadIdentitiesForSearch(bids) {
|
|||||||
if (!window.IdentityManager || typeof IdentityManager.getIdentityData !== 'function') {
|
if (!window.IdentityManager || typeof IdentityManager.getIdentityData !== 'function') {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const addresses = new Set();
|
const addresses = new Set();
|
||||||
bids.forEach(bid => {
|
bids.forEach(bid => {
|
||||||
@@ -638,7 +638,7 @@ async function preloadIdentitiesForSearch(bids) {
|
|||||||
|
|
||||||
const BATCH_SIZE = 20;
|
const BATCH_SIZE = 20;
|
||||||
const addressArray = Array.from(addresses);
|
const addressArray = Array.from(addresses);
|
||||||
|
|
||||||
for (let i = 0; i < addressArray.length; i += BATCH_SIZE) {
|
for (let i = 0; i < addressArray.length; i += BATCH_SIZE) {
|
||||||
const batch = addressArray.slice(i, i + BATCH_SIZE);
|
const batch = addressArray.slice(i, i + BATCH_SIZE);
|
||||||
await Promise.all(batch.map(addr => IdentityManager.getIdentityData(addr)));
|
await Promise.all(batch.map(addr => IdentityManager.getIdentityData(addr)));
|
||||||
@@ -647,7 +647,7 @@ async function preloadIdentitiesForSearch(bids) {
|
|||||||
await new Promise(resolve => setTimeout(resolve, 10));
|
await new Promise(resolve => setTimeout(resolve, 10));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(`Preloaded ${addressArray.length} identities for search`);
|
console.log(`Preloaded ${addressArray.length} identities for search`);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error preloading identities:', error);
|
console.error('Error preloading identities:', error);
|
||||||
@@ -847,7 +847,7 @@ const createIdentityTooltipContent = (identity) => {
|
|||||||
`;
|
`;
|
||||||
};
|
};
|
||||||
|
|
||||||
let tooltipIdsToCleanup = new Set();
|
const tooltipIdsToCleanup = new Set();
|
||||||
|
|
||||||
const cleanupTooltips = () => {
|
const cleanupTooltips = () => {
|
||||||
if (window.TooltipManager) {
|
if (window.TooltipManager) {
|
||||||
@@ -869,7 +869,7 @@ const forceTooltipDOMCleanup = () => {
|
|||||||
foundCount += allTooltipElements.length;
|
foundCount += allTooltipElements.length;
|
||||||
|
|
||||||
allTooltipElements.forEach(element => {
|
allTooltipElements.forEach(element => {
|
||||||
const isDetached = !document.body.contains(element) ||
|
const isDetached = !document.body.contains(element) ||
|
||||||
element.classList.contains('hidden') ||
|
element.classList.contains('hidden') ||
|
||||||
element.style.display === 'none';
|
element.style.display === 'none';
|
||||||
|
|
||||||
@@ -877,7 +877,7 @@ const forceTooltipDOMCleanup = () => {
|
|||||||
const triggerId = element.id;
|
const triggerId = element.id;
|
||||||
const triggerElement = document.querySelector(`[data-tooltip-target="${triggerId}"]`);
|
const triggerElement = document.querySelector(`[data-tooltip-target="${triggerId}"]`);
|
||||||
|
|
||||||
if (!triggerElement ||
|
if (!triggerElement ||
|
||||||
!document.body.contains(triggerElement) ||
|
!document.body.contains(triggerElement) ||
|
||||||
triggerElement.classList.contains('hidden')) {
|
triggerElement.classList.contains('hidden')) {
|
||||||
element.remove();
|
element.remove();
|
||||||
@@ -899,7 +899,7 @@ const forceTooltipDOMCleanup = () => {
|
|||||||
const tippyRoots = document.querySelectorAll('[data-tippy-root]');
|
const tippyRoots = document.querySelectorAll('[data-tippy-root]');
|
||||||
foundCount += tippyRoots.length;
|
foundCount += tippyRoots.length;
|
||||||
tippyRoots.forEach(element => {
|
tippyRoots.forEach(element => {
|
||||||
const isOrphan = !element.children.length ||
|
const isOrphan = !element.children.length ||
|
||||||
element.children[0].classList.contains('hidden') ||
|
element.children[0].classList.contains('hidden') ||
|
||||||
!document.body.contains(element);
|
!document.body.contains(element);
|
||||||
|
|
||||||
@@ -926,7 +926,7 @@ const forceTooltipDOMCleanup = () => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
document.querySelectorAll('.tooltip').forEach(element => {
|
document.querySelectorAll('.tooltip').forEach(element => {
|
||||||
const isTrulyDetached = !element.parentElement ||
|
const isTrulyDetached = !element.parentElement ||
|
||||||
!document.body.contains(element.parentElement) ||
|
!document.body.contains(element.parentElement) ||
|
||||||
element.classList.contains('hidden');
|
element.classList.contains('hidden');
|
||||||
if (isTrulyDetached) {
|
if (isTrulyDetached) {
|
||||||
@@ -1108,7 +1108,7 @@ const updateTableContent = async (type) => {
|
|||||||
if (currentPageData.length > 0) {
|
if (currentPageData.length > 0) {
|
||||||
const BATCH_SIZE = 10;
|
const BATCH_SIZE = 10;
|
||||||
let allRows = [];
|
let allRows = [];
|
||||||
|
|
||||||
for (let i = 0; i < currentPageData.length; i += BATCH_SIZE) {
|
for (let i = 0; i < currentPageData.length; i += BATCH_SIZE) {
|
||||||
const batch = currentPageData.slice(i, i + BATCH_SIZE);
|
const batch = currentPageData.slice(i, i + BATCH_SIZE);
|
||||||
const rowPromises = batch.map(bid => createTableRow(bid));
|
const rowPromises = batch.map(bid => createTableRow(bid));
|
||||||
@@ -1166,7 +1166,7 @@ const initializeTooltips = () => {
|
|||||||
|
|
||||||
window.TooltipManager.cleanup();
|
window.TooltipManager.cleanup();
|
||||||
|
|
||||||
let selector = '#' + state.currentTab + ' [data-tooltip-target]';
|
const selector = '#' + state.currentTab + ' [data-tooltip-target]';
|
||||||
const tooltipTriggers = document.querySelectorAll(selector);
|
const tooltipTriggers = document.querySelectorAll(selector);
|
||||||
const tooltipCount = tooltipTriggers.length;
|
const tooltipCount = tooltipTriggers.length;
|
||||||
if (tooltipCount > 50) {
|
if (tooltipCount > 50) {
|
||||||
@@ -1187,7 +1187,7 @@ const initializeTooltips = () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const offscreenTooltips = Array.from(tooltipTriggers).filter(t => !viewportTooltips.includes(t));
|
const offscreenTooltips = Array.from(tooltipTriggers).filter(t => !viewportTooltips.includes(t));
|
||||||
|
|
||||||
offscreenTooltips.forEach(trigger => {
|
offscreenTooltips.forEach(trigger => {
|
||||||
const createTooltipOnHover = () => {
|
const createTooltipOnHover = () => {
|
||||||
createTooltipForTrigger(trigger);
|
createTooltipForTrigger(trigger);
|
||||||
@@ -1206,7 +1206,7 @@ const initializeTooltips = () => {
|
|||||||
|
|
||||||
const createTooltipForTrigger = (trigger) => {
|
const createTooltipForTrigger = (trigger) => {
|
||||||
if (!trigger || !window.TooltipManager) return;
|
if (!trigger || !window.TooltipManager) return;
|
||||||
|
|
||||||
const targetId = trigger.getAttribute('data-tooltip-target');
|
const targetId = trigger.getAttribute('data-tooltip-target');
|
||||||
const tooltipContent = document.getElementById(targetId);
|
const tooltipContent = document.getElementById(targetId);
|
||||||
|
|
||||||
@@ -1250,7 +1250,7 @@ function cleanupOffscreenTooltips() {
|
|||||||
|
|
||||||
const farOffscreenTriggers = Array.from(tooltipTriggers).filter(trigger => {
|
const farOffscreenTriggers = Array.from(tooltipTriggers).filter(trigger => {
|
||||||
const rect = trigger.getBoundingClientRect();
|
const rect = trigger.getBoundingClientRect();
|
||||||
return (rect.bottom < -window.innerHeight * 2 ||
|
return (rect.bottom < -window.innerHeight * 2 ||
|
||||||
rect.top > window.innerHeight * 3);
|
rect.top > window.innerHeight * 3);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -1312,7 +1312,7 @@ const fetchBids = async () => {
|
|||||||
activeFetchController.abort();
|
activeFetchController.abort();
|
||||||
}
|
}
|
||||||
}, 30000);
|
}, 30000);
|
||||||
|
|
||||||
const response = await fetch(endpoint, {
|
const response = await fetch(endpoint, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
@@ -1328,14 +1328,14 @@ const fetchBids = async () => {
|
|||||||
}),
|
}),
|
||||||
signal: activeFetchController.signal
|
signal: activeFetchController.signal
|
||||||
});
|
});
|
||||||
|
|
||||||
clearTimeout(timeoutId);
|
clearTimeout(timeoutId);
|
||||||
|
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
throw new Error(`HTTP error! status: ${response.status}`);
|
throw new Error(`HTTP error! status: ${response.status}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
let data = await response.json();
|
const data = await response.json();
|
||||||
//console.log('Received raw data:', data.length, 'bids');
|
//console.log('Received raw data:', data.length, 'bids');
|
||||||
|
|
||||||
state.filters.with_expired = includeExpired;
|
state.filters.with_expired = includeExpired;
|
||||||
@@ -1351,7 +1351,7 @@ const fetchBids = async () => {
|
|||||||
} else {
|
} else {
|
||||||
processedData = filterAndSortData(data);
|
processedData = filterAndSortData(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
return processedData;
|
return processedData;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (error.name === 'AbortError') {
|
if (error.name === 'AbortError') {
|
||||||
@@ -1375,12 +1375,12 @@ const updateBidsTable = async () => {
|
|||||||
updateLoadingState(true);
|
updateLoadingState(true);
|
||||||
|
|
||||||
const bids = await fetchBids();
|
const bids = await fetchBids();
|
||||||
|
|
||||||
// Add identity preloading if we're searching
|
// Add identity preloading if we're searching
|
||||||
if (state.filters.searchQuery && state.filters.searchQuery.length > 0) {
|
if (state.filters.searchQuery && state.filters.searchQuery.length > 0) {
|
||||||
await preloadIdentitiesForSearch(bids);
|
await preloadIdentitiesForSearch(bids);
|
||||||
}
|
}
|
||||||
|
|
||||||
state.data[state.currentTab] = bids;
|
state.data[state.currentTab] = bids;
|
||||||
state.currentPage[state.currentTab] = 1;
|
state.currentPage[state.currentTab] = 1;
|
||||||
|
|
||||||
@@ -1911,13 +1911,13 @@ function initialize() {
|
|||||||
WebSocketManager.initialize();
|
WebSocketManager.initialize();
|
||||||
setupEventListeners();
|
setupEventListeners();
|
||||||
}, 10);
|
}, 10);
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
setupRefreshButtons();
|
setupRefreshButtons();
|
||||||
setupFilterEventListeners();
|
setupFilterEventListeners();
|
||||||
updateCoinFilterImages();
|
updateCoinFilterImages();
|
||||||
}, 50);
|
}, 50);
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
updateClearFiltersButton();
|
updateClearFiltersButton();
|
||||||
state.currentTab = 'sent';
|
state.currentTab = 'sent';
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ const BidExporter = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const isSent = type === 'sent';
|
const isSent = type === 'sent';
|
||||||
|
|
||||||
const headers = [
|
const headers = [
|
||||||
'Date/Time',
|
'Date/Time',
|
||||||
'Bid ID',
|
'Bid ID',
|
||||||
@@ -19,9 +19,9 @@ const BidExporter = {
|
|||||||
'Created At',
|
'Created At',
|
||||||
'Expires At'
|
'Expires At'
|
||||||
];
|
];
|
||||||
|
|
||||||
let csvContent = headers.join(',') + '\n';
|
let csvContent = headers.join(',') + '\n';
|
||||||
|
|
||||||
bids.forEach(bid => {
|
bids.forEach(bid => {
|
||||||
const row = [
|
const row = [
|
||||||
`"${formatTime(bid.created_at)}"`,
|
`"${formatTime(bid.created_at)}"`,
|
||||||
@@ -36,17 +36,17 @@ const BidExporter = {
|
|||||||
bid.created_at,
|
bid.created_at,
|
||||||
bid.expire_at
|
bid.expire_at
|
||||||
];
|
];
|
||||||
|
|
||||||
csvContent += row.join(',') + '\n';
|
csvContent += row.join(',') + '\n';
|
||||||
});
|
});
|
||||||
|
|
||||||
return csvContent;
|
return csvContent;
|
||||||
},
|
},
|
||||||
|
|
||||||
download(content, filename) {
|
download(content, filename) {
|
||||||
try {
|
try {
|
||||||
const blob = new Blob([content], { type: 'text/csv;charset=utf-8;' });
|
const blob = new Blob([content], { type: 'text/csv;charset=utf-8;' });
|
||||||
|
|
||||||
if (window.navigator && window.navigator.msSaveOrOpenBlob) {
|
if (window.navigator && window.navigator.msSaveOrOpenBlob) {
|
||||||
window.navigator.msSaveOrOpenBlob(blob, filename);
|
window.navigator.msSaveOrOpenBlob(blob, filename);
|
||||||
return;
|
return;
|
||||||
@@ -54,48 +54,48 @@ const BidExporter = {
|
|||||||
|
|
||||||
const url = URL.createObjectURL(blob);
|
const url = URL.createObjectURL(blob);
|
||||||
const link = document.createElement('a');
|
const link = document.createElement('a');
|
||||||
|
|
||||||
link.href = url;
|
link.href = url;
|
||||||
link.download = filename;
|
link.download = filename;
|
||||||
link.style.display = 'none';
|
link.style.display = 'none';
|
||||||
|
|
||||||
document.body.appendChild(link);
|
document.body.appendChild(link);
|
||||||
link.click();
|
link.click();
|
||||||
document.body.removeChild(link);
|
document.body.removeChild(link);
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
URL.revokeObjectURL(url);
|
URL.revokeObjectURL(url);
|
||||||
}, 100);
|
}, 100);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error downloading CSV:', error);
|
console.error('Error downloading CSV:', error);
|
||||||
|
|
||||||
const csvData = 'data:text/csv;charset=utf-8,' + encodeURIComponent(content);
|
const csvData = 'data:text/csv;charset=utf-8,' + encodeURIComponent(content);
|
||||||
const link = document.createElement('a');
|
const link = document.createElement('a');
|
||||||
link.setAttribute('href', csvData);
|
link.setAttribute('href', csvData);
|
||||||
link.setAttribute('download', filename);
|
link.setAttribute('download', filename);
|
||||||
link.style.display = 'none';
|
link.style.display = 'none';
|
||||||
|
|
||||||
document.body.appendChild(link);
|
document.body.appendChild(link);
|
||||||
link.click();
|
link.click();
|
||||||
document.body.removeChild(link);
|
document.body.removeChild(link);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
exportCurrentView() {
|
exportCurrentView() {
|
||||||
const type = state.currentTab;
|
const type = state.currentTab;
|
||||||
const data = state.data[type];
|
const data = state.data[type];
|
||||||
|
|
||||||
if (!data || !data.length) {
|
if (!data || !data.length) {
|
||||||
alert('No data to export');
|
alert('No data to export');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const csvContent = this.toCSV(data, type);
|
const csvContent = this.toCSV(data, type);
|
||||||
|
|
||||||
const now = new Date();
|
const now = new Date();
|
||||||
const dateStr = now.toISOString().split('T')[0];
|
const dateStr = now.toISOString().split('T')[0];
|
||||||
const filename = `bsx_${type}_bids_${dateStr}.csv`;
|
const filename = `bsx_${type}_bids_${dateStr}.csv`;
|
||||||
|
|
||||||
this.download(csvContent, filename);
|
this.download(csvContent, filename);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -111,7 +111,7 @@ document.addEventListener('DOMContentLoaded', function() {
|
|||||||
BidExporter.exportCurrentView();
|
BidExporter.exportCurrentView();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const exportReceivedButton = document.getElementById('exportReceivedBids');
|
const exportReceivedButton = document.getElementById('exportReceivedBids');
|
||||||
if (exportReceivedButton) {
|
if (exportReceivedButton) {
|
||||||
EventManager.add(exportReceivedButton, 'click', (e) => {
|
EventManager.add(exportReceivedButton, 'click', (e) => {
|
||||||
@@ -127,14 +127,14 @@ document.addEventListener('DOMContentLoaded', function() {
|
|||||||
const originalCleanup = window.cleanup || function(){};
|
const originalCleanup = window.cleanup || function(){};
|
||||||
window.cleanup = function() {
|
window.cleanup = function() {
|
||||||
originalCleanup();
|
originalCleanup();
|
||||||
|
|
||||||
const exportSentButton = document.getElementById('exportSentBids');
|
const exportSentButton = document.getElementById('exportSentBids');
|
||||||
const exportReceivedButton = document.getElementById('exportReceivedBids');
|
const exportReceivedButton = document.getElementById('exportReceivedBids');
|
||||||
|
|
||||||
if (exportSentButton && typeof EventManager !== 'undefined') {
|
if (exportSentButton && typeof EventManager !== 'undefined') {
|
||||||
EventManager.remove(exportSentButton, 'click');
|
EventManager.remove(exportSentButton, 'click');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (exportReceivedButton && typeof EventManager !== 'undefined') {
|
if (exportReceivedButton && typeof EventManager !== 'undefined') {
|
||||||
EventManager.remove(exportReceivedButton, 'click');
|
EventManager.remove(exportReceivedButton, 'click');
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -84,7 +84,7 @@ function setupShutdownModal() {
|
|||||||
|
|
||||||
function showShutdownModal() {
|
function showShutdownModal() {
|
||||||
closeAllDropdowns();
|
closeAllDropdowns();
|
||||||
|
|
||||||
const activeSwaps = parseInt(shutdownButtons[0].getAttribute('data-active-swaps') || '0');
|
const activeSwaps = parseInt(shutdownButtons[0].getAttribute('data-active-swaps') || '0');
|
||||||
if (activeSwaps > 0) {
|
if (activeSwaps > 0) {
|
||||||
shutdownWarning.classList.remove('hidden');
|
shutdownWarning.classList.remove('hidden');
|
||||||
@@ -142,7 +142,7 @@ function setupDarkMode() {
|
|||||||
const themeToggleLightIcon = document.getElementById('theme-toggle-light-icon');
|
const themeToggleLightIcon = document.getElementById('theme-toggle-light-icon');
|
||||||
|
|
||||||
if (themeToggleDarkIcon && themeToggleLightIcon) {
|
if (themeToggleDarkIcon && themeToggleLightIcon) {
|
||||||
if (localStorage.getItem('color-theme') === 'dark' ||
|
if (localStorage.getItem('color-theme') === 'dark' ||
|
||||||
(!('color-theme' in localStorage) && window.matchMedia('(prefers-color-scheme: dark)').matches)) {
|
(!('color-theme' in localStorage) && window.matchMedia('(prefers-color-scheme: dark)').matches)) {
|
||||||
themeToggleLightIcon.classList.remove('hidden');
|
themeToggleLightIcon.classList.remove('hidden');
|
||||||
} else {
|
} else {
|
||||||
@@ -167,12 +167,12 @@ function setupDarkMode() {
|
|||||||
} else {
|
} else {
|
||||||
setTheme('dark');
|
setTheme('dark');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (themeToggleDarkIcon && themeToggleLightIcon) {
|
if (themeToggleDarkIcon && themeToggleLightIcon) {
|
||||||
themeToggleDarkIcon.classList.toggle('hidden');
|
themeToggleDarkIcon.classList.toggle('hidden');
|
||||||
themeToggleLightIcon.classList.toggle('hidden');
|
themeToggleLightIcon.classList.toggle('hidden');
|
||||||
}
|
}
|
||||||
|
|
||||||
toggleImages();
|
toggleImages();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ const ApiManager = (function() {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
await this.requestQueue[apiName];
|
await this.requestQueue[apiName];
|
||||||
|
|
||||||
const executeRequest = async () => {
|
const executeRequest = async () => {
|
||||||
const waitTime = this.getWaitTime(apiName);
|
const waitTime = this.getWaitTime(apiName);
|
||||||
if (waitTime > 0) {
|
if (waitTime > 0) {
|
||||||
@@ -69,7 +69,7 @@ const ApiManager = (function() {
|
|||||||
return publicAPI.rateLimiter.queueRequest(apiName, requestFn, retryCount + 1);
|
return publicAPI.rateLimiter.queueRequest(apiName, requestFn, retryCount + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((error.message.includes('timeout') || error.name === 'NetworkError') &&
|
if ((error.message.includes('timeout') || error.name === 'NetworkError') &&
|
||||||
retryCount < this.retryDelays.length) {
|
retryCount < this.retryDelays.length) {
|
||||||
const delay = this.retryDelays[retryCount];
|
const delay = this.retryDelays[retryCount];
|
||||||
console.warn(`Request failed, retrying in ${delay/1000} seconds...`, {
|
console.warn(`Request failed, retrying in ${delay/1000} seconds...`, {
|
||||||
@@ -87,10 +87,10 @@ const ApiManager = (function() {
|
|||||||
|
|
||||||
this.requestQueue[apiName] = executeRequest();
|
this.requestQueue[apiName] = executeRequest();
|
||||||
return await this.requestQueue[apiName];
|
return await this.requestQueue[apiName];
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (error.message.includes('429') ||
|
if (error.message.includes('429') ||
|
||||||
error.message.includes('timeout') ||
|
error.message.includes('timeout') ||
|
||||||
error.name === 'NetworkError') {
|
error.name === 'NetworkError') {
|
||||||
const cacheKey = `coinData_${apiName}`;
|
const cacheKey = `coinData_${apiName}`;
|
||||||
try {
|
try {
|
||||||
@@ -110,7 +110,7 @@ const ApiManager = (function() {
|
|||||||
const publicAPI = {
|
const publicAPI = {
|
||||||
config,
|
config,
|
||||||
rateLimiter,
|
rateLimiter,
|
||||||
|
|
||||||
initialize: function(options = {}) {
|
initialize: function(options = {}) {
|
||||||
if (state.isInitialized) {
|
if (state.isInitialized) {
|
||||||
console.warn('[ApiManager] Already initialized');
|
console.warn('[ApiManager] Already initialized');
|
||||||
@@ -158,7 +158,7 @@ const ApiManager = (function() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const response = await fetch(url, options);
|
const response = await fetch(url, options);
|
||||||
|
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
throw new Error(`HTTP error! status: ${response.status}`);
|
throw new Error(`HTTP error! status: ${response.status}`);
|
||||||
}
|
}
|
||||||
@@ -215,18 +215,18 @@ const ApiManager = (function() {
|
|||||||
fetchCoinGeckoData: async function() {
|
fetchCoinGeckoData: async function() {
|
||||||
return this.rateLimiter.queueRequest('coingecko', async () => {
|
return this.rateLimiter.queueRequest('coingecko', async () => {
|
||||||
try {
|
try {
|
||||||
const coins = (window.config && window.config.coins) ?
|
const coins = (window.config && window.config.coins) ?
|
||||||
window.config.coins
|
window.config.coins
|
||||||
.filter(coin => coin.usesCoinGecko)
|
.filter(coin => coin.usesCoinGecko)
|
||||||
.map(coin => coin.name)
|
.map(coin => coin.name)
|
||||||
.join(',') :
|
.join(',') :
|
||||||
'bitcoin,monero,particl,bitcoincash,pivx,firo,dash,litecoin,dogecoin,decred';
|
'bitcoin,monero,particl,bitcoincash,pivx,firo,dash,litecoin,dogecoin,decred';
|
||||||
|
|
||||||
//console.log('Fetching coin prices for:', coins);
|
//console.log('Fetching coin prices for:', coins);
|
||||||
const response = await this.fetchCoinPrices(coins);
|
const response = await this.fetchCoinPrices(coins);
|
||||||
|
|
||||||
//console.log('Full API response:', response);
|
//console.log('Full API response:', response);
|
||||||
|
|
||||||
if (!response || typeof response !== 'object') {
|
if (!response || typeof response !== 'object') {
|
||||||
throw new Error('Invalid response type');
|
throw new Error('Invalid response type');
|
||||||
}
|
}
|
||||||
@@ -249,11 +249,11 @@ const ApiManager = (function() {
|
|||||||
fetchVolumeData: async function() {
|
fetchVolumeData: async function() {
|
||||||
return this.rateLimiter.queueRequest('coingecko', async () => {
|
return this.rateLimiter.queueRequest('coingecko', async () => {
|
||||||
try {
|
try {
|
||||||
const coins = (window.config && window.config.coins) ?
|
const coins = (window.config && window.config.coins) ?
|
||||||
window.config.coins
|
window.config.coins
|
||||||
.filter(coin => coin.usesCoinGecko)
|
.filter(coin => coin.usesCoinGecko)
|
||||||
.map(coin => getCoinBackendId ? getCoinBackendId(coin.name) : coin.name)
|
.map(coin => getCoinBackendId ? getCoinBackendId(coin.name) : coin.name)
|
||||||
.join(',') :
|
.join(',') :
|
||||||
'bitcoin,monero,particl,bitcoin-cash,pivx,firo,dash,litecoin,dogecoin,decred';
|
'bitcoin,monero,particl,bitcoin-cash,pivx,firo,dash,litecoin,dogecoin,decred';
|
||||||
|
|
||||||
const url = `https://api.coingecko.com/api/v3/simple/price?ids=${coins}&vs_currencies=usd&include_24hr_vol=true&include_24hr_change=true`;
|
const url = `https://api.coingecko.com/api/v3/simple/price?ids=${coins}&vs_currencies=usd&include_24hr_vol=true&include_24hr_change=true`;
|
||||||
@@ -280,7 +280,7 @@ const ApiManager = (function() {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
fetchCryptoCompareData: function(coin) {
|
fetchCryptoCompareData: function(coin) {
|
||||||
return this.rateLimiter.queueRequest('cryptocompare', async () => {
|
return this.rateLimiter.queueRequest('cryptocompare', async () => {
|
||||||
try {
|
try {
|
||||||
@@ -290,7 +290,7 @@ const ApiManager = (function() {
|
|||||||
'User-Agent': 'Mozilla/5.0',
|
'User-Agent': 'Mozilla/5.0',
|
||||||
'Accept': 'application/json'
|
'Accept': 'application/json'
|
||||||
};
|
};
|
||||||
|
|
||||||
return await this.makePostRequest(url, headers);
|
return await this.makePostRequest(url, headers);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(`CryptoCompare request failed for ${coin}:`, error);
|
console.error(`CryptoCompare request failed for ${coin}:`, error);
|
||||||
@@ -324,7 +324,7 @@ const ApiManager = (function() {
|
|||||||
try {
|
try {
|
||||||
const apiKey = window.config?.apiKeys?.cryptoCompare || '';
|
const apiKey = window.config?.apiKeys?.cryptoCompare || '';
|
||||||
let url;
|
let url;
|
||||||
|
|
||||||
if (resolution === 'day') {
|
if (resolution === 'day') {
|
||||||
url = `https://min-api.cryptocompare.com/data/v2/histohour?fsym=${coin}&tsym=USD&limit=24&api_key=${apiKey}`;
|
url = `https://min-api.cryptocompare.com/data/v2/histohour?fsym=${coin}&tsym=USD&limit=24&api_key=${apiKey}`;
|
||||||
} else if (resolution === 'year') {
|
} else if (resolution === 'year') {
|
||||||
@@ -351,7 +351,7 @@ const ApiManager = (function() {
|
|||||||
await Promise.all(fetchPromises);
|
await Promise.all(fetchPromises);
|
||||||
return results;
|
return results;
|
||||||
},
|
},
|
||||||
|
|
||||||
dispose: function() {
|
dispose: function() {
|
||||||
// Clear any pending requests or resources
|
// Clear any pending requests or resources
|
||||||
rateLimiter.requestQueue = {};
|
rateLimiter.requestQueue = {};
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ const CacheManager = (function() {
|
|||||||
];
|
];
|
||||||
|
|
||||||
const isCacheKey = (key) => {
|
const isCacheKey = (key) => {
|
||||||
return CACHE_KEY_PATTERNS.some(pattern => key.startsWith(pattern)) ||
|
return CACHE_KEY_PATTERNS.some(pattern => key.startsWith(pattern)) ||
|
||||||
key === 'coinGeckoOneLiner' ||
|
key === 'coinGeckoOneLiner' ||
|
||||||
key === PRICES_CACHE_KEY;
|
key === PRICES_CACHE_KEY;
|
||||||
};
|
};
|
||||||
@@ -48,7 +48,7 @@ const CacheManager = (function() {
|
|||||||
const ttlConfig = window.config?.cacheConfig?.ttlSettings || {};
|
const ttlConfig = window.config?.cacheConfig?.ttlSettings || {};
|
||||||
return ttlConfig[resourceType] || window.config?.cacheConfig?.defaultTTL || defaults.defaultTTL;
|
return ttlConfig[resourceType] || window.config?.cacheConfig?.defaultTTL || defaults.defaultTTL;
|
||||||
},
|
},
|
||||||
|
|
||||||
set: function(key, value, resourceTypeOrCustomTtl = null) {
|
set: function(key, value, resourceTypeOrCustomTtl = null) {
|
||||||
try {
|
try {
|
||||||
this.cleanup();
|
this.cleanup();
|
||||||
@@ -119,10 +119,10 @@ const CacheManager = (function() {
|
|||||||
.filter(k => isCacheKey(k))
|
.filter(k => isCacheKey(k))
|
||||||
.sort((a, b) => memoryCache.get(a).timestamp - memoryCache.get(b).timestamp)
|
.sort((a, b) => memoryCache.get(a).timestamp - memoryCache.get(b).timestamp)
|
||||||
.slice(0, Math.floor(memoryCache.size * 0.2)); // Remove oldest 20%
|
.slice(0, Math.floor(memoryCache.size * 0.2)); // Remove oldest 20%
|
||||||
|
|
||||||
keysToDelete.forEach(k => memoryCache.delete(k));
|
keysToDelete.forEach(k => memoryCache.delete(k));
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -194,7 +194,7 @@ const CacheManager = (function() {
|
|||||||
memoryCache.delete(key);
|
memoryCache.delete(key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Cache retrieval error:", error);
|
console.error("Cache retrieval error:", error);
|
||||||
@@ -286,7 +286,7 @@ const CacheManager = (function() {
|
|||||||
.filter(key => isCacheKey(key))
|
.filter(key => isCacheKey(key))
|
||||||
.sort((a, b) => memoryCache.get(a).timestamp - memoryCache.get(b).timestamp)
|
.sort((a, b) => memoryCache.get(a).timestamp - memoryCache.get(b).timestamp)
|
||||||
.slice(0, Math.floor(memoryCache.size * 0.3)); // Remove oldest 30% during aggressive cleanup
|
.slice(0, Math.floor(memoryCache.size * 0.3)); // Remove oldest 30% during aggressive cleanup
|
||||||
|
|
||||||
keysToDelete.forEach(key => memoryCache.delete(key));
|
keysToDelete.forEach(key => memoryCache.delete(key));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -327,7 +327,7 @@ const CacheManager = (function() {
|
|||||||
Array.from(memoryCache.keys())
|
Array.from(memoryCache.keys())
|
||||||
.filter(key => isCacheKey(key))
|
.filter(key => isCacheKey(key))
|
||||||
.forEach(key => memoryCache.delete(key));
|
.forEach(key => memoryCache.delete(key));
|
||||||
|
|
||||||
console.log("Cache cleared successfully");
|
console.log("Cache cleared successfully");
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
@@ -368,7 +368,7 @@ const CacheManager = (function() {
|
|||||||
let memoryCacheSize = 0;
|
let memoryCacheSize = 0;
|
||||||
let memoryCacheItems = 0;
|
let memoryCacheItems = 0;
|
||||||
let memoryCacheExpired = 0;
|
let memoryCacheExpired = 0;
|
||||||
|
|
||||||
memoryCache.forEach((item, key) => {
|
memoryCache.forEach((item, key) => {
|
||||||
if (isCacheKey(key)) {
|
if (isCacheKey(key)) {
|
||||||
memoryCacheItems++;
|
memoryCacheItems++;
|
||||||
@@ -381,7 +381,7 @@ const CacheManager = (function() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
totalSizeMB: (totalSize / 1024 / 1024).toFixed(2),
|
totalSizeMB: (totalSize / 1024 / 1024).toFixed(2),
|
||||||
itemCount,
|
itemCount,
|
||||||
@@ -415,10 +415,10 @@ const CacheManager = (function() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log(`Migrated ${migratedCount} items from memory cache to localStorage.`);
|
console.log(`Migrated ${migratedCount} items from memory cache to localStorage.`);
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
available: storageAvailable,
|
available: storageAvailable,
|
||||||
type: storageAvailable ? 'localStorage' : 'memory'
|
type: storageAvailable ? 'localStorage' : 'memory'
|
||||||
@@ -430,7 +430,7 @@ const CacheManager = (function() {
|
|||||||
...cacheAPI,
|
...cacheAPI,
|
||||||
|
|
||||||
setPrices: function(priceData, customTtl = null) {
|
setPrices: function(priceData, customTtl = null) {
|
||||||
return this.set(PRICES_CACHE_KEY, priceData,
|
return this.set(PRICES_CACHE_KEY, priceData,
|
||||||
customTtl || (typeof customTtl === 'undefined' ? 'prices' : null));
|
customTtl || (typeof customTtl === 'undefined' ? 'prices' : null));
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -447,7 +447,7 @@ const CacheManager = (function() {
|
|||||||
const normalizedSymbol = symbol.toLowerCase();
|
const normalizedSymbol = symbol.toLowerCase();
|
||||||
return prices.value[normalizedSymbol] || null;
|
return prices.value[normalizedSymbol] || null;
|
||||||
},
|
},
|
||||||
|
|
||||||
getCompatiblePrices: function(format) {
|
getCompatiblePrices: function(format) {
|
||||||
const prices = this.getPrices();
|
const prices = this.getPrices();
|
||||||
if (!prices || !prices.value) {
|
if (!prices || !prices.value) {
|
||||||
@@ -464,7 +464,7 @@ const CacheManager = (function() {
|
|||||||
.join(' ')
|
.join(' ')
|
||||||
.toLowerCase()
|
.toLowerCase()
|
||||||
.replace(' ', '-');
|
.replace(' ', '-');
|
||||||
|
|
||||||
ratesFormat[coinKey] = {
|
ratesFormat[coinKey] = {
|
||||||
usd: data.price || data.usd,
|
usd: data.price || data.usd,
|
||||||
btc: data.price_btc || data.btc
|
btc: data.price_btc || data.btc
|
||||||
@@ -493,7 +493,7 @@ const CacheManager = (function() {
|
|||||||
value: geckoFormat,
|
value: geckoFormat,
|
||||||
remainingTime: prices.remainingTime
|
remainingTime: prices.remainingTime
|
||||||
};
|
};
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return prices;
|
return prices;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -111,8 +111,8 @@ const CleanupManager = (function() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
state.eventListeners = state.eventListeners.filter(
|
state.eventListeners = state.eventListeners.filter(
|
||||||
listener => !(listener.element === element &&
|
listener => !(listener.element === element &&
|
||||||
listener.type === type &&
|
listener.type === type &&
|
||||||
listener.handler === handler)
|
listener.handler === handler)
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
@@ -224,10 +224,10 @@ const CleanupManager = (function() {
|
|||||||
intervals: state.intervals.length,
|
intervals: state.intervals.length,
|
||||||
animationFrames: state.animationFrames.length,
|
animationFrames: state.animationFrames.length,
|
||||||
resources: state.resources.size,
|
resources: state.resources.size,
|
||||||
total: state.eventListeners.length +
|
total: state.eventListeners.length +
|
||||||
state.timeouts.length +
|
state.timeouts.length +
|
||||||
state.intervals.length +
|
state.intervals.length +
|
||||||
state.animationFrames.length +
|
state.animationFrames.length +
|
||||||
state.resources.size
|
state.resources.size
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -4,9 +4,9 @@ const ConfigManager = (function() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
function determineWebSocketPort() {
|
function determineWebSocketPort() {
|
||||||
const wsPort =
|
const wsPort =
|
||||||
window.ws_port ||
|
window.ws_port ||
|
||||||
(typeof getWebSocketConfig === 'function' ? getWebSocketConfig().port : null) ||
|
(typeof getWebSocketConfig === 'function' ? getWebSocketConfig().port : null) ||
|
||||||
'11700';
|
'11700';
|
||||||
return wsPort;
|
return wsPort;
|
||||||
}
|
}
|
||||||
@@ -17,10 +17,10 @@ const ConfigManager = (function() {
|
|||||||
cacheDuration: 10 * 60 * 1000,
|
cacheDuration: 10 * 60 * 1000,
|
||||||
requestTimeout: 60000,
|
requestTimeout: 60000,
|
||||||
wsPort: selectedWsPort,
|
wsPort: selectedWsPort,
|
||||||
|
|
||||||
cacheConfig: {
|
cacheConfig: {
|
||||||
defaultTTL: 10 * 60 * 1000,
|
defaultTTL: 10 * 60 * 1000,
|
||||||
|
|
||||||
ttlSettings: {
|
ttlSettings: {
|
||||||
prices: 5 * 60 * 1000,
|
prices: 5 * 60 * 1000,
|
||||||
chart: 5 * 60 * 1000,
|
chart: 5 * 60 * 1000,
|
||||||
@@ -34,7 +34,7 @@ const ConfigManager = (function() {
|
|||||||
maxSizeBytes: 10 * 1024 * 1024,
|
maxSizeBytes: 10 * 1024 * 1024,
|
||||||
maxItems: 200
|
maxItems: 200
|
||||||
},
|
},
|
||||||
|
|
||||||
fallbackTTL: 24 * 60 * 60 * 1000
|
fallbackTTL: 24 * 60 * 60 * 1000
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -92,7 +92,7 @@ const ConfigManager = (function() {
|
|||||||
'Bitcoin Cash': 'BCH',
|
'Bitcoin Cash': 'BCH',
|
||||||
'Dogecoin': 'DOGE'
|
'Dogecoin': 'DOGE'
|
||||||
},
|
},
|
||||||
|
|
||||||
nameToDisplayName: {
|
nameToDisplayName: {
|
||||||
'Bitcoin': 'Bitcoin',
|
'Bitcoin': 'Bitcoin',
|
||||||
'Litecoin': 'Litecoin',
|
'Litecoin': 'Litecoin',
|
||||||
@@ -164,13 +164,13 @@ const ConfigManager = (function() {
|
|||||||
if (options) {
|
if (options) {
|
||||||
Object.assign(this, options);
|
Object.assign(this, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (window.CleanupManager) {
|
if (window.CleanupManager) {
|
||||||
window.CleanupManager.registerResource('configManager', this, (mgr) => mgr.dispose());
|
window.CleanupManager.registerResource('configManager', this, (mgr) => mgr.dispose());
|
||||||
}
|
}
|
||||||
|
|
||||||
this.utils = utils;
|
this.utils = utils;
|
||||||
|
|
||||||
state.isInitialized = true;
|
state.isInitialized = true;
|
||||||
console.log('ConfigManager initialized');
|
console.log('ConfigManager initialized');
|
||||||
return this;
|
return this;
|
||||||
@@ -205,7 +205,7 @@ const ConfigManager = (function() {
|
|||||||
const lowerCoinName = typeof coinName === 'string' ? coinName.toLowerCase() : '';
|
const lowerCoinName = typeof coinName === 'string' ? coinName.toLowerCase() : '';
|
||||||
return nameMap[lowerCoinName] || lowerCoinName;
|
return nameMap[lowerCoinName] || lowerCoinName;
|
||||||
},
|
},
|
||||||
|
|
||||||
coinMatches: function(offerCoin, filterCoin) {
|
coinMatches: function(offerCoin, filterCoin) {
|
||||||
if (!offerCoin || !filterCoin) return false;
|
if (!offerCoin || !filterCoin) return false;
|
||||||
|
|
||||||
@@ -254,7 +254,7 @@ const ConfigManager = (function() {
|
|||||||
get: function(path, defaultValue = null) {
|
get: function(path, defaultValue = null) {
|
||||||
const parts = path.split('.');
|
const parts = path.split('.');
|
||||||
let current = this;
|
let current = this;
|
||||||
|
|
||||||
for (let i = 0; i < parts.length; i++) {
|
for (let i = 0; i < parts.length; i++) {
|
||||||
if (current === undefined || current === null) {
|
if (current === undefined || current === null) {
|
||||||
return defaultValue;
|
return defaultValue;
|
||||||
@@ -376,12 +376,12 @@ const ConfigManager = (function() {
|
|||||||
'firo': { usd: null, btc: null }
|
'firo': { usd: null, btc: null }
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
getCoinSymbol: function(fullName) {
|
getCoinSymbol: function(fullName) {
|
||||||
return publicAPI.coinMappings?.nameToSymbol[fullName] || fullName;
|
return publicAPI.coinMappings?.nameToSymbol[fullName] || fullName;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return publicAPI;
|
return publicAPI;
|
||||||
})();
|
})();
|
||||||
|
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ const IdentityManager = (function() {
|
|||||||
const oldestEntries = [...state.cache.entries()]
|
const oldestEntries = [...state.cache.entries()]
|
||||||
.sort((a, b) => a[1].timestamp - b[1].timestamp)
|
.sort((a, b) => a[1].timestamp - b[1].timestamp)
|
||||||
.slice(0, Math.floor(state.config.maxCacheSize * 0.2));
|
.slice(0, Math.floor(state.config.maxCacheSize * 0.2));
|
||||||
|
|
||||||
oldestEntries.forEach(([key]) => {
|
oldestEntries.forEach(([key]) => {
|
||||||
state.cache.delete(key);
|
state.cache.delete(key);
|
||||||
log(`Pruned cache entry for ${key}`);
|
log(`Pruned cache entry for ${key}`);
|
||||||
@@ -88,10 +88,10 @@ const IdentityManager = (function() {
|
|||||||
const entriesToRemove = [...state.cache.entries()]
|
const entriesToRemove = [...state.cache.entries()]
|
||||||
.sort((a, b) => a[1].timestamp - b[1].timestamp)
|
.sort((a, b) => a[1].timestamp - b[1].timestamp)
|
||||||
.slice(0, state.cache.size - maxSize);
|
.slice(0, state.cache.size - maxSize);
|
||||||
|
|
||||||
entriesToRemove.forEach(([key]) => state.cache.delete(key));
|
entriesToRemove.forEach(([key]) => state.cache.delete(key));
|
||||||
log(`Limited cache size, removed ${entriesToRemove.length} entries`);
|
log(`Limited cache size, removed ${entriesToRemove.length} entries`);
|
||||||
|
|
||||||
return entriesToRemove.length;
|
return entriesToRemove.length;
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -138,11 +138,11 @@ const IdentityManager = (function() {
|
|||||||
if (options) {
|
if (options) {
|
||||||
this.configure(options);
|
this.configure(options);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (window.CleanupManager) {
|
if (window.CleanupManager) {
|
||||||
window.CleanupManager.registerResource('identityManager', this, (mgr) => mgr.dispose());
|
window.CleanupManager.registerResource('identityManager', this, (mgr) => mgr.dispose());
|
||||||
}
|
}
|
||||||
|
|
||||||
log('IdentityManager initialized');
|
log('IdentityManager initialized');
|
||||||
return this;
|
return this;
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ const MemoryManager = (function() {
|
|||||||
|
|
||||||
const nodeCount = document.querySelectorAll('*').length;
|
const nodeCount = document.querySelectorAll('*').length;
|
||||||
console.log('DOM node count:', nodeCount);
|
console.log('DOM node count:', nodeCount);
|
||||||
|
|
||||||
if (window.CleanupManager) {
|
if (window.CleanupManager) {
|
||||||
const counts = CleanupManager.getResourceCounts();
|
const counts = CleanupManager.getResourceCounts();
|
||||||
console.log('Managed resources:', counts);
|
console.log('Managed resources:', counts);
|
||||||
@@ -102,11 +102,11 @@ const MemoryManager = (function() {
|
|||||||
state.cleanupInterval = setInterval(() => {
|
state.cleanupInterval = setInterval(() => {
|
||||||
this.forceCleanup();
|
this.forceCleanup();
|
||||||
}, interval);
|
}, interval);
|
||||||
|
|
||||||
log('Auto-cleanup enabled every', interval/1000, 'seconds');
|
log('Auto-cleanup enabled every', interval/1000, 'seconds');
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
|
|
||||||
disableAutoCleanup: function() {
|
disableAutoCleanup: function() {
|
||||||
if (state.cleanupInterval) {
|
if (state.cleanupInterval) {
|
||||||
clearInterval(state.cleanupInterval);
|
clearInterval(state.cleanupInterval);
|
||||||
@@ -155,7 +155,7 @@ const MemoryManager = (function() {
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
|
|
||||||
setDebugMode: function(enabled) {
|
setDebugMode: function(enabled) {
|
||||||
config.debug = Boolean(enabled);
|
config.debug = Boolean(enabled);
|
||||||
return `Debug mode ${config.debug ? 'enabled' : 'disabled'}`;
|
return `Debug mode ${config.debug ? 'enabled' : 'disabled'}`;
|
||||||
|
|||||||
@@ -30,13 +30,13 @@ const NetworkManager = (function() {
|
|||||||
const publicAPI = {
|
const publicAPI = {
|
||||||
initialize: function(options = {}) {
|
initialize: function(options = {}) {
|
||||||
Object.assign(config, options);
|
Object.assign(config, options);
|
||||||
|
|
||||||
window.addEventListener('online', this.handleOnlineStatus.bind(this));
|
window.addEventListener('online', this.handleOnlineStatus.bind(this));
|
||||||
window.addEventListener('offline', this.handleOfflineStatus.bind(this));
|
window.addEventListener('offline', this.handleOfflineStatus.bind(this));
|
||||||
|
|
||||||
state.isOnline = navigator.onLine;
|
state.isOnline = navigator.onLine;
|
||||||
log(`Network status initialized: ${state.isOnline ? 'online' : 'offline'}`);
|
log(`Network status initialized: ${state.isOnline ? 'online' : 'offline'}`);
|
||||||
|
|
||||||
if (window.CleanupManager) {
|
if (window.CleanupManager) {
|
||||||
window.CleanupManager.registerResource('networkManager', this, (mgr) => mgr.dispose());
|
window.CleanupManager.registerResource('networkManager', this, (mgr) => mgr.dispose());
|
||||||
}
|
}
|
||||||
@@ -61,7 +61,7 @@ const NetworkManager = (function() {
|
|||||||
log('Browser reports online status');
|
log('Browser reports online status');
|
||||||
state.isOnline = true;
|
state.isOnline = true;
|
||||||
this.notifyHandlers('online');
|
this.notifyHandlers('online');
|
||||||
|
|
||||||
if (state.reconnectTimer) {
|
if (state.reconnectTimer) {
|
||||||
this.scheduleReconnectRefresh();
|
this.scheduleReconnectRefresh();
|
||||||
}
|
}
|
||||||
@@ -103,7 +103,7 @@ const NetworkManager = (function() {
|
|||||||
state.reconnectTimer = null;
|
state.reconnectTimer = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const delay = config.reconnectDelay * Math.pow(config.reconnectBackoff,
|
const delay = config.reconnectDelay * Math.pow(config.reconnectBackoff,
|
||||||
Math.min(state.reconnectAttempts, 5));
|
Math.min(state.reconnectAttempts, 5));
|
||||||
|
|
||||||
log(`Scheduling reconnection attempt in ${delay/1000} seconds`);
|
log(`Scheduling reconnection attempt in ${delay/1000} seconds`);
|
||||||
@@ -145,7 +145,7 @@ const NetworkManager = (function() {
|
|||||||
this.notifyHandlers('reconnected');
|
this.notifyHandlers('reconnected');
|
||||||
} else {
|
} else {
|
||||||
log('Backend still unavailable');
|
log('Backend still unavailable');
|
||||||
|
|
||||||
if (state.reconnectAttempts < config.maxReconnectAttempts) {
|
if (state.reconnectAttempts < config.maxReconnectAttempts) {
|
||||||
this.scheduleReconnectRefresh();
|
this.scheduleReconnectRefresh();
|
||||||
} else {
|
} else {
|
||||||
@@ -157,7 +157,7 @@ const NetworkManager = (function() {
|
|||||||
.catch(error => {
|
.catch(error => {
|
||||||
state.connectionTestInProgress = false;
|
state.connectionTestInProgress = false;
|
||||||
log('Error during connection test:', error);
|
log('Error during connection test:', error);
|
||||||
|
|
||||||
if (state.reconnectAttempts < config.maxReconnectAttempts) {
|
if (state.reconnectAttempts < config.maxReconnectAttempts) {
|
||||||
this.scheduleReconnectRefresh();
|
this.scheduleReconnectRefresh();
|
||||||
} else {
|
} else {
|
||||||
@@ -210,7 +210,7 @@ const NetworkManager = (function() {
|
|||||||
|
|
||||||
const handlerId = generateHandlerId();
|
const handlerId = generateHandlerId();
|
||||||
state.eventHandlers[event][handlerId] = handler;
|
state.eventHandlers[event][handlerId] = handler;
|
||||||
|
|
||||||
return handlerId;
|
return handlerId;
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -256,9 +256,9 @@ const NetworkManager = (function() {
|
|||||||
|
|
||||||
window.removeEventListener('online', this.handleOnlineStatus);
|
window.removeEventListener('online', this.handleOnlineStatus);
|
||||||
window.removeEventListener('offline', this.handleOfflineStatus);
|
window.removeEventListener('offline', this.handleOfflineStatus);
|
||||||
|
|
||||||
state.eventHandlers = {};
|
state.eventHandlers = {};
|
||||||
|
|
||||||
log('NetworkManager disposed');
|
log('NetworkManager disposed');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -15,9 +15,9 @@ const SummaryManager = (function() {
|
|||||||
function updateElement(elementId, value) {
|
function updateElement(elementId, value) {
|
||||||
const element = document.getElementById(elementId);
|
const element = document.getElementById(elementId);
|
||||||
if (!element) return false;
|
if (!element) return false;
|
||||||
|
|
||||||
const safeValue = (value !== undefined && value !== null)
|
const safeValue = (value !== undefined && value !== null)
|
||||||
? value
|
? value
|
||||||
: (element.dataset.lastValue || 0);
|
: (element.dataset.lastValue || 0);
|
||||||
|
|
||||||
element.dataset.lastValue = safeValue;
|
element.dataset.lastValue = safeValue;
|
||||||
@@ -32,8 +32,8 @@ const SummaryManager = (function() {
|
|||||||
element.textContent = safeValue;
|
element.textContent = safeValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (['offers-counter', 'bid-requests-counter', 'sent-bids-counter',
|
if (['offers-counter', 'bid-requests-counter', 'sent-bids-counter',
|
||||||
'recv-bids-counter', 'swaps-counter', 'network-offers-counter',
|
'recv-bids-counter', 'swaps-counter', 'network-offers-counter',
|
||||||
'watched-outputs-counter'].includes(elementId)) {
|
'watched-outputs-counter'].includes(elementId)) {
|
||||||
element.classList.remove('bg-blue-500', 'bg-gray-400');
|
element.classList.remove('bg-blue-500', 'bg-gray-400');
|
||||||
element.classList.add(safeValue > 0 ? 'bg-blue-500' : 'bg-gray-400');
|
element.classList.add(safeValue > 0 ? 'bg-blue-500' : 'bg-gray-400');
|
||||||
@@ -57,7 +57,7 @@ const SummaryManager = (function() {
|
|||||||
|
|
||||||
function updateUIFromData(data) {
|
function updateUIFromData(data) {
|
||||||
if (!data) return;
|
if (!data) return;
|
||||||
|
|
||||||
updateElement('network-offers-counter', data.num_network_offers);
|
updateElement('network-offers-counter', data.num_network_offers);
|
||||||
updateElement('offers-counter', data.num_sent_active_offers);
|
updateElement('offers-counter', data.num_sent_active_offers);
|
||||||
updateElement('sent-bids-counter', data.num_sent_active_bids);
|
updateElement('sent-bids-counter', data.num_sent_active_bids);
|
||||||
@@ -65,7 +65,7 @@ const SummaryManager = (function() {
|
|||||||
updateElement('bid-requests-counter', data.num_available_bids);
|
updateElement('bid-requests-counter', data.num_available_bids);
|
||||||
updateElement('swaps-counter', data.num_swapping);
|
updateElement('swaps-counter', data.num_swapping);
|
||||||
updateElement('watched-outputs-counter', data.num_watched_outputs);
|
updateElement('watched-outputs-counter', data.num_watched_outputs);
|
||||||
|
|
||||||
const shutdownButtons = document.querySelectorAll('.shutdown-button');
|
const shutdownButtons = document.querySelectorAll('.shutdown-button');
|
||||||
shutdownButtons.forEach(button => {
|
shutdownButtons.forEach(button => {
|
||||||
button.setAttribute('data-active-swaps', data.num_swapping);
|
button.setAttribute('data-active-swaps', data.num_swapping);
|
||||||
@@ -83,7 +83,7 @@ const SummaryManager = (function() {
|
|||||||
|
|
||||||
function cacheSummaryData(data) {
|
function cacheSummaryData(data) {
|
||||||
if (!data) return;
|
if (!data) return;
|
||||||
|
|
||||||
localStorage.setItem('summary_data_cache', JSON.stringify({
|
localStorage.setItem('summary_data_cache', JSON.stringify({
|
||||||
timestamp: Date.now(),
|
timestamp: Date.now(),
|
||||||
data: data
|
data: data
|
||||||
@@ -92,24 +92,24 @@ const SummaryManager = (function() {
|
|||||||
|
|
||||||
function getCachedSummaryData() {
|
function getCachedSummaryData() {
|
||||||
let cachedData = null;
|
let cachedData = null;
|
||||||
|
|
||||||
cachedData = localStorage.getItem('summary_data_cache');
|
cachedData = localStorage.getItem('summary_data_cache');
|
||||||
if (!cachedData) return null;
|
if (!cachedData) return null;
|
||||||
|
|
||||||
const parsedCache = JSON.parse(cachedData);
|
const parsedCache = JSON.parse(cachedData);
|
||||||
const maxAge = 24 * 60 * 60 * 1000;
|
const maxAge = 24 * 60 * 60 * 1000;
|
||||||
|
|
||||||
if (Date.now() - parsedCache.timestamp < maxAge) {
|
if (Date.now() - parsedCache.timestamp < maxAge) {
|
||||||
return parsedCache.data;
|
return parsedCache.data;
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
function fetchSummaryDataWithTimeout() {
|
function fetchSummaryDataWithTimeout() {
|
||||||
const controller = new AbortController();
|
const controller = new AbortController();
|
||||||
const timeoutId = setTimeout(() => controller.abort(), config.requestTimeout);
|
const timeoutId = setTimeout(() => controller.abort(), config.requestTimeout);
|
||||||
|
|
||||||
return fetch(config.summaryEndpoint, {
|
return fetch(config.summaryEndpoint, {
|
||||||
signal: controller.signal,
|
signal: controller.signal,
|
||||||
headers: {
|
headers: {
|
||||||
@@ -120,11 +120,11 @@ const SummaryManager = (function() {
|
|||||||
})
|
})
|
||||||
.then(response => {
|
.then(response => {
|
||||||
clearTimeout(timeoutId);
|
clearTimeout(timeoutId);
|
||||||
|
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
throw new Error(`HTTP error! Status: ${response.status}`);
|
throw new Error(`HTTP error! Status: ${response.status}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
return response.json();
|
return response.json();
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
@@ -138,21 +138,21 @@ const SummaryManager = (function() {
|
|||||||
webSocket.close();
|
webSocket.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
const wsPort = window.config?.wsPort ||
|
const wsPort = window.config?.wsPort ||
|
||||||
(typeof determineWebSocketPort === 'function' ? determineWebSocketPort() : '11700');
|
(typeof determineWebSocketPort === 'function' ? determineWebSocketPort() : '11700');
|
||||||
|
|
||||||
const wsUrl = "ws://" + window.location.hostname + ":" + wsPort;
|
const wsUrl = "ws://" + window.location.hostname + ":" + wsPort;
|
||||||
webSocket = new WebSocket(wsUrl);
|
webSocket = new WebSocket(wsUrl);
|
||||||
|
|
||||||
webSocket.onopen = () => {
|
webSocket.onopen = () => {
|
||||||
publicAPI.fetchSummaryData()
|
publicAPI.fetchSummaryData()
|
||||||
.then(() => {})
|
.then(() => {})
|
||||||
.catch(() => {});
|
.catch(() => {});
|
||||||
};
|
};
|
||||||
|
|
||||||
webSocket.onmessage = (event) => {
|
webSocket.onmessage = (event) => {
|
||||||
let data;
|
let data;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
data = JSON.parse(event.data);
|
data = JSON.parse(event.data);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -161,18 +161,18 @@ const SummaryManager = (function() {
|
|||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data.event) {
|
if (data.event) {
|
||||||
publicAPI.fetchSummaryData()
|
publicAPI.fetchSummaryData()
|
||||||
.then(() => {})
|
.then(() => {})
|
||||||
.catch(() => {});
|
.catch(() => {});
|
||||||
|
|
||||||
if (window.NotificationManager && typeof window.NotificationManager.handleWebSocketEvent === 'function') {
|
if (window.NotificationManager && typeof window.NotificationManager.handleWebSocketEvent === 'function') {
|
||||||
window.NotificationManager.handleWebSocketEvent(data);
|
window.NotificationManager.handleWebSocketEvent(data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
webSocket.onclose = () => {
|
webSocket.onclose = () => {
|
||||||
setTimeout(setupWebSocket, 5000);
|
setTimeout(setupWebSocket, 5000);
|
||||||
};
|
};
|
||||||
@@ -185,8 +185,8 @@ const SummaryManager = (function() {
|
|||||||
template.innerHTML = document.querySelector('[id^="swapContainer"]')?.innerHTML || '';
|
template.innerHTML = document.querySelector('[id^="swapContainer"]')?.innerHTML || '';
|
||||||
document.body.appendChild(template);
|
document.body.appendChild(template);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!document.getElementById('swap-in-progress-green-template') &&
|
if (!document.getElementById('swap-in-progress-green-template') &&
|
||||||
document.querySelector('[id^="swapContainer"]')?.innerHTML) {
|
document.querySelector('[id^="swapContainer"]')?.innerHTML) {
|
||||||
const greenTemplate = document.createElement('template');
|
const greenTemplate = document.createElement('template');
|
||||||
greenTemplate.id = 'swap-in-progress-green-template';
|
greenTemplate.id = 'swap-in-progress-green-template';
|
||||||
@@ -229,7 +229,7 @@ const SummaryManager = (function() {
|
|||||||
|
|
||||||
if (window.WebSocketManager && typeof window.WebSocketManager.initialize === 'function') {
|
if (window.WebSocketManager && typeof window.WebSocketManager.initialize === 'function') {
|
||||||
const wsManager = window.WebSocketManager;
|
const wsManager = window.WebSocketManager;
|
||||||
|
|
||||||
if (!wsManager.isConnected()) {
|
if (!wsManager.isConnected()) {
|
||||||
wsManager.connect();
|
wsManager.connect();
|
||||||
}
|
}
|
||||||
@@ -239,7 +239,7 @@ const SummaryManager = (function() {
|
|||||||
this.fetchSummaryData()
|
this.fetchSummaryData()
|
||||||
.then(() => {})
|
.then(() => {})
|
||||||
.catch(() => {});
|
.catch(() => {});
|
||||||
|
|
||||||
if (window.NotificationManager && typeof window.NotificationManager.handleWebSocketEvent === 'function') {
|
if (window.NotificationManager && typeof window.NotificationManager.handleWebSocketEvent === 'function') {
|
||||||
window.NotificationManager.handleWebSocketEvent(data);
|
window.NotificationManager.handleWebSocketEvent(data);
|
||||||
}
|
}
|
||||||
@@ -302,7 +302,7 @@ const SummaryManager = (function() {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
startRefreshTimer: function() {
|
startRefreshTimer: function() {
|
||||||
startRefreshTimer();
|
startRefreshTimer();
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -26,14 +26,14 @@ const TooltipManager = (function() {
|
|||||||
|
|
||||||
create(element, content, options = {}) {
|
create(element, content, options = {}) {
|
||||||
if (!element) return null;
|
if (!element) return null;
|
||||||
|
|
||||||
this.destroy(element);
|
this.destroy(element);
|
||||||
|
|
||||||
if (this.tooltipElementsMap.size > this.maxTooltips * this.cleanupThreshold) {
|
if (this.tooltipElementsMap.size > this.maxTooltips * this.cleanupThreshold) {
|
||||||
const oldestEntries = Array.from(this.tooltipElementsMap.entries())
|
const oldestEntries = Array.from(this.tooltipElementsMap.entries())
|
||||||
.sort((a, b) => a[1].timestamp - b[1].timestamp)
|
.sort((a, b) => a[1].timestamp - b[1].timestamp)
|
||||||
.slice(0, 20);
|
.slice(0, 20);
|
||||||
|
|
||||||
oldestEntries.forEach(([el]) => {
|
oldestEntries.forEach(([el]) => {
|
||||||
this.destroy(el);
|
this.destroy(el);
|
||||||
});
|
});
|
||||||
@@ -199,7 +199,7 @@ const TooltipManager = (function() {
|
|||||||
instance[0].destroy();
|
instance[0].destroy();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.warn('Error destroying tooltip:', e);
|
console.warn('Error destroying tooltip:', e);
|
||||||
|
|
||||||
const tippyRoot = document.querySelector(`[data-for-tooltip-id="${id}"]`);
|
const tippyRoot = document.querySelector(`[data-for-tooltip-id="${id}"]`);
|
||||||
if (tippyRoot && tippyRoot.parentNode) {
|
if (tippyRoot && tippyRoot.parentNode) {
|
||||||
tippyRoot.parentNode.removeChild(tippyRoot);
|
tippyRoot.parentNode.removeChild(tippyRoot);
|
||||||
@@ -209,7 +209,7 @@ const TooltipManager = (function() {
|
|||||||
|
|
||||||
this.activeTooltips.delete(element);
|
this.activeTooltips.delete(element);
|
||||||
this.tooltipElementsMap.delete(element);
|
this.tooltipElementsMap.delete(element);
|
||||||
|
|
||||||
element.removeAttribute('data-tooltip-trigger-id');
|
element.removeAttribute('data-tooltip-trigger-id');
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -355,7 +355,7 @@ const TooltipManager = (function() {
|
|||||||
this.handleVisibilityChange = () => {
|
this.handleVisibilityChange = () => {
|
||||||
if (document.hidden) {
|
if (document.hidden) {
|
||||||
this.cleanup();
|
this.cleanup();
|
||||||
|
|
||||||
if (window.MemoryManager) {
|
if (window.MemoryManager) {
|
||||||
window.MemoryManager.forceCleanup();
|
window.MemoryManager.forceCleanup();
|
||||||
}
|
}
|
||||||
@@ -365,7 +365,7 @@ const TooltipManager = (function() {
|
|||||||
window.addEventListener('beforeunload', this.boundCleanup);
|
window.addEventListener('beforeunload', this.boundCleanup);
|
||||||
window.addEventListener('unload', this.boundCleanup);
|
window.addEventListener('unload', this.boundCleanup);
|
||||||
document.addEventListener('visibilitychange', this.handleVisibilityChange);
|
document.addEventListener('visibilitychange', this.handleVisibilityChange);
|
||||||
|
|
||||||
if (window.CleanupManager) {
|
if (window.CleanupManager) {
|
||||||
window.CleanupManager.registerResource('tooltipManager', this, (tm) => tm.dispose());
|
window.CleanupManager.registerResource('tooltipManager', this, (tm) => tm.dispose());
|
||||||
}
|
}
|
||||||
@@ -471,7 +471,7 @@ const TooltipManager = (function() {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
this.mutationObserver.observe(document.body, {
|
this.mutationObserver.observe(document.body, {
|
||||||
childList: true,
|
childList: true,
|
||||||
subtree: true
|
subtree: true
|
||||||
});
|
});
|
||||||
@@ -497,7 +497,7 @@ const TooltipManager = (function() {
|
|||||||
cancelAnimationFrame(id);
|
cancelAnimationFrame(id);
|
||||||
});
|
});
|
||||||
this.pendingAnimationFrames.clear();
|
this.pendingAnimationFrames.clear();
|
||||||
|
|
||||||
if (this.mutationObserver) {
|
if (this.mutationObserver) {
|
||||||
this.mutationObserver.disconnect();
|
this.mutationObserver.disconnect();
|
||||||
this.mutationObserver = null;
|
this.mutationObserver = null;
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ const WalletManager = (function() {
|
|||||||
'Decred': 'DCR',
|
'Decred': 'DCR',
|
||||||
'Bitcoin Cash': 'BCH'
|
'Bitcoin Cash': 'BCH'
|
||||||
},
|
},
|
||||||
|
|
||||||
coingeckoIds: {
|
coingeckoIds: {
|
||||||
'BTC': 'btc',
|
'BTC': 'btc',
|
||||||
'PART': 'part',
|
'PART': 'part',
|
||||||
@@ -51,7 +51,7 @@ const WalletManager = (function() {
|
|||||||
'DCR': 'dcr',
|
'DCR': 'dcr',
|
||||||
'BCH': 'bch'
|
'BCH': 'bch'
|
||||||
},
|
},
|
||||||
|
|
||||||
shortNames: {
|
shortNames: {
|
||||||
'Bitcoin': 'BTC',
|
'Bitcoin': 'BTC',
|
||||||
'Particl': 'PART',
|
'Particl': 'PART',
|
||||||
@@ -99,9 +99,9 @@ const WalletManager = (function() {
|
|||||||
try {
|
try {
|
||||||
const processedData = {};
|
const processedData = {};
|
||||||
const currentSource = config.priceSource.primary;
|
const currentSource = config.priceSource.primary;
|
||||||
|
|
||||||
const shouldIncludeWow = currentSource === 'coingecko.com';
|
const shouldIncludeWow = currentSource === 'coingecko.com';
|
||||||
|
|
||||||
const coinsToFetch = Object.values(coinData.symbols)
|
const coinsToFetch = Object.values(coinData.symbols)
|
||||||
.filter(symbol => shouldIncludeWow || symbol !== 'WOW')
|
.filter(symbol => shouldIncludeWow || symbol !== 'WOW')
|
||||||
.map(symbol => coinData.coingeckoIds[symbol] || symbol.toLowerCase())
|
.map(symbol => coinData.coingeckoIds[symbol] || symbol.toLowerCase())
|
||||||
@@ -171,8 +171,8 @@ const WalletManager = (function() {
|
|||||||
lastError = error;
|
lastError = error;
|
||||||
console.error(`Price fetch attempt ${attempt + 1} failed:`, error);
|
console.error(`Price fetch attempt ${attempt + 1} failed:`, error);
|
||||||
|
|
||||||
if (attempt === config.maxRetries - 1 &&
|
if (attempt === config.maxRetries - 1 &&
|
||||||
config.priceSource.fallback &&
|
config.priceSource.fallback &&
|
||||||
config.priceSource.fallback !== config.priceSource.primary) {
|
config.priceSource.fallback !== config.priceSource.primary) {
|
||||||
const temp = config.priceSource.primary;
|
const temp = config.priceSource.primary;
|
||||||
config.priceSource.primary = config.priceSource.fallback;
|
config.priceSource.primary = config.priceSource.fallback;
|
||||||
@@ -269,14 +269,14 @@ const WalletManager = (function() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const coinId = coinName.toLowerCase().replace(' ', '-');
|
const coinId = coinName.toLowerCase().replace(' ', '-');
|
||||||
|
|
||||||
if (!prices[coinId]) {
|
if (!prices[coinId]) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const price = prices[coinId]?.usd || parseFloat(localStorage.getItem(`${coinId}-price`) || '0');
|
const price = prices[coinId]?.usd || parseFloat(localStorage.getItem(`${coinId}-price`) || '0');
|
||||||
if (!price) return;
|
if (!price) return;
|
||||||
|
|
||||||
const usdValue = (amount * price).toFixed(2);
|
const usdValue = (amount * price).toFixed(2);
|
||||||
|
|
||||||
if (coinName === 'Particl') {
|
if (coinName === 'Particl') {
|
||||||
@@ -300,7 +300,7 @@ const WalletManager = (function() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let usdEl = null;
|
let usdEl = null;
|
||||||
|
|
||||||
const flexContainer = el.closest('.flex');
|
const flexContainer = el.closest('.flex');
|
||||||
if (flexContainer) {
|
if (flexContainer) {
|
||||||
const nextFlex = flexContainer.nextElementSibling;
|
const nextFlex = flexContainer.nextElementSibling;
|
||||||
@@ -384,7 +384,7 @@ const WalletManager = (function() {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateTotalValues(totalUsd, btcPrice) {
|
function updateTotalValues(totalUsd, btcPrice) {
|
||||||
const totalUsdEl = document.getElementById('total-usd-value');
|
const totalUsdEl = document.getElementById('total-usd-value');
|
||||||
if (totalUsdEl) {
|
if (totalUsdEl) {
|
||||||
@@ -439,7 +439,7 @@ const WalletManager = (function() {
|
|||||||
|
|
||||||
const eyeIcon = document.querySelector("#hide-usd-amount-toggle svg");
|
const eyeIcon = document.querySelector("#hide-usd-amount-toggle svg");
|
||||||
if (eyeIcon) {
|
if (eyeIcon) {
|
||||||
eyeIcon.innerHTML = isVisible ?
|
eyeIcon.innerHTML = isVisible ?
|
||||||
'<path d="M23.444,10.239C21.905,8.062,17.708,3,12,3S2.1,8.062,.555,10.24a3.058,3.058,0,0,0,0,3.52h0C2.1,15.938,6.292,21,12,21s9.905-5.062,11.445-7.24A3.058,3.058,0,0,0,23.444,10.239ZM12,17a5,5,0,1,1,5-5A5,5,0,0,1,12,17Z"></path>' :
|
'<path d="M23.444,10.239C21.905,8.062,17.708,3,12,3S2.1,8.062,.555,10.24a3.058,3.058,0,0,0,0,3.52h0C2.1,15.938,6.292,21,12,21s9.905-5.062,11.445-7.24A3.058,3.058,0,0,0,23.444,10.239ZM12,17a5,5,0,1,1,5-5A5,5,0,0,1,12,17Z"></path>' :
|
||||||
'<path d="M23.444,10.239a22.936,22.936,0,0,0-2.492-2.948l-4.021,4.021A5.026,5.026,0,0,1,17,12a5,5,0,0,1-5,5,5.026,5.026,0,0,1-.688-.069L8.055,20.188A10.286,10.286,0,0,0,12,21c5.708,0,9.905-5.062,11.445-7.24A3.058,3.058,0,0,0,23.444,10.239Z"></path><path d="M12,3C6.292,3,2.1,8.062,.555,10.24a3.058,3.058,0,0,0,0,3.52h0a21.272,21.272,0,0,0,4.784,4.9l3.124-3.124a5,5,0,0,1,7.071-7.072L8.464,15.536l10.2-10.2A11.484,11.484,0,0,0,12,3Z"></path><path data-color="color-2" d="M1,24a1,1,0,0,1-.707-1.707l22-22a1,1,0,0,1,1.414,1.414l-22,22A1,1,0,0,1,1,24Z"></path>';
|
'<path d="M23.444,10.239a22.936,22.936,0,0,0-2.492-2.948l-4.021,4.021A5.026,5.026,0,0,1,17,12a5,5,0,0,1-5,5,5.026,5.026,0,0,1-.688-.069L8.055,20.188A10.286,10.286,0,0,0,12,21c5.708,0,9.905-5.062,11.445-7.24A3.058,3.058,0,0,0,23.444,10.239Z"></path><path d="M12,3C6.292,3,2.1,8.062,.555,10.24a3.058,3.058,0,0,0,0,3.52h0a21.272,21.272,0,0,0,4.784,4.9l3.124-3.124a5,5,0,0,1,7.071-7.072L8.464,15.536l10.2-10.2A11.484,11.484,0,0,0,12,3Z"></path><path data-color="color-2" d="M1,24a1,1,0,0,1-.707-1.707l22-22a1,1,0,0,1,1.414,1.414l-22,22A1,1,0,0,1,1,24Z"></path>';
|
||||||
}
|
}
|
||||||
@@ -500,7 +500,7 @@ const WalletManager = (function() {
|
|||||||
document.querySelectorAll('.coinname-value').forEach(el => {
|
document.querySelectorAll('.coinname-value').forEach(el => {
|
||||||
el.textContent = '****';
|
el.textContent = '****';
|
||||||
});
|
});
|
||||||
|
|
||||||
document.querySelectorAll('.usd-value').forEach(el => {
|
document.querySelectorAll('.usd-value').forEach(el => {
|
||||||
el.textContent = '****';
|
el.textContent = '****';
|
||||||
});
|
});
|
||||||
@@ -542,7 +542,7 @@ const WalletManager = (function() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
state.lastUpdateTime = parseInt(localStorage.getItem(stateKeys.lastUpdate) || '0');
|
state.lastUpdateTime = parseInt(localStorage.getItem(stateKeys.lastUpdate) || '0');
|
||||||
state.isWalletsPage = document.querySelector('.wallet-list') !== null ||
|
state.isWalletsPage = document.querySelector('.wallet-list') !== null ||
|
||||||
window.location.pathname.includes('/wallets');
|
window.location.pathname.includes('/wallets');
|
||||||
|
|
||||||
document.querySelectorAll('.usd-value').forEach(el => {
|
document.querySelectorAll('.usd-value').forEach(el => {
|
||||||
@@ -553,7 +553,7 @@ const WalletManager = (function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
storeOriginalValues();
|
storeOriginalValues();
|
||||||
|
|
||||||
if (localStorage.getItem('balancesVisible') === null) {
|
if (localStorage.getItem('balancesVisible') === null) {
|
||||||
localStorage.setItem('balancesVisible', 'true');
|
localStorage.setItem('balancesVisible', 'true');
|
||||||
}
|
}
|
||||||
@@ -581,7 +581,7 @@ const WalletManager = (function() {
|
|||||||
|
|
||||||
state.initialized = true;
|
state.initialized = true;
|
||||||
console.log('WalletManager initialized');
|
console.log('WalletManager initialized');
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -606,7 +606,7 @@ const WalletManager = (function() {
|
|||||||
if (fallbackSource) {
|
if (fallbackSource) {
|
||||||
config.priceSource.fallback = fallbackSource;
|
config.priceSource.fallback = fallbackSource;
|
||||||
}
|
}
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
@@ -43,12 +43,12 @@ const WebSocketManager = (function() {
|
|||||||
wsPort = window.ws_port.toString();
|
wsPort = window.ws_port.toString();
|
||||||
return wsPort;
|
return wsPort;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof getWebSocketConfig === 'function') {
|
if (typeof getWebSocketConfig === 'function') {
|
||||||
const wsConfig = getWebSocketConfig();
|
const wsConfig = getWebSocketConfig();
|
||||||
wsPort = (wsConfig.port || wsConfig.fallbackPort || '11700').toString();
|
wsPort = (wsConfig.port || wsConfig.fallbackPort || '11700').toString();
|
||||||
return wsPort;
|
return wsPort;
|
||||||
}
|
}
|
||||||
|
|
||||||
wsPort = '11700';
|
wsPort = '11700';
|
||||||
return wsPort;
|
return wsPort;
|
||||||
@@ -62,14 +62,14 @@ const WebSocketManager = (function() {
|
|||||||
startHealthCheck();
|
startHealthCheck();
|
||||||
|
|
||||||
log('WebSocketManager initialized with options:', options);
|
log('WebSocketManager initialized with options:', options);
|
||||||
|
|
||||||
if (window.CleanupManager) {
|
if (window.CleanupManager) {
|
||||||
window.CleanupManager.registerResource('webSocketManager', this, (mgr) => mgr.dispose());
|
window.CleanupManager.registerResource('webSocketManager', this, (mgr) => mgr.dispose());
|
||||||
}
|
}
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
},
|
},
|
||||||
|
|
||||||
connect: function() {
|
connect: function() {
|
||||||
if (state.isConnecting || state.isIntentionallyClosed) {
|
if (state.isConnecting || state.isIntentionallyClosed) {
|
||||||
log('Connection attempt blocked - already connecting or intentionally closed');
|
log('Connection attempt blocked - already connecting or intentionally closed');
|
||||||
@@ -87,7 +87,7 @@ const WebSocketManager = (function() {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
const wsPort = determineWebSocketPort();
|
const wsPort = determineWebSocketPort();
|
||||||
|
|
||||||
if (!wsPort) {
|
if (!wsPort) {
|
||||||
state.isConnecting = false;
|
state.isConnecting = false;
|
||||||
return false;
|
return false;
|
||||||
@@ -129,7 +129,7 @@ const WebSocketManager = (function() {
|
|||||||
log('Cannot send message - not connected');
|
log('Cannot send message - not connected');
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
ws.send(JSON.stringify(message));
|
ws.send(JSON.stringify(message));
|
||||||
return true;
|
return true;
|
||||||
@@ -143,13 +143,13 @@ const WebSocketManager = (function() {
|
|||||||
if (!state.messageHandlers[type]) {
|
if (!state.messageHandlers[type]) {
|
||||||
state.messageHandlers[type] = {};
|
state.messageHandlers[type] = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
const handlerId = generateHandlerId();
|
const handlerId = generateHandlerId();
|
||||||
state.messageHandlers[type][handlerId] = handler;
|
state.messageHandlers[type][handlerId] = handler;
|
||||||
|
|
||||||
return handlerId;
|
return handlerId;
|
||||||
},
|
},
|
||||||
|
|
||||||
removeMessageHandler: function(type, handlerId) {
|
removeMessageHandler: function(type, handlerId) {
|
||||||
if (state.messageHandlers[type] && state.messageHandlers[type][handlerId]) {
|
if (state.messageHandlers[type] && state.messageHandlers[type][handlerId]) {
|
||||||
delete state.messageHandlers[type][handlerId];
|
delete state.messageHandlers[type][handlerId];
|
||||||
@@ -158,7 +158,7 @@ const WebSocketManager = (function() {
|
|||||||
|
|
||||||
cleanup: function() {
|
cleanup: function() {
|
||||||
log('Cleaning up WebSocket resources');
|
log('Cleaning up WebSocket resources');
|
||||||
|
|
||||||
clearTimeout(state.connectTimeout);
|
clearTimeout(state.connectTimeout);
|
||||||
stopHealthCheck();
|
stopHealthCheck();
|
||||||
|
|
||||||
@@ -211,11 +211,11 @@ const WebSocketManager = (function() {
|
|||||||
resume: function() {
|
resume: function() {
|
||||||
log('WebSocketManager resumed');
|
log('WebSocketManager resumed');
|
||||||
state.isIntentionallyClosed = false;
|
state.isIntentionallyClosed = false;
|
||||||
|
|
||||||
if (!this.isConnected()) {
|
if (!this.isConnected()) {
|
||||||
this.connect();
|
this.connect();
|
||||||
}
|
}
|
||||||
|
|
||||||
startHealthCheck();
|
startHealthCheck();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -264,16 +264,16 @@ const WebSocketManager = (function() {
|
|||||||
log('WebSocket closed:', event);
|
log('WebSocket closed:', event);
|
||||||
state.isConnecting = false;
|
state.isConnecting = false;
|
||||||
window.ws = null;
|
window.ws = null;
|
||||||
|
|
||||||
if (typeof updateConnectionStatus === 'function') {
|
if (typeof updateConnectionStatus === 'function') {
|
||||||
updateConnectionStatus('disconnected');
|
updateConnectionStatus('disconnected');
|
||||||
}
|
}
|
||||||
|
|
||||||
notifyHandlers('disconnect', {
|
notifyHandlers('disconnect', {
|
||||||
code: event.code,
|
code: event.code,
|
||||||
reason: event.reason
|
reason: event.reason
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!state.isIntentionallyClosed) {
|
if (!state.isIntentionallyClosed) {
|
||||||
handleReconnect();
|
handleReconnect();
|
||||||
}
|
}
|
||||||
@@ -292,12 +292,12 @@ const WebSocketManager = (function() {
|
|||||||
document.addEventListener('visibilitychange', visibilityChangeHandler);
|
document.addEventListener('visibilitychange', visibilityChangeHandler);
|
||||||
state.listeners.visibilityChange = visibilityChangeHandler;
|
state.listeners.visibilityChange = visibilityChangeHandler;
|
||||||
}
|
}
|
||||||
|
|
||||||
function handlePageHidden() {
|
function handlePageHidden() {
|
||||||
log('Page hidden');
|
log('Page hidden');
|
||||||
state.isPageHidden = true;
|
state.isPageHidden = true;
|
||||||
stopHealthCheck();
|
stopHealthCheck();
|
||||||
|
|
||||||
if (ws && ws.readyState === WebSocket.OPEN) {
|
if (ws && ws.readyState === WebSocket.OPEN) {
|
||||||
state.isIntentionallyClosed = true;
|
state.isIntentionallyClosed = true;
|
||||||
ws.close(1000, 'Page hidden');
|
ws.close(1000, 'Page hidden');
|
||||||
@@ -308,7 +308,7 @@ const WebSocketManager = (function() {
|
|||||||
log('Page visible');
|
log('Page visible');
|
||||||
state.isPageHidden = false;
|
state.isPageHidden = false;
|
||||||
state.isIntentionallyClosed = false;
|
state.isIntentionallyClosed = false;
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
if (!publicAPI.isConnected()) {
|
if (!publicAPI.isConnected()) {
|
||||||
publicAPI.connect();
|
publicAPI.connect();
|
||||||
@@ -323,7 +323,7 @@ const WebSocketManager = (function() {
|
|||||||
performHealthCheck();
|
performHealthCheck();
|
||||||
}, 30000);
|
}, 30000);
|
||||||
}
|
}
|
||||||
|
|
||||||
function stopHealthCheck() {
|
function stopHealthCheck() {
|
||||||
if (state.healthCheckInterval) {
|
if (state.healthCheckInterval) {
|
||||||
clearInterval(state.healthCheckInterval);
|
clearInterval(state.healthCheckInterval);
|
||||||
@@ -340,7 +340,7 @@ const WebSocketManager = (function() {
|
|||||||
|
|
||||||
const now = Date.now();
|
const now = Date.now();
|
||||||
const lastCheck = state.lastHealthCheck;
|
const lastCheck = state.lastHealthCheck;
|
||||||
|
|
||||||
if (lastCheck && (now - lastCheck) > 60000) {
|
if (lastCheck && (now - lastCheck) > 60000) {
|
||||||
log('Health check failed - too long since last check');
|
log('Health check failed - too long since last check');
|
||||||
handleReconnect();
|
handleReconnect();
|
||||||
@@ -401,10 +401,10 @@ const WebSocketManager = (function() {
|
|||||||
|
|
||||||
function cleanup() {
|
function cleanup() {
|
||||||
log('Cleaning up WebSocket resources');
|
log('Cleaning up WebSocket resources');
|
||||||
|
|
||||||
clearTimeout(state.connectTimeout);
|
clearTimeout(state.connectTimeout);
|
||||||
stopHealthCheck();
|
stopHealthCheck();
|
||||||
|
|
||||||
if (state.reconnectTimeout) {
|
if (state.reconnectTimeout) {
|
||||||
clearTimeout(state.reconnectTimeout);
|
clearTimeout(state.reconnectTimeout);
|
||||||
state.reconnectTimeout = null;
|
state.reconnectTimeout = null;
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ const Ajax = {
|
|||||||
if (xhr.status === 200) {
|
if (xhr.status === 200) {
|
||||||
if (onSuccess) {
|
if (onSuccess) {
|
||||||
try {
|
try {
|
||||||
const response = xhr.responseText.startsWith('{') ?
|
const response = xhr.responseText.startsWith('{') ?
|
||||||
JSON.parse(xhr.responseText) : xhr.responseText;
|
JSON.parse(xhr.responseText) : xhr.responseText;
|
||||||
onSuccess(response);
|
onSuccess(response);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@@ -153,10 +153,10 @@ const RateManager = {
|
|||||||
|
|
||||||
const params = 'coin_from=' + selectedCoin + '&coin_to=' + coinTo;
|
const params = 'coin_from=' + selectedCoin + '&coin_to=' + coinTo;
|
||||||
|
|
||||||
Ajax.post('/json/rates', params,
|
Ajax.post('/json/rates', params,
|
||||||
(response) => {
|
(response) => {
|
||||||
if (ratesDisplay) {
|
if (ratesDisplay) {
|
||||||
ratesDisplay.innerHTML = typeof response === 'string' ?
|
ratesDisplay.innerHTML = typeof response === 'string' ?
|
||||||
response : '<pre><code>' + JSON.stringify(response, null, ' ') + '</code></pre>';
|
response : '<pre><code>' + JSON.stringify(response, null, ' ') + '</code></pre>';
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -167,7 +167,7 @@ const RateManager = {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
||||||
getRateInferred: (event) => {
|
getRateInferred: (event) => {
|
||||||
if (event) event.preventDefault();
|
if (event) event.preventDefault();
|
||||||
|
|
||||||
@@ -180,12 +180,12 @@ const RateManager = {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const params = 'coin_from=' + encodeURIComponent(coinFrom) +
|
const params = 'coin_from=' + encodeURIComponent(coinFrom) +
|
||||||
'&coin_to=' + encodeURIComponent(coinTo);
|
'&coin_to=' + encodeURIComponent(coinTo);
|
||||||
|
|
||||||
DOM.setValue('rate', 'Loading...');
|
DOM.setValue('rate', 'Loading...');
|
||||||
|
|
||||||
Ajax.post('/json/rates', params,
|
Ajax.post('/json/rates', params,
|
||||||
(response) => {
|
(response) => {
|
||||||
if (response.coingecko && response.coingecko.rate_inferred) {
|
if (response.coingecko && response.coingecko.rate_inferred) {
|
||||||
DOM.setValue('rate', response.coingecko.rate_inferred);
|
DOM.setValue('rate', response.coingecko.rate_inferred);
|
||||||
@@ -213,7 +213,7 @@ const RateManager = {
|
|||||||
swapType: DOM.get('swap_type')
|
swapType: DOM.get('swap_type')
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!elements.coinFrom || !elements.coinTo ||
|
if (!elements.coinFrom || !elements.coinTo ||
|
||||||
!elements.amtFrom || !elements.amtTo || !elements.rate) {
|
!elements.amtFrom || !elements.amtTo || !elements.rate) {
|
||||||
console.log('Required elements for setRate not found');
|
console.log('Required elements for setRate not found');
|
||||||
return;
|
return;
|
||||||
@@ -225,7 +225,7 @@ const RateManager = {
|
|||||||
amtFrom: elements.amtFrom.value,
|
amtFrom: elements.amtFrom.value,
|
||||||
amtTo: elements.amtTo.value,
|
amtTo: elements.amtTo.value,
|
||||||
rate: elements.rate.value,
|
rate: elements.rate.value,
|
||||||
lockRate: elements.rate.value == '' ? false :
|
lockRate: elements.rate.value == '' ? false :
|
||||||
(elements.rateLock ? elements.rateLock.checked : false)
|
(elements.rateLock ? elements.rateLock.checked : false)
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -236,8 +236,8 @@ const RateManager = {
|
|||||||
|
|
||||||
if (elements.swapType) {
|
if (elements.swapType) {
|
||||||
SwapTypeManager.setSwapTypeEnabled(
|
SwapTypeManager.setSwapTypeEnabled(
|
||||||
values.coinFrom,
|
values.coinFrom,
|
||||||
values.coinTo,
|
values.coinTo,
|
||||||
elements.swapType
|
elements.swapType
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -248,8 +248,8 @@ const RateManager = {
|
|||||||
|
|
||||||
let params = 'coin_from=' + values.coinFrom + '&coin_to=' + values.coinTo;
|
let params = 'coin_from=' + values.coinFrom + '&coin_to=' + values.coinTo;
|
||||||
|
|
||||||
if (valueChanged == 'rate' ||
|
if (valueChanged == 'rate' ||
|
||||||
(values.lockRate && valueChanged == 'amt_from') ||
|
(values.lockRate && valueChanged == 'amt_from') ||
|
||||||
(values.amtTo == '' && valueChanged == 'amt_from')) {
|
(values.amtTo == '' && valueChanged == 'amt_from')) {
|
||||||
|
|
||||||
if (values.rate == '' || (values.amtFrom == '' && values.amtTo == '')) {
|
if (values.rate == '' || (values.amtFrom == '' && values.amtTo == '')) {
|
||||||
@@ -274,7 +274,7 @@ const RateManager = {
|
|||||||
params += '&amt_from=' + values.amtFrom + '&amt_to=' + values.amtTo;
|
params += '&amt_from=' + values.amtFrom + '&amt_to=' + values.amtTo;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ajax.post('/json/rate', params,
|
Ajax.post('/json/rate', params,
|
||||||
(response) => {
|
(response) => {
|
||||||
if (response.hasOwnProperty('rate')) {
|
if (response.hasOwnProperty('rate')) {
|
||||||
DOM.setValue('rate', response.rate);
|
DOM.setValue('rate', response.rate);
|
||||||
@@ -314,13 +314,13 @@ const SwapTypeManager = {
|
|||||||
coinFrom = String(coinFrom);
|
coinFrom = String(coinFrom);
|
||||||
coinTo = String(coinTo);
|
coinTo = String(coinTo);
|
||||||
|
|
||||||
if (SwapTypeManager.adaptor_sig_only_coins.includes(coinFrom) ||
|
if (SwapTypeManager.adaptor_sig_only_coins.includes(coinFrom) ||
|
||||||
SwapTypeManager.adaptor_sig_only_coins.includes(coinTo)) {
|
SwapTypeManager.adaptor_sig_only_coins.includes(coinTo)) {
|
||||||
swapTypeElement.disabled = true;
|
swapTypeElement.disabled = true;
|
||||||
swapTypeElement.value = 'xmr_swap';
|
swapTypeElement.value = 'xmr_swap';
|
||||||
makeHidden = true;
|
makeHidden = true;
|
||||||
swapTypeElement.classList.add('select-disabled');
|
swapTypeElement.classList.add('select-disabled');
|
||||||
} else if (SwapTypeManager.secret_hash_only_coins.includes(coinFrom) ||
|
} else if (SwapTypeManager.secret_hash_only_coins.includes(coinFrom) ||
|
||||||
SwapTypeManager.secret_hash_only_coins.includes(coinTo)) {
|
SwapTypeManager.secret_hash_only_coins.includes(coinTo)) {
|
||||||
swapTypeElement.disabled = true;
|
swapTypeElement.disabled = true;
|
||||||
swapTypeElement.value = 'seller_first';
|
swapTypeElement.value = 'seller_first';
|
||||||
@@ -426,7 +426,7 @@ const UIEnhancer = {
|
|||||||
const name = selectedOption.textContent.trim();
|
const name = selectedOption.textContent.trim();
|
||||||
selectCache[select.id] = { image, name };
|
selectCache[select.id] = { image, name };
|
||||||
}
|
}
|
||||||
|
|
||||||
function setSelectData(select) {
|
function setSelectData(select) {
|
||||||
if (!select || !select.options || select.selectedIndex === undefined) return;
|
if (!select || !select.options || select.selectedIndex === undefined) return;
|
||||||
|
|
||||||
@@ -457,9 +457,9 @@ const UIEnhancer = {
|
|||||||
const options = select.querySelectorAll('option');
|
const options = select.querySelectorAll('option');
|
||||||
const selectIcon = select.parentElement?.querySelector('.select-icon');
|
const selectIcon = select.parentElement?.querySelector('.select-icon');
|
||||||
const selectImage = select.parentElement?.querySelector('.select-image');
|
const selectImage = select.parentElement?.querySelector('.select-image');
|
||||||
|
|
||||||
if (!options || !selectIcon || !selectImage) return;
|
if (!options || !selectIcon || !selectImage) return;
|
||||||
|
|
||||||
options.forEach(option => {
|
options.forEach(option => {
|
||||||
const image = option.getAttribute('data-image');
|
const image = option.getAttribute('data-image');
|
||||||
if (image) {
|
if (image) {
|
||||||
@@ -476,7 +476,7 @@ const UIEnhancer = {
|
|||||||
setSelectData(select);
|
setSelectData(select);
|
||||||
Storage.setRaw(select.name, select.value);
|
Storage.setRaw(select.name, select.value);
|
||||||
});
|
});
|
||||||
|
|
||||||
setSelectData(select);
|
setSelectData(select);
|
||||||
selectIcon.style.display = 'none';
|
selectIcon.style.display = 'none';
|
||||||
selectImage.style.display = 'none';
|
selectImage.style.display = 'none';
|
||||||
|
|||||||
@@ -145,7 +145,7 @@ const api = {
|
|||||||
const apiResponse = await Api.fetchCoinGeckoData({
|
const apiResponse = await Api.fetchCoinGeckoData({
|
||||||
coinGecko: window.config.getAPIKeys().coinGecko
|
coinGecko: window.config.getAPIKeys().coinGecko
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!apiResponse || !apiResponse.rates) {
|
if (!apiResponse || !apiResponse.rates) {
|
||||||
if (fallbackData) {
|
if (fallbackData) {
|
||||||
return fallbackData;
|
return fallbackData;
|
||||||
@@ -174,7 +174,7 @@ const api = {
|
|||||||
const wowResponse = await Api.fetchCoinPrices("wownero", {
|
const wowResponse = await Api.fetchCoinPrices("wownero", {
|
||||||
coinGecko: window.config.getAPIKeys().coinGecko
|
coinGecko: window.config.getAPIKeys().coinGecko
|
||||||
});
|
});
|
||||||
|
|
||||||
if (wowResponse && wowResponse.rates && wowResponse.rates.wownero) {
|
if (wowResponse && wowResponse.rates && wowResponse.rates.wownero) {
|
||||||
transformedData['wow'] = {
|
transformedData['wow'] = {
|
||||||
current_price: wowResponse.rates.wownero,
|
current_price: wowResponse.rates.wownero,
|
||||||
@@ -189,9 +189,9 @@ const api = {
|
|||||||
console.error('Error fetching WOW price:', wowError);
|
console.error('Error fetching WOW price:', wowError);
|
||||||
}
|
}
|
||||||
|
|
||||||
const missingCoins = window.config.coins.filter(coin =>
|
const missingCoins = window.config.coins.filter(coin =>
|
||||||
!transformedData[coin.symbol.toLowerCase()] &&
|
!transformedData[coin.symbol.toLowerCase()] &&
|
||||||
fallbackData &&
|
fallbackData &&
|
||||||
fallbackData[coin.symbol.toLowerCase()]
|
fallbackData[coin.symbol.toLowerCase()]
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -203,11 +203,11 @@ const api = {
|
|||||||
});
|
});
|
||||||
|
|
||||||
CacheManager.set(cacheKey, transformedData, 'prices');
|
CacheManager.set(cacheKey, transformedData, 'prices');
|
||||||
|
|
||||||
if (NetworkManager.getReconnectAttempts() > 0) {
|
if (NetworkManager.getReconnectAttempts() > 0) {
|
||||||
NetworkManager.resetReconnectAttempts();
|
NetworkManager.resetReconnectAttempts();
|
||||||
}
|
}
|
||||||
|
|
||||||
return transformedData;
|
return transformedData;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error fetching coin data:', error);
|
console.error('Error fetching coin data:', error);
|
||||||
@@ -250,8 +250,8 @@ const api = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const historicalData = await Api.fetchHistoricalData(
|
const historicalData = await Api.fetchHistoricalData(
|
||||||
coinSymbols,
|
coinSymbols,
|
||||||
window.config.currentResolution,
|
window.config.currentResolution,
|
||||||
{
|
{
|
||||||
cryptoCompare: window.config.getAPIKeys().cryptoCompare
|
cryptoCompare: window.config.getAPIKeys().cryptoCompare
|
||||||
}
|
}
|
||||||
@@ -260,7 +260,7 @@ const api = {
|
|||||||
Object.keys(historicalData).forEach(coin => {
|
Object.keys(historicalData).forEach(coin => {
|
||||||
if (historicalData[coin]) {
|
if (historicalData[coin]) {
|
||||||
results[coin] = historicalData[coin];
|
results[coin] = historicalData[coin];
|
||||||
|
|
||||||
const cacheKey = `historical_${coin}_${window.config.currentResolution}`;
|
const cacheKey = `historical_${coin}_${window.config.currentResolution}`;
|
||||||
CacheManager.set(cacheKey, historicalData[coin], 'historical');
|
CacheManager.set(cacheKey, historicalData[coin], 'historical');
|
||||||
}
|
}
|
||||||
@@ -279,7 +279,7 @@ const api = {
|
|||||||
results[coin] = cachedData.value;
|
results[coin] = cachedData.value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -317,7 +317,7 @@ const rateLimiter = {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
await this.requestQueue[apiName];
|
await this.requestQueue[apiName];
|
||||||
|
|
||||||
const executeRequest = async () => {
|
const executeRequest = async () => {
|
||||||
const waitTime = this.getWaitTime(apiName);
|
const waitTime = this.getWaitTime(apiName);
|
||||||
if (waitTime > 0) {
|
if (waitTime > 0) {
|
||||||
@@ -335,7 +335,7 @@ const rateLimiter = {
|
|||||||
return this.queueRequest(apiName, requestFn, retryCount + 1);
|
return this.queueRequest(apiName, requestFn, retryCount + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((error.message.includes('timeout') || error.name === 'NetworkError') &&
|
if ((error.message.includes('timeout') || error.name === 'NetworkError') &&
|
||||||
retryCount < this.retryDelays.length) {
|
retryCount < this.retryDelays.length) {
|
||||||
const delay = this.retryDelays[retryCount];
|
const delay = this.retryDelays[retryCount];
|
||||||
logger.warn(`Request failed, retrying in ${delay/1000} seconds...`);
|
logger.warn(`Request failed, retrying in ${delay/1000} seconds...`);
|
||||||
@@ -350,12 +350,12 @@ const rateLimiter = {
|
|||||||
this.requestQueue[apiName] = executeRequest();
|
this.requestQueue[apiName] = executeRequest();
|
||||||
return await this.requestQueue[apiName];
|
return await this.requestQueue[apiName];
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (error.message.includes('429') ||
|
if (error.message.includes('429') ||
|
||||||
error.message.includes('timeout') ||
|
error.message.includes('timeout') ||
|
||||||
error.name === 'NetworkError') {
|
error.name === 'NetworkError') {
|
||||||
|
|
||||||
NetworkManager.handleNetworkError(error);
|
NetworkManager.handleNetworkError(error);
|
||||||
|
|
||||||
const cachedData = CacheManager.get(`coinData_${apiName}`);
|
const cachedData = CacheManager.get(`coinData_${apiName}`);
|
||||||
if (cachedData) {
|
if (cachedData) {
|
||||||
return cachedData.value;
|
return cachedData.value;
|
||||||
@@ -375,7 +375,7 @@ const ui = {
|
|||||||
const volumeElement = document.querySelector(`#${coin.toLowerCase()}-volume-24h`);
|
const volumeElement = document.querySelector(`#${coin.toLowerCase()}-volume-24h`);
|
||||||
const btcPriceDiv = document.querySelector(`#${coin.toLowerCase()}-btc-price-div`);
|
const btcPriceDiv = document.querySelector(`#${coin.toLowerCase()}-btc-price-div`);
|
||||||
const priceBtcElement = document.querySelector(`#${coin.toLowerCase()}-price-btc`);
|
const priceBtcElement = document.querySelector(`#${coin.toLowerCase()}-price-btc`);
|
||||||
|
|
||||||
if (priceUsdElement) {
|
if (priceUsdElement) {
|
||||||
priceUsdElement.textContent = isError ? 'N/A' : `$ ${ui.formatPrice(coin, priceUSD)}`;
|
priceUsdElement.textContent = isError ? 'N/A' : `$ ${ui.formatPrice(coin, priceUSD)}`;
|
||||||
}
|
}
|
||||||
@@ -490,8 +490,8 @@ const ui = {
|
|||||||
if (priceChange === null || priceChange === undefined) {
|
if (priceChange === null || priceChange === undefined) {
|
||||||
container.innerHTML = 'N/A';
|
container.innerHTML = 'N/A';
|
||||||
} else {
|
} else {
|
||||||
container.innerHTML = priceChange >= 0 ?
|
container.innerHTML = priceChange >= 0 ?
|
||||||
ui.positivePriceChangeHTML(priceChange) :
|
ui.positivePriceChangeHTML(priceChange) :
|
||||||
ui.negativePriceChangeHTML(priceChange);
|
ui.negativePriceChangeHTML(priceChange);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -504,7 +504,7 @@ const ui = {
|
|||||||
lastRefreshedElement.textContent = `Last Refreshed: ${formattedTime}`;
|
lastRefreshedElement.textContent = `Last Refreshed: ${formattedTime}`;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
updateConnectionStatus: () => {
|
updateConnectionStatus: () => {
|
||||||
const statusElement = document.getElementById('connection-status');
|
const statusElement = document.getElementById('connection-status');
|
||||||
if (statusElement) {
|
if (statusElement) {
|
||||||
@@ -599,12 +599,12 @@ const ui = {
|
|||||||
NetworkManager.manualReconnect();
|
NetworkManager.manualReconnect();
|
||||||
};
|
};
|
||||||
|
|
||||||
const buttonContainer = errorOverlay.querySelector('.button-container') ||
|
const buttonContainer = errorOverlay.querySelector('.button-container') ||
|
||||||
document.createElement('div');
|
document.createElement('div');
|
||||||
buttonContainer.className = "button-container mt-4";
|
buttonContainer.className = "button-container mt-4";
|
||||||
buttonContainer.innerHTML = '';
|
buttonContainer.innerHTML = '';
|
||||||
buttonContainer.appendChild(reconnectBtn);
|
buttonContainer.appendChild(reconnectBtn);
|
||||||
|
|
||||||
if (!errorOverlay.querySelector('.button-container')) {
|
if (!errorOverlay.querySelector('.button-container')) {
|
||||||
errorOverlay.querySelector('div').appendChild(buttonContainer);
|
errorOverlay.querySelector('div').appendChild(buttonContainer);
|
||||||
}
|
}
|
||||||
@@ -701,7 +701,7 @@ const chartModule = {
|
|||||||
const gradient = ctx.createLinearGradient(0, 0, 0, 400);
|
const gradient = ctx.createLinearGradient(0, 0, 0, 400);
|
||||||
gradient.addColorStop(0, 'rgba(77, 132, 240, 0.2)');
|
gradient.addColorStop(0, 'rgba(77, 132, 240, 0.2)');
|
||||||
gradient.addColorStop(1, 'rgba(77, 132, 240, 0)');
|
gradient.addColorStop(1, 'rgba(77, 132, 240, 0)');
|
||||||
|
|
||||||
chartModule.chart = new Chart(ctx, {
|
chartModule.chart = new Chart(ctx, {
|
||||||
type: 'line',
|
type: 'line',
|
||||||
data: {
|
data: {
|
||||||
@@ -897,7 +897,7 @@ const chartModule = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
rawDataPoints.sort((a, b) => a.time - b.time);
|
rawDataPoints.sort((a, b) => a.time - b.time);
|
||||||
|
|
||||||
let preparedData = [];
|
let preparedData = [];
|
||||||
|
|
||||||
if (window.config.currentResolution === 'day') {
|
if (window.config.currentResolution === 'day') {
|
||||||
@@ -918,7 +918,7 @@ const chartModule = {
|
|||||||
closestPoint = point;
|
closestPoint = point;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (closestPoint) {
|
if (closestPoint) {
|
||||||
preparedData.push({
|
preparedData.push({
|
||||||
x: hourUnix,
|
x: hourUnix,
|
||||||
@@ -940,7 +940,7 @@ const chartModule = {
|
|||||||
y: point.close
|
y: point.close
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (preparedData.length === 0 && rawDataPoints.length > 0) {
|
if (preparedData.length === 0 && rawDataPoints.length > 0) {
|
||||||
preparedData = rawDataPoints.map(point => ({
|
preparedData = rawDataPoints.map(point => ({
|
||||||
x: point.time,
|
x: point.time,
|
||||||
@@ -965,7 +965,7 @@ const chartModule = {
|
|||||||
|
|
||||||
if (data.length > 0) {
|
if (data.length > 0) {
|
||||||
const closestDataPoint = data.reduce((prev, curr) =>
|
const closestDataPoint = data.reduce((prev, curr) =>
|
||||||
Math.abs(new Date(curr.x).getTime() - targetTime.getTime()) <
|
Math.abs(new Date(curr.x).getTime() - targetTime.getTime()) <
|
||||||
Math.abs(new Date(prev.x).getTime() - targetTime.getTime()) ? curr : prev
|
Math.abs(new Date(prev.x).getTime() - targetTime.getTime()) ? curr : prev
|
||||||
, data[0]);
|
, data[0]);
|
||||||
hourlyData.push({
|
hourlyData.push({
|
||||||
@@ -989,7 +989,7 @@ const chartModule = {
|
|||||||
}
|
}
|
||||||
chartModule.loadStartTime = Date.now();
|
chartModule.loadStartTime = Date.now();
|
||||||
const cacheKey = `chartData_${coinSymbol}_${window.config.currentResolution}`;
|
const cacheKey = `chartData_${coinSymbol}_${window.config.currentResolution}`;
|
||||||
let cachedData = !forceRefresh ? CacheManager.get(cacheKey) : null;
|
const cachedData = !forceRefresh ? CacheManager.get(cacheKey) : null;
|
||||||
let data;
|
let data;
|
||||||
if (cachedData && Object.keys(cachedData.value).length > 0) {
|
if (cachedData && Object.keys(cachedData.value).length > 0) {
|
||||||
data = cachedData.value;
|
data = cachedData.value;
|
||||||
@@ -1001,7 +1001,7 @@ const chartModule = {
|
|||||||
|
|
||||||
const allData = await api.fetchHistoricalDataXHR([coinSymbol]);
|
const allData = await api.fetchHistoricalDataXHR([coinSymbol]);
|
||||||
data = allData[coinSymbol];
|
data = allData[coinSymbol];
|
||||||
|
|
||||||
if (!data || Object.keys(data).length === 0) {
|
if (!data || Object.keys(data).length === 0) {
|
||||||
throw new Error(`No data returned for ${coinSymbol}`);
|
throw new Error(`No data returned for ${coinSymbol}`);
|
||||||
}
|
}
|
||||||
@@ -1009,7 +1009,7 @@ const chartModule = {
|
|||||||
CacheManager.set(cacheKey, data, 'chart');
|
CacheManager.set(cacheKey, data, 'chart');
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
NetworkManager.handleNetworkError(error);
|
NetworkManager.handleNetworkError(error);
|
||||||
|
|
||||||
if (error.message.includes('429') && currentChartData.length > 0) {
|
if (error.message.includes('429') && currentChartData.length > 0) {
|
||||||
console.warn(`Rate limit hit for ${coinSymbol}, maintaining current chart`);
|
console.warn(`Rate limit hit for ${coinSymbol}, maintaining current chart`);
|
||||||
chartModule.hideChartLoader();
|
chartModule.hideChartLoader();
|
||||||
@@ -1041,7 +1041,7 @@ const chartModule = {
|
|||||||
chartModule.chart.options.scales.x.time.unit = 'hour';
|
chartModule.chart.options.scales.x.time.unit = 'hour';
|
||||||
} else {
|
} else {
|
||||||
const resolution = window.config.chartConfig.resolutions[window.config.currentResolution];
|
const resolution = window.config.chartConfig.resolutions[window.config.currentResolution];
|
||||||
chartModule.chart.options.scales.x.time.unit =
|
chartModule.chart.options.scales.x.time.unit =
|
||||||
resolution && resolution.interval === 'hourly' ? 'hour' :
|
resolution && resolution.interval === 'hourly' ? 'hour' :
|
||||||
window.config.currentResolution === 'year' ? 'month' : 'day';
|
window.config.currentResolution === 'year' ? 'month' : 'day';
|
||||||
}
|
}
|
||||||
@@ -1086,7 +1086,7 @@ const chartModule = {
|
|||||||
loader.classList.add('hidden');
|
loader.classList.add('hidden');
|
||||||
chart.classList.remove('hidden');
|
chart.classList.remove('hidden');
|
||||||
},
|
},
|
||||||
|
|
||||||
cleanup: function() {
|
cleanup: function() {
|
||||||
this.destroyChart();
|
this.destroyChart();
|
||||||
this.currentCoin = null;
|
this.currentCoin = null;
|
||||||
@@ -1181,7 +1181,7 @@ const app = {
|
|||||||
0
|
0
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
return app;
|
return app;
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -1223,13 +1223,13 @@ const app = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
loadAllCoinData: async function() {
|
loadAllCoinData: async function() {
|
||||||
try {
|
try {
|
||||||
if (!NetworkManager.isOnline()) {
|
if (!NetworkManager.isOnline()) {
|
||||||
throw new Error('Network is offline');
|
throw new Error('Network is offline');
|
||||||
}
|
}
|
||||||
|
|
||||||
const allCoinData = await api.fetchCoinGeckoDataXHR();
|
const allCoinData = await api.fetchCoinGeckoDataXHR();
|
||||||
if (allCoinData.error) {
|
if (allCoinData.error) {
|
||||||
throw new Error(allCoinData.error);
|
throw new Error(allCoinData.error);
|
||||||
@@ -1242,7 +1242,7 @@ const app = {
|
|||||||
|
|
||||||
for (const coin of window.config.coins) {
|
for (const coin of window.config.coins) {
|
||||||
const coinData = allCoinData[coin.symbol.toLowerCase()];
|
const coinData = allCoinData[coin.symbol.toLowerCase()];
|
||||||
|
|
||||||
if (coinData) {
|
if (coinData) {
|
||||||
coinData.displayName = coin.displayName || coin.symbol;
|
coinData.displayName = coin.displayName || coin.symbol;
|
||||||
|
|
||||||
@@ -1409,7 +1409,7 @@ const app = {
|
|||||||
const lastGeckoRequest = rateLimiter.lastRequestTime['coingecko'] || 0;
|
const lastGeckoRequest = rateLimiter.lastRequestTime['coingecko'] || 0;
|
||||||
const timeSinceLastRequest = Date.now() - lastGeckoRequest;
|
const timeSinceLastRequest = Date.now() - lastGeckoRequest;
|
||||||
const waitTime = Math.max(0, rateLimiter.minRequestInterval.coingecko - timeSinceLastRequest);
|
const waitTime = Math.max(0, rateLimiter.minRequestInterval.coingecko - timeSinceLastRequest);
|
||||||
|
|
||||||
if (waitTime > 0) {
|
if (waitTime > 0) {
|
||||||
const seconds = Math.ceil(waitTime / 1000);
|
const seconds = Math.ceil(waitTime / 1000);
|
||||||
ui.displayErrorMessage(`Rate limit: Please wait ${seconds} seconds before refreshing`);
|
ui.displayErrorMessage(`Rate limit: Please wait ${seconds} seconds before refreshing`);
|
||||||
@@ -1480,7 +1480,7 @@ const app = {
|
|||||||
if (cachedData && cachedData.value && cachedData.value.total_volume) {
|
if (cachedData && cachedData.value && cachedData.value.total_volume) {
|
||||||
coinData.total_volume = cachedData.value.total_volume;
|
coinData.total_volume = cachedData.value.total_volume;
|
||||||
}
|
}
|
||||||
if (cachedData && cachedData.value && cachedData.value.price_change_percentage_24h &&
|
if (cachedData && cachedData.value && cachedData.value.price_change_percentage_24h &&
|
||||||
!coinData.price_change_percentage_24h) {
|
!coinData.price_change_percentage_24h) {
|
||||||
coinData.price_change_percentage_24h = cachedData.value.price_change_percentage_24h;
|
coinData.price_change_percentage_24h = cachedData.value.price_change_percentage_24h;
|
||||||
}
|
}
|
||||||
@@ -1541,7 +1541,7 @@ const app = {
|
|||||||
|
|
||||||
let countdown = 10;
|
let countdown = 10;
|
||||||
ui.displayErrorMessage(`Refresh failed: ${error.message}. Please try again later. (${countdown}s)`);
|
ui.displayErrorMessage(`Refresh failed: ${error.message}. Please try again later. (${countdown}s)`);
|
||||||
|
|
||||||
const countdownInterval = setInterval(() => {
|
const countdownInterval = setInterval(() => {
|
||||||
countdown--;
|
countdown--;
|
||||||
if (countdown > 0) {
|
if (countdown > 0) {
|
||||||
@@ -1652,7 +1652,7 @@ const app = {
|
|||||||
if (!NetworkManager.isOnline()) {
|
if (!NetworkManager.isOnline()) {
|
||||||
throw new Error('Network is offline');
|
throw new Error('Network is offline');
|
||||||
}
|
}
|
||||||
|
|
||||||
const response = await Api.fetchCoinPrices("bitcoin");
|
const response = await Api.fetchCoinPrices("bitcoin");
|
||||||
|
|
||||||
if (response && response.rates && response.rates.bitcoin) {
|
if (response && response.rates && response.rates.bitcoin) {
|
||||||
@@ -1715,7 +1715,7 @@ resolutionButtons.forEach(button => {
|
|||||||
button.addEventListener('click', () => {
|
button.addEventListener('click', () => {
|
||||||
const resolution = button.id.split('-')[1];
|
const resolution = button.id.split('-')[1];
|
||||||
const currentCoin = chartModule.currentCoin;
|
const currentCoin = chartModule.currentCoin;
|
||||||
|
|
||||||
if (currentCoin !== 'WOW' || resolution === 'day') {
|
if (currentCoin !== 'WOW' || resolution === 'day') {
|
||||||
window.config.currentResolution = resolution;
|
window.config.currentResolution = resolution;
|
||||||
chartModule.updateChart(currentCoin, true);
|
chartModule.updateChart(currentCoin, true);
|
||||||
@@ -1726,12 +1726,12 @@ resolutionButtons.forEach(button => {
|
|||||||
|
|
||||||
function cleanup() {
|
function cleanup() {
|
||||||
console.log('Starting cleanup process');
|
console.log('Starting cleanup process');
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (window.MemoryManager) {
|
if (window.MemoryManager) {
|
||||||
MemoryManager.forceCleanup();
|
MemoryManager.forceCleanup();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (chartModule) {
|
if (chartModule) {
|
||||||
CleanupManager.registerResource('chartModule', chartModule, (cm) => {
|
CleanupManager.registerResource('chartModule', chartModule, (cm) => {
|
||||||
cm.cleanup();
|
cm.cleanup();
|
||||||
@@ -1752,7 +1752,7 @@ function cleanup() {
|
|||||||
|
|
||||||
const cleanupCounts = CleanupManager.clearAll();
|
const cleanupCounts = CleanupManager.clearAll();
|
||||||
console.log('All resources cleaned up:', cleanupCounts);
|
console.log('All resources cleaned up:', cleanupCounts);
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error during cleanup:', error);
|
console.error('Error during cleanup:', error);
|
||||||
CleanupManager.clearAll();
|
CleanupManager.clearAll();
|
||||||
@@ -1801,7 +1801,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
NetworkManager.initialize({
|
NetworkManager.initialize({
|
||||||
connectionTestEndpoint: '/json',
|
connectionTestEndpoint: '/json',
|
||||||
connectionTestTimeout: 3000,
|
connectionTestTimeout: 3000,
|
||||||
reconnectDelay: 5000,
|
reconnectDelay: 5000,
|
||||||
maxReconnectAttempts: 5
|
maxReconnectAttempts: 5
|
||||||
});
|
});
|
||||||
window.networkManagerInitialized = true;
|
window.networkManagerInitialized = true;
|
||||||
|
|||||||
@@ -85,7 +85,7 @@ const getStatusClass = (status, tx_a, tx_b) => {
|
|||||||
|
|
||||||
const getTxStatusClass = (status) => {
|
const getTxStatusClass = (status) => {
|
||||||
if (!status || status === 'None') return 'text-gray-400';
|
if (!status || status === 'None') return 'text-gray-400';
|
||||||
|
|
||||||
if (status.includes('Complete') || status.includes('Confirmed')) {
|
if (status.includes('Complete') || status.includes('Confirmed')) {
|
||||||
return 'text-green-500';
|
return 'text-green-500';
|
||||||
}
|
}
|
||||||
@@ -545,12 +545,12 @@ async function updateSwapsTable(options = {}) {
|
|||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
//console.log('Received swap data:', data);
|
//console.log('Received swap data:', data);
|
||||||
|
|
||||||
state.swapsData = Array.isArray(data)
|
state.swapsData = Array.isArray(data)
|
||||||
? data.filter(swap => {
|
? data.filter(swap => {
|
||||||
const isActive = isActiveSwap(swap);
|
const isActive = isActiveSwap(swap);
|
||||||
//console.log(`Swap ${swap.bid_id}: ${isActive ? 'Active' : 'Inactive'}`, swap.bid_state);
|
//console.log(`Swap ${swap.bid_id}: ${isActive ? 'Active' : 'Inactive'}`, swap.bid_state);
|
||||||
return isActive;
|
return isActive;
|
||||||
})
|
})
|
||||||
: [];
|
: [];
|
||||||
|
|
||||||
//console.log('Filtered active swaps:', state.swapsData);
|
//console.log('Filtered active swaps:', state.swapsData);
|
||||||
@@ -570,7 +570,7 @@ async function updateSwapsTable(options = {}) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const totalPages = Math.ceil(state.swapsData.length / PAGE_SIZE);
|
const totalPages = Math.ceil(state.swapsData.length / PAGE_SIZE);
|
||||||
|
|
||||||
if (resetPage && state.swapsData.length > 0) {
|
if (resetPage && state.swapsData.length > 0) {
|
||||||
state.currentPage = 1;
|
state.currentPage = 1;
|
||||||
}
|
}
|
||||||
@@ -631,18 +631,18 @@ async function updateSwapsTable(options = {}) {
|
|||||||
function isActiveSwap(swap) {
|
function isActiveSwap(swap) {
|
||||||
const activeStates = [
|
const activeStates = [
|
||||||
|
|
||||||
'InProgress',
|
'InProgress',
|
||||||
'Accepted',
|
'Accepted',
|
||||||
'Delaying',
|
'Delaying',
|
||||||
'Auto accept delay',
|
'Auto accept delay',
|
||||||
'Request accepted',
|
'Request accepted',
|
||||||
//'Received',
|
//'Received',
|
||||||
|
|
||||||
'Script coin locked',
|
'Script coin locked',
|
||||||
'Scriptless coin locked',
|
'Scriptless coin locked',
|
||||||
'Script coin lock released',
|
'Script coin lock released',
|
||||||
|
|
||||||
'SendingInitialTx',
|
'SendingInitialTx',
|
||||||
'SendingPaymentTx',
|
'SendingPaymentTx',
|
||||||
|
|
||||||
'Exchanged script lock tx sigs msg',
|
'Exchanged script lock tx sigs msg',
|
||||||
|
|||||||
@@ -62,7 +62,7 @@
|
|||||||
this._handleOutsideClick = this._handleOutsideClick.bind(this);
|
this._handleOutsideClick = this._handleOutsideClick.bind(this);
|
||||||
|
|
||||||
dropdownInstances.push(this);
|
dropdownInstances.push(this);
|
||||||
|
|
||||||
this.init();
|
this.init();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -73,7 +73,7 @@
|
|||||||
this._targetEl.style.position = 'fixed';
|
this._targetEl.style.position = 'fixed';
|
||||||
this._targetEl.style.zIndex = '40';
|
this._targetEl.style.zIndex = '40';
|
||||||
this._targetEl.classList.add('dropdown-menu');
|
this._targetEl.classList.add('dropdown-menu');
|
||||||
|
|
||||||
this._setupEventListeners();
|
this._setupEventListeners();
|
||||||
this._initialized = true;
|
this._initialized = true;
|
||||||
}
|
}
|
||||||
@@ -120,8 +120,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
_handleOutsideClick(e) {
|
_handleOutsideClick(e) {
|
||||||
if (this._visible &&
|
if (this._visible &&
|
||||||
!this._targetEl.contains(e.target) &&
|
!this._targetEl.contains(e.target) &&
|
||||||
!this._triggerEl.contains(e.target)) {
|
!this._triggerEl.contains(e.target)) {
|
||||||
this.hide();
|
this.hide();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user