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
38 changes: 31 additions & 7 deletions app/src/screens/ProveFlow/ProofRequestStatusScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React, { useEffect } from 'react';
import { StatusBar, StyleSheet, View } from 'react-native';

import LottieView from 'lottie-react-native';
import { Spinner } from 'tamagui';
import { ScrollView, Spinner } from 'tamagui';

import loadingAnimation from '../../assets/animations/loading/misc.json';
import failAnimation from '../../assets/animations/proof_failed.json';
Expand All @@ -23,7 +23,8 @@ import {
} from '../../utils/haptic';

const SuccessScreen: React.FC = () => {
const { selectedApp, disclosureStatus, cleanSelfApp } = useProofInfo();
const { selectedApp, disclosureStatus, discloseError, cleanSelfApp } =
useProofInfo();
const appName = selectedApp?.appName;
const goHome = useHapticNavigation('Home');

Expand Down Expand Up @@ -69,6 +70,7 @@ const SuccessScreen: React.FC = () => {
<Info
status={disclosureStatus}
appName={appName === '' ? 'The app' : appName}
reason={discloseError?.reason ?? undefined}
/>
</View>
<PrimaryButton
Expand Down Expand Up @@ -109,9 +111,11 @@ function getTitle(status: ProofStatusEnum) {
function Info({
status,
appName,
reason,
}: {
status: ProofStatusEnum;
appName: string;
reason?: string;
}) {
if (status === 'success') {
return (
Expand All @@ -122,11 +126,31 @@ function Info({
);
} else if (status === 'failure' || status === 'error') {
return (
<Description>
Unable to prove your identity to{' '}
<BodyText style={typography.strong}>{appName}</BodyText>
{status === 'error' && '. Due to technical issues.'}
</Description>
<View style={{ gap: 8 }}>
<Description>
Unable to prove your identity to{' '}
<BodyText style={typography.strong}>{appName}</BodyText>
{status === 'error' && '. Due to technical issues.'}
</Description>
{status === 'failure' && reason && (
<>
<Description>
<BodyText style={[typography.strong, { fontSize: 14 }]}>
Reason:
</BodyText>
</Description>
<View style={{ maxHeight: 60 }}>
<ScrollView showsVerticalScrollIndicator={true}>
<Description>
<BodyText style={[typography.strong, { fontSize: 14 }]}>
{reason}
</BodyText>
</Description>
</ScrollView>
</View>
</>
)}
</View>
);
} else {
return (
Expand Down
4 changes: 3 additions & 1 deletion app/src/screens/ProveFlow/ProveScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,9 @@ const ProveScreen: React.FC = () => {
);
handleProofResult(
currentApp.sessionId,
status === ProofStatusEnum.SUCCESS,
status?.status === ProofStatusEnum.SUCCESS,
status?.error_code,
status?.reason,
);
} catch (e) {
console.log('Error in verification process');
Expand Down
18 changes: 16 additions & 2 deletions app/src/stores/appProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,12 @@ interface IAppContext {
* @param sessionId - The session ID from the scanned QR code.
* @param success - Whether the proof was verified successfully.
*/
handleProofResult: (sessionId: string, success: boolean) => void;
handleProofResult: (
sessionId: string,
success: boolean,
error_code?: string,
reason?: string,
) => void;
}

const AppContext = createContext<IAppContext>({
Expand Down Expand Up @@ -120,7 +125,12 @@ export const AppProvider: React.FC<{ children: React.ReactNode }> = ({
}
};

const handleProofResult = (sessionId: string, proof_verified: boolean) => {
const handleProofResult = (
sessionId: string,
proof_verified: boolean,
error_code?: string,
reason?: string,
) => {
console.log(
'[AppProvider] handleProofResult called with sessionId:',
sessionId,
Expand All @@ -143,11 +153,15 @@ export const AppProvider: React.FC<{ children: React.ReactNode }> = ({
'[AppProvider] Emitting proof_generation_failed event with data:',
{
session_id: sessionId,
error_code,
reason,
},
);

socketRef.current.emit('proof_generation_failed', {
session_id: sessionId,
error_code,
reason,
});
}
};
Expand Down
23 changes: 21 additions & 2 deletions app/src/stores/proofProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,15 @@ export enum ProofStatusEnum {
ERROR = 'error',
}

export type DiscloseError = {
error_code?: string;
reason?: string;
};

interface IProofContext {
registrationStatus: ProofStatusEnum;
disclosureStatus: ProofStatusEnum;
discloseError: DiscloseError | undefined;
selectedApp: SelfApp;
setSelectedApp: (app: SelfApp) => void;
cleanSelfApp: () => void;
Expand All @@ -28,6 +34,7 @@ interface IProofContext {
const defaults: IProofContext = {
registrationStatus: ProofStatusEnum.PENDING,
disclosureStatus: ProofStatusEnum.PENDING,
discloseError: undefined,
selectedApp: {
appName: '',
logoBase64: '',
Expand All @@ -52,7 +59,7 @@ export let globalSetRegistrationStatus:
| ((status: ProofStatusEnum) => void)
| null = null;
export let globalSetDisclosureStatus:
| ((status: ProofStatusEnum) => void)
| ((status: ProofStatusEnum, error?: DiscloseError) => void)
| null = null;

/*
Expand All @@ -66,6 +73,10 @@ export function ProofProvider({ children }: PropsWithChildren<{}>) {
ProofStatusEnum.PENDING,
);

const [discloseError, setDiscloseError] = useState<DiscloseError | undefined>(
undefined,
);

const [selectedApp, setSelectedAppInternal] = useState<SelfApp>(
defaults.selectedApp,
);
Expand All @@ -75,6 +86,7 @@ export function ProofProvider({ children }: PropsWithChildren<{}>) {
return;
}
setRegistrationStatus(ProofStatusEnum.PENDING);
setDiscloseError(undefined);
setSelectedAppInternal(app);
}, []);

Expand All @@ -87,11 +99,15 @@ export function ProofProvider({ children }: PropsWithChildren<{}>) {
const resetProof = useCallback(() => {
setRegistrationStatus(ProofStatusEnum.PENDING);
setDisclosureStatus(ProofStatusEnum.PENDING);
setDiscloseError(undefined);
}, []);

useEffect(() => {
globalSetRegistrationStatus = setRegistrationStatus;
globalSetDisclosureStatus = setDisclosureStatus;
globalSetDisclosureStatus = (status, error) => {
setDisclosureStatus(status);
setDiscloseError(error);
};
return () => {
globalSetRegistrationStatus = null;
globalSetDisclosureStatus = null;
Expand All @@ -102,6 +118,7 @@ export function ProofProvider({ children }: PropsWithChildren<{}>) {
() => ({
registrationStatus,
disclosureStatus,
discloseError,
selectedApp,
setSelectedApp,
cleanSelfApp,
Expand All @@ -110,8 +127,10 @@ export function ProofProvider({ children }: PropsWithChildren<{}>) {
[
registrationStatus,
disclosureStatus,
discloseError,
selectedApp,
setSelectedApp,
setDiscloseError,
cleanSelfApp,
resetProof,
],
Expand Down
6 changes: 3 additions & 3 deletions app/src/utils/proving/payload.ts
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ async function checkIdPassportDscIsInTree(
circuitDNSMapping,
endpointType,
);
if (dscStatus !== ProofStatusEnum.SUCCESS) {
if (dscStatus.status !== ProofStatusEnum.SUCCESS) {
console.log('DSC proof failed');
return false;
}
Expand All @@ -140,9 +140,9 @@ export async function sendDscPayload(
passportData: PassportData,
circuitDNSMapping: Record<string, string>,
endpointType: EndpointType,
): Promise<ProofStatusEnum | false> {
): Promise<{ status: ProofStatusEnum; error_code?: string; reason?: string }> {
if (!passportData) {
return false;
return { status: ProofStatusEnum.FAILURE };
}
// const isSupported = checkPassportSupported(passportData);
// if (!isSupported) {
Expand Down
18 changes: 13 additions & 5 deletions app/src/utils/proving/tee.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
} from '../../../../common/src/constants/constants';
import { EndpointType } from '../../../../common/src/utils/appType';
import {
DiscloseError,
ProofStatusEnum,
globalSetDisclosureStatus,
globalSetRegistrationStatus,
Expand Down Expand Up @@ -67,15 +68,19 @@ export async function sendPayload(
updateGlobalOnFailure?: boolean;
flow?: 'registration' | 'disclosure';
},
): Promise<ProofStatusEnum> {
): Promise<{ status: ProofStatusEnum; error_code?: string; reason?: string }> {
const opts = {
updateGlobalOnSuccess: true,
updateGlobalOnFailure: true,
...options,
};
return new Promise(resolve => {
let finalized = false;
function finalize(status: ProofStatusEnum) {
function finalize(
status: ProofStatusEnum,
error_code?: string,
reason?: string,
) {
if (!finalized) {
finalized = true;
clearTimeout(timer);
Expand All @@ -84,12 +89,15 @@ export async function sendPayload(
(status !== ProofStatusEnum.SUCCESS && opts.updateGlobalOnFailure)
) {
if (options?.flow === 'disclosure') {
globalSetDisclosureStatus && globalSetDisclosureStatus(status);
let discloseError: DiscloseError | undefined =
error_code || reason ? { error_code, reason } : undefined;
globalSetDisclosureStatus &&
globalSetDisclosureStatus(status, discloseError);
} else {
globalSetRegistrationStatus && globalSetRegistrationStatus(status);
}
}
resolve(status);
resolve({ status, error_code, reason });
}
}
const uuid = v4();
Expand Down Expand Up @@ -201,7 +209,7 @@ export async function sendPayload(
if (ws.readyState === WebSocket.OPEN) {
ws.close();
}
finalize(ProofStatusEnum.FAILURE);
finalize(ProofStatusEnum.FAILURE, data.error_code, data.reason);
}
});
socket.on('disconnect', reason => {
Expand Down
5 changes: 4 additions & 1 deletion sdk/qrcode/SelfQRcode.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { getUniversalLink, SelfApp, SelfAppBuilder } from '../../common/src/util
interface SelfQRcodeProps {
selfApp: SelfApp;
onSuccess: () => void;
onError: (data: {error_code?: string, reason?: string}) => void;
type?: 'websocket' | 'deeplink';
websocketUrl?: string;
size?: number;
Expand All @@ -37,6 +38,7 @@ const SelfQRcodeWrapper = (props: SelfQRcodeProps) => {
const SelfQRcode = ({
selfApp,
onSuccess,
onError,
type = 'websocket',
websocketUrl = WS_DB_RELAYER,
size = 300,
Expand All @@ -58,7 +60,8 @@ const SelfQRcode = ({
},
type,
setProofStep,
onSuccess
onSuccess,
onError,
);
}

Expand Down
10 changes: 7 additions & 3 deletions sdk/qrcode/utils/websocket.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ const handleWebSocketMessage =
selfApp: SelfApp,
type: 'websocket' | 'deeplink',
setProofStep: (step: number) => void,
onSuccess: () => void
onSuccess: () => void,
onError: (data: {error_code?: string, reason?: string}) => void
) =>
async (data: any) => {
console.log('[WebSocket] Received mobile status:', data.status, 'for session:', sessionId);
Expand All @@ -55,6 +56,7 @@ const handleWebSocketMessage =
case 'proof_generation_failed':
console.log('[WebSocket] Proof generation failed.');
setProofStep(QRcodeSteps.PROOF_GENERATION_FAILED);
onError(data);
break;
case 'proof_verified':
console.log('[WebSocket] Proof verified.');
Expand All @@ -73,7 +75,8 @@ export function initWebSocket(
selfApp: SelfApp,
type: 'websocket' | 'deeplink',
setProofStep: (step: number) => void,
onSuccess: () => void
onSuccess: () => void,
onError: (data: {error_code?: string, reason?: string}) => void,
) {
const sessionId = selfApp.sessionId;
console.log(`[WebSocket] Initializing WebSocket connection for sessionId: ${sessionId}`);
Expand All @@ -95,7 +98,8 @@ export function initWebSocket(
selfApp,
type,
setProofStep,
onSuccess
onSuccess,
onError
)(data);
});

Expand Down