mirror of
https://github.com/selfxyz/self.git
synced 2026-04-05 03:00:53 -04:00
Proving (#127)
Co-authored-by: turnoffthiscomputer <colin.remi07@gmail.com> Co-authored-by: thomas-senechal <thomas.senechal@pm.me>
This commit is contained in:
@@ -2,17 +2,13 @@ import React from 'react';
|
||||
|
||||
import { XStack, YStack } from 'tamagui';
|
||||
|
||||
import {
|
||||
DisclosureAttributes,
|
||||
DisclosureOption,
|
||||
DisclosureOptions,
|
||||
} from '../../../common/src/utils/appType';
|
||||
import { SelfAppDisclosureConfig } from '../../../common/src/utils/appType';
|
||||
import { BodyText } from '../components/typography/BodyText';
|
||||
import CheckMark from '../images/icons/checkmark.svg';
|
||||
import { slate200, slate500 } from '../utils/colors';
|
||||
|
||||
interface DisclosureProps {
|
||||
disclosures: DisclosureOptions;
|
||||
disclosures: SelfAppDisclosureConfig;
|
||||
}
|
||||
|
||||
function listToString(list: string[]): string {
|
||||
@@ -25,29 +21,28 @@ function listToString(list: string[]): string {
|
||||
}
|
||||
|
||||
export default function Disclosures({ disclosures }: DisclosureProps) {
|
||||
// Convert the array into a lookup map keyed by the disclosure's key.
|
||||
const disclosureMap = React.useMemo(() => {
|
||||
return disclosures.reduce((acc, disclosure) => {
|
||||
acc[disclosure.key] = disclosure;
|
||||
return acc;
|
||||
}, {} as Partial<Record<DisclosureAttributes, DisclosureOption>>);
|
||||
}, [disclosures]);
|
||||
|
||||
// Define the order in which disclosures should appear.
|
||||
const ORDERED_KEYS: DisclosureAttributes[] = [
|
||||
const ORDERED_KEYS = [
|
||||
'issuing_state',
|
||||
'name',
|
||||
'passport_number',
|
||||
'nationality',
|
||||
'date_of_birth',
|
||||
'gender',
|
||||
'expiry_date',
|
||||
'ofac',
|
||||
'excludedCountries',
|
||||
'minimumAge',
|
||||
'ofac',
|
||||
'nationality',
|
||||
];
|
||||
] as const;
|
||||
|
||||
return (
|
||||
<YStack>
|
||||
{ORDERED_KEYS.map(key => {
|
||||
const disclosure = disclosureMap[key];
|
||||
if (!disclosure || !disclosure.enabled) {
|
||||
const isEnabled = disclosures[key];
|
||||
if (!isEnabled) {
|
||||
return null;
|
||||
}
|
||||
|
||||
let text = '';
|
||||
switch (key) {
|
||||
case 'ofac':
|
||||
@@ -55,16 +50,32 @@ export default function Disclosures({ disclosures }: DisclosureProps) {
|
||||
break;
|
||||
case 'excludedCountries':
|
||||
text = `I am not a resident of any of the following countries: ${listToString(
|
||||
(disclosure as { value: string[] }).value,
|
||||
disclosures.excludedCountries || [],
|
||||
)}`;
|
||||
break;
|
||||
case 'nationality':
|
||||
text = `I have a valid passport from ${
|
||||
(disclosure as { value: string }).value
|
||||
}`;
|
||||
break;
|
||||
case 'minimumAge':
|
||||
text = `Age [over ${(disclosure as { value: string }).value}]`;
|
||||
text = `Age [over ${disclosures.minimumAge}]`;
|
||||
break;
|
||||
case 'name':
|
||||
text = 'Name';
|
||||
break;
|
||||
case 'passport_number':
|
||||
text = 'Passport Number';
|
||||
break;
|
||||
case 'date_of_birth':
|
||||
text = 'Date of Birth';
|
||||
break;
|
||||
case 'gender':
|
||||
text = 'Gender';
|
||||
break;
|
||||
case 'expiry_date':
|
||||
text = 'Passport Expiry Date';
|
||||
break;
|
||||
case 'issuing_state':
|
||||
text = 'Issuing State';
|
||||
break;
|
||||
case 'nationality':
|
||||
text = 'Nationality';
|
||||
break;
|
||||
default:
|
||||
return null;
|
||||
|
||||
@@ -20,10 +20,11 @@ export function HeldPrimaryButton({
|
||||
...props
|
||||
}: ButtonProps) {
|
||||
const animation = useAnimatedValue(0);
|
||||
|
||||
const [hasTriggered, setHasTriggered] = useState(false);
|
||||
const [size, setSize] = useState({ width: 0, height: 0 });
|
||||
|
||||
const onPressIn = () => {
|
||||
setHasTriggered(false);
|
||||
Animated.timing(animation, {
|
||||
toValue: 1,
|
||||
duration: ACTION_TIMER,
|
||||
@@ -32,6 +33,7 @@ export function HeldPrimaryButton({
|
||||
};
|
||||
|
||||
const onPressOut = () => {
|
||||
setHasTriggered(false);
|
||||
Animated.timing(animation, {
|
||||
toValue: 0,
|
||||
duration: ACTION_TIMER,
|
||||
@@ -63,8 +65,8 @@ export function HeldPrimaryButton({
|
||||
|
||||
useEffect(() => {
|
||||
animation.addListener(({ value }) => {
|
||||
// when the animation is done we want to call the onPress function
|
||||
if (value >= 0.95) {
|
||||
if (value >= 0.95 && !hasTriggered) {
|
||||
setHasTriggered(true);
|
||||
// @ts-expect-error
|
||||
onPress();
|
||||
}
|
||||
@@ -72,7 +74,7 @@ export function HeldPrimaryButton({
|
||||
return () => {
|
||||
animation.removeAllListeners();
|
||||
};
|
||||
}, [animation]);
|
||||
}, [animation, hasTriggered]);
|
||||
|
||||
return (
|
||||
<PrimaryButton
|
||||
|
||||
@@ -4,9 +4,6 @@ import { StyleSheet } from 'react-native';
|
||||
import { useNavigation } from '@react-navigation/native';
|
||||
import LottieView from 'lottie-react-native';
|
||||
|
||||
// Import passport data generation and payload functions from common
|
||||
import { genMockPassportData } from '../../../../common/src/utils/passports/genMockPassportData';
|
||||
// Import animations
|
||||
import failAnimation from '../../assets/animations/loading/fail.json';
|
||||
import miscAnimation from '../../assets/animations/loading/misc.json';
|
||||
import successAnimation from '../../assets/animations/loading/success.json';
|
||||
@@ -76,24 +73,12 @@ const LoadingScreen: React.FC = () => {
|
||||
const processPayload = async () => {
|
||||
try {
|
||||
// Generate passport data and update the store.
|
||||
const passportData = genMockPassportData(
|
||||
'sha1',
|
||||
'sha256',
|
||||
'rsa_sha256_65537_2048',
|
||||
'FRA',
|
||||
'000101',
|
||||
'300101',
|
||||
);
|
||||
|
||||
const passportDataAndSecret = await getPassportDataAndSecret();
|
||||
if (!passportDataAndSecret) {
|
||||
return;
|
||||
}
|
||||
|
||||
const {
|
||||
// passportData,
|
||||
secret,
|
||||
} = passportDataAndSecret.data;
|
||||
const { passportData, secret } = passportDataAndSecret.data;
|
||||
|
||||
const isSupported = checkPassportSupported(passportData);
|
||||
if (!isSupported) {
|
||||
@@ -107,6 +92,8 @@ const LoadingScreen: React.FC = () => {
|
||||
|
||||
const isRegistered = await isUserRegistered(passportData, secret);
|
||||
const isNullifierOnchain = await isPassportNullified(passportData);
|
||||
console.log('User is registered:', isRegistered);
|
||||
console.log('Passport is nullified:', isNullifierOnchain);
|
||||
if (isNullifierOnchain && !isRegistered) {
|
||||
console.log(
|
||||
'Passport is nullified, but not registered with this secret. Prompt to restore secret from iCloud or manual backup',
|
||||
@@ -120,6 +107,7 @@ const LoadingScreen: React.FC = () => {
|
||||
} catch (error) {
|
||||
console.error('Error processing payload:', error);
|
||||
setStatus(ProofStatusEnum.ERROR);
|
||||
setTimeout(() => resetProof(), 1000);
|
||||
}
|
||||
};
|
||||
processPayload();
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import React, { useCallback, useEffect, useMemo } from 'react';
|
||||
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
||||
import { StyleSheet } from 'react-native';
|
||||
|
||||
import { useNavigation } from '@react-navigation/native';
|
||||
import LottieView from 'lottie-react-native';
|
||||
import { Image, Text, View, YStack } from 'tamagui';
|
||||
|
||||
import { ArgumentsDisclose } from '../../../../common/src/utils/appType';
|
||||
import { SelfAppDisclosureConfig } from '../../../../common/src/utils/appType';
|
||||
import { genMockPassportData } from '../../../../common/src/utils/passports/genMockPassportData';
|
||||
import miscAnimation from '../../assets/animations/loading/misc.json';
|
||||
import Disclosures from '../../components/Disclosures';
|
||||
@@ -13,6 +13,7 @@ import { HeldPrimaryButton } from '../../components/buttons/PrimaryButtonLongHol
|
||||
import { BodyText } from '../../components/typography/BodyText';
|
||||
import { Caption } from '../../components/typography/Caption';
|
||||
import { ExpandableBottomLayout } from '../../layouts/ExpandableBottomLayout';
|
||||
import { useApp } from '../../stores/appProvider';
|
||||
import { usePassport } from '../../stores/passportDataProvider';
|
||||
import { ProofStatusEnum, useProofInfo } from '../../stores/proofProvider';
|
||||
import { black, slate300, white } from '../../utils/colors';
|
||||
@@ -26,15 +27,21 @@ const ProveScreen: React.FC = () => {
|
||||
const { navigate } = useNavigation();
|
||||
const { getPassportDataAndSecret } = usePassport();
|
||||
const { selectedApp, setStatus } = useProofInfo();
|
||||
const { handleProofVerified } = useApp();
|
||||
const selectedAppRef = useRef(selectedApp);
|
||||
|
||||
// Add effect to log when selectedApp changes
|
||||
const isProcessingRef = useRef(false);
|
||||
useEffect(() => {
|
||||
if (!selectedApp || selectedAppRef.current?.sessionId === selectedApp.sessionId) {
|
||||
return; // Avoid unnecessary updates
|
||||
}
|
||||
selectedAppRef.current = selectedApp;
|
||||
console.log('[ProveScreen] Selected app updated:', selectedApp);
|
||||
}, [selectedApp]);
|
||||
|
||||
const disclosureOptions = useMemo(() => {
|
||||
return (selectedApp?.args as ArgumentsDisclose)?.disclosureOptions || [];
|
||||
}, [selectedApp?.args]);
|
||||
return (selectedApp?.disclosures as SelfAppDisclosureConfig) || [];
|
||||
}, [selectedApp?.disclosures]);
|
||||
|
||||
// Format the base64 image string correctly
|
||||
const logoSource = useMemo(() => {
|
||||
@@ -61,6 +68,10 @@ const ProveScreen: React.FC = () => {
|
||||
const onVerify = useCallback(
|
||||
async function () {
|
||||
buttonTap();
|
||||
if (isProcessingRef.current) return;
|
||||
isProcessingRef.current = true;
|
||||
|
||||
const currentApp = selectedAppRef.current;
|
||||
try {
|
||||
// getData first because that triggers biometric authentication and feels nicer to do before navigating
|
||||
// then wait a second and navigate to the status screen. use finally so that any errors thrown here dont prevent the navigate
|
||||
@@ -85,6 +96,7 @@ const ProveScreen: React.FC = () => {
|
||||
// - registration is ongoing => show a loading screen. TODO detect this?
|
||||
// - registration failed => send to ConfirmBelongingScreen to register again
|
||||
const isRegistered = await isUserRegistered(passportData, secret);
|
||||
console.log('isRegistered', isRegistered);
|
||||
if (!isRegistered) {
|
||||
console.log(
|
||||
'User is not registered, sending to ConfirmBelongingScreen',
|
||||
@@ -92,11 +104,22 @@ const ProveScreen: React.FC = () => {
|
||||
navigate('ConfirmBelongingScreen');
|
||||
return;
|
||||
}
|
||||
console.log('currentApp', currentApp);
|
||||
|
||||
await sendVcAndDisclosePayload(secret, passportData, selectedApp);
|
||||
const status = await sendVcAndDisclosePayload(
|
||||
secret,
|
||||
passportData,
|
||||
currentApp,
|
||||
);
|
||||
handleProofVerified(
|
||||
currentApp.sessionId,
|
||||
status === ProofStatusEnum.SUCCESS,
|
||||
);
|
||||
} catch (e) {
|
||||
console.log('Error sending VC and disclose payload', e);
|
||||
setStatus(ProofStatusEnum.ERROR);
|
||||
} finally {
|
||||
isProcessingRef.current = false;
|
||||
}
|
||||
},
|
||||
[
|
||||
@@ -118,7 +141,15 @@ const ProveScreen: React.FC = () => {
|
||||
'000101',
|
||||
'300101',
|
||||
);
|
||||
await sendVcAndDisclosePayload('0', passportData, selectedApp);
|
||||
const status = await sendVcAndDisclosePayload(
|
||||
'0',
|
||||
passportData,
|
||||
selectedApp,
|
||||
);
|
||||
handleProofVerified(
|
||||
selectedAppRef.current.sessionId,
|
||||
status === ProofStatusEnum.SUCCESS,
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
|
||||
@@ -39,7 +39,7 @@ const SplashScreen: React.FC = ({}) => {
|
||||
navigation.navigate('Launch');
|
||||
}
|
||||
}, 1000);
|
||||
}, [navigation]);
|
||||
}, [loadSecret, loadPassportData, navigation]);
|
||||
|
||||
return (
|
||||
<LottieView
|
||||
|
||||
@@ -14,17 +14,47 @@ interface IAppContext {
|
||||
* listens for the "self_app" event and updates the navigation store.
|
||||
*
|
||||
* @param sessionId - The session ID from the scanned QR code.
|
||||
* @param setSelectedApp - The function to update the selected app in the navigation store.
|
||||
*/
|
||||
startAppListener: (
|
||||
sessionId: string,
|
||||
setSelectedApp: (app: SelfApp) => void,
|
||||
) => void;
|
||||
|
||||
/**
|
||||
* Call this function with the sessionId and success status to notify the web app
|
||||
* that the proof has been verified.
|
||||
*
|
||||
* @param sessionId - The session ID from the scanned QR code.
|
||||
* @param success - Whether the proof was verified successfully.
|
||||
*/
|
||||
handleProofVerified: (sessionId: string, success: boolean) => void;
|
||||
}
|
||||
|
||||
const AppContext = createContext<IAppContext>({
|
||||
startAppListener: () => {},
|
||||
handleProofVerified: () => {},
|
||||
});
|
||||
|
||||
const initSocket = (sessionId: string) => {
|
||||
// Ensure the URL uses the proper WebSocket scheme.
|
||||
const connectionUrl = WS_DB_RELAYER.startsWith('https')
|
||||
? WS_DB_RELAYER.replace(/^https/, 'wss')
|
||||
: WS_DB_RELAYER;
|
||||
const socketUrl = `${connectionUrl}/websocket`;
|
||||
|
||||
// Create a new socket connection using the updated URL.
|
||||
const socket = io(socketUrl, {
|
||||
path: '/',
|
||||
transports: ['websocket'],
|
||||
query: {
|
||||
sessionId,
|
||||
clientType: 'mobile',
|
||||
},
|
||||
});
|
||||
return socket;
|
||||
};
|
||||
|
||||
export const AppProvider: React.FC<{ children: React.ReactNode }> = ({
|
||||
children,
|
||||
}) => {
|
||||
@@ -44,21 +74,7 @@ export const AppProvider: React.FC<{ children: React.ReactNode }> = ({
|
||||
socketRef.current.disconnect();
|
||||
}
|
||||
|
||||
// Ensure the URL uses the proper WebSocket scheme.
|
||||
const connectionUrl = WS_DB_RELAYER.startsWith('https')
|
||||
? WS_DB_RELAYER.replace(/^https/, 'wss')
|
||||
: WS_DB_RELAYER;
|
||||
const socketUrl = `${connectionUrl}/websocket`;
|
||||
|
||||
// Create a new socket connection using the updated URL.
|
||||
const socket = io(socketUrl, {
|
||||
path: '/',
|
||||
transports: ['websocket'],
|
||||
query: {
|
||||
sessionId,
|
||||
clientType: 'mobile',
|
||||
},
|
||||
});
|
||||
const socket = initSocket(sessionId);
|
||||
socketRef.current = socket;
|
||||
|
||||
socket.on('connect', () => {
|
||||
@@ -103,6 +119,27 @@ export const AppProvider: React.FC<{ children: React.ReactNode }> = ({
|
||||
}
|
||||
};
|
||||
|
||||
const handleProofVerified = (sessionId: string, proof_verified: boolean) => {
|
||||
console.log(
|
||||
'[AppProvider] handleProofVerified called with sessionId:',
|
||||
sessionId,
|
||||
);
|
||||
|
||||
if (!socketRef.current) {
|
||||
socketRef.current = initSocket(sessionId);
|
||||
}
|
||||
|
||||
console.log('[AppProvider] Emitting proof_verified event with data:', {
|
||||
session_id: sessionId,
|
||||
proof_verified,
|
||||
});
|
||||
|
||||
socketRef.current.emit('proof_verified', {
|
||||
session_id: sessionId,
|
||||
proof_verified,
|
||||
});
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
if (socketRef.current) {
|
||||
@@ -113,7 +150,7 @@ export const AppProvider: React.FC<{ children: React.ReactNode }> = ({
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<AppContext.Provider value={{ startAppListener }}>
|
||||
<AppContext.Provider value={{ startAppListener, handleProofVerified }}>
|
||||
{children}
|
||||
</AppContext.Provider>
|
||||
);
|
||||
|
||||
@@ -86,9 +86,7 @@ export function ProofProvider({ children }: PropsWithChildren) {
|
||||
userId: '',
|
||||
userIdType: 'uuid',
|
||||
devMode: true,
|
||||
args: {
|
||||
disclosureOptions: [],
|
||||
},
|
||||
disclosures: {},
|
||||
};
|
||||
setSelectedAppInternal(emptySelfApp);
|
||||
}, []);
|
||||
|
||||
@@ -1,38 +0,0 @@
|
||||
import { castCSCAProof } from '../../../common/src/utils/types';
|
||||
import useUserStore from '../stores/userStore';
|
||||
import { ModalProofSteps } from './utils';
|
||||
|
||||
export const sendCSCARequest = async (
|
||||
inputs_csca: any,
|
||||
modalServerUrl: string,
|
||||
setModalProofStep: (modalProofStep: number) => void,
|
||||
) => {
|
||||
try {
|
||||
console.log('inputs_csca before requesting modal server - cscaRequest.ts');
|
||||
fetch(modalServerUrl, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify(inputs_csca),
|
||||
})
|
||||
.then(response => {
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP error! status: ${response.status}`);
|
||||
}
|
||||
return response.json();
|
||||
})
|
||||
.then(data => {
|
||||
useUserStore.getState().cscaProof = castCSCAProof(data);
|
||||
setModalProofStep(ModalProofSteps.MODAL_SERVER_SUCCESS);
|
||||
console.log('Response from server:', data);
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error during request:', error);
|
||||
setModalProofStep(ModalProofSteps.MODAL_SERVER_ERROR);
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Error during request:', error);
|
||||
setModalProofStep(ModalProofSteps.MODAL_SERVER_ERROR);
|
||||
}
|
||||
};
|
||||
@@ -15,10 +15,7 @@ import {
|
||||
WS_RPC_URL_VC_AND_DISCLOSE,
|
||||
attributeToPosition,
|
||||
} from '../../../../common/src/constants/constants';
|
||||
import {
|
||||
DisclosureMatchOption,
|
||||
SelfApp,
|
||||
} from '../../../../common/src/utils/appType';
|
||||
import { SelfApp } from '../../../../common/src/utils/appType';
|
||||
import { getCircuitNameFromPassportData } from '../../../../common/src/utils/circuits/circuitsName';
|
||||
import {
|
||||
generateCircuitInputsDSC,
|
||||
@@ -82,6 +79,7 @@ export function checkPassportSupported(passportData: PassportData) {
|
||||
console.log('DSC circuit not supported:', circuitNameDsc);
|
||||
return false;
|
||||
}
|
||||
console.log('Passport supported');
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -137,6 +135,12 @@ async function checkIdPassportDscIsInTree(
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
// console.log('DSC i found in the tree, sending DSC payload for debug');
|
||||
// const dscStatus = await sendDscPayload(passportData);
|
||||
// if (dscStatus !== ProofStatusEnum.SUCCESS) {
|
||||
// console.log('DSC proof failed');
|
||||
// return false;
|
||||
// }
|
||||
console.log('DSC is found in the tree, skipping DSC payload');
|
||||
}
|
||||
return true;
|
||||
@@ -170,7 +174,7 @@ export async function sendDscPayload(
|
||||
|
||||
/*** DISCLOSURE ***/
|
||||
|
||||
async function getSMT() {
|
||||
async function getOfacSMTs() {
|
||||
// TODO: get the SMT from an endpoint
|
||||
const passportNoAndNationalitySMT = new SMT(poseidon2, true);
|
||||
passportNoAndNationalitySMT.import(passportNoAndNationalitySMTData);
|
||||
@@ -186,56 +190,44 @@ async function generateTeeInputsVCAndDisclose(
|
||||
passportData: PassportData,
|
||||
selfApp: SelfApp,
|
||||
) {
|
||||
let majority = DEFAULT_MAJORITY;
|
||||
const minAgeOption = selfApp.args.disclosureOptions.find(
|
||||
opt => opt.key === 'minimumAge',
|
||||
);
|
||||
if (
|
||||
minAgeOption &&
|
||||
minAgeOption.enabled &&
|
||||
minAgeOption.key === 'minimumAge'
|
||||
) {
|
||||
majority = (minAgeOption as DisclosureMatchOption<'minimumAge'>).value;
|
||||
}
|
||||
const { scope, userId, disclosures } = selfApp;
|
||||
|
||||
const user_identifier = selfApp.userId;
|
||||
const selector_dg1 = Array(88).fill('0');
|
||||
|
||||
let selector_dg1 = new Array(88).fill('0');
|
||||
const nationalityOption = selfApp.args.disclosureOptions.find(
|
||||
opt => opt.key === 'nationality',
|
||||
);
|
||||
if (nationalityOption && nationalityOption.enabled) {
|
||||
const [start, end] = attributeToPosition.nationality;
|
||||
for (let i = start; i <= end && i < selector_dg1.length; i++) {
|
||||
selector_dg1[i] = '1';
|
||||
Object.entries(disclosures).forEach(([attribute, reveal]) => {
|
||||
if (['ofac', 'excludedCountries', 'minimumAge'].includes(attribute)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
// TODO: add more options, we have to do it to in OpenpassportQrcode.ts
|
||||
if (reveal) {
|
||||
const [start, end] =
|
||||
attributeToPosition[attribute as keyof typeof attributeToPosition];
|
||||
selector_dg1.fill('1', start, end + 1);
|
||||
}
|
||||
});
|
||||
|
||||
const majority = disclosures.minimumAge
|
||||
? disclosures.minimumAge.toString()
|
||||
: DEFAULT_MAJORITY;
|
||||
const selector_older_than = disclosures.minimumAge ? '1' : '0';
|
||||
|
||||
const selector_ofac = disclosures.ofac ? 1 : 0;
|
||||
|
||||
const selector_older_than = minAgeOption && minAgeOption.enabled ? '1' : '0';
|
||||
const ofacOption = selfApp.args.disclosureOptions.find(
|
||||
opt => opt.key === 'ofac',
|
||||
);
|
||||
const selector_ofac = ofacOption && ofacOption.enabled ? 1 : 0;
|
||||
const { passportNoAndNationalitySMT, nameAndDobSMT, nameAndYobSMT } =
|
||||
await getSMT();
|
||||
const scope = selfApp.scope;
|
||||
const attestation_id = PASSPORT_ATTESTATION_ID;
|
||||
const commitment = generateCommitment(secret, attestation_id, passportData);
|
||||
const _tree = await getCommitmentTree();
|
||||
const tree = LeanIMT.import((a, b) => poseidon2([a, b]), _tree);
|
||||
tree.insert(BigInt(commitment)); // TODO: dont do that! for now we add the commitment as the whole flow is not yet implemented
|
||||
let forbidden_countries_list: string[] = ['ABC', 'DEF']; // TODO: add the countries from the disclosure options
|
||||
const excludedCountriesOption = selfApp.args.disclosureOptions.find(
|
||||
opt => opt.key === 'excludedCountries',
|
||||
) as { enabled: boolean; key: string; value: string[] } | undefined;
|
||||
if (excludedCountriesOption && excludedCountriesOption.enabled) {
|
||||
forbidden_countries_list = excludedCountriesOption.value;
|
||||
}
|
||||
await getOfacSMTs();
|
||||
const serialized_tree = await getCommitmentTree();
|
||||
const tree = LeanIMT.import((a, b) => poseidon2([a, b]), serialized_tree);
|
||||
console.log('tree', tree);
|
||||
// const commitment = generateCommitment(
|
||||
// secret,
|
||||
// PASSPORT_ATTESTATION_ID,
|
||||
// passportData,
|
||||
// );
|
||||
// tree.insert(BigInt(commitment));
|
||||
// Uncomment to add artificially the commitment to the tree
|
||||
|
||||
const inputs = generateCircuitInputsVCandDisclose(
|
||||
secret,
|
||||
attestation_id,
|
||||
PASSPORT_ATTESTATION_ID,
|
||||
passportData,
|
||||
scope,
|
||||
selector_dg1,
|
||||
@@ -246,8 +238,8 @@ async function generateTeeInputsVCAndDisclose(
|
||||
nameAndDobSMT,
|
||||
nameAndYobSMT,
|
||||
selector_ofac,
|
||||
forbidden_countries_list,
|
||||
user_identifier,
|
||||
disclosures.excludedCountries ?? [],
|
||||
userId,
|
||||
);
|
||||
return { inputs, circuitName: 'vc_and_disclose' };
|
||||
}
|
||||
@@ -265,7 +257,7 @@ export async function sendVcAndDisclosePayload(
|
||||
passportData,
|
||||
selfApp,
|
||||
);
|
||||
await sendPayload(
|
||||
return await sendPayload(
|
||||
inputs,
|
||||
'vc_and_disclose',
|
||||
circuitName,
|
||||
|
||||
@@ -85,7 +85,6 @@ export async function sendPayload(
|
||||
resolve(status);
|
||||
}
|
||||
}
|
||||
console.log(inputs);
|
||||
const uuid = v4();
|
||||
const ws = new WebSocket(wsRpcUrl);
|
||||
let socket: Socket | null = null;
|
||||
@@ -172,13 +171,20 @@ export async function sendPayload(
|
||||
const data =
|
||||
typeof message === 'string' ? JSON.parse(message) : message;
|
||||
console.log('SocketIO message:', data);
|
||||
if (data.status === 2) {
|
||||
console.log('Proof generation completed');
|
||||
if (data.status === 4) {
|
||||
console.log('Proof verified');
|
||||
socket?.disconnect();
|
||||
if (ws.readyState === WebSocket.OPEN) {
|
||||
ws.close();
|
||||
}
|
||||
finalize(ProofStatusEnum.SUCCESS);
|
||||
} else if (data.status === 5) {
|
||||
console.log('Failed to verify proof');
|
||||
socket?.disconnect();
|
||||
if (ws.readyState === WebSocket.OPEN) {
|
||||
ws.close();
|
||||
}
|
||||
finalize(ProofStatusEnum.FAILURE);
|
||||
}
|
||||
});
|
||||
socket.on('disconnect', reason => {
|
||||
|
||||
@@ -5,14 +5,14 @@ import pako from 'pako';
|
||||
|
||||
import { SelfApp } from '../../../common/src/utils/appType';
|
||||
import useNavigationStore from '../stores/navigationStore';
|
||||
import useUserStore from '../stores/userStore';
|
||||
import { loadPassportData } from '../stores/passportDataProvider';
|
||||
|
||||
export default async function handleQRCodeScan(
|
||||
result: string,
|
||||
setApp: (app: SelfApp) => void,
|
||||
) {
|
||||
try {
|
||||
const { passportData } = useUserStore.getState();
|
||||
const passportData = await loadPassportData();
|
||||
if (passportData) {
|
||||
const decodedResult = atob(result);
|
||||
const uint8Array = new Uint8Array(
|
||||
@@ -24,7 +24,7 @@ export default async function handleQRCodeScan(
|
||||
|
||||
setApp(openPassportApp);
|
||||
console.log('✅', {
|
||||
message: 'QR code scannedrre',
|
||||
message: 'QR code scanned',
|
||||
customData: {
|
||||
type: 'success',
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user