diff --git a/src/components/wallet/Wallet.js b/src/components/wallet/Wallet.js index fc2cbb9..08fb4a0 100644 --- a/src/components/wallet/Wallet.js +++ b/src/components/wallet/Wallet.js @@ -355,23 +355,14 @@ export async function WalletComponent(container) { try { await syncWalletState(); - // ✅ FORCE FRESH FETCH AFTER WALLET SYNC const [balance, transactions, utxos] = await Promise.all([ - fetchBalance(), - fetchTransactions(), - fetchUtxos(), - ]); - - // Save to cache - saveWalletToCache(balance, transactions, utxos); - - // Update UI - await Promise.all([ updateBalance(false), updateTransactions(false), updateUtxos(false), ]); + if (balance) saveWalletToCache(balance, transactions, utxos); + refreshBtn.textContent = 'Refreshed!'; setTimeout(() => { refreshBtn.textContent = originalText; @@ -520,28 +511,21 @@ export async function WalletComponent(container) { }); } - // Initialize data - updateBalance(); - updateTransactions(); - updateUtxos(); - - // ✅ SMART INITIALIZATION if (shouldFetchFresh) { - console.log('🔄 Fetching fresh data...'); - // Fetch fresh data + console.log('🔄 Syncing and fetching fresh data...'); + try { + await window.api.taker.sync(); + } catch (syncErr) { + console.warn('⚠️ Initial wallet sync failed, proceeding anyway:', syncErr.message); + } const [balance, transactions, utxos] = await Promise.all([ updateBalance(false), updateTransactions(false), updateUtxos(false), ]); - - // Save to cache - if (balance && transactions && utxos) { - saveWalletToCache(balance, transactions, utxos); - } + if (balance) saveWalletToCache(balance, transactions, utxos); } else { console.log('⚡ Using cached data (still fresh)'); - // Just use cache await Promise.all([ updateBalance(true), updateTransactions(true), diff --git a/src/js/app.js b/src/js/app.js index c5ef83e..7c5e0d4 100644 --- a/src/js/app.js +++ b/src/js/app.js @@ -184,7 +184,8 @@ async function checkTakerInitialization(config) { if (result.success) { console.log('✅ Taker initialized'); - await performLaunchSync(startMainApp); + startMainApp(); + startBackgroundOfferbookSync(); } else { console.error('❌ Taker initialization failed:', result.error); alert('Failed to initialize: ' + result.error); @@ -283,7 +284,8 @@ async function showPasswordPrompt(config) { if (result.success) { modal.remove(); resolve(true); - await performLaunchSync(startMainApp); + startMainApp(); + startBackgroundOfferbookSync(); } else if (result.wrongPassword) { errorDiv.classList.remove('hidden'); errorDiv.querySelector('p').textContent = @@ -317,206 +319,34 @@ async function showPasswordPrompt(config) { }); } -/** - * Show an offerbook sync overlay, wait for sync to complete, then call onComplete. - * Used on launch so the user sees makers as soon as the app opens. - */ -async function performLaunchSync(onComplete) { - const escapeHtml = (value) => { - const div = document.createElement('div'); - div.textContent = value || ''; - return div.innerHTML; - }; - - const parseLogLine = (line) => { - const match = line.match( - /^(\d{4}-\d{2}-\d{2}T[\d:.]+)[^\s]*\s+(INFO|WARN|ERROR|DEBUG|TRACE)\s+(.+)$/ - ); - if (!match) { - return { - timestamp: Date.now(), - type: 'info', - message: line, - }; - } - - return { - timestamp: new Date(match[1]).getTime(), - type: match[2].toLowerCase(), - message: match[3], - }; - }; - - const getTypeColor = (type) => { - switch (type) { - case 'error': - return 'text-red-400'; - case 'warn': - return 'text-yellow-400'; - case 'debug': - return 'text-blue-400'; - case 'trace': - return 'text-purple-400'; - default: - return 'text-green-400'; - } - }; - - const formatTime = (timestamp) => - new Date(timestamp).toLocaleTimeString('en-US', { hour12: false }); - - const overlay = document.createElement('div'); - overlay.id = 'launch-sync-overlay'; - overlay.className = 'fixed inset-0 bg-[#0f1419] flex items-center justify-center z-50'; - overlay.innerHTML = ` -
-
-
- -
-

Syncing Market Data

-

Discovering available makers via Tor. This may take a minute...

-

Starting offerbook sync...

-
- -
-
-
- -
-
-
-

Live sync logs

-

Latest coinswap and backend activity during startup

-
- 0 lines -
-
-
-
- `; - document.body.appendChild(overlay); - - const logOutput = overlay.querySelector('#launch-sync-log-output'); - const logCount = overlay.querySelector('#launch-sync-log-count'); - const statusLabel = overlay.querySelector('#launch-sync-status'); - const progressBar = overlay.querySelector('#launch-sync-progress'); - const syncStartedAt = Date.now(); - let logPoll = null; - - function renderLogs(logs) { - if (!logOutput) return; - - if (logCount) { - logCount.textContent = `${logs.length} ${logs.length === 1 ? 'line' : 'lines'}`; - } - - if (logs.length === 0) { - logOutput.innerHTML = - '
Waiting for startup logs...
'; - return; - } - - logOutput.innerHTML = logs - .map((log) => { - return ` -
- [${formatTime(log.timestamp)}] - [${log.type.toUpperCase()}] - ${escapeHtml(log.message)} -
- `; - }) - .join(''); - logOutput.scrollTop = logOutput.scrollHeight; - } - - async function refreshLaunchLogs() { - try { - const data = await window.api.logs.get(120); - if (!data.success || !Array.isArray(data.logs)) return; - - const recentLogs = data.logs - .map(parseLogLine) - .filter((log) => log.timestamp >= syncStartedAt - 5000) - .slice(-50); - - renderLogs(recentLogs); - } catch (error) { - console.error('Failed to refresh launch sync logs:', error); - } - } - +async function startBackgroundOfferbookSync() { try { - await refreshLaunchLogs(); - logPoll = setInterval(refreshLaunchLogs, 1500); - const syncResult = await window.api.taker.syncOfferbookAndWait(); - if (syncResult.success) { - if (statusLabel) statusLabel.textContent = 'Offerbook sync in progress...'; - if (progressBar) progressBar.style.width = '52%'; - - const syncId = syncResult.syncId; - await new Promise((resolve) => { - const poll = setInterval(async () => { - try { - const status = await window.api.taker.getSyncStatus(syncId); - const sync = status.sync || {}; - const syncStatus = sync.status || 'syncing'; - const syncMessage = - sync.message || - (syncStatus === 'completed' - ? 'Offerbook ready' - : syncStatus === 'failed' - ? 'Sync failed' - : 'Syncing offerbook...'); - - if (statusLabel) statusLabel.textContent = syncMessage; - if (progressBar) { - const nextWidth = - typeof sync.progress === 'number' - ? Math.max(18, Math.min(100, sync.progress)) - : syncStatus === 'completed' - ? 100 - : syncStatus === 'failed' - ? 100 - : 76; - progressBar.style.width = `${nextWidth}%`; - } - - const done = - !status.success || - syncStatus === 'completed' || - syncStatus === 'failed'; - if (done) { - clearInterval(poll); - resolve(); - } - } catch (err) { - console.error('Sync polling error:', err); + if (!syncResult.success) { + console.warn('⚠️ Background offerbook sync failed to start:', syncResult.error); + return; + } + const syncId = syncResult.syncId; + await new Promise((resolve) => { + const poll = setInterval(async () => { + try { + const status = await window.api.taker.getSyncStatus(syncId); + const syncStatus = (status.sync || {}).status || 'syncing'; + if (!status.success || syncStatus === 'completed' || syncStatus === 'failed') { clearInterval(poll); resolve(); } - }, 1000); - }); - } else { - if (statusLabel) { - statusLabel.textContent = - syncResult.error || 'Unable to start offerbook sync'; - } - if (progressBar) progressBar.style.width = '100%'; - } + } catch (err) { + console.warn('⚠️ Sync poll error:', err.message); + clearInterval(poll); + resolve(); + } + }, 1000); + }); + console.log('✅ Background offerbook sync complete'); } catch (err) { - console.warn('⚠️ Launch offerbook sync error:', err.message); - if (statusLabel) statusLabel.textContent = 'Offerbook sync hit an issue'; - if (progressBar) progressBar.style.width = '100%'; - } finally { - if (logPoll) clearInterval(logPoll); - await refreshLaunchLogs(); + console.warn('⚠️ Background offerbook sync error:', err.message); } - - overlay.remove(); - onComplete(); } // Start the main app after bitcoind connection is established diff --git a/src/styles/output.css b/src/styles/output.css index ffaa9a2..65c3e2d 100644 --- a/src/styles/output.css +++ b/src/styles/output.css @@ -45,7 +45,6 @@ --spacing: 0.25rem; --container-md: 28rem; --container-2xl: 42rem; - --container-3xl: 48rem; --container-5xl: 64rem; --container-7xl: 80rem; --text-xs: 0.75rem; @@ -516,9 +515,6 @@ .max-w-2xl { max-width: var(--container-2xl); } - .max-w-3xl { - max-width: var(--container-3xl); - } .max-w-5xl { max-width: var(--container-5xl); } @@ -792,9 +788,6 @@ .border-\[\#FF6B35\] { border-color: #FF6B35; } - .border-\[\#FF6B35\]\/10 { - border-color: color-mix(in oklab, #FF6B35 10%, transparent); - } .border-\[\#FF6B35\]\/20 { border-color: color-mix(in oklab, #FF6B35 20%, transparent); } @@ -882,12 +875,6 @@ .border-transparent { border-color: transparent; } - .border-white\/5 { - border-color: color-mix(in srgb, #fff 5%, transparent); - @supports (color: color-mix(in lab, red, red)) { - border-color: color-mix(in oklab, var(--color-white) 5%, transparent); - } - } .border-yellow-500\/30 { border-color: color-mix(in srgb, oklch(79.5% 0.184 86.047) 30%, transparent); @supports (color: color-mix(in lab, red, red)) { @@ -1278,10 +1265,6 @@ --tw-font-weight: var(--font-weight-semibold); font-weight: var(--font-weight-semibold); } - .tracking-\[0\.2em\] { - --tw-tracking: 0.2em; - letter-spacing: 0.2em; - } .tracking-wide { --tw-tracking: var(--tracking-wide); letter-spacing: var(--tracking-wide); @@ -1628,16 +1611,6 @@ } } } - .hover\:bg-white\/5 { - &:hover { - @media (hover: hover) { - background-color: color-mix(in srgb, #fff 5%, transparent); - @supports (color: color-mix(in lab, red, red)) { - background-color: color-mix(in oklab, var(--color-white) 5%, transparent); - } - } - } - } .hover\:text-\[\#FF6B35\] { &:hover { @media (hover: hover) {