mirror of
https://github.com/pezkuwichain/pwap.git
synced 2026-06-13 19:11:01 +00:00
fix(mobile): critical security and error handling improvements
🔐 SECURITY FIXES: - Fixed CRITICAL seed storage vulnerability * Changed from AsyncStorage to SecureStore for wallet seeds * Seeds now encrypted in hardware-backed secure storage * Affects: PolkadotContext.tsx (lines 166, 189) 🛡️ ERROR HANDLING: - Added global ErrorBoundary component * Catches unhandled React errors * Shows user-friendly error UI * Integrated into App.tsx provider hierarchy * Files: ErrorBoundary.tsx (new), App.tsx, components/index.ts 🧹 PRODUCTION READINESS: - Protected all 47 console statements with __DEV__ checks * console.log: 12 statements * console.error: 32 statements * console.warn: 1 statement * Files affected: 16 files across contexts, screens, i18n * Production builds will strip these out 📦 PROVIDER HIERARCHY: - Added BiometricAuthProvider to App.tsx - Updated provider order: ErrorBoundary → Polkadot → Language → BiometricAuth → Navigator Files modified: 18 New files: 1 (ErrorBoundary.tsx) This commit resolves 3 P0 critical issues from production readiness audit.
This commit is contained in:
@@ -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');
|
||||
}
|
||||
},
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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}
|
||||
>
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ const SignInScreen: React.FC<SignInScreenProps> = ({ onSignIn, onNavigateToSignU
|
||||
|
||||
const handleSignIn = () => {
|
||||
// TODO: Implement actual authentication
|
||||
console.log('Sign in:', { email, password });
|
||||
if (__DEV__) console.log('Sign in:', { email, password });
|
||||
onSignIn();
|
||||
};
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ const SignUpScreen: React.FC<SignUpScreenProps> = ({ onSignUp, onNavigateToSignI
|
||||
alert('Passwords do not match!');
|
||||
return;
|
||||
}
|
||||
console.log('Sign up:', { email, password });
|
||||
if (__DEV__) console.log('Sign up:', { email, password });
|
||||
onSignUp();
|
||||
};
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 }));
|
||||
}
|
||||
|
||||
@@ -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');
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user