move common aadhaar functions to msdk (#1200)

* move common aadhaar functions to msdk

* remove comment

* add license headers
This commit is contained in:
Aaron DeRuvo
2025-10-03 14:37:53 +02:00
committed by GitHub
parent 187fc185e2
commit a00cb7e58d
6 changed files with 168 additions and 131 deletions

View File

@@ -754,6 +754,7 @@ async function storeDocumentDirectlyToKeychain(
});
}
// Duplicate funciton. prefer one on mobile sdk
export async function storeDocumentWithDeduplication(
passportData: PassportData | AadhaarData,
): Promise<string> {
@@ -801,7 +802,7 @@ export async function storeDocumentWithDeduplication(
return contentHash;
}
// Duplicate function. prefer one in mobile sdk
export async function storePassportData(
passportData: PassportData | AadhaarData,
) {

View File

@@ -201,6 +201,18 @@ export const SelfClientProvider = ({ children }: PropsWithChildren) => {
}
});
addListener(SdkEvents.PROVING_AADHAAR_UPLOAD_SUCCESS, () => {
if (navigationRef.isReady()) {
navigationRef.navigate('AadhaarUploadSuccess');
}
});
addListener(SdkEvents.PROVING_AADHAAR_UPLOAD_FAILURE, ({ errorType }) => {
if (navigationRef.isReady()) {
// @ts-expect-error
navigationRef.navigate('AadhaarUploadError', { errorType });
}
});
return map;
}, []);

View File

@@ -9,6 +9,7 @@ import { useNavigation, useRoute } from '@react-navigation/native';
import { useSelfClient } from '@selfxyz/mobile-sdk-alpha';
import { AadhaarEvents } from '@selfxyz/mobile-sdk-alpha/constants/analytics';
import { getErrorMessages } from '@selfxyz/mobile-sdk-alpha/onboarding/import-aadhaar';
import { PrimaryButton } from '@/components/buttons/PrimaryButton';
import { SecondaryButton } from '@/components/buttons/SecondaryButton';
@@ -34,24 +35,7 @@ const AadhaarUploadErrorScreen: React.FC = () => {
const { trackEvent } = useSelfClient();
const errorType = route.params?.errorType || 'general';
// Define error messages based on error type
const getErrorMessages = () => {
if (errorType === 'expired') {
return {
title: 'QR Code Has Expired',
description:
'You uploaded a valid Aadhaar QR code, but unfortunately it has expired. Please generate a new QR code from the mAadhaar app and try again.',
};
}
return {
title: 'There was a problem reading the code',
description:
'Please ensure the QR code is clear and well-lit, then try again. For best results, take a screenshot of the QR code instead of photographing it.',
};
};
const { title, description } = getErrorMessages();
const { title, description } = getErrorMessages(errorType);
return (
<YStack flex={1} backgroundColor={slate100}>

View File

@@ -8,13 +8,9 @@ import { Image, XStack, YStack } from 'tamagui';
import { useNavigation } from '@react-navigation/native';
import type { NativeStackNavigationProp } from '@react-navigation/native-stack';
import {
extractQRDataFields,
getAadharRegistrationWindow,
} from '@selfxyz/common/utils';
import type { AadhaarData } from '@selfxyz/common/utils/types';
import { useSelfClient } from '@selfxyz/mobile-sdk-alpha';
import { AadhaarEvents } from '@selfxyz/mobile-sdk-alpha/constants/analytics';
import { useAadhaar } from '@selfxyz/mobile-sdk-alpha/onboarding/import-aadhaar';
import { PrimaryButton } from '@/components/buttons/PrimaryButton';
import { BodyText } from '@/components/typography/BodyText';
@@ -22,7 +18,6 @@ import { useModal } from '@/hooks/useModal';
import AadhaarImage from '@/images/512w.png';
import { useSafeAreaInsets } from '@/mocks/react-native-safe-area-context';
import type { RootStackParamList } from '@/navigation';
import { storePassportData } from '@/providers/passportDataProvider';
import { slate100, slate200, slate400, slate500, white } from '@/utils/colors';
import { extraYPadding } from '@/utils/constants';
import {
@@ -32,6 +27,7 @@ import {
const AadhaarUploadScreen: React.FC = () => {
const { bottom } = useSafeAreaInsets();
const navigation =
useNavigation<NativeStackNavigationProp<RootStackParamList>>();
const { trackEvent } = useSelfClient();
@@ -65,110 +61,7 @@ const AadhaarUploadScreen: React.FC = () => {
}
}, [trackEvent]);
const validateAAdhaarTimestamp = useCallback(
async (timestamp: string) => {
//timestamp is in YYYY-MM-DD HH:MM format
trackEvent(AadhaarEvents.TIMESTAMP_VALIDATION_STARTED);
const currentTimestamp = new Date().getTime();
const timestampDate = new Date(timestamp);
const timestampTimestamp = timestampDate.getTime();
const diff = currentTimestamp - timestampTimestamp;
const diffMinutes = diff / (1000 * 60);
const allowedWindow = await getAadharRegistrationWindow();
const isValid = diffMinutes <= allowedWindow;
if (isValid) {
trackEvent(AadhaarEvents.TIMESTAMP_VALIDATION_SUCCESS);
} else {
trackEvent(AadhaarEvents.TIMESTAMP_VALIDATION_FAILED);
}
return isValid;
},
[trackEvent],
);
const processAadhaarQRCode = useCallback(
async (qrCodeData: string) => {
try {
if (
!qrCodeData ||
typeof qrCodeData !== 'string' ||
qrCodeData.length < 100
) {
trackEvent(AadhaarEvents.QR_CODE_INVALID_FORMAT);
throw new Error('Invalid QR code format - too short or not a string');
}
if (!/^\d+$/.test(qrCodeData)) {
trackEvent(AadhaarEvents.QR_CODE_INVALID_FORMAT);
throw new Error('Invalid QR code format - not a numeric string');
}
if (qrCodeData.length < 100) {
trackEvent(AadhaarEvents.QR_CODE_INVALID_FORMAT);
throw new Error(
'QR code too short - likely not a valid Aadhaar QR code',
);
}
trackEvent(AadhaarEvents.QR_DATA_EXTRACTION_STARTED);
let extractedFields;
try {
extractedFields = extractQRDataFields(qrCodeData);
trackEvent(AadhaarEvents.QR_DATA_EXTRACTION_SUCCESS);
} catch {
trackEvent(AadhaarEvents.QR_CODE_PARSE_FAILED);
throw new Error('Failed to parse Aadhaar QR code - invalid format');
}
if (
!extractedFields.name ||
!extractedFields.dob ||
!extractedFields.gender
) {
trackEvent(AadhaarEvents.QR_CODE_MISSING_FIELDS);
throw new Error('Invalid Aadhaar QR code - missing required fields');
}
if (!(await validateAAdhaarTimestamp(extractedFields.timestamp))) {
trackEvent(AadhaarEvents.QR_CODE_EXPIRED);
throw new Error('QRCODE_EXPIRED');
}
const aadhaarData: AadhaarData = {
documentType: 'aadhaar',
documentCategory: 'aadhaar',
mock: false,
qrData: qrCodeData,
extractedFields: extractedFields,
signature: [],
publicKey: '',
photoHash: '',
};
trackEvent(AadhaarEvents.DATA_STORAGE_STARTED);
await storePassportData(aadhaarData);
trackEvent(AadhaarEvents.DATA_STORAGE_SUCCESS);
trackEvent(AadhaarEvents.QR_UPLOAD_SUCCESS);
navigation.navigate('AadhaarUploadSuccess');
} catch (error) {
// Check if it's a QR code expiration error
const errorType: 'expired' | 'general' =
error instanceof Error && error.message === 'QRCODE_EXPIRED'
? 'expired'
: 'general';
trackEvent(AadhaarEvents.ERROR_SCREEN_NAVIGATED, { errorType });
(navigation.navigate as any)('AadhaarUploadError', { errorType });
}
},
[navigation, trackEvent, validateAAdhaarTimestamp],
);
const { processAadhaarQRCode } = useAadhaar();
const onPhotoLibraryPress = useCallback(async () => {
if (isProcessing) {