EricSam commited on
Commit
304477b
Β·
verified Β·
1 Parent(s): 4e0862d

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +43 -40
index.html CHANGED
@@ -15,7 +15,7 @@
15
  theme: {
16
  extend: {
17
  colors: {
18
- primary: '#1E90FF', // Updated to Dodger Blue to match image
19
  secondary: '#8b5cf6',
20
  darkBg: '#111827',
21
  darkCard: '#1f2937',
@@ -50,7 +50,7 @@
50
  transition: max-height 0.3s ease-in-out;
51
  }
52
  .api-form.open {
53
- max-height: 200px; /* Adjust based on content height */
54
  }
55
  </style>
56
  </head>
@@ -315,22 +315,24 @@
315
  localStorage.setItem('bingxApiKey', API_KEY);
316
  localStorage.setItem('bingxApiSecret', API_SECRET);
317
  alert('API credentials saved successfully! Syncing data...');
318
- fetchData(); // Reload data with new credentials
319
- apiForm.classList.remove('open'); // Close form
320
  } else {
321
  alert('Please enter both API Key and Secret.');
322
  }
323
  });
324
 
325
  // Generate Signature
326
- function generateSignature(params) {
327
- // Sort params by key
328
- const sortedParams = Object.keys(params).sort().reduce((obj, key) => {
329
- obj[key] = params[key];
330
- return obj;
331
- }, {});
332
- const queryString = new URLSearchParams(sortedParams).toString();
333
- return CryptoJS.HmacSHA256(queryString, API_SECRET).toString(CryptoJS.enc.Hex);
 
 
334
  }
335
 
336
  // Fetch from API
@@ -338,13 +340,17 @@
338
  if (!API_KEY || !API_SECRET) {
339
  throw new Error('API Key and Secret are not set. Please enter your credentials.');
340
  }
341
- params.timestamp = Date.now();
342
- params.recvWindow = 5000; // Optional, check if needed
343
- // Do not include IP restriction parameters; assume disabled in API key settings
344
- const signature = generateSignature(params);
345
- params.signature = signature;
346
- const url = `${API_BASE_URL}${endpoint}?${new URLSearchParams(params)}`;
347
- const response = await fetch(url, { method: 'GET', headers: { 'X-BX-APIKEY': API_KEY } });
 
 
 
 
348
  if (!response.ok) {
349
  const errorText = await response.text();
350
  throw new Error(`API Error ${response.status}: ${errorText}`);
@@ -354,34 +360,31 @@
354
 
355
  // Fetch Specific Data
356
  async function fetchBalance() {
357
- const data = await fetchFromAPI('/openApi/swap/v2/account/balance');
358
- // Updated parsing for V2 response structure
359
- return data.data.assets.find(b => b.asset === 'USDT')?.walletBalance || 0;
360
  }
361
 
362
  async function fetchOpenPositions() {
363
- const data = await fetchFromAPI('/openApi/swap/v2/position');
364
- // Updated for V2 response structure
365
  return data.data || [];
366
  }
367
 
368
  async function fetchTradeHistory() {
369
- const data = await fetchFromAPI('/openApi/swap/v2/trade/history', { limit: 100 });
370
- // Updated for V2 response structure
371
  return data.data || [];
372
  }
373
 
374
  // Helper Functions
375
  function calculateTodayProfit(trades) {
376
  const today = new Date().toDateString();
377
- return trades.filter(trade => new Date(trade.closeTime).toDateString() === today)
378
- .reduce((sum, trade) => sum + (trade.realizedProfit || 0), 0);
379
  }
380
 
381
  function calculateAdvancedStats(trades) {
382
  let totalProfit = 0, totalLoss = 0, wins = 0;
383
  trades.forEach(trade => {
384
- const pl = trade.realizedProfit || 0;
385
  if (pl > 0) { totalProfit += pl; wins++; } else { totalLoss += Math.abs(pl); }
386
  });
387
  const profitFactor = totalLoss ? (totalProfit / totalLoss) : 0;
@@ -406,7 +409,7 @@
406
  tbody.innerHTML += `
407
  <tr class="border-b border-gray-200 dark:border-gray-700">
408
  <td class="py-4">${pos.symbol}</td>
409
- <td class="py-4"><span class="${pos.side === 'Long' ? 'bg-green-100 text-green-800' : 'bg-red-100 text-red-800'} px-2 py-1 rounded">${pos.side}</span></td>
410
  <td class="py-4">${pos.quantity}</td>
411
  <td class="py-4">$${pos.entryPrice.toFixed(2)}</td>
412
  <td class="py-4 font-medium">$${pos.markPrice.toFixed(2)}</td>
@@ -419,11 +422,11 @@
419
  tbody.innerHTML += `
420
  <tr class="border-b border-gray-200 dark:border-gray-700">
421
  <td class="py-4">${trade.symbol}</td>
422
- <td class="py-4"><span class="${trade.side === 'Long' ? 'bg-green-100 text-green-800' : 'bg-red-100 text-red-800'} px-2 py-1 rounded">${trade.side}</span></td>
423
- <td class="py-4">${trade.quantity}</td>
424
- <td class="py-4">$${trade.entryPrice.toFixed(2)}</td>
425
- <td class="py-4 font-medium">$${trade.exitPrice.toFixed(2)}</td>
426
- <td class="py-4 font-bold ${trade.realizedProfit > 0 ? 'text-green-500' : 'text-red-500'}">$${trade.realizedProfit.toFixed(2)}</td>
427
  <td class="py-4"><span class="px-2 py-1 rounded bg-gray-100 text-gray-800">Closed</span></td>
428
  <td class="py-4 text-right"><button class="text-gray-400 hover:text-primary"><i class="fas fa-ellipsis-v"></i></button></td>
429
  </tr>`;
@@ -444,8 +447,8 @@
444
 
445
  function updatePerformanceChart(trades) {
446
  const monthlyPL = trades.reduce((acc, trade) => {
447
- const month = new Date(trade.closeTime).toLocaleString('default', { month: 'short' });
448
- acc[month] = (acc[month] || 0) + (trade.realizedProfit || 0);
449
  return acc;
450
  }, {});
451
  performanceChart.data.labels = Object.keys(monthlyPL);
@@ -491,7 +494,7 @@
491
 
492
  document.getElementById('total-balance').textContent = `$${balance.toFixed(2)}`;
493
  document.getElementById('open-trades').textContent = positions.length;
494
- const longCount = positions.filter(p => p.side === 'Long').length;
495
  document.getElementById('trade-types').innerHTML = `<span class="font-medium">${longCount} Long</span><span class="text-gray-500 mx-2 dark:text-gray-400">β€’</span><span class="font-medium">${positions.length - longCount} Short</span>`;
496
  const todayProfit = calculateTodayProfit(trades);
497
  document.getElementById('today-profit').textContent = `$${todayProfit.toFixed(2)}`;
@@ -510,7 +513,7 @@
510
  document.getElementById('allocation-update').textContent = `Last updated: ${new Date().toLocaleTimeString()}`;
511
  } catch (error) {
512
  console.error('Error fetching data:', error);
513
- alert(`Failed to sync with BingX API: ${error.message}. Please check your credentials, network, or BingX API documentation.`);
514
  }
515
  }
516
 
@@ -518,7 +521,7 @@
518
  document.getElementById('refresh-btn').addEventListener('click', fetchData);
519
  document.getElementById('sync-now').addEventListener('click', fetchData);
520
  window.addEventListener('load', fetchData);
521
- setInterval(fetchData, 120000); // Refresh every 2 minutes to avoid rate limiting
522
  </script>
523
  </body>
524
  </html>
 
15
  theme: {
16
  extend: {
17
  colors: {
18
+ primary: '#1E90FF',
19
  secondary: '#8b5cf6',
20
  darkBg: '#111827',
21
  darkCard: '#1f2937',
 
50
  transition: max-height 0.3s ease-in-out;
51
  }
52
  .api-form.open {
53
+ max-height: 200px;
54
  }
55
  </style>
56
  </head>
 
315
  localStorage.setItem('bingxApiKey', API_KEY);
316
  localStorage.setItem('bingxApiSecret', API_SECRET);
317
  alert('API credentials saved successfully! Syncing data...');
318
+ fetchData();
319
+ apiForm.classList.remove('open');
320
  } else {
321
  alert('Please enter both API Key and Secret.');
322
  }
323
  });
324
 
325
  // Generate Signature
326
+ function generateSignature(apiSecret, paramsStr) {
327
+ return CryptoJS.HmacSHA256(paramsStr, apiSecret).toString(CryptoJS.enc.Hex);
328
+ }
329
+
330
+ // Parse Parameters
331
+ function parseParams(params) {
332
+ const sortedKeys = Object.keys(params).sort();
333
+ const paramPairs = sortedKeys.map(key => `${key}=${params[key]}`);
334
+ const paramsStr = paramPairs.join('&');
335
+ return paramsStr ? `${paramsStr}&timestamp=${Date.now()}` : `timestamp=${Date.now()}`;
336
  }
337
 
338
  // Fetch from API
 
340
  if (!API_KEY || !API_SECRET) {
341
  throw new Error('API Key and Secret are not set. Please enter your credentials.');
342
  }
343
+ params.recvWindow = params.recvWindow || 5000; // Default to 5000ms if not provided
344
+ const paramsStr = parseParams(params);
345
+ const signature = generateSignature(API_SECRET, paramsStr);
346
+ const url = `${API_BASE_URL}${endpoint}?${paramsStr}&signature=${signature}`;
347
+ const response = await fetch(url, {
348
+ method: 'GET',
349
+ headers: {
350
+ 'X-BX-APIKEY': API_KEY,
351
+ 'Content-Type': 'application/json'
352
+ }
353
+ });
354
  if (!response.ok) {
355
  const errorText = await response.text();
356
  throw new Error(`API Error ${response.status}: ${errorText}`);
 
360
 
361
  // Fetch Specific Data
362
  async function fetchBalance() {
363
+ const data = await fetchFromAPI('/openApi/swap/v3/user/balance');
364
+ return data.data.find(b => b.asset === 'USDT')?.walletBalance || 0;
 
365
  }
366
 
367
  async function fetchOpenPositions() {
368
+ const data = await fetchFromAPI('/openApi/swap/v2/user/positions', { symbol: 'BTC-USDT' }); // Default symbol, adjust as needed
 
369
  return data.data || [];
370
  }
371
 
372
  async function fetchTradeHistory() {
373
+ const data = await fetchFromAPI('/openApi/swap/v2/user/income', { limit: 100 });
 
374
  return data.data || [];
375
  }
376
 
377
  // Helper Functions
378
  function calculateTodayProfit(trades) {
379
  const today = new Date().toDateString();
380
+ return trades.filter(trade => new Date(trade.time).toDateString() === today)
381
+ .reduce((sum, trade) => sum + (trade.income || 0), 0);
382
  }
383
 
384
  function calculateAdvancedStats(trades) {
385
  let totalProfit = 0, totalLoss = 0, wins = 0;
386
  trades.forEach(trade => {
387
+ const pl = trade.income || 0;
388
  if (pl > 0) { totalProfit += pl; wins++; } else { totalLoss += Math.abs(pl); }
389
  });
390
  const profitFactor = totalLoss ? (totalProfit / totalLoss) : 0;
 
409
  tbody.innerHTML += `
410
  <tr class="border-b border-gray-200 dark:border-gray-700">
411
  <td class="py-4">${pos.symbol}</td>
412
+ <td class="py-4"><span class="${pos.positionSide === 'LONG' ? 'bg-green-100 text-green-800' : 'bg-red-100 text-red-800'} px-2 py-1 rounded">${pos.positionSide}</span></td>
413
  <td class="py-4">${pos.quantity}</td>
414
  <td class="py-4">$${pos.entryPrice.toFixed(2)}</td>
415
  <td class="py-4 font-medium">$${pos.markPrice.toFixed(2)}</td>
 
422
  tbody.innerHTML += `
423
  <tr class="border-b border-gray-200 dark:border-gray-700">
424
  <td class="py-4">${trade.symbol}</td>
425
+ <td class="py-4"><span class="${trade.positionSide === 'LONG' ? 'bg-green-100 text-green-800' : 'bg-red-100 text-red-800'} px-2 py-1 rounded">${trade.positionSide}</span></td>
426
+ <td class="py-4">${trade.quantity || 0}</td>
427
+ <td class="py-4">$${trade.entryPrice?.toFixed(2) || '0.00'}</td>
428
+ <td class="py-4 font-medium">$${trade.exitPrice?.toFixed(2) || '0.00'}</td>
429
+ <td class="py-4 font-bold ${trade.income > 0 ? 'text-green-500' : 'text-red-500'}">$${trade.income?.toFixed(2) || '0.00'}</td>
430
  <td class="py-4"><span class="px-2 py-1 rounded bg-gray-100 text-gray-800">Closed</span></td>
431
  <td class="py-4 text-right"><button class="text-gray-400 hover:text-primary"><i class="fas fa-ellipsis-v"></i></button></td>
432
  </tr>`;
 
447
 
448
  function updatePerformanceChart(trades) {
449
  const monthlyPL = trades.reduce((acc, trade) => {
450
+ const month = new Date(trade.time).toLocaleString('default', { month: 'short' });
451
+ acc[month] = (acc[month] || 0) + (trade.income || 0);
452
  return acc;
453
  }, {});
454
  performanceChart.data.labels = Object.keys(monthlyPL);
 
494
 
495
  document.getElementById('total-balance').textContent = `$${balance.toFixed(2)}`;
496
  document.getElementById('open-trades').textContent = positions.length;
497
+ const longCount = positions.filter(p => p.positionSide === 'LONG').length;
498
  document.getElementById('trade-types').innerHTML = `<span class="font-medium">${longCount} Long</span><span class="text-gray-500 mx-2 dark:text-gray-400">β€’</span><span class="font-medium">${positions.length - longCount} Short</span>`;
499
  const todayProfit = calculateTodayProfit(trades);
500
  document.getElementById('today-profit').textContent = `$${todayProfit.toFixed(2)}`;
 
513
  document.getElementById('allocation-update').textContent = `Last updated: ${new Date().toLocaleTimeString()}`;
514
  } catch (error) {
515
  console.error('Error fetching data:', error);
516
+ alert(`Failed to sync with BingX API: ${error.message}. Please check your credentials, permissions, network, or BingX API documentation.`);
517
  }
518
  }
519
 
 
521
  document.getElementById('refresh-btn').addEventListener('click', fetchData);
522
  document.getElementById('sync-now').addEventListener('click', fetchData);
523
  window.addEventListener('load', fetchData);
524
+ setInterval(fetchData, 120000); // Refresh every 2 minutes, respecting rate limit of 5/s
525
  </script>
526
  </body>
527
  </html>