-
Notifications
You must be signed in to change notification settings - Fork 7
remove sync on startup #84
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -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); | ||
| } | ||
|
Comment on lines
+515
to
+520
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Validate sync failure responses and avoid overlapping startup syncs.
🐛 Proposed fix console.log('🔄 Syncing and fetching fresh data...');
try {
- await window.api.taker.sync();
+ const syncState = await window.api.taker.getCurrentSyncState?.();
+ if (!syncState?.isRunning) {
+ await syncWalletState();
+ } else {
+ console.log('⏳ Sync already running, skipping initial wallet sync');
+ }
} catch (syncErr) {
- console.warn('⚠️ Initial wallet sync failed, proceeding anyway:', syncErr.message);
+ console.error('⚠️ Initial wallet sync failed, proceeding anyway:', syncErr);
}As per coding guidelines, errors should be logged with context using 🤖 Prompt for AI Agents |
||
| 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), | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -184,7 +184,8 @@ async function checkTakerInitialization(config) { | |||||||||
|
|
||||||||||
| if (result.success) { | ||||||||||
| console.log('✅ Taker initialized'); | ||||||||||
| await performLaunchSync(startMainApp); | ||||||||||
| startMainApp(); | ||||||||||
| startBackgroundOfferbookSync(); | ||||||||||
|
Comment on lines
+187
to
+188
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: # First, let's explore the repository structure
git ls-files | grep -E '\.(js|ts|tsx)$' | head -20Repository: citadel-tech/taker-app Length of output: 603 🏁 Script executed: # Check the file size before reading
wc -l src/js/app.jsRepository: citadel-tech/taker-app Length of output: 83 🏁 Script executed: # Read the specific lines mentioned in the review (187-188 and 287-288) with context
sed -n '180,195p' src/js/app.js
echo "---"
sed -n '280,295p' src/js/app.jsRepository: citadel-tech/taker-app Length of output: 1129 🏁 Script executed: # Find the startMainApp function definition
rg -n "^(async\s+)?function\s+startMainApp|const\s+startMainApp\s*=" src/js/app.jsRepository: citadel-tech/taker-app Length of output: 101 🏁 Script executed: # Search for startMainApp calls to understand the context better
rg -n "startMainApp\(" src/js/app.jsRepository: citadel-tech/taker-app Length of output: 207 🏁 Script executed: # Check the startBackgroundOfferbookSync function
rg -n "startBackgroundOfferbookSync" src/js/app.js | head -10Repository: citadel-tech/taker-app Length of output: 207 🏁 Script executed: # Read the startMainApp function definition and implementation
sed -n '353,380p' src/js/app.jsRepository: citadel-tech/taker-app Length of output: 1205 🏁 Script executed: # Read the startBackgroundOfferbookSync function
sed -n '322,350p' src/js/app.jsRepository: citadel-tech/taker-app Length of output: 1083 🏁 Script executed: # Check all context around all startMainApp calls to see if any are awaited
sed -n '150,160p' src/js/app.js
echo "---"
sed -n '204,214p' src/js/app.jsRepository: citadel-tech/taker-app Length of output: 589 🏁 Script executed: # Check if there's error handling for unhandled rejections
rg -n "unhandledrejection|catch|\.then" src/js/app.js | head -20Repository: citadel-tech/taker-app Length of output: 342 Await
Proposed fix- startMainApp();
- startBackgroundOfferbookSync();
+ await startMainApp();
+ startBackgroundOfferbookSync();- startMainApp();
- startBackgroundOfferbookSync();
+ await startMainApp();
+ startBackgroundOfferbookSync();Per the 📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||
| } 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 = ` | ||||||||||
| <div class="bg-[#1a2332] rounded-lg max-w-3xl w-full mx-4 p-8 border border-[#FF6B35]/10 shadow-2xl"> | ||||||||||
| <div class="text-center mb-6"> | ||||||||||
| <div class="w-16 h-16 bg-[#FF6B35]/20 rounded-full flex items-center justify-center mx-auto mb-4"> | ||||||||||
| <span class="text-3xl animate-spin inline-block">⏳</span> | ||||||||||
| </div> | ||||||||||
| <h2 class="text-xl font-bold text-white mb-2">Syncing Market Data</h2> | ||||||||||
| <p class="text-gray-400 text-sm mb-4">Discovering available makers via Tor. This may take a minute...</p> | ||||||||||
| <p id="launch-sync-status" class="text-xs uppercase tracking-[0.2em] text-[#FF6B35]">Starting offerbook sync...</p> | ||||||||||
| </div> | ||||||||||
|
|
||||||||||
| <div class="bg-gray-700 rounded-full h-2 overflow-hidden"> | ||||||||||
| <div id="launch-sync-progress" class="bg-[#FF6B35] h-2 rounded-full transition-all duration-500" style="width: 18%"></div> | ||||||||||
| </div> | ||||||||||
|
|
||||||||||
| <div class="mt-6 bg-[#0f1419] rounded-xl border border-white/5 overflow-hidden"> | ||||||||||
| <div class="flex items-center justify-between px-4 py-3 border-b border-white/5"> | ||||||||||
| <div> | ||||||||||
| <p class="text-sm font-semibold text-white">Live sync logs</p> | ||||||||||
| <p class="text-xs text-gray-500">Latest coinswap and backend activity during startup</p> | ||||||||||
| </div> | ||||||||||
| <span id="launch-sync-log-count" class="text-xs text-gray-500">0 lines</span> | ||||||||||
| </div> | ||||||||||
| <div id="launch-sync-log-output" class="h-64 overflow-y-auto px-4 py-3 font-mono text-xs text-left"></div> | ||||||||||
| </div> | ||||||||||
| </div> | ||||||||||
| `; | ||||||||||
| 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 = | ||||||||||
| '<div class="text-gray-500 text-center py-12">Waiting for startup logs...</div>'; | ||||||||||
| return; | ||||||||||
| } | ||||||||||
|
|
||||||||||
| logOutput.innerHTML = logs | ||||||||||
| .map((log) => { | ||||||||||
| return ` | ||||||||||
| <div class="mb-1 rounded px-2 py-1 hover:bg-white/5"> | ||||||||||
| <span class="text-gray-500">[${formatTime(log.timestamp)}]</span> | ||||||||||
| <span class="${getTypeColor(log.type)}">[${log.type.toUpperCase()}]</span> | ||||||||||
| <span class="text-gray-300">${escapeHtml(log.message)}</span> | ||||||||||
| </div> | ||||||||||
| `; | ||||||||||
| }) | ||||||||||
| .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'); | ||||||||||
|
Comment on lines
+330
to
+346
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do not log failed offerbook syncs as complete. The polling loop resolves on 🐛 Proposed fix- await new Promise((resolve) => {
+ const finalSyncStatus = 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') {
+ if (!status.success) {
clearInterval(poll);
- resolve();
+ resolve('missing');
+ return;
+ }
+ if (syncStatus === 'completed' || syncStatus === 'failed') {
+ clearInterval(poll);
+ resolve(syncStatus);
}
} catch (err) {
- console.warn('⚠️ Sync poll error:', err.message);
+ console.error('⚠️ Background offerbook sync poll error:', err);
clearInterval(poll);
- resolve();
+ resolve('error');
}
}, 1000);
});
+ if (finalSyncStatus !== 'completed') {
+ console.error('⚠️ Background offerbook sync did not complete:', finalSyncStatus);
+ return;
+ }
console.log('✅ Background offerbook sync complete');As per coding guidelines, errors should be logged with context using 🤖 Prompt for AI Agents |
||||||||||
| } 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 | ||||||||||
|
|
||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Avoid marking partial wallet data as a fresh cache entry.
Saving when only
balanceexists can cache missing or fallbacktransactions/utxosas fresh for 15 minutes, hiding a failed transaction/UTXO refresh behind the cache.🐛 Proposed fix
Also applies to: 526-526
🤖 Prompt for AI Agents