Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 46 additions & 0 deletions app/src/providers/passportDataProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ interface DocumentMetadata {
documentCategory: DocumentCategory; // passport, id_card, aadhaar
data: string; // DG1/MRZ data for passports/IDs, relevant data for aadhaar
mock: boolean; // whether this is a mock document
isRegistered?: boolean; // whether the document is registered onChain
}

interface DocumentCatalog {
Expand Down Expand Up @@ -185,6 +186,7 @@ export async function storeDocumentWithDeduplication(
inferDocumentCategory(passportData.documentType),
data: passportData.mrz || '', // Store MRZ for passports/IDs, relevant data for aadhaar
mock: passportData.mock || false,
isRegistered: false,
};

catalog.documents.push(metadata);
Expand Down Expand Up @@ -522,6 +524,12 @@ interface IPassportContext {
migrateFromLegacyStorage: () => Promise<void>;
getCurrentDocumentType: () => Promise<string | null>;
clearDocumentCatalogForMigrationTesting: () => Promise<void>;
markCurrentDocumentAsRegistered: () => Promise<void>;
updateDocumentRegistrationState: (
documentId: string,
isRegistered: boolean,
) => Promise<void>;
checkIfAnyDocumentsNeedMigration: () => Promise<boolean>;
}

export const PassportContext = createContext<IPassportContext>({
Expand All @@ -542,6 +550,9 @@ export const PassportContext = createContext<IPassportContext>({
getCurrentDocumentType: getCurrentDocumentType,
clearDocumentCatalogForMigrationTesting:
clearDocumentCatalogForMigrationTesting,
markCurrentDocumentAsRegistered: markCurrentDocumentAsRegistered,
updateDocumentRegistrationState: updateDocumentRegistrationState,
checkIfAnyDocumentsNeedMigration: checkIfAnyDocumentsNeedMigration,
});

export const PassportProvider = ({ children }: PassportProviderProps) => {
Expand Down Expand Up @@ -598,6 +609,9 @@ export const PassportProvider = ({ children }: PassportProviderProps) => {
getCurrentDocumentType: getCurrentDocumentType,
clearDocumentCatalogForMigrationTesting:
clearDocumentCatalogForMigrationTesting,
markCurrentDocumentAsRegistered: markCurrentDocumentAsRegistered,
updateDocumentRegistrationState: updateDocumentRegistrationState,
checkIfAnyDocumentsNeedMigration: checkIfAnyDocumentsNeedMigration,
}),
[
getData,
Expand Down Expand Up @@ -674,3 +688,35 @@ export async function getCurrentDocumentType(): Promise<string | null> {
);
return metadata?.documentType || null;
}

export async function updateDocumentRegistrationState(
documentId: string,
isRegistered: boolean,
): Promise<void> {
const catalog = await loadDocumentCatalog();
const documentIndex = catalog.documents.findIndex(d => d.id === documentId);

if (documentIndex !== -1) {
catalog.documents[documentIndex].isRegistered = isRegistered;
await saveDocumentCatalog(catalog);
console.log(
`Updated registration state for document ${documentId}: ${isRegistered}`,
);
} else {
console.warn(`Document ${documentId} not found in catalog`);
}
}

export async function markCurrentDocumentAsRegistered(): Promise<void> {
const catalog = await loadDocumentCatalog();
if (catalog.selectedDocumentId) {
await updateDocumentRegistrationState(catalog.selectedDocumentId, true);
} else {
console.warn('No selected document to mark as registered');
}
}

export async function checkIfAnyDocumentsNeedMigration(): Promise<boolean> {
const catalog = await loadDocumentCatalog();
return catalog.documents.some(doc => doc.isRegistered === undefined);
}
16 changes: 15 additions & 1 deletion app/src/screens/aesop/PassportOnboardingScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,28 @@ import useHapticNavigation from '../../hooks/useHapticNavigation';
import Scan from '../../images/icons/passport_camera_scan.svg';
import { ExpandableBottomLayout } from '../../layouts/ExpandableBottomLayout';
import { black, slate100, white } from '../../utils/colors';
import { hasAnyValidRegisteredDocument } from '../../utils/proving/validateDocument';

interface PassportOnboardingScreenProps {}

const PassportOnboardingScreen: React.FC<
PassportOnboardingScreenProps
> = ({}) => {
const handleCameraPress = useHapticNavigation('PassportCamera');
const onCancelPress = useHapticNavigation('Launch', { action: 'cancel' });
const navigateToLaunch = useHapticNavigation('Launch', {
action: 'cancel',
});
const navigateToHome = useHapticNavigation('Home', {
action: 'cancel',
});
const onCancelPress = async () => {
const hasValidDocument = await hasAnyValidRegisteredDocument();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is what you where mentioning during the meet, nice that you found a solution

if (hasValidDocument) {
navigateToHome();
} else {
navigateToLaunch();
}
};
const animationRef = useRef<LottieView>(null);

useEffect(() => {
Expand Down
23 changes: 21 additions & 2 deletions app/src/screens/misc/SplashScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,17 @@ import { StyleSheet } from 'react-native';

import splashAnimation from '../../assets/animations/splash.json';
import { useAuth } from '../../providers/authProvider';
import { migrateFromLegacyStorage } from '../../providers/passportDataProvider';
import {
checkIfAnyDocumentsNeedMigration,
migrateFromLegacyStorage,
} from '../../providers/passportDataProvider';
import { useSettingStore } from '../../stores/settingStore';
import { black } from '../../utils/colors';
import { impactLight } from '../../utils/haptic';
import { hasAnyValidRegisteredDocument } from '../../utils/proving/validateDocument';
import {
checkAndUpdateRegistrationStates,
hasAnyValidRegisteredDocument,
} from '../../utils/proving/validateDocument';

const SplashScreen: React.FC = ({}) => {
const navigation = useNavigation();
Expand All @@ -35,6 +41,19 @@ const SplashScreen: React.FC = ({}) => {
const loadDataAndDetermineNextScreen = async () => {
try {
await migrateFromLegacyStorage();

const needsMigration = await checkIfAnyDocumentsNeedMigration();
if (needsMigration) {
console.log(
'Documents need registration state migration, running...',
);
await checkAndUpdateRegistrationStates();
} else {
console.log(
'No documents need registration state migration, skipping...',
);
}

const hasValid = await hasAnyValidRegisteredDocument();
setNextScreen(hasValid ? 'Home' : 'Launch');
} catch (error) {
Expand Down
15 changes: 14 additions & 1 deletion app/src/screens/passport/PassportCameraScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import useUserStore from '../../stores/userStore';
import analytics from '../../utils/analytics';
import { black, slate400, slate800, white } from '../../utils/colors';
import { dinot } from '../../utils/fonts';
import { hasAnyValidRegisteredDocument } from '../../utils/proving/validateDocument';
import { checkScannedInfo, formatDateToYYMMDD } from '../../utils/utils';

interface PassportNFCScanScreen {}
Expand Down Expand Up @@ -113,9 +114,21 @@ const PassportCameraScreen: React.FC<PassportNFCScanScreen> = ({}) => {
},
[store, navigation],
);
const onCancelPress = useHapticNavigation('Launch', {
const navigateToLaunch = useHapticNavigation('Launch', {
action: 'cancel',
});
const navigateToHome = useHapticNavigation('Home', {
action: 'cancel',
});

const onCancelPress = async () => {
const hasValidDocument = await hasAnyValidRegisteredDocument();
if (hasValidDocument) {
navigateToHome();
} else {
navigateToLaunch();
}
};
Comment on lines +124 to +131
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Critical: Add error handling to prevent crashes

The async function needs error handling like the other screens to prevent app crashes if document validation fails.

  const onCancelPress = async () => {
+    try {
      const hasValidDocument = await hasAnyValidRegisteredDocument();
      if (hasValidDocument) {
        navigateToHome();
      } else {
        navigateToLaunch();
      }
+    } catch (error) {
+      console.error('Error checking document validation:', error);
+      navigateToLaunch();
+    }
  };
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const onCancelPress = async () => {
const hasValidDocument = await hasAnyValidRegisteredDocument();
if (hasValidDocument) {
navigateToHome();
} else {
navigateToLaunch();
}
};
const onCancelPress = async () => {
try {
const hasValidDocument = await hasAnyValidRegisteredDocument();
if (hasValidDocument) {
navigateToHome();
} else {
navigateToLaunch();
}
} catch (error) {
console.error('Error checking document validation:', error);
navigateToLaunch();
}
};
🤖 Prompt for AI Agents
In app/src/screens/passport/PassportCameraScreen.tsx around lines 124 to 131,
the async function onCancelPress lacks error handling which can cause app
crashes if hasAnyValidRegisteredDocument fails. Wrap the await call and
subsequent navigation logic in a try-catch block. In the catch block, handle or
log the error appropriately to prevent the app from crashing.


return (
<ExpandableBottomLayout.Layout backgroundColor={white}>
Expand Down
15 changes: 14 additions & 1 deletion app/src/screens/passport/PassportNFCScanScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ import {
} from '../../utils/haptic';
import { registerModalCallbacks } from '../../utils/modalCallbackRegistry';
import { parseScanResponse, scan } from '../../utils/nfcScanner';
import { hasAnyValidRegisteredDocument } from '../../utils/proving/validateDocument';

const { trackEvent } = analytics();

Expand Down Expand Up @@ -275,9 +276,21 @@ const PassportNFCScanScreen: React.FC<PassportNFCScanScreenProps> = ({}) => {
openErrorModal,
]);

const onCancelPress = useHapticNavigation('Launch', {
const navigateToLaunch = useHapticNavigation('Launch', {
action: 'cancel',
});
const navigateToHome = useHapticNavigation('Home', {
action: 'cancel',
});

const onCancelPress = async () => {
const hasValidDocument = await hasAnyValidRegisteredDocument();
if (hasValidDocument) {
navigateToHome();
} else {
navigateToLaunch();
}
};
Comment on lines +286 to +293
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

⚠️ Potential issue

Critical: Complete the error handling pattern across all screens

This is the final screen missing error handling. For consistency and robustness, apply the same error handling pattern used in the other screens.

  const onCancelPress = async () => {
+    try {
      const hasValidDocument = await hasAnyValidRegisteredDocument();
      if (hasValidDocument) {
        navigateToHome();
      } else {
        navigateToLaunch();
      }
+    } catch (error) {
+      console.error('Error checking document validation:', error);
+      navigateToLaunch();
+    }
  };

Consider creating the shared custom hook I mentioned earlier to eliminate code duplication and ensure consistent error handling across all screens.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const onCancelPress = async () => {
const hasValidDocument = await hasAnyValidRegisteredDocument();
if (hasValidDocument) {
navigateToHome();
} else {
navigateToLaunch();
}
};
const onCancelPress = async () => {
try {
const hasValidDocument = await hasAnyValidRegisteredDocument();
if (hasValidDocument) {
navigateToHome();
} else {
navigateToLaunch();
}
} catch (error) {
console.error('Error checking document validation:', error);
navigateToLaunch();
}
};
🤖 Prompt for AI Agents
In app/src/screens/passport/PassportNFCScanScreen.tsx around lines 286 to 293,
the onCancelPress function lacks error handling, unlike other screens. Wrap the
async call to hasAnyValidRegisteredDocument and the subsequent navigation calls
in a try-catch block. In the catch block, handle or log the error appropriately
to maintain consistency and robustness. Additionally, consider refactoring this
logic into a shared custom hook to avoid duplication and ensure uniform error
handling across all screens.


// eslint-disable-next-line @typescript-eslint/no-unused-vars
const _cancelScanIfRunning = useCallback(async () => {
Expand Down
15 changes: 14 additions & 1 deletion app/src/screens/passport/PassportNFCScanScreen.web.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,26 @@ import useHapticNavigation from '../../hooks/useHapticNavigation';
import NFC_IMAGE from '../../images/nfc.png';
import { ExpandableBottomLayout } from '../../layouts/ExpandableBottomLayout';
import { black, slate100, white } from '../../utils/colors';
import { hasAnyValidRegisteredDocument } from '../../utils/proving/validateDocument';

interface PassportNFCScanScreenProps {}

const PassportNFCScanScreen: React.FC<PassportNFCScanScreenProps> = ({}) => {
const onCancelPress = useHapticNavigation('Launch', {
const navigateToLaunch = useHapticNavigation('Launch', {
action: 'cancel',
});
const navigateToHome = useHapticNavigation('Home', {
action: 'cancel',
});

const onCancelPress = async () => {
const hasValidDocument = await hasAnyValidRegisteredDocument();
if (hasValidDocument) {
navigateToHome();
} else {
navigateToLaunch();
}
};

return (
<ExpandableBottomLayout.Layout backgroundColor={black}>
Expand Down
13 changes: 12 additions & 1 deletion app/src/screens/passport/UnsupportedPassportScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,23 @@ import { ExpandableBottomLayout } from '../../layouts/ExpandableBottomLayout';
import analytics from '../../utils/analytics';
import { black, white } from '../../utils/colors';
import { notificationError } from '../../utils/haptic';
import { hasAnyValidRegisteredDocument } from '../../utils/proving/validateDocument';
import { styles } from '../prove/ProofRequestStatusScreen';

const { flush: flushAnalytics } = analytics();

const UnsupportedPassportScreen: React.FC = () => {
const onPress = useHapticNavigation('Launch');
const navigateToLaunch = useHapticNavigation('Launch');
const navigateToHome = useHapticNavigation('Home');

const onPress = async () => {
const hasValidDocument = await hasAnyValidRegisteredDocument();
if (hasValidDocument) {
navigateToHome();
} else {
navigateToLaunch();
}
};
Comment on lines +26 to +33
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Add error handling for async document validation

The async function lacks error handling, which could cause the app to crash if hasAnyValidRegisteredDocument() throws an error.

  const onPress = async () => {
-    const hasValidDocument = await hasAnyValidRegisteredDocument();
-    if (hasValidDocument) {
-      navigateToHome();
-    } else {
-      navigateToLaunch();
-    }
+    try {
+      const hasValidDocument = await hasAnyValidRegisteredDocument();
+      if (hasValidDocument) {
+        navigateToHome();
+      } else {
+        navigateToLaunch();
+      }
+    } catch (error) {
+      console.error('Error checking document validation:', error);
+      // Fallback to Launch screen on error
+      navigateToLaunch();
+    }
  };
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const onPress = async () => {
const hasValidDocument = await hasAnyValidRegisteredDocument();
if (hasValidDocument) {
navigateToHome();
} else {
navigateToLaunch();
}
};
const onPress = async () => {
try {
const hasValidDocument = await hasAnyValidRegisteredDocument();
if (hasValidDocument) {
navigateToHome();
} else {
navigateToLaunch();
}
} catch (error) {
console.error('Error checking document validation:', error);
// Fallback to Launch screen on error
navigateToLaunch();
}
};
🤖 Prompt for AI Agents
In app/src/screens/passport/UnsupportedPassportScreen.tsx around lines 26 to 33,
the async function onPress calls hasAnyValidRegisteredDocument() without error
handling, risking app crashes if the promise rejects. Wrap the await call in a
try-catch block to catch any errors, and handle them gracefully, such as logging
the error and providing fallback navigation or user feedback.

useEffect(() => {
notificationError();
// error screen, flush analytics
Expand Down
13 changes: 12 additions & 1 deletion app/src/screens/recovery/PassportDataNotFoundScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,22 @@ import useHapticNavigation from '../../hooks/useHapticNavigation';
import { ExpandableBottomLayout } from '../../layouts/ExpandableBottomLayout';
import analytics from '../../utils/analytics';
import { black, slate200, white } from '../../utils/colors';
import { hasAnyValidRegisteredDocument } from '../../utils/proving/validateDocument';

const { flush: flushAnalytics } = analytics();

const PassportDataNotFound: React.FC = () => {
const onPress = useHapticNavigation('Launch');
const navigateToLaunch = useHapticNavigation('Launch');
const navigateToHome = useHapticNavigation('Home');

const onPress = async () => {
const hasValidDocument = await hasAnyValidRegisteredDocument();
if (hasValidDocument) {
navigateToHome();
} else {
navigateToLaunch();
}
};

// error screen, flush analytics
useEffect(() => {
Expand Down
27 changes: 27 additions & 0 deletions app/src/utils/proving/provingMachine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import { unsafe_getPrivateKey } from '../../providers/authProvider';
import {
clearPassportData,
loadSelectedDocument,
markCurrentDocumentAsRegistered,
reStorePassportDataWithRightCSCA,
} from '../../providers/passportDataProvider';
import { useProtocolStore } from '../../stores/protocolStore';
Expand Down Expand Up @@ -237,6 +238,20 @@ export const useProvingStore = create<ProvingState>((set, get) => {
trackEvent(ProofEvents.PROOF_COMPLETED, {
circuitType: get().circuitType,
});

// Mark document as registered onChain
if (get().circuitType === 'register') {
(async () => {
try {
await markCurrentDocumentAsRegistered();
console.log('Document marked as registered on-chain');
} catch (error) {
//This will be checked and updated when the app launches the next time
console.error('Error marking document as registered:', error);
}
})();
}

if (get().circuitType !== 'disclose' && navigationRef.isReady()) {
setTimeout(() => {
navigationRef.navigate('AccountVerifiedSuccess');
Expand Down Expand Up @@ -709,6 +724,18 @@ export const useProvingStore = create<ProvingState>((set, get) => {
);
if (isRegistered) {
reStorePassportDataWithRightCSCA(passportData, csca as string);

// Mark document as registered since its already onChain
(async () => {
try {
await markCurrentDocumentAsRegistered();
console.log('Document marked as registered (already on-chain)');
} catch (error) {
//it will be checked and marked as registered during next app launch
console.error('Error marking document as registered:', error);
}
})();

trackEvent(ProofEvents.ALREADY_REGISTERED);
actor!.send({ type: 'ALREADY_REGISTERED' });
return;
Expand Down
Loading
Loading