mirror of
https://github.com/selfxyz/self.git
synced 2026-04-27 03:01:15 -04:00
Merge pull request #84 from zk-passport/android-witnesscalc
Moving to PolygonID's stack on Android
This commit is contained in:
36
app/App.tsx
36
app/App.tsx
@@ -19,7 +19,7 @@ import { YStack } from 'tamagui';
|
||||
import { prove } from './src/utils/prover';
|
||||
import { useToastController } from '@tamagui/toast';
|
||||
import * as amplitude from '@amplitude/analytics-react-native';
|
||||
import { checkForZkey } from './src/utils/zkeyDownload';
|
||||
import { downloadZkey, IsZkeyDownloading, ShowWarningModalProps } from './src/utils/zkeyDownload';
|
||||
import RNFS from 'react-native-fs';
|
||||
global.Buffer = Buffer;
|
||||
|
||||
@@ -40,8 +40,16 @@ function App(): JSX.Element {
|
||||
const [proof, setProof] = useState<Proof | null>(null);
|
||||
const [mintText, setMintText] = useState<string>("");
|
||||
const [majority, setMajority] = useState<number>(18);
|
||||
const [zkeydownloadStatus, setDownloadStatus] = useState<"not_started" | "downloading" | "completed" | "error">("not_started");
|
||||
const [showWarning, setShowWarning] = useState(false);
|
||||
const [isZkeyDownloading, setIsZkeyDownloading] = useState<IsZkeyDownloading>({
|
||||
register_sha256WithRSAEncryption_65537: false,
|
||||
disclose: false,
|
||||
proof_of_passport: false,
|
||||
});
|
||||
const [showWarningModal, setShowWarningModal] = useState<ShowWarningModalProps>({
|
||||
show: false,
|
||||
circuit: "",
|
||||
size: 0,
|
||||
});
|
||||
|
||||
const [disclosure, setDisclosure] = useState({
|
||||
issuing_state: false,
|
||||
@@ -65,12 +73,16 @@ function App(): JSX.Element {
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
checkForZkey({
|
||||
setDownloadStatus,
|
||||
setShowWarning,
|
||||
toast
|
||||
})
|
||||
amplitude.init(AMPLITUDE_KEY);
|
||||
// downloadZkey("register_sha256WithRSAEncryption_65537"); // temporary, might move after nfc scanning
|
||||
// downloadZkey("disclose");
|
||||
downloadZkey(
|
||||
"proof_of_passport",
|
||||
isZkeyDownloading,
|
||||
setIsZkeyDownloading,
|
||||
setShowWarningModal,
|
||||
toast
|
||||
);
|
||||
}, []);
|
||||
|
||||
const handleStartCameraScan = async () => {
|
||||
@@ -144,10 +156,10 @@ function App(): JSX.Element {
|
||||
setDateOfExpiry={setDateOfExpiry}
|
||||
majority={majority}
|
||||
setMajority={setMajority}
|
||||
zkeydownloadStatus={zkeydownloadStatus}
|
||||
showWarning={showWarning}
|
||||
setShowWarning={setShowWarning}
|
||||
setDownloadStatus={setDownloadStatus}
|
||||
isZkeyDownloading={isZkeyDownloading}
|
||||
showWarningModal={showWarningModal}
|
||||
setShowWarningModal={setShowWarningModal}
|
||||
setIsZkeyDownloading={setIsZkeyDownloading}
|
||||
/>
|
||||
</YStack>
|
||||
</YStack>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { useState, useEffect, Profiler } from 'react';
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { YStack, XStack, Text, Button, Tabs, Sheet, Label, Fieldset, Input, Switch, H2, Image, useWindowDimensions, H4, H3, ScrollView } from 'tamagui'
|
||||
import { HelpCircle, IterationCw, VenetianMask, Cog, CheckCircle2, ExternalLink } from '@tamagui/lucide-icons';
|
||||
import X from '../images/x.png'
|
||||
@@ -17,7 +17,7 @@ import { bgColor, blueColorLight, borderColor, componentBgColor, textColor1, tex
|
||||
import MintScreen from './MintScreen';
|
||||
import { ToastViewport, useToastController } from '@tamagui/toast';
|
||||
import { ToastMessage } from '../components/ToastMessage';
|
||||
import { downloadZkey } from '../utils/zkeyDownload';
|
||||
import { CircuitName, fetchZkey, IsZkeyDownloading, ShowWarningModalProps } from '../utils/zkeyDownload';
|
||||
|
||||
interface MainScreenProps {
|
||||
onStartCameraScan: () => void;
|
||||
@@ -43,10 +43,10 @@ interface MainScreenProps {
|
||||
setDateOfExpiry: (date: string) => void;
|
||||
majority: number;
|
||||
setMajority: (age: number) => void;
|
||||
zkeydownloadStatus: string;
|
||||
showWarning: boolean;
|
||||
setShowWarning: (value: boolean) => void;
|
||||
setDownloadStatus: (value: "not_started" | "downloading" | "completed" | "error") => void;
|
||||
isZkeyDownloading: IsZkeyDownloading;
|
||||
showWarningModal: ShowWarningModalProps;
|
||||
setShowWarningModal: (value: ShowWarningModalProps) => void;
|
||||
setIsZkeyDownloading: (value: IsZkeyDownloading) => void;
|
||||
}
|
||||
|
||||
const MainScreen: React.FC<MainScreenProps> = ({
|
||||
@@ -73,10 +73,10 @@ const MainScreen: React.FC<MainScreenProps> = ({
|
||||
setDateOfExpiry,
|
||||
majority,
|
||||
setMajority,
|
||||
zkeydownloadStatus,
|
||||
showWarning,
|
||||
setShowWarning,
|
||||
setDownloadStatus
|
||||
isZkeyDownloading,
|
||||
showWarningModal,
|
||||
setShowWarningModal,
|
||||
setIsZkeyDownloading
|
||||
}) => {
|
||||
const [NFCScanIsOpen, setNFCScanIsOpen] = useState(false);
|
||||
const [SettingsIsOpen, setSettingsIsOpen] = useState(false);
|
||||
@@ -442,7 +442,9 @@ const MainScreen: React.FC<MainScreenProps> = ({
|
||||
setEns={setEns}
|
||||
majority={majority}
|
||||
setMajority={setMajority}
|
||||
zkeydownloadStatus={zkeydownloadStatus}
|
||||
isZkeyDownloading={isZkeyDownloading}
|
||||
setIsZkeyDownloading={setIsZkeyDownloading}
|
||||
setShowWarningModal={setShowWarningModal}
|
||||
/>
|
||||
</Tabs.Content>
|
||||
<Tabs.Content value="mint" f={1}>
|
||||
@@ -457,20 +459,26 @@ const MainScreen: React.FC<MainScreenProps> = ({
|
||||
</Tabs.Content>
|
||||
</Tabs>
|
||||
</YStack>
|
||||
<Modal visible={showWarning} animationType="slide" transparent={true}>
|
||||
<Modal visible={showWarningModal.show} animationType="slide" transparent={true}>
|
||||
<YStack bc="#161616" p={20} ai="center" jc="center" position="absolute" top={0} bottom={0} left={0} right={0}>
|
||||
<YStack bc="#343434" p={20} borderRadius={10} ai="center" jc="center">
|
||||
<Text fontWeight="bold" fontSize={18} color="#a0a0a0">👋 Hi</Text>
|
||||
<Text mt={10} textAlign="center" color="#a0a0a0">
|
||||
The app needs to download a large file (300MB). Please make sure you're connected to a Wi-Fi network before continuing.
|
||||
The app needs to download a large file ({(showWarningModal.size / 1024 / 1024).toFixed(2)}MB). Please make sure you're connected to a Wi-Fi network before continuing.
|
||||
</Text>
|
||||
<XStack mt={20}>
|
||||
<Button onPress={() => {
|
||||
downloadZkey(
|
||||
setDownloadStatus,
|
||||
fetchZkey(
|
||||
showWarningModal.circuit as CircuitName,
|
||||
isZkeyDownloading,
|
||||
setIsZkeyDownloading,
|
||||
toast
|
||||
);
|
||||
setShowWarning(false)
|
||||
setShowWarningModal({
|
||||
show: false,
|
||||
circuit: '',
|
||||
size: 0,
|
||||
})
|
||||
}} bc="#4caf50" borderRadius={5} padding={10}>
|
||||
<Text color="#ffffff">Continue</Text>
|
||||
</Button>
|
||||
|
||||
@@ -12,7 +12,7 @@ import { useToastController } from '@tamagui/toast'
|
||||
import { ethers } from 'ethers';
|
||||
import { Platform } from 'react-native';
|
||||
import { formatAttribute } from '../utils/utils';
|
||||
import { Proof } from '../../../common/src/utils/types';
|
||||
import { downloadZkey, IsZkeyDownloading, ShowWarningModalProps } from '../utils/zkeyDownload';
|
||||
|
||||
interface ProveScreenProps {
|
||||
selectedApp: App | null;
|
||||
@@ -28,7 +28,9 @@ interface ProveScreenProps {
|
||||
setEns: (ens: string) => void;
|
||||
majority: number;
|
||||
setMajority: (age: number) => void;
|
||||
zkeydownloadStatus: string;
|
||||
isZkeyDownloading: IsZkeyDownloading;
|
||||
setIsZkeyDownloading: (value: IsZkeyDownloading) => void;
|
||||
setShowWarningModal: (value: ShowWarningModalProps) => void;
|
||||
}
|
||||
|
||||
const ProveScreen: React.FC<ProveScreenProps> = ({
|
||||
@@ -45,13 +47,33 @@ const ProveScreen: React.FC<ProveScreenProps> = ({
|
||||
setEns,
|
||||
majority,
|
||||
setMajority,
|
||||
zkeydownloadStatus
|
||||
isZkeyDownloading,
|
||||
setIsZkeyDownloading,
|
||||
setShowWarningModal
|
||||
}) => {
|
||||
const { height } = useWindowDimensions();
|
||||
const [inputValue, setInputValue] = useState(DEFAULT_ADDRESS ?? '');
|
||||
const provider = new ethers.JsonRpcProvider(`https://eth-mainnet.g.alchemy.com/v2/lpOn3k6Fezetn1e5QF-iEsn-J0C6oGE0`);
|
||||
const toast = useToastController()
|
||||
const circuit = "proof_of_passport" //later, pass this as input
|
||||
|
||||
useEffect(() => {
|
||||
launchZkeyDownloadIfRequired();
|
||||
|
||||
}, [])
|
||||
|
||||
async function launchZkeyDownloadIfRequired() {
|
||||
if (!isZkeyDownloading[circuit]) {
|
||||
// this already checks if downloading is required
|
||||
downloadZkey(
|
||||
circuit,
|
||||
isZkeyDownloading,
|
||||
setIsZkeyDownloading,
|
||||
setShowWarningModal,
|
||||
toast
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (ens != '' && inputValue == '') {
|
||||
@@ -236,7 +258,7 @@ const ProveScreen: React.FC<ProveScreenProps> = ({
|
||||
</YStack >
|
||||
</YStack >
|
||||
<Button
|
||||
disabled={zkeydownloadStatus != "completed" || (address == ethers.ZeroAddress)}
|
||||
disabled={isZkeyDownloading[circuit] || (address == ethers.ZeroAddress)}
|
||||
borderWidth={1.3}
|
||||
borderColor={borderColor}
|
||||
borderRadius={100}
|
||||
@@ -245,20 +267,13 @@ const ProveScreen: React.FC<ProveScreenProps> = ({
|
||||
backgroundColor={address == ethers.ZeroAddress ? "#cecece" : "#3185FC"}
|
||||
alignSelf='center'
|
||||
>
|
||||
{zkeydownloadStatus === "downloading" ? (
|
||||
{isZkeyDownloading[circuit] ? (
|
||||
<XStack ai="center" gap="$1">
|
||||
<Spinner />
|
||||
<Text color={textColor1} fow="bold">
|
||||
Downloading ZK proving key
|
||||
</Text>
|
||||
</XStack>
|
||||
) : zkeydownloadStatus === "error" ? (
|
||||
<XStack ai="center" gap="$1">
|
||||
<Spinner />
|
||||
<Text color={textColor1} fow="bold">
|
||||
Error downloading ZK proving key
|
||||
</Text>
|
||||
</XStack>
|
||||
) : generatingProof ? (
|
||||
<XStack ai="center" gap="$1">
|
||||
<Spinner />
|
||||
@@ -278,7 +293,6 @@ const ProveScreen: React.FC<ProveScreenProps> = ({
|
||||
</Button>
|
||||
{(height > 750) && <Text fontSize={10} color={generatingProof ? "#a0a0a0" : "#161616"} py="$2" alignSelf='center'>This operation can take up to 2 mn, phone may freeze during this time</Text>}
|
||||
</YStack >
|
||||
|
||||
</YStack >
|
||||
);
|
||||
};
|
||||
|
||||
@@ -4,7 +4,7 @@ import groth16ExportSolidityCallData from '../../utils/snarkjs';
|
||||
import contractAddresses from "../../deployments/addresses.json";
|
||||
import proofOfPassportArtefact from "../../deployments/ProofOfPassport.json";
|
||||
import { Steps } from './utils';
|
||||
import { AWS_ENDPOINT } from '../../../common/src/constants/constants';
|
||||
import { RELAYER_URL } from '../../../common/src/constants/constants';
|
||||
import { Proof } from "../../../common/src/utils/types";
|
||||
|
||||
interface MinterProps {
|
||||
@@ -42,7 +42,7 @@ export const mint = async ({ proof, setStep, setMintText, toast }: MinterProps)
|
||||
.mint.populateTransaction(...callData);
|
||||
console.log('transactionRequest', transactionRequest);
|
||||
|
||||
const response = await axios.post(AWS_ENDPOINT, {
|
||||
const response = await axios.post(RELAYER_URL, {
|
||||
chain: "sepolia",
|
||||
tx_data: transactionRequest
|
||||
});
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { NativeModules, Platform } from 'react-native';
|
||||
import { revealBitmapFromMapping } from '../../../common/src/utils/revealBitmap';
|
||||
import { generateCircuitInputs } from '../../../common/src/utils/generateInputs';
|
||||
import { Steps } from './utils';
|
||||
import { parseProofAndroid, Steps } from './utils';
|
||||
import { PassportData, Proof } from '../../../common/src/utils/types';
|
||||
import * as amplitude from '@amplitude/analytics-react-native';
|
||||
import RNFS from 'react-native-fs';
|
||||
@@ -14,7 +14,7 @@ interface ProverProps {
|
||||
setStep: (value: number) => void;
|
||||
setGeneratingProof: (value: boolean) => void;
|
||||
setProofTime: (value: number) => void;
|
||||
setProof: (value: Proof | null) => void;
|
||||
setProof: (proof: Proof) => void;
|
||||
toast: any
|
||||
}
|
||||
|
||||
@@ -128,24 +128,4 @@ const generateProof = async (
|
||||
} catch (err: any) {
|
||||
console.log('err', err);
|
||||
}
|
||||
};
|
||||
|
||||
const parseProofAndroid = (response: string) => {
|
||||
const match = response.match(/ZkProof\(proof=Proof\(pi_a=\[(.*?)\], pi_b=\[\[(.*?)\], \[(.*?)\], \[1, 0\]\], pi_c=\[(.*?)\], protocol=groth16, curve=bn128\), pub_signals=\[(.*?)\]\)/);
|
||||
|
||||
if (!match) throw new Error('Invalid input format');
|
||||
|
||||
const [, pi_a, pi_b_1, pi_b_2, pi_c, pub_signals] = match;
|
||||
|
||||
return {
|
||||
proof: {
|
||||
a: pi_a.split(',').map((n: string) => n.trim()),
|
||||
b: [
|
||||
pi_b_1.split(',').map((n: string) => n.trim()),
|
||||
pi_b_2.split(',').map((n: string) => n.trim()),
|
||||
],
|
||||
c: pi_c.split(',').map((n: string) => n.trim()),
|
||||
},
|
||||
pub_signals: pub_signals.split(',').map((n: string) => n.trim())
|
||||
} as Proof;
|
||||
};
|
||||
@@ -1,6 +1,7 @@
|
||||
// Function to extract information from a two-line MRZ.
|
||||
|
||||
import { countryCodes } from "../../../common/src/constants/constants";
|
||||
import { Proof } from "../../../common/src/utils/types";
|
||||
|
||||
// The actual parsing would depend on the standard being used (TD1, TD2, TD3, MRVA, MRVB).
|
||||
export function extractMRZInfo(mrzString: string) {
|
||||
@@ -54,4 +55,24 @@ export function formatAttribute(key: string, attribute: string) {
|
||||
return countryCodes[attribute as keyof typeof countryCodes]
|
||||
}
|
||||
return attribute;
|
||||
}
|
||||
}
|
||||
|
||||
export const parseProofAndroid = (response: string) => {
|
||||
const match = response.match(/ZkProof\(proof=Proof\(pi_a=\[(.*?)\], pi_b=\[\[(.*?)\], \[(.*?)\], \[1, 0\]\], pi_c=\[(.*?)\], protocol=groth16, curve=bn128\), pub_signals=\[(.*?)\]\)/);
|
||||
|
||||
if (!match) throw new Error('Invalid input format');
|
||||
|
||||
const [, pi_a, pi_b_1, pi_b_2, pi_c, pub_signals] = match;
|
||||
|
||||
return {
|
||||
proof: {
|
||||
a: pi_a.split(',').map((n: string) => n.trim()),
|
||||
b: [
|
||||
pi_b_1.split(',').map((n: string) => n.trim()),
|
||||
pi_b_2.split(',').map((n: string) => n.trim()),
|
||||
],
|
||||
c: pi_c.split(',').map((n: string) => n.trim()),
|
||||
},
|
||||
pub_signals: pub_signals.split(',').map((n: string) => n.trim())
|
||||
} as Proof;
|
||||
};
|
||||
@@ -1,81 +1,186 @@
|
||||
import {
|
||||
NativeModules,
|
||||
Platform,
|
||||
} from 'react-native';
|
||||
import RNFS from 'react-native-fs';
|
||||
import { ARKZKEY_URL, ZKEY_NAME, ZKEY_URL } from '../../../common/src/constants/constants';
|
||||
import * as amplitude from '@amplitude/analytics-react-native';
|
||||
import NetInfo from '@react-native-community/netinfo';
|
||||
import axios from 'axios';
|
||||
import { unzip } from 'react-native-zip-archive';
|
||||
|
||||
const localZkeyPath = RNFS.DocumentDirectoryPath + '/proof_of_passport.zkey';
|
||||
const localZipPath = RNFS.DocumentDirectoryPath + '/proof_of_passport.zip';
|
||||
const localUrlPath = RNFS.DocumentDirectoryPath + '/zkey_url.txt';
|
||||
// this should not change, instead update the zkey on the bucket
|
||||
const zkeyZipUrls = {
|
||||
register_sha256WithRSAEncryption_65537: "qweqwe",
|
||||
disclose: "qweqwe",
|
||||
proof_of_passport: `https://d8o9bercqupgk.cloudfront.net/proof_of_passport.zkey.zip`,
|
||||
};
|
||||
|
||||
async function initMopro() {
|
||||
if (Platform.OS === 'android') {
|
||||
const res = await NativeModules.Prover.runInitAction()
|
||||
console.log('Mopro init res:', res)
|
||||
}
|
||||
export type CircuitName = keyof typeof zkeyZipUrls;
|
||||
|
||||
export type ShowWarningModalProps = {
|
||||
show: boolean,
|
||||
circuit: CircuitName | "",
|
||||
size: number,
|
||||
}
|
||||
|
||||
export type IsZkeyDownloading = {
|
||||
[circuit in CircuitName]: boolean;
|
||||
}
|
||||
|
||||
// each time we download a zkey, we store the size of the zip file in a file named <circuit_name>_zip_size.txt
|
||||
// we assume a new zkey zip will always have a different size
|
||||
|
||||
// the downloadZkey function downloads a zkey if either:
|
||||
// 1. the zkey file does not exist
|
||||
// 2. <circuit_name>_zip_size.txt does not show the same size as the server response (zkey is outdated)
|
||||
// 3. the zkey is currently downloading
|
||||
// 4. the commitment is already registered and the function is called for a register zkey. If it's the case, there is no need to download the latest zkey.
|
||||
// => this should be fine is the function is never called after the commitment is registered.
|
||||
|
||||
export async function downloadZkey(
|
||||
setDownloadStatus: (value: "not_started" | "downloading" | "completed" | "error") => void,
|
||||
circuit: CircuitName,
|
||||
isZkeyDownloading: IsZkeyDownloading,
|
||||
setIsZkeyDownloading: (value: IsZkeyDownloading) => void,
|
||||
setShowWarningModal: (value: ShowWarningModalProps) => void,
|
||||
toast: any
|
||||
) {
|
||||
console.log('launching zkey download')
|
||||
setDownloadStatus('downloading');
|
||||
amplitude.track('Downloading zkey...');
|
||||
const downloadRequired = await isDownloadRequired(circuit, isZkeyDownloading);
|
||||
if (!downloadRequired) {
|
||||
console.log(`zkey for ${circuit} already downloaded`)
|
||||
amplitude.track(`zkey for ${circuit} already downloaded`);
|
||||
return;
|
||||
}
|
||||
|
||||
const networkInfo = await NetInfo.fetch();
|
||||
console.log('Network type:', networkInfo.type)
|
||||
if (networkInfo.type === 'wifi') {
|
||||
fetchZkey(
|
||||
circuit,
|
||||
isZkeyDownloading,
|
||||
setIsZkeyDownloading,
|
||||
toast
|
||||
);
|
||||
} else {
|
||||
setShowWarningModal({
|
||||
show: true,
|
||||
circuit: circuit,
|
||||
size: 0,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export async function isDownloadRequired(
|
||||
circuit: CircuitName,
|
||||
isZkeyDownloading: IsZkeyDownloading
|
||||
) {
|
||||
if (isZkeyDownloading[circuit]) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const fileExists = await RNFS.exists(`${RNFS.DocumentDirectoryPath}/${circuit}.zkey`);
|
||||
if (!fileExists) {
|
||||
return true;
|
||||
}
|
||||
|
||||
let storedZipSize = 0;
|
||||
try {
|
||||
storedZipSize = Number(await RNFS.readFile(`${RNFS.DocumentDirectoryPath}/${circuit}_zip_size.txt`, 'utf8'));
|
||||
} catch (error) {
|
||||
console.log(`${circuit}_zip_size.txt file not found, so assuming zkey is outdated.`);
|
||||
return true;
|
||||
}
|
||||
|
||||
console.log('storedZipSize:', storedZipSize)
|
||||
|
||||
const response = await axios.head(zkeyZipUrls[circuit]);
|
||||
const expectedSize = parseInt(response.headers['content-length'], 10);
|
||||
|
||||
console.log('expectedSize:', expectedSize)
|
||||
|
||||
const isZipComplete = storedZipSize === expectedSize;
|
||||
|
||||
console.log('isZipComplete:', isZipComplete)
|
||||
|
||||
if (!isZipComplete) {
|
||||
return true;
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
export async function fetchZkey(
|
||||
circuit: CircuitName,
|
||||
isZkeyDownloading: IsZkeyDownloading,
|
||||
setIsZkeyDownloading: (value: IsZkeyDownloading) => void,
|
||||
toast: any
|
||||
) {
|
||||
console.log(`fetching zkey for ${circuit} ...`)
|
||||
amplitude.track(`fetching zkey for ${circuit} ...`);
|
||||
|
||||
setIsZkeyDownloading({
|
||||
...isZkeyDownloading,
|
||||
[circuit]: true,
|
||||
});
|
||||
|
||||
const startTime = Date.now();
|
||||
|
||||
const url = Platform.OS === 'android' ? ARKZKEY_URL : ZKEY_URL
|
||||
|
||||
let previousPercentComplete = -1;
|
||||
|
||||
const options = {
|
||||
fromUrl: url,
|
||||
toFile: localZipPath,
|
||||
fromUrl: zkeyZipUrls[circuit],
|
||||
toFile: `${RNFS.DocumentDirectoryPath}/${circuit}.zkey.zip`,
|
||||
background: true,
|
||||
begin: () => {
|
||||
console.log('Download has begun');
|
||||
},
|
||||
progress: (res: any) => {
|
||||
const percentComplete = Math.floor((res.bytesWritten / res.contentLength) * 100);
|
||||
if (percentComplete !== previousPercentComplete) {
|
||||
if (percentComplete % 5 === 0 && percentComplete !== previousPercentComplete) {
|
||||
console.log(`${percentComplete}%`);
|
||||
previousPercentComplete = percentComplete;
|
||||
}
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
RNFS.downloadFile(options).promise
|
||||
.then(async () => {
|
||||
console.log('Download complete');
|
||||
|
||||
RNFS.readDir(RNFS.DocumentDirectoryPath)
|
||||
.then((result) => {
|
||||
console.log('Directory contents before:', result);
|
||||
console.log('Directory contents before unzipping:', result);
|
||||
})
|
||||
|
||||
const unzipPath = RNFS.DocumentDirectoryPath;
|
||||
await unzip(localZipPath, unzipPath);
|
||||
const oldPath = `${unzipPath}/${ZKEY_NAME}${Platform.OS === 'android' ? '.arkzkey' : '.zkey'}`;
|
||||
const newPath = `${unzipPath}/proof_of_passport.zkey`;
|
||||
await RNFS.moveFile(oldPath, newPath);
|
||||
await unzip(`${RNFS.DocumentDirectoryPath}/${circuit}.zkey.zip`, RNFS.DocumentDirectoryPath);
|
||||
|
||||
RNFS.readDir(RNFS.DocumentDirectoryPath)
|
||||
.then((result) => {
|
||||
console.log('Directory contents after:', result);
|
||||
console.log('Directory contents after unzipping:', result);
|
||||
})
|
||||
console.log('Unzip complete');
|
||||
setDownloadStatus('completed')
|
||||
const endTime = Date.now();
|
||||
amplitude.track('zkey download succeeded, took ' + ((endTime - startTime) / 1000) + ' seconds');
|
||||
RNFS.writeFile(localUrlPath, url, 'utf8');
|
||||
initMopro()
|
||||
setIsZkeyDownloading({
|
||||
...isZkeyDownloading,
|
||||
[circuit]: false,
|
||||
});
|
||||
|
||||
amplitude.track('zkey download succeeded, took ' + ((Date.now() - startTime) / 1000) + ' seconds');
|
||||
|
||||
const zipSize = await RNFS.stat(`${RNFS.DocumentDirectoryPath}/${circuit}.zkey.zip`);
|
||||
|
||||
console.log('zipSize:', zipSize.size);
|
||||
|
||||
RNFS.writeFile(`${RNFS.DocumentDirectoryPath}/${circuit}_zip_size.txt`, zipSize.size.toString(), 'utf8');
|
||||
|
||||
console.log('zip size written to file');
|
||||
|
||||
// delete the zip file
|
||||
RNFS.unlink(`${RNFS.DocumentDirectoryPath}/${circuit}.zkey.zip`)
|
||||
.then(() => {
|
||||
console.log('zip file deleted');
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error(error);
|
||||
});
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error(error);
|
||||
setDownloadStatus('error');
|
||||
setIsZkeyDownloading({
|
||||
...isZkeyDownloading,
|
||||
[circuit]: false,
|
||||
});
|
||||
amplitude.track('zkey download failed: ' + error.message);
|
||||
toast.show('Error', {
|
||||
message: `Error: ${error.message}`,
|
||||
@@ -84,55 +189,4 @@ export async function downloadZkey(
|
||||
},
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
interface CheckForZkeyProps {
|
||||
setDownloadStatus: (value: "not_started" | "downloading" | "completed" | "error") => void;
|
||||
setShowWarning: (value: boolean) => void;
|
||||
toast: any
|
||||
}
|
||||
|
||||
export async function checkForZkey({
|
||||
setDownloadStatus,
|
||||
setShowWarning,
|
||||
toast
|
||||
}: CheckForZkeyProps) {
|
||||
console.log('local zip path:', localZipPath)
|
||||
const url = Platform.OS === 'android' ? ARKZKEY_URL : ZKEY_URL
|
||||
|
||||
let storedUrl = '';
|
||||
try {
|
||||
storedUrl = await RNFS.readFile(localUrlPath, 'utf8');
|
||||
} catch (error) {
|
||||
console.log('zkey_url.txt file not found, so assuming zkey is outdated.');
|
||||
}
|
||||
|
||||
const fileExists = await RNFS.exists(localZipPath);
|
||||
const fileInfo = fileExists ? await RNFS.stat(localZipPath) : null;
|
||||
|
||||
const response = await axios.head(url);
|
||||
const expectedSize = parseInt(response.headers['content-length'], 10);
|
||||
const isFileComplete = fileInfo && fileInfo.size === expectedSize;
|
||||
|
||||
console.log('expectedSize:', expectedSize)
|
||||
console.log('fileInfo.size:', fileInfo?.size)
|
||||
console.log('isFileComplete:', isFileComplete)
|
||||
|
||||
if (!isFileComplete || url !== storedUrl) {
|
||||
const state = await NetInfo.fetch();
|
||||
console.log('Network start type:', state.type)
|
||||
if (state.type === 'wifi') {
|
||||
downloadZkey(
|
||||
setDownloadStatus,
|
||||
toast
|
||||
)
|
||||
} else {
|
||||
setShowWarning(true);
|
||||
}
|
||||
} else {
|
||||
console.log('zkey already downloaded')
|
||||
amplitude.track('zkey already downloaded');
|
||||
setDownloadStatus('completed');
|
||||
initMopro()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,4 @@
|
||||
export const AWS_ENDPOINT = "https://0pw5u65m3a.execute-api.eu-north-1.amazonaws.com/api-stage/mint"
|
||||
|
||||
export const ZKEY_NAME = "proof_of_passport_final_v01"
|
||||
export const ZKEY_URL = `https://d8o9bercqupgk.cloudfront.net/${ZKEY_NAME}.zkey.zip`
|
||||
export const RELAYER_URL = "https://0pw5u65m3a.execute-api.eu-north-1.amazonaws.com/api-stage/mint"
|
||||
|
||||
export const TREE_DEPTH = 16
|
||||
|
||||
|
||||
@@ -280,9 +280,9 @@ describe("Proof of Passport", function () {
|
||||
|
||||
console.log('transactionRequest', transactionRequest);
|
||||
|
||||
const apiEndpoint = process.env.AWS_ENDPOINT;
|
||||
const apiEndpoint = process.env.RELAYER_URL;
|
||||
if (!apiEndpoint) {
|
||||
throw new Error('AWS_ENDPOINT env variable is not set');
|
||||
throw new Error('RELAYER_URL env variable is not set');
|
||||
}
|
||||
const response = await axios.post(apiEndpoint, {
|
||||
chain: "mumbai",
|
||||
|
||||
Reference in New Issue
Block a user