mirror of
https://github.com/selfxyz/self.git
synced 2026-01-20 03:58:11 -05:00
add NextScreen and RegisterScreen
This commit is contained in:
committed by
0xturboblitz
parent
852ecfd617
commit
b08e090e08
@@ -37,7 +37,7 @@ export const sbtApp: AppType = {
|
||||
selectable: true,
|
||||
icon: Flame,
|
||||
tags: [sepolia()],
|
||||
|
||||
|
||||
// ProveScreen UI
|
||||
name: 'Soulbound token',
|
||||
disclosureOptions: {
|
||||
@@ -45,7 +45,7 @@ export const sbtApp: AppType = {
|
||||
expiry_date: "optional",
|
||||
older_than: "optional"
|
||||
},
|
||||
|
||||
|
||||
// SendProofScreen UI before sending proof
|
||||
beforeSendText1: "You can now use this proof to mint a Soulbound token.",
|
||||
beforeSendText2: "Disclosed information will be displayed on SBT.",
|
||||
@@ -62,14 +62,14 @@ export const sbtApp: AppType = {
|
||||
|
||||
return (
|
||||
<Pressable onPress={() => {
|
||||
Clipboard.setString(txHash);
|
||||
toast?.show('🖨️', {
|
||||
message: "Tx copied to clipboard",
|
||||
customData: {
|
||||
type: "success",
|
||||
},
|
||||
})
|
||||
}}
|
||||
Clipboard.setString(txHash);
|
||||
toast?.show('🖨️', {
|
||||
message: "Tx copied to clipboard",
|
||||
customData: {
|
||||
type: "success",
|
||||
},
|
||||
})
|
||||
}}
|
||||
>
|
||||
<XStack jc='space-between' h="$2" ai="center">
|
||||
<Text color={textColor1} fontWeight="bold" fontSize="$5">
|
||||
@@ -122,9 +122,9 @@ export const sbtApp: AppType = {
|
||||
} = useUserStore.getState();
|
||||
|
||||
setStep(Steps.GENERATING_PROOF);
|
||||
|
||||
|
||||
const reveal_bitmap = revealBitmapFromMapping(disclosure);
|
||||
|
||||
|
||||
const response = await axios.get(COMMITMENT_TREE_TRACKER_URL)
|
||||
// const serializedCommitmentTree = "[[\"9366833337168993085050982292715343583458999801189875133285760454940954329736\",\"17067815450997614268337156469331439256078702232208444991806942459610897177755\",\"6218618977460894587557092460164616095207478656436068295742870309857616419830\",\"1009498555512750055176786258919772755314598234878788682229429740456064488924\",\"2317777252282411584898482846587421326341858131145081778162865818517424463113\",\"14350861400343175672772758664935358862843556622155842278173685659399974430673\"],[\"5757843324860707578753413472099376283217223062835733089254074659436006978958\",\"9384382887555344903988763589988369409408141218078864334664000402547342440893\",\"20714514634358291855499138323356766695315870633431415798546884765927810445680\"],[\"6444500081923737565029349850782686417529434309028817508928891238372057960879\",\"20714514634358291855499138323356766695315870633431415798546884765927810445680\"],[\"13949165376611379310020797746578693825960496340786495286952352659551479278661\"]]"
|
||||
console.log('response.data:', response.data);
|
||||
@@ -149,7 +149,7 @@ export const sbtApp: AppType = {
|
||||
);
|
||||
|
||||
console.log('inputs:', inputs);
|
||||
|
||||
|
||||
const start = Date.now();
|
||||
|
||||
const proof = await generateProof(
|
||||
@@ -173,7 +173,7 @@ export const sbtApp: AppType = {
|
||||
type: "error",
|
||||
},
|
||||
})
|
||||
setStep(Steps.NFC_SCAN_COMPLETED);
|
||||
setStep(Steps.NEXT_SCREEN);
|
||||
amplitude.track(error.message);
|
||||
}
|
||||
},
|
||||
@@ -188,15 +188,15 @@ export const sbtApp: AppType = {
|
||||
toast,
|
||||
setStep
|
||||
} = useNavigationStore.getState();
|
||||
|
||||
|
||||
if (!proof) {
|
||||
console.error('Proof is not generated');
|
||||
return;
|
||||
}
|
||||
|
||||
setStep(Steps.PROOF_SENDING);
|
||||
|
||||
toast?.show('🚀',{
|
||||
|
||||
toast?.show('🚀', {
|
||||
message: "Transaction sent...",
|
||||
customData: {
|
||||
type: "info",
|
||||
@@ -214,7 +214,7 @@ export const sbtApp: AppType = {
|
||||
txHash: txHash,
|
||||
proofSentText: `SBT minting... Network: Sepolia. Transaction hash: ${txHash}`
|
||||
});
|
||||
|
||||
|
||||
const receipt = await provider.waitForTransaction(txHash);
|
||||
console.log('receipt status:', receipt?.status);
|
||||
|
||||
@@ -248,7 +248,7 @@ export const sbtApp: AppType = {
|
||||
if (error.isAxiosError && error.response) {
|
||||
const errorMessage = error.response.data.error;
|
||||
console.log('Server error message:', errorMessage);
|
||||
|
||||
|
||||
// parse blockchain error and show it
|
||||
const match = errorMessage.match(/execution reverted: "([^"]*)"/);
|
||||
if (match && match[1]) {
|
||||
|
||||
@@ -41,7 +41,7 @@ const CameraScreen: React.FC<CameraScreenProps> = ({ sheetIsOpen, setSheetIsOpen
|
||||
|
||||
</YStack>
|
||||
|
||||
<YStack gap="$2">
|
||||
<YStack gap="$2" mb="$6">
|
||||
<Button borderWidth={1.3} borderColor={borderColor} borderRadius="$10" bg="#3185FC" onPress={startCameraScan}><Camera color={textColor1} /></Button>
|
||||
<Button bg={textColor2} borderColor={borderColor} borderRadius="$10" onPress={() => setSheetIsOpen(true)}><SquarePen /></Button>
|
||||
</YStack>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { YStack, XStack, Text, Button, Tabs, Sheet, Label, Fieldset, Input, Switch, H2, Image, useWindowDimensions, H4, H3 } from 'tamagui'
|
||||
import { HelpCircle, IterationCw, VenetianMask, Cog, CheckCircle2, ChevronLeft, Share } from '@tamagui/lucide-icons';
|
||||
import { HelpCircle, IterationCw, VenetianMask, Cog, CheckCircle2, ChevronLeft, Share, Eraser } from '@tamagui/lucide-icons';
|
||||
import X from '../images/x.png'
|
||||
import Telegram from '../images/telegram.png'
|
||||
import Github from '../images/github.png'
|
||||
@@ -20,17 +20,19 @@ import { scan } from '../utils/nfcScanner';
|
||||
import useNavigationStore from '../stores/navigationStore';
|
||||
import NfcScreen from './NfcScreen';
|
||||
import CameraScreen from './CameraScreen';
|
||||
import NextScreen from './NextScreen';
|
||||
import { mockPassportData_sha256WithRSAEncryption_65537 } from '../../../common/src/utils/mockPassportData';
|
||||
import Dialog from "react-native-dialog";
|
||||
import { contribute } from '../utils/contribute';
|
||||
import RegisterScreen from './RegisterScreen';
|
||||
|
||||
|
||||
const MainScreen: React.FC = () => {
|
||||
const [NFCScanIsOpen, setNFCScanIsOpen] = useState(false);
|
||||
const [displayOtherOptions, setDisplayOtherOptions] = useState(false);
|
||||
const [SettingsIsOpen, setSettingsIsOpen] = useState(false);
|
||||
const [DialogContributeIsOpen, setDialogContributeIsOpen] = useState(false);
|
||||
const [HelpIsOpen, setHelpIsOpen] = useState(false);
|
||||
const [brokenCamera, setBrokenCamera] = useState(false);
|
||||
const [sheetIsOpen, setSheetIsOpen] = useState(false);
|
||||
|
||||
const {
|
||||
@@ -42,28 +44,11 @@ const MainScreen: React.FC = () => {
|
||||
clearPassportDataFromStorage,
|
||||
clearSecretFromStorage,
|
||||
registerCommitment,
|
||||
registerPassportData,
|
||||
passportData,
|
||||
secret
|
||||
registered
|
||||
} = useUserStore()
|
||||
|
||||
const decrementStep = () => {
|
||||
if (selectedTab === "nfc") {
|
||||
updateNavigationStore({
|
||||
selectedTab: "scan",
|
||||
})
|
||||
}
|
||||
else if (selectedTab === "app") {
|
||||
updateNavigationStore({
|
||||
selectedTab: "nfc",
|
||||
})
|
||||
}
|
||||
else if (selectedTab === "prove") {
|
||||
updateNavigationStore({
|
||||
selectedTab: "app",
|
||||
})
|
||||
}
|
||||
};
|
||||
|
||||
const {
|
||||
showWarningModal,
|
||||
update: updateNavigationStore,
|
||||
@@ -82,25 +67,42 @@ const MainScreen: React.FC = () => {
|
||||
})
|
||||
deleteMrzFields();
|
||||
}
|
||||
|
||||
const handleSkip = () => {
|
||||
registerCommitment(
|
||||
secret,
|
||||
mockPassportData_sha256WithRSAEncryption_65537
|
||||
)
|
||||
update({
|
||||
passportData: mockPassportData_sha256WithRSAEncryption_65537
|
||||
})
|
||||
setStep(Steps.NFC_SCAN_COMPLETED);
|
||||
deleteMrzFields();
|
||||
toast?.show("Using mock passport data!", { type: "info" })
|
||||
}
|
||||
|
||||
const handleHideData = () => {
|
||||
updateNavigationStore({
|
||||
hideData: !hideData,
|
||||
})
|
||||
}
|
||||
|
||||
const handleSkip = () => {
|
||||
registerPassportData(
|
||||
mockPassportData_sha256WithRSAEncryption_65537
|
||||
)
|
||||
update({
|
||||
passportData: mockPassportData_sha256WithRSAEncryption_65537
|
||||
})
|
||||
setStep(Steps.NEXT_SCREEN);
|
||||
deleteMrzFields();
|
||||
toast?.show("Using mock passport data!", { type: "info" })
|
||||
}
|
||||
|
||||
const decrementStep = () => {
|
||||
if (selectedTab === "nfc") {
|
||||
setStep(Steps.MRZ_SCAN);
|
||||
}
|
||||
else if (selectedTab === "next") {
|
||||
setStep(Steps.MRZ_SCAN_COMPLETED);
|
||||
}
|
||||
else if (selectedTab === "register") {
|
||||
setStep(Steps.NEXT_SCREEN);
|
||||
}
|
||||
else if (selectedTab === "prove") {
|
||||
setStep(Steps.REGISTERED);
|
||||
}
|
||||
else if (selectedTab === "mint") {
|
||||
setStep(Steps.REGISTERED);
|
||||
}
|
||||
};
|
||||
|
||||
const handleNFCScan = () => {
|
||||
if ((Platform.OS === 'ios')) {
|
||||
console.log('ios');
|
||||
@@ -117,13 +119,19 @@ const MainScreen: React.FC = () => {
|
||||
setDialogContributeIsOpen(false);
|
||||
}
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
if (passportNumber?.length === 9 && (dateOfBirth?.length === 6 && dateOfExpiry?.length === 6)) {
|
||||
setStep(Steps.MRZ_SCAN_COMPLETED);
|
||||
}
|
||||
}, [passportNumber, dateOfBirth, dateOfExpiry]);
|
||||
|
||||
useEffect(() => {
|
||||
if (registered) {
|
||||
setStep(Steps.REGISTERED);
|
||||
}
|
||||
}, [registered]);
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
let timeoutId: ReturnType<typeof setTimeout>;
|
||||
if (step == Steps.MRZ_SCAN) {
|
||||
@@ -142,7 +150,7 @@ const MainScreen: React.FC = () => {
|
||||
setNFCScanIsOpen(false);
|
||||
}, 0);
|
||||
}
|
||||
else if (step == Steps.NFC_SCAN_COMPLETED) {
|
||||
else if (step == Steps.NEXT_SCREEN) {
|
||||
// Set the timeout and store its ID
|
||||
timeoutId = setTimeout(() => {
|
||||
setNFCScanIsOpen(false);
|
||||
@@ -153,7 +161,17 @@ const MainScreen: React.FC = () => {
|
||||
selectedTab: "mint",
|
||||
})
|
||||
}
|
||||
if (step == Steps.NFC_SCAN_COMPLETED) {
|
||||
if (step == Steps.NEXT_SCREEN) {
|
||||
updateNavigationStore({
|
||||
selectedTab: "next",
|
||||
})
|
||||
}
|
||||
if (step == Steps.REGISTER) {
|
||||
updateNavigationStore({
|
||||
selectedTab: "register",
|
||||
})
|
||||
}
|
||||
if (step == Steps.REGISTERED) {
|
||||
updateNavigationStore({
|
||||
selectedTab: "app",
|
||||
})
|
||||
@@ -172,7 +190,7 @@ const MainScreen: React.FC = () => {
|
||||
<YStack f={1} bc="#161616" mt={Platform.OS === 'ios' ? "$8" : "$0"} >
|
||||
<YStack >
|
||||
<XStack jc="space-between" ai="center" px="$3">
|
||||
<Button p="$2" py="$3" unstyled onPress={decrementStep}><ChevronLeft color={selectedTab === "scan" ? "transparent" : "#a0a0a0"} /></Button>
|
||||
<Button p="$2" py="$3" unstyled onPress={decrementStep}><ChevronLeft color={(selectedTab === "scan" || selectedTab === "app") ? "transparent" : "#a0a0a0"} /></Button>
|
||||
|
||||
<Text fontSize="$6" color="#a0a0a0">
|
||||
{selectedTab === "scan" ? "Scan" : (selectedTab === "app" ? "Apps" : "Prove")}
|
||||
@@ -187,7 +205,7 @@ const MainScreen: React.FC = () => {
|
||||
<Sheet.Frame>
|
||||
<YStack gap="$5" f={1} pt="$3">
|
||||
<H2 textAlign='center'>Ready to scan</H2>
|
||||
{step >= Steps.NFC_SCAN_COMPLETED ?
|
||||
{step >= Steps.NEXT_SCREEN ?
|
||||
<CheckCircle2
|
||||
size="$8"
|
||||
alignSelf='center'
|
||||
@@ -217,74 +235,15 @@ const MainScreen: React.FC = () => {
|
||||
<H2 color={textColor1}>Settings</H2>
|
||||
<Cog color={textColor1} mt="$1" alignSelf='center' size="$2" />
|
||||
</XStack>
|
||||
<Fieldset horizontal>
|
||||
<Label color={textColor1} width={225} justifyContent="flex-end" htmlFor="name" >
|
||||
Broken camera
|
||||
</Label>
|
||||
<Switch size="$3.5" checked={brokenCamera} onCheckedChange={setBrokenCamera}>
|
||||
<Switch.Thumb animation="bouncy" bc={bgColor} />
|
||||
</Switch>
|
||||
</Fieldset>
|
||||
{
|
||||
brokenCamera &&
|
||||
<YStack pl="$3" gap="$1">
|
||||
<Fieldset gap="$4" horizontal>
|
||||
<Label color={textColor1} width={160} justifyContent="flex-end" fontSize={13}>
|
||||
Passport Number
|
||||
</Label>
|
||||
<Input
|
||||
bg={componentBgColor}
|
||||
color={textColor1}
|
||||
h="$3.5"
|
||||
borderColor={passportNumber?.length === 9 ? "green" : "unset"}
|
||||
flex={1}
|
||||
id="passportnumber"
|
||||
onChangeText={(text) => {
|
||||
update({ passportNumber: text.toUpperCase() })
|
||||
}}
|
||||
value={passportNumber}
|
||||
keyboardType="default"
|
||||
/>
|
||||
</Fieldset>
|
||||
<Fieldset gap="$4" horizontal>
|
||||
<Label color={textColor1} width={160} justifyContent="flex-end" fontSize={13}>
|
||||
Date of birth (yymmdd)
|
||||
</Label>
|
||||
<Input
|
||||
bg={componentBgColor}
|
||||
color={textColor1}
|
||||
h="$3.5"
|
||||
borderColor={dateOfBirth?.length === 6 ? "green" : "unset"}
|
||||
flex={1}
|
||||
id="dateofbirth"
|
||||
onChangeText={(text) => {
|
||||
update({ dateOfBirth: text })
|
||||
}}
|
||||
value={dateOfBirth}
|
||||
keyboardType={Platform.OS === "ios" ? "default" : "number-pad"}
|
||||
/>
|
||||
</Fieldset>
|
||||
<Fieldset gap="$4" horizontal>
|
||||
<Label color={textColor1} width={160} justifyContent="flex-end" fontSize={13}>
|
||||
Date of expiry (yymmdd)
|
||||
</Label>
|
||||
<Input
|
||||
bg={componentBgColor}
|
||||
color={textColor1}
|
||||
h="$3.5"
|
||||
borderColor={dateOfExpiry?.length === 6 ? "green" : "unset"}
|
||||
flex={1}
|
||||
id="dateofexpiry"
|
||||
onChangeText={(text) => {
|
||||
update({ dateOfExpiry: text })
|
||||
}}
|
||||
value={dateOfExpiry}
|
||||
keyboardType={Platform.OS === "ios" ? "default" : "number-pad"}
|
||||
/>
|
||||
</Fieldset>
|
||||
</YStack>
|
||||
}
|
||||
|
||||
<Fieldset gap="$4" mt="$1" horizontal>
|
||||
<Label color={textColor1} width={200} justifyContent="flex-end" htmlFor="restart">
|
||||
Contribute
|
||||
</Label>
|
||||
<Button bg={componentBgColor} jc="center" borderColor={borderColor} borderWidth={1.2} size="$3.5" ml="$2" onPress={() => setDialogContributeIsOpen(true)}>
|
||||
<Share color={textColor1} />
|
||||
</Button>
|
||||
</Fieldset>
|
||||
<Fieldset horizontal>
|
||||
<Label color={textColor1} width={225} justifyContent="flex-end" htmlFor="restart" >
|
||||
Private mode
|
||||
@@ -294,13 +253,15 @@ const MainScreen: React.FC = () => {
|
||||
</Switch>
|
||||
</Fieldset>
|
||||
|
||||
<Fieldset gap="$4" mt="$1" horizontal>
|
||||
<Label color={textColor1} width={200} justifyContent="flex-end" htmlFor="restart">
|
||||
Contribute
|
||||
|
||||
|
||||
<Fieldset horizontal>
|
||||
<Label color={textColor1} width={225} justifyContent="flex-end" htmlFor="restart" >
|
||||
Display other options
|
||||
</Label>
|
||||
<Button bg={componentBgColor} jc="center" borderColor={borderColor} borderWidth={1.2} size="$3.5" ml="$2" onPress={() => setDialogContributeIsOpen(true)}>
|
||||
<Share color={textColor1} />
|
||||
</Button>
|
||||
<Switch size="$3.5" checked={displayOtherOptions} onCheckedChange={() => setDisplayOtherOptions(!displayOtherOptions)}>
|
||||
<Switch.Thumb animation="bouncy" bc={bgColor} />
|
||||
</Switch>
|
||||
</Fieldset>
|
||||
|
||||
<Dialog.Container visible={DialogContributeIsOpen}>
|
||||
@@ -314,42 +275,46 @@ const MainScreen: React.FC = () => {
|
||||
</Dialog.Container>
|
||||
|
||||
|
||||
{displayOtherOptions && (
|
||||
<>
|
||||
<XStack my="$3" alignSelf='center' h={2} w="80%" bg={componentBgColor} borderRadius={100} />
|
||||
<Fieldset gap="$4" horizontal>
|
||||
<Label color={textColor1} width={200} justifyContent="flex-end" htmlFor="restart">
|
||||
Restart to step 1
|
||||
</Label>
|
||||
<Button bg={componentBgColor} jc="center" borderColor={borderColor} borderWidth={1.2} size="$3.5" ml="$2" onPress={handleRestart}>
|
||||
<IterationCw color={textColor1} />
|
||||
</Button>
|
||||
</Fieldset>
|
||||
|
||||
<Fieldset gap="$4" mt="$1" horizontal>
|
||||
<Label color={textColor1} width={200} justifyContent="flex-end" htmlFor="restart">
|
||||
Restart to step 1
|
||||
</Label>
|
||||
<Button bg={componentBgColor} jc="center" borderColor={borderColor} borderWidth={1.2} size="$3.5" ml="$2" onPress={handleRestart}>
|
||||
<IterationCw color={textColor1} />
|
||||
</Button>
|
||||
</Fieldset>
|
||||
<Fieldset gap="$4" mt="$1" horizontal>
|
||||
<Label color={textColor1} width={200} justifyContent="flex-end" htmlFor="skip" >
|
||||
Use mock passport data
|
||||
</Label>
|
||||
<Button bg={componentBgColor} jc="center" borderColor={borderColor} borderWidth={1.2} size="$3.5" ml="$2" onPress={handleSkip}>
|
||||
<VenetianMask color={textColor1} />
|
||||
</Button>
|
||||
</Fieldset>
|
||||
|
||||
<Fieldset gap="$4" mt="$1" horizontal>
|
||||
<Label color={textColor1} width={200} justifyContent="flex-end" htmlFor="skip" >
|
||||
Use mock passport data
|
||||
</Label>
|
||||
<Button bg={componentBgColor} jc="center" borderColor={borderColor} borderWidth={1.2} size="$3.5" ml="$2" onPress={handleSkip}>
|
||||
<VenetianMask color={textColor1} />
|
||||
</Button>
|
||||
</Fieldset>
|
||||
<Fieldset gap="$4" mt="$1" horizontal>
|
||||
<Label color={textColor1} width={200} justifyContent="flex-end" htmlFor="skip" >
|
||||
Delete passport data
|
||||
</Label>
|
||||
<Button bg={componentBgColor} jc="center" borderColor={borderColor} borderWidth={1.2} size="$3.5" ml="$2" onPress={clearPassportDataFromStorage}>
|
||||
<Eraser color={textColor1} />
|
||||
</Button>
|
||||
</Fieldset>
|
||||
|
||||
<Fieldset gap="$4" mt="$1" horizontal>
|
||||
<Label color={textColor1} width={200} justifyContent="flex-end" htmlFor="skip" >
|
||||
Delete passport data
|
||||
</Label>
|
||||
<Button bg={componentBgColor} jc="center" borderColor={borderColor} borderWidth={1.2} size="$3.5" ml="$2" onPress={clearPassportDataFromStorage}>
|
||||
<VenetianMask color={textColor1} />
|
||||
</Button>
|
||||
</Fieldset>
|
||||
|
||||
<Fieldset gap="$4" mt="$1" horizontal>
|
||||
<Label color={textColor1} width={200} justifyContent="flex-end" htmlFor="skip" >
|
||||
Delete secret (caution)
|
||||
</Label>
|
||||
<Button bg={componentBgColor} jc="center" borderColor={borderColor} borderWidth={1.2} size="$3.5" ml="$2" onPress={clearSecretFromStorage}>
|
||||
<VenetianMask color={textColor1} />
|
||||
</Button>
|
||||
</Fieldset>
|
||||
<Fieldset gap="$4" mt="$1" horizontal>
|
||||
<Label color={textColor1} width={200} justifyContent="flex-end" htmlFor="skip" >
|
||||
Delete secret (caution)
|
||||
</Label>
|
||||
<Button bg={componentBgColor} jc="center" borderColor={borderColor} borderWidth={1.2} size="$3.5" ml="$2" onPress={clearSecretFromStorage}>
|
||||
<Eraser color={textColor2} />
|
||||
</Button>
|
||||
</Fieldset>
|
||||
</>
|
||||
)}
|
||||
|
||||
<YStack flex={1} />
|
||||
|
||||
@@ -359,6 +324,7 @@ const MainScreen: React.FC = () => {
|
||||
</Button> */}
|
||||
</YStack>
|
||||
</YStack>
|
||||
|
||||
</Sheet.Frame>
|
||||
</Sheet>
|
||||
|
||||
@@ -491,7 +457,7 @@ const MainScreen: React.FC = () => {
|
||||
</Sheet>
|
||||
<XStack bc="#343434" h={1.2} />
|
||||
</YStack>
|
||||
<Tabs f={1} orientation="horizontal" flexDirection="column" defaultValue="scan"
|
||||
<Tabs f={1} orientation="horizontal" flexDirection="column" defaultValue={"scan"}
|
||||
value={selectedTab}
|
||||
onValueChange={(value) => updateNavigationStore({ selectedTab: value })}
|
||||
>
|
||||
@@ -508,11 +474,15 @@ const MainScreen: React.FC = () => {
|
||||
handleNFCScan={handleNFCScan}
|
||||
/>
|
||||
</Tabs.Content>
|
||||
|
||||
<Tabs.Content value="next" f={1}>
|
||||
<NextScreen />
|
||||
</Tabs.Content>
|
||||
<Tabs.Content value="register" f={1}>
|
||||
<RegisterScreen />
|
||||
</Tabs.Content>
|
||||
<Tabs.Content value="app" f={1}>
|
||||
<AppScreen />
|
||||
</Tabs.Content>
|
||||
|
||||
<Tabs.Content value="prove" f={1}>
|
||||
<ProveScreen />
|
||||
</Tabs.Content>
|
||||
|
||||
111
app/src/screens/NextScreen.tsx
Normal file
111
app/src/screens/NextScreen.tsx
Normal file
@@ -0,0 +1,111 @@
|
||||
import React from 'react';
|
||||
import { YStack, XStack, Text, Button, Image, useWindowDimensions, Fieldset } from 'tamagui';
|
||||
import { Info } from '@tamagui/lucide-icons';
|
||||
import { getFirstName, maskString } from '../../utils/utils';
|
||||
import { attributeToPosition } from '../../../common/src/constants/constants';
|
||||
import USER from '../images/user.png'
|
||||
import { borderColor, componentBgColor, textColor1, textColor2 } from '../utils/colors';
|
||||
import { Platform } from 'react-native';
|
||||
import { formatAttribute, Steps } from '../utils/utils';
|
||||
import useUserStore from '../stores/userStore';
|
||||
import useNavigationStore from '../stores/navigationStore';
|
||||
|
||||
|
||||
const NextScreen: React.FC = () => {
|
||||
const {
|
||||
hideData,
|
||||
setStep,
|
||||
|
||||
} = useNavigationStore()
|
||||
|
||||
const {
|
||||
passportData,
|
||||
} = useUserStore();
|
||||
|
||||
const disclosureOptions: any = {
|
||||
gender: "optional",
|
||||
nationality: "optional",
|
||||
expiry_date: "optional",
|
||||
date_of_birth: "optional",
|
||||
};
|
||||
|
||||
const { height } = useWindowDimensions();
|
||||
|
||||
return (
|
||||
<YStack px="$4" f={1} mb={Platform.OS === 'ios' ? "$5" : "$0"}>
|
||||
<YStack flex={1} mx="$2" gap="$2">
|
||||
<YStack alignSelf='center' my="$3">
|
||||
{hideData
|
||||
? <Image
|
||||
w={height > 750 ? 150 : 100}
|
||||
h={height > 750 ? 190 : 80}
|
||||
borderRadius={height > 800 ? "$7" : "$6"}
|
||||
source={{
|
||||
uri: USER,
|
||||
}}
|
||||
/>
|
||||
: <Image
|
||||
w={height > 750 ? 150 : 110}
|
||||
h={height > 750 ? 190 : 130}
|
||||
borderRadius={height > 750 ? "$7" : "$6"}
|
||||
source={{
|
||||
uri: passportData.photoBase64 ?? USER,
|
||||
}}
|
||||
/>
|
||||
}
|
||||
</YStack>
|
||||
<Text color={textColor1} fontSize="$5" fontWeight="bold">
|
||||
Hi {" "}
|
||||
{
|
||||
hideData
|
||||
? maskString(getFirstName(passportData.mrz))
|
||||
: getFirstName(passportData.mrz)
|
||||
}
|
||||
👋
|
||||
</Text>
|
||||
|
||||
<YStack gap="$2.5" mt="$2" ml="$2">
|
||||
{Object.keys(disclosureOptions).map((key) => {
|
||||
const key_ = key;
|
||||
const indexes = attributeToPosition[key_ as keyof typeof attributeToPosition];
|
||||
const keyFormatted = key_.replace(/_/g, ' ').split(' ').map((word: string) => word.charAt(0).toUpperCase() + word.slice(1)).join(' ');
|
||||
const mrzAttribute = passportData.mrz.slice(indexes[0], indexes[1] + 1);
|
||||
const mrzAttributeFormatted = formatAttribute(key_, mrzAttribute);
|
||||
|
||||
return (
|
||||
<Fieldset horizontal key={key} gap="$3" alignItems='center'>
|
||||
<Text color={textColor2} w="$10" justifyContent="flex-end" >
|
||||
{keyFormatted}:
|
||||
</Text>
|
||||
<Text
|
||||
color={textColor1}
|
||||
>
|
||||
{hideData ? maskString(mrzAttributeFormatted) : mrzAttributeFormatted}
|
||||
</Text>
|
||||
|
||||
</Fieldset>
|
||||
);
|
||||
})}
|
||||
</YStack>
|
||||
<YStack f={1} />
|
||||
|
||||
<XStack mt="$6" bg={componentBgColor} borderRadius={100} borderWidth={1} borderColor={borderColor} py="$2.5" px="$3">
|
||||
<Info alignSelf='center' size={24} color={textColor1} />
|
||||
<Text ml="$3" pr="$6" fontSize="$3" color={textColor1}>Your information will remain confidential and will not be used or shared without your explicit consent.</Text>
|
||||
</XStack>
|
||||
<Button
|
||||
mt="$8"
|
||||
alignSelf='center'
|
||||
onPress={() => setStep(Steps.REGISTER)}
|
||||
borderWidth={1.3} borderColor={borderColor} borderRadius="$10" bg="#3185FC"
|
||||
mb="$6"
|
||||
w="100%"
|
||||
>
|
||||
<Text color="white" fontSize="$5">Next</Text>
|
||||
</Button>
|
||||
</YStack >
|
||||
</YStack >
|
||||
);
|
||||
};
|
||||
|
||||
export default NextScreen;
|
||||
@@ -53,7 +53,7 @@ const NfcScreen: React.FC<NfcScreenProps> = ({ handleNFCScan }) => {
|
||||
|
||||
</YStack>
|
||||
|
||||
<YStack gap="$2">
|
||||
<YStack gap="$2" mb="$6">
|
||||
<Button borderWidth={1.3} borderColor={borderColor} borderRadius="$10" bg="#3185FC" onPress={handleNFCScan}><Nfc color={textColor1} /></Button>
|
||||
</YStack>
|
||||
|
||||
|
||||
61
app/src/screens/RegisterScreen.tsx
Normal file
61
app/src/screens/RegisterScreen.tsx
Normal file
@@ -0,0 +1,61 @@
|
||||
import React, { useState } from 'react';
|
||||
import { YStack, XStack, Text, Button, Spinner } from 'tamagui';
|
||||
import { LockKeyhole } from '@tamagui/lucide-icons';
|
||||
import { borderColor, componentBgColor, componentBgColor2, textColor1, textColor2 } from '../utils/colors';
|
||||
import { Platform } from 'react-native';
|
||||
import useUserStore from '../stores/userStore';
|
||||
import useNavigationStore from '../stores/navigationStore';
|
||||
|
||||
const RegisterScreen: React.FC = () => {
|
||||
|
||||
const [registering, setRegistering] = useState(false);
|
||||
|
||||
const { isZkeyDownloading } = useNavigationStore.getState();
|
||||
|
||||
const handleRegister = async () => {
|
||||
setRegistering(true);
|
||||
useUserStore.getState().registerCommitment()
|
||||
}
|
||||
|
||||
return (
|
||||
<YStack px="$4" f={1} mb={Platform.OS === 'ios' ? "$5" : "$0"}>
|
||||
<YStack flex={1} mx="$2" gap="$2">
|
||||
<Text mt="$12" color={textColor1} fontSize="$10" fontWeight="bold">
|
||||
Register
|
||||
</Text>
|
||||
<Text mt="$6" fontSize="$6" color={textColor1}>Join Proof of Passport to affirm your identity and start sharing securely.</Text>
|
||||
<Text mt="$1" fontSize="$4" color={textColor2}>Easily verify your nationality, gender, or age and take control of your personal data.</Text>
|
||||
<Text fontSize="$4" color={textColor2}>Share only what you want with the application you wish.</Text>
|
||||
<YStack f={1} />
|
||||
|
||||
<XStack mt="$5" bg={componentBgColor} borderRadius={100} borderWidth={1} borderColor={borderColor} py="$2" px="$3">
|
||||
<XStack bg={componentBgColor2} borderRadius={100} p="$2" >
|
||||
<LockKeyhole alignSelf='center' size={24} color={textColor1} />
|
||||
|
||||
</XStack>
|
||||
<Text alignSelf='center' ml="$3" pr="$5" fontSize="$3" color={textColor1}>Registration does not leak any personal information</Text>
|
||||
|
||||
</XStack>
|
||||
|
||||
<Button
|
||||
disabled={isZkeyDownloading.register_sha256WithRSAEncryption_65537}
|
||||
mt="$8"
|
||||
alignSelf='center'
|
||||
onPress={handleRegister}
|
||||
borderWidth={1.3} borderColor={borderColor} borderRadius="$10" bg={isZkeyDownloading.register_sha256WithRSAEncryption_65537 ? "gray" : "#3185FC"}
|
||||
mb="$6"
|
||||
w="100%"
|
||||
>
|
||||
<XStack gap="$2.5">
|
||||
{(registering || isZkeyDownloading.register_sha256WithRSAEncryption_65537) && <Spinner color="white" size="small" />}
|
||||
<Text color="white" fontSize="$5" >
|
||||
{isZkeyDownloading.register_sha256WithRSAEncryption_65537 ? "Downloading zkey..." : (registering ? "Registering..." : "Register")}
|
||||
</Text>
|
||||
</XStack>
|
||||
</Button>
|
||||
</YStack >
|
||||
</YStack >
|
||||
);
|
||||
};
|
||||
|
||||
export default RegisterScreen;
|
||||
@@ -1,183 +0,0 @@
|
||||
import React from 'react';
|
||||
import { YStack, Text, XStack, Button, Image, ScrollView } from 'tamagui';
|
||||
import { Steps } from '../utils/utils';
|
||||
import { Camera, ExternalLink, Nfc, X } from '@tamagui/lucide-icons';
|
||||
import { blueColorDark, blueColorLight, borderColor, componentBgColor2, greenColorDark, greenColorLight, redColorDark, redColorLight, textColor1, textColor2 } from '../utils/colors';
|
||||
import { useToastController } from '@tamagui/toast'
|
||||
import NFCHelp from '../images/nfc_help.png'
|
||||
import SCANHelp from '../images/scan_help.png'
|
||||
import { Linking } from 'react-native';
|
||||
import { startCameraScan } from '../utils/cameraScanner';
|
||||
|
||||
interface ScanScreenProps {
|
||||
handleNFCScan: () => void;
|
||||
step: number;
|
||||
}
|
||||
|
||||
|
||||
const ScanScreen: React.FC<ScanScreenProps> = ({ handleNFCScan, step }) => {
|
||||
return (
|
||||
<ScrollView f={1}>
|
||||
<YStack mt="$4" mb="$6" f={1} p="$5" gap="$5" px="$5" justifyContent='center'>
|
||||
|
||||
|
||||
<YStack bc="#1c1c1c" borderWidth={1.2} borderColor="#343434" borderRadius="$6">
|
||||
<YStack p="$3">
|
||||
<XStack gap="$4" ai="center">
|
||||
<XStack p="$2" bc="#232323" borderWidth={1.2} borderColor="#343434" borderRadius="$3">
|
||||
<Camera color="#a0a0a0" />
|
||||
</XStack>
|
||||
<YStack gap="$1">
|
||||
<Text fontSize={16} fow="bold" color="#ededed">Step 1</Text>
|
||||
<Text color="#a0a0a0">Scan your passport </Text>
|
||||
</YStack>
|
||||
</XStack>
|
||||
</YStack>
|
||||
<YStack gap="$2" p="$3" bc="#232323" borderWidth={1.2} borderLeftWidth={0} borderRightWidth={0} borderColor="#343434">
|
||||
<Image borderRadius="$5"
|
||||
w="full"
|
||||
h="$13"
|
||||
source={{ uri: SCANHelp }}
|
||||
/>
|
||||
<Text mt="$1" color={textColor1}>Use your camera to scan the main page of your passport.</Text>
|
||||
<Text fontSize="$2" style={{ fontStyle: 'italic' }} color={textColor2}>No personal data will be stored or shared with external apps.</Text>
|
||||
|
||||
</YStack>
|
||||
<YStack p="$2">
|
||||
<XStack gap="$4" ai="center">
|
||||
{step >= Steps.MRZ_SCAN_COMPLETED ? (
|
||||
<XStack ml="$2" p="$2" px="$3" bc="#0d1e18" borderRadius="$10">
|
||||
<Text color="#3bb178" fow="bold">Done</Text>
|
||||
</XStack>
|
||||
) : (
|
||||
<XStack ml="$2" p="$2" px="$3" bc={blueColorDark} borderRadius="$10">
|
||||
<Text color={blueColorLight} fow="bold">To-do</Text>
|
||||
</XStack>
|
||||
)}
|
||||
<XStack f={1} />
|
||||
<Button h="$3" onPress={startCameraScan} p="$2" borderRadius="$4" borderWidth={1} backgroundColor="#282828" borderColor="#343434">
|
||||
<XStack gap="$2">
|
||||
<Text color="#ededed" fontSize="$5" >Open camera</Text>
|
||||
<ExternalLink size="$1" color="#ededed" />
|
||||
</XStack>
|
||||
</Button>
|
||||
</XStack>
|
||||
</YStack>
|
||||
</YStack >
|
||||
|
||||
<YStack bc="#1c1c1c" borderWidth={1.2} borderColor="#343434" borderRadius="$6">
|
||||
<YStack p="$3">
|
||||
<XStack gap="$4" ai="center">
|
||||
<XStack p="$2" bc="#232323" borderWidth={1.2} borderColor="#343434" borderRadius="$3">
|
||||
<Nfc color="#a0a0a0" />
|
||||
</XStack>
|
||||
<YStack gap="$1">
|
||||
<Text fontSize={16} fow="bold" color="#ededed">Step 2</Text>
|
||||
<Text color="#a0a0a0">Read the NFC chip </Text>
|
||||
</YStack>
|
||||
</XStack>
|
||||
</YStack>
|
||||
<XStack gap="$2.5" p="$3" bc="#232323" borderWidth={1.2} borderLeftWidth={0} borderRightWidth={0} borderColor="#343434">
|
||||
<Image borderRadius="$5"
|
||||
w="$12"
|
||||
h="$14"
|
||||
source={{ uri: NFCHelp }}
|
||||
/>
|
||||
<YStack w="$13" jc="space-between">
|
||||
<Text color={textColor1}>Hold your passport against your device to read the biometric chip.</Text>
|
||||
<Text color={textColor1}>Follow <Text onPress={() => Linking.openURL('https://zk-passport.github.io/posts/how-to-scan-your-passport-using-nfc/')} color={blueColorLight} style={{ textDecorationLine: 'underline', fontStyle: 'italic' }}>this guide</Text> if you have trouble reading your passport.</Text>
|
||||
<Text fontSize="$2" color={textColor2} style={{ fontStyle: 'italic' }}>No personnal data will be stored or shared with external apps.</Text>
|
||||
|
||||
|
||||
</YStack>
|
||||
</XStack>
|
||||
<YStack p="$2">
|
||||
<XStack gap="$4" ai="center">
|
||||
{step < Steps.MRZ_SCAN_COMPLETED ? (
|
||||
<YStack ml="$2" p="$2" px="$3" bc="#282828" borderRadius="$10">
|
||||
<Text color="#a0a0a0" fontWeight="bold">To-do</Text>
|
||||
</YStack>
|
||||
) : step < Steps.NFC_SCAN_COMPLETED ? (
|
||||
<XStack ml="$2" p="$2" px="$3" bc={blueColorDark} borderRadius="$10">
|
||||
<Text color={blueColorLight} fow="bold">To-do</Text>
|
||||
</XStack>
|
||||
) : (
|
||||
<XStack ml="$2" p="$2" px="$3" bc="#0d1e18" borderRadius="$10">
|
||||
<Text color="#3bb178" fow="bold">Done</Text>
|
||||
</XStack>
|
||||
)}
|
||||
<XStack f={1} />
|
||||
<Button h="$3" onPress={handleNFCScan} p="$2" borderRadius="$4" borderWidth={1} backgroundColor="#282828" borderColor="#343434">
|
||||
<XStack gap="$2">
|
||||
<Text color={step < Steps.MRZ_SCAN_COMPLETED ? "#a0a0a0" : "#ededed"} fontSize="$5" >Scan with NFC</Text>
|
||||
<ExternalLink size="$1" color={step < Steps.MRZ_SCAN_COMPLETED ? "#a0a0a0" : "#ededed"} />
|
||||
</XStack>
|
||||
</Button>
|
||||
</XStack>
|
||||
</YStack>
|
||||
</YStack >
|
||||
|
||||
|
||||
|
||||
|
||||
{/*
|
||||
<XStack
|
||||
jc="center"
|
||||
borderColor="#a0a0a0"
|
||||
borderWidth={1}
|
||||
borderRadius="$10"
|
||||
f={0}
|
||||
w="$1.5"
|
||||
h="$1.5"
|
||||
alignSelf='center'>
|
||||
<Text color="#a0a0a0" fontSize="$4" y={0} x={0} alignSelf='center'>1</Text>
|
||||
</XStack>
|
||||
<Text color="#a0a0a0" fontSize="$6" textAlign='center' mt="$2" >Scan the machine readable zone on the main page of your passport</Text> */}
|
||||
|
||||
{/* <XStack
|
||||
mt="$10"
|
||||
jc="center"
|
||||
borderColor="#a0a0a0"
|
||||
borderWidth={1}
|
||||
borderRadius="$10"
|
||||
f={0}
|
||||
w="$1.5"
|
||||
h="$1.5"
|
||||
alignSelf='center'>
|
||||
<Text color="#a0a0a0" fontSize="$4" y={0} x={0} alignSelf='center'>2</Text>
|
||||
</XStack>
|
||||
<Text color="#a0a0a0" fontSize="$6" textAlign='center' mt="$2" >Hold your passport against your device to read the biometric chip</Text> */}
|
||||
{/*
|
||||
<YStack ai="center">
|
||||
{
|
||||
step < Steps.NFC_SCAN_COMPLETED
|
||||
? (
|
||||
step < Steps.MRZ_SCAN_COMPLETED
|
||||
?
|
||||
<YStack mt="$6">
|
||||
<Button borderWidth={1} backgroundColor="#282828" borderColor="#343434" variant="outlined">
|
||||
<Camera color="#ededed" />
|
||||
<Text color="#ededed" fontSize="$6" onPress={onStartCameraScan} >Open camera</Text>
|
||||
</Button>
|
||||
<Spinner mt="$4" color={step === Steps.NFC_SCANNING ? "#3185FC" : "transparent"} />
|
||||
|
||||
</YStack>
|
||||
: (
|
||||
<YStack mt="$6">
|
||||
<Text p="$6" fontSize="$6" color="#3185FC" onPress={handleNFCScan}>
|
||||
{step === Steps.NFC_SCANNING ? "Scanning" : "Scan passport with NFC"}
|
||||
</Text>
|
||||
<Spinner mt="$4" color={step === Steps.NFC_SCANNING ? "#3185FC" : "transparent"} />
|
||||
</YStack>
|
||||
)
|
||||
)
|
||||
:
|
||||
<XStack />
|
||||
}
|
||||
</YStack> */}
|
||||
</YStack >
|
||||
</ScrollView>
|
||||
);
|
||||
};
|
||||
|
||||
export default ScanScreen;
|
||||
@@ -28,7 +28,7 @@ interface UserState {
|
||||
secret: string
|
||||
initUserStore: () => void
|
||||
registerPassportData: (passportData: PassportData) => void
|
||||
registerCommitment: (secret: string, passportData: PassportData) => void
|
||||
registerCommitment: (passportData?: PassportData) => void
|
||||
clearPassportDataFromStorage: () => void
|
||||
clearSecretFromStorage: () => void
|
||||
update: (patch: any) => void
|
||||
@@ -68,7 +68,7 @@ const useUserStore = create<UserState>((set, get) => ({
|
||||
passportData: JSON.parse(passportData),
|
||||
registered: true,
|
||||
});
|
||||
useNavigationStore.getState().setStep(Steps.NFC_SCAN_COMPLETED); // this means go to app selection screen
|
||||
useNavigationStore.getState().setStep(Steps.REGISTERED); // this means go to app selection screen
|
||||
|
||||
// TODO: check if the commitment is already registered, if not retry registering it
|
||||
|
||||
@@ -81,7 +81,6 @@ const useUserStore = create<UserState>((set, get) => ({
|
||||
// - Check presence of secret. If there is none, create one and store it
|
||||
// - Store the passportData and try registering the commitment in the background
|
||||
registerPassportData: async (passportData) => {
|
||||
const secret = await loadSecret() as string;
|
||||
|
||||
const alreadyStoredPassportData = await loadPassportData();
|
||||
|
||||
@@ -92,17 +91,21 @@ const useUserStore = create<UserState>((set, get) => ({
|
||||
|
||||
await storePassportData(passportData)
|
||||
set({ passportData });
|
||||
|
||||
get().registerCommitment(
|
||||
secret,
|
||||
passportData
|
||||
)
|
||||
},
|
||||
|
||||
registerCommitment: async (secret, passportData) => {
|
||||
registerCommitment: async (mockPassportData?: PassportData) => {
|
||||
const {
|
||||
toast
|
||||
} = useNavigationStore.getState();
|
||||
const secret = await loadSecret() as string;
|
||||
let passportData = get().passportData
|
||||
if (mockPassportData) {
|
||||
passportData = mockPassportData
|
||||
}
|
||||
console.log("register commitment")
|
||||
console.log("sig alg: in userstore", passportData.signatureAlgorithm)
|
||||
console.log(secret)
|
||||
console.log(passportData)
|
||||
|
||||
try {
|
||||
const inputs = generateCircuitInputsRegister(
|
||||
@@ -113,7 +116,7 @@ const useUserStore = create<UserState>((set, get) => ({
|
||||
);
|
||||
|
||||
amplitude.track(`Sig alg supported: ${passportData.signatureAlgorithm}`);
|
||||
|
||||
|
||||
Object.keys(inputs).forEach((key) => {
|
||||
if (Array.isArray(inputs[key as keyof typeof inputs])) {
|
||||
console.log(key, inputs[key as keyof typeof inputs].slice(0, 10), '...');
|
||||
@@ -121,7 +124,7 @@ const useUserStore = create<UserState>((set, get) => ({
|
||||
console.log(key, inputs[key as keyof typeof inputs]);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
const start = Date.now();
|
||||
|
||||
const sigAlgFormatted = formatSigAlgNameForCircuit(passportData.signatureAlgorithm, passportData.pubKey.exponent);
|
||||
|
||||
@@ -17,8 +17,8 @@ export const scan = async () => {
|
||||
dateOfBirth,
|
||||
dateOfExpiry
|
||||
} = useUserStore.getState()
|
||||
|
||||
const {toast, setStep} = useNavigationStore.getState();
|
||||
|
||||
const { toast, setStep } = useNavigationStore.getState();
|
||||
|
||||
const check = checkInputs(
|
||||
passportNumber,
|
||||
@@ -52,7 +52,7 @@ const scanAndroid = async () => {
|
||||
dateOfBirth,
|
||||
dateOfExpiry
|
||||
} = useUserStore.getState()
|
||||
const {toast, setStep} = useNavigationStore.getState();
|
||||
const { toast, setStep } = useNavigationStore.getState();
|
||||
|
||||
try {
|
||||
const response = await PassportReader.scan({
|
||||
@@ -83,7 +83,7 @@ const scanIOS = async () => {
|
||||
dateOfBirth,
|
||||
dateOfExpiry
|
||||
} = useUserStore.getState()
|
||||
const {toast, setStep} = useNavigationStore.getState();
|
||||
const { toast, setStep } = useNavigationStore.getState();
|
||||
|
||||
try {
|
||||
const response = await NativeModules.PassportReader.scanPassport(
|
||||
@@ -112,7 +112,7 @@ const scanIOS = async () => {
|
||||
const handleResponseIOS = async (
|
||||
response: any,
|
||||
) => {
|
||||
const {toast} = useNavigationStore.getState();
|
||||
const { toast } = useNavigationStore.getState();
|
||||
|
||||
const parsed = JSON.parse(response);
|
||||
|
||||
@@ -177,7 +177,7 @@ const handleResponseIOS = async (
|
||||
console.log("photoBase64", passportData.photoBase64.substring(0, 100) + '...')
|
||||
|
||||
useUserStore.getState().registerPassportData(passportData)
|
||||
useNavigationStore.getState().setStep(Steps.NFC_SCAN_COMPLETED);
|
||||
useNavigationStore.getState().setStep(Steps.NEXT_SCREEN);
|
||||
} catch (e: any) {
|
||||
console.log('error during parsing:', e);
|
||||
useNavigationStore.getState().setStep(Steps.MRZ_SCAN_COMPLETED);
|
||||
@@ -231,7 +231,7 @@ const handleResponseAndroid = async (
|
||||
...passportData,
|
||||
photoBase64: passportData.photoBase64.substring(0, 100) + '...'
|
||||
}, null, 2));
|
||||
|
||||
|
||||
console.log('mrz', passportData.mrz);
|
||||
console.log('signatureAlgorithm', passportData.signatureAlgorithm);
|
||||
console.log('pubKey', passportData.pubKey);
|
||||
@@ -247,5 +247,5 @@ const handleResponseAndroid = async (
|
||||
console.log("encapContent", encapContent)
|
||||
|
||||
useUserStore.getState().registerPassportData(passportData)
|
||||
useNavigationStore.getState().setStep(Steps.NFC_SCAN_COMPLETED);
|
||||
useNavigationStore.getState().setStep(Steps.NEXT_SCREEN);
|
||||
};
|
||||
@@ -37,12 +37,14 @@ export const Steps = {
|
||||
MRZ_SCAN: 1,
|
||||
MRZ_SCAN_COMPLETED: 2,
|
||||
NFC_SCANNING: 3,
|
||||
NFC_SCAN_COMPLETED: 4,
|
||||
APP_SELECTED: 5,
|
||||
GENERATING_PROOF: 6,
|
||||
PROOF_GENERATED: 7,
|
||||
PROOF_SENDING: 8,
|
||||
PROOF_SENT: 9
|
||||
NEXT_SCREEN: 4,
|
||||
REGISTER: 5,
|
||||
REGISTERED: 6,
|
||||
APP_SELECTED: 7,
|
||||
GENERATING_PROOF: 8,
|
||||
PROOF_GENERATED: 9,
|
||||
PROOF_SENDING: 10,
|
||||
PROOF_SENT: 11
|
||||
};
|
||||
|
||||
export function formatAttribute(key: string, attribute: string) {
|
||||
@@ -54,6 +56,17 @@ export function formatAttribute(key: string, attribute: string) {
|
||||
} else if (key === 'nationality' && attribute in countryCodes) {
|
||||
return countryCodes[attribute as keyof typeof countryCodes]
|
||||
}
|
||||
else if (key === 'date_of_birth') {
|
||||
let year = '19' + attribute.substring(0, 2);
|
||||
const currentYear = 2024;
|
||||
const birthYear = parseInt(year);
|
||||
if (currentYear - birthYear > 100) {
|
||||
year = '20' + attribute.substring(0, 2);
|
||||
}
|
||||
const month = attribute.substring(2, 4);
|
||||
const day = attribute.substring(4, 6);
|
||||
return `${year}-${month}-${day}`; // ISO 8601 format (YYYY-MM-DD)
|
||||
}
|
||||
return attribute;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user