diff --git a/app/src/screens/AppScreen.tsx b/app/src/screens/AppScreen.tsx index 037bbee72..fbab190a3 100644 --- a/app/src/screens/AppScreen.tsx +++ b/app/src/screens/AppScreen.tsx @@ -1,7 +1,6 @@ import React from 'react'; import { ScrollView, Text, YStack } from 'tamagui'; import useNavigationStore from '../stores/navigationStore'; -import { createAppType } from '../../../common/src/utils/appType'; import { XStack } from 'tamagui'; import CustomButton from '../components/CustomButton'; import { BadgeCheck, Binary, List, QrCode, Smartphone } from '@tamagui/lucide-icons'; @@ -9,6 +8,8 @@ import { bgGreen, textBlack } from '../utils/colors'; import useUserStore from '../stores/userStore'; import { Platform } from 'react-native'; import { NativeModules } from 'react-native'; +import { AppType } from '../../../sdk/src'; +import { reconstructAppType } from '../../../common/src/utils/appType'; interface AppScreenProps { setSheetAppListOpen: (value: boolean) => void; @@ -73,16 +74,24 @@ const AppScreen: React.FC = ({ setSheetAppListOpen, setSheetRegi const handleQRCodeScan = (result: string) => { try { console.log(result); - const app = createAppType(JSON.parse(result)); - console.log(app); + const parsedJson = JSON.parse(result); + const app: AppType = reconstructAppType(parsedJson); setSelectedApp(app); setSelectedTab("prove"); + toast.show('✅', { + message: "QR code scanned", + customData: { + type: "success", + }, + }) } catch (error) { console.error('Error parsing QR code result:', error); - toast.show('Error', { - message: 'Invalid QR code format', - type: 'error', - }); + toast.show('❌', { + message: "Error parsing QR code", + customData: { + type: "error", + }, + }) } }; @@ -167,11 +176,6 @@ const AppScreen: React.FC = ({ setSheetAppListOpen, setSheetRegi }} Icon={} /> - setSheetAppListOpen(true) - : - () => setSheetRegisterIsOpen(true)} Icon={} /> ); diff --git a/app/src/screens/ProveScreen.tsx b/app/src/screens/ProveScreen.tsx index 5af737c87..d145fd994 100644 --- a/app/src/screens/ProveScreen.tsx +++ b/app/src/screens/ProveScreen.tsx @@ -11,6 +11,7 @@ import { generateCircuitInputsProve } from '../../../common/src/utils/generateIn import { revealBitmapFromAttributes } from '../../../common/src/utils/revealBitmap'; import { formatProof, generateProof } from '../utils/prover'; import io, { Socket } from 'socket.io-client'; +import { getCircuitName, getSignatureAlgorithm } from '../../../common/src/utils/handleCertificate'; interface ProveScreenProps { setSheetRegisterIsOpen: (value: boolean) => void; @@ -26,7 +27,9 @@ const ProveScreen: React.FC = ({ setSheetRegisterIsOpen }) => } = useNavigationStore() const { - setProofVerificationResult + setProofVerificationResult, + registered, + passportData, } = useUserStore() const [socket, setSocket] = useState(null); @@ -87,9 +90,9 @@ const ProveScreen: React.FC = ({ setSheetRegisterIsOpen }) => } await waitForSocketConnection(socket); - setIsConnecting(false); - socket.emit('proof_generation_start', { sessionId: selectedApp.userId }); + + socket.emit('proof_generation_start', { sessionId: selectedApp.sessionId }); const inputs = generateCircuitInputsProve( passportData, 64, 32, @@ -98,21 +101,16 @@ const ProveScreen: React.FC = ({ setSheetRegisterIsOpen }) => disclosureOptions?.older_than ?? DEFAULT_MAJORITY, selectedApp.userId ); - + const { signatureAlgorithm, hashFunction } = getSignatureAlgorithm(passportData.dsc as string); + const circuitName = getCircuitName(selectedApp.circuit, signatureAlgorithm, hashFunction); const rawDscProof = await generateProof( - selectedApp.circuit, + circuitName, inputs, ); const dscProof = formatProof(rawDscProof); - // Send the proof via WebSocket - const response = { - dsc: passportData.dsc, - dscProof: dscProof - }; - + const response = { dsc: passportData.dsc, dscProof: dscProof, circuit: selectedApp.circuit } console.log("response", response); - - socket.emit('proof_generated', { sessionId: selectedApp.userId, proof: response }); + socket.emit('proof_generated', { sessionId: selectedApp.sessionId, proof: response }); } catch (error) { console.error('Error in handleProve:', error); @@ -122,10 +120,7 @@ const ProveScreen: React.FC = ({ setSheetRegisterIsOpen }) => } }; - const { - registered, - passportData, - } = useUserStore(); + const disclosureFieldsToText = (key: string, value: string = "") => { diff --git a/app/src/utils/prover.ts b/app/src/utils/prover.ts index 3c9966ac1..fb194d820 100644 --- a/app/src/utils/prover.ts +++ b/app/src/utils/prover.ts @@ -50,7 +50,7 @@ export const generateProof = async ( } }; -export const formatProof = (rawProof: any) => { +export const formatProof = (rawProof: any): any => { return { proof: { pi_a: [ diff --git a/common/src/utils/appType.ts b/common/src/utils/appType.ts index 2eefff4c9..c9722f622 100644 --- a/common/src/utils/appType.ts +++ b/common/src/utils/appType.ts @@ -14,8 +14,6 @@ export interface ArgumentsProve { older_than?: string, nationality?: string, }, - scope: string, - user_identifier: string } export interface ArgumentsRegister { @@ -27,8 +25,82 @@ export interface ArgumentsDisclose { older_than?: string, nationality?: string, }, - scope: string, - user_identifier: string, merkle_root: string, merkletree_size: string, -} \ No newline at end of file +} + +export function reconstructAppType(json: any): AppType { + if (typeof json !== 'object' || json === null) { + throw new Error('Input must be a non-null object'); + } + + if (!json.name || typeof json.name !== 'string') { + throw new Error('Invalid or missing name'); + } + + if (!json.scope || typeof json.scope !== 'string') { + throw new Error('Invalid or missing scope'); + } + + if (!json.userId || typeof json.userId !== 'string') { + throw new Error('Invalid or missing userId'); + } + + if (!json.sessionId || typeof json.sessionId !== 'string') { + throw new Error('Invalid or missing sessionId'); + } + + if (!json.circuit || !['prove', 'register', 'disclose'].includes(json.circuit)) { + throw new Error('Invalid or missing circuit'); + } + + if (!json.arguments || typeof json.arguments !== 'object') { + throw new Error('Invalid or missing arguments'); + } + + let circuitArgs: ArgumentsProve | ArgumentsRegister | ArgumentsDisclose; + + switch (json.circuit) { + case 'prove': + case 'disclose': + if (!json.arguments.disclosureOptions || typeof json.arguments.disclosureOptions !== 'object') { + throw new Error('Invalid or missing disclosureOptions for prove/disclose'); + } + circuitArgs = { + disclosureOptions: { + older_than: json.arguments.disclosureOptions.older_than, + nationality: json.arguments.disclosureOptions.nationality, + }, + }; + if (json.circuit === 'disclose') { + if (!json.arguments.merkle_root || typeof json.arguments.merkle_root !== 'string') { + throw new Error('Invalid or missing merkle_root for disclose'); + } + if (!json.arguments.merkletree_size || typeof json.arguments.merkletree_size !== 'string') { + throw new Error('Invalid or missing merkletree_size for disclose'); + } + (circuitArgs as ArgumentsDisclose).merkle_root = json.arguments.merkle_root; + (circuitArgs as ArgumentsDisclose).merkletree_size = json.arguments.merkletree_size; + } + break; + case 'register': + if (!json.arguments.attestation_id || typeof json.arguments.attestation_id !== 'string') { + throw new Error('Invalid or missing attestation_id for register'); + } + circuitArgs = { + attestation_id: json.arguments.attestation_id, + }; + break; + default: + throw new Error('Unexpected circuit type'); + } + + return { + name: json.name, + scope: json.scope, + userId: json.userId, + sessionId: json.sessionId, + circuit: json.circuit as CircuitName, + arguments: circuitArgs, + }; +}