mirror of
https://github.com/selfxyz/self.git
synced 2026-04-05 03:00:53 -04:00
Feat: Show error code in SDK (#500)
* feat: emit `error_code` and `reason` in app * feat: add `onError` in sdk * feat: Display reason in app * lint & fmt * feat: add scrollview in ProofRequestStatusScreen for long reasons
This commit is contained in:
@@ -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';
|
||||
@@ -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');
|
||||
|
||||
@@ -69,6 +70,7 @@ const SuccessScreen: React.FC = () => {
|
||||
<Info
|
||||
status={disclosureStatus}
|
||||
appName={appName === '' ? 'The app' : appName}
|
||||
reason={discloseError?.reason ?? undefined}
|
||||
/>
|
||||
</View>
|
||||
<PrimaryButton
|
||||
@@ -109,9 +111,11 @@ function getTitle(status: ProofStatusEnum) {
|
||||
function Info({
|
||||
status,
|
||||
appName,
|
||||
reason,
|
||||
}: {
|
||||
status: ProofStatusEnum;
|
||||
appName: string;
|
||||
reason?: string;
|
||||
}) {
|
||||
if (status === 'success') {
|
||||
return (
|
||||
@@ -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 (
|
||||
|
||||
@@ -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');
|
||||
|
||||
@@ -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>({
|
||||
@@ -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,
|
||||
@@ -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,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
@@ -28,6 +34,7 @@ interface IProofContext {
|
||||
const defaults: IProofContext = {
|
||||
registrationStatus: ProofStatusEnum.PENDING,
|
||||
disclosureStatus: ProofStatusEnum.PENDING,
|
||||
discloseError: undefined,
|
||||
selectedApp: {
|
||||
appName: '',
|
||||
logoBase64: '',
|
||||
@@ -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;
|
||||
|
||||
/*
|
||||
@@ -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,
|
||||
);
|
||||
@@ -75,6 +86,7 @@ export function ProofProvider({ children }: PropsWithChildren<{}>) {
|
||||
return;
|
||||
}
|
||||
setRegistrationStatus(ProofStatusEnum.PENDING);
|
||||
setDiscloseError(undefined);
|
||||
setSelectedAppInternal(app);
|
||||
}, []);
|
||||
|
||||
@@ -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;
|
||||
@@ -102,6 +118,7 @@ export function ProofProvider({ children }: PropsWithChildren<{}>) {
|
||||
() => ({
|
||||
registrationStatus,
|
||||
disclosureStatus,
|
||||
discloseError,
|
||||
selectedApp,
|
||||
setSelectedApp,
|
||||
cleanSelfApp,
|
||||
@@ -110,8 +127,10 @@ export function ProofProvider({ children }: PropsWithChildren<{}>) {
|
||||
[
|
||||
registrationStatus,
|
||||
disclosureStatus,
|
||||
discloseError,
|
||||
selectedApp,
|
||||
setSelectedApp,
|
||||
setDiscloseError,
|
||||
cleanSelfApp,
|
||||
resetProof,
|
||||
],
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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) {
|
||||
|
||||
@@ -10,6 +10,7 @@ import {
|
||||
} from '../../../../common/src/constants/constants';
|
||||
import { EndpointType } from '../../../../common/src/utils/appType';
|
||||
import {
|
||||
DiscloseError,
|
||||
ProofStatusEnum,
|
||||
globalSetDisclosureStatus,
|
||||
globalSetRegistrationStatus,
|
||||
@@ -67,7 +68,7 @@ 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,
|
||||
@@ -75,7 +76,11 @@ export async function sendPayload(
|
||||
};
|
||||
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);
|
||||
@@ -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();
|
||||
@@ -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 => {
|
||||
|
||||
Reference in New Issue
Block a user