add ens address management, improve regex and keyboard management

This commit is contained in:
Rémi Colin
2024-02-14 14:15:57 +01:00
parent ff11cadb21
commit 6052aee6fa
7 changed files with 148 additions and 46 deletions

View File

@@ -31,7 +31,7 @@ import {
import { samplePassportData } from '../common/src/utils/passportDataStatic';
import "@ethersproject/shims"
import { ethers } from "ethers";
import { ethers, ZeroAddress } from "ethers";
import axios from 'axios';
import groth16ExportSolidityCallData from './utils/snarkjs';
import contractAddresses from "./deployments/addresses.json"
@@ -59,7 +59,7 @@ function App(): JSX.Element {
const [passportNumber, setPassportNumber] = useState(DEFAULT_PNUMBER ?? "");
const [dateOfBirth, setDateOfBirth] = useState(DEFAULT_DOB ?? '');
const [dateOfExpiry, setDateOfExpiry] = useState(DEFAULT_DOE ?? '');
const [address, setAddress] = useState(DEFAULT_ADDRESS ?? '');
const [address, setAddress] = useState<string>(ethers.ZeroAddress);
const [passportData, setPassportData] = useState<PassportData>(samplePassportData as PassportData);
const [step, setStep] = useState<number>(Steps.MRZ_SCAN);
const [error, setError] = useState<any>(null);

View File

@@ -20,7 +20,7 @@
"body-parser": "^1.20.2",
"buffer": "^6.0.3",
"crypto-js": "^4.1.1",
"ethers": "^6.9.1",
"ethers": "^6.11.0",
"express": "^4.18.2",
"js-sha256": "^0.9.0",
"node-forge": "^1.3.1",

View File

@@ -32,7 +32,6 @@ const AppCard: React.FC<AppCardProps> = ({
borderColor={(selected) ? "#3185FC" : ((Platform.OS === 'ios') ? "white" : "transparent")}
borderWidth={(selected) ? 3 : 3}
shadowColor={selected ? "#3185FC" : "black"}
animation="quick"
>
<Card
key={id}

View File

@@ -7,6 +7,7 @@ import { Steps } from '../utils/utils';
import AppScreen from './AppScreen';
import { App } from '../utils/AppClass';
import { Platform } from 'react-native';
import { Keyboard } from 'react-native';
import NFC_IMAGE from '../images/nfc.png'
@@ -58,6 +59,7 @@ const MainScreen: React.FC<MainScreenProps> = ({
setDateOfExpiry
}) => {
const [isOpen, setIsOpen] = useState(false);
const [ens, setEns] = useState<string>('');
const [selectedTab, setSelectedTab] = useState("scan");
const [selectedApp, setSelectedApp] = useState<App | null>(null);
const [brokenCamera, setBrokenCamera] = useState(false);
@@ -119,6 +121,24 @@ const MainScreen: React.FC<MainScreenProps> = ({
};
}, [step]);
// Keyboard management
const [keyboardVisible, setKeyboardVisible] = useState(false);
useEffect(() => {
const showSubscription = Keyboard.addListener('keyboardDidShow', () => {
setKeyboardVisible(true);
});
const hideSubscription = Keyboard.addListener('keyboardDidHide', () => {
setKeyboardVisible(false);
});
return () => {
showSubscription.remove();
hideSubscription.remove();
};
}, []);
return (
<YStack f={1} bc="white" mt={Platform.OS === 'ios' ? "$8" : "$0"} mb={Platform.OS === 'ios' ? "$3" : "$0"}>
@@ -419,50 +439,55 @@ const MainScreen: React.FC<MainScreenProps> = ({
proof={proof}
proofTime={proofTime}
handleMint={handleMint}
hideData={hideData} />
hideData={hideData}
ens={ens}
setEns={setEns} />
</Tabs.Content>
<Separator />
{keyboardVisible == false &&
<Tabs.List separator={<Separator vertical />} pt="$4" pb="$3">
<Tabs.Tab value="scan" unstyled w="33%">
<YStack ai="center">
<Scan color={selectedTab === "scan" ? '#3185FC' : 'black'} />
<Text color={selectedTab === "scan" ? '#3185FC' : 'black'}>Scan</Text>
</YStack>
</Tabs.Tab>
{step >= Steps.NFC_SCAN_COMPLETED ?
<Tabs.Tab value="app" unstyled w="33%">
<YStack ai="center">
<LayoutGrid color={selectedTab === "app" ? '#3185FC' : 'black'} />
<Text color={selectedTab === "app" ? '#3185FC' : 'black'}>Apps</Text>
</YStack>
</Tabs.Tab>
:
<Tabs.List separator={<Separator vertical />} pt="$4" pb="$3">
<Tabs.Tab value="scan" unstyled w="33%">
<YStack ai="center">
<LayoutGrid color="#bcbcbc" />
<Text color="#bcbcbc">Apps</Text>
<Scan color={selectedTab === "scan" ? '#3185FC' : 'black'} />
<Text color={selectedTab === "scan" ? '#3185FC' : 'black'}>Scan</Text>
</YStack>
</Tabs.Tab>
}
{
(step >= Steps.NFC_SCAN_COMPLETED) && (selectedApp != null) ?
<Tabs.Tab value="generate" unstyled w="33%">
{step >= Steps.NFC_SCAN_COMPLETED ?
<Tabs.Tab value="app" unstyled w="33%">
<YStack ai="center">
<UserCheck color={selectedTab === "generate" ? '#3185FC' : 'black'} />
<Text color={selectedTab === "generate" ? '#3185FC' : 'black'}>Prove</Text>
<LayoutGrid color={selectedTab === "app" ? '#3185FC' : 'black'} />
<Text color={selectedTab === "app" ? '#3185FC' : 'black'}>Apps</Text>
</YStack>
</Tabs.Tab>
:
<Tabs.Tab value={step >= Steps.NFC_SCAN_COMPLETED ? "app" : "scan"} unstyled w="33%">
<Tabs.Tab value="scan" unstyled w="33%">
<YStack ai="center">
<UserCheck color="#bcbcbc" />
<Text color="#bcbcbc">Prove</Text>
<LayoutGrid color="#bcbcbc" />
<Text color="#bcbcbc">Apps</Text>
</YStack>
</Tabs.Tab>
}
</Tabs.List>
}
{
(step >= Steps.NFC_SCAN_COMPLETED) && (selectedApp != null) ?
<Tabs.Tab value="generate" unstyled w="33%">
<YStack ai="center">
<UserCheck color={selectedTab === "generate" ? '#3185FC' : 'black'} />
<Text color={selectedTab === "generate" ? '#3185FC' : 'black'}>Prove</Text>
</YStack>
</Tabs.Tab>
:
<Tabs.Tab value={step >= Steps.NFC_SCAN_COMPLETED ? "app" : "scan"} unstyled w="33%">
<YStack ai="center">
<UserCheck color="#bcbcbc" />
<Text color="#bcbcbc">Prove</Text>
</YStack>
</Tabs.Tab>
}
</Tabs.List>
}
</Tabs>
</YStack >
);

View File

@@ -8,6 +8,11 @@ import USER from '../images/user.png'
import ProofGrid from '../components/ProofGrid';
import { App } from '../utils/AppClass';
import { Keyboard } from 'react-native';
const { ethers } = require('ethers');
/// j'input un string, si c'est .eth ça la converti en address et la diplay si c'ets la longueur, ça la set
///
interface ProveScreenProps {
selectedApp: App | null;
@@ -24,6 +29,8 @@ interface ProveScreenProps {
proof: { proof: string, inputs: string } | null;
proofTime: number;
hideData: boolean;
ens: string;
setEns: (ens: string) => void;
}
const ProveScreen: React.FC<ProveScreenProps> = ({
@@ -40,13 +47,74 @@ const ProveScreen: React.FC<ProveScreenProps> = ({
proof,
proofTime,
handleMint,
hideData
hideData,
ens,
setEns
}) => {
const maskString = (input: string): string => {
return '*'.repeat(input.length);
if (input.length <= 5) {
return input.charAt(0) + '*'.repeat(input.length - 1);
} else {
return input.charAt(0) + input.charAt(1) + '*'.repeat(input.length - 2);
}
}
const [inputValue, setInputValue] = useState('');
const provider = new ethers.JsonRpcProvider(`https://eth-mainnet.g.alchemy.com/v2/lpOn3k6Fezetn1e5QF-iEsn-J0C6oGE0`);
useEffect(() => {
if (ens != '') {
setInputValue(ens);
}
else if (address != ethers.ZeroAddress) {
setInputValue(address);
}
}, [])
useEffect(() => {
const resolveENS = async () => {
if (inputValue)
if (inputValue.endsWith('.eth')) {
try {
const resolvedAddress = await provider.resolveName(inputValue);
console.log(resolvedAddress);
if (resolvedAddress) {
setAddress(resolvedAddress);
setEns(inputValue);
console.log("new address settled:" + address);
if (hideData) {
console.log(maskString(address));
// setInputValue(maskString(address));
}
else {
// setInputValue(address);
}
} else {
console.error("Could not resolve ENS name.");
}
} catch (error) {
console.error("Error resolving ENS name:", error);
}
} else if (inputValue.length === 42 && inputValue.startsWith('0x')) {
setAddress(inputValue);
}
};
resolveENS();
}, [inputValue]);
// Keyboard management
const [keyboardVisible, setKeyboardVisible] = useState(false);
useEffect(() => {
@@ -63,7 +131,6 @@ const ProveScreen: React.FC<ProveScreenProps> = ({
};
}, []);
return (
<YStack px="$4" f={1}>
{(step >= Steps.NFC_SCAN_COMPLETED && selectedApp != null) ?
@@ -88,18 +155,22 @@ const ProveScreen: React.FC<ProveScreenProps> = ({
fontSize={13}
mt="$3"
placeholder="Your Address or ens name"
value={address}
onChangeText={setAddress}
value={inputValue}
onChangeText={setInputValue}
autoCorrect={false}
autoCapitalize='none'
borderColor={address != ethers.ZeroAddress ? "#3185FC" : "unset"}
/>
<YStack mt="$6" f={1}>
{!keyboardVisible && <YStack mt="$6" f={1}>
<Text h="$3">{selectedApp?.disclosurephrase}</Text>
<YStack mt="$1">
{selectedApp && Object.keys(selectedApp.disclosure).map((key) => {
const key_ = key as string;
const indexes = attributeToPosition[key_];
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]);
const mrzAttributeFormatted = mrzAttribute.replace(/</g, ' ');
const mrzAttribute = passportData.mrz.slice(indexes[0], indexes[1] + 1);
const mrzAttributeFormatted = mrzAttribute;
return (
<XStack key={key} m="$2" gap="$4">
@@ -120,11 +191,11 @@ const ProveScreen: React.FC<ProveScreenProps> = ({
);
})}
</YStack>
</YStack>
</YStack>}
<XStack f={1} />
<XStack f={1} />
<XStack f={1} />
<Button borderRadius={100} onPress={handleProve} mt="$8" backgroundColor="#3185FC" alignSelf='center' >
{!keyboardVisible && <Button borderRadius={100} onPress={handleProve} mt="$8" backgroundColor="#3185FC" alignSelf='center' >
{generatingProof ? (
<XStack ai="center">
<Spinner />
@@ -133,10 +204,11 @@ const ProveScreen: React.FC<ProveScreenProps> = ({
) : (
<Text color="white" fow="bold">Generate ZK proof</Text>
)}
</Button>
</Button>}
<Text fontSize={10} color={generatingProof ? "gray" : "white"} alignSelf='center'>This operation can take up to 2 mn</Text>
<Text fontSize={9} color={generatingProof ? "gray" : "white"} pb="$2" alignSelf='center'>The application may freeze during this time (hard work)</Text>
</YStack>
) : (
<YStack flex={1} m="$2" justifyContent='center' alignItems='center' gap="$5">
<XStack flex={1} />

View File

@@ -2,13 +2,19 @@ import React from 'react';
import { YStack, Text, Spinner, XStack } from 'tamagui';
import { Steps } from '../utils/utils';
interface ScanScreenProps {
onStartCameraScan: () => void;
handleNFCScan: () => void;
step: number;
}
const ScanScreen: React.FC<ScanScreenProps> = ({ onStartCameraScan, handleNFCScan, step }) => {
return (
<YStack f={1} p="$5" gap="$1" px="$5" justifyContent='center'>
<XStack

View File

@@ -4615,7 +4615,7 @@ etag@~1.8.1:
resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887"
integrity sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==
ethers@^6.9.1:
ethers@^6.11.0:
version "6.11.0"
resolved "https://registry.yarnpkg.com/ethers/-/ethers-6.11.0.tgz#6d3e884ad36454c29d4662ae49439d5d04556c66"
integrity sha512-kPHNTnhVWiWU6AVo6CAeTjXEK24SpCXyZvwG9ROFjT0Vlux0EOhWKBAeC+45iDj80QNJTYaT1SDEmeunT0vDNw==