mirror of
https://github.com/basicswap/basicswap.git
synced 2026-04-09 10:57:23 +02:00
ui: USD prices (single/total) in wallet/wallets, tooltip header update.
This commit is contained in:
@@ -33,10 +33,36 @@
|
||||
<img class="absolute z-10 right-4 bottom-4" src="/static/images/elements/dots-red.svg" alt="">
|
||||
<img class="absolute h-64 left-1/2 top-1/2 transform -translate-x-1/2 -translate-y-1/2 object-cover" src="/static/images/elements/wave.svg" alt="">
|
||||
<div class="relative z-20 flex flex-wrap items-center -m-3">
|
||||
<div class="w-full md:w-1/2 p-3">
|
||||
<h2 class="mb-6 text-4xl font-bold text-white tracking-tighter">Wallets</h2>
|
||||
<p class="font-normal text-coolGray-200 dark:text-white">Check your coin balances and manage your wallets. {% if refresh %} (Page Refresh: {{ refresh }} seconds) {% endif %}</p>
|
||||
<div class="w-full md:w-1/2 p-3 h-48">
|
||||
|
||||
|
||||
<h2 class="mb-6 text-4xl font-bold text-white tracking-tighter">
|
||||
Wallets
|
||||
</h2>
|
||||
<div class="flex items-center">
|
||||
<h2 class="text-lg font-bold text-white tracking-tighter mr-2">
|
||||
Total Assets:
|
||||
</h2>
|
||||
<button id="hide-usd-amount-toggle" class="flex items-center justify-center p-1 focus:ring-0 focus:outline-none">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="#ffffff" height="20" width="20" viewBox="0 0 24 24">
|
||||
<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>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
<div class="flex items-baseline mt-2">
|
||||
<div id="total-usd-value" class="text-5xl font-bold text-white"></div>
|
||||
<div id="usd-text" class="text-sm text-white ml-1">USD</div>
|
||||
</div>
|
||||
<div id="total-btc-value" class="text-sm text-white mt-2"></div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<div class="w-full md:w-1/2 p-3 p-6 container flex flex-wrap items-center justify-end items-center mx-auto">
|
||||
<a class="mr-5 flex flex-wrap justify-center px-5 py-3 bg-blue-500 hover:bg-blue-600 font-medium text-sm text-white border dark:bg-gray-500 dark:hover:bg-gray-700 border-blue-500 rounded-md shadow-button focus:ring-0 focus:outline-none" id="refresh" href="/changepassword">
|
||||
<svg class="text-gray-500 w-5 h-5 mr-2" xmlns="http://www.w3.org/2000/svg" height="24" width="24" viewBox="0 0 24 24">
|
||||
@@ -82,31 +108,54 @@
|
||||
</div>
|
||||
<div class="p-6 bg-coolGray-100 dark:bg-gray-600">
|
||||
<!-- bg here -->
|
||||
<div class="flex mb-2 justify-between items-center">
|
||||
<h4 class="text-xs font-medium dark:text-white">Balance:</h4>
|
||||
<span class="bold inline-block py-1 px-2 rounded-full bg-blue-100 text-xs text-black-500 dark:bg-gray-500 dark:text-gray-200">{{ w.balance }}</span>
|
||||
</div>{% if w.unconfirmed %}
|
||||
<div class="flex mb-2 justify-between items-center">
|
||||
<h4 class="text-xs font-medium dark:text-white">Unconfirmed:</h4>
|
||||
<span class="inline-block py-1 px-2 rounded-full bg-blue-100 text-xs text-black-500 dark:bg-gray-500 dark:text-gray-200">{{ w.unconfirmed }}</span>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<div class="flex mb-2 justify-between items-center">
|
||||
<h4 class="text-xs font-medium dark:text-white">Balance:</h4>
|
||||
<div class="bold inline-block py-1 px-2 rounded-full bg-blue-100 text-xs text-black-500 dark:bg-gray-500 dark:text-gray-200 coinname-value" data-coinname="{{ w.name }}">{{ w.balance }} {{ w.ticker }}</div>
|
||||
</div>
|
||||
{% if w.unconfirmed %}
|
||||
<div class="flex mb-2 justify-between items-center">
|
||||
<h4 class="text-xs font-medium dark:text-white">Unconfirmed:</h4>
|
||||
<span class="inline-block py-1 px-2 rounded-full bg-green-100 text-xs text-green-500 dark:bg-gray-500 dark:text-green-500">+{{ w.unconfirmed }} {{ w.ticker }}</span>
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="flex mb-2 justify-between items-center">
|
||||
<h4 class="text-xs font-medium dark:text-white">USD value:</h4>
|
||||
<div class="bold inline-block py-1 px-2 rounded-full bg-blue-100 text-xs text-black-500 dark:bg-gray-500 dark:text-gray-200 usd-value"></div>
|
||||
</div>
|
||||
|
||||
|
||||
{% if w.cid == '1' %}
|
||||
<div class="flex mb-2 justify-between items-center">
|
||||
<h4 class="text-xs font-medium dark:text-white">Blind Balance:</h4>
|
||||
<span class="bold inline-block py-1 px-2 rounded-full bg-blue-100 text-xs text-black-500 dark:bg-gray-500 dark:text-gray-200">{{ w.blind_balance }}</span>
|
||||
</div>{% if w.blind_unconfirmed %}
|
||||
<span class="bold inline-block py-1 px-2 rounded-full bg-blue-100 text-xs text-black-500 dark:bg-gray-500 dark:text-gray-200 coinname-value" data-coinname="{{ w.name }}">{{ w.blind_balance }} {{ w.ticker }}</span>
|
||||
</div>
|
||||
<div class="flex mb-2 justify-between items-center">
|
||||
<h4 class="text-xs font-medium dark:text-white">USD value:</h4>
|
||||
<div class="bold inline-block py-1 px-2 rounded-full bg-blue-100 text-xs text-black-500 dark:bg-gray-500 dark:text-gray-200 usd-value"></div>
|
||||
</div>
|
||||
|
||||
|
||||
{% if w.blind_unconfirmed %}
|
||||
<div class="flex mb-2 justify-between items-center">
|
||||
<h4 class="text-xs font-medium dark:text-white">Blind Unconfirmed:</h4>
|
||||
<span class="inline-block py-1 px-2 rounded-full bg-blue-100 text-xs text-black-500 dark:bg-gray-500 dark:text-gray-200">{{ w.blind_unconfirmed }}</span>
|
||||
<span class="bold inline-block py-1 px-2 rounded-full bg-green-100 text-xs text-green-500 dark:bg-gray-500 dark:text-green-500">+{{ w.blind_unconfirmed }} {{ w.ticker }}</span>
|
||||
</div>{% endif %}
|
||||
<div class="flex mb-2 justify-between items-center">
|
||||
<h4 class="text-xs font-medium dark:text-white">Anon Balance:</h4>
|
||||
<span class="bold inline-block py-1 px-2 rounded-full bg-blue-100 text-xs text-black-500 dark:bg-gray-500 dark:text-gray-200">{{ w.anon_balance }}</span>
|
||||
</div>{% if w.anon_pending %}
|
||||
<span class="bold inline-block py-1 px-2 rounded-full bg-blue-100 text-xs text-black-500 dark:bg-gray-500 dark:text-gray-200 coinname-value" data-coinname="{{ w.name }}">{{ w.anon_balance }} {{ w.ticker }}</span>
|
||||
</div>
|
||||
<div class="flex mb-2 justify-between items-center">
|
||||
<h4 class="text-xs font-medium dark:text-white">USD value:</h4>
|
||||
<div class="bold inline-block py-1 px-2 rounded-full bg-blue-100 text-xs text-black-500 dark:bg-gray-500 dark:text-gray-200 usd-value"></div>
|
||||
</div>
|
||||
|
||||
|
||||
{% if w.anon_pending %}
|
||||
<div class="flex mb-2 justify-between items-center">
|
||||
<h4 class="text-xs font-medium dark:text-white">Anon Pending:</h4>
|
||||
<span class="inline-block py-1 px-2 rounded-full bg-blue-100 text-xs text-black-500 dark:bg-gray-500 dark:text-gray-200">{{ w.anon_pending }}</span>
|
||||
<span class="bold inline-block py-1 px-2 rounded-full bg-green-100 text-xs text-green-500 dark:bg-gray-500 dark:text-green-500">
|
||||
+{{ w.anon_pending }} {{ w.ticker }}</span>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
@@ -146,6 +195,226 @@
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
{% include 'footer.html' %}
|
||||
<script>
|
||||
const coinNameToSymbol = {
|
||||
'Bitcoin': 'BTC',
|
||||
'Particl': 'PART',
|
||||
'Particl Blind': 'PART',
|
||||
'Particl Anon': 'PART',
|
||||
'Monero': 'XMR',
|
||||
'Litecoin': 'LTC',
|
||||
'Firo': 'FIRO',
|
||||
'Dash': 'DASH',
|
||||
'PIVX': 'PIVX'
|
||||
};
|
||||
|
||||
const getUsdValue = (cryptoValue, coinSymbol) => {
|
||||
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 {
|
||||
usdValue: cryptoValue * exchangeRate,
|
||||
btcValue: cryptoValue / exchangeRate
|
||||
};
|
||||
} else {
|
||||
throw new Error(`Invalid exchange rate for ${coinSymbol}`);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const updateValues = async () => {
|
||||
const coinNameValues = document.querySelectorAll('.coinname-value');
|
||||
|
||||
for (const coinNameValue of coinNameValues) {
|
||||
const coinFullName = coinNameValue.getAttribute('data-coinname');
|
||||
const cryptoValue = parseFloat(coinNameValue.textContent);
|
||||
const coinSymbol = coinNameToSymbol[coinFullName];
|
||||
|
||||
if (coinSymbol) {
|
||||
try {
|
||||
const { usdValue, btcValue } = await getUsdValue(cryptoValue, coinSymbol);
|
||||
|
||||
const usdValueElement = coinNameValue.nextElementSibling.querySelector('.usd-value');
|
||||
if (usdValueElement) {
|
||||
usdValueElement.textContent = `$${usdValue.toFixed(2)}`;
|
||||
}
|
||||
|
||||
const btcValueElement = coinNameValue.nextElementSibling.querySelector('.btc-value');
|
||||
if (btcValueElement) {
|
||||
btcValueElement.textContent = `${btcValue.toFixed(8)} BTC`;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(`Error retrieving exchange rate for ${coinSymbol}`);
|
||||
}
|
||||
} else {
|
||||
console.error(`Coin symbol not found for full name: ${coinFullName}`);
|
||||
}
|
||||
}
|
||||
|
||||
calculateTotalUsdValue();
|
||||
calculateTotalBtcValue();
|
||||
};
|
||||
|
||||
const toggleUsdAmount = (usdCell, isVisible) => {
|
||||
const usdText = document.getElementById('usd-text');
|
||||
if (usdText) {
|
||||
usdText.style.display = isVisible ? 'inline' : 'none';
|
||||
}
|
||||
|
||||
if (isVisible) {
|
||||
const coinFullName = usdCell.previousElementSibling.getAttribute('data-coinname');
|
||||
const cryptoValue = parseFloat(usdCell.previousElementSibling.textContent);
|
||||
const coinSymbol = coinNameToSymbol[coinFullName];
|
||||
if (coinSymbol) {
|
||||
updateValues();
|
||||
} else {
|
||||
console.error(`Coin symbol not found for full name: ${coinFullName}`);
|
||||
}
|
||||
} else {
|
||||
usdCell.textContent = "******";
|
||||
const btcValueElement = usdCell.nextElementSibling;
|
||||
if (btcValueElement) {
|
||||
btcValueElement.textContent = "****";
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const toggleUsdIcon = (isVisible) => {
|
||||
const usdIcon = document.querySelector("#hide-usd-amount-toggle svg");
|
||||
if (usdIcon) {
|
||||
if (isVisible) {
|
||||
usdIcon.innerHTML = `
|
||||
<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>
|
||||
`;
|
||||
} else {
|
||||
usdIcon.innerHTML = `
|
||||
<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>
|
||||
`;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const calculateTotalUsdValue = async () => {
|
||||
const coinNameValues = document.querySelectorAll('.coinname-value');
|
||||
let totalUsdValue = 0;
|
||||
|
||||
for (const coinNameValue of coinNameValues) {
|
||||
const coinFullName = coinNameValue.getAttribute('data-coinname');
|
||||
const cryptoValue = parseFloat(coinNameValue.textContent);
|
||||
const coinSymbol = coinNameToSymbol[coinFullName];
|
||||
|
||||
if (coinSymbol) {
|
||||
try {
|
||||
const { usdValue } = await getUsdValue(cryptoValue, coinSymbol);
|
||||
totalUsdValue += usdValue;
|
||||
|
||||
const usdValueElement = coinNameValue.parentElement.nextElementSibling.querySelector('.usd-value');
|
||||
if (usdValueElement) {
|
||||
usdValueElement.textContent = `$${usdValue.toFixed(2)}`;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(`Error retrieving exchange rate for ${coinSymbol}`);
|
||||
}
|
||||
} else {
|
||||
console.error(`Coin symbol not found for full name: ${coinFullName}`);
|
||||
}
|
||||
}
|
||||
|
||||
const totalUsdValueElement = document.getElementById('total-usd-value');
|
||||
if (totalUsdValueElement) {
|
||||
totalUsdValueElement.textContent = `$${totalUsdValue.toFixed(2)}`;
|
||||
}
|
||||
};
|
||||
|
||||
const calculateTotalBtcValue = async () => {
|
||||
const usdValueElements = document.getElementsByClassName('usd-value');
|
||||
let totalBtcValue = 0;
|
||||
|
||||
try {
|
||||
const btcToUsdRate = await fetch('https://min-api.cryptocompare.com/data/price?fsym=BTC&tsyms=USD')
|
||||
.then(response => response.json())
|
||||
.then(data => data.USD);
|
||||
|
||||
for (const usdValueElement of usdValueElements) {
|
||||
const usdValue = parseFloat(usdValueElement.textContent.replace('$', ''));
|
||||
const btcValue = usdValue / btcToUsdRate;
|
||||
|
||||
if (!isNaN(btcValue)) {
|
||||
totalBtcValue += btcValue;
|
||||
} else {
|
||||
console.error(`Invalid USD value: ${usdValue}`);
|
||||
}
|
||||
}
|
||||
|
||||
const totalBtcValueElement = document.getElementById('total-btc-value');
|
||||
if (totalBtcValueElement) {
|
||||
if (localStorage.getItem('usdAmountVisible') === 'false') {
|
||||
totalBtcValueElement.textContent = "****";
|
||||
} else {
|
||||
totalBtcValueElement.textContent = `~ ${totalBtcValue.toFixed(8)} BTC`;
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(`Error retrieving BTC to USD exchange rate: ${error}`);
|
||||
}
|
||||
};
|
||||
|
||||
const loadUsdAmountVisibility = async () => {
|
||||
let usdAmountVisible = localStorage.getItem('usdAmountVisible') === 'true';
|
||||
toggleUsdIcon(usdAmountVisible);
|
||||
|
||||
const usdValueElements = document.getElementsByClassName('usd-value');
|
||||
for (const usdValueElement of usdValueElements) {
|
||||
toggleUsdAmount(usdValueElement, usdAmountVisible, !usdAmountVisible);
|
||||
}
|
||||
|
||||
const totalUsdValueElement = document.getElementById('total-usd-value');
|
||||
if (!usdAmountVisible && totalUsdValueElement) {
|
||||
totalUsdValueElement.textContent = "*****";
|
||||
} else if (usdAmountVisible && totalUsdValueElement) {
|
||||
await calculateTotalUsdValue();
|
||||
calculateTotalBtcValue();
|
||||
}
|
||||
};
|
||||
|
||||
window.onload = async () => {
|
||||
const hideUsdAmountToggle = document.getElementById('hide-usd-amount-toggle');
|
||||
let usdAmountVisible = localStorage.getItem('usdAmountVisible') === 'true';
|
||||
|
||||
hideUsdAmountToggle.addEventListener('click', async () => {
|
||||
usdAmountVisible = !usdAmountVisible;
|
||||
localStorage.setItem('usdAmountVisible', usdAmountVisible);
|
||||
|
||||
toggleUsdIcon(usdAmountVisible);
|
||||
|
||||
const usdValueElements = document.getElementsByClassName('usd-value');
|
||||
for (const usdValueElement of usdValueElements) {
|
||||
toggleUsdAmount(usdValueElement, usdAmountVisible);
|
||||
}
|
||||
|
||||
const totalUsdValueElement = document.getElementById('total-usd-value');
|
||||
if (!usdAmountVisible && totalUsdValueElement) {
|
||||
totalUsdValueElement.textContent = "*****";
|
||||
} else if (usdAmountVisible && totalUsdValueElement) {
|
||||
await calculateTotalUsdValue();
|
||||
}
|
||||
|
||||
const totalBtcValueElement = document.getElementById('total-btc-value');
|
||||
if (!usdAmountVisible && totalBtcValueElement) {
|
||||
totalBtcValueElement.textContent = "";
|
||||
} else if (usdAmountVisible && totalBtcValueElement) {
|
||||
await calculateTotalBtcValue();
|
||||
}
|
||||
});
|
||||
|
||||
await loadUsdAmountVisibility();
|
||||
};
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
Reference in New Issue
Block a user