diff --git a/app/src/navigation/document.ts b/app/src/navigation/document.ts index 72a6eb548..8de50f32b 100644 --- a/app/src/navigation/document.ts +++ b/app/src/navigation/document.ts @@ -62,7 +62,8 @@ const documentScreens = { headerShown: false, } as NativeStackNavigationOptions, initialParams: { - passportData: null, + countryCode: null, + documentCategory: null, }, }, DocumentNFCMethodSelection: { diff --git a/app/src/providers/selfClientProvider.tsx b/app/src/providers/selfClientProvider.tsx index 480a8ddd0..768688933 100644 --- a/app/src/providers/selfClientProvider.tsx +++ b/app/src/providers/selfClientProvider.tsx @@ -132,10 +132,11 @@ export const SelfClientProvider = ({ children }: PropsWithChildren) => { addListener( SdkEvents.PROVING_PASSPORT_NOT_SUPPORTED, - ({ passportData }) => { + ({ countryCode, documentCategory }) => { if (navigationRef.isReady()) { navigationRef.navigate('UnsupportedDocument', { - passportData, + countryCode, + documentCategory, } as any); } }, diff --git a/app/src/screens/document/UnsupportedDocumentScreen.tsx b/app/src/screens/document/UnsupportedDocumentScreen.tsx index 69eced262..c0157dc31 100644 --- a/app/src/screens/document/UnsupportedDocumentScreen.tsx +++ b/app/src/screens/document/UnsupportedDocumentScreen.tsx @@ -10,7 +10,7 @@ import { XStack, YStack } from 'tamagui'; import type { RouteProp } from '@react-navigation/native'; import { countryCodes } from '@selfxyz/common/constants'; -import type { PassportData } from '@selfxyz/common/types'; +import type { DocumentCategory } from '@selfxyz/common/types'; import { hasAnyValidRegisteredDocument, useSelfClient, @@ -39,7 +39,8 @@ type CountryFlagsRecord = Record; type UnsupportedDocumentScreenRouteProp = RouteProp< { UnsupportedDocument: { - passportData: PassportData | null; + countryCode: string | null; + documentCategory: DocumentCategory | null; }; }, 'UnsupportedDocument' @@ -55,11 +56,10 @@ const UnsupportedDocumentScreen: React.FC = ({ const selfClient = useSelfClient(); const navigateToLaunch = useHapticNavigation('Launch'); const navigateToHome = useHapticNavigation('Home'); - const passportData = route.params?.passportData; const { countryName, country2AlphaCode, documentTypeText } = useMemo(() => { try { - const countryCode = passportData?.passportMetadata?.countryCode; + const countryCode = route.params?.countryCode; if (countryCode) { // Handle Germany corner case where country code is "D<<" instead of "DEU" let normalizedCountryCode = countryCode; @@ -74,7 +74,7 @@ const UnsupportedDocumentScreen: React.FC = ({ const name = countryCodes[normalizedCountryCode as keyof typeof countryCodes]; const docType = - passportData?.documentCategory === 'id_card' + route.params?.documentCategory === 'id_card' ? 'ID Cards' : 'Passports'; return { @@ -87,13 +87,13 @@ const UnsupportedDocumentScreen: React.FC = ({ console.error('Error extracting country from passport data:', error); } const docType = - passportData?.documentCategory === 'id_card' ? 'ID Cards' : 'Passports'; + route.params?.documentCategory === 'id_card' ? 'ID Cards' : 'Passports'; return { countryName: 'Unknown', country2AlphaCode: 'Unknown', documentTypeText: docType, }; - }, [passportData]); + }, [route.params?.documentCategory, route.params?.countryCode]); // Get country flag component dynamically const getCountryFlag = (code: string) => { @@ -127,7 +127,7 @@ const UnsupportedDocumentScreen: React.FC = ({ countryName, countryCode: country2AlphaCode !== 'Unknown' ? country2AlphaCode : undefined, - documentCategory: passportData?.documentCategory, + documentCategory: route.params?.documentCategory ?? '', }); } catch (error) { console.error('Failed to open email client:', error); diff --git a/app/src/utils/proving/provingMachine.ts b/app/src/utils/proving/provingMachine.ts index 99048b622..834c6f171 100644 --- a/app/src/utils/proving/provingMachine.ts +++ b/app/src/utils/proving/provingMachine.ts @@ -1096,8 +1096,13 @@ export const useProvingStore = create((set, get) => { }, _handlePassportNotSupported: (selfClient: SelfClient) => { + const passportData = get().passportData; + const countryCode = passportData?.passportMetadata?.countryCode; + const documentCategory = passportData?.documentCategory; + selfClient.emit(SdkEvents.PROVING_PASSPORT_NOT_SUPPORTED, { - passportData: get().passportData as PassportData, + countryCode: countryCode ?? null, + documentCategory: documentCategory ?? null, }); }, diff --git a/app/tests/utils/proving/provingMachine.test.ts b/app/tests/utils/proving/provingMachine.test.ts index a930d224e..4c38c03bd 100644 --- a/app/tests/utils/proving/provingMachine.test.ts +++ b/app/tests/utils/proving/provingMachine.test.ts @@ -67,6 +67,34 @@ describe('events', () => { eContent: [1, 2, 3], signedAttr: [1, 2, 3], encryptedDigest: [1, 2, 3], + passportMetadata: { + countryCode: 'test', + }, + documentCategory: 'passport', + } as PassportData; + + const selfClient = { + emit: emitMock, + } as unknown as SelfClient; + + await act(async () => { + useProvingStore.setState({ passportData: mockPassportData }); + useProvingStore.getState()._handlePassportNotSupported(selfClient); + }); + + expect(emitMock).toHaveBeenCalledWith( + SdkEvents.PROVING_PASSPORT_NOT_SUPPORTED, + { + countryCode: 'test', + documentCategory: 'passport', + }, + ); + }); + + it('emits PROVING_MACHINE_PASSPORT_NOT_SUPPORTED with no passport data', async () => { + const emitMock = jest.fn(); + const mockPassportData = { + passportMetadata: {}, } as PassportData; const selfClient = { @@ -81,7 +109,8 @@ describe('events', () => { expect(emitMock).toHaveBeenCalledWith( SdkEvents.PROVING_PASSPORT_NOT_SUPPORTED, { - passportData: mockPassportData, + countryCode: null, + documentCategory: null, }, ); }); diff --git a/packages/mobile-sdk-alpha/src/types/events.ts b/packages/mobile-sdk-alpha/src/types/events.ts index 30175dd5d..91ddc9cd6 100644 --- a/packages/mobile-sdk-alpha/src/types/events.ts +++ b/packages/mobile-sdk-alpha/src/types/events.ts @@ -2,7 +2,9 @@ // SPDX-License-Identifier: BUSL-1.1 // NOTE: Converts to Apache-2.0 on 2029-06-11 per LICENSE. -import type { PassportData, Progress } from './public'; +import { DocumentCategory } from '@selfxyz/common/types'; + +import type { Progress } from './public'; export enum SdkEvents { ERROR = 'ERROR', @@ -23,7 +25,8 @@ export interface SDKEventMap { hasValidDocument: boolean; }; [SdkEvents.PROVING_PASSPORT_NOT_SUPPORTED]: { - passportData: PassportData; + countryCode: string | null; + documentCategory: DocumentCategory | null; }; [SdkEvents.PROVING_ACCOUNT_RECOVERY_REQUIRED]: undefined; diff --git a/packages/mobile-sdk-alpha/tests/client.test.ts b/packages/mobile-sdk-alpha/tests/client.test.ts index 2b091ad28..075575473 100644 --- a/packages/mobile-sdk-alpha/tests/client.test.ts +++ b/packages/mobile-sdk-alpha/tests/client.test.ts @@ -6,7 +6,7 @@ import { describe, expect, it, vi } from 'vitest'; import type { CryptoAdapter, DocumentsAdapter, NetworkAdapter, ScannerAdapter } from '../src'; import { createListenersMap, createSelfClient, SdkEvents } from '../src/index'; -import { AuthAdapter, PassportData } from '../src/types/public'; +import { AuthAdapter } from '../src/types/public'; describe('createSelfClient', () => { // Test eager validation during client creation @@ -111,7 +111,7 @@ describe('createSelfClient', () => { listeners: listeners.map, }); - client.emit(SdkEvents.PROVING_PASSPORT_NOT_SUPPORTED, { passportData: { mrz: 'test' } as PassportData }); + client.emit(SdkEvents.PROVING_PASSPORT_NOT_SUPPORTED, { countryCode: 'test', documentCategory: 'passport' }); client.emit(SdkEvents.PROVING_ACCOUNT_RECOVERY_REQUIRED); client.emit(SdkEvents.PROVING_REGISTER_ERROR_OR_FAILURE, { hasValidDocument: true }); @@ -120,10 +120,10 @@ describe('createSelfClient', () => { expect(anotherAccountRecoveryChoiceListener).toHaveBeenCalledTimes(1); expect(anotherAccountRecoveryChoiceListener).toHaveBeenCalledWith(undefined); - expect(passportNotSupportedListener).toHaveBeenCalledWith({ passportData: { mrz: 'test' } }); + expect(passportNotSupportedListener).toHaveBeenCalledWith({ countryCode: 'test', documentCategory: 'passport' }); expect(passportNotSupportedListener).toHaveBeenCalledTimes(1); - client.emit(SdkEvents.PROVING_PASSPORT_NOT_SUPPORTED, { passportData: { mrz: 'test' } as PassportData }); + client.emit(SdkEvents.PROVING_PASSPORT_NOT_SUPPORTED, { countryCode: 'test', documentCategory: 'passport' }); client.emit(SdkEvents.PROVING_ACCOUNT_RECOVERY_REQUIRED); client.emit(SdkEvents.PROVING_REGISTER_ERROR_OR_FAILURE, { hasValidDocument: true });