import { useState, useCallback, useEffect } from 'react';
import './App.css';
import Sidebar from './components/Sidebar';
import BalanceHeader from './components/BalanceHeader';
import SendModal from './components/SendModal';
import ReceiveModal from './components/ReceiveModal';
import OverviewTab from './components/OverviewTab';
import UTXOTab from './components/UTXOTab';
import AddressesTab from './components/AddressesTab';
import HistoryTab from './components/HistoryTab';
import NetworkTab from './components/NetworkTab';
import WalletCreation from './components/WalletCreation';
import MultisigCreation from './MultisigCreation';
import { useWallet } from './hooks/useWallet';
type TabKey = 'overview' | 'utxos' | 'addresses' | 'history' | 'network';
function App() {
const [activeTab, setActiveTab] = useState<TabKey>('overview');
const [showMultisig, setShowMultisig] = useState(false);
const wallet = useWallet();
const [showSend, setShowSend] = useState(false);
const [showReceive, setShowReceive] = useState(false);
const [currency, setCurrency] = useState<string>('USD');
const [fiatRate, setFiatRate] = useState<number>(0);
// Fetch fiat rate on mount and periodically
const fetchFiatRate = useCallback(async () => {
try {
const resp = await fetch('https://api.coingecko.com/api/v3/simple/price?ids=bitcoin&vs_currencies=usd');
const data = await resp.json();
if (data.bitcoin?.usd) {
setFiatRate(data.bitcoin.usd);
}
} catch { /* ignore */ }
}, []);
// Fetch rate on mount
useEffect(() => {
fetchFiatRate();
}, [fetchFiatRate]);
const handleWalletComplete = useCallback((_walletData: any, _addresses: any[], _seed: string) => {
wallet.switchWallet(_walletData, _addresses);
}, [wallet]);
// Handle wallet selection from sidebar
const handleSelectWallet = useCallback((path: string) => {
wallet.loadWalletFromDisk(path);
}, [wallet]);
const handleDeriveMore = useCallback(async (n: number) => {
const newAddrs = await wallet.deriveMore(n);
return newAddrs;
}, [wallet]);
const handleSetLabel = useCallback((kind: string, identifier: string, label: string) => {
wallet.setLabel(kind, identifier, label);
}, [wallet]);
const handleRefreshTx = useCallback(async (txid: string) => {
const status = await wallet.refreshTxStatus(txid);
return status;
}, [wallet]);
// If showing multisig creation page
if (showMultisig) {
return (
<MultisigCreation
onBack={() => setShowMultisig(false)}
/>
);
}
// If no wallet loaded, show creation
if (!wallet.currentWallet) {
return (
<WalletCreation onComplete={handleWalletComplete} />
);
}
const balanceSats = wallet.balance?.balance_sats ?? 0;
const balanceBtc = balanceSats / 100_000_000;
const fiatBalance = balanceBtc * fiatRate;
return (
<div className="app-layout">
{/* Sidebar */}
<Sidebar
wallets={wallet.savedWallets}
currentWalletName={wallet.currentWallet?.name}
onSelectWallet={handleSelectWallet}
activeTab={activeTab}
onTabChange={setActiveTab}
onNewWallet={() => setShowMultisig(true)}
/>
{/* Main content area */}
<div className="main-content">
{/* Sticky header */}
<BalanceHeader
walletName={wallet.currentWallet?.name}
balanceBtc={balanceBtc}
fiatRate={fiatRate}
fiatBalance={fiatBalance}
currency={currency}
onCurrencyChange={setCurrency}
onSend={() => setShowSend(true)}
onReceive={() => setShowReceive(true)}
onRefresh={() => wallet.refreshAll()}
loading={wallet.loading}
/>
{/* Tab content */}
<div className="tab-container">
{activeTab === 'overview' && (
<OverviewTab
wallet={wallet.currentWallet}
balance={wallet.balance}
recentTxs={wallet.txHistory.slice(0, 10)}
networkInfo={wallet.networkInfo}
blockCount={wallet.blockCount}
feeEstimate={wallet.feeEstimate}
onSend={() => setShowSend(true)}
onReceive={() => setShowReceive(true)}
/>
)}
{activeTab === 'utxos' && (
<UTXOTab
utxos={wallet.utxos}
utxoTree={wallet.utxoTree}
onFetchTree={() => wallet.fetchUtxoTree()}
/>
)}
{activeTab === 'addresses' && (
<AddressesTab
addresses={wallet.addresses}
addrLabels={wallet.addrLabels}
onSetLabel={handleSetLabel}
onDeriveMore={handleDeriveMore}
loading={wallet.loading}
/>
)}
{activeTab === 'history' && (
<HistoryTab
txHistory={wallet.txHistory}
refreshTxStatus={handleRefreshTx}
/>
)}
{activeTab === 'network' && (
<NetworkTab
networkInfo={wallet.networkInfo}
blockCount={wallet.blockCount}
feeEstimate={wallet.feeEstimate}
/>
)}
</div>
</div>
{/* Modals */}
{showSend && (
<SendModal
wallet={wallet.currentWallet!}
addresses={wallet.addresses}
utxos={wallet.utxos}
password={wallet.walletPassword}
feeEstimate={wallet.feeEstimate}
onClose={() => setShowSend(false)}
onBroadcast={() => {
wallet.refreshAll();
setShowSend(false);
}}
/>
)}
{showReceive && (
<ReceiveModal
wallet={wallet.currentWallet!}
addresses={wallet.addresses}
addrLabels={wallet.addrLabels}
onClose={() => setShowReceive(false)}
/>
)}
</div>
);
}
export default App;