function setRecentTransactionsForWalletState(state) { recentTransactionsCacheReadId += 1; latestTransactionsSyncId += 1; clearRecentTransactionsRows(); stopLatestDashboardTransactionsPolling(); if (state === "registered") { setRecentTransactionsState(""); resetLatestDashboardTransactionsMemory(); updateLatestDashboardTransactionsPolling(); startBackgroundTransactionSync(); return; } stopBackgroundTransactionSync(); resetLatestDashboardTransactionsMemory(); if (state === "checking") { setRecentTransactionsState("Checking address registration before loading transactions."); return; } if (state === "unregistered") { setRecentTransactionsState("Address registration required before transactions can appear."); return; } setRecentTransactionsState("Load a wallet to view recent transactions."); } function resetBalances(message = "Load wallet", statusMessage = "Balances refresh while dashboard is open.") { activeWalletBalances = []; if (typeof refreshTransferAssetOptions === "function") { refreshTransferAssetOptions(); } if (typeof refreshActiveTransactionFormAfterWalletData === "function") { refreshActiveTransactionFormAfterWalletData(); } if (baseBalanceLabel) { baseBalanceLabel.textContent = `${activeBaseCoin()} Balance`; } if (clcBalance) { clcBalance.textContent = message; } if (tokenBalances) { tokenBalances.innerHTML = `
Token Balances
No wallet loaded.
`; } dashboardLastBalanceStatus = ""; setBalanceStatus(statusMessage); } async function refreshDashboardBalances({ force = false, quiet = false } = {}) { if (!walletLoaded || !registrationRegistered || currentView !== "dashboard" || balanceRefreshInFlight) { return false; } const invoke = window.__TAURI__?.core?.invoke; const broadcastNode = activeBroadcastNode(); if (!invoke || !broadcastNode) { return false; } balanceRefreshInFlight = true; const requestId = ++balanceRefreshRequestId; if (force && !quiet) { setBalanceStatus("Refreshing balances..."); } try { const balances = await invoke("get_active_wallet_balances", { broadcastNode }); if (requestId !== balanceRefreshRequestId || !walletLoaded) { return false; } renderBalances(balances); dashboardLastBalanceStatus = `Updated ${new Date().toLocaleTimeString()}`; setBalanceStatus(dashboardLastBalanceStatus, "success"); return true; } catch (error) { if (requestId !== balanceRefreshRequestId || !walletLoaded) { return false; } setBalanceStatus(String(error), "error"); return false; } finally { if (requestId === balanceRefreshRequestId) { balanceRefreshInFlight = false; } } } function startBalanceRefresh({ immediate = true } = {}) { if (balanceRefreshTimer || !walletLoaded || !registrationRegistered || currentView !== "dashboard") { return; } if (immediate) { refreshDashboardBalances({ force: true }); } balanceRefreshTimer = setInterval(() => { refreshDashboardBalances(); }, BALANCE_REFRESH_MS); } function stopBalanceRefresh() { if (balanceRefreshTimer) { clearInterval(balanceRefreshTimer); balanceRefreshTimer = null; } } function updateBalanceRefreshState() { if (walletLoaded && registrationRegistered && currentView === "dashboard") { startBalanceRefresh(); return; } stopBalanceRefresh(); } function restoreLatestDashboardTransactionsFromMemory() { if (!latestDashboardTransactionRecords.size || !latestDashboardTxids.length) { return false; } const latestCache = { transactions: Object.fromEntries(latestDashboardTransactionRecords) }; updateTransactionCacheChainStatus(latestCache); latestDashboardTransactionRecords = new Map(Object.entries(latestCache.transactions)); renderRecentTransactions(normalizeRecentTransactionRecords( transactionRecordsForTxids(latestCache, latestDashboardTxids), { preserveOrder: true } )); setRecentTransactionsState(""); return true; } async function startRegisteredDashboardLoadSequence({ resetTransactions = false, quiet = false } = {}) { const loadId = ++dashboardRegisteredLoadId; stopLatestDashboardTransactionsPolling(); stopBalanceRefresh(); if (resetTransactions) { resetLatestDashboardTransactionsMemory(); } const restoredTransactions = restoreLatestDashboardTransactionsFromMemory(); if (!restoredTransactions && !quiet) { setRecentTransactionsForWalletState("checking"); } if (!walletLoaded || !registrationRegistered || currentView !== "dashboard") { return; } if (dashboardLastBalanceStatus) { setBalanceStatus(dashboardLastBalanceStatus, "success"); } await refreshDashboardBalances({ force: true, quiet: quiet || Boolean(dashboardLastBalanceStatus) }); if ( loadId !== dashboardRegisteredLoadId || !walletLoaded || !registrationRegistered || currentView !== "dashboard" ) { return; } startBalanceRefresh({ immediate: false }); if (!restoredTransactions) { setRecentTransactionsForWalletState("registered"); return; } updateLatestDashboardTransactionsPolling(); startBackgroundTransactionSync(); } function startNetworkInfoRefresh() { if (networkInfoRefreshTimer || !walletLoaded || currentView !== "dashboard") { return; } refreshNetworkInfo({ target: "dashboard" }); networkInfoRefreshTimer = setInterval(() => { refreshNetworkInfo({ target: "dashboard" }); }, NETWORK_INFO_REFRESH_MS); } function stopNetworkInfoRefresh() { if (networkInfoRefreshTimer) { clearInterval(networkInfoRefreshTimer); networkInfoRefreshTimer = null; } } function updateNetworkInfoRefreshState() { if (walletLoaded && currentView === "dashboard") { startNetworkInfoRefresh(); return; } stopNetworkInfoRefresh(); } function startNodeInfoRefresh() { if (nodeInfoRefreshTimer || !walletLoaded) { renderNodeInfo(null); return; } refreshNetworkInfo({ target: "node", force: true }); nodeInfoRefreshTimer = setInterval(() => { refreshNetworkInfo({ target: "node", force: true }); }, NODE_INFO_REFRESH_MS); } function stopNodeInfoRefresh() { if (nodeInfoRefreshTimer) { clearInterval(nodeInfoRefreshTimer); nodeInfoRefreshTimer = null; } } function activeBroadcastNode() { return broadcastNodeButton?.value || broadcastNodeButton?.dataset.broadcastNode || broadcastNodeButton?.textContent?.trim() || ""; } function setRegistrationState(state) { const states = ["registered", "unregistered", "checking"]; registrationBadge?.classList.remove(...states); registrationAction?.classList.remove(...states); registrationNotice?.classList.remove(...states); if (state === "registered") { registrationRegistered = true; registrationBadge && (registrationBadge.textContent = "Registered"); registrationBadge?.classList.add("registered"); if (registrationNotice) { registrationNotice.textContent = "Address registered. This wallet can receive coins and tokens."; registrationNotice.classList.add("registered"); } if (registrationAction) { registrationAction.textContent = "Address Registered"; registrationAction.disabled = true; registrationAction.classList.add("registered"); } startRegisteredDashboardLoadSequence(); updateHistoryRefreshState(); updateNetworkInfoRefreshState(); refreshReceivePage(); if (typeof refreshActiveTransactionFormAfterWalletData === "function") { refreshActiveTransactionFormAfterWalletData(); } return; } if (state === "checking") { registrationBadge && (registrationBadge.textContent = "Checking"); registrationBadge?.classList.add("checking"); if (registrationNotice) { registrationNotice.textContent = "Checking whether this address can receive coins and tokens."; registrationNotice.classList.add("checking"); } if (registrationAction) { registrationAction.textContent = "Checking..."; registrationAction.disabled = true; registrationAction.classList.add("checking"); } dashboardRegisteredLoadId += 1; stopBalanceRefresh(); setRecentTransactionsForWalletState("checking"); updateHistoryRefreshState(); refreshReceivePage(); return; } registrationRegistered = false; registrationBadge && (registrationBadge.textContent = "Unregistered"); registrationBadge?.classList.add("unregistered"); if (registrationNotice) { registrationNotice.textContent = "Address must be registered before this wallet can receive coins or tokens."; registrationNotice.classList.add("unregistered"); } if (registrationAction) { registrationAction.textContent = "Register Address"; registrationAction.disabled = false; registrationAction.classList.add("unregistered"); } dashboardRegisteredLoadId += 1; stopBalanceRefresh(); setRecentTransactionsForWalletState("unregistered"); updateHistoryRefreshState(); updateNetworkInfoRefreshState(); refreshReceivePage(); } async function checkWalletRegistrationOnce() { if (!walletLoaded || registrationRegistered || registrationCheckInFlight) { return; } const invoke = window.__TAURI__?.core?.invoke; const broadcastNode = activeBroadcastNode(); if (!invoke || !broadcastNode) { setRegistrationState("unregistered"); return; } registrationCheckInFlight = true; const requestId = ++registrationRequestId; setRegistrationState("checking"); try { const status = await invoke("check_wallet_registration", { broadcastNode }); if (requestId !== registrationRequestId || !walletLoaded) { return; } setRegistrationState(status?.registered ? "registered" : "unregistered"); } catch (_) { if (requestId !== registrationRequestId || !walletLoaded) { return; } setRegistrationState("unregistered"); } finally { if (requestId === registrationRequestId) { registrationCheckInFlight = false; } } } async function registerActiveWallet() { if (!walletLoaded || registrationRegistered || registrationCheckInFlight) { return; } const invoke = window.__TAURI__?.core?.invoke; const broadcastNode = activeBroadcastNode(); if (!invoke || !broadcastNode) { setRegistrationState("unregistered"); return; } registrationCheckInFlight = true; const requestId = ++registrationRequestId; setRegistrationState("checking"); try { const status = await invoke("register_active_wallet", { broadcastNode }); if (requestId !== registrationRequestId || !walletLoaded) { return; } setRegistrationState(status?.registered ? "registered" : "unregistered"); } catch (_) { if (requestId !== registrationRequestId || !walletLoaded) { return; } setRegistrationState("unregistered"); } finally { if (requestId === registrationRequestId) { registrationCheckInFlight = false; } } }