const fallbackDashboard = { active_account: { name: 'Main Wallet', address: '0x1111111111111111111111111111111111111111', source: 'SeedPhrase' }, chains: [ { id: 1, name: 'Ethereum' }, { id: 8453, name: 'Base' } ], balances: [ { chain_id: 1, symbol: 'ETH', amount: 1.24, usd_value: 4200 }, { chain_id: 8453, symbol: 'USDC', amount: 1280, usd_value: 1280 } ], approvals: [ { chain_id: 1, asset_symbol: 'USDC', spender: '0x2222222222222222222222222222222222222222', allowance: 'unlimited', risk: 'High' } ], activities: [ { label: 'Swap ETH → USDC', status: 'Confirmed', chain_id: 1 } ], settings: { theme: 'System', language: 'en', currency: 'USD', auto_lock_minutes: 15, prefer_rabby_over_metamask: true } }; const fallbackFeatures = [ ['Create/unlock wallet', 'Password, lock/unlock, encrypted local state', 'RuntimeImplemented'], ['Import/create accounts', 'Seed phrase, private key, JSON, watch-only', 'Modeled'], ['Multi-chain networks', 'Built-in, custom RPC, testnet, offline chain flags', 'Modeled'], ['Portfolio dashboard', 'Balances, NFTs, DeFi positions, activity', 'UiPrototype'], ['Dapp provider and permissions', 'Origin/account/chain permissions', 'Modeled'], ['Signing and security previews', 'Typed data/message/transaction previews and risk', 'Modeled'], ['Settings and customization', 'Theme, language, currency, auto-lock, default wallet mode', 'UiPrototype'] ]; function money(value) { return new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD' }).format(value || 0); } function shortAddress(address) { if (!address || address.length < 12) return address || ''; return `${address.slice(0, 6)}…${address.slice(-4)}`; } function statusLabel(value) { if (typeof value === 'string') return value; if (value && typeof value === 'object') return Object.keys(value)[0] || 'Modeled'; return 'Modeled'; } async function invokeOrFallback(command, fallback) { try { const tauri = window.__TAURI__?.core; if (!tauri) return fallback; return await tauri.invoke(command); } catch (_) { return fallback; } } function renderDashboard(dashboard) { const total = dashboard.balances.reduce((sum, token) => sum + token.usd_value, 0); const highRisk = dashboard.approvals.filter((approval) => ['High', 'Critical'].includes(statusLabel(approval.risk))).length; document.getElementById('account-address').textContent = shortAddress(dashboard.active_account.address); document.getElementById('portfolio-total').textContent = money(total); document.getElementById('hero-total').textContent = money(total); document.getElementById('chain-count').textContent = dashboard.chains.length; document.getElementById('risk-count').textContent = highRisk; document.getElementById('approval-risk').textContent = highRisk; document.getElementById('token-list').innerHTML = dashboard.balances.map((token) => `
${token.symbol.slice(0, 1)}
${token.symbol}Chain ${token.chain_id}
${money(token.usd_value)}${token.amount}
`).join(''); document.getElementById('approval-list').innerHTML = dashboard.approvals.map((approval) => `
${approval.asset_symbol} allowance${shortAddress(approval.spender)}
${statusLabel(approval.risk)}
`).join(''); document.getElementById('activity-list').innerHTML = dashboard.activities.map((activity) => `
${activity.label}${statusLabel(activity.status)} · Chain ${activity.chain_id}
`).join(''); const settings = dashboard.settings; document.getElementById('settings-summary').innerHTML = [ ['Theme', statusLabel(settings.theme)], ['Language', settings.language], ['Currency', settings.currency], ['Auto-lock', `${settings.auto_lock_minutes} min`], ['Default wallet', settings.prefer_rabby_over_metamask ? 'Rabby' : 'Browser default'] ].map(([label, value]) => `
${label}${value}
`).join(''); } function renderFeatures(features) { document.getElementById('wallet-features').innerHTML = features.map((feature) => { const title = Array.isArray(feature) ? feature[0] : feature.feature; const acceptance = Array.isArray(feature) ? feature[1] : feature.acceptance; const status = Array.isArray(feature) ? feature[2] : statusLabel(feature.status); return `
${status} ${title}

${acceptance}

`; }).join(''); } async function saveDemoVault() { const passphrase = document.getElementById('vault-passphrase').value; const output = document.getElementById('vault-status'); output.textContent = 'Encrypting demo vault…'; try { const tauri = window.__TAURI__?.core; if (!tauri) throw new Error('Tauri bridge unavailable in browser preview'); const status = await tauri.invoke('save_demo_wallet_vault', { passphrase, path: null }); output.textContent = `Encrypted with ${status.cipher} + ${status.kdf}: ${status.path}`; } catch (error) { output.textContent = String(error); } } function wireVaultActions() { const button = document.getElementById('save-vault'); if (button) button.addEventListener('click', saveDemoVault); } async function loadAppConfig() { return invokeOrFallback('load_app_config', { theme_id: 'rabby-light', restore_workspace: true, profiles: [], shortcuts: [] }); } async function saveSettings() { const theme = document.getElementById('theme-select').value; const output = document.getElementById('settings-status'); output.textContent = 'Saving settings…'; try { const tauri = window.__TAURI__?.core; if (!tauri) throw new Error('Tauri bridge unavailable in browser preview'); const config = await loadAppConfig(); config.theme_id = theme; const saved = await tauri.invoke('save_app_config', { config, path: null }); output.textContent = `Saved ${saved.theme_id}`; } catch (error) { output.textContent = String(error); } } function wireSettingsActions() { const button = document.getElementById('save-settings'); if (button) button.addEventListener('click', saveSettings); } async function runLocalTerminalCommand() { const command = document.getElementById('terminal-command').value; const output = document.getElementById('terminal-output'); output.textContent = 'Running…'; try { const tauri = window.__TAURI__?.core; if (!tauri) throw new Error('Tauri bridge unavailable in browser preview'); const result = await tauri.invoke('run_local_command', { command, cwd: null }); output.textContent = [ `$ ${command}`, `exit ${result.exit_code}`, result.stdout ? `stdout:\n${result.stdout}` : '', result.stderr ? `stderr:\n${result.stderr}` : '' ].filter(Boolean).join('\n'); } catch (error) { output.textContent = String(error); } } function wireTerminalActions() { const button = document.getElementById('run-terminal'); if (button) button.addEventListener('click', runLocalTerminalCommand); } async function boot() { const [dashboard, features] = await Promise.all([ invokeOrFallback('wallet_dashboard', fallbackDashboard), invokeOrFallback('wallet_mvp_summary', fallbackFeatures) ]); renderDashboard(dashboard); renderFeatures(features); wireVaultActions(); wireSettingsActions(); wireTerminalActions(); } boot();