lockmihai's picture
Add the logic for backend API calls and the logic to update the UI after a backend call returns.
2bc07bb verified
Raw
History Blame Contribute Delete
8.52 kB
// API Base URL
const API_BASE_URL = 'https://api.solbotsentinel.com/v1';
// Initialize tooltips and fetch initial data
document.addEventListener('DOMContentLoaded', () => {
// Add tooltips to action buttons
const actionButtons = document.querySelectorAll('[data-action]');
actionButtons.forEach(button => {
const action = button.getAttribute('data-action');
button.setAttribute('data-tooltip', action.charAt(0).toUpperCase() + action.slice(1));
});
// Load initial data
fetchWallets();
fetchPerformanceStats();
// Set up event listeners
setupEventListeners();
});
function setupEventListeners() {
// Add wallet button
document.querySelector('button[data-action="add-wallet"]')?.addEventListener('click', addWallet);
// Copy trade buttons
document.querySelectorAll('button[data-action="copy-trade"]').forEach(btn => {
btn.addEventListener('click', () => {
const wallet = btn.closest('tr').querySelector('td:first-child p').textContent;
startCopyTrading(wallet);
});
});
// Stop trade buttons
document.querySelectorAll('button[data-action="stop-trade"]').forEach(btn => {
btn.addEventListener('click', () => {
const wallet = btn.closest('tr').querySelector('td:first-child p').textContent;
stopCopyTrading(wallet);
});
});
}
async function fetchWallets() {
try {
const response = await fetch(`${API_BASE_URL}/wallets`);
const data = await response.json();
updateWalletTable(data);
} catch (error) {
console.error('Failed to fetch wallets:', error);
showNotification('error', 'Failed to load wallet data');
}
}
async function fetchPerformanceStats() {
try {
const response = await fetch(`${API_BASE_URL}/performance`);
const data = await response.json();
updatePerformanceStats(data);
} catch (error) {
console.error('Failed to fetch performance stats:', error);
showNotification('error', 'Failed to load performance data');
}
}
function updateWalletTable(wallets) {
const tbody = document.querySelector('tbody');
tbody.innerHTML = '';
wallets.forEach(wallet => {
const row = document.createElement('tr');
row.className = 'hover:bg-gray-700 transition';
row.innerHTML = `
<td class="py-4">
<div class="flex items-center gap-3">
<div class="w-8 h-8 rounded-full bg-primary flex items-center justify-center">
<i data-feather="user" class="w-4 h-4"></i>
</div>
<div>
<p class="font-medium">${wallet.address.substring(0, 4)}...${wallet.address.substring(wallet.address.length - 4)}</p>
<p class="text-xs text-gray-400">Added ${formatDate(wallet.addedAt)}</p>
</div>
</div>
</td>
<td>
<span class="inline-flex items-center px-3 py-1 rounded-full text-sm font-medium ${wallet.status === 'copying' ? 'bg-green-900 text-green-300' : 'bg-gray-700 text-gray-300'}">
<i data-feather="${wallet.status === 'copying' ? 'check-circle' : 'pause'}" class="w-3 h-3 mr-1"></i>
${wallet.status === 'copying' ? 'Copying' : 'Watching'}
</span>
</td>
<td class="${wallet.pnl >= 0 ? 'text-secondary' : 'text-red-500'} font-bold">${wallet.pnl >= 0 ? '+' : ''}${wallet.pnl.toFixed(2)}</td>
<td>
<div class="flex gap-2">
<button class="p-2 rounded-lg hover:bg-gray-700 transition" data-action="view">
<i data-feather="eye"></i>
</button>
${wallet.status === 'copying' ?
`<button class="p-2 rounded-lg hover:bg-gray-700 transition" data-action="stop-trade">
<i data-feather="stop-circle" class="text-red-500"></i>
</button>` :
`<button class="p-2 rounded-lg hover:bg-gray-700 transition" data-action="copy-trade">
<i data-feather="play" class="text-secondary"></i>
</button>`
}
</div>
</td>
`;
tbody.appendChild(row);
});
feather.replace();
}
function updatePerformanceStats(stats) {
document.querySelector('.stats-total-profit').textContent = `+${stats.totalProfit.toFixed(2)}`;
document.querySelector('.stats-total-loss').textContent = `-${Math.abs(stats.totalLoss).toFixed(2)}`;
document.querySelector('.stats-win-rate').textContent = `${stats.winRate.toFixed(1)}%`;
document.querySelector('.stats-active-trades').textContent = stats.activeTrades;
}
async function addWallet() {
const walletInput = document.querySelector('input[placeholder="Enter wallet address"]');
const walletAddress = walletInput.value.trim();
if (!walletAddress || walletAddress.length < 10) {
showNotification('error', 'Please enter a valid wallet address');
return;
}
try {
const response = await fetch(`${API_BASE_URL}/wallets`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ address: walletAddress })
});
if (!response.ok) {
throw new Error(await response.text());
}
walletInput.value = '';
showNotification('success', `Wallet ${walletAddress.substring(0, 6)}... added successfully`);
fetchWallets(); // Refresh wallet list
} catch (error) {
console.error('Failed to add wallet:', error);
showNotification('error', error.message || 'Failed to add wallet');
}
}
async function startCopyTrading(walletAddress) {
try {
const response = await fetch(`${API_BASE_URL}/copy-trade/start`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ address: walletAddress })
});
if (!response.ok) {
throw new Error(await response.text());
}
showNotification('success', `Started copy trading for wallet ${walletAddress.substring(0, 6)}...`);
fetchWallets(); // Refresh wallet list
fetchPerformanceStats(); // Refresh stats
} catch (error) {
console.error('Failed to start copy trading:', error);
showNotification('error', error.message || 'Failed to start copy trading');
}
}
async function stopCopyTrading(walletAddress) {
try {
const response = await fetch(`${API_BASE_URL}/copy-trade/stop`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ address: walletAddress })
});
if (!response.ok) {
throw new Error(await response.text());
}
showNotification('success', `Stopped copy trading for wallet ${walletAddress.substring(0, 6)}...`);
fetchWallets(); // Refresh wallet list
fetchPerformanceStats(); // Refresh stats
} catch (error) {
console.error('Failed to stop copy trading:', error);
showNotification('error', error.message || 'Failed to stop copy trading');
}
}
function showNotification(type, message) {
const notification = document.createElement('div');
notification.className = `fixed top-4 right-4 p-4 rounded-lg shadow-lg z-50 transform transition-all duration-300 ${type === 'error' ? 'bg-red-500' : 'bg-green-500'}`;
notification.textContent = message;
document.body.appendChild(notification);
setTimeout(() => {
notification.style.transform = 'translateX(200%)';
setTimeout(() => notification.remove(), 300);
}, 3000);
}
function formatDate(timestamp) {
const now = new Date();
const date = new Date(timestamp);
const diffInDays = Math.floor((now - date) / (1000 * 60 * 60 * 24));
if (diffInDays === 0) return 'today';
if (diffInDays === 1) return 'yesterday';
if (diffInDays < 7) return `${diffInDays} days ago`;
if (diffInDays < 30) return `${Math.floor(diffInDays/7)} weeks ago`;
return `${Math.floor(diffInDays/30)} months ago`;
}