mirror of
https://github.com/selfxyz/self.git
synced 2026-04-05 03:00:53 -04:00
Bringing openpassport/main (#19)
Co-authored-by: seshanthS <seshanth@protonmail.com> Co-authored-by: turnoffthiscomputer <colin.remi07@gmail.com> Co-authored-by: thomas-senechal <thomas.senechal@pm.me> Co-authored-by: motemotech <i.am.nicoshark@gmail.com> Co-authored-by: turnoffthiscomputer <98749896+remicolin@users.noreply.github.com> Co-authored-by: ayman <aymanshaik1015@gmail.com>
This commit is contained in:
69
app/App.tsx
69
app/App.tsx
@@ -1,8 +1,13 @@
|
||||
import React, { useEffect } from 'react';
|
||||
import 'react-native-get-random-values';
|
||||
|
||||
import * as amplitude from '@amplitude/analytics-react-native';
|
||||
import { AMPLITUDE_KEY } from '@env';
|
||||
import { SEGMENT_KEY } from '@env';
|
||||
import {
|
||||
EventPlugin,
|
||||
PluginType,
|
||||
SegmentEvent,
|
||||
createClient,
|
||||
} from '@segment/analytics-react-native';
|
||||
import '@ethersproject/shims';
|
||||
import { Buffer } from 'buffer';
|
||||
import { YStack } from 'tamagui';
|
||||
@@ -15,6 +20,57 @@ import { setupUniversalLinkListener } from './src/utils/qrCode';
|
||||
|
||||
global.Buffer = Buffer;
|
||||
|
||||
// Adjust the import path as needed
|
||||
|
||||
export class DisableTrackingPlugin extends EventPlugin {
|
||||
type = PluginType.before;
|
||||
|
||||
execute(event: SegmentEvent): SegmentEvent {
|
||||
// Ensure context exists
|
||||
if (!event.context) {
|
||||
event.context = {};
|
||||
}
|
||||
|
||||
// Ensure device context exists
|
||||
if (!event.context.device) {
|
||||
event.context.device = {};
|
||||
}
|
||||
|
||||
// Force tracking related fields to be disabled
|
||||
event.context.device.adTrackingEnabled = false;
|
||||
event.context.device.advertisingId = undefined;
|
||||
event.context.device.trackingStatus = 'not-authorized';
|
||||
event.context.device.id = undefined;
|
||||
|
||||
return event;
|
||||
}
|
||||
}
|
||||
|
||||
export const createSegmentClient = () => {
|
||||
if (!SEGMENT_KEY) return null;
|
||||
|
||||
const client = createClient({
|
||||
writeKey: SEGMENT_KEY,
|
||||
trackAppLifecycleEvents: true,
|
||||
debug: true,
|
||||
collectDeviceId: false,
|
||||
defaultSettings: {
|
||||
integrations: {
|
||||
'Segment.io': {
|
||||
apiKey: SEGMENT_KEY,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
client.add({ plugin: new DisableTrackingPlugin() });
|
||||
|
||||
return client;
|
||||
};
|
||||
|
||||
// Export the client variable (will be initialized later)
|
||||
export let segmentClient: ReturnType<typeof createClient> | null = null;
|
||||
|
||||
function App(): React.JSX.Element {
|
||||
// const toast = useToastController();
|
||||
// const setToast = useNavigationStore(state => state.setToast);
|
||||
@@ -34,14 +90,13 @@ function App(): React.JSX.Element {
|
||||
// }, [setSelectedTab]);
|
||||
|
||||
useEffect(() => {
|
||||
if (AMPLITUDE_KEY) {
|
||||
amplitude.init(AMPLITUDE_KEY);
|
||||
}
|
||||
const cleanup = setupUniversalLinkListener();
|
||||
return cleanup;
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
const cleanup = setupUniversalLinkListener();
|
||||
return cleanup;
|
||||
// Initialize segment directly without any tracking checks
|
||||
segmentClient = createSegmentClient();
|
||||
}, []);
|
||||
|
||||
return (
|
||||
|
||||
@@ -85,8 +85,8 @@ android {
|
||||
applicationId "com.proofofpassportapp"
|
||||
minSdkVersion rootProject.ext.minSdkVersion
|
||||
targetSdkVersion rootProject.ext.targetSdkVersion
|
||||
versionCode 16
|
||||
versionName "1.5"
|
||||
versionCode 19
|
||||
versionName "1.8"
|
||||
externalNativeBuild {
|
||||
cmake {
|
||||
cppFlags += "-fexceptions -frtti -std=c++11"
|
||||
|
||||
@@ -362,11 +362,13 @@ class RNPassportReaderModule(private val reactContext: ReactApplicationContext)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
eventMessageEmitter("Reading DG1.....")
|
||||
val dg1In = service.getInputStream(PassportService.EF_DG1)
|
||||
dg1File = DG1File(dg1In)
|
||||
val dg2In = service.getInputStream(PassportService.EF_DG2)
|
||||
dg2File = DG2File(dg2In)
|
||||
dg1File = DG1File(dg1In)
|
||||
// eventMessageEmitter("Reading DG2.....")
|
||||
// val dg2In = service.getInputStream(PassportService.EF_DG2)
|
||||
// dg2File = DG2File(dg2In)
|
||||
eventMessageEmitter("Reading SOD.....")
|
||||
val sodIn = service.getInputStream(PassportService.EF_SOD)
|
||||
sodFile = SODFile(sodIn)
|
||||
|
||||
@@ -406,20 +408,20 @@ class RNPassportReaderModule(private val reactContext: ReactApplicationContext)
|
||||
// sendDataToJS(PassportData(dg1File, dg2File, sodFile))
|
||||
// Log.d(TAG, "============DATA SENT TO JS=============")
|
||||
|
||||
val allFaceImageInfo: MutableList<FaceImageInfo> = ArrayList()
|
||||
dg2File.faceInfos.forEach {
|
||||
allFaceImageInfo.addAll(it.faceImageInfos)
|
||||
}
|
||||
if (allFaceImageInfo.isNotEmpty()) {
|
||||
val faceImageInfo = allFaceImageInfo.first()
|
||||
val imageLength = faceImageInfo.imageLength
|
||||
val dataInputStream = DataInputStream(faceImageInfo.imageInputStream)
|
||||
val buffer = ByteArray(imageLength)
|
||||
dataInputStream.readFully(buffer, 0, imageLength)
|
||||
val inputStream: InputStream = ByteArrayInputStream(buffer, 0, imageLength)
|
||||
bitmap = decodeImage(reactContext, faceImageInfo.mimeType, inputStream)
|
||||
imageBase64 = Base64.encodeToString(buffer, Base64.DEFAULT)
|
||||
}
|
||||
// val allFaceImageInfo: MutableList<FaceImageInfo> = ArrayList()
|
||||
// dg2File.faceInfos.forEach {
|
||||
// allFaceImageInfo.addAll(it.faceImageInfos)
|
||||
// }
|
||||
// if (allFaceImageInfo.isNotEmpty()) {
|
||||
// val faceImageInfo = allFaceImageInfo.first()
|
||||
// val imageLength = faceImageInfo.imageLength
|
||||
// val dataInputStream = DataInputStream(faceImageInfo.imageInputStream)
|
||||
// val buffer = ByteArray(imageLength)
|
||||
// dataInputStream.readFully(buffer, 0, imageLength)
|
||||
// val inputStream: InputStream = ByteArrayInputStream(buffer, 0, imageLength)
|
||||
// bitmap = decodeImage(reactContext, faceImageInfo.mimeType, inputStream)
|
||||
// imageBase64 = Base64.encodeToString(buffer, Base64.DEFAULT)
|
||||
// }
|
||||
} catch (e: Exception) {
|
||||
eventMessageEmitter(Messages.RESET)
|
||||
return e
|
||||
@@ -429,6 +431,7 @@ class RNPassportReaderModule(private val reactContext: ReactApplicationContext)
|
||||
|
||||
private fun doChipAuth(service: PassportService) {
|
||||
try {
|
||||
eventMessageEmitter("Reading DG14.....")
|
||||
val dg14In = service.getInputStream(PassportService.EF_DG14)
|
||||
dg14Encoded = IOUtils.toByteArray(dg14In)
|
||||
val dg14InByte = ByteArrayInputStream(dg14Encoded)
|
||||
@@ -459,11 +462,8 @@ class RNPassportReaderModule(private val reactContext: ReactApplicationContext)
|
||||
|
||||
val dataHashes = sodFile.dataGroupHashes
|
||||
|
||||
eventMessageEmitter("Reading DG14.....")
|
||||
val dg14Hash = if (chipAuthSucceeded) digest.digest(dg14Encoded) else ByteArray(0)
|
||||
eventMessageEmitter("Reading DG1.....")
|
||||
val dg1Hash = digest.digest(dg1File.encoded)
|
||||
eventMessageEmitter("Reading DG2.....")
|
||||
val dg2Hash = digest.digest(dg2File.encoded)
|
||||
|
||||
// val gson = Gson()
|
||||
@@ -486,7 +486,8 @@ class RNPassportReaderModule(private val reactContext: ReactApplicationContext)
|
||||
|
||||
Log.d(TAG, "Comparing data group hashes...")
|
||||
eventMessageEmitter(Messages.COMPARING)
|
||||
if (Arrays.equals(dg1Hash, dataHashes[1]) && Arrays.equals(dg2Hash, dataHashes[2])
|
||||
// if (Arrays.equals(dg1Hash, dataHashes[1]) && Arrays.equals(dg2Hash, dataHashes[2])
|
||||
if (Arrays.equals(dg1Hash, dataHashes[1])
|
||||
&& (!chipAuthSucceeded || Arrays.equals(dg14Hash, dataHashes[14]))) {
|
||||
|
||||
Log.d(TAG, "Data group hashes match.")
|
||||
@@ -660,13 +661,13 @@ class RNPassportReaderModule(private val reactContext: ReactApplicationContext)
|
||||
// Log.d(TAG, "signedData.signerInfos: ${gson.toJson(signedData.signerInfos)}")
|
||||
// Log.d(TAG, "signedData.certificates: ${gson.toJson(signedData.certificates)}")
|
||||
|
||||
var quality = 100
|
||||
val base64 = bitmap?.let { toBase64(it, quality) }
|
||||
val photo = Arguments.createMap()
|
||||
photo.putString("base64", base64 ?: "")
|
||||
photo.putInt("width", bitmap?.width ?: 0)
|
||||
photo.putInt("height", bitmap?.height ?: 0)
|
||||
passport.putMap("photo", photo)
|
||||
// var quality = 100
|
||||
// val base64 = bitmap?.let { toBase64(it, quality) }
|
||||
// val photo = Arguments.createMap()
|
||||
// photo.putString("base64", base64 ?: "")
|
||||
// photo.putInt("width", bitmap?.width ?: 0)
|
||||
// photo.putInt("height", bitmap?.height ?: 0)
|
||||
// passport.putMap("photo", photo)
|
||||
// passport.putString("dg2File", gson.toJson(dg2File))
|
||||
|
||||
eventMessageEmitter(Messages.COMPLETED)
|
||||
|
||||
@@ -34,7 +34,6 @@
|
||||
1686F0E02C500FBD00841CDE /* QRScannerBridge.m in Sources */ = {isa = PBXBuildFile; fileRef = 1686F0DF2C500FBD00841CDE /* QRScannerBridge.m */; };
|
||||
16E6646E2B8D292500FDD6A0 /* QKMRZScannerViewRepresentable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 16E6646D2B8D292500FDD6A0 /* QKMRZScannerViewRepresentable.swift */; };
|
||||
16E884A52C5BD764003B7125 /* passport.json in Resources */ = {isa = PBXBuildFile; fileRef = 16E884A42C5BD764003B7125 /* passport.json */; };
|
||||
1B904271B8E1DB8434EF0613 /* Pods_OpenPassport.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3435ED6D988B5E2DE0DE8101 /* Pods_OpenPassport.framework */; };
|
||||
4A1791A6108347E5A635DB1C /* Inter-ThinItalic.otf in Resources */ = {isa = PBXBuildFile; fileRef = EEA2A4D24A8F4B10A5ECA607 /* Inter-ThinItalic.otf */; };
|
||||
5008C8140A304ED79DB817C5 /* slkscrb.ttf in Resources */ = {isa = PBXBuildFile; fileRef = B4E7218406B64A95BCE0DFE4 /* slkscrb.ttf */; };
|
||||
5C66B65890614C638590DC8A /* Inter-ExtraBold.otf in Resources */ = {isa = PBXBuildFile; fileRef = 8CE3CC4CFFC24314A22F1391 /* Inter-ExtraBold.otf */; };
|
||||
@@ -61,6 +60,7 @@
|
||||
EBECCA4983EC6929A7722578 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = E56E082698598B41447667BB /* PrivacyInfo.xcprivacy */; };
|
||||
EEF3331B93C24D6482021BA2 /* Inter-ExtraLightItalic.otf in Resources */ = {isa = PBXBuildFile; fileRef = 090474A3F07B4FFA82C9A751 /* Inter-ExtraLightItalic.otf */; };
|
||||
F1961109CC004035884F79D9 /* Inter-ExtraBoldItalic.otf in Resources */ = {isa = PBXBuildFile; fileRef = 37A4DECF3A824D5BAA8863FD /* Inter-ExtraBoldItalic.otf */; };
|
||||
F2B6CAF95CEE1D3F94541B0F /* Pods_OpenPassport.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF34842C3AD0E76B7A7D5C5E /* Pods_OpenPassport.framework */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXCopyFilesBuildPhase section */
|
||||
@@ -142,12 +142,12 @@
|
||||
16E6646D2B8D292500FDD6A0 /* QKMRZScannerViewRepresentable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QKMRZScannerViewRepresentable.swift; sourceTree = "<group>"; };
|
||||
16E884A42C5BD764003B7125 /* passport.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = passport.json; sourceTree = "<group>"; };
|
||||
276287D0D37B4E8EBD7A1ABD /* Inter-SemiBold.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = undefined; includeInIndex = 0; lastKnownFileType = unknown; name = "Inter-SemiBold.otf"; path = "../node_modules/@tamagui/font-inter/otf/Inter-SemiBold.otf"; sourceTree = "<group>"; };
|
||||
3435ED6D988B5E2DE0DE8101 /* Pods_OpenPassport.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_OpenPassport.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
37A4DECF3A824D5BAA8863FD /* Inter-ExtraBoldItalic.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = undefined; includeInIndex = 0; lastKnownFileType = unknown; name = "Inter-ExtraBoldItalic.otf"; path = "../node_modules/@tamagui/font-inter/otf/Inter-ExtraBoldItalic.otf"; sourceTree = "<group>"; };
|
||||
3BF771EA645241D9A28A3AE9 /* Inter-Bold.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = undefined; includeInIndex = 0; lastKnownFileType = unknown; name = "Inter-Bold.otf"; path = "../node_modules/@tamagui/font-inter/otf/Inter-Bold.otf"; sourceTree = "<group>"; };
|
||||
4B261C28061D47B7B3BB3E37 /* Inter-Black.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = undefined; includeInIndex = 0; lastKnownFileType = unknown; name = "Inter-Black.otf"; path = "../node_modules/@tamagui/font-inter/otf/Inter-Black.otf"; sourceTree = "<group>"; };
|
||||
64F386964AAE4C1E8F2DF789 /* Inter-ExtraLight.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = undefined; includeInIndex = 0; lastKnownFileType = unknown; name = "Inter-ExtraLight.otf"; path = "../node_modules/@tamagui/font-inter/otf/Inter-ExtraLight.otf"; sourceTree = "<group>"; };
|
||||
6CF8D6DF98634423ACD5D630 /* Inter-Regular.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = undefined; includeInIndex = 0; lastKnownFileType = unknown; name = "Inter-Regular.otf"; path = "../node_modules/@tamagui/font-inter/otf/Inter-Regular.otf"; sourceTree = "<group>"; };
|
||||
73A8B182B1187BFE180CBB44 /* Pods-OpenPassport.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-OpenPassport.release.xcconfig"; path = "Target Support Files/Pods-OpenPassport/Pods-OpenPassport.release.xcconfig"; sourceTree = "<group>"; };
|
||||
7CCB5F83F57540E88D54B34A /* slkscr.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = undefined; includeInIndex = 0; lastKnownFileType = unknown; name = slkscr.ttf; path = "../node_modules/@tamagui/font-silkscreen/files/slkscr.ttf"; sourceTree = "<group>"; };
|
||||
7E5C3CEF7EDA4871B3D0EBE1 /* Advercase-Regular.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = undefined; includeInIndex = 0; lastKnownFileType = unknown; name = "Advercase-Regular.otf"; path = "../src/assets/fonts/Advercase-Regular.otf"; sourceTree = "<group>"; };
|
||||
81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = LaunchScreen.storyboard; path = OpenPassport/LaunchScreen.storyboard; sourceTree = "<group>"; };
|
||||
@@ -158,10 +158,10 @@
|
||||
905B70062A72774000AFA232 /* PassportReader.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = PassportReader.m; sourceTree = "<group>"; };
|
||||
905B70082A729CD400AFA232 /* OpenPassport.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; name = OpenPassport.entitlements; path = OpenPassport/OpenPassport.entitlements; sourceTree = "<group>"; };
|
||||
9BF744D9A73A4BAC96EC569A /* DINOT-Medium.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = undefined; includeInIndex = 0; lastKnownFileType = unknown; name = "DINOT-Medium.otf"; path = "../src/assets/fonts/DINOT-Medium.otf"; sourceTree = "<group>"; };
|
||||
A239B1BBD7EF208EB51EF7DE /* Pods-OpenPassport.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-OpenPassport.release.xcconfig"; path = "Target Support Files/Pods-OpenPassport/Pods-OpenPassport.release.xcconfig"; sourceTree = "<group>"; };
|
||||
AF34842C3AD0E76B7A7D5C5E /* Pods_OpenPassport.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_OpenPassport.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
B4E7218406B64A95BCE0DFE4 /* slkscrb.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = undefined; includeInIndex = 0; lastKnownFileType = unknown; name = slkscrb.ttf; path = "../node_modules/@tamagui/font-silkscreen/files/slkscrb.ttf"; sourceTree = "<group>"; };
|
||||
BB9316819FB038104D42933E /* Pods-OpenPassport.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-OpenPassport.debug.xcconfig"; path = "Target Support Files/Pods-OpenPassport/Pods-OpenPassport.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
C56F122245594D6DA9B7570A /* slkscr.woff */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = undefined; includeInIndex = 0; lastKnownFileType = unknown; name = slkscr.woff; path = "../node_modules/@tamagui/font-silkscreen/files/slkscr.woff"; sourceTree = "<group>"; };
|
||||
CA67A75B161A05334E3E9402 /* Pods-OpenPassport.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-OpenPassport.debug.xcconfig"; path = "Target Support Files/Pods-OpenPassport/Pods-OpenPassport.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
D58C0CED91AE4265A5A406A0 /* Inter-BlackItalic.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = undefined; includeInIndex = 0; lastKnownFileType = unknown; name = "Inter-BlackItalic.otf"; path = "../node_modules/@tamagui/font-inter/otf/Inter-BlackItalic.otf"; sourceTree = "<group>"; };
|
||||
DD642F4F3A114B43A22296D7 /* Inter-Thin.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = undefined; includeInIndex = 0; lastKnownFileType = unknown; name = "Inter-Thin.otf"; path = "../node_modules/@tamagui/font-inter/otf/Inter-Thin.otf"; sourceTree = "<group>"; };
|
||||
E56E082698598B41447667BB /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xml; name = PrivacyInfo.xcprivacy; path = OpenPassport/PrivacyInfo.xcprivacy; sourceTree = "<group>"; };
|
||||
@@ -186,7 +186,7 @@
|
||||
05D985F62BB331AB00F58EEA /* libfr.a in Frameworks */,
|
||||
167D934A2C91D2EA00530E6B /* libwitnesscalc_prove_rsa_65537_sha256.a in Frameworks */,
|
||||
167D93462C91B1E100530E6B /* libwitnesscalc_register_rsa_65537_sha1.a in Frameworks */,
|
||||
1B904271B8E1DB8434EF0613 /* Pods_OpenPassport.framework in Frameworks */,
|
||||
F2B6CAF95CEE1D3F94541B0F /* Pods_OpenPassport.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@@ -273,7 +273,7 @@
|
||||
0569F35E2BBC98C9006670BD /* libfq.a */,
|
||||
0569F35A2BBC900D006670BD /* librapidsnark.a */,
|
||||
ED297162215061F000B7C4FE /* JavaScriptCore.framework */,
|
||||
3435ED6D988B5E2DE0DE8101 /* Pods_OpenPassport.framework */,
|
||||
AF34842C3AD0E76B7A7D5C5E /* Pods_OpenPassport.framework */,
|
||||
);
|
||||
name = Frameworks;
|
||||
sourceTree = "<group>";
|
||||
@@ -343,8 +343,8 @@
|
||||
BBD78D7AC51CEA395F1C20DB /* Pods */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
BB9316819FB038104D42933E /* Pods-OpenPassport.debug.xcconfig */,
|
||||
A239B1BBD7EF208EB51EF7DE /* Pods-OpenPassport.release.xcconfig */,
|
||||
CA67A75B161A05334E3E9402 /* Pods-OpenPassport.debug.xcconfig */,
|
||||
73A8B182B1187BFE180CBB44 /* Pods-OpenPassport.release.xcconfig */,
|
||||
);
|
||||
path = Pods;
|
||||
sourceTree = "<group>";
|
||||
@@ -356,15 +356,15 @@
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "OpenPassport" */;
|
||||
buildPhases = (
|
||||
62212FE980074600640A3F2F /* [CP] Check Pods Manifest.lock */,
|
||||
1C3B778186C749AEAB10A0B1 /* [CP] Check Pods Manifest.lock */,
|
||||
FD10A7F022414F080027D42C /* Start Packager */,
|
||||
13B07F871A680F5B00A75B9A /* Sources */,
|
||||
13B07F8C1A680F5B00A75B9A /* Frameworks */,
|
||||
13B07F8E1A680F5B00A75B9A /* Resources */,
|
||||
00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */,
|
||||
054340D12C71B2980014B445 /* Embed App Clips */,
|
||||
19B6B230BF58128B7603B834 /* [CP] Embed Pods Frameworks */,
|
||||
CCF107224BF9CF7E8A4F57B7 /* [CP] Copy Pods Resources */,
|
||||
0C6411FE06C61E7F495D9204 /* [CP] Embed Pods Frameworks */,
|
||||
DAB2FFB78D69B620A585FF8C /* [CP] Copy Pods Resources */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
@@ -461,7 +461,7 @@
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "set -e\n\nWITH_ENVIRONMENT=\"../node_modules/react-native/scripts/xcode/with-environment.sh\"\nREACT_NATIVE_XCODE=\"../node_modules/react-native/scripts/react-native-xcode.sh\"\n\n/bin/sh -c \"$WITH_ENVIRONMENT $REACT_NATIVE_XCODE\"\n";
|
||||
};
|
||||
19B6B230BF58128B7603B834 /* [CP] Embed Pods Frameworks */ = {
|
||||
0C6411FE06C61E7F495D9204 /* [CP] Embed Pods Frameworks */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
@@ -478,7 +478,7 @@
|
||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-OpenPassport/Pods-OpenPassport-frameworks.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
62212FE980074600640A3F2F /* [CP] Check Pods Manifest.lock */ = {
|
||||
1C3B778186C749AEAB10A0B1 /* [CP] Check Pods Manifest.lock */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
@@ -500,7 +500,7 @@
|
||||
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
CCF107224BF9CF7E8A4F57B7 /* [CP] Copy Pods Resources */ = {
|
||||
DAB2FFB78D69B620A585FF8C /* [CP] Copy Pods Resources */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
@@ -584,7 +584,7 @@
|
||||
/* Begin XCBuildConfiguration section */
|
||||
13B07F941A680F5B00A75B9A /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = BB9316819FB038104D42933E /* Pods-OpenPassport.debug.xcconfig */;
|
||||
baseConfigurationReference = CA67A75B161A05334E3E9402 /* Pods-OpenPassport.debug.xcconfig */;
|
||||
buildSettings = {
|
||||
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
@@ -592,7 +592,7 @@
|
||||
CODE_SIGN_ENTITLEMENTS = OpenPassport/OpenPassportDebug.entitlements;
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 67;
|
||||
CURRENT_PROJECT_VERSION = 72;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
DEVELOPMENT_TEAM = 5B29R5LYHQ;
|
||||
ENABLE_BITCODE = NO;
|
||||
@@ -707,7 +707,7 @@
|
||||
"$(PROJECT_DIR)",
|
||||
"$(PROJECT_DIR)/MoproKit/Libs",
|
||||
);
|
||||
MARKETING_VERSION = 2.0.0;
|
||||
MARKETING_VERSION = 2.0.6;
|
||||
OTHER_LDFLAGS = (
|
||||
"$(inherited)",
|
||||
"-ObjC",
|
||||
@@ -725,13 +725,13 @@
|
||||
};
|
||||
13B07F951A680F5B00A75B9A /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = A239B1BBD7EF208EB51EF7DE /* Pods-OpenPassport.release.xcconfig */;
|
||||
baseConfigurationReference = 73A8B182B1187BFE180CBB44 /* Pods-OpenPassport.release.xcconfig */;
|
||||
buildSettings = {
|
||||
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = OpenPassport/OpenPassport.entitlements;
|
||||
CURRENT_PROJECT_VERSION = 67;
|
||||
CURRENT_PROJECT_VERSION = 72;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
DEVELOPMENT_TEAM = 5B29R5LYHQ;
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
@@ -845,7 +845,7 @@
|
||||
"$(PROJECT_DIR)",
|
||||
"$(PROJECT_DIR)/MoproKit/Libs",
|
||||
);
|
||||
MARKETING_VERSION = 2.0.0;
|
||||
MARKETING_VERSION = 2.0.6;
|
||||
OTHER_LDFLAGS = (
|
||||
"$(inherited)",
|
||||
"-ObjC",
|
||||
|
||||
@@ -97,7 +97,7 @@ class PassportReader: NSObject{
|
||||
// let masterListURL = Bundle.main.url(forResource: "masterList", withExtension: ".pem")
|
||||
// passportReader.setMasterListURL( masterListURL! )
|
||||
|
||||
let passport = try await passportReader.readPassport( mrzKey: mrzKey, customDisplayMessage: customMessageHandler)
|
||||
let passport = try await passportReader.readPassport( mrzKey: mrzKey, tags: [.COM, .DG1, .SOD], customDisplayMessage: customMessageHandler)
|
||||
|
||||
var ret = [String:String]()
|
||||
print("documentType", passport.documentType)
|
||||
@@ -118,13 +118,13 @@ class PassportReader: NSObject{
|
||||
ret["phoneNumber"] = passport.phoneNumber
|
||||
ret["personalNumber"] = passport.personalNumber
|
||||
|
||||
let passportPhotoData = passport.passportPhoto // [UInt8]
|
||||
if let passportPhotoData = passport.passportPhoto {
|
||||
let data = Data(passportPhotoData)
|
||||
let base64String = data.base64EncodedString()
|
||||
// let passportPhotoData = passport.passportPhoto // [UInt8]
|
||||
// if let passportPhotoData = passport.passportPhoto {
|
||||
// let data = Data(passportPhotoData)
|
||||
// let base64String = data.base64EncodedString()
|
||||
|
||||
ret["passportPhoto"] = base64String
|
||||
}
|
||||
// ret["passportPhoto"] = base64String
|
||||
// }
|
||||
|
||||
// documentSigningCertificate
|
||||
// countrySigningCertificate
|
||||
|
||||
@@ -24,7 +24,7 @@ target 'OpenPassport' do
|
||||
config = use_native_modules!
|
||||
|
||||
use_frameworks!
|
||||
pod 'NFCPassportReader', git: 'https://github.com/0xturboblitz/NFCPassportReader.git', commit: '0a8e26d56f5f85f698b67c5df5ea9ecbb53cbc45'
|
||||
pod 'NFCPassportReader', git: 'https://github.com/zk-passport/NFCPassportReader', commit: '8e72f0a2d3ca3bede00304bd22ed10829535dd53'
|
||||
pod 'QKMRZScanner'
|
||||
pod 'RNFS', :path => '../node_modules/react-native-fs'
|
||||
pod 'lottie-ios'
|
||||
|
||||
@@ -7,9 +7,9 @@ PODS:
|
||||
- fmt (9.1.0)
|
||||
- glog (0.3.5)
|
||||
- lottie-ios (4.5.0)
|
||||
- NFCPassportReader (2.0.3):
|
||||
- OpenSSL-Universal (= 1.1.1100)
|
||||
- OpenSSL-Universal (1.1.1100)
|
||||
- NFCPassportReader (2.1.1):
|
||||
- OpenSSL-Universal (= 1.1.1900)
|
||||
- OpenSSL-Universal (1.1.1900)
|
||||
- QKMRZParser (2.0.0)
|
||||
- QKMRZScanner (3.0.0):
|
||||
- QKMRZParser (~> 2.0.0)
|
||||
@@ -1227,6 +1227,10 @@ PODS:
|
||||
- React-Core
|
||||
- react-native-nfc-manager (3.16.1):
|
||||
- React-Core
|
||||
- react-native-safe-area-context (5.1.0):
|
||||
- React-Core
|
||||
- react-native-tracking-transparency (0.1.2):
|
||||
- React
|
||||
- React-nativeconfig (0.75.4)
|
||||
- React-NativeModulesApple (0.75.4):
|
||||
- glog
|
||||
@@ -1474,6 +1478,27 @@ PODS:
|
||||
- React-Core
|
||||
- RNFS (2.20.0):
|
||||
- React-Core
|
||||
- RNGestureHandler (2.22.1):
|
||||
- DoubleConversion
|
||||
- glog
|
||||
- RCT-Folly (= 2024.01.01.00)
|
||||
- RCTRequired
|
||||
- RCTTypeSafety
|
||||
- React-Core
|
||||
- React-debug
|
||||
- React-Fabric
|
||||
- React-featureflags
|
||||
- React-graphics
|
||||
- React-ImageManager
|
||||
- React-jsi
|
||||
- React-NativeModulesApple
|
||||
- React-RCTFabric
|
||||
- React-rendererdebug
|
||||
- React-utils
|
||||
- ReactCodegen
|
||||
- ReactCommon/turbomodule/bridging
|
||||
- ReactCommon/turbomodule/core
|
||||
- Yoga
|
||||
- RNKeychain (8.2.0):
|
||||
- React-Core
|
||||
- RNSVG (13.4.0):
|
||||
@@ -1485,7 +1510,12 @@ PODS:
|
||||
- RNZipArchive/Core (6.1.2):
|
||||
- React-Core
|
||||
- SSZipArchive (~> 2.2)
|
||||
- segment-analytics-react-native (2.20.3):
|
||||
- React-Core
|
||||
- sovran-react-native
|
||||
- SocketRocket (0.7.0)
|
||||
- sovran-react-native (1.1.3):
|
||||
- React-Core
|
||||
- SSZipArchive (2.4.3)
|
||||
- SwiftQRScanner (1.1.6)
|
||||
- SwiftyTesseract (3.1.3)
|
||||
@@ -1499,7 +1529,7 @@ DEPENDENCIES:
|
||||
- fmt (from `../node_modules/react-native/third-party-podspecs/fmt.podspec`)
|
||||
- glog (from `../node_modules/react-native/third-party-podspecs/glog.podspec`)
|
||||
- lottie-ios
|
||||
- NFCPassportReader (from `https://github.com/0xturboblitz/NFCPassportReader.git`, commit `0a8e26d56f5f85f698b67c5df5ea9ecbb53cbc45`)
|
||||
- NFCPassportReader (from `https://github.com/zk-passport/NFCPassportReader`, commit `8e72f0a2d3ca3bede00304bd22ed10829535dd53`)
|
||||
- QKMRZScanner
|
||||
- RCT-Folly (from `../node_modules/react-native/third-party-podspecs/RCT-Folly.podspec`)
|
||||
- RCT-Folly/Fabric (from `../node_modules/react-native/third-party-podspecs/RCT-Folly.podspec`)
|
||||
@@ -1536,6 +1566,8 @@ DEPENDENCIES:
|
||||
- react-native-get-random-values (from `../node_modules/react-native-get-random-values`)
|
||||
- "react-native-netinfo (from `../node_modules/@react-native-community/netinfo`)"
|
||||
- react-native-nfc-manager (from `../node_modules/react-native-nfc-manager`)
|
||||
- react-native-safe-area-context (from `../node_modules/react-native-safe-area-context`)
|
||||
- react-native-tracking-transparency (from `../node_modules/react-native-tracking-transparency`)
|
||||
- React-nativeconfig (from `../node_modules/react-native/ReactCommon`)
|
||||
- React-NativeModulesApple (from `../node_modules/react-native/ReactCommon/react/nativemodule/core/platform/ios`)
|
||||
- React-perflogger (from `../node_modules/react-native/ReactCommon/reactperflogger`)
|
||||
@@ -1563,9 +1595,12 @@ DEPENDENCIES:
|
||||
- ReactCommon/turbomodule/core (from `../node_modules/react-native/ReactCommon`)
|
||||
- "RNCAsyncStorage (from `../node_modules/@react-native-async-storage/async-storage`)"
|
||||
- RNFS (from `../node_modules/react-native-fs`)
|
||||
- RNGestureHandler (from `../node_modules/react-native-gesture-handler`)
|
||||
- RNKeychain (from `../node_modules/react-native-keychain`)
|
||||
- RNSVG (from `../node_modules/react-native-svg`)
|
||||
- RNZipArchive (from `../node_modules/react-native-zip-archive`)
|
||||
- "segment-analytics-react-native (from `../node_modules/@segment/analytics-react-native`)"
|
||||
- "sovran-react-native (from `../node_modules/@segment/sovran-react-native`)"
|
||||
- SwiftQRScanner (from `https://github.com/vinodiOS/SwiftQRScanner`)
|
||||
- Yoga (from `../node_modules/react-native/ReactCommon/yoga`)
|
||||
|
||||
@@ -1593,8 +1628,8 @@ EXTERNAL SOURCES:
|
||||
glog:
|
||||
:podspec: "../node_modules/react-native/third-party-podspecs/glog.podspec"
|
||||
NFCPassportReader:
|
||||
:commit: 0a8e26d56f5f85f698b67c5df5ea9ecbb53cbc45
|
||||
:git: https://github.com/0xturboblitz/NFCPassportReader.git
|
||||
:commit: 8e72f0a2d3ca3bede00304bd22ed10829535dd53
|
||||
:git: https://github.com/zk-passport/NFCPassportReader
|
||||
RCT-Folly:
|
||||
:podspec: "../node_modules/react-native/third-party-podspecs/RCT-Folly.podspec"
|
||||
RCTDeprecation:
|
||||
@@ -1661,6 +1696,10 @@ EXTERNAL SOURCES:
|
||||
:path: "../node_modules/@react-native-community/netinfo"
|
||||
react-native-nfc-manager:
|
||||
:path: "../node_modules/react-native-nfc-manager"
|
||||
react-native-safe-area-context:
|
||||
:path: "../node_modules/react-native-safe-area-context"
|
||||
react-native-tracking-transparency:
|
||||
:path: "../node_modules/react-native-tracking-transparency"
|
||||
React-nativeconfig:
|
||||
:path: "../node_modules/react-native/ReactCommon"
|
||||
React-NativeModulesApple:
|
||||
@@ -1715,12 +1754,18 @@ EXTERNAL SOURCES:
|
||||
:path: "../node_modules/@react-native-async-storage/async-storage"
|
||||
RNFS:
|
||||
:path: "../node_modules/react-native-fs"
|
||||
RNGestureHandler:
|
||||
:path: "../node_modules/react-native-gesture-handler"
|
||||
RNKeychain:
|
||||
:path: "../node_modules/react-native-keychain"
|
||||
RNSVG:
|
||||
:path: "../node_modules/react-native-svg"
|
||||
RNZipArchive:
|
||||
:path: "../node_modules/react-native-zip-archive"
|
||||
segment-analytics-react-native:
|
||||
:path: "../node_modules/@segment/analytics-react-native"
|
||||
sovran-react-native:
|
||||
:path: "../node_modules/@segment/sovran-react-native"
|
||||
SwiftQRScanner:
|
||||
:git: https://github.com/vinodiOS/SwiftQRScanner
|
||||
Yoga:
|
||||
@@ -1728,8 +1773,8 @@ EXTERNAL SOURCES:
|
||||
|
||||
CHECKOUT OPTIONS:
|
||||
NFCPassportReader:
|
||||
:commit: 0a8e26d56f5f85f698b67c5df5ea9ecbb53cbc45
|
||||
:git: https://github.com/0xturboblitz/NFCPassportReader.git
|
||||
:commit: 8e72f0a2d3ca3bede00304bd22ed10829535dd53
|
||||
:git: https://github.com/zk-passport/NFCPassportReader
|
||||
SwiftQRScanner:
|
||||
:commit: fddcabcb431cd6110cea0394660082661dbafa7e
|
||||
:git: https://github.com/vinodiOS/SwiftQRScanner
|
||||
@@ -1742,8 +1787,8 @@ SPEC CHECKSUMS:
|
||||
fmt: 4c2741a687cc09f0634a2e2c72a838b99f1ff120
|
||||
glog: 69ef571f3de08433d766d614c73a9838a06bf7eb
|
||||
lottie-ios: a881093fab623c467d3bce374367755c272bdd59
|
||||
NFCPassportReader: a160b80e3df3b5325c13902f90405f5eef7520b3
|
||||
OpenSSL-Universal: ebc357f1e6bc71fa463ccb2fe676756aff50e88c
|
||||
NFCPassportReader: e931c61c189e08a4b4afa0ed4014af19eab2f129
|
||||
OpenSSL-Universal: 84efb8a29841f2764ac5403e0c4119a28b713346
|
||||
QKMRZParser: 6b419b6f07d6bff6b50429b97de10846dc902c29
|
||||
QKMRZScanner: cf2348fd6ce441e758328da4adf231ef2b51d769
|
||||
RCT-Folly: 4464f4d875961fce86008d45f4ecf6cef6de0740
|
||||
@@ -1779,6 +1824,8 @@ SPEC CHECKSUMS:
|
||||
react-native-get-random-values: 21325b2244dfa6b58878f51f9aa42821e7ba3d06
|
||||
react-native-netinfo: f0a9899081c185db1de5bb2fdc1c88c202a059ac
|
||||
react-native-nfc-manager: 5213321cf6c18d879c8092c0bf56806b771ec5ac
|
||||
react-native-safe-area-context: 04803a01f39f31cc6605a5531280b477b48f8a88
|
||||
react-native-tracking-transparency: 25ff1ff866e338c137c818bdec20526bb05ffcc1
|
||||
React-nativeconfig: 31072ab0146e643594f6959c7f970a04b6c9ddd0
|
||||
React-NativeModulesApple: 5df767d9a2197ac25f4d8dd2d4ae1af3624022e2
|
||||
React-perflogger: 59e1a3182dca2cee7b9f1f7aab204018d46d1914
|
||||
@@ -1806,15 +1853,18 @@ SPEC CHECKSUMS:
|
||||
ReactCommon: 03d2d48fcd1329fe3bc4e428a78a0181b68068c2
|
||||
RNCAsyncStorage: ec53e44dc3e75b44aa2a9f37618a49c3bc080a7a
|
||||
RNFS: 4ac0f0ea233904cb798630b3c077808c06931688
|
||||
RNGestureHandler: e705387b01bba53f4643bdff381ee08c7b9679a1
|
||||
RNKeychain: bfe3d12bf4620fe488771c414530bf16e88f3678
|
||||
RNSVG: 07dbd870b0dcdecc99b3a202fa37c8ca163caec2
|
||||
RNZipArchive: 6d736ee4e286dbbd9d81206b7a4da355596ca04a
|
||||
segment-analytics-react-native: d57ed4971cbb995706babf29215ebdbf242ecdab
|
||||
SocketRocket: abac6f5de4d4d62d24e11868d7a2f427e0ef940d
|
||||
sovran-react-native: eec37f82e4429f0e3661f46aaf4fcd85d1b54f60
|
||||
SSZipArchive: fe6a26b2a54d5a0890f2567b5cc6de5caa600aef
|
||||
SwiftQRScanner: e85a25f9b843e9231dab89a96e441472fe54a724
|
||||
SwiftyTesseract: 1f3d96668ae92dc2208d9842c8a59bea9fad2cbb
|
||||
Yoga: b05994d1933f507b0a28ceaa4fdb968dc18da178
|
||||
|
||||
PODFILE CHECKSUM: cc6778e0dcd4c510b705f4dc458411547dc1d00c
|
||||
PODFILE CHECKSUM: a5761927116120f511f409f5249a18a8c626545c
|
||||
|
||||
COCOAPODS: 1.16.2
|
||||
COCOAPODS: 1.15.2
|
||||
|
||||
@@ -27,6 +27,8 @@
|
||||
"@react-navigation/elements": "^2.2.5",
|
||||
"@react-navigation/native": "^7.0.14",
|
||||
"@react-navigation/stack": "^7.1.1",
|
||||
"@segment/analytics-react-native": "^2.20.3",
|
||||
"@segment/sovran-react-native": "^1.1.3",
|
||||
"@tamagui/colors": "1.110.0",
|
||||
"@tamagui/config": "1.110.0",
|
||||
"@tamagui/core": "1.110.0",
|
||||
@@ -57,6 +59,7 @@
|
||||
"react-native-passport-reader": "^1.0.3",
|
||||
"react-native-safe-area-context": "^5.1.0",
|
||||
"react-native-svg": "13.4.0",
|
||||
"react-native-tracking-transparency": "^0.1.2",
|
||||
"react-native-zip-archive": "^6.1.0",
|
||||
"socket.io-client": "^4.7.5",
|
||||
"tamagui": "1.110.0",
|
||||
|
||||
@@ -19,7 +19,8 @@ import {
|
||||
} from 'tamagui';
|
||||
|
||||
import { countryCodes } from '../../../common/src/constants/constants';
|
||||
import { genMockPassportData } from '../../../common/src/utils/genMockPassportData';
|
||||
import { genMockPassportData } from '../../../common/src/utils/passports/genMockPassportData';
|
||||
import { parsePassportData } from '../../../common/src/utils/passports/passport_parsing/parsePassportData';
|
||||
import CustomButton from '../components/CustomButton';
|
||||
import useUserStore from '../stores/userStore';
|
||||
import {
|
||||
@@ -77,20 +78,38 @@ const MockDataScreen: React.FC<MockDataScreenProps> = ({}) => {
|
||||
.toUpperCase();
|
||||
await new Promise(resolve =>
|
||||
setTimeout(() => {
|
||||
let mockPassportData;
|
||||
const hashAlgo = selectedAlgorithm === 'rsa sha1' ? 'sha1' : 'sha256';
|
||||
const mockPassportData = genMockPassportData(
|
||||
hashAlgo,
|
||||
hashAlgo,
|
||||
signatureAlgorithmToStrictSignatureAlgorithm[
|
||||
selectedAlgorithm as keyof typeof signatureAlgorithmToStrictSignatureAlgorithm
|
||||
],
|
||||
selectedCountry as keyof typeof countryCodes,
|
||||
castDate(-age),
|
||||
castDate(expiryYears),
|
||||
randomPassportNumber,
|
||||
...(isInOfacList ? ['HENAO MONTOYA', 'ARCANGEL DE JESUS'] : []),
|
||||
);
|
||||
if (isInOfacList) {
|
||||
mockPassportData = genMockPassportData(
|
||||
hashAlgo,
|
||||
hashAlgo,
|
||||
signatureAlgorithmToStrictSignatureAlgorithm[
|
||||
selectedAlgorithm as keyof typeof signatureAlgorithmToStrictSignatureAlgorithm
|
||||
],
|
||||
selectedCountry as keyof typeof countryCodes,
|
||||
castDate(-age),
|
||||
castDate(expiryYears),
|
||||
randomPassportNumber,
|
||||
'HENAO MONTOYA', // this name is the OFAC list
|
||||
'ARCANGEL DE JESUS',
|
||||
);
|
||||
} else {
|
||||
mockPassportData = genMockPassportData(
|
||||
hashAlgo,
|
||||
hashAlgo,
|
||||
signatureAlgorithmToStrictSignatureAlgorithm[
|
||||
selectedAlgorithm as keyof typeof signatureAlgorithmToStrictSignatureAlgorithm
|
||||
],
|
||||
selectedCountry as keyof typeof countryCodes,
|
||||
castDate(-age),
|
||||
castDate(expiryYears),
|
||||
randomPassportNumber,
|
||||
);
|
||||
}
|
||||
useUserStore.getState().registerPassportData(mockPassportData);
|
||||
const parsedPassportData = parsePassportData(mockPassportData);
|
||||
useUserStore.getState().setPassportMetadata(parsedPassportData);
|
||||
useUserStore.getState().setRegistered(true);
|
||||
resolve(null);
|
||||
}, 0),
|
||||
|
||||
@@ -50,9 +50,10 @@ const NextScreen: React.FC = () => {
|
||||
h={height > 750 ? 190 : 130}
|
||||
borderRadius={height > 750 ? '$7' : '$6'}
|
||||
source={{
|
||||
uri: passportData.mockUser
|
||||
? USER_PROFILE
|
||||
: passportData.photoBase64 ?? USER_PROFILE,
|
||||
uri:
|
||||
passportData?.mockUser || !!!passportData?.photoBase64
|
||||
? USER_PROFILE
|
||||
: passportData?.photoBase64 ?? USER_PROFILE,
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
@@ -78,16 +79,34 @@ const NextScreen: React.FC = () => {
|
||||
const key_ = key;
|
||||
const indexes =
|
||||
attributeToPosition[key_ as keyof typeof attributeToPosition];
|
||||
if (!passportData?.mrz || !indexes) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const keyFormatted = key_
|
||||
.replace(/_/g, ' ')
|
||||
.split(' ')
|
||||
.map((word: string) => word.charAt(0).toUpperCase() + word.slice(1))
|
||||
.join(' ');
|
||||
|
||||
if (
|
||||
indexes[0] >= passportData.mrz.length ||
|
||||
indexes[1] >= passportData.mrz.length
|
||||
) {
|
||||
console.warn(
|
||||
`Invalid indexes for key ${key_}: [${indexes[0]}, ${indexes[1]}]`,
|
||||
);
|
||||
return null;
|
||||
}
|
||||
|
||||
const mrzAttribute = passportData.mrz.slice(
|
||||
indexes[0],
|
||||
indexes[1] + 1,
|
||||
);
|
||||
const mrzAttributeFormatted = formatAttribute(key_, mrzAttribute);
|
||||
const mrzAttributeFormatted = formatAttribute(
|
||||
key_,
|
||||
mrzAttribute ?? '',
|
||||
);
|
||||
|
||||
return (
|
||||
<Fieldset horizontal key={key} gap="$3" alignItems="center">
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
|
||||
import { useNavigation } from '@react-navigation/native';
|
||||
import io, { Socket } from 'socket.io-client';
|
||||
import { Text, YStack } from 'tamagui';
|
||||
|
||||
import {
|
||||
DEVELOPMENT_MODE,
|
||||
max_cert_bytes,
|
||||
MAX_CERT_BYTES,
|
||||
} from '../../../../common/src/constants/constants';
|
||||
import {
|
||||
ArgumentsProveOffChain,
|
||||
@@ -16,13 +14,15 @@ import {
|
||||
getCircuitNameOld,
|
||||
parseCertificateSimple,
|
||||
} from '../../../../common/src/utils/certificate_parsing/parseCertificateSimple';
|
||||
// import {
|
||||
// getCSCAFromSKI,
|
||||
// sendCSCARequest,
|
||||
// } from '../../../../common/src/utils/csca';
|
||||
import {
|
||||
generateCircuitInputsDSC,
|
||||
getCSCAFromSKI,
|
||||
sendCSCARequest,
|
||||
} from '../../../../common/src/utils/csca';
|
||||
} from '../../../../common/src/utils/circuits/generateInputs';
|
||||
import { buildAttestation } from '../../../../common/src/utils/openPassportAttestation';
|
||||
import { parsePassportData } from '../../../../common/src/utils/parsePassportData';
|
||||
import { parsePassportData } from '../../../../common/src/utils/passports/passport_parsing/parsePassportData';
|
||||
import Disclosures from '../../components/Disclosures';
|
||||
import { PrimaryButton } from '../../components/buttons/PrimaryButton';
|
||||
import { BodyText } from '../../components/typography/BodyText';
|
||||
@@ -31,7 +31,7 @@ import { ExpandableBottomLayout } from '../../layouts/ExpandableBottomLayout';
|
||||
import useNavigationStore from '../../stores/navigationStore';
|
||||
import useUserStore from '../../stores/userStore';
|
||||
import { black, slate300, white } from '../../utils/colors';
|
||||
import { generateCircuitInputsInApp } from '../../utils/generateInputsInApp';
|
||||
// import { generateCircuitInputsInApp } from '../../utils/generateInputsInApp';
|
||||
import { generateProof } from '../../utils/prover';
|
||||
import { CircuitName } from '../../utils/zkeyDownload';
|
||||
|
||||
@@ -188,34 +188,34 @@ const ProveScreen: React.FC = () => {
|
||||
switch (selectedApp.mode) {
|
||||
case 'prove_onchain':
|
||||
case 'register':
|
||||
const cscaInputs = generateCircuitInputsDSC(
|
||||
dscSecret as string,
|
||||
passportData.dsc,
|
||||
max_cert_bytes,
|
||||
selectedApp.devMode,
|
||||
);
|
||||
[dscProof, proof] = await Promise.all([
|
||||
sendCSCARequest(cscaInputs),
|
||||
generateProof(circuitName, inputs),
|
||||
]);
|
||||
const cscaPem = getCSCAFromSKI(
|
||||
authorityKeyIdentifier,
|
||||
DEVELOPMENT_MODE,
|
||||
);
|
||||
const { signatureAlgorithm: signatureAlgorithmDsc } =
|
||||
parseCertificateSimple(cscaPem);
|
||||
attestation = buildAttestation({
|
||||
mode: selectedApp.mode,
|
||||
proof: proof.proof,
|
||||
publicSignals: proof.publicSignals,
|
||||
signatureAlgorithm: signatureAlgorithm,
|
||||
hashFunction: parsedPassportData.signedAttrHashFunction,
|
||||
userIdType: selectedApp.userIdType,
|
||||
dscProof: (dscProof as any).proof,
|
||||
dscPublicSignals: (dscProof as any).pub_signals,
|
||||
signatureAlgorithmDsc: signatureAlgorithmDsc,
|
||||
hashFunctionDsc: parsedPassportData.signedAttrHashFunction,
|
||||
});
|
||||
// const cscaInputs = generateCircuitInputsDSC(
|
||||
// dscSecret as string,
|
||||
// passportData.dsc,
|
||||
// MAX_CERT_BYTES,
|
||||
// selectedApp.devMode,
|
||||
// );
|
||||
// [dscProof, proof] = await Promise.all([
|
||||
// sendCSCARequest(cscaInputs),
|
||||
// generateProof(circuitName, inputs),
|
||||
// ]);
|
||||
// const cscaPem = getCSCAFromSKI(
|
||||
// authorityKeyIdentifier,
|
||||
// DEVELOPMENT_MODE,
|
||||
// );
|
||||
// const { signatureAlgorithm: signatureAlgorithmDsc } =
|
||||
// parseCertificateSimple(cscaPem);
|
||||
// attestation = buildAttestation({
|
||||
// mode: selectedApp.mode,
|
||||
// proof: proof.proof,
|
||||
// publicSignals: proof.publicSignals,
|
||||
// signatureAlgorithm: signatureAlgorithm,
|
||||
// hashFunction: parsedPassportData.signedAttrHashFunction,
|
||||
// userIdType: selectedApp.userIdType,
|
||||
// dscProof: (dscProof as any).proof,
|
||||
// dscPublicSignals: (dscProof as any).pub_signals,
|
||||
// signatureAlgorithmDsc: signatureAlgorithmDsc,
|
||||
// hashFunctionDsc: parsedPassportData.signedAttrHashFunction,
|
||||
// });
|
||||
break;
|
||||
default:
|
||||
proof = await generateProof(circuitName, inputs);
|
||||
|
||||
@@ -2,7 +2,7 @@ import React from 'react';
|
||||
|
||||
import { ScrollView, Separator, Text, XStack, YStack } from 'tamagui';
|
||||
|
||||
import { parsePassportData } from '../../../common/src/utils/parsePassportData';
|
||||
import { parsePassportData } from '../../../common/src/utils/passports/passport_parsing/parsePassportData';
|
||||
import useUserStore from '../stores/userStore';
|
||||
import { separatorColor, textBlack } from '../utils/colors';
|
||||
|
||||
@@ -126,7 +126,7 @@ const UserInfo: React.FC = () => {
|
||||
|
||||
<InfoRow
|
||||
label="CSCA Signature Algorithm"
|
||||
value={passportMetaData?.cscaSignature || 'None'}
|
||||
value={passportMetaData?.cscaSignatureAlgorithm || 'None'}
|
||||
/>
|
||||
<Separator borderColor={separatorColor} />
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ import { useToastController } from '@tamagui/toast';
|
||||
import { create } from 'zustand';
|
||||
|
||||
import { OpenPassportApp } from '../../../common/src/utils/appType';
|
||||
import { segmentClient } from '../../App';
|
||||
import {
|
||||
IsZkeyDownloading,
|
||||
ShowWarningModalProps,
|
||||
@@ -24,10 +25,12 @@ interface NavigationState {
|
||||
setNfcSheetIsOpen: (isOpen: boolean) => void;
|
||||
zkeyDownloadedPercentage: number;
|
||||
setZkeyDownloadedPercentage: (percentage: number) => void;
|
||||
trackEvent: (eventName: string, properties?: Record<string, any>) => void;
|
||||
trackNavigation: (tab: string) => void;
|
||||
}
|
||||
|
||||
const useNavigationStore = create<NavigationState>((set, get) => ({
|
||||
zkeyDownloadedPercentage: 100,
|
||||
zkeyDownloadedPercentage: 0,
|
||||
setZkeyDownloadedPercentage: (percentage: number) =>
|
||||
set({ zkeyDownloadedPercentage: percentage }),
|
||||
isZkeyDownloading: {
|
||||
@@ -54,7 +57,10 @@ const useNavigationStore = create<NavigationState>((set, get) => ({
|
||||
setToast: toast => set({ toast }),
|
||||
setSelectedApp: app => set({ selectedApp: app }),
|
||||
|
||||
setSelectedTab: tab => set({ selectedTab: tab }),
|
||||
setSelectedTab: (tab: string) => {
|
||||
const { trackNavigation } = get();
|
||||
trackNavigation(tab);
|
||||
},
|
||||
|
||||
update: patch => {
|
||||
set({
|
||||
@@ -64,6 +70,21 @@ const useNavigationStore = create<NavigationState>((set, get) => ({
|
||||
},
|
||||
nfcSheetIsOpen: false,
|
||||
setNfcSheetIsOpen: isOpen => set({ nfcSheetIsOpen: isOpen }),
|
||||
|
||||
trackEvent: (eventName: string, properties?: Record<string, any>) => {
|
||||
if (segmentClient) {
|
||||
segmentClient.track(eventName, properties);
|
||||
}
|
||||
},
|
||||
|
||||
trackNavigation: (tab: string) => {
|
||||
if (segmentClient) {
|
||||
segmentClient.track('Navigation Change', {
|
||||
tab,
|
||||
});
|
||||
}
|
||||
set({ selectedTab: tab });
|
||||
},
|
||||
}));
|
||||
|
||||
export default useNavigationStore;
|
||||
|
||||
@@ -3,12 +3,15 @@ import { resetGenericPassword } from 'react-native-keychain';
|
||||
import { DEFAULT_DOB, DEFAULT_DOE, DEFAULT_PNUMBER } from '@env';
|
||||
import { create } from 'zustand';
|
||||
|
||||
import { generateDscSecret } from '../../../common/src/utils/csca';
|
||||
// import { generateDscSecret } from '../../../common/src/utils/csca';
|
||||
import { PassportMetadata } from '../../../common/src/utils/passports/passport_parsing/parsePassportData';
|
||||
import { PassportData, Proof } from '../../../common/src/utils/types';
|
||||
import {
|
||||
loadPassportData,
|
||||
loadPassportMetadata,
|
||||
loadSecretOrCreateIt,
|
||||
storePassportData,
|
||||
storePassportMetadata,
|
||||
} from '../utils/keychain';
|
||||
|
||||
interface UserState {
|
||||
@@ -18,6 +21,7 @@ interface UserState {
|
||||
countryCode: string;
|
||||
registered: boolean;
|
||||
passportData: PassportData | null;
|
||||
passportMetadata: PassportMetadata | null;
|
||||
secret: string;
|
||||
cscaProof: Proof | null;
|
||||
localProof: Proof | null;
|
||||
@@ -35,6 +39,8 @@ interface UserState {
|
||||
setUserLoaded: (userLoaded: boolean) => void;
|
||||
proofVerificationResult: string;
|
||||
setProofVerificationResult: (proofVerificationResult: string) => void;
|
||||
setPassportMetadata: (metadata: PassportMetadata) => void;
|
||||
clearPassportMetadataFromStorage: () => void;
|
||||
}
|
||||
|
||||
const useUserStore = create<UserState>((set, get) => ({
|
||||
@@ -46,6 +52,7 @@ const useUserStore = create<UserState>((set, get) => ({
|
||||
dscSecret: null,
|
||||
registered: false,
|
||||
passportData: null,
|
||||
passportMetadata: null,
|
||||
secret: '',
|
||||
cscaProof: null,
|
||||
localProof: null,
|
||||
@@ -58,6 +65,10 @@ const useUserStore = create<UserState>((set, get) => ({
|
||||
setUserLoaded: (userLoaded: boolean) => {
|
||||
set({ userLoaded });
|
||||
},
|
||||
setPassportMetadata: async (metadata: PassportMetadata) => {
|
||||
await storePassportMetadata(metadata);
|
||||
set({ passportMetadata: metadata });
|
||||
},
|
||||
proofVerificationResult: 'null',
|
||||
setProofVerificationResult: (proofVerificationResult: string) => {
|
||||
set({ proofVerificationResult });
|
||||
@@ -68,16 +79,18 @@ const useUserStore = create<UserState>((set, get) => ({
|
||||
// - If the commitment is present in the tree, proceed to main screen
|
||||
// - If the commitment is not present in the tree, proceed to main screen AND try registering it in the background
|
||||
initUserStore: async () => {
|
||||
// download zkeys if they are not already downloaded
|
||||
|
||||
const secret = await loadSecretOrCreateIt();
|
||||
set({ secret });
|
||||
const dscSecret = await generateDscSecret();
|
||||
set({ dscSecret });
|
||||
// const dscSecret = await generateDscSecret();
|
||||
// set({ dscSecret });
|
||||
|
||||
const passportDataString = await loadPassportData();
|
||||
if (!passportDataString) {
|
||||
console.log('No passport data found, starting onboarding flow');
|
||||
const passportMetadataString = await loadPassportMetadata();
|
||||
|
||||
if (!passportDataString || !passportMetadataString) {
|
||||
console.log(
|
||||
'No passport data or metadata found, starting onboarding flow',
|
||||
);
|
||||
set({
|
||||
userLoaded: true,
|
||||
});
|
||||
@@ -87,6 +100,9 @@ const useUserStore = create<UserState>((set, get) => ({
|
||||
// const isAlreadyRegistered = await isCommitmentRegistered(secret, JSON.parse(passportData));
|
||||
const isAlreadyRegistered = true;
|
||||
const passportData: PassportData = JSON.parse(passportDataString);
|
||||
const passportMetadata: PassportMetadata = JSON.parse(
|
||||
passportMetadataString,
|
||||
);
|
||||
|
||||
if (!isAlreadyRegistered) {
|
||||
console.log(
|
||||
@@ -94,9 +110,9 @@ const useUserStore = create<UserState>((set, get) => ({
|
||||
);
|
||||
set({
|
||||
passportData: passportData,
|
||||
passportMetadata: passportMetadata,
|
||||
userLoaded: true,
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -105,9 +121,10 @@ const useUserStore = create<UserState>((set, get) => ({
|
||||
);
|
||||
set({
|
||||
passportData: passportData,
|
||||
passportMetadata: passportMetadata,
|
||||
registered: true,
|
||||
userLoaded: true,
|
||||
});
|
||||
set({ userLoaded: true });
|
||||
},
|
||||
|
||||
// When reading passport for the first time:
|
||||
@@ -152,6 +169,11 @@ const useUserStore = create<UserState>((set, get) => ({
|
||||
dateOfBirth: '',
|
||||
dateOfExpiry: '',
|
||||
}),
|
||||
|
||||
clearPassportMetadataFromStorage: async () => {
|
||||
await resetGenericPassword({ service: 'passportMetadata' });
|
||||
set({ passportMetadata: null });
|
||||
},
|
||||
}));
|
||||
|
||||
export default useUserStore;
|
||||
|
||||
@@ -15,11 +15,11 @@ import {
|
||||
OpenPassportApp,
|
||||
} from '../../../common/src/utils/appType';
|
||||
import {
|
||||
generateCircuitInputsDisclose,
|
||||
generateCircuitInputsProve,
|
||||
} from '../../../common/src/utils/generateInputs';
|
||||
import { fetchTreeFromUrl } from '../../../common/src/utils/pubkeyTree';
|
||||
import { revealBitmapFromAttributes } from '../../../common/src/utils/revealBitmap';
|
||||
generateCircuitInputsRegister,
|
||||
generateCircuitInputsVCandDisclose,
|
||||
} from '../../../common/src/utils/circuits/generateInputs';
|
||||
import { fetchTreeFromUrl } from '../../../common/src/utils/trees';
|
||||
import { revealBitmapFromAttributes } from '../../../common/src/utils/circuits/formatOutputs';
|
||||
import { PassportData } from '../../../common/src/utils/types';
|
||||
import useUserStore from '../stores/userStore';
|
||||
|
||||
@@ -99,7 +99,7 @@ export const generateCircuitInputsInApp = async (
|
||||
disclosureOptionsDisclose.excludedCountries.value.map(country =>
|
||||
getCountryCode(country),
|
||||
);
|
||||
return generateCircuitInputsDisclose(
|
||||
return generateCircuitInputsVCandDisclose(
|
||||
secret,
|
||||
PASSPORT_ATTESTATION_ID,
|
||||
passportData,
|
||||
|
||||
@@ -2,6 +2,7 @@ import * as Keychain from 'react-native-keychain';
|
||||
|
||||
import { ethers } from 'ethers';
|
||||
|
||||
import { PassportMetadata } from '../../../common/src/utils/passports/passport_parsing/parsePassportData';
|
||||
import { PassportData } from '../../../common/src/utils/types';
|
||||
|
||||
export async function loadSecretOrCreateIt() {
|
||||
@@ -36,3 +37,18 @@ export async function storePassportData(passportData: PassportData) {
|
||||
{ service: 'passportData' },
|
||||
);
|
||||
}
|
||||
|
||||
export async function loadPassportMetadata() {
|
||||
const metadataCreds = await Keychain.getGenericPassword({
|
||||
service: 'passportMetadata',
|
||||
});
|
||||
return metadataCreds === false ? false : metadataCreds.password;
|
||||
}
|
||||
|
||||
export async function storePassportMetadata(metadata: PassportMetadata) {
|
||||
await Keychain.setGenericPassword(
|
||||
'passportMetadata',
|
||||
JSON.stringify(metadata),
|
||||
{ service: 'passportMetadata' },
|
||||
);
|
||||
}
|
||||
|
||||
@@ -2,10 +2,9 @@ import { NativeModules, Platform } from 'react-native';
|
||||
import PassportReader from 'react-native-passport-reader';
|
||||
|
||||
// @ts-ignore
|
||||
import * as amplitude from '@amplitude/analytics-react-native';
|
||||
import { Buffer } from 'buffer';
|
||||
|
||||
import { parsePassportData } from '../../../common/src/utils/parsePassportData';
|
||||
import { parsePassportData } from '../../../common/src/utils/passports/passport_parsing/parsePassportData';
|
||||
import { PassportData } from '../../../common/src/utils/types';
|
||||
import useNavigationStore from '../stores/navigationStore';
|
||||
import useUserStore from '../stores/userStore';
|
||||
@@ -16,12 +15,15 @@ export const scan = async (
|
||||
) => {
|
||||
const { passportNumber, dateOfBirth, dateOfExpiry } = useUserStore.getState();
|
||||
|
||||
const { toast } = useNavigationStore.getState();
|
||||
const { toast, trackEvent } = useNavigationStore.getState();
|
||||
|
||||
const check = checkInputs(passportNumber, dateOfBirth, dateOfExpiry);
|
||||
|
||||
if (!check.success) {
|
||||
amplitude.track('inputs_invalid', { error: check.message });
|
||||
trackEvent('Inputs Failed', {
|
||||
success: false,
|
||||
error: check.message,
|
||||
});
|
||||
toast.show('Unvailable', {
|
||||
message: check.message,
|
||||
customData: {
|
||||
@@ -31,20 +33,26 @@ export const scan = async (
|
||||
return;
|
||||
}
|
||||
|
||||
trackEvent('NFC Started', {
|
||||
success: true,
|
||||
});
|
||||
|
||||
console.log('scanning...');
|
||||
|
||||
if (Platform.OS === 'android') {
|
||||
scanAndroid(setModalProofStep);
|
||||
scanAndroid(setModalProofStep, Date.now());
|
||||
} else {
|
||||
scanIOS(setModalProofStep);
|
||||
scanIOS(setModalProofStep, Date.now());
|
||||
}
|
||||
};
|
||||
|
||||
const scanAndroid = async (
|
||||
setModalProofStep: (modalProofStep: number) => void,
|
||||
startTime: number,
|
||||
) => {
|
||||
const { passportNumber, dateOfBirth, dateOfExpiry } = useUserStore.getState();
|
||||
const { toast, setNfcSheetIsOpen } = useNavigationStore.getState();
|
||||
const { toast, setNfcSheetIsOpen, trackEvent } =
|
||||
useNavigationStore.getState();
|
||||
setNfcSheetIsOpen(true);
|
||||
|
||||
try {
|
||||
@@ -55,12 +63,15 @@ const scanAndroid = async (
|
||||
});
|
||||
console.log('scanned');
|
||||
setNfcSheetIsOpen(false);
|
||||
amplitude.track('nfc_scan_successful');
|
||||
handleResponseAndroid(response, setModalProofStep);
|
||||
|
||||
trackEvent('NFC Success', {
|
||||
success: true,
|
||||
duration_ms: Date.now() - startTime,
|
||||
});
|
||||
} catch (e: any) {
|
||||
console.log('error during scan:', e);
|
||||
setNfcSheetIsOpen(false);
|
||||
amplitude.track('nfc_scan_unsuccessful', { error: e.message });
|
||||
if (e.message.includes('InvalidMRZKey')) {
|
||||
toast.show('Error', {
|
||||
message:
|
||||
@@ -70,6 +81,10 @@ const scanAndroid = async (
|
||||
},
|
||||
timeout: 5000,
|
||||
});
|
||||
trackEvent('Invalid Key', {
|
||||
success: false,
|
||||
error: e.message,
|
||||
});
|
||||
useNavigationStore.getState().setSelectedTab('scan');
|
||||
} else {
|
||||
toast.show('Error', {
|
||||
@@ -78,13 +93,21 @@ const scanAndroid = async (
|
||||
type: 'error',
|
||||
},
|
||||
});
|
||||
trackEvent('NFC Failed', {
|
||||
success: false,
|
||||
error: e.message,
|
||||
duration_ms: Date.now() - startTime,
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const scanIOS = async (setModalProofStep: (modalProofStep: number) => void) => {
|
||||
const scanIOS = async (
|
||||
setModalProofStep: (modalProofStep: number) => void,
|
||||
startTime: number,
|
||||
) => {
|
||||
const { passportNumber, dateOfBirth, dateOfExpiry } = useUserStore.getState();
|
||||
const { toast } = useNavigationStore.getState();
|
||||
const { toast, trackEvent } = useNavigationStore.getState();
|
||||
|
||||
console.log('passportNumber', passportNumber);
|
||||
console.log('dateOfBirth', dateOfBirth);
|
||||
@@ -98,18 +121,13 @@ const scanIOS = async (setModalProofStep: (modalProofStep: number) => void) => {
|
||||
);
|
||||
console.log('scanned');
|
||||
handleResponseIOS(response, setModalProofStep);
|
||||
amplitude.track('nfc_scan_successful');
|
||||
|
||||
trackEvent('NFC Success', {
|
||||
success: true,
|
||||
duration_ms: Date.now() - startTime,
|
||||
});
|
||||
} catch (e: any) {
|
||||
console.log('error during scan:', e);
|
||||
amplitude.track('nfc_scan_unsuccessful', { error: e.message });
|
||||
// if (!e.message.includes("UserCanceled")) {
|
||||
// toast.show('Failed to read passport', {
|
||||
// message: e.message,
|
||||
// customData: {
|
||||
// type: "error",
|
||||
// },
|
||||
// })
|
||||
// }
|
||||
if (e.message.includes('InvalidMRZKey')) {
|
||||
toast.show('Error', {
|
||||
message:
|
||||
@@ -120,6 +138,10 @@ const scanIOS = async (setModalProofStep: (modalProofStep: number) => void) => {
|
||||
timeout: 5000,
|
||||
});
|
||||
useNavigationStore.getState().setSelectedTab('scan');
|
||||
trackEvent('Invalid Key', {
|
||||
success: false,
|
||||
error: e.message,
|
||||
});
|
||||
} else {
|
||||
toast.show('Error', {
|
||||
message: e.message,
|
||||
@@ -127,6 +149,10 @@ const scanIOS = async (setModalProofStep: (modalProofStep: number) => void) => {
|
||||
type: 'error',
|
||||
},
|
||||
});
|
||||
trackEvent('NFC Failed', {
|
||||
success: false,
|
||||
error: e.message,
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -135,7 +161,7 @@ const handleResponseIOS = async (
|
||||
response: any,
|
||||
_setModalProofStep: (modalProofStep: number) => void,
|
||||
) => {
|
||||
const { toast } = useNavigationStore.getState();
|
||||
const { toast, trackEvent } = useNavigationStore.getState();
|
||||
|
||||
const parsed = JSON.parse(response);
|
||||
|
||||
@@ -149,21 +175,16 @@ const handleResponseIOS = async (
|
||||
const signedAttributes = parsed?.signedAttributes; // this is what we call eContent in android world
|
||||
const mrz = parsed?.passportMRZ;
|
||||
const signatureBase64 = parsed?.signatureBase64;
|
||||
console.log('dataGroupsPresent', parsed?.dataGroupsPresent);
|
||||
console.log('placeOfBirth', parsed?.placeOfBirth);
|
||||
console.log('activeAuthenticationPassed', parsed?.activeAuthenticationPassed);
|
||||
console.log('isPACESupported', parsed?.isPACESupported);
|
||||
console.log(
|
||||
'isChipAuthenticationSupported',
|
||||
parsed?.isChipAuthenticationSupported,
|
||||
);
|
||||
console.log('residenceAddress', parsed?.residenceAddress);
|
||||
console.log('passportPhoto', parsed?.passportPhoto.substring(0, 100) + '...');
|
||||
console.log(
|
||||
'encapsulatedContentDigestAlgorithm',
|
||||
parsed?.encapsulatedContentDigestAlgorithm,
|
||||
);
|
||||
console.log('documentSigningCertificate', parsed?.documentSigningCertificate);
|
||||
const pem = JSON.parse(parsed?.documentSigningCertificate).PEM.replace(
|
||||
/\n/g,
|
||||
'',
|
||||
@@ -186,18 +207,6 @@ const handleResponseIOS = async (
|
||||
Buffer.from(signatureBase64, 'base64'),
|
||||
).map(byte => (byte > 127 ? byte - 256 : byte));
|
||||
|
||||
// amplitude.track('nfc_response_parsed', {
|
||||
// dataGroupsPresent: parsed?.dataGroupsPresent,
|
||||
// eContentLength: signedEContentArray?.length,
|
||||
// concatenatedDataHashesLength: concatenatedDataHashesArraySigned?.length,
|
||||
// encryptedDigestLength: encryptedDigestArray?.length,
|
||||
// activeAuthenticationPassed: parsed?.activeAuthenticationPassed,
|
||||
// isPACESupported: parsed?.isPACESupported,
|
||||
// isChipAuthenticationSupported: parsed?.isChipAuthenticationSupported,
|
||||
// encapsulatedContentDigestAlgorithm: parsed?.encapsulatedContentDigestAlgorithm,
|
||||
// dsc: pem,
|
||||
// });
|
||||
|
||||
const passportData = {
|
||||
mrz,
|
||||
dsc: pem,
|
||||
@@ -207,24 +216,28 @@ const handleResponseIOS = async (
|
||||
eContent: concatenatedDataHashesArraySigned,
|
||||
signedAttr: signedEContentArray,
|
||||
encryptedDigest: encryptedDigestArray,
|
||||
photoBase64: 'data:image/jpeg;base64,' + parsed.passportPhoto,
|
||||
photoBase64: parsed?.passportPhoto
|
||||
? 'data:image/jpeg;base64,' + parsed?.passportPhoto
|
||||
: '',
|
||||
mockUser: false,
|
||||
parsed: false,
|
||||
};
|
||||
const parsedPassportData = parsePassportData(passportData);
|
||||
amplitude.track('nfc_response_parsed', parsedPassportData);
|
||||
|
||||
try {
|
||||
useUserStore.getState().registerPassportData(passportData);
|
||||
useNavigationStore.getState().setSelectedTab('next');
|
||||
parsePassportDataAsync(passportData);
|
||||
} catch (e: any) {
|
||||
console.log('error during parsing:', e);
|
||||
amplitude.track('error_parsing_nfc_response', { error: e.message });
|
||||
toast.show('Error', {
|
||||
toast.show('Error during passport data parsing', {
|
||||
message: e.message,
|
||||
customData: {
|
||||
type: 'error',
|
||||
},
|
||||
});
|
||||
|
||||
trackEvent('Passport ParseFailed', {
|
||||
success: false,
|
||||
error: e.message,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
@@ -232,18 +245,18 @@ const handleResponseAndroid = async (
|
||||
response: any,
|
||||
_setModalProofStep: (modalProofStep: number) => void,
|
||||
) => {
|
||||
const { toast } = useNavigationStore.getState();
|
||||
const { toast, trackEvent } = useNavigationStore.getState();
|
||||
|
||||
const {
|
||||
mrz,
|
||||
eContent,
|
||||
encryptedDigest,
|
||||
photo,
|
||||
digestAlgorithm,
|
||||
signerInfoDigestAlgorithm,
|
||||
digestEncryptionAlgorithm,
|
||||
LDSVersion,
|
||||
unicodeVersion,
|
||||
// digestAlgorithm,
|
||||
// signerInfoDigestAlgorithm,
|
||||
// digestEncryptionAlgorithm,
|
||||
// LDSVersion,
|
||||
// unicodeVersion,
|
||||
encapContent,
|
||||
documentSigningCertificate,
|
||||
dataGroupHashes,
|
||||
@@ -272,8 +285,9 @@ const handleResponseAndroid = async (
|
||||
eContent: JSON.parse(encapContent),
|
||||
signedAttr: JSON.parse(eContent),
|
||||
encryptedDigest: JSON.parse(encryptedDigest),
|
||||
photoBase64: photo.base64,
|
||||
photoBase64: photo?.base64 ?? '',
|
||||
mockUser: false,
|
||||
parsed: false,
|
||||
};
|
||||
|
||||
console.log(
|
||||
@@ -287,7 +301,7 @@ const handleResponseAndroid = async (
|
||||
2,
|
||||
),
|
||||
);
|
||||
|
||||
/***
|
||||
console.log('mrz', passportData?.mrz);
|
||||
console.log('dataGroupHashes', passportData?.eContent);
|
||||
console.log('eContent', passportData?.eContent);
|
||||
@@ -303,31 +317,56 @@ const handleResponseAndroid = async (
|
||||
console.log('unicodeVersion', unicodeVersion);
|
||||
console.log('encapContent', encapContent);
|
||||
console.log('documentSigningCertificate', documentSigningCertificate);
|
||||
|
||||
const parsedPassportData = parsePassportData(passportData);
|
||||
amplitude.track('nfc_response_parsed', parsedPassportData);
|
||||
// amplitude.track('nfc_response_parsed', {
|
||||
// dataGroupHashesLength: passportData?.eContent?.length,
|
||||
// eContentLength: passportData?.eContent?.length,
|
||||
// encryptedDigestLength: passportData?.encryptedDigest?.length,
|
||||
// digestAlgorithm: digestAlgorithm,
|
||||
// signerInfoDigestAlgorithm: signerInfoDigestAlgorithm,
|
||||
// digestEncryptionAlgorithm: digestEncryptionAlgorithm,
|
||||
// dsc: pem,
|
||||
// mockUser: false
|
||||
// });
|
||||
***/
|
||||
|
||||
try {
|
||||
await useUserStore.getState().registerPassportData(passportData);
|
||||
useNavigationStore.getState().setSelectedTab('next');
|
||||
parsePassportDataAsync(passportData);
|
||||
} catch (e: any) {
|
||||
console.log('error during parsing:', e);
|
||||
amplitude.track('error_parsing_nfc_response', { error: e.message });
|
||||
toast.show('Error', {
|
||||
message: e.message,
|
||||
customData: {
|
||||
type: 'error',
|
||||
},
|
||||
});
|
||||
|
||||
trackEvent('Passport ParseFailed', {
|
||||
success: false,
|
||||
error: e.message,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
async function parsePassportDataAsync(passportData: PassportData) {
|
||||
const { trackEvent } = useNavigationStore.getState();
|
||||
const parsedPassportData = parsePassportData(passportData);
|
||||
useUserStore.getState().setPassportMetadata(parsedPassportData);
|
||||
await useUserStore.getState().registerPassportData(passportData);
|
||||
trackEvent('Passport Parsed', {
|
||||
success: true,
|
||||
data_groups: parsedPassportData.dataGroups,
|
||||
dg1_hash_function: parsedPassportData.dg1HashFunction,
|
||||
dg1_hash_offset: parsedPassportData.dg1HashOffset,
|
||||
dg_padding_bytes: parsedPassportData.dgPaddingBytes,
|
||||
e_content_size: parsedPassportData.eContentSize,
|
||||
e_content_hash_function: parsedPassportData.eContentHashFunction,
|
||||
e_content_hash_offset: parsedPassportData.eContentHashOffset,
|
||||
signed_attr_size: parsedPassportData.signedAttrSize,
|
||||
signed_attr_hash_function: parsedPassportData.signedAttrHashFunction,
|
||||
signature_algorithm: parsedPassportData.signatureAlgorithm,
|
||||
salt_length: parsedPassportData.saltLength,
|
||||
curve_or_exponent: parsedPassportData.curveOrExponent,
|
||||
signature_algorithm_bits: parsedPassportData.signatureAlgorithmBits,
|
||||
country_code: parsedPassportData.countryCode,
|
||||
csca_found: parsedPassportData.cscaFound,
|
||||
csca_hash_function: parsedPassportData.cscaHashFunction,
|
||||
csca_signature_algorithm: parsedPassportData.cscaSignatureAlgorithm,
|
||||
csca_salt_length: parsedPassportData.cscaSaltLength,
|
||||
csca_curve_or_exponent: parsedPassportData.cscaCurveOrExponent,
|
||||
csca_signature_algorithm_bits:
|
||||
parsedPassportData.cscaSignatureAlgorithmBits,
|
||||
dsc: parsedPassportData.dsc,
|
||||
});
|
||||
|
||||
useNavigationStore.getState().setSelectedTab('next');
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ import * as amplitude from '@amplitude/analytics-react-native';
|
||||
import '@react-navigation/native';
|
||||
import { Buffer } from 'buffer';
|
||||
|
||||
import { parsePassportData } from '../../../common/src/utils/parsePassportData';
|
||||
import { parsePassportData } from '../../../common/src/utils/passports/passport_parsing/parsePassportData';
|
||||
import { PassportData } from '../../../common/src/utils/types';
|
||||
import useNavigationStore from '../stores/navigationStore';
|
||||
import useUserStore from '../stores/userStore';
|
||||
@@ -179,6 +179,7 @@ const handleResponseIOS = async (response: any) => {
|
||||
encryptedDigest: encryptedDigestArray,
|
||||
photoBase64: 'data:image/jpeg;base64,' + parsed.passportPhoto,
|
||||
mockUser: false,
|
||||
parsed: false,
|
||||
};
|
||||
const parsedPassportData = parsePassportData(passportData);
|
||||
amplitude.track('nfc_response_parsed', parsedPassportData);
|
||||
@@ -238,6 +239,7 @@ const handleResponseAndroid = async (response: any) => {
|
||||
encryptedDigest: JSON.parse(encryptedDigest),
|
||||
photoBase64: photo.base64,
|
||||
mockUser: false,
|
||||
parsed: false,
|
||||
};
|
||||
|
||||
console.log(
|
||||
|
||||
@@ -1,27 +1,30 @@
|
||||
import { NativeModules, Platform } from 'react-native';
|
||||
import RNFS from 'react-native-fs';
|
||||
|
||||
import * as amplitude from '@amplitude/analytics-react-native';
|
||||
|
||||
import useNavigationStore from '../stores/navigationStore';
|
||||
import { parseProofAndroid } from './utils';
|
||||
|
||||
export const generateProof = async (circuit: string, inputs: any) => {
|
||||
console.log('launching generateProof function');
|
||||
console.log('inputs in prover.ts', inputs);
|
||||
console.log('circuit', circuit);
|
||||
const startTime = Date.now();
|
||||
const { trackEvent } = useNavigationStore.getState();
|
||||
|
||||
trackEvent('Proof Started', {
|
||||
success: true,
|
||||
circuit: circuit,
|
||||
});
|
||||
|
||||
// Example: "/data/user/0/com.proofofpassportapp/files/register_sha256WithRSAEncryption_65537.zkey" on android
|
||||
const zkey_path = `${RNFS.DocumentDirectoryPath}/${circuit}.zkey`;
|
||||
const dat_path = `${RNFS.DocumentDirectoryPath}/${circuit}.dat`;
|
||||
|
||||
const witness_calculator = circuit;
|
||||
|
||||
if (!zkey_path || !witness_calculator || !dat_path) {
|
||||
trackEvent('Proof Failed', {
|
||||
success: false,
|
||||
error: 'Required parameters are missing',
|
||||
circuit: circuit,
|
||||
});
|
||||
throw new Error('Required parameters are missing');
|
||||
}
|
||||
console.log('zkey_path', zkey_path);
|
||||
console.log('witness_calculator', witness_calculator);
|
||||
console.log('dat_path', dat_path);
|
||||
|
||||
try {
|
||||
const response = await NativeModules.Prover.runProveAction(
|
||||
@@ -31,15 +34,24 @@ export const generateProof = async (circuit: string, inputs: any) => {
|
||||
inputs,
|
||||
);
|
||||
|
||||
// console.log('local proof:', response);
|
||||
|
||||
if (Platform.OS === 'android') {
|
||||
const parsedResponse = parseProofAndroid(response);
|
||||
console.log('parsedResponse', parsedResponse);
|
||||
|
||||
trackEvent('Proof Generated', {
|
||||
success: true,
|
||||
duration_ms: Date.now() - startTime,
|
||||
circuit: circuit,
|
||||
});
|
||||
|
||||
return formatProof(parsedResponse);
|
||||
} else {
|
||||
const parsedResponse = JSON.parse(response);
|
||||
console.log('parsedResponse', parsedResponse);
|
||||
|
||||
trackEvent('Proof Generated', {
|
||||
success: true,
|
||||
duration_ms: Date.now() - startTime,
|
||||
circuit: circuit,
|
||||
});
|
||||
|
||||
return formatProof({
|
||||
proof: parsedResponse.proof,
|
||||
@@ -47,31 +59,47 @@ export const generateProof = async (circuit: string, inputs: any) => {
|
||||
});
|
||||
}
|
||||
} catch (err: any) {
|
||||
console.log('err', err);
|
||||
amplitude.track('error_generating_proof', {
|
||||
trackEvent('Proof Failed', {
|
||||
success: false,
|
||||
error: err.message,
|
||||
duration_ms: Date.now() - startTime,
|
||||
circuit: circuit,
|
||||
zkey_path: zkey_path,
|
||||
witness_calculator: witness_calculator,
|
||||
dat_path: dat_path,
|
||||
});
|
||||
|
||||
throw new Error(err);
|
||||
}
|
||||
};
|
||||
|
||||
export const formatProof = (rawProof: any): any => {
|
||||
return {
|
||||
proof: {
|
||||
pi_a: [rawProof.proof.a[0], rawProof.proof.a[1], '1'],
|
||||
pi_b: [
|
||||
[rawProof.proof.b[0][0], rawProof.proof.b[0][1]],
|
||||
[rawProof.proof.b[1][0], rawProof.proof.b[1][1]],
|
||||
['1', '0'],
|
||||
],
|
||||
pi_c: [rawProof.proof.c[0], rawProof.proof.c[1], '1'],
|
||||
protocol: 'groth16',
|
||||
curve: 'bn128',
|
||||
},
|
||||
publicSignals: (rawProof as any).pub_signals,
|
||||
};
|
||||
const { trackEvent } = useNavigationStore.getState();
|
||||
try {
|
||||
const formattedProof = {
|
||||
proof: {
|
||||
pi_a: [rawProof.proof.a[0], rawProof.proof.a[1], '1'],
|
||||
pi_b: [
|
||||
[rawProof.proof.b[0][0], rawProof.proof.b[0][1]],
|
||||
[rawProof.proof.b[1][0], rawProof.proof.b[1][1]],
|
||||
['1', '0'],
|
||||
],
|
||||
pi_c: [rawProof.proof.c[0], rawProof.proof.c[1], '1'],
|
||||
protocol: 'groth16',
|
||||
curve: 'bn128',
|
||||
},
|
||||
publicSignals: (rawProof as any).pub_signals,
|
||||
};
|
||||
trackEvent('Proof Formatted', {
|
||||
success: true,
|
||||
});
|
||||
|
||||
return formattedProof;
|
||||
} catch (err: any) {
|
||||
trackEvent('Proof FormatFailed', {
|
||||
success: false,
|
||||
error: err.message,
|
||||
});
|
||||
throw err;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -5,7 +5,6 @@ import pako from 'pako';
|
||||
|
||||
import { Mode, OpenPassportApp } from '../../../common/src/utils/appType';
|
||||
import { getCircuitNameOld } from '../../../common/src/utils/certificate_parsing/parseCertificateSimple';
|
||||
import { parsePassportData } from '../../../common/src/utils/parsePassportData';
|
||||
import useNavigationStore from '../stores/navigationStore';
|
||||
import useUserStore from '../stores/userStore';
|
||||
import { downloadZkey } from './zkeyDownload';
|
||||
@@ -26,81 +25,66 @@ export const scanQRCode = () => {
|
||||
const { toast, setSelectedApp, setSelectedTab } =
|
||||
useNavigationStore.getState();
|
||||
|
||||
Linking.getInitialURL()
|
||||
.then(url => {
|
||||
if (url) {
|
||||
handleUniversalLink(url);
|
||||
} else {
|
||||
if (Platform.OS === 'ios') {
|
||||
console.log('Scanning QR code on iOS without Universal Link');
|
||||
|
||||
const qrScanner = NativeModules.QRScannerBridge;
|
||||
if (qrScanner && qrScanner.scanQRCode) {
|
||||
qrScanner
|
||||
.scanQRCode()
|
||||
.then((result: string) => {
|
||||
const params = parseUrlParams(result);
|
||||
const encodedData = params.get('data');
|
||||
handleQRCodeScan(
|
||||
encodedData as string,
|
||||
toast,
|
||||
setSelectedApp,
|
||||
setSelectedTab,
|
||||
);
|
||||
})
|
||||
.catch((error: any) => {
|
||||
console.error('QR Scanner Error:', error);
|
||||
toast.show('Error', {
|
||||
message: 'Failed to scan QR code',
|
||||
type: 'error',
|
||||
});
|
||||
});
|
||||
} else {
|
||||
console.error('QR Scanner module not found for iOS');
|
||||
toast.show('Error', {
|
||||
message: 'QR Scanner not available',
|
||||
type: 'error',
|
||||
});
|
||||
}
|
||||
} else if (Platform.OS === 'android') {
|
||||
const qrScanner = NativeModules.QRCodeScanner;
|
||||
if (qrScanner && qrScanner.scanQRCode) {
|
||||
qrScanner
|
||||
.scanQRCode()
|
||||
.then((result: string) => {
|
||||
const params = parseUrlParams(result);
|
||||
const encodedData = params.get('data');
|
||||
handleQRCodeScan(
|
||||
encodedData as string,
|
||||
toast,
|
||||
setSelectedApp,
|
||||
setSelectedTab,
|
||||
);
|
||||
})
|
||||
.catch((error: any) => {
|
||||
console.error('QR Scanner Error:', error);
|
||||
toast.show('Error', {
|
||||
message: 'Failed to scan QR code',
|
||||
type: 'error',
|
||||
});
|
||||
});
|
||||
} else {
|
||||
console.error('QR Scanner module not found for Android');
|
||||
toast.show('Error', {
|
||||
message: 'QR Scanner not available',
|
||||
type: 'error',
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
.catch(err => {
|
||||
console.error('An error occurred while getting initial URL', err);
|
||||
if (Platform.OS === 'ios') {
|
||||
console.log('Scanning QR code on iOS');
|
||||
const qrScanner = NativeModules.QRScannerBridge;
|
||||
if (qrScanner && qrScanner.scanQRCode) {
|
||||
qrScanner
|
||||
.scanQRCode()
|
||||
.then((result: string) => {
|
||||
const params = parseUrlParams(result);
|
||||
const encodedData = params.get('data');
|
||||
handleQRCodeScan(
|
||||
encodedData as string,
|
||||
toast,
|
||||
setSelectedApp,
|
||||
setSelectedTab,
|
||||
);
|
||||
})
|
||||
.catch((error: any) => {
|
||||
console.error('QR Scanner Error:', error);
|
||||
toast.show('Error', {
|
||||
message: 'Failed to scan QR code',
|
||||
type: 'error',
|
||||
});
|
||||
});
|
||||
} else {
|
||||
console.error('QR Scanner module not found for iOS');
|
||||
toast.show('Error', {
|
||||
message: 'Failed to process initial link',
|
||||
message: 'QR Scanner not available',
|
||||
type: 'error',
|
||||
});
|
||||
});
|
||||
}
|
||||
} else if (Platform.OS === 'android') {
|
||||
const qrScanner = NativeModules.QRCodeScanner;
|
||||
if (qrScanner && qrScanner.scanQRCode) {
|
||||
qrScanner
|
||||
.scanQRCode()
|
||||
.then((result: string) => {
|
||||
const params = parseUrlParams(result);
|
||||
const encodedData = params.get('data');
|
||||
handleQRCodeScan(
|
||||
encodedData as string,
|
||||
toast,
|
||||
setSelectedApp,
|
||||
setSelectedTab,
|
||||
);
|
||||
})
|
||||
.catch((error: any) => {
|
||||
console.error('QR Scanner Error:', error);
|
||||
toast.show('Error', {
|
||||
message: 'Failed to scan QR code',
|
||||
type: 'error',
|
||||
});
|
||||
});
|
||||
} else {
|
||||
console.error('QR Scanner module not found for Android');
|
||||
toast.show('Error', {
|
||||
message: 'QR Scanner not available',
|
||||
type: 'error',
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const handleQRCodeScan = (
|
||||
@@ -110,8 +94,8 @@ const handleQRCodeScan = (
|
||||
setSelectedTab: any,
|
||||
) => {
|
||||
try {
|
||||
const passportData = useUserStore.getState().passportData;
|
||||
if (passportData) {
|
||||
const { passportData, passportMetadata } = useUserStore.getState();
|
||||
if (passportData && passportMetadata) {
|
||||
const decodedResult = atob(result);
|
||||
const uint8Array = new Uint8Array(
|
||||
decodedResult.split('').map(char => char.charCodeAt(0)),
|
||||
@@ -120,7 +104,6 @@ const handleQRCodeScan = (
|
||||
const unpackedData = msgpack.decode(decompressedData);
|
||||
const openPassportApp: OpenPassportApp = unpackedData;
|
||||
setSelectedApp(openPassportApp);
|
||||
const passportMetadata = parsePassportData(passportData);
|
||||
|
||||
const circuitName =
|
||||
openPassportApp.mode === 'vc_and_disclose'
|
||||
|
||||
@@ -5,7 +5,7 @@ import pako from 'pako';
|
||||
|
||||
import { Mode, OpenPassportApp } from '../../../common/src/utils/appType';
|
||||
import { getCircuitNameOld } from '../../../common/src/utils/certificate_parsing/parseCertificateSimple';
|
||||
import { parsePassportData } from '../../../common/src/utils/parsePassportData';
|
||||
import { parsePassportData } from '../../../common/src/utils/passports/passport_parsing/parsePassportData';
|
||||
import useNavigationStore from '../stores/navigationStore';
|
||||
import useUserStore from '../stores/userStore';
|
||||
import { downloadZkey } from './zkeyDownload';
|
||||
|
||||
@@ -1,56 +0,0 @@
|
||||
import { LeanIMT, LeanIMTHashFunction } from '@openpassport/zk-kit-lean-imt';
|
||||
import axios from 'axios';
|
||||
import { poseidon2 } from 'poseidon-lite';
|
||||
|
||||
import {
|
||||
COMMITMENT_TREE_TRACKER_URL,
|
||||
PASSPORT_ATTESTATION_ID,
|
||||
} from '../../../common/src/constants/constants';
|
||||
import { findIndexInTree } from '../../../common/src/utils/generateInputs';
|
||||
import {
|
||||
generateCommitment,
|
||||
getLeaf,
|
||||
} from '../../../common/src/utils/pubkeyTree';
|
||||
import { PassportData } from '../../../common/src/utils/types';
|
||||
import { formatMrz, packBytes } from '../../../common/src/utils/utils';
|
||||
|
||||
export async function isCommitmentRegistered(
|
||||
secret: string,
|
||||
passportData: PassportData,
|
||||
) {
|
||||
let response;
|
||||
|
||||
console.log(COMMITMENT_TREE_TRACKER_URL);
|
||||
try {
|
||||
response = await axios.get(COMMITMENT_TREE_TRACKER_URL);
|
||||
} catch (error) {
|
||||
console.error('Error fetching commitment tree:', error);
|
||||
throw error; // rethrow the error after logging
|
||||
}
|
||||
console.log('response.data:', response.data);
|
||||
|
||||
const hashFunction: LeanIMTHashFunction = (a: bigint, b: bigint) =>
|
||||
poseidon2([a, b]);
|
||||
const imt = LeanIMT.import(hashFunction, response.data);
|
||||
|
||||
const pubkey_leaf = getLeaf(passportData.dsc);
|
||||
|
||||
const formattedMrz = formatMrz(passportData.mrz);
|
||||
const mrz_bytes = packBytes(formattedMrz);
|
||||
const commitment = generateCommitment(
|
||||
secret,
|
||||
PASSPORT_ATTESTATION_ID,
|
||||
pubkey_leaf,
|
||||
mrz_bytes,
|
||||
passportData.dg2Hash?.map(x => x.toString()) || [],
|
||||
);
|
||||
|
||||
console.log('commitment', commitment.toString());
|
||||
|
||||
try {
|
||||
findIndexInTree(imt as any, commitment); // this will throw if not found
|
||||
return true;
|
||||
} catch (err) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -1,148 +0,0 @@
|
||||
import axios from 'axios';
|
||||
import { ethers } from 'ethers';
|
||||
|
||||
import {
|
||||
CHAIN_NAME,
|
||||
RELAYER_URL,
|
||||
RPC_URL,
|
||||
SignatureAlgorithmIndex,
|
||||
} from '../../../common/src/constants/constants';
|
||||
import {
|
||||
formatCallData_disclose,
|
||||
formatCallData_dsc,
|
||||
formatCallData_register,
|
||||
} from '../../../common/src/utils/formatCallData';
|
||||
import { Proof } from '../../../common/src/utils/types';
|
||||
import registerArtefacts from '../../deployments/artifacts/Deploy_Registry#OpenPassportRegister.json';
|
||||
import sbtArtefacts from '../../deployments/artifacts/Deploy_Registry#SBT.json';
|
||||
import contractAddresses from '../../deployments/deployed_addresses.json';
|
||||
import groth16ExportSolidityCallData from './snarkjs';
|
||||
|
||||
export const sendRegisterTransaction = async (
|
||||
proof: Proof,
|
||||
cscaProof: Proof,
|
||||
sigAlgIndex: SignatureAlgorithmIndex,
|
||||
) => {
|
||||
const provider = new ethers.JsonRpcProvider(RPC_URL);
|
||||
|
||||
if (
|
||||
!contractAddresses['Deploy_Registry#OpenPassportRegister'] ||
|
||||
!registerArtefacts.abi
|
||||
) {
|
||||
console.log('contracts addresses or abi not found');
|
||||
return;
|
||||
}
|
||||
|
||||
// Format the proof and publicInputs as calldata for the verifier contract
|
||||
//console.log("exporting local proof:", proof, proof.proof, proof.pub_signals);
|
||||
const cd = groth16ExportSolidityCallData(proof.proof, proof.pub_signals);
|
||||
const callData = JSON.parse(`[${cd}]`);
|
||||
//console.log('callData', callData);
|
||||
const formattedCallData_register = formatCallData_register(callData);
|
||||
console.log('formattedCallData_register', formattedCallData_register);
|
||||
|
||||
//console.log("exporting csca proof", cscaProof, cscaProof.proof, cscaProof.pub_signals)
|
||||
const cd_csca = groth16ExportSolidityCallData(
|
||||
cscaProof.proof,
|
||||
cscaProof.pub_signals,
|
||||
);
|
||||
const callData_csca = JSON.parse(`[${cd_csca}]`);
|
||||
//console.log('callData_csca', callData_csca);
|
||||
const formattedCallData_csca = formatCallData_dsc(callData_csca);
|
||||
console.log('formattedCallData_csca', formattedCallData_csca);
|
||||
|
||||
try {
|
||||
const registerContract = new ethers.Contract(
|
||||
contractAddresses['Deploy_Registry#OpenPassportRegister'],
|
||||
registerArtefacts.abi,
|
||||
provider,
|
||||
);
|
||||
|
||||
const transactionRequest =
|
||||
await registerContract.validateProof.populateTransaction(
|
||||
formattedCallData_register,
|
||||
formattedCallData_csca,
|
||||
sigAlgIndex,
|
||||
sigAlgIndex,
|
||||
);
|
||||
console.log('transactionRequest', transactionRequest);
|
||||
|
||||
const response = await axios.post(RELAYER_URL, {
|
||||
chain: CHAIN_NAME,
|
||||
tx_data: transactionRequest,
|
||||
});
|
||||
console.log('response status', response.status);
|
||||
console.log('response data', response.data);
|
||||
return response;
|
||||
} catch (err: any) {
|
||||
console.log('err', err);
|
||||
if (err.isAxiosError && err.response) {
|
||||
const errorMessage = err.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]) {
|
||||
console.log('Parsed blockchain error:', match[1]);
|
||||
throw new Error(match[1]);
|
||||
} else {
|
||||
throw new Error(errorMessage);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export const mintSBT = async (proof: Proof) => {
|
||||
const provider = new ethers.JsonRpcProvider(RPC_URL);
|
||||
|
||||
if (!contractAddresses['Deploy_Registry#SBT'] || !sbtArtefacts.abi) {
|
||||
console.log('contracts addresses or abi not found');
|
||||
return;
|
||||
}
|
||||
|
||||
// Format the proof and publicInputs as calldata for the verifier contract
|
||||
const cd = groth16ExportSolidityCallData(proof.proof, proof.pub_signals);
|
||||
const parsedCallData_disclose = JSON.parse(`[${cd}]`);
|
||||
console.log('parsedCallData_disclose', parsedCallData_disclose);
|
||||
|
||||
const formattedCallData_disclose = formatCallData_disclose(
|
||||
parsedCallData_disclose,
|
||||
);
|
||||
|
||||
try {
|
||||
const proofOfPassportContract = new ethers.Contract(
|
||||
contractAddresses['Deploy_Registry#SBT'],
|
||||
sbtArtefacts.abi,
|
||||
provider,
|
||||
);
|
||||
|
||||
const transactionRequest =
|
||||
await proofOfPassportContract.mint.populateTransaction(
|
||||
formattedCallData_disclose,
|
||||
);
|
||||
console.log('transactionRequest', transactionRequest);
|
||||
|
||||
const response = await axios.post(RELAYER_URL, {
|
||||
chain: CHAIN_NAME,
|
||||
tx_data: transactionRequest,
|
||||
});
|
||||
console.log('response status', response.status);
|
||||
console.log('response data', response.data);
|
||||
return response;
|
||||
} catch (err: any) {
|
||||
console.log('err', err);
|
||||
if (err.isAxiosError && err.response) {
|
||||
const errorMessage = err.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]) {
|
||||
console.log('Parsed blockchain error:', match[1]);
|
||||
throw new Error(match[1]);
|
||||
} else {
|
||||
throw new Error(errorMessage);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -85,10 +85,14 @@ export const parseProofAndroid = (response: string) => {
|
||||
};
|
||||
|
||||
export function getFirstName(mrz: string): string {
|
||||
const names = mrz.split('<<');
|
||||
const firstName = names[1].split('<')[0].trim();
|
||||
const capitalized = firstName.charAt(0) + firstName.slice(1).toLowerCase();
|
||||
return capitalized || 'Unknown';
|
||||
try {
|
||||
const names = mrz.split('<<');
|
||||
const firstName = names[1].split('<')[0].trim();
|
||||
const capitalized = firstName.charAt(0) + firstName.slice(1).toLowerCase();
|
||||
return capitalized || 'Unknown';
|
||||
} catch (error) {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
export function checkInputs(
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import RNFS from 'react-native-fs';
|
||||
import { unzip } from 'react-native-zip-archive';
|
||||
|
||||
import * as amplitude from '@amplitude/analytics-react-native';
|
||||
import NetInfo from '@react-native-community/netinfo';
|
||||
import axios from 'axios';
|
||||
|
||||
@@ -54,33 +53,59 @@ export type IsZkeyDownloading = {
|
||||
// => this should be fine is the function is never called after the commitment is registered.
|
||||
|
||||
export async function downloadZkey(circuit: CircuitName) {
|
||||
const { isZkeyDownloading, update } = useNavigationStore.getState();
|
||||
const { isZkeyDownloading, update, trackEvent } =
|
||||
useNavigationStore.getState();
|
||||
const startTime = Date.now();
|
||||
|
||||
trackEvent('Download Started', {
|
||||
success: true,
|
||||
circuit: circuit,
|
||||
});
|
||||
|
||||
const downloadRequired = await isDownloadRequired(circuit, isZkeyDownloading);
|
||||
if (!downloadRequired) {
|
||||
console.log(`zkey and dat for ${circuit} already downloaded`);
|
||||
amplitude.track('zkey_already_downloaded', { circuit: circuit });
|
||||
trackEvent('Download Skipped', {
|
||||
success: true,
|
||||
circuit: circuit,
|
||||
reason: 'already_downloaded',
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const networkInfo = await NetInfo.fetch();
|
||||
console.log('Network type:', networkInfo.type);
|
||||
if (networkInfo.type === 'wifi') {
|
||||
fetchZkeyAndDat(circuit);
|
||||
} else {
|
||||
const zkeyResponse = await axios.head(zkeyZipUrls[circuit]);
|
||||
const datResponse = await axios.head(datZipUrls[circuit]);
|
||||
const expectedSize =
|
||||
parseInt(zkeyResponse.headers['content-length'], 10) +
|
||||
parseInt(datResponse.headers['content-length'], 10);
|
||||
try {
|
||||
const networkInfo = await NetInfo.fetch();
|
||||
if (networkInfo.type === 'wifi') {
|
||||
fetchZkeyAndDat(circuit);
|
||||
} else {
|
||||
const zkeyResponse = await axios.head(zkeyZipUrls[circuit]);
|
||||
const datResponse = await axios.head(datZipUrls[circuit]);
|
||||
const expectedSize =
|
||||
parseInt(zkeyResponse.headers['content-length'], 10) +
|
||||
parseInt(datResponse.headers['content-length'], 10);
|
||||
|
||||
update({
|
||||
showWarningModal: {
|
||||
show: true,
|
||||
update({
|
||||
showWarningModal: {
|
||||
show: true,
|
||||
circuit: circuit,
|
||||
size: expectedSize,
|
||||
},
|
||||
});
|
||||
|
||||
trackEvent('Download Paused', {
|
||||
success: true,
|
||||
circuit: circuit,
|
||||
size: expectedSize,
|
||||
},
|
||||
reason: 'no_wifi',
|
||||
expected_size: expectedSize,
|
||||
});
|
||||
}
|
||||
} catch (error: any) {
|
||||
trackEvent('Download Failed', {
|
||||
success: false,
|
||||
error: error.message,
|
||||
circuit: circuit,
|
||||
duration_ms: Date.now() - startTime,
|
||||
});
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -136,11 +161,19 @@ export async function isDownloadRequired(
|
||||
}
|
||||
|
||||
export async function fetchZkeyAndDat(circuit: CircuitName) {
|
||||
console.log(`fetching zkey and dat for ${circuit} ...`);
|
||||
amplitude.track('fetching_zkey_and_dat', { circuit: circuit });
|
||||
const startTime = Date.now();
|
||||
const {
|
||||
isZkeyDownloading,
|
||||
toast,
|
||||
update,
|
||||
setZkeyDownloadedPercentage,
|
||||
trackEvent,
|
||||
} = useNavigationStore.getState();
|
||||
|
||||
const { isZkeyDownloading, toast, update, setZkeyDownloadedPercentage } =
|
||||
useNavigationStore.getState();
|
||||
trackEvent('Files Download Started', {
|
||||
success: true,
|
||||
circuit: circuit,
|
||||
});
|
||||
|
||||
update({
|
||||
isZkeyDownloading: {
|
||||
@@ -149,7 +182,6 @@ export async function fetchZkeyAndDat(circuit: CircuitName) {
|
||||
},
|
||||
});
|
||||
|
||||
const startTime = Date.now();
|
||||
let previousPercentComplete = -1;
|
||||
|
||||
const downloadFile = async (url: string, fileName: string) => {
|
||||
@@ -158,7 +190,11 @@ export async function fetchZkeyAndDat(circuit: CircuitName) {
|
||||
toFile: `${RNFS.DocumentDirectoryPath}/${fileName}`,
|
||||
background: false,
|
||||
begin: () => {
|
||||
console.log(`Download of ${fileName} has begun`);
|
||||
trackEvent('File Download Started', {
|
||||
success: true,
|
||||
circuit: circuit,
|
||||
file_type: fileName.includes('zkey') ? 'zkey' : 'dat',
|
||||
});
|
||||
},
|
||||
progress: (res: any) => {
|
||||
if (fileName.endsWith('.zkey.zip')) {
|
||||
@@ -169,7 +205,6 @@ export async function fetchZkeyAndDat(circuit: CircuitName) {
|
||||
percentComplete % 5 === 0 &&
|
||||
percentComplete !== previousPercentComplete
|
||||
) {
|
||||
console.log(`${percentComplete}%`);
|
||||
previousPercentComplete = percentComplete;
|
||||
setZkeyDownloadedPercentage(percentComplete);
|
||||
}
|
||||
@@ -178,9 +213,11 @@ export async function fetchZkeyAndDat(circuit: CircuitName) {
|
||||
};
|
||||
|
||||
await RNFS.downloadFile(options).promise;
|
||||
console.log(`Download of ${fileName} complete`);
|
||||
RNFS.readDir(RNFS.DocumentDirectoryPath).then(result => {
|
||||
console.log('Directory contents before unzipping:', result);
|
||||
|
||||
trackEvent('File Download Completed', {
|
||||
success: true,
|
||||
circuit: circuit,
|
||||
file_type: fileName.includes('zkey') ? 'zkey' : 'dat',
|
||||
});
|
||||
};
|
||||
|
||||
@@ -198,60 +235,88 @@ export async function fetchZkeyAndDat(circuit: CircuitName) {
|
||||
},
|
||||
});
|
||||
|
||||
console.log(
|
||||
'zkey and dat download succeeded, took ' +
|
||||
(Date.now() - startTime) / 1000 +
|
||||
' seconds',
|
||||
);
|
||||
|
||||
await saveFileSize(circuit, 'zkey');
|
||||
await saveFileSize(circuit, 'dat');
|
||||
|
||||
await RNFS.unlink(`${RNFS.DocumentDirectoryPath}/${circuit}.zkey.zip`);
|
||||
await RNFS.unlink(`${RNFS.DocumentDirectoryPath}/${circuit}.dat.zip`);
|
||||
console.log('zip files deleted');
|
||||
|
||||
const result = await RNFS.readDir(RNFS.DocumentDirectoryPath);
|
||||
console.log('Directory contents at the end:', result);
|
||||
trackEvent('Files Download Completed', {
|
||||
success: true,
|
||||
circuit: circuit,
|
||||
duration_ms: Date.now() - startTime,
|
||||
});
|
||||
} catch (error: any) {
|
||||
console.error(error);
|
||||
update({
|
||||
isZkeyDownloading: {
|
||||
...isZkeyDownloading,
|
||||
[circuit]: false,
|
||||
},
|
||||
});
|
||||
|
||||
trackEvent('Files Download Failed', {
|
||||
success: false,
|
||||
error: error.message,
|
||||
circuit: circuit,
|
||||
duration_ms: Date.now() - startTime,
|
||||
});
|
||||
|
||||
toast.show('Error', {
|
||||
message: `Error: ${error.message}`,
|
||||
customData: {
|
||||
type: 'error',
|
||||
},
|
||||
customData: { type: 'error' },
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
async function unzipFile(circuit: CircuitName, fileType: 'zkey' | 'dat') {
|
||||
const unzipPath = `${RNFS.DocumentDirectoryPath}/${circuit}_temp`;
|
||||
await unzip(
|
||||
`${RNFS.DocumentDirectoryPath}/${circuit}.${fileType}.zip`,
|
||||
unzipPath,
|
||||
);
|
||||
const files = await RNFS.readDir(unzipPath);
|
||||
const targetFile = files.find(file => file.name.endsWith(`.${fileType}`));
|
||||
if (targetFile) {
|
||||
const destinationPath = `${RNFS.DocumentDirectoryPath}/${circuit}.${fileType}`;
|
||||
if (await RNFS.exists(destinationPath)) {
|
||||
await RNFS.unlink(destinationPath);
|
||||
console.log(`Old ${fileType} file deleted`);
|
||||
}
|
||||
await RNFS.moveFile(targetFile.path, destinationPath);
|
||||
console.log(`File moved to ${circuit}.${fileType}`);
|
||||
} else {
|
||||
throw new Error(
|
||||
`${fileType.toUpperCase()} file not found in the unzipped directory`,
|
||||
const { trackEvent } = useNavigationStore.getState();
|
||||
const startTime = Date.now();
|
||||
|
||||
trackEvent('File Unzip Started', {
|
||||
success: true,
|
||||
circuit: circuit,
|
||||
file_type: fileType,
|
||||
});
|
||||
|
||||
try {
|
||||
const unzipPath = `${RNFS.DocumentDirectoryPath}/${circuit}_temp`;
|
||||
await unzip(
|
||||
`${RNFS.DocumentDirectoryPath}/${circuit}.${fileType}.zip`,
|
||||
unzipPath,
|
||||
);
|
||||
const files = await RNFS.readDir(unzipPath);
|
||||
const targetFile = files.find(file => file.name.endsWith(`.${fileType}`));
|
||||
if (targetFile) {
|
||||
const destinationPath = `${RNFS.DocumentDirectoryPath}/${circuit}.${fileType}`;
|
||||
if (await RNFS.exists(destinationPath)) {
|
||||
await RNFS.unlink(destinationPath);
|
||||
console.log(`Old ${fileType} file deleted`);
|
||||
}
|
||||
await RNFS.moveFile(targetFile.path, destinationPath);
|
||||
console.log(`File moved to ${circuit}.${fileType}`);
|
||||
} else {
|
||||
throw new Error(
|
||||
`${fileType.toUpperCase()} file not found in the unzipped directory`,
|
||||
);
|
||||
}
|
||||
await RNFS.unlink(unzipPath);
|
||||
|
||||
trackEvent('File Unzip Completed', {
|
||||
success: true,
|
||||
circuit: circuit,
|
||||
file_type: fileType,
|
||||
duration_ms: Date.now() - startTime,
|
||||
});
|
||||
} catch (error: any) {
|
||||
trackEvent('File Unzip Failed', {
|
||||
success: false,
|
||||
error: error.message,
|
||||
circuit: circuit,
|
||||
file_type: fileType,
|
||||
duration_ms: Date.now() - startTime,
|
||||
});
|
||||
throw error;
|
||||
}
|
||||
await RNFS.unlink(unzipPath);
|
||||
}
|
||||
|
||||
async function saveFileSize(circuit: CircuitName, fileType: 'zkey' | 'dat') {
|
||||
|
||||
1330
app/yarn.lock
1330
app/yarn.lock
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user