diff --git a/basicswap/static/js/wallets.js b/basicswap/static/js/wallets.js
new file mode 100644
index 0000000..4f5f70c
--- /dev/null
+++ b/basicswap/static/js/wallets.js
@@ -0,0 +1,654 @@
+const Wallets = (function() {
+ const CONFIG = {
+ MAX_RETRIES: 5,
+ BASE_DELAY: 500,
+ CACHE_EXPIRATION: 5 * 60 * 1000,
+ PRICE_UPDATE_INTERVAL: 5 * 60 * 1000,
+ API_TIMEOUT: 30000,
+ DEBOUNCE_DELAY: 300,
+ CACHE_MIN_INTERVAL: 60 * 1000,
+ DEFAULT_TTL: 300,
+ PRICE_SOURCE: {
+ PRIMARY: 'coingecko.com',
+ FALLBACK: 'cryptocompare.com',
+ ENABLED_SOURCES: ['coingecko.com', 'cryptocompare.com']
+ }
+ };
+
+ const COIN_SYMBOLS = {
+ 'Bitcoin': 'BTC',
+ 'Particl': 'PART',
+ 'Monero': 'XMR',
+ 'Wownero': 'WOW',
+ 'Litecoin': 'LTC',
+ 'Dogecoin': 'DOGE',
+ 'Firo': 'FIRO',
+ 'Dash': 'DASH',
+ 'PIVX': 'PIVX',
+ 'Decred': 'DCR',
+ 'Bitcoin Cash': 'BCH'
+ };
+
+ const COINGECKO_IDS = {
+ 'BTC': 'btc',
+ 'PART': 'part',
+ 'XMR': 'xmr',
+ 'WOW': 'wownero',
+ 'LTC': 'ltc',
+ 'DOGE': 'doge',
+ 'FIRO': 'firo',
+ 'DASH': 'dash',
+ 'PIVX': 'pivx',
+ 'DCR': 'dcr',
+ 'BCH': 'bch'
+ };
+
+ const SHORT_NAMES = {
+ 'Bitcoin': 'BTC',
+ 'Particl': 'PART',
+ 'Monero': 'XMR',
+ 'Wownero': 'WOW',
+ 'Litecoin': 'LTC',
+ 'Litecoin MWEB': 'LTC MWEB',
+ 'Firo': 'FIRO',
+ 'Dash': 'DASH',
+ 'PIVX': 'PIVX',
+ 'Decred': 'DCR',
+ 'Bitcoin Cash': 'BCH',
+ 'Dogecoin': 'DOGE'
+ };
+
+ class Cache {
+ constructor(expirationTime) {
+ this.data = null;
+ this.timestamp = null;
+ this.expirationTime = expirationTime;
+ }
+
+ isValid() {
+ return Boolean(
+ this.data &&
+ this.timestamp &&
+ (Date.now() - this.timestamp < this.expirationTime)
+ );
+ }
+
+ set(data) {
+ this.data = data;
+ this.timestamp = Date.now();
+ }
+
+ get() {
+ if (this.isValid()) {
+ return this.data;
+ }
+ return null;
+ }
+
+ clear() {
+ this.data = null;
+ this.timestamp = null;
+ }
+ }
+
+ class ApiClient {
+ constructor() {
+ this.cache = new Cache(CONFIG.CACHE_EXPIRATION);
+ this.lastFetchTime = 0;
+ }
+
+ async fetchPrices(forceUpdate = false) {
+ const now = Date.now();
+ const timeSinceLastFetch = now - this.lastFetchTime;
+
+ if (!forceUpdate && timeSinceLastFetch < CONFIG.CACHE_MIN_INTERVAL) {
+ const cachedData = this.cache.get();
+ if (cachedData) {
+ return cachedData;
+ }
+ }
+
+ let lastError = null;
+ for (let attempt = 0; attempt < CONFIG.MAX_RETRIES; attempt++) {
+ try {
+ const processedData = {};
+ const currentSource = CONFIG.PRICE_SOURCE.PRIMARY;
+
+ const shouldIncludeWow = currentSource === 'coingecko.com';
+
+ const coinsToFetch = Object.values(COIN_SYMBOLS)
+ .filter(symbol => shouldIncludeWow || symbol !== 'WOW')
+ .map(symbol => COINGECKO_IDS[symbol] || symbol.toLowerCase())
+ .join(',');
+
+ const mainResponse = await fetch("/json/coinprices", {
+ method: "POST",
+ headers: {'Content-Type': 'application/json'},
+ body: JSON.stringify({
+ coins: coinsToFetch,
+ source: currentSource,
+ ttl: CONFIG.DEFAULT_TTL
+ })
+ });
+
+ if (!mainResponse.ok) {
+ throw new Error(`HTTP error: ${mainResponse.status}`);
+ }
+
+ const mainData = await mainResponse.json();
+
+ if (mainData && mainData.rates) {
+ Object.entries(mainData.rates).forEach(([coinId, price]) => {
+ const symbol = Object.entries(COINGECKO_IDS).find(([sym, id]) => id.toLowerCase() === coinId.toLowerCase())?.[0];
+ if (symbol) {
+ const coinKey = Object.keys(COIN_SYMBOLS).find(key => COIN_SYMBOLS[key] === symbol);
+ if (coinKey) {
+ processedData[coinKey.toLowerCase().replace(' ', '-')] = {
+ usd: price,
+ btc: symbol === 'BTC' ? 1 : price / (mainData.rates.btc || 1)
+ };
+ }
+ }
+ });
+ }
+
+ if (!shouldIncludeWow && !processedData['wownero']) {
+ try {
+ const wowResponse = await fetch("/json/coinprices", {
+ method: "POST",
+ headers: {'Content-Type': 'application/json'},
+ body: JSON.stringify({
+ coins: "wownero",
+ source: "coingecko.com",
+ ttl: CONFIG.DEFAULT_TTL
+ })
+ });
+
+ if (wowResponse.ok) {
+ const wowData = await wowResponse.json();
+ if (wowData && wowData.rates && wowData.rates.wownero) {
+ processedData['wownero'] = {
+ usd: wowData.rates.wownero,
+ btc: processedData.bitcoin ? wowData.rates.wownero / processedData.bitcoin.usd : 0
+ };
+ }
+ }
+ } catch (wowError) {
+ console.error('Error fetching WOW price:', wowError);
+ }
+ }
+
+ this.cache.set(processedData);
+ this.lastFetchTime = now;
+ return processedData;
+ } catch (error) {
+ lastError = error;
+ console.error(`Price fetch attempt ${attempt + 1} failed:`, error);
+
+ if (attempt === CONFIG.MAX_RETRIES - 1 &&
+ CONFIG.PRICE_SOURCE.FALLBACK &&
+ CONFIG.PRICE_SOURCE.FALLBACK !== CONFIG.PRICE_SOURCE.PRIMARY) {
+ const temp = CONFIG.PRICE_SOURCE.PRIMARY;
+ CONFIG.PRICE_SOURCE.PRIMARY = CONFIG.PRICE_SOURCE.FALLBACK;
+ CONFIG.PRICE_SOURCE.FALLBACK = temp;
+
+ console.warn(`Switching to fallback source: ${CONFIG.PRICE_SOURCE.PRIMARY}`);
+ attempt = -1;
+ continue;
+ }
+
+ if (attempt < CONFIG.MAX_RETRIES - 1) {
+ const delay = Math.min(CONFIG.BASE_DELAY * Math.pow(2, attempt), 10000);
+ await new Promise(resolve => setTimeout(resolve, delay));
+ }
+ }
+ }
+
+ const cachedData = this.cache.get();
+ if (cachedData) {
+ console.warn('Using cached data after fetch failures');
+ return cachedData;
+ }
+
+ throw lastError || new Error('Failed to fetch prices');
+ }
+
+ setPriceSource(primarySource, fallbackSource = null) {
+ if (!CONFIG.PRICE_SOURCE.ENABLED_SOURCES.includes(primarySource)) {
+ throw new Error(`Invalid primary source: ${primarySource}`);
+ }
+
+ if (fallbackSource && !CONFIG.PRICE_SOURCE.ENABLED_SOURCES.includes(fallbackSource)) {
+ throw new Error(`Invalid fallback source: ${fallbackSource}`);
+ }
+
+ CONFIG.PRICE_SOURCE.PRIMARY = primarySource;
+ if (fallbackSource) {
+ CONFIG.PRICE_SOURCE.FALLBACK = fallbackSource;
+ }
+ }
+ }
+
+ class UiManager {
+ constructor() {
+ this.api = new ApiClient();
+ this.toggleInProgress = false;
+ this.toggleDebounceTimer = null;
+ this.priceUpdateInterval = null;
+ this.lastUpdateTime = parseInt(localStorage.getItem(STATE_KEYS.LAST_UPDATE) || '0');
+ this.isWalletsPage = document.querySelector('.wallet-list') !== null ||
+ window.location.pathname.includes('/wallets');
+ }
+
+ getShortName(fullName) {
+ return SHORT_NAMES[fullName] || fullName;
+ }
+
+ storeOriginalValues() {
+ document.querySelectorAll('.coinname-value').forEach(el => {
+ const coinName = el.getAttribute('data-coinname');
+ const value = el.textContent?.trim() || '';
+
+ if (coinName) {
+ const amount = value ? parseFloat(value.replace(/[^0-9.-]+/g, '')) : 0;
+ const coinId = COIN_SYMBOLS[coinName];
+ const shortName = this.getShortName(coinName);
+
+ if (coinId) {
+ if (coinName === 'Particl') {
+ const isBlind = el.closest('.flex')?.querySelector('h4')?.textContent?.includes('Blind');
+ const isAnon = el.closest('.flex')?.querySelector('h4')?.textContent?.includes('Anon');
+ const balanceType = isBlind ? 'blind' : isAnon ? 'anon' : 'public';
+ localStorage.setItem(`particl-${balanceType}-amount`, amount.toString());
+ } else if (coinName === 'Litecoin') {
+ const isMWEB = el.closest('.flex')?.querySelector('h4')?.textContent?.includes('MWEB');
+ const balanceType = isMWEB ? 'mweb' : 'public';
+ localStorage.setItem(`litecoin-${balanceType}-amount`, amount.toString());
+ } else {
+ localStorage.setItem(`${coinId.toLowerCase()}-amount`, amount.toString());
+ }
+
+ el.setAttribute('data-original-value', `${amount} ${shortName}`);
+ }
+ }
+ });
+
+ document.querySelectorAll('.usd-value').forEach(el => {
+ const text = el.textContent?.trim() || '';
+ if (text === 'Loading...') {
+ el.textContent = '';
+ }
+ });
+ }
+
+ async updatePrices(forceUpdate = false) {
+ try {
+ const prices = await this.api.fetchPrices(forceUpdate);
+ let newTotal = 0;
+
+ const currentTime = Date.now();
+ localStorage.setItem(STATE_KEYS.LAST_UPDATE, currentTime.toString());
+ this.lastUpdateTime = currentTime;
+
+ if (prices) {
+ Object.entries(prices).forEach(([coinId, priceData]) => {
+ if (priceData?.usd) {
+ localStorage.setItem(`${coinId}-price`, priceData.usd.toString());
+ }
+ });
+ }
+
+ document.querySelectorAll('.coinname-value').forEach(el => {
+ const coinName = el.getAttribute('data-coinname');
+ const amountStr = el.getAttribute('data-original-value') || el.textContent?.trim() || '';
+
+ if (!coinName) return;
+
+ let amount = 0;
+ if (amountStr) {
+ const matches = amountStr.match(/([0-9]*[.])?[0-9]+/);
+ if (matches && matches.length > 0) {
+ amount = parseFloat(matches[0]);
+ }
+ }
+
+ const coinId = coinName.toLowerCase().replace(' ', '-');
+
+ if (!prices[coinId]) {
+ return;
+ }
+
+ const price = prices[coinId]?.usd || parseFloat(localStorage.getItem(`${coinId}-price`) || '0');
+ if (!price) return;
+
+ const usdValue = (amount * price).toFixed(2);
+
+ if (coinName === 'Particl') {
+ const isBlind = el.closest('.flex')?.querySelector('h4')?.textContent?.includes('Blind');
+ const isAnon = el.closest('.flex')?.querySelector('h4')?.textContent?.includes('Anon');
+ const balanceType = isBlind ? 'blind' : isAnon ? 'anon' : 'public';
+ localStorage.setItem(`particl-${balanceType}-last-value`, usdValue);
+ localStorage.setItem(`particl-${balanceType}-amount`, amount.toString());
+ } else if (coinName === 'Litecoin') {
+ const isMWEB = el.closest('.flex')?.querySelector('h4')?.textContent?.includes('MWEB');
+ const balanceType = isMWEB ? 'mweb' : 'public';
+ localStorage.setItem(`litecoin-${balanceType}-last-value`, usdValue);
+ localStorage.setItem(`litecoin-${balanceType}-amount`, amount.toString());
+ } else {
+ localStorage.setItem(`${coinId}-last-value`, usdValue);
+ localStorage.setItem(`${coinId}-amount`, amount.toString());
+ }
+
+ if (amount > 0) {
+ newTotal += parseFloat(usdValue);
+ }
+
+ let usdEl = null;
+
+ const flexContainer = el.closest('.flex');
+ if (flexContainer) {
+ const nextFlex = flexContainer.nextElementSibling;
+ if (nextFlex) {
+ const usdInNextFlex = nextFlex.querySelector('.usd-value');
+ if (usdInNextFlex) {
+ usdEl = usdInNextFlex;
+ }
+ }
+ }
+
+ if (!usdEl) {
+ const parentCell = el.closest('td');
+ if (parentCell) {
+ const usdInSameCell = parentCell.querySelector('.usd-value');
+ if (usdInSameCell) {
+ usdEl = usdInSameCell;
+ }
+ }
+ }
+
+ if (!usdEl) {
+ const sibling = el.nextElementSibling;
+ if (sibling && sibling.classList.contains('usd-value')) {
+ usdEl = sibling;
+ }
+ }
+
+ if (!usdEl) {
+ const parentElement = el.parentElement;
+ if (parentElement) {
+ const usdElNearby = parentElement.querySelector('.usd-value');
+ if (usdElNearby) {
+ usdEl = usdElNearby;
+ }
+ }
+ }
+
+ if (usdEl) {
+ usdEl.textContent = `$${usdValue}`;
+ usdEl.setAttribute('data-original-value', usdValue);
+ }
+ });
+
+ document.querySelectorAll('.usd-value').forEach(el => {
+ if (el.closest('tr')?.querySelector('td')?.textContent?.includes('Fee Estimate:')) {
+ const parentCell = el.closest('td');
+ if (!parentCell) return;
+
+ const coinValueEl = parentCell.querySelector('.coinname-value');
+ if (!coinValueEl) return;
+
+ const coinName = coinValueEl.getAttribute('data-coinname');
+ if (!coinName) return;
+
+ const amountStr = coinValueEl.textContent?.trim() || '0';
+ const amount = parseFloat(amountStr) || 0;
+
+ const coinId = coinName.toLowerCase().replace(' ', '-');
+ if (!prices[coinId]) return;
+
+ const price = prices[coinId]?.usd || parseFloat(localStorage.getItem(`${coinId}-price`) || '0');
+ if (!price) return;
+
+ const usdValue = (amount * price).toFixed(8);
+ el.textContent = `$${usdValue}`;
+ el.setAttribute('data-original-value', usdValue);
+ }
+ });
+
+ if (this.isWalletsPage) {
+ this.updateTotalValues(newTotal, prices?.bitcoin?.usd);
+ }
+
+ localStorage.setItem(STATE_KEYS.PREVIOUS_TOTAL, localStorage.getItem(STATE_KEYS.CURRENT_TOTAL) || '0');
+ localStorage.setItem(STATE_KEYS.CURRENT_TOTAL, newTotal.toString());
+
+ return true;
+ } catch (error) {
+ console.error('Price update failed:', error);
+ return false;
+ }
+ }
+
+ updateTotalValues(totalUsd, btcPrice) {
+ const totalUsdEl = document.getElementById('total-usd-value');
+ if (totalUsdEl) {
+ totalUsdEl.textContent = `$${totalUsd.toFixed(2)}`;
+ totalUsdEl.setAttribute('data-original-value', totalUsd.toString());
+ localStorage.setItem('total-usd', totalUsd.toString());
+ }
+
+ if (btcPrice) {
+ const btcTotal = btcPrice ? totalUsd / btcPrice : 0;
+ const totalBtcEl = document.getElementById('total-btc-value');
+ if (totalBtcEl) {
+ totalBtcEl.textContent = `~ ${btcTotal.toFixed(8)} BTC`;
+ totalBtcEl.setAttribute('data-original-value', btcTotal.toString());
+ }
+ }
+ }
+
+ async toggleBalances() {
+ if (this.toggleInProgress) return;
+
+ try {
+ this.toggleInProgress = true;
+ const balancesVisible = localStorage.getItem('balancesVisible') === 'true';
+ const newVisibility = !balancesVisible;
+
+ localStorage.setItem('balancesVisible', newVisibility.toString());
+ this.updateVisibility(newVisibility);
+
+ if (this.toggleDebounceTimer) {
+ clearTimeout(this.toggleDebounceTimer);
+ }
+
+ this.toggleDebounceTimer = window.setTimeout(async () => {
+ this.toggleInProgress = false;
+ if (newVisibility) {
+ await this.updatePrices(true);
+ }
+ }, CONFIG.DEBOUNCE_DELAY);
+ } catch (error) {
+ console.error('Failed to toggle balances:', error);
+ this.toggleInProgress = false;
+ }
+ }
+
+ updateVisibility(isVisible) {
+ if (isVisible) {
+ this.showBalances();
+ } else {
+ this.hideBalances();
+ }
+
+ const eyeIcon = document.querySelector("#hide-usd-amount-toggle svg");
+ if (eyeIcon) {
+ eyeIcon.innerHTML = isVisible ?
+ ' ' :
+ ' ';
+ }
+ }
+
+ showBalances() {
+ const usdText = document.getElementById('usd-text');
+ if (usdText) {
+ usdText.style.display = 'inline';
+ }
+
+ document.querySelectorAll('.coinname-value').forEach(el => {
+ const originalValue = el.getAttribute('data-original-value');
+ if (originalValue) {
+ el.textContent = originalValue;
+ }
+ });
+
+ document.querySelectorAll('.usd-value').forEach(el => {
+ const storedValue = el.getAttribute('data-original-value');
+ if (storedValue !== null && storedValue !== undefined) {
+ if (el.closest('tr')?.querySelector('td')?.textContent?.includes('Fee Estimate:')) {
+ el.textContent = `$${parseFloat(storedValue).toFixed(8)}`;
+ } else {
+ el.textContent = `$${parseFloat(storedValue).toFixed(2)}`;
+ }
+ } else {
+ if (el.closest('tr')?.querySelector('td')?.textContent?.includes('Fee Estimate:')) {
+ el.textContent = '$0.00000000';
+ } else {
+ el.textContent = '$0.00';
+ }
+ }
+ });
+
+ if (this.isWalletsPage) {
+ ['total-usd-value', 'total-btc-value'].forEach(id => {
+ const el = document.getElementById(id);
+ const originalValue = el?.getAttribute('data-original-value');
+ if (el && originalValue) {
+ if (id === 'total-usd-value') {
+ el.textContent = `$${parseFloat(originalValue).toFixed(2)}`;
+ el.classList.add('font-extrabold');
+ } else {
+ el.textContent = `~ ${parseFloat(originalValue).toFixed(8)} BTC`;
+ }
+ }
+ });
+ }
+ }
+
+ hideBalances() {
+ const usdText = document.getElementById('usd-text');
+ if (usdText) {
+ usdText.style.display = 'none';
+ }
+
+ document.querySelectorAll('.coinname-value').forEach(el => {
+ el.textContent = '****';
+ });
+
+ document.querySelectorAll('.usd-value').forEach(el => {
+ el.textContent = '****';
+ });
+
+ if (this.isWalletsPage) {
+ ['total-usd-value', 'total-btc-value'].forEach(id => {
+ const el = document.getElementById(id);
+ if (el) {
+ el.textContent = '****';
+ }
+ });
+
+ const totalUsdEl = document.getElementById('total-usd-value');
+ if (totalUsdEl) {
+ totalUsdEl.classList.remove('font-extrabold');
+ }
+ }
+ }
+
+ async initialize() {
+ document.querySelectorAll('.usd-value').forEach(el => {
+ const text = el.textContent?.trim() || '';
+ if (text === 'Loading...') {
+ el.textContent = '';
+ }
+ });
+
+ this.storeOriginalValues();
+
+ if (localStorage.getItem('balancesVisible') === null) {
+ localStorage.setItem('balancesVisible', 'true');
+ }
+
+ const hideBalancesToggle = document.getElementById('hide-usd-amount-toggle');
+ if (hideBalancesToggle) {
+ hideBalancesToggle.addEventListener('click', () => this.toggleBalances());
+ }
+
+ await this.loadBalanceVisibility();
+
+ if (this.priceUpdateInterval) {
+ clearInterval(this.priceUpdateInterval);
+ }
+
+ this.priceUpdateInterval = setInterval(() => {
+ if (localStorage.getItem('balancesVisible') === 'true' && !this.toggleInProgress) {
+ this.updatePrices(false);
+ }
+ }, CONFIG.PRICE_UPDATE_INTERVAL);
+ }
+
+ async loadBalanceVisibility() {
+ const balancesVisible = localStorage.getItem('balancesVisible') === 'true';
+ this.updateVisibility(balancesVisible);
+
+ if (balancesVisible) {
+ await this.updatePrices(true);
+ }
+ }
+
+ cleanup() {
+ if (this.priceUpdateInterval) {
+ clearInterval(this.priceUpdateInterval);
+ }
+ }
+ }
+
+ const STATE_KEYS = {
+ LAST_UPDATE: 'last-update-time',
+ PREVIOUS_TOTAL: 'previous-total-usd',
+ CURRENT_TOTAL: 'current-total-usd',
+ BALANCES_VISIBLE: 'balancesVisible'
+ };
+
+ return {
+ initialize: function() {
+ const uiManager = new UiManager();
+
+ window.cryptoPricingManager = uiManager;
+
+ window.addEventListener('beforeunload', () => {
+ uiManager.cleanup();
+ });
+
+ uiManager.initialize().catch(error => {
+ console.error('Failed to initialize crypto pricing:', error);
+ });
+
+ return uiManager;
+ },
+
+ getUiManager: function() {
+ return window.cryptoPricingManager;
+ },
+
+ setPriceSource: function(primarySource, fallbackSource = null) {
+ const uiManager = this.getUiManager();
+ if (uiManager && uiManager.api) {
+ uiManager.api.setPriceSource(primarySource, fallbackSource);
+ }
+ }
+ };
+})();
+
+document.addEventListener('DOMContentLoaded', function() {
+ Wallets.initialize();
+});
diff --git a/basicswap/templates/header.html b/basicswap/templates/header.html
index a8ed7ae..0e8b867 100644
--- a/basicswap/templates/header.html
+++ b/basicswap/templates/header.html
@@ -120,8 +120,25 @@
updateShutdownButtons();
});
-
+
+
+
-
-
-
-
+
+
+
+
+
+
-
({{ w.ticker }}) {{ w.name }} Wallet
+
+
+ ({{ w.ticker }}) {{ w.name }} Wallet
-
- {% include 'inc_messages.html' %}
- {% if w.updating %}
+
+
+{% include 'inc_messages.html' %}
+
+{% if w.updating %}
- {% endif %}
- {% if w.havedata %}
- {% if w.error %}
+{% endif %}
+
+{% if w.havedata %}
+{% if w.error %}
- {% else %}
+{% else %}
+
{% if w.cid == '18' %} {# DOGE #}
-
- NOTICE:
- This version of DOGE Core is experimental and has been custom-built for compatibility with BasicSwap. As a result, it may not always be fully aligned with upstream changes, features unrelated to BasicSwap might not work as expected, and its code may differ from the official release.
+ NOTICE: This version of DOGE Core is experimental and has been custom-built for compatibility with BasicSwap. As a result, it may not always be fully aligned with upstream changes, features unrelated to BasicSwap might not work as expected, and its code may differ from the official release.
@@ -102,9 +94,10 @@
{% endif %}
-
@@ -316,14 +314,13 @@
Subaddress:
-
{{ w.deposit_address }}
+
{{ w.deposit_address }}
{{ circular_arrows_svg }} New {{ w.name }} Deposit Address
-
Stealth Address:
-
{{ w.stealth_address }}
+
{{ w.stealth_address }}
-
MWEB Address:
-
{{ w.mweb_address }}
+
{{ w.mweb_address }}
@@ -350,11 +346,8 @@
{{ circular_arrows_svg }} New MWEB Address
-
@@ -368,7 +361,8 @@
- {% if w.cid == '1' %}
+
+{% if w.cid == '1' %}
{# PART #}
+
{% elif w.cid == '3' %}
{# LTC #}
{% endif %}
+
{% if w.cid in '6, 9' %}
{# XMR | WOW #}
+
+
{% else %}
+
{% endif %}
+
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
- Options
-
-
- Input
-
-
-
-
- Balance:
- {{ w.balance }} {{ w.ticker }}
-
- {% if w.cid == '3' %}
- {# LTC #}
-
- MWEB Balance:
- {{ w.mweb_balance }} {{ w.ticker }}
-
- {% elif w.cid == '1' %}
- {# PART #}
-
- Blind Balance:
- {{ w.blind_balance }} {{ w.ticker }}
-
-
- Anon Balance:
- {{ w.anon_balance }} {{ w.ticker }}
-
- {% endif %}
-
- {{ w.name }} Address:
-
-
-
- {{ w.name }} Amount:
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Options
+
+
+ Input
+
+
+
+
+ Balance:
+
+ {{ w.balance }} {{ w.ticker }}
+ ( )
+
+
+ {% if w.cid == '3' %}
+ {# LTC #}
+
+ MWEB Balance:
+
+ {{ w.mweb_balance }} {{ w.ticker }}
+ ( )
+
+
+ {% elif w.cid == '1' %}
+ {# PART #}
+
+ Blind Balance:
+
+ {{ w.blind_balance }} {{ w.ticker }}
+ ( )
+
+
+
+ Anon Balance:
+
+ {{ w.anon_balance }} {{ w.ticker }}
+ ( )
+
+
+ {% endif %}
+
+ {{ w.name }} Address:
+
+
+
+ {{ w.name }} Amount:
+
+
+
+
{% if w.cid == '1' %}
{# PART #}
25%
50%
100%
+
+
{# / PART #}
+
{% elif w.cid == '3' %}
{# LTC #}
25%
50%
100%
+
+
{# / LTC #}
{% else %}
25%
50%
100%
+
-{% endif %}
+ let sweepAllCheckbox = document.getElementById('sweepall');
+ if (sweepAllCheckbox) {
+ if (specialCids.includes(parseInt(cid)) && percent === 1) {
+ sweepAllCheckbox.checked = true;
+ console.log("Sweep All checkbox checked");
+ } else {
+ sweepAllCheckbox.checked = false;
+ console.log("Sweep All checkbox unchecked");
+ }
+ }
+
+ let subfeeCheckbox = document.querySelector(`[name="subfee_${cid}"]`);
+ if (subfeeCheckbox) {
+ subfeeCheckbox.checked = (percent === 1);
+ console.log("Subfee checkbox status for CID", cid, ":", subfeeCheckbox.checked);
+ }
+ }
+
+ {% endif %}
+
+
+
+
+
+
+ {% if w.cid in '6, 9' %} {# XMR | WOW #}
+ Sweep All:
+
+
+
+ {% else %}
+ Subtract Fee:
+
+
+
+ {% endif %}
+
+
+
+ {% if w.cid == '1' %}
+ {# PART #}
+
+ Type From:
+
+
+
{{ select_box_arrow_svg | safe }}
+ Select Type
+ Plain
+ Blind
+ Anon
+
+
+
+
+
+ Type To:
+
+
+
{{ select_box_arrow_svg }}
+ Select Type
+ Plain
+ Blind
+ Anon
+
+
+
+
+ {# / PART #}
+ {% elif w.cid == '3' %} {# LTC #}
+
+ Type From:
+
+
+
{{ select_box_arrow_svg }}
+ Plain
+ MWEB
+
+
+
+
+ {% endif %}
+ {# / LTC #}
+ {% if w.cid not in '6,9' %} {# Not XMR WOW #}
+
+ Fee Rate:
+ {{ w.fee_rate }}
+
+
+ Fee Estimate:
+
+ {{ w.est_fee }}
+ ( )
+
+
+ {% endif %}
+
+
+
+
+
-
-
-
-
- {% if w.cid in '6, 9' %} {# XMR | WOW #}
- Sweep All:
-
-
-
- {% else %}
- Subtract Fee:
-
-
-
- {% endif %}
-
-
-
- {% if w.cid == '1' %}
- {# PART #}
-
- Type From:
-
-
-
{{ select_box_arrow_svg | safe }}
- Select Type
- Plain
- Blind
- Anon
-
-
-
-
-
- Type To:
-
-
-
{{ select_box_arrow_svg }}
- Select Type
- Plain
- Blind
- Anon
-
-
-
-
- {# / PART #}
- {% elif w.cid == '3' %} {# LTC #}
-
- Type From:
-
-
-
{{ select_box_arrow_svg }}
- Plain
- MWEB
-
-
-
-
- {% endif %}
- {# / LTC #}
- {% if w.cid not in '6,9' %} {# Not XMR WOW #}
-
- Fee Rate:
- {{ w.fee_rate }}
-
-
- Fee Estimate:
- {{ w.est_fee }}
-
- {% endif %}
-
-
-
-
-
-
-
-
-
-
-
+
+
@@ -787,8 +968,9 @@ document.addEventListener('DOMContentLoaded', function() {
-
- {% if w.show_utxo_groups %}
+
+
+{% if w.show_utxo_groups %}
@@ -796,6 +978,7 @@ document.addEventListener('DOMContentLoaded', function() {
+
@@ -834,6 +1017,7 @@ document.addEventListener('DOMContentLoaded', function() {
+
@@ -851,166 +1035,155 @@ document.addEventListener('DOMContentLoaded', function() {
- {% else %}
{% endif %}
+
{% endif %}
{% endif %}
{% endif %}
+
+
+
+
+
+
+
Confirm Action
+
Are you sure?
+
+
+ Confirm
+
+
+ Cancel
+
+
+
+
+
+
+
+
+
{% include 'footer.html' %}