diff --git a/mobile/App.tsx b/mobile/App.tsx
index 69f5dff3..06ae87ee 100644
--- a/mobile/App.tsx
+++ b/mobile/App.tsx
@@ -2,8 +2,10 @@ import React, { useEffect, useState } from 'react';
import { View, ActivityIndicator, StyleSheet } from 'react-native';
import { StatusBar } from 'expo-status-bar';
import { initializeI18n } from './src/i18n';
+import { ErrorBoundary } from './src/components/ErrorBoundary';
import { LanguageProvider } from './src/contexts/LanguageContext';
import { PolkadotProvider } from './src/contexts/PolkadotContext';
+import { BiometricAuthProvider } from './src/contexts/BiometricAuthContext';
import AppNavigator from './src/navigation/AppNavigator';
import { KurdistanColors } from './src/theme/colors';
@@ -35,12 +37,16 @@ export default function App() {
}
return (
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
);
}
diff --git a/mobile/src/components/ErrorBoundary.tsx b/mobile/src/components/ErrorBoundary.tsx
new file mode 100644
index 00000000..5ac6494d
--- /dev/null
+++ b/mobile/src/components/ErrorBoundary.tsx
@@ -0,0 +1,250 @@
+// ========================================
+// Error Boundary Component (React Native)
+// ========================================
+// Catches React errors and displays fallback UI
+
+import React, { Component, ErrorInfo, ReactNode } from 'react';
+import { View, Text, TouchableOpacity, ScrollView, StyleSheet } from 'react-native';
+
+interface Props {
+ children: ReactNode;
+ fallback?: ReactNode;
+ onError?: (error: Error, errorInfo: ErrorInfo) => void;
+}
+
+interface State {
+ hasError: boolean;
+ error: Error | null;
+ errorInfo: ErrorInfo | null;
+}
+
+/**
+ * Global Error Boundary for React Native
+ * Catches unhandled errors in React component tree
+ *
+ * @example
+ *
+ *
+ *
+ */
+export class ErrorBoundary extends Component {
+ constructor(props: Props) {
+ super(props);
+ this.state = {
+ hasError: false,
+ error: null,
+ errorInfo: null,
+ };
+ }
+
+ static getDerivedStateFromError(error: Error): Partial {
+ // Update state so next render shows fallback UI
+ return {
+ hasError: true,
+ error,
+ };
+ }
+
+ componentDidCatch(error: Error, errorInfo: ErrorInfo): void {
+ // Log error to console
+ if (__DEV__) {
+ console.error('ErrorBoundary caught an error:', error, errorInfo);
+ }
+
+ // Update state with error details
+ this.setState({
+ error,
+ errorInfo,
+ });
+
+ // Call custom error handler if provided
+ if (this.props.onError) {
+ this.props.onError(error, errorInfo);
+ }
+
+ // In production, you might want to log to an error reporting service
+ // Example: Sentry.captureException(error);
+ }
+
+ handleReset = (): void => {
+ this.setState({
+ hasError: false,
+ error: null,
+ errorInfo: null,
+ });
+ };
+
+ render(): ReactNode {
+ if (this.state.hasError) {
+ // Use custom fallback if provided
+ if (this.props.fallback) {
+ return this.props.fallback;
+ }
+
+ // Default error UI for React Native
+ return (
+
+
+
+ {/* Error Icon */}
+
+ ⚠️
+
+
+ {/* Error Title */}
+ Something Went Wrong
+
+ An unexpected error occurred. We apologize for the inconvenience.
+
+
+ {/* Error Details (Development Only) */}
+ {__DEV__ && this.state.error && (
+
+
+ Error Details (for developers)
+
+
+ Error:
+
+ {this.state.error.toString()}
+
+ {this.state.errorInfo && (
+ <>
+
+ Component Stack:
+
+
+ {this.state.errorInfo.componentStack}
+
+ >
+ )}
+
+
+ )}
+
+ {/* Action Buttons */}
+
+
+ Try Again
+
+
+
+ {/* Support Contact */}
+
+ If this problem persists, please contact support at{' '}
+ info@pezkuwichain.io
+
+
+
+
+ );
+ }
+
+ // No error, render children normally
+ return this.props.children;
+ }
+}
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ backgroundColor: '#0a0a0a',
+ },
+ scrollView: {
+ flex: 1,
+ },
+ scrollContent: {
+ flexGrow: 1,
+ justifyContent: 'center',
+ padding: 16,
+ },
+ card: {
+ backgroundColor: '#1a1a1a',
+ borderRadius: 12,
+ borderWidth: 1,
+ borderColor: '#2a2a2a',
+ padding: 24,
+ },
+ iconContainer: {
+ alignItems: 'center',
+ marginBottom: 16,
+ },
+ iconText: {
+ fontSize: 48,
+ },
+ title: {
+ fontSize: 24,
+ fontWeight: 'bold',
+ color: '#ffffff',
+ textAlign: 'center',
+ marginBottom: 12,
+ },
+ description: {
+ fontSize: 16,
+ color: '#9ca3af',
+ textAlign: 'center',
+ marginBottom: 24,
+ lineHeight: 24,
+ },
+ errorDetails: {
+ marginBottom: 24,
+ },
+ errorDetailsTitle: {
+ fontSize: 14,
+ fontWeight: '600',
+ color: '#6b7280',
+ marginBottom: 12,
+ },
+ errorBox: {
+ backgroundColor: '#0a0a0a',
+ borderRadius: 8,
+ borderWidth: 1,
+ borderColor: '#374151',
+ padding: 12,
+ },
+ errorLabel: {
+ fontSize: 12,
+ fontWeight: 'bold',
+ color: '#ef4444',
+ marginBottom: 8,
+ },
+ stackLabel: {
+ marginTop: 12,
+ },
+ errorText: {
+ fontSize: 11,
+ fontFamily: 'monospace',
+ color: '#9ca3af',
+ lineHeight: 16,
+ },
+ buttonContainer: {
+ marginBottom: 16,
+ },
+ primaryButton: {
+ backgroundColor: '#00A94F',
+ borderRadius: 8,
+ padding: 16,
+ alignItems: 'center',
+ },
+ buttonText: {
+ color: '#ffffff',
+ fontSize: 16,
+ fontWeight: '600',
+ },
+ supportText: {
+ fontSize: 14,
+ color: '#6b7280',
+ textAlign: 'center',
+ lineHeight: 20,
+ },
+ supportEmail: {
+ color: '#00A94F',
+ },
+});
diff --git a/mobile/src/components/index.ts b/mobile/src/components/index.ts
index b1c311fd..d1fd2537 100644
--- a/mobile/src/components/index.ts
+++ b/mobile/src/components/index.ts
@@ -3,6 +3,7 @@
* Inspired by Material Design 3, iOS HIG, and Kurdistan aesthetics
*/
+export { ErrorBoundary } from './ErrorBoundary';
export { Card } from './Card';
export { Button } from './Button';
export { Input } from './Input';
diff --git a/mobile/src/contexts/BiometricAuthContext.tsx b/mobile/src/contexts/BiometricAuthContext.tsx
index f008ff4e..d5a28420 100644
--- a/mobile/src/contexts/BiometricAuthContext.tsx
+++ b/mobile/src/contexts/BiometricAuthContext.tsx
@@ -85,7 +85,7 @@ export const BiometricAuthProvider: React.FC<{ children: React.ReactNode }> = ({
}
}
} catch (error) {
- console.error('Biometric init error:', error);
+ if (__DEV__) console.error('Biometric init error:', error);
}
};
@@ -108,7 +108,7 @@ export const BiometricAuthProvider: React.FC<{ children: React.ReactNode }> = ({
// Check if app should be locked
await checkAutoLock();
} catch (error) {
- console.error('Error loading settings:', error);
+ if (__DEV__) console.error('Error loading settings:', error);
}
};
@@ -136,7 +136,7 @@ export const BiometricAuthProvider: React.FC<{ children: React.ReactNode }> = ({
return false;
} catch (error) {
- console.error('Authentication error:', error);
+ if (__DEV__) console.error('Authentication error:', error);
return false;
}
};
@@ -159,7 +159,7 @@ export const BiometricAuthProvider: React.FC<{ children: React.ReactNode }> = ({
return false;
} catch (error) {
- console.error('Enable biometric error:', error);
+ if (__DEV__) console.error('Enable biometric error:', error);
return false;
}
};
@@ -173,7 +173,7 @@ export const BiometricAuthProvider: React.FC<{ children: React.ReactNode }> = ({
await AsyncStorage.setItem(BIOMETRIC_ENABLED_KEY, 'false');
setIsBiometricEnabled(false);
} catch (error) {
- console.error('Disable biometric error:', error);
+ if (__DEV__) console.error('Disable biometric error:', error);
}
};
@@ -191,7 +191,7 @@ export const BiometricAuthProvider: React.FC<{ children: React.ReactNode }> = ({
// Store in SecureStore (encrypted on device)
await SecureStore.setItemAsync(PIN_CODE_KEY, hashedPin);
} catch (error) {
- console.error('Set PIN error:', error);
+ if (__DEV__) console.error('Set PIN error:', error);
throw error;
}
};
@@ -220,7 +220,7 @@ export const BiometricAuthProvider: React.FC<{ children: React.ReactNode }> = ({
return false;
} catch (error) {
- console.error('Verify PIN error:', error);
+ if (__DEV__) console.error('Verify PIN error:', error);
return false;
}
};
@@ -250,7 +250,7 @@ export const BiometricAuthProvider: React.FC<{ children: React.ReactNode }> = ({
await AsyncStorage.setItem(AUTO_LOCK_TIMER_KEY, minutes.toString());
setAutoLockTimerState(minutes);
} catch (error) {
- console.error('Set auto-lock timer error:', error);
+ if (__DEV__) console.error('Set auto-lock timer error:', error);
}
};
@@ -273,7 +273,7 @@ export const BiometricAuthProvider: React.FC<{ children: React.ReactNode }> = ({
try {
await AsyncStorage.setItem(LAST_UNLOCK_TIME_KEY, Date.now().toString());
} catch (error) {
- console.error('Save unlock time error:', error);
+ if (__DEV__) console.error('Save unlock time error:', error);
}
};
@@ -303,7 +303,7 @@ export const BiometricAuthProvider: React.FC<{ children: React.ReactNode }> = ({
setIsLocked(false);
}
} catch (error) {
- console.error('Check auto-lock error:', error);
+ if (__DEV__) console.error('Check auto-lock error:', error);
// On error, lock for safety
setIsLocked(true);
}
diff --git a/mobile/src/contexts/LanguageContext.tsx b/mobile/src/contexts/LanguageContext.tsx
index e8436027..10aa5baa 100644
--- a/mobile/src/contexts/LanguageContext.tsx
+++ b/mobile/src/contexts/LanguageContext.tsx
@@ -29,7 +29,7 @@ export const LanguageProvider: React.FC<{ children: ReactNode }> = ({ children }
const saved = await AsyncStorage.getItem(LANGUAGE_KEY);
setHasSelectedLanguage(!!saved);
} catch (error) {
- console.error('Failed to check language selection:', error);
+ if (__DEV__) console.error('Failed to check language selection:', error);
}
};
@@ -49,7 +49,7 @@ export const LanguageProvider: React.FC<{ children: ReactNode }> = ({ children }
// You may want to show a message to restart the app
}
} catch (error) {
- console.error('Failed to change language:', error);
+ if (__DEV__) console.error('Failed to change language:', error);
}
};
diff --git a/mobile/src/contexts/PolkadotContext.tsx b/mobile/src/contexts/PolkadotContext.tsx
index d821f80d..e4a5cd61 100644
--- a/mobile/src/contexts/PolkadotContext.tsx
+++ b/mobile/src/contexts/PolkadotContext.tsx
@@ -3,6 +3,7 @@ import { ApiPromise, WsProvider } from '@polkadot/api';
import { Keyring } from '@polkadot/keyring';
import { KeyringPair } from '@polkadot/keyring/types';
import AsyncStorage from '@react-native-async-storage/async-storage';
+import * as SecureStore from 'expo-secure-store';
import { cryptoWaitReady } from '@polkadot/util-crypto';
import { DEFAULT_ENDPOINT } from '../../../shared/blockchain/polkadot';
@@ -56,9 +57,9 @@ export const PolkadotProvider: React.FC = ({
await cryptoWaitReady();
const kr = new Keyring({ type: 'sr25519' });
setKeyring(kr);
- console.log('✅ Crypto libraries initialized');
+ if (__DEV__) console.log('✅ Crypto libraries initialized');
} catch (err) {
- console.error('❌ Failed to initialize crypto:', err);
+ if (__DEV__) console.error('❌ Failed to initialize crypto:', err);
setError('Failed to initialize crypto libraries');
}
};
@@ -70,7 +71,7 @@ export const PolkadotProvider: React.FC = ({
useEffect(() => {
const initApi = async () => {
try {
- console.log('🔗 Connecting to Pezkuwi node:', endpoint);
+ if (__DEV__) console.log('🔗 Connecting to Pezkuwi node:', endpoint);
const provider = new WsProvider(endpoint);
const apiInstance = await ApiPromise.create({ provider });
@@ -81,7 +82,7 @@ export const PolkadotProvider: React.FC = ({
setIsApiReady(true);
setError(null);
- console.log('✅ Connected to Pezkuwi node');
+ if (__DEV__) console.log('✅ Connected to Pezkuwi node');
// Get chain info
const [chain, nodeName, nodeVersion] = await Promise.all([
@@ -90,10 +91,12 @@ export const PolkadotProvider: React.FC = ({
apiInstance.rpc.system.version(),
]);
- console.log(`📡 Chain: ${chain}`);
- console.log(`🖥️ Node: ${nodeName} v${nodeVersion}`);
+ if (__DEV__) {
+ console.log(`📡 Chain: ${chain}`);
+ console.log(`🖥️ Node: ${nodeName} v${nodeVersion}`);
+ }
} catch (err) {
- console.error('❌ Failed to connect to node:', err);
+ if (__DEV__) console.error('❌ Failed to connect to node:', err);
setError(`Failed to connect to node: ${endpoint}`);
setIsApiReady(false);
}
@@ -127,7 +130,7 @@ export const PolkadotProvider: React.FC = ({
}
}
} catch (err) {
- console.error('Failed to load accounts:', err);
+ if (__DEV__) console.error('Failed to load accounts:', err);
}
};
@@ -161,18 +164,18 @@ export const PolkadotProvider: React.FC = ({
setAccounts(updatedAccounts);
await AsyncStorage.setItem(WALLET_STORAGE_KEY, JSON.stringify(updatedAccounts));
- // Store encrypted seed separately
- const seedKey = `@pezkuwi_seed_${pair.address}`;
- await AsyncStorage.setItem(seedKey, mnemonicPhrase);
+ // SECURITY: Store encrypted seed in SecureStore (encrypted hardware-backed storage)
+ const seedKey = `pezkuwi_seed_${pair.address}`;
+ await SecureStore.setItemAsync(seedKey, mnemonicPhrase);
- console.log('✅ Wallet created:', pair.address);
+ if (__DEV__) console.log('✅ Wallet created:', pair.address);
return {
address: pair.address,
mnemonic: mnemonicPhrase,
};
} catch (err) {
- console.error('❌ Failed to create wallet:', err);
+ if (__DEV__) console.error('❌ Failed to create wallet:', err);
throw new Error('Failed to create wallet');
}
};
@@ -184,12 +187,12 @@ export const PolkadotProvider: React.FC = ({
}
try {
- // Load seed from storage
- const seedKey = `@pezkuwi_seed_${address}`;
- const mnemonic = await AsyncStorage.getItem(seedKey);
+ // SECURITY: Load seed from SecureStore (encrypted storage)
+ const seedKey = `pezkuwi_seed_${address}`;
+ const mnemonic = await SecureStore.getItemAsync(seedKey);
if (!mnemonic) {
- console.error('No seed found for address:', address);
+ if (__DEV__) console.error('No seed found for address:', address);
return null;
}
@@ -197,7 +200,7 @@ export const PolkadotProvider: React.FC = ({
const pair = keyring.addFromMnemonic(mnemonic);
return pair;
} catch (err) {
- console.error('Failed to get keypair:', err);
+ if (__DEV__) console.error('Failed to get keypair:', err);
return null;
}
};
@@ -218,9 +221,9 @@ export const PolkadotProvider: React.FC = ({
await AsyncStorage.setItem(SELECTED_ACCOUNT_KEY, accounts[0].address);
}
- console.log(`✅ Connected with ${accounts.length} account(s)`);
+ if (__DEV__) console.log(`✅ Connected with ${accounts.length} account(s)`);
} catch (err) {
- console.error('❌ Wallet connection failed:', err);
+ if (__DEV__) console.error('❌ Wallet connection failed:', err);
setError('Failed to connect wallet');
}
};
@@ -229,7 +232,7 @@ export const PolkadotProvider: React.FC = ({
const disconnectWallet = () => {
setSelectedAccount(null);
AsyncStorage.removeItem(SELECTED_ACCOUNT_KEY);
- console.log('🔌 Wallet disconnected');
+ if (__DEV__) console.log('🔌 Wallet disconnected');
};
// Update selected account storage when it changes
diff --git a/mobile/src/i18n/index.ts b/mobile/src/i18n/index.ts
index e27af39a..0b7f29ed 100644
--- a/mobile/src/i18n/index.ts
+++ b/mobile/src/i18n/index.ts
@@ -27,7 +27,7 @@ const initializeI18n = async () => {
savedLanguage = stored;
}
} catch (error) {
- console.warn('Failed to load saved language:', error);
+ if (__DEV__) console.warn('Failed to load saved language:', error);
}
i18n
@@ -58,7 +58,7 @@ export const saveLanguage = async (languageCode: string) => {
await AsyncStorage.setItem(LANGUAGE_KEY, languageCode);
await i18n.changeLanguage(languageCode);
} catch (error) {
- console.error('Failed to save language:', error);
+ if (__DEV__) console.error('Failed to save language:', error);
}
};
diff --git a/mobile/src/screens/EducationScreen.tsx b/mobile/src/screens/EducationScreen.tsx
index 8572dd57..ce58ecbb 100644
--- a/mobile/src/screens/EducationScreen.tsx
+++ b/mobile/src/screens/EducationScreen.tsx
@@ -47,7 +47,7 @@ const EducationScreen: React.FC = () => {
const allCourses = await getAllCourses(api);
setCourses(allCourses);
} catch (error) {
- console.error('Failed to fetch courses:', error);
+ if (__DEV__) console.error('Failed to fetch courses:', error);
} finally {
setLoading(false);
setRefreshing(false);
@@ -64,7 +64,7 @@ const EducationScreen: React.FC = () => {
const studentEnrollments = await getStudentEnrollments(selectedAccount.address);
setEnrollments(studentEnrollments);
} catch (error) {
- console.error('Failed to fetch enrollments:', error);
+ if (__DEV__) console.error('Failed to fetch enrollments:', error);
}
}, [selectedAccount]);
@@ -102,7 +102,7 @@ const EducationScreen: React.FC = () => {
Alert.alert('Success', 'Successfully enrolled in course!');
fetchEnrollments();
} catch (error: any) {
- console.error('Enrollment failed:', error);
+ if (__DEV__) console.error('Enrollment failed:', error);
Alert.alert('Enrollment Failed', error.message || 'Failed to enroll in course');
} finally {
setEnrolling(null);
@@ -138,7 +138,7 @@ const EducationScreen: React.FC = () => {
Alert.alert('Success', 'Course completed! Certificate issued.');
fetchEnrollments();
} catch (error: any) {
- console.error('Completion failed:', error);
+ if (__DEV__) console.error('Completion failed:', error);
Alert.alert('Error', error.message || 'Failed to complete course');
}
},
diff --git a/mobile/src/screens/ForumScreen.tsx b/mobile/src/screens/ForumScreen.tsx
index 23c293ae..189750df 100644
--- a/mobile/src/screens/ForumScreen.tsx
+++ b/mobile/src/screens/ForumScreen.tsx
@@ -134,7 +134,7 @@ const ForumScreen: React.FC = () => {
await new Promise((resolve) => setTimeout(resolve, 500));
setThreads(MOCK_THREADS);
} catch (error) {
- console.error('Failed to fetch threads:', error);
+ if (__DEV__) console.error('Failed to fetch threads:', error);
} finally {
setLoading(false);
setRefreshing(false);
diff --git a/mobile/src/screens/GovernanceScreen.tsx b/mobile/src/screens/GovernanceScreen.tsx
index 52ad6baf..9fc988d3 100644
--- a/mobile/src/screens/GovernanceScreen.tsx
+++ b/mobile/src/screens/GovernanceScreen.tsx
@@ -121,7 +121,7 @@ export default function GovernanceScreen() {
setProposals(proposalsList);
} catch (error) {
- console.error('Error fetching proposals:', error);
+ if (__DEV__) console.error('Error fetching proposals:', error);
Alert.alert('Error', 'Failed to load proposals');
} finally {
setLoading(false);
@@ -162,7 +162,7 @@ export default function GovernanceScreen() {
];
setElections(mockElections);
} catch (error) {
- console.error('Error fetching elections:', error);
+ if (__DEV__) console.error('Error fetching elections:', error);
}
};
@@ -191,7 +191,7 @@ export default function GovernanceScreen() {
}
});
} catch (error: any) {
- console.error('Voting error:', error);
+ if (__DEV__) console.error('Voting error:', error);
Alert.alert('Error', error.message || 'Failed to submit vote');
} finally {
setVoting(false);
@@ -231,7 +231,7 @@ export default function GovernanceScreen() {
setVotedCandidates([]);
fetchElections();
} catch (error: any) {
- console.error('Election voting error:', error);
+ if (__DEV__) console.error('Election voting error:', error);
Alert.alert('Error', error.message || 'Failed to submit vote');
} finally {
setVoting(false);
diff --git a/mobile/src/screens/NFTGalleryScreen.tsx b/mobile/src/screens/NFTGalleryScreen.tsx
index a85674a1..44c5c70b 100644
--- a/mobile/src/screens/NFTGalleryScreen.tsx
+++ b/mobile/src/screens/NFTGalleryScreen.tsx
@@ -110,7 +110,7 @@ export default function NFTGalleryScreen() {
setNfts(nftList);
} catch (error) {
- console.error('Error fetching NFTs:', error);
+ if (__DEV__) console.error('Error fetching NFTs:', error);
} finally {
setLoading(false);
setRefreshing(false);
diff --git a/mobile/src/screens/P2PScreen.tsx b/mobile/src/screens/P2PScreen.tsx
index 93b57fe9..f48e5b47 100644
--- a/mobile/src/screens/P2PScreen.tsx
+++ b/mobile/src/screens/P2PScreen.tsx
@@ -64,7 +64,7 @@ const P2PScreen: React.FC = () => {
setOffers(enrichedOffers);
} catch (error) {
- console.error('Fetch offers error:', error);
+ if (__DEV__) console.error('Fetch offers error:', error);
} finally {
setLoading(false);
setRefreshing(false);
@@ -191,7 +191,7 @@ const P2PScreen: React.FC = () => {
variant="primary"
onPress={() => {
// TODO: Open trade modal
- console.log('Trade with offer:', item.id);
+ if (__DEV__) console.log('Trade with offer:', item.id);
}}
style={styles.tradeButton}
>
diff --git a/mobile/src/screens/ReferralScreen.tsx b/mobile/src/screens/ReferralScreen.tsx
index aac73623..3fce2087 100644
--- a/mobile/src/screens/ReferralScreen.tsx
+++ b/mobile/src/screens/ReferralScreen.tsx
@@ -67,10 +67,10 @@ const ReferralScreen: React.FC = () => {
});
if (result.action === Share.sharedAction) {
- console.log('Shared successfully');
+ if (__DEV__) console.log('Shared successfully');
}
} catch (error) {
- console.error('Error sharing:', error);
+ if (__DEV__) console.error('Error sharing:', error);
}
};
diff --git a/mobile/src/screens/SignInScreen.tsx b/mobile/src/screens/SignInScreen.tsx
index a39ab846..421482a8 100644
--- a/mobile/src/screens/SignInScreen.tsx
+++ b/mobile/src/screens/SignInScreen.tsx
@@ -27,7 +27,7 @@ const SignInScreen: React.FC = ({ onSignIn, onNavigateToSignU
const handleSignIn = () => {
// TODO: Implement actual authentication
- console.log('Sign in:', { email, password });
+ if (__DEV__) console.log('Sign in:', { email, password });
onSignIn();
};
diff --git a/mobile/src/screens/SignUpScreen.tsx b/mobile/src/screens/SignUpScreen.tsx
index 80a406f6..a94fe3bb 100644
--- a/mobile/src/screens/SignUpScreen.tsx
+++ b/mobile/src/screens/SignUpScreen.tsx
@@ -32,7 +32,7 @@ const SignUpScreen: React.FC = ({ onSignUp, onNavigateToSignI
alert('Passwords do not match!');
return;
}
- console.log('Sign up:', { email, password });
+ if (__DEV__) console.log('Sign up:', { email, password });
onSignUp();
};
diff --git a/mobile/src/screens/StakingScreen.tsx b/mobile/src/screens/StakingScreen.tsx
index c7441135..7be652dd 100644
--- a/mobile/src/screens/StakingScreen.tsx
+++ b/mobile/src/screens/StakingScreen.tsx
@@ -122,7 +122,7 @@ export default function StakingScreen() {
estimatedAPY,
});
} catch (error) {
- console.error('Error fetching staking data:', error);
+ if (__DEV__) console.error('Error fetching staking data:', error);
Alert.alert('Error', 'Failed to load staking data');
} finally {
setLoading(false);
@@ -155,7 +155,7 @@ export default function StakingScreen() {
}
});
} catch (error: any) {
- console.error('Staking error:', error);
+ if (__DEV__) console.error('Staking error:', error);
Alert.alert('Error', error.message || 'Failed to stake tokens');
} finally {
setProcessing(false);
@@ -189,7 +189,7 @@ export default function StakingScreen() {
}
});
} catch (error: any) {
- console.error('Unstaking error:', error);
+ if (__DEV__) console.error('Unstaking error:', error);
Alert.alert('Error', error.message || 'Failed to unstake tokens');
} finally {
setProcessing(false);
diff --git a/mobile/src/screens/SwapScreen.tsx b/mobile/src/screens/SwapScreen.tsx
index b5fe9dcc..e038a58c 100644
--- a/mobile/src/screens/SwapScreen.tsx
+++ b/mobile/src/screens/SwapScreen.tsx
@@ -98,7 +98,7 @@ const SwapScreen: React.FC = () => {
newBalances[token.symbol] = '0.0000';
}
} catch (error) {
- console.log(`No balance for ${token.symbol}`);
+ if (__DEV__) console.log(`No balance for ${token.symbol}`);
newBalances[token.symbol] = '0.0000';
}
}
@@ -106,7 +106,7 @@ const SwapScreen: React.FC = () => {
setBalances(newBalances);
} catch (error) {
- console.error('Failed to fetch balances:', error);
+ if (__DEV__) console.error('Failed to fetch balances:', error);
}
}, [api, isApiReady, selectedAccount]);
@@ -159,7 +159,7 @@ const SwapScreen: React.FC = () => {
setPoolReserves({ reserve1, reserve2 });
setState((prev) => ({ ...prev, loading: false }));
} catch (error) {
- console.error('Failed to fetch pool reserves:', error);
+ if (__DEV__) console.error('Failed to fetch pool reserves:', error);
Alert.alert('Error', 'Failed to fetch pool information.');
setState((prev) => ({ ...prev, loading: false }));
}
@@ -214,7 +214,7 @@ const SwapScreen: React.FC = () => {
setState((prev) => ({ ...prev, toAmount: toAmountFormatted }));
setPriceImpact(impact);
} catch (error) {
- console.error('Calculation error:', error);
+ if (__DEV__) console.error('Calculation error:', error);
setState((prev) => ({ ...prev, toAmount: '' }));
}
}, [state.fromAmount, state.fromToken, state.toToken, poolReserves]);
@@ -326,12 +326,14 @@ const SwapScreen: React.FC = () => {
// Create swap path
const path = [state.fromToken.assetId, state.toToken.assetId];
- console.log('Swap params:', {
- path,
- amountIn,
- amountOutMin,
- slippage: state.slippage,
- });
+ if (__DEV__) {
+ console.log('Swap params:', {
+ path,
+ amountIn,
+ amountOutMin,
+ slippage: state.slippage,
+ });
+ }
// Create transaction
const tx = api.tx.assetConversion.swapTokensForExactTokens(
@@ -347,7 +349,7 @@ const SwapScreen: React.FC = () => {
let unsub: (() => void) | undefined;
tx.signAndSend(keyPair, ({ status, events, dispatchError }) => {
- console.log('Transaction status:', status.type);
+ if (__DEV__) console.log('Transaction status:', status.type);
if (dispatchError) {
if (dispatchError.isModule) {
@@ -365,7 +367,7 @@ const SwapScreen: React.FC = () => {
}
if (status.isInBlock || status.isFinalized) {
- console.log('Transaction included in block');
+ if (__DEV__) console.log('Transaction included in block');
resolve();
if (unsub) unsub();
}
@@ -398,7 +400,7 @@ const SwapScreen: React.FC = () => {
]
);
} catch (error: any) {
- console.error('Swap failed:', error);
+ if (__DEV__) console.error('Swap failed:', error);
Alert.alert('Swap Failed', error.message || 'An error occurred.');
setState((prev) => ({ ...prev, swapping: false }));
}
diff --git a/mobile/src/screens/WalletScreen.tsx b/mobile/src/screens/WalletScreen.tsx
index 72622b26..2a5eb154 100644
--- a/mobile/src/screens/WalletScreen.tsx
+++ b/mobile/src/screens/WalletScreen.tsx
@@ -149,7 +149,7 @@ const WalletScreen: React.FC = () => {
}
}
} catch (err) {
- console.log('PEZ asset not found or not accessible');
+ if (__DEV__) console.log('PEZ asset not found or not accessible');
}
// Fetch USDT balance (wUSDT - asset ID 2)
@@ -163,7 +163,7 @@ const WalletScreen: React.FC = () => {
}
}
} catch (err) {
- console.log('USDT asset not found or not accessible');
+ if (__DEV__) console.log('USDT asset not found or not accessible');
}
setBalances({
@@ -172,7 +172,7 @@ const WalletScreen: React.FC = () => {
USDT: usdtBalance,
});
} catch (err) {
- console.error('Failed to fetch balances:', err);
+ if (__DEV__) console.error('Failed to fetch balances:', err);
Alert.alert('Error', 'Failed to fetch token balances');
} finally {
setIsLoadingBalances(false);
@@ -198,7 +198,7 @@ const WalletScreen: React.FC = () => {
await connectWallet();
Alert.alert('Connected', 'Wallet connected successfully!');
} catch (err) {
- console.error('Failed to connect wallet:', err);
+ if (__DEV__) console.error('Failed to connect wallet:', err);
Alert.alert('Error', 'Failed to connect wallet');
}
};
@@ -220,7 +220,7 @@ const WalletScreen: React.FC = () => {
[{ text: 'OK', onPress: () => connectWallet() }]
);
} catch (err) {
- console.error('Failed to create wallet:', err);
+ if (__DEV__) console.error('Failed to create wallet:', err);
Alert.alert('Error', 'Failed to create wallet');
}
};