diff --git a/app/App.tsx b/app/App.tsx
index 98bd2d896..d6000e2b4 100644
--- a/app/App.tsx
+++ b/app/App.tsx
@@ -6,10 +6,11 @@ import { YStack } from 'tamagui';
import ErrorBoundary from './src/components/ErrorBoundary';
import AppNavigation from './src/navigation';
+import { AuthProvider } from './src/providers/authProvider';
+import { DatabaseProvider } from './src/providers/databaseProvider';
+import { NotificationTrackingProvider } from './src/providers/notificationTrackingProvider';
+import { PassportProvider } from './src/providers/passportDataProvider';
import { initSentry, wrapWithSentry } from './src/Sentry';
-import { AuthProvider } from './src/stores/authProvider';
-import { DatabaseProvider } from './src/stores/databaseProvider';
-import { PassportProvider } from './src/stores/passportDataProvider';
initSentry();
@@ -22,7 +23,9 @@ function App(): React.JSX.Element {
-
+
+
+
diff --git a/app/android/app/build.gradle b/app/android/app/build.gradle
index 8adf156c5..c1ba63a2f 100644
--- a/app/android/app/build.gradle
+++ b/app/android/app/build.gradle
@@ -47,11 +47,11 @@ react {
// extraPackagerArgs = []
/* Hermes Commands */
- // The hermes compiler command to run. By default it is 'hermesc'
- // hermesCommand = "$rootDir/my-custom-hermesc/bin/hermesc"
- //
- // The list of flags to pass to the Hermes compiler. By default is "-O", "-output-source-map"
- // hermesFlags = ["-O", "-output-source-map"]
+ // The hermes compiler command to run. By default it is 'hermesc'
+ hermesCommand = "../node_modules/react-native/sdks/hermesc/osx-bin/hermesc"
+
+ // The list of flags to pass to the Hermes compiler. By default is "-O", "-output-source-map"
+ hermesFlags = ["-O", "-output-source-map"]
/* Autolinking */
autolinkLibrariesWithApp()
@@ -86,7 +86,7 @@ android {
applicationId "com.proofofpassportapp"
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
- versionCode 66
+ versionCode 67
versionName "2.5.2"
externalNativeBuild {
cmake {
diff --git a/app/fastlane/Fastfile b/app/fastlane/Fastfile
index 74fd97f86..7b2af4acd 100644
--- a/app/fastlane/Fastfile
+++ b/app/fastlane/Fastfile
@@ -257,7 +257,7 @@ platform :android do
Fastlane::Helpers.with_retry(max_retries: 3, delay: 10) do
gradle(
- task: "clean bundleRelease",
+ task: "clean bundleRelease --stacktrace --info",
project_dir: "android/",
properties: {
"android.injected.signing.store.file" => ENV["ANDROID_KEYSTORE_PATH"],
diff --git a/app/ios/OpenPassport/AppDelegate.mm b/app/ios/OpenPassport/AppDelegate.mm
index ef53149e0..ee123aefe 100644
--- a/app/ios/OpenPassport/AppDelegate.mm
+++ b/app/ios/OpenPassport/AppDelegate.mm
@@ -13,10 +13,21 @@
{
[FIRApp configure];
- if ([UNUserNotificationCenter class] != nil) {
- UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
- center.delegate = self;
- }
+ // TODO: Uncomment this after the APN has been configured
+ // if ([UNUserNotificationCenter class] != nil) {
+ // UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
+ // center.delegate = self;
+
+ // // Request permission for notifications
+ // [center requestAuthorizationWithOptions:(UNAuthorizationOptionSound | UNAuthorizationOptionAlert | UNAuthorizationOptionBadge)
+ // completionHandler:^(BOOL granted, NSError * _Nullable error) {
+ // if (granted) {
+ // dispatch_async(dispatch_get_main_queue(), ^{
+ // [[UIApplication sharedApplication] registerForRemoteNotifications];
+ // });
+ // }
+ // }];
+ // }
self.moduleName = @"OpenPassport";
self.initialProps = @{};
diff --git a/app/ios/Podfile.lock b/app/ios/Podfile.lock
index 0a1b46eb3..0b3ad6b7a 100644
--- a/app/ios/Podfile.lock
+++ b/app/ios/Podfile.lock
@@ -1811,9 +1811,9 @@ PODS:
- segment-analytics-react-native (2.21.0):
- React-Core
- sovran-react-native
- - Sentry (8.52.0):
- - Sentry/Core (= 8.52.0)
- - Sentry/Core (8.52.0)
+ - Sentry (8.52.1):
+ - Sentry/Core (= 8.52.1)
+ - Sentry/Core (8.52.1)
- Sentry/HybridSDK (8.48.0)
- SentryPrivate (8.21.0)
- SocketRocket (0.7.0)
diff --git a/app/ios/Self.xcodeproj/project.pbxproj b/app/ios/Self.xcodeproj/project.pbxproj
index ef9d12a0b..620e404ad 100644
--- a/app/ios/Self.xcodeproj/project.pbxproj
+++ b/app/ios/Self.xcodeproj/project.pbxproj
@@ -427,7 +427,7 @@
CODE_SIGN_ENTITLEMENTS = OpenPassport/OpenPassportDebug.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
- CURRENT_PROJECT_VERSION = 127;
+ CURRENT_PROJECT_VERSION = 128;
DEBUG_INFORMATION_FORMAT = dwarf;
DEVELOPMENT_TEAM = 5B29R5LYHQ;
ENABLE_BITCODE = NO;
@@ -565,7 +565,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = OpenPassport/OpenPassport.entitlements;
- CURRENT_PROJECT_VERSION = 127;
+ CURRENT_PROJECT_VERSION = 128;
DEBUG_INFORMATION_FORMAT = dwarf;
DEVELOPMENT_TEAM = 5B29R5LYHQ;
FRAMEWORK_SEARCH_PATHS = (
diff --git a/app/package.json b/app/package.json
index dc43dd5bc..9d9206e95 100644
--- a/app/package.json
+++ b/app/package.json
@@ -16,9 +16,14 @@
"bump-version:major": "npm version major && yarn sync-versions",
"bump-version:minor": "npm version minor && yarn sync-versions",
"bump-version:patch": "npm version patch && yarn sync-versions",
- "clean": "watchman watch-del-all && rm -rf ../node_modules ios/Pods ios/build android/app/build android/build ../.yarn/cache ios/.xcode.env.local",
+ "clean": "yarn clean:watchman && yarn clean:build && yarn clean:ios && yarn clean:android && yarn clean:xcode && yarn clean:pod-cache && yarn clean:node",
"clean:android": "rm -rf android/app/build android/build",
- "clean:ios": "rm -rf ios/Pods ios/build",
+ "clean:build": "rm -rf ios/build android/app/build android/build",
+ "clean:ios": "rm -rf ios/Pods ios/Podfile.lock",
+ "clean:node": "rm -rf ../node_modules app/node_modules",
+ "clean:pod-cache": "cd ios && pod cache clean --all && cd ..",
+ "clean:watchman": "watchman watch-del-all",
+ "clean:xcode": "rm -rf ~/Library/Developer/Xcode/DerivedData",
"clean:xcode-env-local": "rm -f ios/.xcode.env.local",
"fmt": "prettier --check .",
"fmt:fix": "prettier --write .",
diff --git a/app/src/consts/analytics.ts b/app/src/consts/analytics.ts
index bffa2af40..e8af73ab2 100644
--- a/app/src/consts/analytics.ts
+++ b/app/src/consts/analytics.ts
@@ -6,6 +6,13 @@ export const AppEvents = {
UPDATE_STARTED: 'App: Update Started',
};
+export const NotificationEvents = {
+ BACKGROUND_NOTIFICATION_OPENED:
+ 'Notification: Background Notification Opened',
+ COLD_START_NOTIFICATION_OPENED:
+ 'Notification: Cold Start Notification Opened',
+};
+
export const AuthEvents = {
AUTHENTICATION_TIMEOUT: 'Auth: Authentication Timeout',
BIOMETRIC_AUTH_FAILED: 'Auth: Biometric Auth Failed',
diff --git a/app/src/hooks/useMnemonic.ts b/app/src/hooks/useMnemonic.ts
index 967bb408c..935d66899 100644
--- a/app/src/hooks/useMnemonic.ts
+++ b/app/src/hooks/useMnemonic.ts
@@ -1,7 +1,7 @@
import { ethers } from 'ethers';
import { useCallback, useState } from 'react';
-import { useAuth } from '../stores/authProvider';
+import { useAuth } from '../providers/authProvider';
export default function useMnemonic() {
const { getOrCreateMnemonic } = useAuth();
diff --git a/app/src/stores/authProvider.tsx b/app/src/providers/authProvider.tsx
similarity index 100%
rename from app/src/stores/authProvider.tsx
rename to app/src/providers/authProvider.tsx
diff --git a/app/src/stores/databaseProvider.tsx b/app/src/providers/databaseProvider.tsx
similarity index 86%
rename from app/src/stores/databaseProvider.tsx
rename to app/src/providers/databaseProvider.tsx
index 751d481e7..30e54e2d4 100644
--- a/app/src/stores/databaseProvider.tsx
+++ b/app/src/providers/databaseProvider.tsx
@@ -1,6 +1,6 @@
import React, { createContext, useEffect } from 'react';
-import { useProofHistoryStore } from './proofHistoryStore';
+import { useProofHistoryStore } from '../stores/proofHistoryStore';
export const DatabaseContext = createContext(null);
diff --git a/app/src/providers/notificationTrackingProvider.tsx b/app/src/providers/notificationTrackingProvider.tsx
new file mode 100644
index 000000000..79e16baa0
--- /dev/null
+++ b/app/src/providers/notificationTrackingProvider.tsx
@@ -0,0 +1,41 @@
+import messaging from '@react-native-firebase/messaging';
+import React, { PropsWithChildren, useEffect } from 'react';
+
+import { NotificationEvents } from '../consts/analytics';
+import analytics from '../utils/analytics';
+
+const { trackEvent } = analytics();
+
+export const NotificationTrackingProvider: React.FC = ({
+ children,
+}) => {
+ useEffect(() => {
+ const unsubscribe = messaging().onNotificationOpenedApp(remoteMessage => {
+ trackEvent(NotificationEvents.BACKGROUND_NOTIFICATION_OPENED, {
+ messageId: remoteMessage.messageId,
+ // Only track notification type/category if available
+ type: remoteMessage.data?.type,
+ // Track if user interacted with any actions
+ actionId: remoteMessage.data?.actionId,
+ });
+ });
+
+ messaging()
+ .getInitialNotification()
+ .then(remoteMessage => {
+ if (remoteMessage) {
+ trackEvent(NotificationEvents.COLD_START_NOTIFICATION_OPENED, {
+ messageId: remoteMessage.messageId,
+ // Only track notification type/category if available
+ type: remoteMessage.data?.type,
+ // Track if user interacted with any actions
+ actionId: remoteMessage.data?.actionId,
+ });
+ }
+ });
+
+ return unsubscribe;
+ }, []);
+
+ return <>{children}>;
+};
diff --git a/app/src/stores/passportDataProvider.tsx b/app/src/providers/passportDataProvider.tsx
similarity index 98%
rename from app/src/stores/passportDataProvider.tsx
rename to app/src/providers/passportDataProvider.tsx
index ac80c7fa1..d6c088f68 100644
--- a/app/src/stores/passportDataProvider.tsx
+++ b/app/src/providers/passportDataProvider.tsx
@@ -11,7 +11,7 @@ import React, {
} from 'react';
import Keychain from 'react-native-keychain';
-import { unsafe_getPrivateKey } from '../stores/authProvider';
+import { unsafe_getPrivateKey } from '../providers/authProvider';
import { useAuth } from './authProvider';
// TODO: refactor this as it shouldnt be used directly IMHO
diff --git a/app/src/screens/dev/DevSettingsScreen.tsx b/app/src/screens/dev/DevSettingsScreen.tsx
index 8c1da7729..2f471eb8e 100644
--- a/app/src/screens/dev/DevSettingsScreen.tsx
+++ b/app/src/screens/dev/DevSettingsScreen.tsx
@@ -25,11 +25,11 @@ import { RootStackParamList } from '../../navigation';
import {
unsafe_clearSecrets,
unsafe_getPrivateKey,
-} from '../../stores/authProvider';
+} from '../../providers/authProvider';
import {
storePassportData,
usePassport,
-} from '../../stores/passportDataProvider';
+} from '../../providers/passportDataProvider';
import { borderColor, textBlack } from '../../utils/colors';
interface DevSettingsScreenProps extends PropsWithChildren {
diff --git a/app/src/screens/dev/MockDataScreen.tsx b/app/src/screens/dev/MockDataScreen.tsx
index 8376d7ee6..b1aaf05a9 100644
--- a/app/src/screens/dev/MockDataScreen.tsx
+++ b/app/src/screens/dev/MockDataScreen.tsx
@@ -29,7 +29,7 @@ import ButtonsContainer from '../../components/ButtonsContainer';
import { BodyText } from '../../components/typography/BodyText';
import { Title } from '../../components/typography/Title';
import { MockDataEvents } from '../../consts/analytics';
-import { storePassportData } from '../../stores/passportDataProvider';
+import { storePassportData } from '../../providers/passportDataProvider';
import analytics from '../../utils/analytics';
import {
borderColor,
diff --git a/app/src/screens/dev/MockDataScreenDeepLink.tsx b/app/src/screens/dev/MockDataScreenDeepLink.tsx
index 84f3b9d40..e91c911e1 100644
--- a/app/src/screens/dev/MockDataScreenDeepLink.tsx
+++ b/app/src/screens/dev/MockDataScreenDeepLink.tsx
@@ -14,7 +14,7 @@ import { BodyText } from '../../components/typography/BodyText';
import Description from '../../components/typography/Description';
import { Title } from '../../components/typography/Title';
import { MockDataEvents } from '../../consts/analytics';
-import { storePassportData } from '../../stores/passportDataProvider';
+import { storePassportData } from '../../providers/passportDataProvider';
import useUserStore from '../../stores/userStore';
import { black, borderColor, white } from '../../utils/colors';
diff --git a/app/src/screens/misc/LoadingScreen.tsx b/app/src/screens/misc/LoadingScreen.tsx
index ade17b0fe..4f85b15f1 100644
--- a/app/src/screens/misc/LoadingScreen.tsx
+++ b/app/src/screens/misc/LoadingScreen.tsx
@@ -15,7 +15,7 @@ import CloseWarningIcon from '../../images/icons/close-warning.svg';
import {
clearPassportData,
loadPassportDataAndSecret,
-} from '../../stores/passportDataProvider';
+} from '../../providers/passportDataProvider';
import analytics from '../../utils/analytics';
import { black, slate400, white, zinc500, zinc900 } from '../../utils/colors';
import { advercase, dinot } from '../../utils/fonts';
diff --git a/app/src/screens/misc/SplashScreen.tsx b/app/src/screens/misc/SplashScreen.tsx
index 1fcc6219a..9a0f182b0 100644
--- a/app/src/screens/misc/SplashScreen.tsx
+++ b/app/src/screens/misc/SplashScreen.tsx
@@ -5,8 +5,8 @@ import React, { useCallback, useEffect, useRef } from 'react';
import { StyleSheet } from 'react-native';
import splashAnimation from '../../assets/animations/splash.json';
-import { useAuth } from '../../stores/authProvider';
-import { loadPassportDataAndSecret } from '../../stores/passportDataProvider';
+import { useAuth } from '../../providers/authProvider';
+import { loadPassportDataAndSecret } from '../../providers/passportDataProvider';
import { useProtocolStore } from '../../stores/protocolStore';
import { useSettingStore } from '../../stores/settingStore';
import { black } from '../../utils/colors';
diff --git a/app/src/screens/passport/PassportNFCScanScreen.tsx b/app/src/screens/passport/PassportNFCScanScreen.tsx
index 7136a8374..6d9e7fd1f 100644
--- a/app/src/screens/passport/PassportNFCScanScreen.tsx
+++ b/app/src/screens/passport/PassportNFCScanScreen.tsx
@@ -31,7 +31,7 @@ import { PassportEvents } from '../../consts/analytics';
import useHapticNavigation from '../../hooks/useHapticNavigation';
import NFC_IMAGE from '../../images/nfc.png';
import { ExpandableBottomLayout } from '../../layouts/ExpandableBottomLayout';
-import { storePassportData } from '../../stores/passportDataProvider';
+import { storePassportData } from '../../providers/passportDataProvider';
import useUserStore from '../../stores/userStore';
import analytics from '../../utils/analytics';
import { black, slate100, white } from '../../utils/colors';
diff --git a/app/src/screens/recovery/AccountRecoveryChoiceScreen.tsx b/app/src/screens/recovery/AccountRecoveryChoiceScreen.tsx
index 09424f703..85892aef3 100644
--- a/app/src/screens/recovery/AccountRecoveryChoiceScreen.tsx
+++ b/app/src/screens/recovery/AccountRecoveryChoiceScreen.tsx
@@ -12,11 +12,11 @@ import useHapticNavigation from '../../hooks/useHapticNavigation';
import Keyboard from '../../images/icons/keyboard.svg';
import RestoreAccountSvg from '../../images/icons/restore_account.svg';
import { ExpandableBottomLayout } from '../../layouts/ExpandableBottomLayout';
-import { useAuth } from '../../stores/authProvider';
+import { useAuth } from '../../providers/authProvider';
import {
loadPassportDataAndSecret,
reStorePassportDataWithRightCSCA,
-} from '../../stores/passportDataProvider';
+} from '../../providers/passportDataProvider';
import { useSettingStore } from '../../stores/settingStore';
import analytics from '../../utils/analytics';
import { STORAGE_NAME, useBackupMnemonic } from '../../utils/cloudBackup';
diff --git a/app/src/screens/recovery/RecoverWithPhraseScreen.tsx b/app/src/screens/recovery/RecoverWithPhraseScreen.tsx
index 7d074e13c..f4d6e0ab5 100644
--- a/app/src/screens/recovery/RecoverWithPhraseScreen.tsx
+++ b/app/src/screens/recovery/RecoverWithPhraseScreen.tsx
@@ -8,11 +8,11 @@ import { Text, TextArea, View, XStack, YStack } from 'tamagui';
import { SecondaryButton } from '../../components/buttons/SecondaryButton';
import Description from '../../components/typography/Description';
import Paste from '../../images/icons/paste.svg';
-import { useAuth } from '../../stores/authProvider';
+import { useAuth } from '../../providers/authProvider';
import {
loadPassportDataAndSecret,
reStorePassportDataWithRightCSCA,
-} from '../../stores/passportDataProvider';
+} from '../../providers/passportDataProvider';
import {
black,
slate300,
diff --git a/app/src/screens/settings/CloudBackupScreen.tsx b/app/src/screens/settings/CloudBackupScreen.tsx
index 5b14a2281..e37d48160 100644
--- a/app/src/screens/settings/CloudBackupScreen.tsx
+++ b/app/src/screens/settings/CloudBackupScreen.tsx
@@ -13,7 +13,7 @@ import { useModal } from '../../hooks/useModal';
import Cloud from '../../images/icons/logo_cloud_backup.svg';
import { ExpandableBottomLayout } from '../../layouts/ExpandableBottomLayout';
import { RootStackParamList } from '../../navigation';
-import { useAuth } from '../../stores/authProvider';
+import { useAuth } from '../../providers/authProvider';
import { useSettingStore } from '../../stores/settingStore';
import analytics from '../../utils/analytics';
import { STORAGE_NAME, useBackupMnemonic } from '../../utils/cloudBackup';
diff --git a/app/src/screens/settings/PassportDataInfoScreen.tsx b/app/src/screens/settings/PassportDataInfoScreen.tsx
index 7152c9451..13699ff71 100644
--- a/app/src/screens/settings/PassportDataInfoScreen.tsx
+++ b/app/src/screens/settings/PassportDataInfoScreen.tsx
@@ -5,7 +5,7 @@ import { useSafeAreaInsets } from 'react-native-safe-area-context';
import { ScrollView, Separator, XStack, YStack } from 'tamagui';
import { Caption } from '../../components/typography/Caption';
-import { usePassport } from '../../stores/passportDataProvider';
+import { usePassport } from '../../providers/passportDataProvider';
import { black, slate200, white } from '../../utils/colors';
import { extraYPadding } from '../../utils/constants';
diff --git a/app/src/utils/proving/provingMachine.ts b/app/src/utils/proving/provingMachine.ts
index a63735e9a..d45fc7bb9 100644
--- a/app/src/utils/proving/provingMachine.ts
+++ b/app/src/utils/proving/provingMachine.ts
@@ -13,7 +13,7 @@ import {
clearPassportData,
loadPassportDataAndSecret,
reStorePassportDataWithRightCSCA,
-} from '../../stores/passportDataProvider';
+} from '../../providers/passportDataProvider';
import { useProtocolStore } from '../../stores/protocolStore';
import { useSelfAppStore } from '../../stores/selfAppStore';
import { getPublicKey, verifyAttestation } from './attest';