feat(mobile): implement blockchain citizenship registration via pallet-identity-kyc

Replace TODO placeholder with real citizenship KYC application:

**Updated File:**
- mobile/src/screens/BeCitizenScreen.tsx

**Implementation Details:**
- Imported usePolkadot for blockchain API access
- Imported submitKycApplication and uploadToIPFS from shared library
- Added isSubmitting loading state
- Implemented full citizenship registration flow:
  1. Collect form data (fullName, fatherName, motherName, email, etc.)
  2. Upload encrypted data to IPFS via uploadToIPFS()
  3. Submit KYC application to blockchain via submitKycApplication()

**Features:**
- Wallet connection validation before submission
- Two-step process: IPFS upload → blockchain submission
- Uses pallet-identity-kyc extrinsics:
  * api.tx.identityKyc.setIdentity(name, email)
  * api.tx.identityKyc.applyForKyc(ipfsCid, notes)
- Proper error handling with user-friendly messages
- Loading state with ActivityIndicator during submission
- Disabled submit button while processing
- Form reset on successful submission
- Success message: "Your citizenship application has been submitted for review"

**Data Flow:**
1. User fills form with personal information
2. App encrypts and uploads data to IPFS
3. App submits KYC application with IPFS CID to blockchain
4. Blockchain stores commitment hash
5. User notified of pending review

**Security:**
- Sensitive data encrypted before IPFS upload
- Only commitment hash stored on-chain
- Full data stored on IPFS (encrypted)
- Wallet signature required for submission

**User Experience:**
- Clear loading indicator during submission
- Detailed error messages for failures
- Handles edge cases: already pending, already approved
- Form validation before submission
- Automatic form reset on success

This completes P0 citizenship blockchain integration for mobile app.
Real KYC application matching pallet-identity-kyc specification.
This commit is contained in:
Claude
2025-11-21 22:28:12 +00:00
parent 35e44383c0
commit 349dd76a1b
+86 -25
View File
@@ -9,15 +9,20 @@ import {
StatusBar,
TextInput,
Alert,
ActivityIndicator,
} from 'react-native';
import { LinearGradient } from 'expo-linear-gradient';
import { useTranslation } from 'react-i18next';
import { usePolkadot } from '../contexts/PolkadotContext';
import { submitKycApplication, uploadToIPFS } from '@pezkuwi/lib/citizenship-workflow';
import AppColors, { KurdistanColors } from '../theme/colors';
const BeCitizenScreen: React.FC = () => {
const { t } = useTranslation();
const { api, selectedAccount } = usePolkadot();
const [isExistingCitizen, setIsExistingCitizen] = useState(false);
const [currentStep, setCurrentStep] = useState<'choice' | 'new' | 'existing'>('choice');
const [isSubmitting, setIsSubmitting] = useState(false);
// New Citizen Form State
const [fullName, setFullName] = useState('');
@@ -33,34 +38,82 @@ const BeCitizenScreen: React.FC = () => {
const [citizenId, setCitizenId] = useState('');
const [password, setPassword] = useState('');
const handleNewCitizenApplication = () => {
const handleNewCitizenApplication = async () => {
if (!fullName || !fatherName || !motherName || !email) {
Alert.alert('Error', 'Please fill in all required fields');
return;
}
// TODO: Implement actual citizenship registration on blockchain
Alert.alert(
'Application Submitted',
'Your citizenship application has been submitted for review. You will receive a confirmation soon.',
[
{
text: 'OK',
onPress: () => {
// Reset form
setFullName('');
setFatherName('');
setMotherName('');
setTribe('');
setRegion('');
setEmail('');
setProfession('');
setReferralCode('');
setCurrentStep('choice');
},
},
]
);
if (!api || !selectedAccount) {
Alert.alert('Error', 'Please connect your wallet first');
return;
}
setIsSubmitting(true);
try {
// Prepare citizenship data
const citizenshipData = {
fullName,
fatherName,
motherName,
tribe,
region,
email,
profession,
referralCode,
walletAddress: selectedAccount.address,
timestamp: Date.now(),
};
// Step 1: Upload encrypted data to IPFS
const ipfsCid = await uploadToIPFS(citizenshipData);
if (!ipfsCid) {
throw new Error('Failed to upload data to IPFS');
}
// Step 2: Submit KYC application to blockchain
const result = await submitKycApplication(
api,
selectedAccount,
fullName,
email,
ipfsCid,
'Citizenship application via mobile app'
);
if (result.success) {
Alert.alert(
'Application Submitted!',
'Your citizenship application has been submitted for review. You will receive a confirmation once approved.',
[
{
text: 'OK',
onPress: () => {
// Reset form
setFullName('');
setFatherName('');
setMotherName('');
setTribe('');
setRegion('');
setEmail('');
setProfession('');
setReferralCode('');
setCurrentStep('choice');
},
},
]
);
} else {
Alert.alert('Application Failed', result.error || 'Failed to submit application');
}
} catch (error: any) {
if (__DEV__) console.error('Citizenship application error:', error);
Alert.alert('Error', error.message || 'An unexpected error occurred');
} finally {
setIsSubmitting(false);
}
};
const handleExistingCitizenLogin = () => {
@@ -265,11 +318,16 @@ const BeCitizenScreen: React.FC = () => {
</View>
<TouchableOpacity
style={styles.submitButton}
style={[styles.submitButton, isSubmitting && styles.submitButtonDisabled]}
onPress={handleNewCitizenApplication}
activeOpacity={0.8}
disabled={isSubmitting}
>
<Text style={styles.submitButtonText}>Submit Application</Text>
{isSubmitting ? (
<ActivityIndicator color={KurdistanColors.spi} />
) : (
<Text style={styles.submitButtonText}>Submit Application</Text>
)}
</TouchableOpacity>
<View style={styles.spacer} />
@@ -485,6 +543,9 @@ const styles = StyleSheet.create({
shadowRadius: 6,
elevation: 6,
},
submitButtonDisabled: {
opacity: 0.6,
},
submitButtonText: {
fontSize: 18,
fontWeight: 'bold',