mirror of
https://github.com/basicswap/basicswap.git
synced 2024-11-16 15:58:17 +00:00
Fix wownero rate + bug fixes.
- Fix wownero rates on offers page. - Fix wownero USD price on wallet/wallets page. - Set dark mode as default. - Fix tooltips. - Fix JS errors.
This commit is contained in:
parent
34d94760a3
commit
64165e387e
5 changed files with 240 additions and 229 deletions
|
@ -43,69 +43,67 @@
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
<script>
|
<script>
|
||||||
(function() {
|
var toggleImages = function() {
|
||||||
var toggleImages = function() {
|
var html = document.querySelector('html');
|
||||||
var html = document.querySelector('html');
|
var darkImages = document.querySelectorAll('.dark-image');
|
||||||
var darkImages = document.querySelectorAll('.dark-image');
|
var lightImages = document.querySelectorAll('.light-image');
|
||||||
var lightImages = document.querySelectorAll('.light-image');
|
|
||||||
|
|
||||||
if (html && html.classList.contains('dark')) {
|
if (html && html.classList.contains('dark')) {
|
||||||
toggleImageDisplay(darkImages, 'block');
|
toggleImageDisplay(darkImages, 'block');
|
||||||
toggleImageDisplay(lightImages, 'none');
|
toggleImageDisplay(lightImages, 'none');
|
||||||
} else {
|
} else {
|
||||||
toggleImageDisplay(darkImages, 'none');
|
toggleImageDisplay(darkImages, 'none');
|
||||||
toggleImageDisplay(lightImages, 'block');
|
toggleImageDisplay(lightImages, 'block');
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
var toggleImageDisplay = function(images, display) {
|
var toggleImageDisplay = function(images, display) {
|
||||||
images.forEach(function(img) {
|
images.forEach(function(img) {
|
||||||
img.style.display = display;
|
img.style.display = display;
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
document.addEventListener('DOMContentLoaded', function() {
|
|
||||||
var themeToggle = document.getElementById('theme-toggle');
|
|
||||||
|
|
||||||
if (themeToggle) {
|
|
||||||
themeToggle.addEventListener('click', function() {
|
|
||||||
toggleImages();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
toggleImages();
|
|
||||||
});
|
});
|
||||||
})();
|
};
|
||||||
</script>
|
|
||||||
<script>
|
|
||||||
var themeToggleDarkIcon = document.getElementById('theme-toggle-dark-icon');
|
|
||||||
var themeToggleLightIcon = document.getElementById('theme-toggle-light-icon');
|
|
||||||
|
|
||||||
if (localStorage.getItem('color-theme') === 'dark' || (!('color-theme' in localStorage) && window.matchMedia('(prefers-color-scheme: dark)').matches)) {
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
themeToggleLightIcon.classList.remove('hidden');
|
var themeToggle = document.getElementById('theme-toggle');
|
||||||
} else {
|
|
||||||
themeToggleDarkIcon.classList.remove('hidden');
|
|
||||||
}
|
|
||||||
|
|
||||||
function setTheme(theme) {
|
if (themeToggle) {
|
||||||
if (theme === 'light') {
|
themeToggle.addEventListener('click', function() {
|
||||||
document.documentElement.classList.remove('dark');
|
|
||||||
localStorage.setItem('color-theme', 'light');
|
|
||||||
} else {
|
|
||||||
document.documentElement.classList.add('dark');
|
|
||||||
localStorage.setItem('color-theme', 'dark');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
document.getElementById('theme-toggle').addEventListener('click', () => {
|
|
||||||
if (localStorage.getItem('color-theme') === 'dark') {
|
|
||||||
setTheme('light');
|
|
||||||
} else {
|
|
||||||
setTheme('dark');
|
|
||||||
}
|
|
||||||
themeToggleDarkIcon.classList.toggle('hidden');
|
|
||||||
themeToggleLightIcon.classList.toggle('hidden');
|
|
||||||
toggleImages();
|
toggleImages();
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
</script>
|
toggleImages();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
<script>
|
||||||
|
var themeToggleDarkIcon = document.getElementById('theme-toggle-dark-icon');
|
||||||
|
var themeToggleLightIcon = document.getElementById('theme-toggle-light-icon');
|
||||||
|
|
||||||
|
if (localStorage.getItem('color-theme') === 'dark' || (!('color-theme' in localStorage) && window.matchMedia('(prefers-color-scheme: dark)').matches)) {
|
||||||
|
themeToggleLightIcon.classList.remove('hidden');
|
||||||
|
} else {
|
||||||
|
themeToggleDarkIcon.classList.remove('hidden');
|
||||||
|
}
|
||||||
|
|
||||||
|
function setTheme(theme) {
|
||||||
|
if (theme === 'light') {
|
||||||
|
document.documentElement.classList.remove('dark');
|
||||||
|
localStorage.setItem('color-theme', 'light');
|
||||||
|
} else {
|
||||||
|
document.documentElement.classList.add('dark');
|
||||||
|
localStorage.setItem('color-theme', 'dark');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
document.getElementById('theme-toggle').addEventListener('click', () => {
|
||||||
|
if (localStorage.getItem('color-theme') === 'dark') {
|
||||||
|
setTheme('light');
|
||||||
|
} else {
|
||||||
|
setTheme('dark');
|
||||||
|
}
|
||||||
|
themeToggleDarkIcon.classList.toggle('hidden');
|
||||||
|
themeToggleLightIcon.classList.toggle('hidden');
|
||||||
|
toggleImages();
|
||||||
|
});
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
<link type="text/css" media="all" href="/static/css/style.css" rel="stylesheet">
|
<link type="text/css" media="all" href="/static/css/style.css" rel="stylesheet">
|
||||||
<script src="/static/js/main.js"></script>
|
<script src="/static/js/main.js"></script>
|
||||||
<script src="/static/js/libs/flowbite.js"></script>
|
<script src="/static/js/libs/flowbite.js"></script>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
const isDarkMode =
|
const isDarkMode =
|
||||||
localStorage.getItem('color-theme') === 'dark' ||
|
localStorage.getItem('color-theme') === 'dark' ||
|
||||||
|
@ -19,7 +20,7 @@
|
||||||
window.matchMedia('(prefers-color-scheme: dark)').matches);
|
window.matchMedia('(prefers-color-scheme: dark)').matches);
|
||||||
|
|
||||||
if (!localStorage.getItem('color-theme')) {
|
if (!localStorage.getItem('color-theme')) {
|
||||||
localStorage.setItem('color-theme', isDarkMode ? 'dark' : 'light');
|
localStorage.setItem('color-theme', 'dark');
|
||||||
}
|
}
|
||||||
|
|
||||||
document.documentElement.classList.toggle('dark', isDarkMode);
|
document.documentElement.classList.toggle('dark', isDarkMode);
|
||||||
|
@ -260,26 +261,25 @@
|
||||||
<!-- dev mode icons on/off -->
|
<!-- dev mode icons on/off -->
|
||||||
<ul class="xl:flex">
|
<ul class="xl:flex">
|
||||||
<li>
|
<li>
|
||||||
<div data-tooltip-target="tooltip-debug" class="ml-5 flex items-center text-gray-50 hover:text-gray-100 text-sm">
|
<div data-tooltip-target="tooltip-DEV" class="ml-5 flex items-center text-gray-50 hover:text-gray-100 text-sm">
|
||||||
{{ debug_nerd_svg | safe }}
|
{{ debug_nerd_svg | safe }}
|
||||||
<span data-tooltip-target="tooltip-DEV" ></span> </div>
|
</div>
|
||||||
<div id="tooltip-debug" role="tooltip" class="inline-block absolute invisible z-10 py-2 px-3 text-sm font-medium text-white bg-blue-500 rounded-lg shadow-sm opacity-0 transition-opacity duration-300 tooltip">
|
<div id="tooltip-DEV" role="tooltip" class="inline-block absolute invisible z-10 py-2 px-3 text-sm font-medium text-white bg-blue-500 rounded-lg shadow-sm opacity-0 transition-opacity duration-300 tooltip">
|
||||||
<p><b>Debug mode:</b> Active</p>
|
<p><b>Debug mode:</b> Active</p>
|
||||||
{% if debug_ui_mode == true %}
|
{% if debug_ui_mode == true %}
|
||||||
<p><b>Debug UI mode:</b> Active</p>
|
<p><b>Debug UI mode:</b> Active</p>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
<!-- dev mode icons on/off -->
|
<!-- dev mode icons on/off -->
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% if encrypted == true %}
|
{% if encrypted == true %}
|
||||||
<ul class="xl:flex"><li>
|
<ul class="xl:flex"><li>
|
||||||
{% if locked == true %}
|
{% if locked == true %}
|
||||||
<div data-tooltip-target="tooltip-locked-wallets" class="ml-5 flex items-center text-gray-50 hover:text-gray-100 text-sm">
|
<div data-tooltip-target="tooltip-locked-wallets" class="ml-5 flex items-center text-gray-50 hover:text-gray-100 text-sm">
|
||||||
{{ wallet_locked_svg | safe }}
|
{{ wallet_locked_svg | safe }}</div>
|
||||||
<span data-tooltip-target="tooltip-locked-wallets" ></span> </div>
|
|
||||||
<div id="tooltip-locked-wallets" role="tooltip" class="inline-block absolute invisible z-10 py-2 px-3 text-sm font-medium text-white bg-blue-500 rounded-lg shadow-sm opacity-0 transition-opacity duration-300 tooltip">
|
<div id="tooltip-locked-wallets" role="tooltip" class="inline-block absolute invisible z-10 py-2 px-3 text-sm font-medium text-white bg-blue-500 rounded-lg shadow-sm opacity-0 transition-opacity duration-300 tooltip">
|
||||||
<p><b>Wallets:</b> Locked </p>
|
<p><b>Wallets:</b> Locked </p>
|
||||||
</div>
|
</div>
|
||||||
|
@ -287,8 +287,7 @@
|
||||||
<a href='/lock'>
|
<a href='/lock'>
|
||||||
<div data-tooltip-target="tooltip-unlocked-wallets" class="ml-5 flex items-center text-gray-50 hover:text-gray-100 text-sm">
|
<div data-tooltip-target="tooltip-unlocked-wallets" class="ml-5 flex items-center text-gray-50 hover:text-gray-100 text-sm">
|
||||||
{{ wallet_unlocked_svg | safe }}
|
{{ wallet_unlocked_svg | safe }}
|
||||||
<span data-tooltip-target="tooltip-unlocked-wallets" ></span> </div>
|
</div>
|
||||||
<div class="tooltip-arrow" data-popper-arrow></div>
|
|
||||||
<div id="tooltip-unlocked-wallets" role="tooltip" class="inline-block absolute invisible z-10 py-2 px-3 text-sm font-medium text-white bg-blue-500 rounded-lg shadow-sm opacity-0 transition-opacity duration-300 tooltip">
|
<div id="tooltip-unlocked-wallets" role="tooltip" class="inline-block absolute invisible z-10 py-2 px-3 text-sm font-medium text-white bg-blue-500 rounded-lg shadow-sm opacity-0 transition-opacity duration-300 tooltip">
|
||||||
<p><b>Wallets:</b> Unlocked </p>
|
<p><b>Wallets:</b> Unlocked </p>
|
||||||
</div>
|
</div>
|
||||||
|
@ -303,7 +302,7 @@
|
||||||
<a href="/tor">
|
<a href="/tor">
|
||||||
<div data-tooltip-target="tooltip-tor" class="flex items-center text-gray-50 hover:text-gray-100 text-sm">
|
<div data-tooltip-target="tooltip-tor" class="flex items-center text-gray-50 hover:text-gray-100 text-sm">
|
||||||
{{ tor_purple_svg | safe }}
|
{{ tor_purple_svg | safe }}
|
||||||
</a> <span data-tooltip-target="tooltip-tor"></span></div>
|
</a></div>
|
||||||
<div id="tooltip-tor" role="tooltip" class="inline-block absolute invisible z-10 py-2 px-3 text-sm font-medium text-white bg-blue-500 rounded-lg shadow-sm opacity-0 transition-opacity duration-300 tooltip"><b>Tor mode:</b> Active
|
<div id="tooltip-tor" role="tooltip" class="inline-block absolute invisible z-10 py-2 px-3 text-sm font-medium text-white bg-blue-500 rounded-lg shadow-sm opacity-0 transition-opacity duration-300 tooltip"><b>Tor mode:</b> Active
|
||||||
{% if tor_established == true %}
|
{% if tor_established == true %}
|
||||||
<br><b>Tor:</b> Connected
|
<br><b>Tor:</b> Connected
|
||||||
|
@ -316,7 +315,6 @@
|
||||||
<button data-tooltip-target="tooltip-darkmode" id="theme-toggle" type="button" class="text-gray-500 dark:text-gray-400 focus:outline-none rounded-lg text-sm ml-5">
|
<button data-tooltip-target="tooltip-darkmode" id="theme-toggle" type="button" class="text-gray-500 dark:text-gray-400 focus:outline-none rounded-lg text-sm ml-5">
|
||||||
{{ sun_svg | safe }}
|
{{ sun_svg | safe }}
|
||||||
{{ moon_svg | safe }}
|
{{ moon_svg | safe }}
|
||||||
<span data-tooltip-target="tooltip-darkmode"></span>
|
|
||||||
<div id="tooltip-darkmode" role="tooltip" class="inline-block absolute invisible z-10 py-2 px-3 text-sm font-medium text-white bg-blue-500 rounded-lg shadow-sm opacity-0 transition-opacity duration-300 tooltip">Dark mode</div>
|
<div id="tooltip-darkmode" role="tooltip" class="inline-block absolute invisible z-10 py-2 px-3 text-sm font-medium text-white bg-blue-500 rounded-lg shadow-sm opacity-0 transition-opacity duration-300 tooltip">Dark mode</div>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -486,22 +486,40 @@ window.addEventListener('load', function() {
|
||||||
if (container != null) {
|
if (container != null) {
|
||||||
container.addEventListener('click', () => {
|
container.addEventListener('click', () => {
|
||||||
setActiveContainer(container_id);
|
setActiveContainer(container_id);
|
||||||
updateChart(coin);
|
updateChart(coin, coinGeckoApiKey);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (coin === 'WOW') {
|
if (coin === 'WOW') {
|
||||||
fetchWowneroData();
|
fetchWowneroData(coinGeckoApiKey);
|
||||||
} else if (coin === 'ZANO') {
|
} else if (coin === 'ZANO') {
|
||||||
fetchZanoData(coinGeckoApiKey);
|
fetchZanoData(coinGeckoApiKey);
|
||||||
} else {
|
} else {
|
||||||
fetchCryptoCompareData(coin, api_key);
|
fetchCryptoCompareData(coin, api_key);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
updateChart('BTC');
|
updateChart('BTC', coinGeckoApiKey);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function fetchWowneroData(coinGeckoApiKey) {
|
||||||
|
fetch(`https://api.coingecko.com/api/v3/coins/wownero/market_chart?vs_currency=usd&days=1&api_key={{coingecko_api_key}}`)
|
||||||
|
.then(response => {
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error(`Error fetching data. Status: ${response.status}`);
|
||||||
|
}
|
||||||
|
return response.json();
|
||||||
|
})
|
||||||
|
.then(data => {
|
||||||
|
displayWowneroData(data);
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.error('Fetching Wownero data:', error);
|
||||||
|
displayErrorMessage('Unable to fetch data for Wownero. Please try again later.');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
function fetchZanoData(coinGeckoApiKey) {
|
function fetchZanoData(coinGeckoApiKey) {
|
||||||
fetch(`https://api.coingecko.com/api/v3/coins/zano/market_chart?vs_currency=usd&days=30&interval=daily&api_key=${coinGeckoApiKey}`)
|
fetch(`https://api.coingecko.com/api/v3/coins/zano/market_chart?vs_currency=usd&days=30&interval=daily&api_key={{coingecko_api_key}}`)
|
||||||
.then(response => {
|
.then(response => {
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
throw new Error(`Error fetching data. Status: ${response.status}`);
|
throw new Error(`Error fetching data. Status: ${response.status}`);
|
||||||
|
@ -517,40 +535,22 @@ function fetchZanoData(coinGeckoApiKey) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function fetchCryptoCompareData(coin, api_key) {
|
function fetchCryptoCompareData(coin, api_key) {
|
||||||
fetch(`https://min-api.cryptocompare.com/data/pricemultifull?fsyms=${coin}&tsyms=USD,BTC&api_key=${api_key}`)
|
fetch(`https://min-api.cryptocompare.com/data/pricemultifull?fsyms=${coin}&tsyms=USD,BTC&api_key={{chart_api_key}}`)
|
||||||
.then(response => {
|
.then(response => {
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
throw new Error(`Error fetching data. Status: ${response.status}`);
|
throw new Error(`Error fetching data. Status: ${response.status}`);
|
||||||
}
|
}
|
||||||
return response.json();
|
return response.json();
|
||||||
})
|
})
|
||||||
.then(data => {
|
.then(data => {
|
||||||
displayCoinData(coin, data);
|
displayCoinData(coin, data);
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
console.error(`Fetching ${coin} data:`, error);
|
console.error(`Fetching ${coin} data:`, error);
|
||||||
displayErrorMessage(`Unable to fetch data. Please verify your API key or try again later.`);
|
displayErrorMessage(`Unable to fetch data. Please verify your API key or try again later.`);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function fetchWowneroData(coinGeckoApiKey) {
|
|
||||||
fetch(`https://api.coingecko.com/api/v3/coins/wownero/market_chart?vs_currency=usd&days=1&api_key=${coinGeckoApiKey}`)
|
|
||||||
.then(response => {
|
|
||||||
if (!response.ok) {
|
|
||||||
throw new Error(`Error fetching data. Status: ${response.status}`);
|
|
||||||
}
|
|
||||||
return response.json();
|
|
||||||
})
|
|
||||||
.then(data => {
|
|
||||||
displayWowneroData(data);
|
|
||||||
})
|
|
||||||
.catch(error => {
|
|
||||||
console.error('Fetching Wownero data:', error);
|
|
||||||
displayErrorMessage('Unable to fetch data for Wownero. Please try again later.');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function displayWowneroData(data) {
|
function displayWowneroData(data) {
|
||||||
const prices = data.prices;
|
const prices = data.prices;
|
||||||
|
@ -667,6 +667,8 @@ function negativePriceChangeHTML(value) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function setActiveContainer(containerId) {
|
function setActiveContainer(containerId) {
|
||||||
|
const api_key = '{{chart_api_key}}';
|
||||||
|
const coinGeckoApiKey = '{{coingecko_api_key}}';
|
||||||
const containerIds = ['btc-container', 'xmr-container', 'part-container', 'pivx-container', 'firo-container', 'dash-container', 'ltc-container', 'doge-container', 'eth-container', 'dcr-container', 'zano-container', 'wow-container'];
|
const containerIds = ['btc-container', 'xmr-container', 'part-container', 'pivx-container', 'firo-container', 'dash-container', 'ltc-container', 'doge-container', 'eth-container', 'dcr-container', 'zano-container', 'wow-container'];
|
||||||
const activeClass = 'active-container';
|
const activeClass = 'active-container';
|
||||||
containerIds.forEach(id => {
|
containerIds.forEach(id => {
|
||||||
|
@ -691,13 +693,10 @@ const coinOptions = {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
function updateChart(coinSymbol) {
|
function updateChart(coinSymbol, coinGeckoApiKey) {
|
||||||
coin = coinSymbol;
|
coin = coinSymbol;
|
||||||
const api_key = '{{chart_api_key}}';
|
|
||||||
const coinGeckoApiKey = '{{coingecko_api_key}}';
|
|
||||||
|
|
||||||
if (coinSymbol === 'WOW') {
|
if (coinSymbol === 'WOW') {
|
||||||
fetch(`https://api.coingecko.com/api/v3/coins/wownero/market_chart?vs_currency=usd&days=30&interval=daily&api_key=${coinGeckoApiKey}`)
|
fetch(`https://api.coingecko.com/api/v3/coins/wownero/market_chart?vs_currency=usd&days=30&interval=daily&api_key={{coingecko_api_key}}`)
|
||||||
.then(response => response.json())
|
.then(response => response.json())
|
||||||
.then(data => {
|
.then(data => {
|
||||||
const chartData = {
|
const chartData = {
|
||||||
|
@ -717,7 +716,7 @@ function updateChart(coinSymbol) {
|
||||||
})
|
})
|
||||||
.catch(error => console.error('Error updating chart for Wownero:', error));
|
.catch(error => console.error('Error updating chart for Wownero:', error));
|
||||||
} else if (coinSymbol === 'ZANO') {
|
} else if (coinSymbol === 'ZANO') {
|
||||||
fetch(`https://api.coingecko.com/api/v3/coins/zano/market_chart?vs_currency=usd&days=30&interval=daily&api_key=${coinGeckoApiKey}`)
|
fetch(`https://api.coingecko.com/api/v3/coins/zano/market_chart?vs_currency=usd&days=30&interval=daily&api_key={{coingecko_api_key}}`)
|
||||||
.then(response => response.json())
|
.then(response => response.json())
|
||||||
.then(data => {
|
.then(data => {
|
||||||
const chartData = {
|
const chartData = {
|
||||||
|
@ -737,7 +736,7 @@ function updateChart(coinSymbol) {
|
||||||
})
|
})
|
||||||
.catch(error => console.error('Error updating chart for Zano:', error));
|
.catch(error => console.error('Error updating chart for Zano:', error));
|
||||||
} else {
|
} else {
|
||||||
fetch(`https://min-api.cryptocompare.com/data/v2/histoday?fsym=${coinSymbol}&tsym=USD&limit=30&api_key=${api_key}`)
|
fetch(`https://min-api.cryptocompare.com/data/v2/histoday?fsym=${coinSymbol}&tsym=USD&limit=30&api_key={{chart_api_key}}`)
|
||||||
.then(response => response.json())
|
.then(response => response.json())
|
||||||
.then(data => {
|
.then(data => {
|
||||||
// Check if data is undefined
|
// Check if data is undefined
|
||||||
|
@ -1322,6 +1321,7 @@ const coinNameToSymbol = {
|
||||||
};
|
};
|
||||||
|
|
||||||
const exchangeRateCache = {};
|
const exchangeRateCache = {};
|
||||||
|
const coinGeckoApiKey = '{{coingecko_api_key}}';
|
||||||
|
|
||||||
function updateUsdValue(cryptoCell, coinFullName, isRate = false) {
|
function updateUsdValue(cryptoCell, coinFullName, isRate = false) {
|
||||||
const coinSymbol = coinNameToSymbol[coinFullName];
|
const coinSymbol = coinNameToSymbol[coinFullName];
|
||||||
|
@ -1332,68 +1332,52 @@ function updateUsdValue(cryptoCell, coinFullName, isRate = false) {
|
||||||
|
|
||||||
const cryptoValue = parseFloat(cryptoCell.textContent);
|
const cryptoValue = parseFloat(cryptoCell.textContent);
|
||||||
const usdCell = cryptoCell.nextElementSibling;
|
const usdCell = cryptoCell.nextElementSibling;
|
||||||
if (usdCell) {
|
if (!usdCell) {
|
||||||
// Check if the exchange rate is in the cache and is not expired
|
console.error("USD cell does not exist.");
|
||||||
if (exchangeRateCache[coinSymbol] && !isCacheExpired(coinSymbol)) {
|
return;
|
||||||
console.log(`Using cached exchange rate for ${coinSymbol}`);
|
|
||||||
const exchangeRate = exchangeRateCache[coinSymbol].rate;
|
|
||||||
const cryptoValue = parseFloat(cryptoCell.textContent);
|
|
||||||
const usdValue = cryptoValue * exchangeRate;
|
|
||||||
usdCell.textContent = `${usdValue.toFixed(2)} USD`;
|
|
||||||
|
|
||||||
updateProfitLoss(cryptoCell.closest('tr'));
|
|
||||||
updateProfitValue(cryptoCell.closest('tr'));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isRate) {
|
if (exchangeRateCache[coinSymbol] && !isCacheExpired(coinSymbol)) {
|
||||||
const rateCell = usdCell.nextElementSibling;
|
console.log(`Using cached exchange rate for ${coinSymbol}`);
|
||||||
if (rateCell) {
|
const exchangeRate = exchangeRateCache[coinSymbol].rate;
|
||||||
const usdValue = rateCell.previousElementSibling.textContent * cryptoValue;
|
const usdValue = cryptoValue * exchangeRate;
|
||||||
usdCell.textContent = `${usdValue.toFixed(2)} USD`;
|
usdCell.textContent = `${usdValue.toFixed(2)} USD`;
|
||||||
} else {
|
|
||||||
console.error("Rate cell does not exist.");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
const apiUrl = `https://min-api.cryptocompare.com/data/price?fsym=${coinSymbol}&tsyms=USD`;
|
|
||||||
|
|
||||||
if (exchangeRateCache[coinSymbol] && !isCacheExpired(coinSymbol)) {
|
updateProfitLoss(cryptoCell.closest('tr'));
|
||||||
// console.log(`Using cached exchange rate for ${coinSymbol}`);
|
updateProfitValue(cryptoCell.closest('tr'));
|
||||||
const exchangeRate = exchangeRateCache[coinSymbol].rate;
|
return;
|
||||||
const usdValue = cryptoValue * exchangeRate;
|
|
||||||
usdCell.textContent = `${usdValue.toFixed(2)} USD`;
|
|
||||||
|
|
||||||
updateProfitLoss(cryptoCell.closest('tr'));
|
|
||||||
updateProfitValue(cryptoCell.closest('tr'));
|
|
||||||
} else {
|
|
||||||
// console.log(`Fetching exchange rate from API for ${coinSymbol}`);
|
|
||||||
fetch(apiUrl)
|
|
||||||
.then(response => response.json())
|
|
||||||
.then(data => {
|
|
||||||
const exchangeRate = data.USD;
|
|
||||||
if (!isNaN(exchangeRate)) {
|
|
||||||
// console.log(`Received exchange rate from API for ${coinSymbol}`);
|
|
||||||
const usdValue = cryptoValue * exchangeRate;
|
|
||||||
usdCell.textContent = `${usdValue.toFixed(2)} USD`;
|
|
||||||
|
|
||||||
exchangeRateCache[coinSymbol] = {
|
|
||||||
rate: exchangeRate,
|
|
||||||
timestamp: Date.now(),
|
|
||||||
ttl: 300000 // 5 minutes
|
|
||||||
};
|
|
||||||
|
|
||||||
updateProfitLoss(cryptoCell.closest('tr'));
|
|
||||||
updateProfitValue(cryptoCell.closest('tr'));
|
|
||||||
} else {
|
|
||||||
console.error('Invalid exchange rate. Response:', data);
|
|
||||||
usdCell.textContent = 'Invalid exchange rate';
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch(error => {
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const apiUrl = coinSymbol === 'WOW'
|
||||||
|
? `https://api.coingecko.com/api/v3/simple/price?ids=wownero&vs_currencies=usd&api_key=${{coingecko_api_key}}`
|
||||||
|
: `https://min-api.cryptocompare.com/data/price?fsym=${coinSymbol}&tsyms=USD`;
|
||||||
|
|
||||||
|
fetch(apiUrl)
|
||||||
|
.then(response => response.json())
|
||||||
|
.then(data => {
|
||||||
|
const exchangeRate = coinSymbol === 'WOW' ? data.wownero.usd : data.USD;
|
||||||
|
if (!isNaN(exchangeRate)) {
|
||||||
|
console.log(`Received exchange rate from API for ${coinSymbol}`);
|
||||||
|
const usdValue = cryptoValue * exchangeRate;
|
||||||
|
usdCell.textContent = `${usdValue.toFixed(2)} USD`;
|
||||||
|
|
||||||
|
exchangeRateCache[coinSymbol] = {
|
||||||
|
rate: exchangeRate,
|
||||||
|
timestamp: Date.now(),
|
||||||
|
ttl: 300000 // 5 minutes
|
||||||
|
};
|
||||||
|
|
||||||
|
updateProfitLoss(cryptoCell.closest('tr'));
|
||||||
|
updateProfitValue(cryptoCell.closest('tr'));
|
||||||
|
} else {
|
||||||
|
console.error('Invalid exchange rate. Response:', data);
|
||||||
|
usdCell.textContent = 'Invalid exchange rate';
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.error(`Fetching ${coinSymbol} data:`, error);
|
||||||
|
usdCell.textContent = 'Error fetching data';
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function isCacheExpired(coinSymbol) {
|
function isCacheExpired(coinSymbol) {
|
||||||
|
@ -1408,15 +1392,17 @@ function updateProfitLoss(row) {
|
||||||
|
|
||||||
if (!isNaN(sellingUSD) && !isNaN(buyingUSD)) {
|
if (!isNaN(sellingUSD) && !isNaN(buyingUSD)) {
|
||||||
const profitLossPercentage = ((sellingUSD - buyingUSD) / buyingUSD) * 100;
|
const profitLossPercentage = ((sellingUSD - buyingUSD) / buyingUSD) * 100;
|
||||||
profitLossCell.textContent = `${profitLossPercentage.toFixed(2)}%`;
|
|
||||||
|
|
||||||
if (profitLossPercentage > 0) {
|
if (profitLossPercentage > 0) {
|
||||||
profitLossCell.classList.add('text-green-500'); // Profit (positive)
|
profitLossCell.textContent = `-${profitLossPercentage.toFixed(2)}%`; // Change from "+" to "-"
|
||||||
|
profitLossCell.classList.add('text-green-500'); // Profit (negative)
|
||||||
profitLossCell.classList.remove('text-red-500');
|
profitLossCell.classList.remove('text-red-500');
|
||||||
} else if (profitLossPercentage < 0) {
|
} else if (profitLossPercentage < 0) {
|
||||||
profitLossCell.classList.add('text-red-500'); // Loss (negative)
|
profitLossCell.textContent = `+${Math.abs(profitLossPercentage).toFixed(2)}%`; // Change from "-" to "+"
|
||||||
|
profitLossCell.classList.add('text-red-500'); // Loss (positive)
|
||||||
profitLossCell.classList.remove('text-green-500');
|
profitLossCell.classList.remove('text-green-500');
|
||||||
} else {
|
} else {
|
||||||
|
profitLossCell.textContent = `${profitLossPercentage.toFixed(2)}%`;
|
||||||
profitLossCell.classList.add('text-yellow-500'); // No profit or loss (zero)
|
profitLossCell.classList.add('text-yellow-500'); // No profit or loss (zero)
|
||||||
profitLossCell.classList.remove('text-green-500', 'text-red-500');
|
profitLossCell.classList.remove('text-green-500', 'text-red-500');
|
||||||
}
|
}
|
||||||
|
@ -1426,6 +1412,7 @@ function updateProfitLoss(row) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function updateProfitValue(row) {
|
function updateProfitValue(row) {
|
||||||
const sellingUSD = parseFloat(row.querySelector('.usd-value').textContent);
|
const sellingUSD = parseFloat(row.querySelector('.usd-value').textContent);
|
||||||
const profitValueCell = row.querySelector('.profit-value');
|
const profitValueCell = row.querySelector('.profit-value');
|
||||||
|
@ -1460,51 +1447,43 @@ function sortTable(columnIndex) {
|
||||||
const sortIcon = document.getElementById(`sort-icon-${columnIndex}`);
|
const sortIcon = document.getElementById(`sort-icon-${columnIndex}`);
|
||||||
let sortOrder = sortIcon.textContent === '↓' ? 1 : -1;
|
let sortOrder = sortIcon.textContent === '↓' ? 1 : -1;
|
||||||
|
|
||||||
if (sortOrder === 1) {
|
sortIcon.textContent = sortOrder === 1 ? '↑' : '↓';
|
||||||
sortIcon.textContent = '↑';
|
|
||||||
} else {
|
|
||||||
sortIcon.textContent = '↓';
|
|
||||||
}
|
|
||||||
|
|
||||||
rows.sort((a, b) => {
|
rows.sort((a, b) => {
|
||||||
const aValue = a.cells[columnIndex].textContent.trim();
|
const aValue = a.cells[columnIndex].textContent.trim();
|
||||||
const bValue = b.cells[columnIndex].textContent.trim();
|
const bValue = b.cells[columnIndex].textContent.trim();
|
||||||
|
|
||||||
if (aValue < bValue) return -1 * sortOrder;
|
return aValue < bValue ? -1 * sortOrder : aValue > bValue ? 1 * sortOrder : 0;
|
||||||
if (aValue > bValue) return 1 * sortOrder;
|
|
||||||
return 0;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
rows.forEach(row => table.querySelector('tbody').appendChild(row));
|
rows.forEach(row => table.querySelector('tbody').appendChild(row));
|
||||||
}
|
}
|
||||||
|
|
||||||
document.addEventListener('DOMContentLoaded', function() {
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
const coinToSelect = document.getElementById('coin_to');
|
const coinToSelect = document.getElementById('coin_to');
|
||||||
const coinFromSelect = document.getElementById('coin_from');
|
const coinFromSelect = document.getElementById('coin_from');
|
||||||
const coinToButton = document.getElementById('coin_to_button');
|
const coinToButton = document.getElementById('coin_to_button');
|
||||||
const coinFromButton = document.getElementById('coin_from_button');
|
const coinFromButton = document.getElementById('coin_from_button');
|
||||||
|
|
||||||
function updateSelectedImage(selectElement, buttonElement) {
|
function updateSelectedImage(selectElement, buttonElement) {
|
||||||
const selectedOption = selectElement.options[selectElement.selectedIndex];
|
const selectedOption = selectElement.options[selectElement.selectedIndex];
|
||||||
const imageURL = selectedOption.getAttribute('data-image');
|
const imageURL = selectedOption.getAttribute('data-image');
|
||||||
if (imageURL) {
|
buttonElement.style.backgroundImage = imageURL ? `url('${imageURL}')` : 'none';
|
||||||
buttonElement.style.backgroundImage = `url('${imageURL}')`;
|
|
||||||
} else {
|
|
||||||
buttonElement.style.backgroundImage = 'none';
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
coinToSelect.addEventListener('change', function() {
|
coinToSelect.addEventListener('change', function() {
|
||||||
|
updateSelectedImage(coinToSelect, coinToButton);
|
||||||
|
});
|
||||||
|
|
||||||
|
coinFromSelect.addEventListener('change', function() {
|
||||||
|
updateSelectedImage(coinFromSelect, coinFromButton);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Initialize selected images on page load
|
||||||
updateSelectedImage(coinToSelect, coinToButton);
|
updateSelectedImage(coinToSelect, coinToButton);
|
||||||
});
|
|
||||||
|
|
||||||
coinFromSelect.addEventListener('change', function() {
|
|
||||||
updateSelectedImage(coinFromSelect, coinFromButton);
|
updateSelectedImage(coinFromSelect, coinFromButton);
|
||||||
});
|
|
||||||
|
|
||||||
// Initialize selected images on page load
|
|
||||||
updateSelectedImage(coinToSelect, coinToButton);
|
|
||||||
updateSelectedImage(coinFromSelect, coinFromButton);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
{% include 'footer.html' %}
|
{% include 'footer.html' %}
|
||||||
</body>
|
</body>
|
||||||
|
|
|
@ -842,30 +842,46 @@
|
||||||
<input type="hidden" name="formid" value="{{ form_id }}">
|
<input type="hidden" name="formid" value="{{ form_id }}">
|
||||||
</form>
|
</form>
|
||||||
<script>
|
<script>
|
||||||
const coinNameToSymbol = {
|
const coinNameToSymbol = {
|
||||||
'Bitcoin': 'BTC',
|
'Bitcoin': 'BTC',
|
||||||
'Particl': 'PART',
|
'Particl': 'PART',
|
||||||
'Particl Blind': 'PART',
|
'Particl Blind': 'PART',
|
||||||
'Particl Anon': 'PART',
|
'Particl Anon': 'PART',
|
||||||
'Monero': 'XMR',
|
'Monero': 'XMR',
|
||||||
'Litecoin': 'LTC',
|
'Wownero': 'WOW',
|
||||||
'Firo': 'FIRO',
|
'Litecoin': 'LTC',
|
||||||
'Dash': 'DASH',
|
'Firo': 'FIRO',
|
||||||
'PIVX': 'PIVX',
|
'Dash': 'DASH',
|
||||||
'DECRED': 'DCR',
|
'PIVX': 'PIVX',
|
||||||
'WOWNERO': 'WOW'
|
'Decred': 'DCR',
|
||||||
};
|
'Zano': 'ZANO',
|
||||||
|
};
|
||||||
|
|
||||||
const getUsdValue = (cryptoValue, coinSymbol) => fetch(`https://min-api.cryptocompare.com/data/price?fsym=${coinSymbol}&tsyms=USD`)
|
const getUsdValue = (cryptoValue, coinSymbol) => {
|
||||||
.then(response => response.json())
|
if (coinSymbol === 'WOW') {
|
||||||
.then(data => {
|
return fetch(`https://api.coingecko.com/api/v3/simple/price?ids=wownero&vs_currencies=usd`)
|
||||||
const exchangeRate = data.USD;
|
.then(response => response.json())
|
||||||
if (!isNaN(exchangeRate)) {
|
.then(data => {
|
||||||
return cryptoValue * exchangeRate;
|
const exchangeRate = data.wownero.usd;
|
||||||
} else {
|
if (!isNaN(exchangeRate)) {
|
||||||
throw new Error(`Invalid exchange rate for ${coinSymbol}`);
|
return cryptoValue * exchangeRate;
|
||||||
}
|
} else {
|
||||||
});
|
throw new Error(`Invalid exchange rate for ${coinSymbol}`);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
return fetch(`https://min-api.cryptocompare.com/data/price?fsym=${coinSymbol}&tsyms=USD`)
|
||||||
|
.then(response => response.json())
|
||||||
|
.then(data => {
|
||||||
|
const exchangeRate = data.USD;
|
||||||
|
if (!isNaN(exchangeRate)) {
|
||||||
|
return cryptoValue * exchangeRate;
|
||||||
|
} else {
|
||||||
|
throw new Error(`Invalid exchange rate for ${coinSymbol}`);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const updateUsdValue = async (cryptoCell, coinFullName, usdValueSpan) => {
|
const updateUsdValue = async (cryptoCell, coinFullName, usdValueSpan) => {
|
||||||
const coinSymbol = coinNameToSymbol[coinFullName] || '';
|
const coinSymbol = coinNameToSymbol[coinFullName] || '';
|
||||||
|
|
|
@ -223,17 +223,37 @@ const coinNameToSymbol = {
|
||||||
};
|
};
|
||||||
|
|
||||||
const getUsdValue = (cryptoValue, coinSymbol) => {
|
const getUsdValue = (cryptoValue, coinSymbol) => {
|
||||||
return fetch(`https://min-api.cryptocompare.com/data/price?fsym=${coinSymbol}&tsyms=USD`)
|
let apiUrl;
|
||||||
|
|
||||||
|
if (coinSymbol === 'WOW') {
|
||||||
|
apiUrl = `https://api.coingecko.com/api/v3/simple/price?ids=wownero&vs_currencies=usd`;
|
||||||
|
} else {
|
||||||
|
apiUrl = `https://min-api.cryptocompare.com/data/price?fsym=${coinSymbol}&tsyms=USD`;
|
||||||
|
}
|
||||||
|
|
||||||
|
return fetch(apiUrl)
|
||||||
.then(response => response.json())
|
.then(response => response.json())
|
||||||
.then(data => {
|
.then(data => {
|
||||||
const exchangeRate = data.USD;
|
if (coinSymbol === 'WOW') {
|
||||||
if (!isNaN(exchangeRate)) {
|
const exchangeRate = data.wownero.usd;
|
||||||
return {
|
if (!isNaN(exchangeRate)) {
|
||||||
usdValue: cryptoValue * exchangeRate,
|
return {
|
||||||
btcValue: cryptoValue / exchangeRate
|
usdValue: cryptoValue * exchangeRate,
|
||||||
};
|
btcValue: cryptoValue / exchangeRate
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
throw new Error(`Invalid exchange rate for ${coinSymbol}`);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
throw new Error(`Invalid exchange rate for ${coinSymbol}`);
|
const exchangeRate = data.USD;
|
||||||
|
if (!isNaN(exchangeRate)) {
|
||||||
|
return {
|
||||||
|
usdValue: cryptoValue * exchangeRate,
|
||||||
|
btcValue: cryptoValue / exchangeRate
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
throw new Error(`Invalid exchange rate for ${coinSymbol}`);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue