import React, { useState, useEffect, useCallback } from 'react'; import { View, Text, TouchableOpacity, StyleSheet, SafeAreaView, ScrollView, StatusBar, Modal, TextInput, Alert, ActivityIndicator, RefreshControl, Image, Platform, Clipboard, Share, } from 'react-native'; import { LinearGradient } from 'expo-linear-gradient'; import { useNavigation } from '@react-navigation/native'; import QRCode from 'react-native-qrcode-svg'; import AsyncStorage from '@react-native-async-storage/async-storage'; import * as SecureStore from 'expo-secure-store'; import { KurdistanColors } from '../theme/colors'; import { usePezkuwi, NetworkType, NETWORKS } from '../contexts/PezkuwiContext'; import { AddTokenModal } from '../components/wallet/AddTokenModal'; import { HezTokenLogo, PezTokenLogo } from '../components/icons'; import { decodeAddress, checkAddress, encodeAddress } from '@pezkuwi/util-crypto'; // Secure storage helper - same as in PezkuwiContext const secureStorage = { getItem: async (key: string): Promise => { if (Platform.OS === 'web') { return await AsyncStorage.getItem(key); } else { return await SecureStore.getItemAsync(key); } }, }; // Cross-platform alert helper const showAlert = (title: string, message: string, buttons?: Array<{text: string; onPress?: () => void; style?: string}>) => { if (Platform.OS === 'web') { if (buttons && buttons.length > 1) { const result = window.confirm(`${title}\n\n${message}`); if (result && buttons[1]?.onPress) { buttons[1].onPress(); } else if (!result && buttons[0]?.onPress) { buttons[0].onPress(); } } else { window.alert(`${title}\n\n${message}`); if (buttons?.[0]?.onPress) buttons[0].onPress(); } } else { showAlert(title, message, buttons as any); } }; // Token Images - From shared/images // Standardized token logos const hezLogo = require('../../../shared/images/hez_token_512.png'); const pezLogo = require('../../../shared/images/pez_token_512.png'); const usdtLogo = require('../../../shared/images/USDT(hez)logo.png'); const dotLogo = require('../../../shared/images/dot.png'); const btcLogo = require('../../../shared/images/bitcoin.png'); const ethLogo = require('../../../shared/images/etherium.png'); const bnbLogo = require('../../../shared/images/BNB_logo.png'); const adaLogo = require('../../../shared/images/ADAlogo.png'); interface Token { symbol: string; name: string; balance: string; value: string; change: string; logo: any; // Image source assetId?: number; isLive: boolean; } interface Transaction { hash: string; method: string; section: string; from: string; to?: string; amount?: string; blockNumber: number; timestamp?: number; isIncoming: boolean; } const WalletScreen: React.FC = () => { const navigation = useNavigation(); const { api, isApiReady, accounts, selectedAccount, setSelectedAccount, connectWallet, disconnectWallet, createWallet, deleteWallet, getKeyPair, currentNetwork, switchNetwork, error: pezkuwiError } = usePezkuwi(); const [selectedToken, setSelectedToken] = useState(null); const [sendModalVisible, setSendModalVisible] = useState(false); const [receiveModalVisible, setReceiveModalVisible] = useState(false); const [createWalletModalVisible, setCreateWalletModalVisible] = useState(false); const [importWalletModalVisible, setImportWalletModalVisible] = useState(false); const [backupModalVisible, setBackupModalVisible] = useState(false); const [networkSelectorVisible, setNetworkSelectorVisible] = useState(false); const [walletSelectorVisible, setWalletSelectorVisible] = useState(false); const [addTokenModalVisible, setAddTokenModalVisible] = useState(false); const [recipientAddress, setRecipientAddress] = useState(''); const [sendAmount, setSendAmount] = useState(''); const [walletName, setWalletName] = useState(''); const [importMnemonic, setImportMnemonic] = useState(''); const [importWalletName, setImportWalletName] = useState(''); const [userMnemonic, setUserMnemonic] = useState(''); const [isSending, setIsSending] = useState(false); const [isLoadingBalances, setIsLoadingBalances] = useState(false); // Transaction History State const [transactions, setTransactions] = useState([]); const [isLoadingHistory, setIsLoadingHistory] = useState(false); const [balances, setBalances] = useState<{ [key: string]: string }>({ HEZ: '0.00', PEZ: '0.00', USDT: '0.00', }); // Gas fee estimation state const [estimatedFee, setEstimatedFee] = useState(''); const [isEstimatingFee, setIsEstimatingFee] = useState(false); const [addressError, setAddressError] = useState(''); // Address Book state interface SavedAddress { address: string; name: string; lastUsed?: number; } const [savedAddresses, setSavedAddresses] = useState([]); const [addressBookVisible, setAddressBookVisible] = useState(false); const [saveAddressModalVisible, setSaveAddressModalVisible] = useState(false); const [newAddressName, setNewAddressName] = useState(''); const tokens: Token[] = [ { symbol: 'HEZ', name: 'Pezkuwi', balance: balances.HEZ, value: '$0.00', change: '+0.00%', logo: hezLogo, isLive: true }, { symbol: 'PEZ', name: 'Pezkuwi Token', balance: balances.PEZ, value: '$0.00', change: '+0.00%', logo: pezLogo, assetId: 1, isLive: true }, { symbol: 'USDT', name: 'Tether USD', balance: balances.USDT, value: '$0.00', change: '+0.00%', logo: usdtLogo, assetId: 1000, isLive: true }, ]; // Fetch balances and history const fetchData = useCallback(async () => { if (!api || !isApiReady || !selectedAccount) return; setIsLoadingBalances(true); try { // 1. Fetch Balances - decode address to raw bytes to avoid SS58 encoding issues let accountId: Uint8Array; try { accountId = decodeAddress(selectedAccount.address); } catch (e) { console.warn('[Wallet] Failed to decode address, using raw:', e); accountId = selectedAccount.address as any; } const accountInfo = await api.query.system.account(accountId); const hezBalance = (Number(accountInfo.data.free.toString()) / 1e12).toFixed(2); let pezBalance = '0.00'; try { if (api.query.assets?.account) { const pezAsset = await api.query.assets.account(1, accountId); if (pezAsset.isSome) pezBalance = (Number(pezAsset.unwrap().balance.toString()) / 1e12).toFixed(2); } } catch (e) { console.warn('[Wallet] PEZ balance fetch failed:', e); } let usdtBalance = '0.00'; try { if (api.query.assets?.account) { // Check ID 1000 first (as per constants), fallback to 2 just in case let usdtAsset = await api.query.assets.account(1000, accountId); if (usdtAsset.isNone) { usdtAsset = await api.query.assets.account(2, accountId); } if (usdtAsset.isSome) { // USDT uses 6 decimals usually, checking constants or assuming standard usdtBalance = (Number(usdtAsset.unwrap().balance.toString()) / 1e6).toFixed(2); } } } catch (e) { console.warn('[Wallet] USDT balance fetch failed:', e); } setBalances({ HEZ: hezBalance, PEZ: pezBalance, USDT: usdtBalance }); // 2. Fetch History - TODO: Connect to production indexer when available // For now, skip indexer and show empty history (chain query is too slow for mobile) setIsLoadingHistory(true); // Indexer disabled until production endpoint is available // When ready, use: https://indexer.pezkuwichain.io/api/history/${selectedAccount.address} setTransactions([]); } catch (error) { console.error('Fetch error:', error); } finally { setIsLoadingBalances(false); setIsLoadingHistory(false); } }, [api, isApiReady, selectedAccount]); // Real-time balance subscription useEffect(() => { if (!api || !isApiReady || !selectedAccount) return; let unsubscribe: (() => void) | null = null; const subscribeToBalance = async () => { try { let accountId: Uint8Array; try { accountId = decodeAddress(selectedAccount.address); } catch { return; } // Subscribe to balance changes unsubscribe = await api.query.system.account(accountId, (accountInfo: any) => { const hezBalance = (Number(accountInfo.data.free.toString()) / 1e12).toFixed(2); setBalances(prev => ({ ...prev, HEZ: hezBalance })); console.log('[Wallet] Balance updated via subscription:', hezBalance, 'HEZ'); }) as unknown as () => void; } catch (e) { console.warn('[Wallet] Subscription failed, falling back to polling:', e); // Fallback to polling if subscription fails fetchData(); } }; subscribeToBalance(); // Initial fetch for other tokens (PEZ, USDT) fetchData(); return () => { if (unsubscribe) { unsubscribe(); } }; }, [api, isApiReady, selectedAccount]); const handleTokenPress = (token: Token) => { if (!token.isLive) return; setSelectedToken(token); setSendModalVisible(true); }; const handleSend = () => { setSelectedToken(tokens[0]); // Default to HEZ setSendModalVisible(true); }; const handleReceive = () => { setSelectedToken(tokens[0]); setReceiveModalVisible(true); }; // Load saved addresses from storage useEffect(() => { const loadAddressBook = async () => { try { const stored = await AsyncStorage.getItem('@pezkuwi_address_book'); if (stored) { setSavedAddresses(JSON.parse(stored)); } } catch (e) { console.warn('[Wallet] Failed to load address book:', e); } }; loadAddressBook(); }, []); // Save address to address book const saveAddress = async (address: string, name: string) => { try { const newAddress: SavedAddress = { address, name, lastUsed: Date.now(), }; const updated = [...savedAddresses.filter(a => a.address !== address), newAddress]; setSavedAddresses(updated); await AsyncStorage.setItem('@pezkuwi_address_book', JSON.stringify(updated)); showAlert('Saved', `Address "${name}" saved to address book`); } catch (e) { console.warn('[Wallet] Failed to save address:', e); } }; // Delete address from address book const deleteAddress = async (address: string) => { try { const updated = savedAddresses.filter(a => a.address !== address); setSavedAddresses(updated); await AsyncStorage.setItem('@pezkuwi_address_book', JSON.stringify(updated)); } catch (e) { console.warn('[Wallet] Failed to delete address:', e); } }; // Select address from address book const selectSavedAddress = (address: string) => { setRecipientAddress(address); setAddressBookVisible(false); validateAddress(address); }; // Validate address format const validateAddress = (address: string): boolean => { if (!address || address.length < 10) { setAddressError('Address is too short'); return false; } try { // Try to decode the address - will throw if invalid decodeAddress(address); setAddressError(''); return true; } catch (e) { setAddressError('Invalid address format'); return false; } }; // Estimate gas fee before sending const estimateFee = async () => { if (!api || !isApiReady || !selectedAccount || !recipientAddress || !sendAmount || !selectedToken) { return; } if (!validateAddress(recipientAddress)) { return; } setIsEstimatingFee(true); try { const decimals = selectedToken.symbol === 'USDT' ? 1e6 : 1e12; const amountInUnits = BigInt(Math.floor(parseFloat(sendAmount) * decimals)); let tx; if (selectedToken.symbol === 'HEZ') { tx = api.tx.balances.transferKeepAlive(recipientAddress, amountInUnits); } else if (selectedToken.assetId !== undefined) { tx = api.tx.assets.transfer(selectedToken.assetId, recipientAddress, amountInUnits); } else { return; } // Get payment info for fee estimation const paymentInfo = await tx.paymentInfo(selectedAccount.address); const feeInHez = (Number(paymentInfo.partialFee.toString()) / 1e12).toFixed(6); setEstimatedFee(feeInHez); } catch (e) { console.warn('[Wallet] Fee estimation failed:', e); setEstimatedFee('~0.001'); // Fallback estimate } finally { setIsEstimatingFee(false); } }; // Auto-estimate fee when inputs change useEffect(() => { if (sendModalVisible && recipientAddress && sendAmount && parseFloat(sendAmount) > 0) { const timer = setTimeout(estimateFee, 500); // Debounce 500ms return () => clearTimeout(timer); } }, [recipientAddress, sendAmount, sendModalVisible, selectedToken]); const handleConfirmSend = async () => { if (!recipientAddress || !sendAmount || !selectedToken || !selectedAccount || !api) { showAlert('Error', 'Please enter recipient address and amount'); return; } // Validate address before sending if (!validateAddress(recipientAddress)) { showAlert('Error', 'Invalid recipient address'); return; } // Check if amount is valid const amount = parseFloat(sendAmount); if (isNaN(amount) || amount <= 0) { showAlert('Error', 'Please enter a valid amount'); return; } // Check if user has enough balance const currentBalance = parseFloat(balances[selectedToken.symbol] || '0'); const feeEstimate = parseFloat(estimatedFee || '0.001'); if (selectedToken.symbol === 'HEZ' && amount + feeEstimate > currentBalance) { showAlert('Error', `Insufficient balance. You need ${(amount + feeEstimate).toFixed(4)} HEZ (including fee)`); return; } else if (selectedToken.symbol !== 'HEZ' && amount > currentBalance) { showAlert('Error', `Insufficient ${selectedToken.symbol} balance`); return; } setIsSending(true); try { const keypair = await getKeyPair(selectedAccount.address); if (!keypair) throw new Error('Failed to load keypair'); // Adjust decimals based on token const decimals = selectedToken.symbol === 'USDT' ? 1e6 : 1e12; const amountInUnits = BigInt(Math.floor(amount * decimals)); let tx; if (selectedToken.symbol === 'HEZ') { // Use transferKeepAlive to prevent account from being reaped tx = api.tx.balances.transferKeepAlive(recipientAddress, amountInUnits); } else if (selectedToken.assetId !== undefined) { tx = api.tx.assets.transfer(selectedToken.assetId, recipientAddress, amountInUnits); } else { throw new Error('Unknown token type'); } await tx.signAndSend(keypair, ({ status, events }) => { if (status.isInBlock) { console.log('[Wallet] Transaction in block:', status.asInBlock.toHex()); } if (status.isFinalized) { setSendModalVisible(false); setIsSending(false); setRecipientAddress(''); setSendAmount(''); setEstimatedFee(''); showAlert('Success', `Transaction finalized!\nBlock: ${status.asFinalized.toHex().slice(0, 10)}...`); fetchData(); } }); } catch (e: any) { setIsSending(false); showAlert('Error', e.message); } }; // Connect/Create Wallet handlers const handleConnectWallet = async () => { if (accounts.length === 0) setCreateWalletModalVisible(true); else await connectWallet(); }; const handleCreateWallet = async () => { try { const { address, mnemonic } = await createWallet(walletName); setUserMnemonic(mnemonic); // Save for backup setCreateWalletModalVisible(false); showAlert('Wallet Created', `Save this mnemonic:\n${mnemonic}`, [{ text: 'OK', onPress: () => connectWallet() }]); } catch (e) { showAlert('Error', 'Failed'); } }; // Copy Address Handler const handleCopyAddress = () => { if (!selectedAccount) return; Clipboard.setString(selectedAccount.address); showAlert('Copied!', 'Address copied to clipboard'); }; // Import Wallet Handler const handleImportWallet = async () => { if (!importMnemonic.trim()) { showAlert('Error', 'Please enter a valid mnemonic'); return; } try { // Use createWallet but inject mnemonic (you may need to modify PezkuwiContext) // For now, basic implementation: const { Keyring } = await import('@pezkuwi/keyring'); const keyring = new Keyring({ type: 'sr25519' }); const pair = keyring.addFromMnemonic(importMnemonic.trim()); // Store in AsyncStorage (via context method ideally) showAlert('Success', `Wallet imported: ${pair.address.slice(0,8)}...`); setImportWalletModalVisible(false); setImportMnemonic(''); connectWallet(); } catch (e: any) { showAlert('Error', e.message || 'Invalid mnemonic'); } }; // Backup Mnemonic Handler const handleBackupMnemonic = async () => { if (!selectedAccount) { showAlert('No Wallet', 'Please create or import a wallet first.'); return; } try { // Retrieve mnemonic from secure storage const seedKey = `pezkuwi_seed_${selectedAccount.address}`; const storedMnemonic = await secureStorage.getItem(seedKey); if (storedMnemonic) { setUserMnemonic(storedMnemonic); setBackupModalVisible(true); } else { showAlert('No Backup', 'Mnemonic not found in secure storage. It may have been imported from another device.'); } } catch (error) { console.error('Error retrieving mnemonic:', error); showAlert('Error', 'Failed to retrieve mnemonic from secure storage.'); } }; // Share QR Code const handleShareQR = async () => { if (!selectedAccount) return; try { await Share.share({ message: `My Pezkuwichain Address:\n${selectedAccount.address}`, }); } catch (e) { console.error(e); } }; // Network Switch Handler const handleNetworkSwitch = async (network: NetworkType) => { try { await switchNetwork(network); setNetworkSelectorVisible(false); showAlert('Success', `Switched to ${NETWORKS[network].displayName}`); } catch (e: any) { showAlert('Error', e.message || 'Failed to switch network'); } }; // Redirect to WalletSetupScreen if no wallet exists useEffect(() => { if (!selectedAccount && accounts.length === 0) { navigation.replace('WalletSetup'); } }, [selectedAccount, accounts, navigation]); // Show loading while checking wallet state or redirecting if (!selectedAccount && accounts.length === 0) { return ( Loading wallet... ); } return ( {/* Top Header with Back Button */} navigation.goBack()} style={styles.backButton} testID="wallet-back-button"> ← Back Wallet setNetworkSelectorVisible(true)} testID="wallet-network-button"> 🌐 {NETWORKS[currentNetwork].displayName} } showsVerticalScrollIndicator={false} testID="wallet-scroll-view" > {/* Wallet Selector Row */} setWalletSelectorVisible(true)} testID="wallet-selector-button" > {selectedAccount?.name || 'Wallet'} {selectedAccount?.address ? `${selectedAccount.address.slice(0, 8)}...${selectedAccount.address.slice(-6)}` : ''} β–Ό navigation.navigate('WalletSetup')} testID="add-wallet-button" > + showAlert('Scan', 'QR Scanner coming soon')} testID="wallet-scan-button" > ⊑ {/* Main Token Cards - HEZ and PEZ side by side */} {/* HEZ Card */} handleTokenPress(tokens[0])}> HEZ {balances.HEZ} Welati Coin {/* PEZ Card */} handleTokenPress(tokens[1])}> PEZ {balances.PEZ} Pezkuwichain Token {/* Action Buttons Grid - 1x4 */} ↑ Send ↓ Receive navigation.navigate('Swap')}> πŸ”„ Swap showAlert('Staking', 'Navigate to Staking')}> πŸ₯© Staking {/* Tokens List */} Tokens πŸ” setAddTokenModalVisible(true)}> βž• βš™οΈ {/* USDT */} USDT PEZ Network {balances.USDT} $0.00 {/* DOT */} DOT Polkadot 0.00 $0.00 {/* Modals */} setSendModalVisible(false)}> Send {selectedToken?.symbol} {selectedToken && } {/* Recipient Address Input with Address Book */} { setRecipientAddress(text); if (text.length > 10) validateAddress(text); }} autoCapitalize="none" autoCorrect={false} /> setAddressBookVisible(true)} > πŸ“’ {addressError ? {addressError} : null} {/* Save Address Button (if valid new address) */} {recipientAddress && !addressError && !savedAddresses.find(a => a.address === recipientAddress) && ( setSaveAddressModalVisible(true)} > πŸ’Ύ Save this address )} {/* Amount Input */} {/* Gas Fee Preview */} {(estimatedFee || isEstimatingFee) && ( Estimated Fee: {isEstimatingFee ? ( ) : ( {estimatedFee} HEZ )} )} {/* Total (Amount + Fee) */} {estimatedFee && sendAmount && selectedToken?.symbol === 'HEZ' && ( Total (incl. fee): {(parseFloat(sendAmount || '0') + parseFloat(estimatedFee || '0')).toFixed(6)} HEZ )} { setSendModalVisible(false); setRecipientAddress(''); setSendAmount(''); setEstimatedFee(''); setAddressError(''); }}>Cancel {isSending ? 'Sending...' : 'Confirm'} setReceiveModalVisible(false)}> Receive Address {selectedAccount && } {selectedAccount?.address} πŸ“‹ Copy πŸ“€ Share setReceiveModalVisible(false)}> Close {/* Backup Mnemonic Modal */} setBackupModalVisible(false)}> πŸ” Backup Mnemonic ⚠️ NEVER share this with anyone! Write it down and store safely. {userMnemonic} { Clipboard.setString(userMnemonic); showAlert('Copied', 'Mnemonic copied to clipboard'); }}> πŸ“‹ Copy setBackupModalVisible(false)}> Close {/* Wallet Selector Modal */} setWalletSelectorVisible(false)}> πŸ‘› My Wallets Select a wallet or create a new one {/* Wallet List */} {accounts.map((account) => { const isSelected = account.address === selectedAccount?.address; return ( { setSelectedAccount(account); setWalletSelectorVisible(false); }} > πŸ‘› {account.name} {account.address.slice(0, 12)}...{account.address.slice(-8)} {isSelected && βœ“} { const confirmDelete = Platform.OS === 'web' ? window.confirm(`Delete "${account.name}"?\n\nThis action cannot be undone. Make sure you have backed up your recovery phrase.`) : await new Promise((resolve) => { Alert.alert( 'Delete Wallet', `Are you sure you want to delete "${account.name}"?\n\nThis action cannot be undone. Make sure you have backed up your recovery phrase.`, [ { text: 'Cancel', style: 'cancel', onPress: () => resolve(false) }, { text: 'Delete', style: 'destructive', onPress: () => resolve(true) } ] ); }); if (confirmDelete) { try { await deleteWallet(account.address); if (accounts.length <= 1) { setWalletSelectorVisible(false); } } catch (err) { if (Platform.OS === 'web') { window.alert('Failed to delete wallet'); } else { Alert.alert('Error', 'Failed to delete wallet'); } } } }} > πŸ—‘οΈ ); })} {/* Add New Wallet Button */} { setWalletSelectorVisible(false); navigation.navigate('WalletSetup'); }} > + Add New Wallet setWalletSelectorVisible(false)}> Close {/* Network Selector Modal */} setNetworkSelectorVisible(false)}> 🌐 Select Network Choose the network you want to connect to {(Object.keys(NETWORKS) as NetworkType[]).map((networkKey) => { const network = NETWORKS[networkKey]; const isSelected = networkKey === currentNetwork; return ( handleNetworkSwitch(networkKey)} > {network.displayName} {network.type === 'mainnet' ? '🟒 Mainnet' : network.type === 'testnet' ? '🟑 Testnet' : '🟠 Canary'} {isSelected && βœ“} ); })} setNetworkSelectorVisible(false)}> Close {/* Add Token Modal */} setAddTokenModalVisible(false)} onTokenAdded={fetchData} /> {/* Address Book Modal */} setAddressBookVisible(false)}> πŸ“’ Address Book {savedAddresses.length === 0 ? ( No saved addresses yet ) : ( {savedAddresses.map((saved) => ( selectSavedAddress(saved.address)} > {saved.name} {saved.address.slice(0, 12)}...{saved.address.slice(-8)} deleteAddress(saved.address)} > πŸ—‘οΈ ))} )} setAddressBookVisible(false)}> Close {/* Save Address Modal */} setSaveAddressModalVisible(false)}> πŸ’Ύ Save Address {recipientAddress.slice(0, 16)}...{recipientAddress.slice(-12)} { setSaveAddressModalVisible(false); setNewAddressName(''); }}> Cancel { if (newAddressName.trim()) { saveAddress(recipientAddress, newAddressName.trim()); setSaveAddressModalVisible(false); setNewAddressName(''); } }} > Save ); }; const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: '#F8F9FA' }, scrollContent: { flex: 1, }, loadingContainer: { flex: 1, justifyContent: 'center', alignItems: 'center', }, loadingText: { marginTop: 16, fontSize: 16, color: '#666', }, // Top Header with Back Button topHeader: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', paddingHorizontal: 16, paddingVertical: 12, backgroundColor: '#FFFFFF', borderBottomWidth: 1, borderBottomColor: '#E5E5E5', }, backButton: { paddingVertical: 4, paddingRight: 8, }, backButtonText: { fontSize: 16, color: KurdistanColors.kesk, fontWeight: '500', }, topHeaderTitle: { fontSize: 18, fontWeight: '600', color: '#333', }, // Header Styles (New Design) headerContainer: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', paddingHorizontal: 20, paddingTop: Platform.OS === 'android' ? 16 : 12, paddingBottom: 16, backgroundColor: '#FFFFFF', }, walletTitle: { fontSize: 22, fontWeight: 'bold', color: '#333', }, networkBadge: { fontSize: 14, color: KurdistanColors.kesk, backgroundColor: 'rgba(0, 143, 67, 0.1)', paddingHorizontal: 12, paddingVertical: 6, borderRadius: 16, overflow: 'hidden', }, scanButton: { width: 40, height: 40, borderRadius: 20, backgroundColor: '#F5F5F5', justifyContent: 'center', alignItems: 'center', }, scanIcon: { fontSize: 20, color: '#333', }, // Main Token Cards (HEZ & PEZ) - New Design mainTokensRow: { flexDirection: 'row', paddingHorizontal: 16, paddingVertical: 16, gap: 12, }, mainTokenCard: { flex: 1, backgroundColor: '#FFFFFF', borderRadius: 20, padding: 20, alignItems: 'center', boxShadow: '0px 2px 8px rgba(0, 0, 0, 0.08)', elevation: 4, }, mainTokenLogo: { width: 56, height: 56, marginBottom: 12, }, mainTokenLogoContainer: { width: 56, height: 56, marginBottom: 12, justifyContent: 'center', alignItems: 'center', }, mainTokenSymbol: { fontSize: 18, fontWeight: 'bold', color: '#333', marginBottom: 8, }, mainTokenBalance: { fontSize: 24, fontWeight: 'bold', color: KurdistanColors.kesk, marginBottom: 4, }, mainTokenSubtitle: { fontSize: 11, color: '#888', }, // Action Buttons Grid (2x4) - New Design actionsGrid: { flexDirection: 'row', flexWrap: 'wrap', paddingHorizontal: 16, paddingVertical: 8, gap: 12, }, actionButton: { width: '23%', aspectRatio: 1, borderRadius: 16, justifyContent: 'center', alignItems: 'center', boxShadow: '0px 2px 4px rgba(0, 0, 0, 0.1)', elevation: 3, }, actionIcon: { fontSize: 24, color: '#FFFFFF', marginBottom: 4, }, actionLabel: { fontSize: 11, fontWeight: '600', color: '#FFFFFF', }, // Tokens List Section - New Design tokensSection: { paddingHorizontal: 16, paddingTop: 20, }, tokensSectionHeader: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', marginBottom: 16, paddingHorizontal: 4, }, tokensTitle: { fontSize: 20, fontWeight: 'bold', color: '#333', }, tokenHeaderIcons: { flexDirection: 'row', gap: 12, }, tokenHeaderIcon: { width: 36, height: 36, borderRadius: 18, backgroundColor: '#F5F5F5', justifyContent: 'center', alignItems: 'center', }, tokenListItem: { flexDirection: 'row', alignItems: 'center', backgroundColor: '#FFFFFF', borderRadius: 16, padding: 16, marginBottom: 12, boxShadow: '0px 1px 4px rgba(0, 0, 0, 0.05)', elevation: 2, }, tokenListLogo: { width: 44, height: 44, marginRight: 12, }, tokenListInfo: { flex: 1, }, tokenListSymbol: { fontSize: 16, fontWeight: 'bold', color: '#333', marginBottom: 2, }, tokenListNetwork: { fontSize: 12, color: '#888', }, tokenListBalance: { alignItems: 'flex-end', }, tokenListAmount: { fontSize: 16, fontWeight: 'bold', color: '#333', marginBottom: 2, }, tokenListUsdValue: { fontSize: 12, color: '#888', }, // Modal Styles modalOverlay: { flex: 1, backgroundColor: 'rgba(0,0,0,0.5)', justifyContent: 'center', alignItems: 'center', padding: 20 }, modalCard: { backgroundColor: 'white', borderRadius: 20, padding: 24, width: '100%', alignItems: 'center' }, modalHeader: { fontSize: 20, fontWeight: 'bold', marginBottom: 20 }, inputField: { width: '100%', backgroundColor: '#F5F5F5', padding: 16, borderRadius: 12, marginBottom: 12 }, modalActions: { flexDirection: 'row', width: '100%', gap: 12, marginTop: 10 }, btnCancel: { flex: 1, padding: 16, borderRadius: 12, backgroundColor: '#EEE', alignItems: 'center' }, btnConfirm: { flex: 1, padding: 16, borderRadius: 12, backgroundColor: KurdistanColors.kesk, alignItems: 'center' }, addrFull: { textAlign: 'center', color: '#666', fontSize: 12, marginVertical: 10, fontFamily: 'monospace' }, inputError: { borderWidth: 1, borderColor: '#EF4444', backgroundColor: '#FEF2F2', }, errorText: { color: '#EF4444', fontSize: 12, marginTop: -8, marginBottom: 8, paddingHorizontal: 4, }, feePreview: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', backgroundColor: '#F0FDF4', padding: 12, borderRadius: 8, marginBottom: 8, }, feeLabel: { fontSize: 14, color: '#666', }, feeAmount: { fontSize: 14, fontWeight: '600', color: KurdistanColors.kesk, }, totalPreview: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', backgroundColor: '#FEF3C7', padding: 12, borderRadius: 8, marginBottom: 8, }, totalLabel: { fontSize: 14, color: '#92400E', }, totalAmount: { fontSize: 14, fontWeight: 'bold', color: '#92400E', }, btnDisabled: { backgroundColor: '#9CA3AF', opacity: 0.7, }, // Address Book styles addressInputRow: { flexDirection: 'row', alignItems: 'center', width: '100%', marginBottom: 12, }, inputFieldFlex: { flex: 1, backgroundColor: '#F5F5F5', padding: 16, borderRadius: 12, marginRight: 8, }, addressBookButton: { width: 48, height: 48, borderRadius: 12, backgroundColor: '#F5F5F5', justifyContent: 'center', alignItems: 'center', }, addressBookIcon: { fontSize: 24, }, saveAddressLink: { alignSelf: 'flex-start', marginTop: -8, marginBottom: 8, }, saveAddressLinkText: { fontSize: 13, color: KurdistanColors.kesk, }, emptyAddressBook: { color: '#999', textAlign: 'center', paddingVertical: 32, }, addressList: { width: '100%', maxHeight: 300, marginBottom: 16, }, savedAddressRow: { flexDirection: 'row', alignItems: 'center', backgroundColor: '#F8F9FA', padding: 12, borderRadius: 12, marginBottom: 8, }, savedAddressInfo: { flex: 1, }, savedAddressName: { fontSize: 16, fontWeight: '600', color: '#333', marginBottom: 2, }, savedAddressAddr: { fontSize: 12, color: '#999', fontFamily: 'monospace', }, deleteAddressButton: { width: 36, height: 36, borderRadius: 8, backgroundColor: 'rgba(239, 68, 68, 0.1)', justifyContent: 'center', alignItems: 'center', }, // Network Selector Styles networkOption: { flexDirection: 'row', width: '100%', padding: 16, borderRadius: 12, backgroundColor: '#F5F5F5', marginBottom: 8, alignItems: 'center' }, networkOptionSelected: { backgroundColor: 'rgba(0, 143, 67, 0.1)', borderWidth: 2, borderColor: KurdistanColors.kesk }, networkName: { fontSize: 16, fontWeight: '600', color: '#333' }, networkType: { fontSize: 12, color: '#666', marginTop: 4 }, // Welcome Screen Styles welcomeGradient: { flex: 0.45, justifyContent: 'center', alignItems: 'center', borderBottomLeftRadius: 32, borderBottomRightRadius: 32, }, welcomeContent: { alignItems: 'center', paddingHorizontal: 20, }, welcomeEmoji: { fontSize: 64, marginBottom: 16, }, welcomeTitle: { fontSize: 18, color: 'rgba(255,255,255,0.8)', marginBottom: 8, }, welcomeBrand: { fontSize: 32, fontWeight: 'bold', color: 'white', marginBottom: 8, textAlign: 'center', }, welcomeSubtitle: { fontSize: 16, color: 'rgba(255,255,255,0.7)', textAlign: 'center', }, // Button Container (Welcome Screen) buttonContainer: { flex: 0.55, paddingHorizontal: 24, paddingTop: 32, justifyContent: 'flex-start', }, // Primary Button (Welcome Screen) primaryWalletButton: { marginBottom: 16, borderRadius: 16, overflow: 'hidden', boxShadow: '0px 4px 8px rgba(0, 128, 0, 0.3)', elevation: 8, }, buttonGradient: { flexDirection: 'row', alignItems: 'center', padding: 20, borderRadius: 16, }, buttonIcon: { width: 52, height: 52, borderRadius: 26, backgroundColor: 'rgba(255,255,255,0.2)', justifyContent: 'center', alignItems: 'center', marginRight: 16, }, buttonIconText: { fontSize: 24, color: 'white', }, buttonTextContainer: { flex: 1, }, primaryButtonText: { fontSize: 18, fontWeight: 'bold', color: 'white', marginBottom: 4, }, primaryButtonSubtext: { fontSize: 14, color: 'rgba(255,255,255,0.8)', }, // Secondary Button (Welcome Screen) secondaryWalletButton: { backgroundColor: 'white', borderRadius: 16, marginBottom: 24, boxShadow: '0px 2px 8px rgba(0, 0, 0, 0.1)', elevation: 4, }, secondaryButtonContent: { flexDirection: 'row', alignItems: 'center', padding: 20, }, secondaryButtonText: { fontSize: 18, fontWeight: '600', color: '#333', marginBottom: 4, }, secondaryButtonSubtext: { fontSize: 14, color: '#666', }, // Security Notice (Welcome Screen) securityNotice: { flexDirection: 'row', alignItems: 'center', backgroundColor: 'rgba(0,105,62,0.05)', padding: 16, borderRadius: 12, marginTop: 'auto', marginBottom: 20, }, securityIcon: { fontSize: 20, marginRight: 12, }, securityText: { flex: 1, fontSize: 12, color: '#666', lineHeight: 18, }, // Wallet Selector Row walletSelectorRow: { flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between', paddingHorizontal: 16, paddingVertical: 12, marginBottom: 8, }, walletSelector: { flex: 1, flexDirection: 'row', alignItems: 'center', backgroundColor: '#FFFFFF', borderRadius: 12, padding: 12, marginRight: 12, boxShadow: '0px 2px 4px rgba(0, 0, 0, 0.05)', elevation: 2, }, walletSelectorInfo: { flex: 1, }, walletSelectorName: { fontSize: 16, fontWeight: '600', color: KurdistanColors.reş, }, walletSelectorAddress: { fontSize: 12, color: '#999', marginTop: 2, }, walletSelectorArrow: { fontSize: 12, color: '#666', marginLeft: 8, }, walletHeaderButtons: { flexDirection: 'row', gap: 8, }, addWalletButton: { width: 44, height: 44, borderRadius: 12, backgroundColor: '#FFFFFF', justifyContent: 'center', alignItems: 'center', boxShadow: '0px 2px 4px rgba(0, 0, 0, 0.05)', elevation: 2, }, addWalletIcon: { fontSize: 24, color: KurdistanColors.kesk, fontWeight: '300', }, // Wallet Selector Modal walletOption: { flexDirection: 'row', alignItems: 'center', padding: 16, backgroundColor: '#F8F9FA', borderRadius: 12, marginBottom: 8, borderWidth: 2, borderColor: 'transparent', }, walletOptionSelected: { borderColor: KurdistanColors.kesk, backgroundColor: 'rgba(0, 143, 67, 0.05)', }, walletOptionIcon: { width: 48, height: 48, borderRadius: 24, backgroundColor: '#FFFFFF', justifyContent: 'center', alignItems: 'center', marginRight: 12, }, walletOptionName: { fontSize: 16, fontWeight: '600', color: KurdistanColors.reş, }, walletOptionAddress: { fontSize: 12, color: '#999', marginTop: 2, }, addNewWalletOption: { flexDirection: 'row', alignItems: 'center', padding: 16, backgroundColor: 'rgba(0, 143, 67, 0.05)', borderRadius: 12, marginBottom: 16, borderWidth: 2, borderColor: KurdistanColors.kesk, borderStyle: 'dashed', }, addNewWalletIcon: { width: 48, height: 48, borderRadius: 24, backgroundColor: '#FFFFFF', justifyContent: 'center', alignItems: 'center', marginRight: 12, }, addNewWalletText: { fontSize: 16, fontWeight: '600', color: KurdistanColors.kesk, }, // Delete wallet walletOptionRow: { flexDirection: 'row', alignItems: 'center', marginBottom: 8, gap: 8, }, deleteWalletButton: { width: 44, height: 44, borderRadius: 12, backgroundColor: 'rgba(239, 68, 68, 0.1)', justifyContent: 'center', alignItems: 'center', }, deleteWalletIcon: { fontSize: 18, }, }); export default WalletScreen;