From 01b0d3558cf98bbe8bde16569bb8552501cf8180 Mon Sep 17 00:00:00 2001 From: Alex Bakoushin Date: Wed, 12 Feb 2025 11:09:53 +0100 Subject: [PATCH] chore: sync with valora (#73) ### Resolved conflicts > CONFLICT (rename/rename): __mocks__/react-native-fs.ts renamed to packages/@divvi/mobile/__mocks__/react-native-fs.ts in HEAD and to __mocks__/@divvi/react-native-fs.ts in upstream/main. > CONFLICT (rename/rename): __mocks__/react-native-keychain.ts renamed to packages/@divvi/mobile/__mocks__/react-native-keychain.ts in HEAD and to __mocks__/@divvi/react-native-keychain.ts in upstream/main. > CONFLICT (content): Merge conflict in package.json > CONFLICT (content): Merge conflict in packages/@divvi/mobile/src/analytics/AppAnalytics.test.ts > CONFLICT (content): Merge conflict in packages/@divvi/mobile/src/firebase/remoteConfigValuesDefaults.ts > CONFLICT (file location): src/navigator/DemoModeAuthBlock.test.tsx added in upstream/main inside a directory that was renamed in HEAD, suggesting it should perhaps be moved to packages/@divvi/mobile/src/navigator/DemoModeAuthBlock.test.tsx. > CONFLICT (file location): src/navigator/DemoModeAuthBlock.tsx added in upstream/main inside a directory that was renamed in HEAD, suggesting it should perhaps be moved to packages/@divvi/mobile/src/navigator/DemoModeAuthBlock.tsx. > CONFLICT (rename/delete): src/pincode/pin-blocklist-hibpv7-top-25k-with-keyboard-translations.json renamed to packages/@divvi/mobile/src/pincode/pin-blocklist-hibpv7-top-25k-with-keyboard-translations.json in HEAD, but deleted in upstream/main. > CONFLICT (modify/delete): packages/@divvi/mobile/src/pincode/pin-blocklist-hibpv7-top-25k-with-keyboard-translations.json deleted in upstream/main and modified in HEAD. Version HEAD of packages/@divvi/mobile/src/pincode/pin-blocklist-hibpv7-top-25k-with-keyboard-translations.json left in tree. > CONFLICT (content): Merge conflict in packages/@divvi/mobile/src/tokens/TabWallet.test.tsx > CONFLICT (content): Merge conflict in packages/@divvi/mobile/src/tokens/utils.ts > CONFLICT (content): Merge conflict in packages/@divvi/mobile/src/transactions/feed/TransactionFeed.test.tsx > CONFLICT (content): Merge conflict in packages/@divvi/mobile/src/transactions/feed/TransactionFeedV2.test.tsx > CONFLICT (modify/delete): src/firebase/remoteConfigValuesDefaults.e2e.ts deleted in HEAD and modified in upstream/main. Version upstream/main of src/firebase/remoteConfigValuesDefaults.e2e.ts left in tree. > CONFLICT (content): Merge conflict in yarn.lock --------- Co-authored-by: Kathy Luo Co-authored-by: valora-bot-crowdin <80050969+valora-bot-crowdin@users.noreply.github.com> Co-authored-by: Valora Bot <89419329+valora-bot@users.noreply.github.com> Co-authored-by: Myroslav Sviderok Co-authored-by: valora-bot Co-authored-by: Satish Ravi Co-authored-by: Anka --- .env.alfajores | 1 + .env.alfajoresdev | 1 + .env.alfajoresnightly | 1 + .env.example | 1 + .env.mainnet | 1 + .env.mainnetdev | 1 + .env.mainnetnightly | 1 + .env.test | 1 + android/app/build.gradle | 3 +- android/gradle.properties | 2 +- apps/example/package.json | 6 +- ios/MobileStack.xcodeproj/project.pbxproj | 8 +- ios/Podfile.lock | 25 +- package.json | 6 +- .../__mocks__/{ => @divvi}/react-native-fs.ts | 0 .../{ => @divvi}/react-native-keychain.ts | 8 + .../mobile/__mocks__/react-native-config.ts | 1 + .../mobile/locales/base/translation.json | 5 + .../@divvi/mobile/locales/de/translation.json | 5 + .../mobile/locales/en-US/translation.json | 5 + .../mobile/locales/es-419/translation.json | 5 + .../mobile/locales/fr-FR/translation.json | 5 + .../mobile/locales/it-IT/translation.json | 5 + .../mobile/locales/pl-PL/translation.json | 5 + .../mobile/locales/pt-BR/translation.json | 5 + .../mobile/locales/ru-RU/translation.json | 5 + .../mobile/locales/th-TH/translation.json | 5 + .../mobile/locales/tr-TR/translation.json | 5 + .../mobile/locales/uk-UA/translation.json | 5 + .../mobile/locales/vi-VN/translation.json | 5 + .../mobile/locales/zh-CN/translation.json | 5 + packages/@divvi/mobile/metro.config.js | 2 +- packages/@divvi/mobile/package.json | 9 +- .../mobile/src/account/LicenseDisclaimer.txt | 303 ++++++++---------- .../src/account/ProfileSubmenu.test.tsx | 12 +- .../src/account/SecuritySubmenu.test.tsx | 32 +- .../@divvi/mobile/src/account/saga.test.ts | 4 +- .../mobile/src/analytics/AppAnalytics.test.ts | 6 +- .../mobile/src/analytics/AppAnalytics.ts | 4 +- .../@divvi/mobile/src/analytics/saga.test.ts | 5 + packages/@divvi/mobile/src/analytics/saga.ts | 4 +- packages/@divvi/mobile/src/app/actions.ts | 2 +- packages/@divvi/mobile/src/app/reducers.ts | 33 +- packages/@divvi/mobile/src/app/saga.test.ts | 36 ++- packages/@divvi/mobile/src/app/saga.ts | 50 +-- packages/@divvi/mobile/src/app/selectors.ts | 19 -- .../mobile/src/backup/BackupPhrase.test.tsx | 2 +- .../mobile/src/celoNews/CeloNewsFeed.tsx | 8 +- packages/@divvi/mobile/src/celoNews/types.ts | 3 - .../src/components/TokenBalance.test.tsx | 14 +- .../mobile/src/components/TokenBalance.tsx | 6 +- packages/@divvi/mobile/src/config.ts | 5 +- .../mobile/src/dapps/DappsScreen.test.tsx | 21 +- packages/@divvi/mobile/src/dapps/saga.test.ts | 25 +- packages/@divvi/mobile/src/dapps/saga.ts | 11 +- packages/@divvi/mobile/src/dapps/selectors.ts | 7 +- packages/@divvi/mobile/src/dapps/slice.ts | 28 +- .../DappFeaturedActions.test.tsx | 2 - .../src/dappsExplorer/TabDiscover.test.tsx | 11 +- .../mobile/src/earn/EarnEnterAmount.test.tsx | 9 +- .../mobile/src/earn/EarnEnterAmount.tsx | 1 + .../EarnPoolInfoScreen.test.tsx | 8 +- .../WithdrawBottomSheet.test.tsx | 1 - .../FiatExchangeCurrencyBottomSheet.test.tsx | 14 +- .../FiatExchangeCurrencyBottomSheet.tsx | 5 +- .../@divvi/mobile/src/firebase/firebase.ts | 21 -- .../firebase/remoteConfigValuesDefaults.ts | 30 +- .../@divvi/mobile/src/home/TabHome.test.tsx | 4 - packages/@divvi/mobile/src/i18n/i18n.test.ts | 2 +- packages/@divvi/mobile/src/i18n/index.ts | 2 +- .../mobile/src/i18n/otaTranslations.test.ts | 2 +- .../@divvi/mobile/src/i18n/otaTranslations.ts | 2 +- packages/@divvi/mobile/src/i18n/saga.test.ts | 2 - packages/@divvi/mobile/src/i18n/saga.ts | 11 +- packages/@divvi/mobile/src/i18n/selectors.ts | 2 - packages/@divvi/mobile/src/i18n/slice.ts | 19 +- .../KeylessBackupProgress.test.tsx | 2 +- .../src/navigator/DemoModeAuthBlock.test.tsx | 60 ++++ .../src/navigator/DemoModeAuthBlock.tsx | 61 ++++ .../mobile/src/navigator/NavigationService.ts | 9 +- .../@divvi/mobile/src/navigator/Navigator.tsx | 2 + .../mobile/src/navigator/NavigatorWrapper.tsx | 9 +- .../@divvi/mobile/src/navigator/Screens.tsx | 1 + .../src/navigator/SettingsMenu.test.tsx | 16 +- .../mobile/src/navigator/SettingsMenu.tsx | 13 +- .../@divvi/mobile/src/navigator/types.tsx | 1 + packages/@divvi/mobile/src/nfts/saga.test.tsx | 9 +- packages/@divvi/mobile/src/nfts/saga.ts | 5 +- .../registration/EnableBiometry.test.tsx | 4 +- .../registration/EnableBiometry.tsx | 2 +- .../mobile/src/onboarding/steps.test.ts | 2 +- .../@divvi/mobile/src/onboarding/steps.ts | 2 +- .../mobile/src/pincode/PincodeLock.test.tsx | 2 +- .../@divvi/mobile/src/pincode/PincodeSet.tsx | 22 +- .../mobile/src/pincode/authentication.test.ts | 89 ++--- .../mobile/src/pincode/authentication.ts | 59 +--- ...v7-top-25k-with-keyboard-translations.json | 1 - .../points/PointsHistoryBottomSheet.test.tsx | 6 - .../mobile/src/points/cardDefinitions.tsx | 6 +- .../@divvi/mobile/src/positions/saga.test.ts | 22 +- packages/@divvi/mobile/src/positions/saga.ts | 7 +- .../@divvi/mobile/src/public/createApp.ts | 1 + packages/@divvi/mobile/src/qrcode/QRCode.tsx | 4 +- packages/@divvi/mobile/src/qrcode/utils.ts | 2 +- .../@divvi/mobile/src/redux/migrations.ts | 30 +- .../@divvi/mobile/src/redux/store.test.ts | 20 +- packages/@divvi/mobile/src/redux/store.ts | 2 +- .../mobile/src/send/EnterAmountOptions.tsx | 5 +- .../mobile/src/send/SendConfirmation.test.tsx | 2 +- .../mobile/src/send/SendConfirmation.tsx | 2 +- .../mobile/src/send/SendEnterAmount.test.tsx | 5 - .../mobile/src/send/SendEnterAmount.tsx | 4 +- packages/@divvi/mobile/src/send/utils.test.ts | 5 - packages/@divvi/mobile/src/send/utils.ts | 5 +- packages/@divvi/mobile/src/sentry/Sentry.ts | 13 +- .../@divvi/mobile/src/statsig/constants.ts | 30 +- .../@divvi/mobile/src/statsig/index.test.ts | 100 +----- packages/@divvi/mobile/src/statsig/index.ts | 16 +- packages/@divvi/mobile/src/statsig/types.ts | 6 +- .../@divvi/mobile/src/storage/keychain.tsx | 10 +- .../@divvi/mobile/src/styles/variables.tsx | 1 + .../mobile/src/swap/SwapScreen.test.tsx | 16 +- .../@divvi/mobile/src/swap/SwapScreen.tsx | 15 +- .../mobile/src/swap/SwapScreenV2.test.tsx | 16 +- .../@divvi/mobile/src/swap/SwapScreenV2.tsx | 14 +- packages/@divvi/mobile/src/swap/saga.test.ts | 4 - packages/@divvi/mobile/src/swap/saga.ts | 17 +- packages/@divvi/mobile/src/swap/selectors.ts | 3 - packages/@divvi/mobile/src/swap/slice.ts | 25 +- .../@divvi/mobile/src/swap/useFilterChips.ts | 4 +- .../mobile/src/tokens/AssetList.test.tsx | 11 +- .../@divvi/mobile/src/tokens/AssetList.tsx | 5 +- .../mobile/src/tokens/TabWallet.test.tsx | 5 +- .../@divvi/mobile/src/tokens/TabWallet.tsx | 4 +- .../mobile/src/tokens/TokenDetails.test.tsx | 12 +- .../@divvi/mobile/src/tokens/TokenDetails.tsx | 9 +- .../mobile/src/tokens/TokenImport.test.tsx | 14 +- .../@divvi/mobile/src/tokens/TokenImport.tsx | 5 +- .../@divvi/mobile/src/tokens/hooks.test.tsx | 38 +-- packages/@divvi/mobile/src/tokens/hooks.ts | 21 +- .../@divvi/mobile/src/tokens/saga.test.ts | 77 ++--- packages/@divvi/mobile/src/tokens/saga.ts | 8 +- packages/@divvi/mobile/src/tokens/utils.ts | 21 +- .../@divvi/mobile/src/transactions/api.ts | 4 +- .../feed/TransactionFeed.test.tsx | 17 +- .../feed/TransactionFeedV2.test.tsx | 14 +- .../transactions/feed/TransactionFeedV2.tsx | 9 +- .../detailContent/TransferReceivedContent.tsx | 8 +- .../src/transactions/feed/queryHelper.ts | 7 +- .../mobile/src/transactions/saga.test.ts | 15 +- .../@divvi/mobile/src/transactions/saga.ts | 11 +- .../mobile/src/transactions/selectors.ts | 32 +- .../mobile/src/transactions/slice.test.ts | 5 - .../@divvi/mobile/src/utils/Logger.test.ts | 2 +- packages/@divvi/mobile/src/utils/Logger.ts | 2 +- .../mobile/src/utils/accountChecker.test.ts | 4 +- .../VerificationCodeInputScreen.test.tsx | 4 +- .../verify/VerificationStartScreen.test.tsx | 14 +- .../@divvi/mobile/src/verify/hooks.test.tsx | 4 +- packages/@divvi/mobile/src/viem/saga.ts | 10 + .../mobile/src/walletConnect/saga.test.ts | 35 +- .../@divvi/mobile/src/walletConnect/saga.ts | 28 +- .../screens/ActionRequest.test.tsx | 3 - packages/@divvi/mobile/src/web3/utils.ts | 5 + .../@divvi/mobile/test/RootStateSchema.json | 159 +++------ packages/@divvi/mobile/test/mockedKeychain.ts | 2 +- packages/@divvi/mobile/test/schemas.ts | 41 ++- .../@react-native-cookies+cookies+6.2.1.patch | 71 ---- patches/react-native-fs+2.20.0.patch | 52 --- patches/react-native-keychain+8.2.0.patch | 13 - yarn.lock | 134 ++++---- 171 files changed, 1028 insertions(+), 1632 deletions(-) rename packages/@divvi/mobile/__mocks__/{ => @divvi}/react-native-fs.ts (100%) rename packages/@divvi/mobile/__mocks__/{ => @divvi}/react-native-keychain.ts (86%) create mode 100644 packages/@divvi/mobile/src/navigator/DemoModeAuthBlock.test.tsx create mode 100644 packages/@divvi/mobile/src/navigator/DemoModeAuthBlock.tsx delete mode 100644 packages/@divvi/mobile/src/pincode/pin-blocklist-hibpv7-top-25k-with-keyboard-translations.json delete mode 100644 patches/@react-native-cookies+cookies+6.2.1.patch delete mode 100644 patches/react-native-fs+2.20.0.patch delete mode 100644 patches/react-native-keychain+8.2.0.patch diff --git a/.env.alfajores b/.env.alfajores index fd97bef2981..3f1e81abc00 100644 --- a/.env.alfajores +++ b/.env.alfajores @@ -15,3 +15,4 @@ ONBOARDING_FEATURES_ENABLED=CloudBackup,CloudBackupSetupInOnboarding,EnableBiome DEEP_LINK_URL_SCHEME=celo # APP_REGISTRY_NAME should not contain spaces, it is used for the app buildable name and user agent header APP_REGISTRY_NAME=Valora +ENABLED_NETWORK_IDS=celo-alfajores,ethereum-sepolia,arbitrum-sepolia,op-sepolia,base-sepolia diff --git a/.env.alfajoresdev b/.env.alfajoresdev index 1a0e0563e73..a4e145c3ab7 100644 --- a/.env.alfajoresdev +++ b/.env.alfajoresdev @@ -17,3 +17,4 @@ ONBOARDING_FEATURES_ENABLED=CloudBackup,CloudBackupSetupInOnboarding,EnableBiome DEEP_LINK_URL_SCHEME=celo # APP_REGISTRY_NAME should not contain spaces, it is used for the app buildable name and user agent header APP_REGISTRY_NAME=Valora +ENABLED_NETWORK_IDS=celo-alfajores,ethereum-sepolia,arbitrum-sepolia,op-sepolia,base-sepolia diff --git a/.env.alfajoresnightly b/.env.alfajoresnightly index cc778b9a3ee..bf9be2fbf60 100644 --- a/.env.alfajoresnightly +++ b/.env.alfajoresnightly @@ -15,3 +15,4 @@ ONBOARDING_FEATURES_ENABLED=CloudBackup,CloudBackupSetupInOnboarding,EnableBiome DEEP_LINK_URL_SCHEME=celo # APP_REGISTRY_NAME should not contain spaces, it is used for the app buildable name and user agent header APP_REGISTRY_NAME=Valora +ENABLED_NETWORK_IDS=celo-alfajores,ethereum-sepolia,arbitrum-sepolia,op-sepolia,base-sepolia diff --git a/.env.example b/.env.example index 98cb1d1aa88..81480c9621d 100644 --- a/.env.example +++ b/.env.example @@ -27,3 +27,4 @@ ONBOARDING_FEATURES_ENABLED=CloudBackup,CloudBackupSetupInOnboarding,EnableBiome DEEP_LINK_URL_SCHEME=celo # APP_REGISTRY_NAME should not contain spaces, it is used for the app buildable name and user agent header APP_REGISTRY_NAME=Valora +ENABLED_NETWORK_IDS=celo-mainnet,ethereum-mainnet,arbitrum-one,op-mainnet,base-mainnet diff --git a/.env.mainnet b/.env.mainnet index fa9ef08a76c..68b0b8d8ec0 100644 --- a/.env.mainnet +++ b/.env.mainnet @@ -15,3 +15,4 @@ ONBOARDING_FEATURES_ENABLED=CloudBackup,CloudBackupSetupInOnboarding,EnableBiome DEEP_LINK_URL_SCHEME=celo # APP_REGISTRY_NAME should not contain spaces, it is used for the app buildable name and user agent header APP_REGISTRY_NAME=Valora +ENABLED_NETWORK_IDS=celo-mainnet,ethereum-mainnet,arbitrum-one,op-mainnet,base-mainnet diff --git a/.env.mainnetdev b/.env.mainnetdev index 89e033182d8..a313c7241ce 100644 --- a/.env.mainnetdev +++ b/.env.mainnetdev @@ -17,3 +17,4 @@ ONBOARDING_FEATURES_ENABLED=CloudBackup,CloudBackupSetupInOnboarding,EnableBiome DEEP_LINK_URL_SCHEME=celo # APP_REGISTRY_NAME should not contain spaces, it is used for the app buildable name and user agent header APP_REGISTRY_NAME=Valora +ENABLED_NETWORK_IDS=celo-mainnet,ethereum-mainnet,arbitrum-one,op-mainnet,base-mainnet diff --git a/.env.mainnetnightly b/.env.mainnetnightly index 7f6eaeb9d49..a11b5db4f65 100644 --- a/.env.mainnetnightly +++ b/.env.mainnetnightly @@ -15,3 +15,4 @@ ONBOARDING_FEATURES_ENABLED=CloudBackupSetupInOnboarding,CloudBackup,EnableBiome DEEP_LINK_URL_SCHEME=celo # APP_REGISTRY_NAME should not contain spaces, it is used for the app buildable name and user agent header APP_REGISTRY_NAME=Valora +ENABLED_NETWORK_IDS=celo-mainnet,ethereum-mainnet,arbitrum-one,op-mainnet,base-mainnet diff --git a/.env.test b/.env.test index 958ac81ad8d..2a34674250a 100644 --- a/.env.test +++ b/.env.test @@ -13,3 +13,4 @@ ONBOARDING_FEATURES_ENABLED=EnableBiometry,ProtectWallet,PhoneVerification DEEP_LINK_URL_SCHEME=celo # APP_REGISTRY_NAME should not contain spaces, it is used for the app buildable name and user agent header APP_REGISTRY_NAME=Valora +ENABLED_NETWORK_IDS=celo-mainnet,ethereum-mainnet,arbitrum-one,op-mainnet,base-mainnet diff --git a/android/app/build.gradle b/android/app/build.gradle index bff7bb0c86c..4010f7b77cd 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -1,5 +1,6 @@ apply plugin: "com.android.application" apply plugin: "com.facebook.react" +apply plugin: 'kotlin-android' import com.android.build.OutputFile import groovy.json.JsonSlurper @@ -150,7 +151,7 @@ android { minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion versionCode appVersionCode - versionName "1.103.0" + versionName "1.104.0" multiDexEnabled true testBuildType System.getProperty('testBuildType', 'debug') testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" diff --git a/android/gradle.properties b/android/gradle.properties index ff6709671d9..deb44d488d7 100644 --- a/android/gradle.properties +++ b/android/gradle.properties @@ -25,7 +25,7 @@ RELEASE_KEY_ALIAS=mobilestack-key-alias # Setting this manually based on version number until we have this deploying via Cloud Build # Example: v1.5.1 deployment number 1 = 1005001001 (1 005 001 001) -VERSION_CODE=1021071687 +VERSION_CODE=1021071688 # AndroidX package structure to make it clearer which packages are bundled with the # Android operating system, and which are packaged with your app's APK # https://developer.android.com/topic/libraries/support-library/androidx-rn diff --git a/apps/example/package.json b/apps/example/package.json index b70416e4467..03d7a74f32f 100644 --- a/apps/example/package.json +++ b/apps/example/package.json @@ -19,12 +19,14 @@ "e2e:test:ios-release": "detox test -c ios.release -l verbose" }, "dependencies": { + "@divvi/cookies": "^6.2.3", "@divvi/mobile": "*", + "@divvi/react-native-fs": "^2.20.1", + "@divvi/react-native-keychain": "^9.2.2", "@interaxyz/react-native-webview": "^13.13.4", "@react-native-async-storage/async-storage": "^2.1.0", "@react-native-clipboard/clipboard": "^1.15.0", "@react-native-community/netinfo": "^11.4.1", - "@react-native-cookies/cookies": "^6.2.1", "@react-native-firebase/analytics": "19.1.0", "@react-native-firebase/app": "19.1.0", "@react-native-firebase/auth": "19.1.0", @@ -65,11 +67,9 @@ "react-native-device-info": "^13.2.0", "react-native-exit-app": "^2.0.0", "react-native-fast-image": "^8.6.3", - "react-native-fs": "^2.20.0", "react-native-gesture-handler": "^2.21.2", "react-native-haptic-feedback": "^2.3.3", "react-native-in-app-review": "^4.3.3", - "react-native-keychain": "^8.2.0", "react-native-launch-arguments": "^4.0.2", "react-native-linear-gradient": "^2.8.3", "react-native-localize": "^3.3.0", diff --git a/ios/MobileStack.xcodeproj/project.pbxproj b/ios/MobileStack.xcodeproj/project.pbxproj index 211f01867e9..d63836e4ef4 100644 --- a/ios/MobileStack.xcodeproj/project.pbxproj +++ b/ios/MobileStack.xcodeproj/project.pbxproj @@ -765,7 +765,7 @@ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 168; + CURRENT_PROJECT_VERSION = 169; ENABLE_BITCODE = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = "arm64 "; @@ -792,7 +792,7 @@ "${PODS_CONFIGURATION_BUILD_DIR}/React-graphics/React_graphics.framework/Headers/react/renderer/graphics/platform/ios", ); IPHONEOS_DEPLOYMENT_TARGET = 15.0; - MARKETING_VERSION = 1.103.0; + MARKETING_VERSION = 1.104.0; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; OTHER_CFLAGS = "$(inherited)"; @@ -826,7 +826,7 @@ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = YES; - CURRENT_PROJECT_VERSION = 168; + CURRENT_PROJECT_VERSION = 169; ENABLE_BITCODE = NO; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; @@ -851,7 +851,7 @@ "${PODS_CONFIGURATION_BUILD_DIR}/React-graphics/React_graphics.framework/Headers/react/renderer/graphics/platform/ios", ); IPHONEOS_DEPLOYMENT_TARGET = 15.0; - MARKETING_VERSION = 1.103.0; + MARKETING_VERSION = 1.104.0; MTL_ENABLE_DEBUG_INFO = NO; OTHER_CFLAGS = "$(inherited)"; OTHER_CPLUSPLUSFLAGS = "$(inherited)"; diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 3aaacfa16e2..00533c984c3 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -581,7 +581,7 @@ PODS: - React-Core - react-native-contacts (5.0.0): - React-Core - - react-native-cookies (6.2.1): + - react-native-cookies (6.2.3): - React-Core - react-native-flipper (0.212.0): - React-Core @@ -778,12 +778,13 @@ PODS: - Firebase/RemoteConfig (= 10.23.0) - React-Core - RNFBApp - - RNFS (2.20.0): + - RNFS (2.20.1): - React-Core - RNGestureHandler (2.21.2): - RCT-Folly (= 2021.07.22.00) - React-Core - - RNKeychain (8.2.0): + - RNKeychain (9.2.2): + - RCT-Folly (= 2021.07.22.00) - React-Core - RNLocalize (3.3.0): - React-Core @@ -900,7 +901,7 @@ DEPENDENCIES: - "react-native-compat (from `../node_modules/@walletconnect/react-native-compat`)" - react-native-config (from `../node_modules/react-native-config`) - react-native-contacts (from `../node_modules/react-native-contacts`) - - "react-native-cookies (from `../node_modules/@react-native-cookies/cookies`)" + - "react-native-cookies (from `../node_modules/@divvi/cookies`)" - react-native-flipper (from `../node_modules/react-native-flipper`) - react-native-in-app-review (from `../node_modules/react-native-in-app-review`) - react-native-launch-arguments (from `../node_modules/react-native-launch-arguments`) @@ -945,9 +946,9 @@ DEPENDENCIES: - "RNFBDynamicLinks (from `../node_modules/@react-native-firebase/dynamic-links`)" - "RNFBMessaging (from `../node_modules/@react-native-firebase/messaging`)" - "RNFBRemoteConfig (from `../node_modules/@react-native-firebase/remote-config`)" - - RNFS (from `../node_modules/react-native-fs`) + - "RNFS (from `../node_modules/@divvi/react-native-fs`)" - RNGestureHandler (from `../node_modules/react-native-gesture-handler`) - - RNKeychain (from `../node_modules/react-native-keychain`) + - "RNKeychain (from `../node_modules/@divvi/react-native-keychain`)" - RNLocalize (from `../node_modules/react-native-localize`) - RNPermissions (from `../node_modules/react-native-permissions`) - RNPersonaInquiry2 (from `../node_modules/react-native-persona`) @@ -1076,7 +1077,7 @@ EXTERNAL SOURCES: react-native-contacts: :path: "../node_modules/react-native-contacts" react-native-cookies: - :path: "../node_modules/@react-native-cookies/cookies" + :path: "../node_modules/@divvi/cookies" react-native-flipper: :path: "../node_modules/react-native-flipper" react-native-in-app-review: @@ -1166,11 +1167,11 @@ EXTERNAL SOURCES: RNFBRemoteConfig: :path: "../node_modules/@react-native-firebase/remote-config" RNFS: - :path: "../node_modules/react-native-fs" + :path: "../node_modules/@divvi/react-native-fs" RNGestureHandler: :path: "../node_modules/react-native-gesture-handler" RNKeychain: - :path: "../node_modules/react-native-keychain" + :path: "../node_modules/@divvi/react-native-keychain" RNLocalize: :path: "../node_modules/react-native-localize" RNPermissions: @@ -1269,7 +1270,7 @@ SPEC CHECKSUMS: react-native-compat: 03e54a7e1a09f56471b0af199867b4edf13de7ca react-native-config: ea75335a7cca1d3326de1da384227e580a7c082e react-native-contacts: 5eeeb8bff95a0e1680a11329e15653eb73d29a1d - react-native-cookies: f7772e020f2d61cbbb591cf769ac352b8c1517e6 + react-native-cookies: 0613d8218d02d4a8138d100ee077096a267c82f6 react-native-flipper: 03f211cc2af0ecf4b9569f0dddcc3e5d2b2d8201 react-native-in-app-review: b3d1eed3d1596ebf6539804778272c4c65e4a400 react-native-launch-arguments: d4759f7591e2766e6c5ec746b7032429edaf7058 @@ -1315,9 +1316,9 @@ SPEC CHECKSUMS: RNFBDynamicLinks: f761317263bd33aa3bced596bdc0f345d53b4c1b RNFBMessaging: d90c3a9e3da96dc2cf150a01d3aa0a68a3c32501 RNFBRemoteConfig: 1c92f072b1772b91663247b07a711cd4e9e191e8 - RNFS: 89de7d7f4c0f6bafa05343c578f61118c8282ed8 + RNFS: e21dbd93b9beabe4649fb73ff29114c18e78d36d RNGestureHandler: b81313e62e717cc165ea3b99436aa305d04c57b4 - RNKeychain: bbe2f6d5cc008920324acb49ef86ccc03d3b38e4 + RNKeychain: 91dc223bc77e3bb8576a3c75cdd28863bc2cb26e RNLocalize: d024afa9204c13885e61dc88b8190651bcaabac9 RNPermissions: 1d002266e43df33d7080d5355a64b7d12bdb5e75 RNPersonaInquiry2: 4202f797d7a172af2908f271954123858abe47bf diff --git a/package.json b/package.json index b184a7aa726..239002dd3c2 100644 --- a/package.json +++ b/package.json @@ -48,11 +48,13 @@ }, "//resolutions": "Ensure we use a single version of expo, react, react-native and native dependencies otherwise it can cause issues", "resolutions": { + "@divvi/cookies": "^6.2.3", + "@divvi/react-native-fs": "^2.20.1", + "@divvi/react-native-keychain": "^9.2.2", "@interaxyz/react-native-webview": "^13.13.4", "@react-native-async-storage/async-storage": "^2.1.0", "@react-native-clipboard/clipboard": "^1.15.0", "@react-native-community/netinfo": "^11.4.1", - "@react-native-cookies/cookies": "^6.2.1", "@react-native-firebase/analytics": "19.1.0", "@react-native-firebase/app": "19.1.0", "@react-native-firebase/auth": "19.1.0", @@ -89,11 +91,9 @@ "react-native-device-info": "^13.2.0", "react-native-exit-app": "^2.0.0", "react-native-fast-image": "^8.6.3", - "react-native-fs": "^2.20.0", "react-native-gesture-handler": "^2.21.2", "react-native-haptic-feedback": "^2.3.3", "react-native-in-app-review": "^4.3.3", - "react-native-keychain": "^8.2.0", "react-native-launch-arguments": "^4.0.2", "react-native-linear-gradient": "^2.8.3", "react-native-localize": "^3.3.0", diff --git a/packages/@divvi/mobile/__mocks__/react-native-fs.ts b/packages/@divvi/mobile/__mocks__/@divvi/react-native-fs.ts similarity index 100% rename from packages/@divvi/mobile/__mocks__/react-native-fs.ts rename to packages/@divvi/mobile/__mocks__/@divvi/react-native-fs.ts diff --git a/packages/@divvi/mobile/__mocks__/react-native-keychain.ts b/packages/@divvi/mobile/__mocks__/@divvi/react-native-keychain.ts similarity index 86% rename from packages/@divvi/mobile/__mocks__/react-native-keychain.ts rename to packages/@divvi/mobile/__mocks__/@divvi/react-native-keychain.ts index 4ca1163f48d..9af314df36f 100644 --- a/packages/@divvi/mobile/__mocks__/react-native-keychain.ts +++ b/packages/@divvi/mobile/__mocks__/@divvi/react-native-keychain.ts @@ -28,6 +28,14 @@ const keychainMock = { SECURE_HARDWARE: 'SECURE_HARDWARE', ANY: 'ANY', }, + STORAGE_TYPE: { + FB: 'MOCK_FacebookConceal', + AES: 'MOCK_KeystoreAESCBC', + AES_CBC: 'MOCK_KeystoreAESCBC', + AES_GCM_NO_AUTH: 'MOCK_KeystoreAESGCM_NoAuth', + AES_GCM: 'MOCK_KeystoreAESGCM', + RSA: 'MOCK_KeystoreRSAECB', + }, setGenericPassword: jest.fn(async (username, password, options) => { mockedItems.set(options.service, { username, password, options }) return true diff --git a/packages/@divvi/mobile/__mocks__/react-native-config.ts b/packages/@divvi/mobile/__mocks__/react-native-config.ts index 9dfaff26ac7..8d3f0970510 100644 --- a/packages/@divvi/mobile/__mocks__/react-native-config.ts +++ b/packages/@divvi/mobile/__mocks__/react-native-config.ts @@ -6,4 +6,5 @@ export default { AUTH0_DOMAIN: 'auth0.com', DEEP_LINK_URL_SCHEME: 'celo', APP_REGISTRY_NAME: 'app', + ENABLED_NETWORK_IDS: 'celo-alfajores,ethereum-sepolia,arbitrum-sepolia,op-sepolia,base-sepolia', } diff --git a/packages/@divvi/mobile/locales/base/translation.json b/packages/@divvi/mobile/locales/base/translation.json index cfc3b376d9c..c26f2ff85b0 100644 --- a/packages/@divvi/mobile/locales/base/translation.json +++ b/packages/@divvi/mobile/locales/base/translation.json @@ -2873,6 +2873,11 @@ "info": "You are currently viewing the app in demo mode", "cta": "Exit Demo" }, + "restrictedAccess": { + "title": "In Demo Mode", + "info": "You can't complete this action because you are viewing the app in demo mode", + "cta": "Exit Demo" + }, "inAppIndicatorLabel": "Demo Mode" } } diff --git a/packages/@divvi/mobile/locales/de/translation.json b/packages/@divvi/mobile/locales/de/translation.json index a78da62fead..606b16ef554 100644 --- a/packages/@divvi/mobile/locales/de/translation.json +++ b/packages/@divvi/mobile/locales/de/translation.json @@ -2867,6 +2867,11 @@ "info": "Du siehst die App derzeit im Demo-Modus", "cta": "Demo beenden" }, + "restrictedAccess": { + "title": "Im Demo-Modus", + "info": "Du kannst diese Aktion nicht abschließen, weil du die App im Demo-Modus betrachtest", + "cta": "Demo beenden" + }, "inAppIndicatorLabel": "Demo-Modus" }, "celoDollarAmount": "<0> Celo Dollar", diff --git a/packages/@divvi/mobile/locales/en-US/translation.json b/packages/@divvi/mobile/locales/en-US/translation.json index 458a01a7e66..6cebe8b105e 100644 --- a/packages/@divvi/mobile/locales/en-US/translation.json +++ b/packages/@divvi/mobile/locales/en-US/translation.json @@ -2867,6 +2867,11 @@ "info": "You are currently viewing the app in demo mode", "cta": "Exit Demo" }, + "restrictedAccess": { + "title": "In Demo Mode", + "info": "You can't complete this action because you are viewing the app in demo mode", + "cta": "Exit Demo" + }, "inAppIndicatorLabel": "Demo Mode" }, "celoDollarAmount": "<0> Celo Dollar", diff --git a/packages/@divvi/mobile/locales/es-419/translation.json b/packages/@divvi/mobile/locales/es-419/translation.json index 57a49c8fdcb..4af5f63acac 100644 --- a/packages/@divvi/mobile/locales/es-419/translation.json +++ b/packages/@divvi/mobile/locales/es-419/translation.json @@ -2867,6 +2867,11 @@ "info": "Estás viendo la aplicación en modo demo", "cta": "Salir de la Demo" }, + "restrictedAccess": { + "title": "En modo Demo", + "info": "No puedes completar esta acción porque estás viendo la app en modo demo", + "cta": "Salir de la Demo" + }, "inAppIndicatorLabel": "Modo Demo" }, "celoDollarAmount": "<0> Celo Dollar", diff --git a/packages/@divvi/mobile/locales/fr-FR/translation.json b/packages/@divvi/mobile/locales/fr-FR/translation.json index 3f3a7286f09..bf66a73a634 100644 --- a/packages/@divvi/mobile/locales/fr-FR/translation.json +++ b/packages/@divvi/mobile/locales/fr-FR/translation.json @@ -2867,6 +2867,11 @@ "info": "Tu visualises actuellement l'appli en mode démo.", "cta": "Quitter la démo" }, + "restrictedAccess": { + "title": "En mode démo", + "info": "Tu ne peux pas effectuer cette action car tu visualises l'appli en mode démo", + "cta": "Quitter la démo" + }, "inAppIndicatorLabel": "Mode démo" }, "celoDollarAmount": "<0> Celo Dollar", diff --git a/packages/@divvi/mobile/locales/it-IT/translation.json b/packages/@divvi/mobile/locales/it-IT/translation.json index 8d6a937d5a2..0b2fd040d96 100644 --- a/packages/@divvi/mobile/locales/it-IT/translation.json +++ b/packages/@divvi/mobile/locales/it-IT/translation.json @@ -2867,6 +2867,11 @@ "info": "Stai visualizzando l'applicazione in modalità demo", "cta": "Esci dalla demo" }, + "restrictedAccess": { + "title": "In modalità demo", + "info": "Non puoi completare questa azione perché stai visualizzando l'applicazione in modalità demo.", + "cta": "Esci dalla demo" + }, "inAppIndicatorLabel": "Modalità demo" }, "celoDollarAmount": "<0> Celo Dollar", diff --git a/packages/@divvi/mobile/locales/pl-PL/translation.json b/packages/@divvi/mobile/locales/pl-PL/translation.json index 2f4923f9a88..add9a482832 100644 --- a/packages/@divvi/mobile/locales/pl-PL/translation.json +++ b/packages/@divvi/mobile/locales/pl-PL/translation.json @@ -2871,6 +2871,11 @@ "info": "Aktualnie przeglądasz aplikację w trybie demonstracyjnym", "cta": "Exit Demo" }, + "restrictedAccess": { + "title": "W trybie demonstracyjnym", + "info": "Nie możesz wykonać tej czynności, ponieważ przeglądasz aplikację w trybie demonstracyjnym", + "cta": "Exit Demo" + }, "inAppIndicatorLabel": "Tryb demonstracyjny" }, "celoDollarAmount_0": "<0> Celo Dolar", diff --git a/packages/@divvi/mobile/locales/pt-BR/translation.json b/packages/@divvi/mobile/locales/pt-BR/translation.json index bc7d127bbd9..975cc2ef712 100644 --- a/packages/@divvi/mobile/locales/pt-BR/translation.json +++ b/packages/@divvi/mobile/locales/pt-BR/translation.json @@ -2867,6 +2867,11 @@ "info": "No momento, você está visualizando o aplicativo no modo de demonstração", "cta": "Sair da demonstração" }, + "restrictedAccess": { + "title": "No modo de demonstração", + "info": "Não é possível concluir essa ação porque você está visualizando o aplicativo no modo de demonstração", + "cta": "Sair da demonstração" + }, "inAppIndicatorLabel": "Modo de demonstração" }, "celoDollarAmount": "<0> Celo Dollar", diff --git a/packages/@divvi/mobile/locales/ru-RU/translation.json b/packages/@divvi/mobile/locales/ru-RU/translation.json index f3fceec0468..bace881e22a 100644 --- a/packages/@divvi/mobile/locales/ru-RU/translation.json +++ b/packages/@divvi/mobile/locales/ru-RU/translation.json @@ -2871,6 +2871,11 @@ "info": "В данный момент ты просматриваешь приложение в демонстрационном режиме", "cta": "Выход из демоверсии" }, + "restrictedAccess": { + "title": "В демонстрационном режиме", + "info": "Ты не можешь выполнить это действие, потому что просматриваешь приложение в демонстрационном режиме", + "cta": "Выход из демоверсии" + }, "inAppIndicatorLabel": "Демо-режим" }, "celoDollarAmount_0": "<0> Celo Dollar", diff --git a/packages/@divvi/mobile/locales/th-TH/translation.json b/packages/@divvi/mobile/locales/th-TH/translation.json index 1cc27241b66..b6701555625 100644 --- a/packages/@divvi/mobile/locales/th-TH/translation.json +++ b/packages/@divvi/mobile/locales/th-TH/translation.json @@ -2865,6 +2865,11 @@ "info": "You are currently viewing the app in demo mode", "cta": "Exit Demo" }, + "restrictedAccess": { + "title": "In Demo Mode", + "info": "You can't complete this action because you are viewing the app in demo mode", + "cta": "Exit Demo" + }, "inAppIndicatorLabel": "Demo Mode" }, "celoDollarAmount_0": "&lt;0&gt;&lt;/0&gt; Celo ดอลลาร์" diff --git a/packages/@divvi/mobile/locales/tr-TR/translation.json b/packages/@divvi/mobile/locales/tr-TR/translation.json index 289b0e621b1..42ea84074ff 100644 --- a/packages/@divvi/mobile/locales/tr-TR/translation.json +++ b/packages/@divvi/mobile/locales/tr-TR/translation.json @@ -2867,6 +2867,11 @@ "info": "Şu anda uygulamayı demo modunda görüntülüyorsunuz", "cta": "Çıkış Demosu" }, + "restrictedAccess": { + "title": "Demo Modunda", + "info": "Uygulamayı demo modunda görüntülediğiniz için bu işlemi tamamlayamazsınız", + "cta": "Çıkış Demosu" + }, "inAppIndicatorLabel": "Demo Modu" }, "celoDollarAmount": "<0> Celo Dollar", diff --git a/packages/@divvi/mobile/locales/uk-UA/translation.json b/packages/@divvi/mobile/locales/uk-UA/translation.json index ad618152aa4..40e9aec1084 100644 --- a/packages/@divvi/mobile/locales/uk-UA/translation.json +++ b/packages/@divvi/mobile/locales/uk-UA/translation.json @@ -2871,6 +2871,11 @@ "info": "Ви зараз переглядаєте додаток у демо-режимі", "cta": "Вихідна демонстрація" }, + "restrictedAccess": { + "title": "У демонстраційному режимі", + "info": "Ви не можете виконати цю дію, оскільки переглядаєте додаток у демо-режимі", + "cta": "Вихідна демонстрація" + }, "inAppIndicatorLabel": "Демонстраційний режим" }, "celoDollarAmount_0": "<0> Celo Dollar", diff --git a/packages/@divvi/mobile/locales/vi-VN/translation.json b/packages/@divvi/mobile/locales/vi-VN/translation.json index 81514d1fc5d..00293ca7ac5 100644 --- a/packages/@divvi/mobile/locales/vi-VN/translation.json +++ b/packages/@divvi/mobile/locales/vi-VN/translation.json @@ -2865,6 +2865,11 @@ "info": "You are currently viewing the app in demo mode", "cta": "Exit Demo" }, + "restrictedAccess": { + "title": "In Demo Mode", + "info": "You can't complete this action because you are viewing the app in demo mode", + "cta": "Exit Demo" + }, "inAppIndicatorLabel": "Demo Mode" }, "celoDollarAmount_0": "&lt;0&gt;&lt;/0&gt; Đô la Celo" diff --git a/packages/@divvi/mobile/locales/zh-CN/translation.json b/packages/@divvi/mobile/locales/zh-CN/translation.json index bb2d57a225e..be4da916475 100644 --- a/packages/@divvi/mobile/locales/zh-CN/translation.json +++ b/packages/@divvi/mobile/locales/zh-CN/translation.json @@ -2865,6 +2865,11 @@ "info": "您正在以演示模式查看应用程序", "cta": "退出演示" }, + "restrictedAccess": { + "title": "演示模式", + "info": "由于您是在演示模式下查看应用程序,因此无法完成此操作", + "cta": "退出演示" + }, "inAppIndicatorLabel": "演示模式" }, "celoDollarAmount_0": "&lt;0&gt;&lt;/0&gt; Celo 美元" diff --git a/packages/@divvi/mobile/metro.config.js b/packages/@divvi/mobile/metro.config.js index baa573f77dc..12a4e225e06 100644 --- a/packages/@divvi/mobile/metro.config.js +++ b/packages/@divvi/mobile/metro.config.js @@ -35,7 +35,7 @@ const config = { // This is the crypto module we want to use moving forward (unless something better comes up). // It is implemented natively using OpenSSL. crypto: require.resolve('react-native-quick-crypto'), - fs: require.resolve('react-native-fs'), + fs: require.resolve('@divvi/react-native-fs'), }, sourceExts: isE2E ? ['e2e.ts', 'e2e.js'].concat(defaultSourceExts) : defaultSourceExts, }, diff --git a/packages/@divvi/mobile/package.json b/packages/@divvi/mobile/package.json index b2de28ed4da..8fe41d8c93d 100644 --- a/packages/@divvi/mobile/package.json +++ b/packages/@divvi/mobile/package.json @@ -91,11 +91,13 @@ ] }, "peerDependencies": { + "@divvi/cookies": "^6.2.3", + "@divvi/react-native-fs": "^2.20.1", + "@divvi/react-native-keychain": "^9.2.2", "@interaxyz/react-native-webview": "^13.13.4", "@react-native-async-storage/async-storage": "^2.1.0", "@react-native-clipboard/clipboard": "^1.15.0", "@react-native-community/netinfo": "^11.4.1", - "@react-native-cookies/cookies": "^6.2.1", "@react-native-firebase/analytics": "19.1.0", "@react-native-firebase/app": "19.1.0", "@react-native-firebase/auth": "19.1.0", @@ -130,11 +132,9 @@ "react-native-device-info": "^13.2.0", "react-native-exit-app": "^2.0.0", "react-native-fast-image": "^8.6.3", - "react-native-fs": "^2.20.0", "react-native-gesture-handler": "^2.21.2", "react-native-haptic-feedback": "^2.3.3", "react-native-in-app-review": "^4.3.3", - "react-native-keychain": "^8.2.0", "react-native-launch-arguments": "^4.0.2", "react-native-linear-gradient": "^2.8.3", "react-native-localize": "^3.3.0", @@ -156,7 +156,7 @@ "dependencies": { "@badrap/result": "~0.2.13", "@crowdin/ota-client": "^0.7.0", - "@fiatconnect/fiatconnect-sdk": "^0.5.66", + "@fiatconnect/fiatconnect-sdk": "^0.5.71", "@fiatconnect/fiatconnect-types": "^13.3.10", "@gorhom/bottom-sheet": "^5.0.6", "@interaxyz/react-navigation-bottom-sheet": "^0.3.2", @@ -227,7 +227,6 @@ "@types/node": "^20", "@types/react": "^18.0.24", "@types/react-native-auth0": "^2.17.5", - "@types/react-native-fs": "^2.13.0", "@types/react-native-video": "^5.0.15", "@types/react-test-renderer": "^18.0.0", "@types/redux-mock-store": "^1.0.6", diff --git a/packages/@divvi/mobile/src/account/LicenseDisclaimer.txt b/packages/@divvi/mobile/src/account/LicenseDisclaimer.txt index 3d136c55caf..fda5f4ba39e 100644 --- a/packages/@divvi/mobile/src/account/LicenseDisclaimer.txt +++ b/packages/@divvi/mobile/src/account/LicenseDisclaimer.txt @@ -390,6 +390,58 @@ SOFTWARE. ----- +The following software may be included in this product: @divvi/cookies. A copy of the source code may be downloaded from git+https://github.com/divvixyz/cookies.git. This software contains the following license and notice below: + +MIT License + +Copyright (c) 2020 React Native Community + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +----- + +The following software may be included in this product: @divvi/react-native-fs, react-native-fs. A copy of the source code may be downloaded from git+https@https://github.com/divvixyz/react-native-fs.git (@divvi/react-native-fs), git@github.com:itinance/react-native-fs.git (react-native-fs). This software contains the following license and notice below: + +The MIT License (MIT) + +Copyright (c) 2015 Johannes Lumpe + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +----- + The following software may be included in this product: @egjs/hammerjs. A copy of the source code may be downloaded from git://github.com/naver/hammer.js.git. This software contains the following license and notice below: The MIT License (MIT) @@ -553,6 +605,84 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ----- +The following software may be included in this product: @interaxyz/react-native-keychain, react-native-animatable. A copy of the source code may be downloaded from git://github.com/mobilestack-xyz/react-native-keychain.git (@interaxyz/react-native-keychain), git://github.com/oblador/react-native-animatable.git (react-native-animatable). This software contains the following license and notice below: + +The MIT License (MIT) + +Copyright (c) 2015 Joel Arvidsson + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +----- + +The following software may be included in this product: @interaxyz/react-native-webview, @react-native-community/netinfo, @react-native-masked-view/masked-view, @react-native-picker/picker. A copy of the source code may be downloaded from git+https://github.com/interaxyz/react-native-webview.git (@interaxyz/react-native-webview), https://github.com/react-native-netinfo/react-native-netinfo.git (@react-native-community/netinfo), git+https://github.com/react-native-masked-view/masked-view.git (@react-native-masked-view/masked-view), https://github.com/react-native-picker/picker.git (@react-native-picker/picker). This software contains the following license and notice below: + +MIT License + +Copyright (c) 2015-present, Facebook, Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +----- + +The following software may be included in this product: @interaxyz/react-navigation-bottom-sheet. A copy of the source code may be downloaded from https://github.com/interaxyz/react-navigation-bottom-sheet. This software contains the following license and notice below: + +MIT License + +Copyright (c) 2021 Janic Duplessis + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +----- + The following software may be included in this product: @jest/create-cache-key-function, @jest/environment, @jest/fake-timers, @jest/schemas, @jest/types, hermes-estree, hermes-parser, jest-environment-node, jest-get-type, jest-message-util, jest-mock, jest-util, jest-validate, pretty-format, react-native, scheduler, use-sync-external-store. A copy of the source code may be downloaded from https://github.com/jestjs/jest.git (@jest/create-cache-key-function), https://github.com/jestjs/jest.git (@jest/environment), https://github.com/jestjs/jest.git (@jest/fake-timers), https://github.com/jestjs/jest.git (@jest/schemas), https://github.com/jestjs/jest.git (@jest/types), git@github.com:facebook/hermes.git (hermes-estree), git@github.com:facebook/hermes.git (hermes-parser), https://github.com/jestjs/jest.git (jest-environment-node), https://github.com/jestjs/jest.git (jest-get-type), https://github.com/jestjs/jest.git (jest-message-util), https://github.com/jestjs/jest.git (jest-mock), https://github.com/jestjs/jest.git (jest-util), https://github.com/jestjs/jest.git (jest-validate), https://github.com/jestjs/jest.git (pretty-format), https://github.com/facebook/react-native.git (react-native), https://github.com/facebook/react.git (scheduler), https://github.com/facebook/react.git (use-sync-external-store). This software contains the following license and notice below: MIT License @@ -885,58 +1015,6 @@ SOFTWARE. ----- -The following software may be included in this product: @react-native-community/netinfo, @react-native-masked-view/masked-view, @react-native-picker/picker, react-native-webview. A copy of the source code may be downloaded from https://github.com/react-native-netinfo/react-native-netinfo.git (@react-native-community/netinfo), git+https://github.com/react-native-masked-view/masked-view.git (@react-native-masked-view/masked-view), https://github.com/react-native-picker/picker.git (@react-native-picker/picker), https://github.com/react-native-webview/react-native-webview.git (react-native-webview). This software contains the following license and notice below: - -MIT License - -Copyright (c) 2015-present, Facebook, Inc. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - ------ - -The following software may be included in this product: @react-native-cookies/cookies. A copy of the source code may be downloaded from git+https://github.com/react-native-cookies/cookies.git. This software contains the following license and notice below: - -MIT License - -Copyright (c) 2020 React Native Community - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - ------ - The following software may be included in this product: @react-native-firebase/analytics, @react-native-firebase/auth, @react-native-firebase/database, @react-native-firebase/dynamic-links, @react-native-firebase/messaging, @react-native-firebase/remote-config. A copy of the source code may be downloaded from https://github.com/invertase/react-native-firebase/tree/main/packages/analytics (@react-native-firebase/analytics), https://github.com/invertase/react-native-firebase/tree/main/packages/auth (@react-native-firebase/auth), https://github.com/invertase/react-native-firebase/tree/main/packages/database (@react-native-firebase/database), https://github.com/invertase/react-native-firebase/tree/main/packages/dynamic-links (@react-native-firebase/dynamic-links), https://github.com/invertase/react-native-firebase/tree/main/packages/messaging (@react-native-firebase/messaging), https://github.com/invertase/react-native-firebase/tree/main/packages/remote-config (@react-native-firebase/remote-config). This software contains the following license and notice below: Apache-2.0 License @@ -3154,32 +3232,6 @@ Copyright (c) 2016-2021 The Stdlib Authors. ----- -The following software may be included in this product: @th3rdwave/react-navigation-bottom-sheet. A copy of the source code may be downloaded from https://github.com/th3rdwave/react-navigation-bottom-sheet. This software contains the following license and notice below: - -MIT License - -Copyright (c) 2021 Janic Duplessis - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - ------ - The following software may be included in this product: @toruslabs/bs58, @toruslabs/http-helpers. A copy of the source code may be downloaded from git+https://github.com/torusresearch/bs58.git (@toruslabs/bs58), git+https://github.com/torusresearch/http-helpers.git (@toruslabs/http-helpers). This software contains the following license and notice below: MIT License @@ -3781,7 +3833,7 @@ The following software may be included in this product: apg-js. A copy of the so ## [2-Clause BSD License](https://opensource.org/licenses/BSD-2-Clause)

-Copyright (c) 2023 Lowell D. Thomas
+Copyright (c) 2024 Lowell D. Thomas
All rights reserved. Redistribution and use in source and binary forms, with or without @@ -11818,32 +11870,6 @@ SOFTWARE. ----- -The following software may be included in this product: react-native-animatable, react-native-keychain. A copy of the source code may be downloaded from git://github.com/oblador/react-native-animatable.git (react-native-animatable), git://github.com/oblador/react-native-keychain.git (react-native-keychain). This software contains the following license and notice below: - -The MIT License (MIT) - -Copyright (c) 2015 Joel Arvidsson - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - ------ - The following software may be included in this product: react-native-auth0. A copy of the source code may be downloaded from git+https://github.com/auth0/react-native-auth0.git. This software contains the following license and notice below: The MIT License (MIT) @@ -12026,32 +12052,6 @@ SOFTWARE. ----- -The following software may be included in this product: react-native-fs. A copy of the source code may be downloaded from git@github.com:itinance/react-native-fs.git. This software contains the following license and notice below: - -The MIT License (MIT) - -Copyright (c) 2015 Johannes Lumpe - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - ------ - The following software may be included in this product: react-native-gesture-handler, react-native-reanimated. A copy of the source code may be downloaded from git+https://github.com/software-mansion/react-native-gesture-handler.git (react-native-gesture-handler), git+https://github.com/software-mansion/react-native-reanimated.git (react-native-reanimated). This software contains the following license and notice below: The MIT License (MIT) @@ -14927,22 +14927,6 @@ SOFTWARE. ----- -The following software may be included in this product: uri-js. A copy of the source code may be downloaded from http://github.com/garycourt/uri-js. This software contains the following license and notice below: - -Copyright 2011 Gary Court. All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - -1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - -2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY GARY COURT "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GARY COURT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -The views and conclusions contained in the software and documentation are those of the authors and should not be interpreted as representing official policies, either expressed or implied, of Gary Court. - ------ - The following software may be included in this product: url. A copy of the source code may be downloaded from https://github.com/defunctzombie/node-url.git. This software contains the following license and notice below: The MIT License (MIT) @@ -15060,31 +15044,6 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI ----- -The following software may be included in this product: valid-url. A copy of the source code may be downloaded from git://github.com/ogt/valid-url.git. This software contains the following license and notice below: - -Copyright (c) 2013 Odysseas Tsatalos and oDesk Corporation - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - ------ - The following software may be included in this product: vary. A copy of the source code may be downloaded from https://github.com/jshttp/vary.git. This software contains the following license and notice below: (The MIT License) diff --git a/packages/@divvi/mobile/src/account/ProfileSubmenu.test.tsx b/packages/@divvi/mobile/src/account/ProfileSubmenu.test.tsx index 76a9466bd37..b336121d2ca 100644 --- a/packages/@divvi/mobile/src/account/ProfileSubmenu.test.tsx +++ b/packages/@divvi/mobile/src/account/ProfileSubmenu.test.tsx @@ -1,18 +1,18 @@ +import * as Keychain from '@divvi/react-native-keychain' +import { act, fireEvent, render, waitFor } from '@testing-library/react-native' +import { FetchMock } from 'jest-fetch-mock/types' import * as React from 'react' import 'react-native' import { Provider } from 'react-redux' import ProfileSubmenu from 'src/account/ProfileSubmenu' import { Screens } from 'src/navigator/Screens' +import Logger from 'src/utils/Logger' +import networkConfig from 'src/web3/networkConfig' import MockedNavigator from 'test/MockedNavigator' -import { FetchMock } from 'jest-fetch-mock/types' import { createMockStore, getMockStackScreenProps } from 'test/utils' import { mockE164Number } from 'test/values' -import networkConfig from 'src/web3/networkConfig' -import { act, fireEvent, render, waitFor } from '@testing-library/react-native' -import * as Keychain from 'react-native-keychain' const mockFetch = fetch as FetchMock const mockedKeychain = jest.mocked(Keychain) -import Logger from 'src/utils/Logger' jest.mock('src/utils/Logger') @@ -20,7 +20,7 @@ mockedKeychain.getGenericPassword.mockResolvedValue({ username: 'some username', password: 'someSignedMessage', service: 'some service', - storage: 'some string', + storage: Keychain.STORAGE_TYPE.RSA, }) describe('ProfileSubmenu', () => { diff --git a/packages/@divvi/mobile/src/account/SecuritySubmenu.test.tsx b/packages/@divvi/mobile/src/account/SecuritySubmenu.test.tsx index 55c8d23ff99..4a1337b0628 100644 --- a/packages/@divvi/mobile/src/account/SecuritySubmenu.test.tsx +++ b/packages/@divvi/mobile/src/account/SecuritySubmenu.test.tsx @@ -1,28 +1,28 @@ +import * as Keychain from '@divvi/react-native-keychain' +import { BIOMETRY_TYPE } from '@divvi/react-native-keychain' +import { act, fireEvent, render, waitFor } from '@testing-library/react-native' +import { FetchMock } from 'jest-fetch-mock/types' import * as React from 'react' import 'react-native' import { Provider } from 'react-redux' -import SecuritySubmenu from 'src/account/SecuritySubmenu' -import { Screens } from 'src/navigator/Screens' -import MockedNavigator from 'test/MockedNavigator' -import { createMockStore } from 'test/utils' -import { fireEvent, render, waitFor, act } from '@testing-library/react-native' -import { ensurePincode, navigate } from 'src/navigator/NavigationService' -import { FetchMock } from 'jest-fetch-mock/types' -import * as Keychain from 'react-native-keychain' -import { setAnalyticsEnabled } from 'src/app/actions' -import { showError } from 'src/alert/actions' -import { ErrorMessages } from 'src/app/ErrorMessages' import { setPincodeSuccess } from 'src/account/actions' -import { mockE164Number } from 'test/values' -import { BIOMETRY_TYPE } from 'react-native-keychain' import { PincodeType } from 'src/account/reducer' -import { removeStoredPin, setPincodeWithBiometry } from 'src/pincode/authentication' +import SecuritySubmenu from 'src/account/SecuritySubmenu' +import { showError } from 'src/alert/actions' import AppAnalytics from 'src/analytics/AppAnalytics' import { SettingsEvents } from 'src/analytics/Events' -import { getFeatureGate } from 'src/statsig/index' +import { setAnalyticsEnabled } from 'src/app/actions' +import { ErrorMessages } from 'src/app/ErrorMessages' import { deleteKeylessBackupStarted, hideDeleteKeylessBackupError } from 'src/keylessBackup/slice' import { KeylessBackupDeleteStatus } from 'src/keylessBackup/types' +import { ensurePincode, navigate } from 'src/navigator/NavigationService' +import { Screens } from 'src/navigator/Screens' +import { removeStoredPin, setPincodeWithBiometry } from 'src/pincode/authentication' +import { getFeatureGate } from 'src/statsig/index' import networkConfig from 'src/web3/networkConfig' +import MockedNavigator from 'test/MockedNavigator' +import { createMockStore } from 'test/utils' +import { mockE164Number } from 'test/values' const mockedEnsurePincode = jest.mocked(ensurePincode) const mockFetch = fetch as FetchMock @@ -31,7 +31,7 @@ mockedKeychain.getGenericPassword.mockResolvedValue({ username: 'some username', password: 'someSignedMessage', service: 'some service', - storage: 'some string', + storage: Keychain.STORAGE_TYPE.RSA, }) jest.mock('src/analytics/AppAnalytics') diff --git a/packages/@divvi/mobile/src/account/saga.test.ts b/packages/@divvi/mobile/src/account/saga.test.ts index 10fa1df42a0..97a8e5dd770 100644 --- a/packages/@divvi/mobile/src/account/saga.test.ts +++ b/packages/@divvi/mobile/src/account/saga.test.ts @@ -1,5 +1,5 @@ +import * as Keychain from '@divvi/react-native-keychain' import { FetchMock } from 'jest-fetch-mock/types' -import * as Keychain from 'react-native-keychain' import { expectSaga } from 'redux-saga-test-plan' import * as matchers from 'redux-saga-test-plan/matchers' import { throwError } from 'redux-saga-test-plan/providers' @@ -103,7 +103,7 @@ describe('generateSignedMessage', () => { username: 'some username', password: 'someSignedMessage', service: 'some service', - storage: 'some string', + storage: Keychain.STORAGE_TYPE.RSA, }) await expectSaga(generateSignedMessage) diff --git a/packages/@divvi/mobile/src/analytics/AppAnalytics.test.ts b/packages/@divvi/mobile/src/analytics/AppAnalytics.test.ts index b54877d49bb..fb372cddeb1 100644 --- a/packages/@divvi/mobile/src/analytics/AppAnalytics.test.ts +++ b/packages/@divvi/mobile/src/analytics/AppAnalytics.test.ts @@ -4,7 +4,7 @@ import AppAnalyticsModule from 'src/analytics/AppAnalytics' import { OnboardingEvents } from 'src/analytics/Events' import * as config from 'src/config' import { store } from 'src/redux/store' -import { getDefaultStatsigUser, getFeatureGate, getMultichainFeatures } from 'src/statsig' +import { getDefaultStatsigUser, getFeatureGate } from 'src/statsig' import { NetworkId } from 'src/transactions/types' import { Statsig } from 'statsig-react-native' import { getMockStoreData } from 'test/utils' @@ -209,11 +209,9 @@ describe('AppAnalytics', () => { mockConfig.STATSIG_API_KEY = 'statsig-key' mockConfig.STATSIG_ENABLED = true mockConfig.SEGMENT_API_KEY = 'segment-key' + mockConfig.ENABLED_NETWORK_IDS = ['celo-alfajores'] mockStore.getState.mockImplementation(() => state) jest.mocked(getFeatureGate).mockReturnValue(true) - jest.mocked(getMultichainFeatures).mockReturnValue({ - showBalances: [NetworkId['celo-alfajores']], - }) }) describe('init', () => { diff --git a/packages/@divvi/mobile/src/analytics/AppAnalytics.ts b/packages/@divvi/mobile/src/analytics/AppAnalytics.ts index 26e2ac63d41..4b5ac2b3196 100644 --- a/packages/@divvi/mobile/src/analytics/AppAnalytics.ts +++ b/packages/@divvi/mobile/src/analytics/AppAnalytics.ts @@ -23,9 +23,9 @@ import { } from 'src/config' import { store } from 'src/redux/store' import { getDefaultStatsigUser } from 'src/statsig' -import { getSupportedNetworkIdsForTokenBalances } from 'src/tokens/utils' import { ensureError } from 'src/utils/ensureError' import Logger from 'src/utils/Logger' +import { getSupportedNetworkIds } from 'src/web3/utils' import { Statsig } from 'statsig-react-native' import { sha256 } from 'viem' @@ -310,7 +310,7 @@ class AppAnalytics { // Super props, i.e. props sent with all events private getSuperProps() { - const traits = getCurrentUserTraits(store.getState(), getSupportedNetworkIdsForTokenBalances()) + const traits = getCurrentUserTraits(store.getState(), getSupportedNetworkIds()) // Prefix super props with `s` so they don't clash with events props const prefixedSuperProps = Object.fromEntries( Object.entries({ diff --git a/packages/@divvi/mobile/src/analytics/saga.test.ts b/packages/@divvi/mobile/src/analytics/saga.test.ts index 64f07b7744a..910f66e2de2 100644 --- a/packages/@divvi/mobile/src/analytics/saga.test.ts +++ b/packages/@divvi/mobile/src/analytics/saga.test.ts @@ -6,6 +6,11 @@ import { updateUserTraits } from 'src/analytics/saga' import { getCurrentUserTraits } from 'src/analytics/selectors' import networkConfig from 'src/web3/networkConfig' +jest.mock('src/config', () => ({ + ...jest.requireActual('src/config'), + ENABLED_NETWORK_IDS: ['celo-alfajores'], +})) + describe(updateUserTraits, () => { beforeAll(() => { jest.useRealTimers() diff --git a/packages/@divvi/mobile/src/analytics/saga.ts b/packages/@divvi/mobile/src/analytics/saga.ts index f84a3329c61..8de4c3fd05e 100644 --- a/packages/@divvi/mobile/src/analytics/saga.ts +++ b/packages/@divvi/mobile/src/analytics/saga.ts @@ -1,12 +1,12 @@ import AppAnalytics from 'src/analytics/AppAnalytics' import { getCurrentUserTraits } from 'src/analytics/selectors' -import { getSupportedNetworkIdsForTokenBalances } from 'src/tokens/utils' +import { getSupportedNetworkIds } from 'src/web3/utils' import { call, select, spawn, take } from 'typed-redux-saga' export function* updateUserTraits() { let prevTraits while (true) { - const traits = yield* select(getCurrentUserTraits, getSupportedNetworkIdsForTokenBalances()) + const traits = yield* select(getCurrentUserTraits, getSupportedNetworkIds()) if (traits !== prevTraits) { const { walletAddress } = traits yield* call([AppAnalytics, 'identify'], walletAddress as string | null, traits) diff --git a/packages/@divvi/mobile/src/app/actions.ts b/packages/@divvi/mobile/src/app/actions.ts index a3fb4fb41c2..7aa9cf347c6 100644 --- a/packages/@divvi/mobile/src/app/actions.ts +++ b/packages/@divvi/mobile/src/app/actions.ts @@ -1,4 +1,4 @@ -import { BIOMETRY_TYPE } from 'react-native-keychain' +import { BIOMETRY_TYPE } from '@divvi/react-native-keychain' import { RemoteConfigValues } from 'src/app/saga' import { Screens } from 'src/navigator/Screens' diff --git a/packages/@divvi/mobile/src/app/reducers.ts b/packages/@divvi/mobile/src/app/reducers.ts index 1bb134bad2a..19f45bb37d4 100644 --- a/packages/@divvi/mobile/src/app/reducers.ts +++ b/packages/@divvi/mobile/src/app/reducers.ts @@ -1,7 +1,6 @@ +import { BIOMETRY_TYPE } from '@divvi/react-native-keychain' import { Platform } from 'react-native' -import { BIOMETRY_TYPE } from 'react-native-keychain' import { Actions, ActionTypes, AppState } from 'src/app/actions' -import { CeloNewsConfig } from 'src/celoNews/types' import { DEEP_LINK_URL_SCHEME } from 'src/config' import { REMOTE_CONFIG_VALUES_DEFAULTS } from 'src/firebase/remoteConfigValuesDefaults' import { Screens } from 'src/navigator/Screens' @@ -21,25 +20,15 @@ interface State { locked: boolean lastTimeBackgrounded: number sessionId: string - celoEducationUri: string | null activeScreen: Screens - walletConnectV2Enabled: boolean // In 1.13 we had a critical error which requires a migration to fix. See |verificationMigration.ts| // for the migration code. We can remove all the code associated with this after some time has passed. - logPhoneNumberTypeEnabled: boolean googleMobileServicesAvailable?: boolean huaweiMobileServicesAvailable?: boolean - pincodeUseExpandedBlocklist: boolean - sentryTracesSampleRate: number - sentryNetworkErrors: string[] supportedBiometryType: BIOMETRY_TYPE | null fiatConnectCashInEnabled: boolean fiatConnectCashOutEnabled: boolean - coinbasePayEnabled: boolean - maxSwapSlippagePercentage: number inviterAddress: string | null - networkTimeoutSeconds: number - celoNews: CeloNewsConfig hapticFeedbackEnabled: boolean pushNotificationRequestedUnixTime: number | null pushNotificationsEnabled: boolean @@ -63,23 +52,13 @@ const initialState = { locked: false, lastTimeBackgrounded: 0, sessionId: '', - celoEducationUri: null, activeScreen: Screens.Main, - walletConnectV2Enabled: REMOTE_CONFIG_VALUES_DEFAULTS.walletConnectV2Enabled, - logPhoneNumberTypeEnabled: REMOTE_CONFIG_VALUES_DEFAULTS.logPhoneNumberTypeEnabled, googleMobileServicesAvailable: undefined, huaweiMobileServicesAvailable: undefined, - pincodeUseExpandedBlocklist: REMOTE_CONFIG_VALUES_DEFAULTS.pincodeUseExpandedBlocklist, - sentryTracesSampleRate: REMOTE_CONFIG_VALUES_DEFAULTS.sentryTracesSampleRate, - sentryNetworkErrors: REMOTE_CONFIG_VALUES_DEFAULTS.sentryNetworkErrors.split(','), supportedBiometryType: null, fiatConnectCashInEnabled: REMOTE_CONFIG_VALUES_DEFAULTS.fiatConnectCashInEnabled, fiatConnectCashOutEnabled: REMOTE_CONFIG_VALUES_DEFAULTS.fiatConnectCashOutEnabled, - coinbasePayEnabled: REMOTE_CONFIG_VALUES_DEFAULTS.coinbasePayEnabled, - maxSwapSlippagePercentage: REMOTE_CONFIG_VALUES_DEFAULTS.maxSwapSlippagePercentage, inviterAddress: null, - networkTimeoutSeconds: REMOTE_CONFIG_VALUES_DEFAULTS.networkTimeoutSeconds, - celoNews: JSON.parse(REMOTE_CONFIG_VALUES_DEFAULTS.celoNews), hapticFeedbackEnabled: true, pushNotificationRequestedUnixTime: null, pushNotificationsEnabled: false, @@ -167,18 +146,8 @@ export const appReducer = ( case Actions.UPDATE_REMOTE_CONFIG_VALUES: return { ...state, - celoEducationUri: action.configValues.celoEducationUri, - walletConnectV2Enabled: action.configValues.walletConnectV2Enabled, - logPhoneNumberTypeEnabled: action.configValues.logPhoneNumberTypeEnabled, - pincodeUseExpandedBlocklist: action.configValues.pincodeUseExpandedBlocklist, - sentryTracesSampleRate: action.configValues.sentryTracesSampleRate, - sentryNetworkErrors: action.configValues.sentryNetworkErrors, fiatConnectCashInEnabled: action.configValues.fiatConnectCashInEnabled, fiatConnectCashOutEnabled: action.configValues.fiatConnectCashOutEnabled, - coinbasePayEnabled: action.configValues.coinbasePayEnabled, - maxSwapSlippagePercentage: action.configValues.maxSwapSlippagePercentage, - networkTimeoutSeconds: action.configValues.networkTimeoutSeconds, - celoNews: action.configValues.celoNews, } case Actions.ACTIVE_SCREEN_CHANGED: return { diff --git a/packages/@divvi/mobile/src/app/saga.test.ts b/packages/@divvi/mobile/src/app/saga.test.ts index 6e7344a75a3..ef5aadf2f89 100644 --- a/packages/@divvi/mobile/src/app/saga.test.ts +++ b/packages/@divvi/mobile/src/app/saga.test.ts @@ -1,4 +1,4 @@ -import { BIOMETRY_TYPE } from 'react-native-keychain' +import { BIOMETRY_TYPE } from '@divvi/react-native-keychain' import * as RNLocalize from 'react-native-localize' import { expectSaga } from 'redux-saga-test-plan' import * as matchers from 'redux-saga-test-plan/matchers' @@ -27,17 +27,12 @@ import { getLastTimeBackgrounded, getRequirePinOnAppOpen, inAppReviewLastInteractionTimestampSelector, - sentryNetworkErrorsSelector, } from 'src/app/selectors' import { DEEP_LINK_URL_SCHEME } from 'src/config' import { activeDappSelector } from 'src/dapps/selectors' import { FiatExchangeFlow } from 'src/fiatExchanges/types' import { initI18n } from 'src/i18n' -import { - allowOtaTranslationsSelector, - currentLanguageSelector, - otaTranslationsAppVersionSelector, -} from 'src/i18n/selectors' +import { currentLanguageSelector, otaTranslationsAppVersionSelector } from 'src/i18n/selectors' import { jumpstartLinkHandler } from 'src/jumpstart/jumpstartLinkHandler' import { navigate } from 'src/navigator/NavigationService' import { Screens } from 'src/navigator/Screens' @@ -46,11 +41,12 @@ import { allowHooksPreviewSelector } from 'src/positions/selectors' import { handlePaymentDeeplink } from 'src/send/utils' import { initializeSentry } from 'src/sentry/Sentry' import { getDynamicConfigParams, getFeatureGate, patchUpdateStatsigUser } from 'src/statsig' +import { StatsigFeatureGates } from 'src/statsig/types' import { NetworkId } from 'src/transactions/types' import { navigateToURI } from 'src/utils/linking' import Logger from 'src/utils/Logger' import { ONE_DAY_IN_MILLIS } from 'src/utils/time' -import { initialiseWalletConnect } from 'src/walletConnect/saga' +import { _setClientForTesting, initialiseWalletConnect } from 'src/walletConnect/saga' import { selectHasPendingState } from 'src/walletConnect/selectors' import { WalletConnectRequestType } from 'src/walletConnect/types' import { handleWalletConnectDeepLink } from 'src/walletConnect/walletConnect' @@ -286,6 +282,7 @@ describe('handleDeepLink', () => { describe('WalletConnect deeplinks', () => { beforeEach(() => { jest.clearAllMocks() + _setClientForTesting({} as any) }) const connectionString = encodeURIComponent( @@ -546,10 +543,8 @@ describe('appInit', () => { }) const defaultProviders: (EffectProviders | StaticProvider)[] = [ - [select(allowOtaTranslationsSelector), true], [select(otaTranslationsAppVersionSelector), '1'], [select(currentLanguageSelector), 'nl-NL'], - [select(sentryNetworkErrorsSelector), ['network error']], ] it('should initialise the correct components, with the stored language', async () => { @@ -619,7 +614,12 @@ describe(requestInAppReview, () => { `( `Should show when isAvailable: true, Last Interaction: $lastInteraction and Wallet Address: 0xTest`, async ({ lastInteractionTimestamp }) => { - jest.mocked(getFeatureGate).mockReturnValue(true) + jest.mocked(getFeatureGate).mockImplementation((featureGate) => { + if (featureGate === StatsigFeatureGates.APP_REVIEW) { + return true + } + return false + }) mockIsInAppReviewAvailable.mockReturnValue(true) mockRequestInAppReview.mockResolvedValue(true) @@ -648,7 +648,12 @@ describe(requestInAppReview, () => { `( `Should not show when Device Available: $isAvailable, Feature Gate: $featureGate, Last Interaction: $lastInteraction and Wallet Address: $walletAddress`, async ({ lastInteractionTimestamp, isAvailable, featureGate, walletAddress }) => { - jest.mocked(getFeatureGate).mockReturnValue(featureGate) + jest.mocked(getFeatureGate).mockImplementation((gate) => { + if (gate === StatsigFeatureGates.APP_REVIEW) { + return featureGate + } + return false + }) mockIsInAppReviewAvailable.mockReturnValue(isAvailable) mockRequestInAppReview.mockResolvedValue(true) @@ -668,7 +673,12 @@ describe(requestInAppReview, () => { ) it('Should handle error from react-native-in-app-review', async () => { - jest.mocked(getFeatureGate).mockReturnValue(true) + jest.mocked(getFeatureGate).mockImplementation((featureGate) => { + if (featureGate === StatsigFeatureGates.APP_REVIEW) { + return true + } + return false + }) mockIsInAppReviewAvailable.mockReturnValue(true) mockRequestInAppReview.mockRejectedValue(new Error('🤖💥')) diff --git a/packages/@divvi/mobile/src/app/saga.ts b/packages/@divvi/mobile/src/app/saga.ts index 7dd576beb34..98976d79582 100644 --- a/packages/@divvi/mobile/src/app/saga.ts +++ b/packages/@divvi/mobile/src/app/saga.ts @@ -1,8 +1,8 @@ +import * as Keychain from '@divvi/react-native-keychain' import locales from 'locales' import { AppState, Platform } from 'react-native' import DeviceInfo from 'react-native-device-info' import InAppReview from 'react-native-in-app-review' -import * as Keychain from 'react-native-keychain' import { findBestLanguageTag } from 'react-native-localize' import { eventChannel } from 'redux-saga' import AppAnalytics from 'src/analytics/AppAnalytics' @@ -10,14 +10,14 @@ import { AppEvents, InviteEvents } from 'src/analytics/Events' import { HooksEnablePreviewOrigin } from 'src/analytics/types' import { Actions, - OpenDeepLink, - OpenUrlAction, - SetAppState, androidMobileServicesAvailabilityChecked, appLock, inAppReviewRequested, inviteLinkConsumed, + OpenDeepLink, openDeepLink, + OpenUrlAction, + SetAppState, setAppState, setSupportedBiometryType, updateRemoteConfigValues, @@ -28,19 +28,19 @@ import { googleMobileServicesAvailableSelector, huaweiMobileServicesAvailableSelector, inAppReviewLastInteractionTimestampSelector, - sentryNetworkErrorsSelector, } from 'src/app/selectors' -import { CeloNewsConfig } from 'src/celoNews/types' -import { DEFAULT_APP_LANGUAGE, FETCH_TIMEOUT_DURATION, isE2EEnv } from 'src/config' +import { + DEFAULT_APP_LANGUAGE, + DEFAULT_SENTRY_NETWORK_ERRORS, + ENABLE_OTA_TRANSLATIONS, + FETCH_TIMEOUT_DURATION, + isE2EEnv, +} from 'src/config' import { FiatExchangeFlow } from 'src/fiatExchanges/types' import { FiatAccountSchemaCountryOverrides } from 'src/fiatconnect/types' import { fetchRemoteConfigValues } from 'src/firebase/firebase' import { initI18n } from 'src/i18n' -import { - allowOtaTranslationsSelector, - currentLanguageSelector, - otaTranslationsAppVersionSelector, -} from 'src/i18n/selectors' +import { currentLanguageSelector, otaTranslationsAppVersionSelector } from 'src/i18n/selectors' import { jumpstartClaim } from 'src/jumpstart/saga' import { navigate, navigateHome } from 'src/navigator/NavigationService' import { Screens } from 'src/navigator/Screens' @@ -98,15 +98,16 @@ const REVIEW_INTERVAL = ONE_DAY_IN_MILLIS * 120 // 120 days // Work that's done before other sagas are initalized // Be mindful to not put long blocking tasks here export function* appInit() { + yield* call(initializeSentry) + SentryTransactionHub.startTransaction(SentryTransaction.app_init_saga) - const allowOtaTranslations = yield* select(allowOtaTranslationsSelector) const otaTranslationsAppVersion = yield* select(otaTranslationsAppVersionSelector) const language = yield* select(currentLanguageSelector) const bestLanguage = findBestLanguageTag(Object.keys(locales))?.languageTag + const allowOtaTranslations = ENABLE_OTA_TRANSLATIONS yield* all([ - call(initializeSentry), call([AppAnalytics, 'init']), call( initI18n, @@ -116,10 +117,7 @@ export function* appInit() { ), ]) - // This step is important if the user is offline and unable to fetch remote - // config values, we can use the persisted value instead of an empty one - const sentryNetworkErrors = yield* select(sentryNetworkErrorsSelector) - Logger.setNetworkErrors(sentryNetworkErrors) + Logger.setNetworkErrors(DEFAULT_SENTRY_NETWORK_ERRORS) const supportedBiometryType = yield* call(Keychain.getSupportedBiometryType) yield* put(setSupportedBiometryType(supportedBiometryType)) @@ -176,25 +174,10 @@ export function* checkAndroidMobileServicesSaga() { } export interface RemoteConfigValues { - celoEducationUri: string | null - dappListApiUrl: string | null inviteRewardsVersion: string - walletConnectV2Enabled: boolean - logPhoneNumberTypeEnabled: boolean - pincodeUseExpandedBlocklist: boolean - allowOtaTranslations: boolean - sentryTracesSampleRate: number - sentryNetworkErrors: string[] - maxNumRecentDapps: number - dappsWebViewEnabled: boolean fiatConnectCashInEnabled: boolean fiatConnectCashOutEnabled: boolean fiatAccountSchemaCountryOverrides: FiatAccountSchemaCountryOverrides - coinbasePayEnabled: boolean - maxSwapSlippagePercentage: number - networkTimeoutSeconds: number - celoNews: CeloNewsConfig - priceImpactWarningThreshold: number } export function* appRemoteFeatureFlagSaga() { @@ -215,7 +198,6 @@ export function* appRemoteFeatureFlagSaga() { timeout: delay(FETCH_TIMEOUT_DURATION), }) if (configValues) { - Logger.setNetworkErrors(configValues.sentryNetworkErrors) yield* put(updateRemoteConfigValues(configValues)) lastLoadTime = Date.now() } diff --git a/packages/@divvi/mobile/src/app/selectors.ts b/packages/@divvi/mobile/src/app/selectors.ts index 4d245fc13ea..27761c06a9f 100644 --- a/packages/@divvi/mobile/src/app/selectors.ts +++ b/packages/@divvi/mobile/src/app/selectors.ts @@ -24,24 +24,12 @@ export const sessionIdSelector = (state: RootState) => { return state.app.sessionId } -// this can be called with undefined state in the tests -export const walletConnectEnabledSelector = (state?: RootState) => ({ - v2: state?.app.walletConnectV2Enabled ?? false, -}) - -export const logPhoneNumberTypeEnabledSelector = (state: RootState) => - state.app.logPhoneNumberTypeEnabled - export const googleMobileServicesAvailableSelector = (state: RootState) => state.app.googleMobileServicesAvailable export const huaweiMobileServicesAvailableSelector = (state: RootState) => state.app.huaweiMobileServicesAvailable -export const sentryTracesSampleRateSelector = (state: RootState) => state.app.sentryTracesSampleRate - -export const sentryNetworkErrorsSelector = (state: RootState) => state.app.sentryNetworkErrors - export const supportedBiometryTypeSelector = (state: RootState) => state.app.supportedBiometryType export const fiatConnectCashInEnabledSelector = (state: RootState) => @@ -49,17 +37,10 @@ export const fiatConnectCashInEnabledSelector = (state: RootState) => export const fiatConnectCashOutEnabledSelector = (state: RootState) => state.app.fiatConnectCashOutEnabled -export const maxSwapSlippagePercentageSelector = (state: RootState) => - state.app.maxSwapSlippagePercentage - export const phoneNumberVerifiedSelector = (state: RootState) => state.app.phoneNumberVerified export const inviterAddressSelector = (state: RootState) => state.app.inviterAddress -export const networkTimeoutSecondsSelector = (state: RootState) => state.app.networkTimeoutSeconds - -export const celoNewsConfigSelector = (state: RootState) => state.app.celoNews - export const hapticFeedbackEnabledSelector = (state: RootState) => state.app.hapticFeedbackEnabled export const pushNotificationsEnabledSelector = (state: RootState) => diff --git a/packages/@divvi/mobile/src/backup/BackupPhrase.test.tsx b/packages/@divvi/mobile/src/backup/BackupPhrase.test.tsx index ca072c2b0ce..d0ab7086ccd 100644 --- a/packages/@divvi/mobile/src/backup/BackupPhrase.test.tsx +++ b/packages/@divvi/mobile/src/backup/BackupPhrase.test.tsx @@ -1,7 +1,7 @@ +import * as Keychain from '@divvi/react-native-keychain' import { fireEvent, render } from '@testing-library/react-native' import * as React from 'react' import 'react-native' -import * as Keychain from 'react-native-keychain' import { Provider } from 'react-redux' import BackupPhrase from 'src/backup/BackupPhrase' import { navigate } from 'src/navigator/NavigationService' diff --git a/packages/@divvi/mobile/src/celoNews/CeloNewsFeed.tsx b/packages/@divvi/mobile/src/celoNews/CeloNewsFeed.tsx index ba511e6d0b5..6d4f12cc0a0 100644 --- a/packages/@divvi/mobile/src/celoNews/CeloNewsFeed.tsx +++ b/packages/@divvi/mobile/src/celoNews/CeloNewsFeed.tsx @@ -4,14 +4,15 @@ import { useTranslation } from 'react-i18next' import { FlatList, ListRenderItemInfo, StyleSheet, Text, View } from 'react-native' import AppAnalytics from 'src/analytics/AppAnalytics' import { CeloNewsEvents } from 'src/analytics/Events' -import { celoNewsConfigSelector } from 'src/app/selectors' import CeloNewsFeedItem from 'src/celoNews/CeloNewsFeedItem' import { CeloNewsArticle, CeloNewsArticles } from 'src/celoNews/types' import Button, { BtnSizes, BtnTypes } from 'src/components/Button' import EmptyView from 'src/components/EmptyView' import { navigate } from 'src/navigator/NavigationService' import { Screens } from 'src/navigator/Screens' -import { useSelector } from 'src/redux/hooks' +import { getDynamicConfigParams } from 'src/statsig' +import { DynamicConfigs } from 'src/statsig/constants' +import { StatsigDynamicConfigs } from 'src/statsig/types' import colors from 'src/styles/colors' import { typeScale } from 'src/styles/fonts' import { Spacing } from 'src/styles/styles' @@ -61,7 +62,8 @@ export default function CeloNewsFeed() { const { t } = useTranslation() const asyncArticles = useFetchArticles() - const { readMoreUrl } = useSelector(celoNewsConfigSelector) + const { links } = getDynamicConfigParams(DynamicConfigs[StatsigDynamicConfigs.APP_CONFIG]) + const readMoreUrl = links?.celoNews const isLoading = asyncArticles.status === 'loading' useEffect(() => { diff --git a/packages/@divvi/mobile/src/celoNews/types.ts b/packages/@divvi/mobile/src/celoNews/types.ts index 78fa7ccc275..7aea02b5dbc 100644 --- a/packages/@divvi/mobile/src/celoNews/types.ts +++ b/packages/@divvi/mobile/src/celoNews/types.ts @@ -1,6 +1,3 @@ -export interface CeloNewsConfig { - readMoreUrl?: string -} export interface CeloNewsArticles { articles: CeloNewsArticle[] nextPageId: string diff --git a/packages/@divvi/mobile/src/components/TokenBalance.test.tsx b/packages/@divvi/mobile/src/components/TokenBalance.test.tsx index ad6e3b61b54..5c00d24caa4 100644 --- a/packages/@divvi/mobile/src/components/TokenBalance.test.tsx +++ b/packages/@divvi/mobile/src/components/TokenBalance.test.tsx @@ -2,15 +2,14 @@ import { fireEvent, render } from '@testing-library/react-native' import * as React from 'react' import { Provider } from 'react-redux' import { hideAlert } from 'src/alert/actions' -import { HomeEvents } from 'src/analytics/Events' import AppAnalytics from 'src/analytics/AppAnalytics' +import { HomeEvents } from 'src/analytics/Events' import { toggleHideBalances } from 'src/app/actions' import { AssetsTokenBalance, FiatExchangeTokenBalance } from 'src/components/TokenBalance' import { LocalCurrencyCode } from 'src/localCurrency/consts' import { navigateClearingStack } from 'src/navigator/NavigationService' import { Screens } from 'src/navigator/Screens' -import { getFeatureGate, getMultichainFeatures } from 'src/statsig' -import { NetworkId } from 'src/transactions/types' +import { getFeatureGate } from 'src/statsig' import { ONE_DAY_IN_MILLIS } from 'src/utils/time' import { createMockStore, getElementText } from 'test/utils' import { @@ -98,15 +97,6 @@ const staleTokens = { }, } -jest.mocked(getMultichainFeatures).mockReturnValue({ - showBalances: [ - NetworkId['ethereum-sepolia'], - NetworkId['celo-alfajores'], - NetworkId['arbitrum-sepolia'], - NetworkId['op-sepolia'], - ], -}) - // Behavior specific to AssetsTokenBalance describe('AssetsTokenBalance', () => { beforeEach(() => { diff --git a/packages/@divvi/mobile/src/components/TokenBalance.tsx b/packages/@divvi/mobile/src/components/TokenBalance.tsx index da35891be57..f573380d118 100644 --- a/packages/@divvi/mobile/src/components/TokenBalance.tsx +++ b/packages/@divvi/mobile/src/components/TokenBalance.tsx @@ -47,7 +47,7 @@ import { useTotalTokenBalance, } from 'src/tokens/hooks' import { tokenFetchErrorSelector } from 'src/tokens/selectors' -import { getSupportedNetworkIdsForTokenBalances } from 'src/tokens/utils' +import { getSupportedNetworkIds } from 'src/web3/utils' function TokenBalance({ style = styles.balance, @@ -58,7 +58,7 @@ function TokenBalance({ singleTokenViewEnabled?: boolean showBalanceToggle?: boolean }) { - const supportedNetworkIds = getSupportedNetworkIdsForTokenBalances() + const supportedNetworkIds = getSupportedNetworkIds() const tokensWithUsdValue = useTokensWithUsdValue(supportedNetworkIds) const localCurrencySymbol = useSelector(getLocalCurrencySymbol) const totalTokenBalanceLocal = useTotalTokenBalance() @@ -136,7 +136,7 @@ function HideBalanceButton({ hideBalance }: { hideBalance: boolean }) { function useErrorMessageWithRefresh() { const { t } = useTranslation() - const supportedNetworkIds = getSupportedNetworkIdsForTokenBalances() + const supportedNetworkIds = getSupportedNetworkIds() const tokensInfoUnavailable = useTokensInfoUnavailable(supportedNetworkIds) const tokenFetchError = useSelector(tokenFetchErrorSelector) const localCurrencyError = useSelector(localCurrencyExchangeRateErrorSelector) diff --git a/packages/@divvi/mobile/src/config.ts b/packages/@divvi/mobile/src/config.ts index 102ea40125b..fda10f8e10e 100644 --- a/packages/@divvi/mobile/src/config.ts +++ b/packages/@divvi/mobile/src/config.ts @@ -1,6 +1,6 @@ +import { CachesDirectoryPath } from '@divvi/react-native-fs' import { Network } from '@fiatconnect/fiatconnect-types' import Config from 'react-native-config' -import { CachesDirectoryPath } from 'react-native-fs' import { SpendMerchant } from 'src/fiatExchanges/Spend' import { LoggerLevel } from 'src/utils/LoggerLevels' // eslint-disable-next-line import/no-relative-packages @@ -72,6 +72,8 @@ export const DEFAULT_FORNO_URL = ? 'https://forno.celo.org/' : 'https://alfajores-forno.celo-testnet.org/' +export const ENABLED_NETWORK_IDS = configOrThrow('ENABLED_NETWORK_IDS').split(',') + export const APP_BUNDLE_ID = configOrThrow('APP_BUNDLE_ID') export const DEEP_LINK_URL_SCHEME = configOrThrow('DEEP_LINK_URL_SCHEME') @@ -162,6 +164,7 @@ export const SIMPLEX_FEES_URL = export const APP_STORE_ID = Config.APP_STORE_ID export const DYNAMIC_LINK_DOMAIN_URI_PREFIX = 'https://vlra.app' +export const ENABLE_OTA_TRANSLATIONS = true export const CROWDIN_DISTRIBUTION_HASH = 'e-f9f6869461793b9d1a353b2v7c' export const OTA_TRANSLATIONS_FILEPATH = `file://${CachesDirectoryPath}/translations` diff --git a/packages/@divvi/mobile/src/dapps/DappsScreen.test.tsx b/packages/@divvi/mobile/src/dapps/DappsScreen.test.tsx index 8f6708b5f29..9b27c987857 100644 --- a/packages/@divvi/mobile/src/dapps/DappsScreen.test.tsx +++ b/packages/@divvi/mobile/src/dapps/DappsScreen.test.tsx @@ -39,7 +39,7 @@ const dappsCategories: DappCategory[] = [ ] const defaultStore = createMockStore({ - dapps: { dappListApiUrl: 'http://url.com', dappsList, dappsCategories }, + dapps: { dappsList, dappsCategories }, }) describe('DappsScreen', () => { @@ -106,7 +106,6 @@ describe('DappsScreen', () => { it('opens dapps directly', () => { const store = createMockStore({ dapps: { - dappListApiUrl: 'http://url.com', dappsList, dappsCategories, }, @@ -130,7 +129,6 @@ describe('DappsScreen', () => { it('renders error message when fetching dapps fails', () => { const store = createMockStore({ dapps: { - dappListApiUrl: 'http://url.com', dappsList: [], dappsCategories: [], dappsListError: 'Error fetching dapps', @@ -152,7 +150,6 @@ describe('DappsScreen', () => { it('renders correctly when there are no favorite dapps', () => { const store = createMockStore({ dapps: { - dappListApiUrl: 'http://url.com', dappsList, dappsCategories, favoriteDappIds: [], @@ -173,7 +170,6 @@ describe('DappsScreen', () => { it('renders correctly when there are favourited dapps', () => { const store = createMockStore({ dapps: { - dappListApiUrl: 'http://url.com', dappsList, dappsCategories, favoriteDappIds: ['dapp2'], @@ -195,7 +191,6 @@ describe('DappsScreen', () => { it('triggers the events when favoriting', () => { const store = createMockStore({ dapps: { - dappListApiUrl: 'http://url.com', dappsList, dappsCategories, favoriteDappIds: ['dapp1'], @@ -230,7 +225,6 @@ describe('DappsScreen', () => { it('triggers the events when unfavoriting', () => { const store = createMockStore({ dapps: { - dappListApiUrl: 'http://url.com', dappsList, dappsCategories, favoriteDappIds: ['dapp2'], @@ -268,7 +262,6 @@ describe('DappsScreen', () => { it('renders correctly when there are no search results', () => { const store = createMockStore({ dapps: { - dappListApiUrl: 'http://url.com', dappsList, dappsCategories, favoriteDappIds: [], @@ -291,7 +284,6 @@ describe('DappsScreen', () => { it('renders correctly when there are search results in both sections', () => { const store = createMockStore({ dapps: { - dappListApiUrl: 'http://url.com', dappsList, dappsCategories, favoriteDappIds: ['dapp2'], @@ -324,7 +316,6 @@ describe('DappsScreen', () => { it('clearing search input should show all dapps', () => { const store = createMockStore({ dapps: { - dappListApiUrl: 'http://url.com', dappsList, dappsCategories, favoriteDappIds: ['dapp2'], @@ -360,7 +351,6 @@ describe('DappsScreen', () => { it('renders correctly when there are no filters applied', () => { const store = createMockStore({ dapps: { - dappListApiUrl: 'http://url.com', dappsList, dappsCategories, favoriteDappIds: ['dapp1'], @@ -391,7 +381,6 @@ describe('DappsScreen', () => { it('renders correctly when there are filters applied', () => { const store = createMockStore({ dapps: { - dappListApiUrl: 'http://url.com', dappsList, dappsCategories, favoriteDappIds: ['dapp1'], @@ -425,7 +414,6 @@ describe('DappsScreen', () => { it('triggers event when filtering', () => { const store = createMockStore({ dapps: { - dappListApiUrl: 'http://url.com', dappsList, dappsCategories, favoriteDappIds: ['dapp1'], @@ -453,7 +441,6 @@ describe('DappsScreen', () => { it('triggers events when toggling a category filter', () => { const store = createMockStore({ dapps: { - dappListApiUrl: 'http://url.com', dappsList, dappsCategories, favoriteDappIds: ['dapp1'], @@ -488,7 +475,6 @@ describe('DappsScreen', () => { it('triggers event when clearing filters from category section', () => { const store = createMockStore({ dapps: { - dappListApiUrl: 'http://url.com', dappsList, dappsCategories, favoriteDappIds: ['dapp2'], @@ -524,7 +510,6 @@ describe('DappsScreen', () => { it('triggers event when clearing filters from favorite section', () => { const store = createMockStore({ dapps: { - dappListApiUrl: 'http://url.com', dappsList, dappsCategories, favoriteDappIds: ['dapp1'], @@ -559,7 +544,6 @@ describe('DappsScreen', () => { it('renders correctly when there are results in all and favorites sections', () => { const store = createMockStore({ dapps: { - dappListApiUrl: 'http://url.com', dappsList, dappsCategories, favoriteDappIds: ['dapp1'], @@ -588,7 +572,6 @@ describe('DappsScreen', () => { it('renders correctly when there are results in favorites and no results in all', () => { const store = createMockStore({ dapps: { - dappListApiUrl: 'http://url.com', dappsList, dappsCategories, favoriteDappIds: ['dapp1'], @@ -619,7 +602,6 @@ describe('DappsScreen', () => { it('renders correctly when there are no results in favorites and results in all', () => { const store = createMockStore({ dapps: { - dappListApiUrl: 'http://url.com', dappsList, dappsCategories, favoriteDappIds: ['dapp2'], @@ -651,7 +633,6 @@ describe('DappsScreen', () => { describe('dapp open analytics event properties', () => { const defaultStoreProps = { - dappListApiUrl: 'http://url.com', dappsList, dappsCategories, favoriteDappIds: [], diff --git a/packages/@divvi/mobile/src/dapps/saga.test.ts b/packages/@divvi/mobile/src/dapps/saga.test.ts index a87beab6c49..0f2a93dc4be 100644 --- a/packages/@divvi/mobile/src/dapps/saga.test.ts +++ b/packages/@divvi/mobile/src/dapps/saga.test.ts @@ -3,17 +3,22 @@ import { expectSaga } from 'redux-saga-test-plan' import { select } from 'redux-saga/effects' import { DEEP_LINK_URL_SCHEME } from 'src/config' import { handleFetchDappsList, handleOpenDapp } from 'src/dapps/saga' -import { dappsListApiUrlSelector, dappsWebViewEnabledSelector } from 'src/dapps/selectors' import { dappSelected, fetchDappsListCompleted, fetchDappsListFailed } from 'src/dapps/slice' import { Dapp, DappSection } from 'src/dapps/types' import { currentLanguageSelector } from 'src/i18n/selectors' import { navigate } from 'src/navigator/NavigationService' import { Screens } from 'src/navigator/Screens' -import { getExperimentParams } from 'src/statsig' +import { getDynamicConfigParams, getExperimentParams } from 'src/statsig' import { walletAddressSelector } from 'src/web3/selectors' import { mockAccount } from 'test/values' jest.mock('src/statsig') +jest.mocked(getDynamicConfigParams).mockReturnValue({ + inAppWebviewEnabled: true, + links: { + dappList: 'http://some.url', + }, +}) describe('Dapps saga', () => { describe('Handles opening a dapp', () => { @@ -30,9 +35,7 @@ describe('Dapps saga', () => { await expectSaga( handleOpenDapp, dappSelected({ dapp: { ...baseDapp, openedFrom: DappSection.All } }) - ) - .provide([[select(dappsWebViewEnabledSelector), true]]) - .run() + ).run() expect(navigate).toHaveBeenCalledWith(Screens.WebViewScreen, { uri: baseDapp.dappUrl, @@ -50,10 +53,7 @@ describe('Dapps saga', () => { }, }) ) - .provide([ - [select(dappsWebViewEnabledSelector), true], - [select(walletAddressSelector), mockAccount], - ]) + .provide([[select(walletAddressSelector), mockAccount]]) .run() expect(navigate).toHaveBeenCalledWith(Screens.BidaliScreen, { currency: undefined }) @@ -68,10 +68,7 @@ describe('Dapps saga', () => { it('does not fetch the dapps list if the wallet is not yet initialized', async () => { await expectSaga(handleFetchDappsList) - .provide([ - [select(dappsListApiUrlSelector), 'http://some.url'], - [select(walletAddressSelector), null], - ]) + .provide([[select(walletAddressSelector), null]]) .run() expect(mockFetch).not.toHaveBeenCalled() @@ -123,7 +120,6 @@ describe('Dapps saga', () => { await expectSaga(handleFetchDappsList) .provide([ - [select(dappsListApiUrlSelector), 'http://some.url'], [select(walletAddressSelector), '0xabc'], [select(currentLanguageSelector), 'en'], ]) @@ -171,7 +167,6 @@ describe('Dapps saga', () => { await expectSaga(handleFetchDappsList) .provide([ - [select(dappsListApiUrlSelector), 'http://some.url'], [select(walletAddressSelector), '0xabc'], [select(currentLanguageSelector), 'en'], ]) diff --git a/packages/@divvi/mobile/src/dapps/saga.ts b/packages/@divvi/mobile/src/dapps/saga.ts index e8390dfcb3d..6e74267a9e4 100644 --- a/packages/@divvi/mobile/src/dapps/saga.ts +++ b/packages/@divvi/mobile/src/dapps/saga.ts @@ -1,7 +1,6 @@ import { PayloadAction } from '@reduxjs/toolkit' import { openDeepLink, openUrl } from 'src/app/actions' import { handleDeepLink, handleOpenUrl } from 'src/app/saga' -import { dappsListApiUrlSelector, dappsWebViewEnabledSelector } from 'src/dapps/selectors' import { dappSelected, DappSelectedAction, @@ -14,6 +13,9 @@ import { currentLanguageSelector } from 'src/i18n/selectors' import { setLanguage } from 'src/i18n/slice' import { navigate } from 'src/navigator/NavigationService' import { Screens } from 'src/navigator/Screens' +import { getDynamicConfigParams } from 'src/statsig' +import { DynamicConfigs } from 'src/statsig/constants' +import { StatsigDynamicConfigs } from 'src/statsig/types' import { isDeepLink } from 'src/utils/linking' import Logger from 'src/utils/Logger' import { safely } from 'src/utils/safely' @@ -36,7 +38,9 @@ interface Application { export function* handleOpenDapp(action: PayloadAction) { const { dappUrl } = action.payload.dapp - const dappsWebViewEnabled = yield* select(dappsWebViewEnabledSelector) + const dappsWebViewEnabled = getDynamicConfigParams( + DynamicConfigs[StatsigDynamicConfigs.DAPP_WEBVIEW_CONFIG] + ).inAppWebviewEnabled if (dappsWebViewEnabled) { const walletConnectEnabled: boolean = yield* call(isWalletConnectEnabled, dappUrl) @@ -51,7 +55,8 @@ export function* handleOpenDapp(action: PayloadAction) { } export function* handleFetchDappsList() { - const dappsListApiUrl = yield* select(dappsListApiUrlSelector) + const { links } = getDynamicConfigParams(DynamicConfigs[StatsigDynamicConfigs.APP_CONFIG]) + const dappsListApiUrl = links.dappList if (!dappsListApiUrl) { Logger.warn(TAG, 'dappsListApiUrl not found, skipping dapps list fetch') return diff --git a/packages/@divvi/mobile/src/dapps/selectors.ts b/packages/@divvi/mobile/src/dapps/selectors.ts index 3dac0e4a3ef..5342bc82e59 100644 --- a/packages/@divvi/mobile/src/dapps/selectors.ts +++ b/packages/@divvi/mobile/src/dapps/selectors.ts @@ -17,12 +17,7 @@ function getDappsById(dapps: Dapp[], dappIds: string[]) { return matchingDapps } -export const dappsListApiUrlSelector = (state: RootState) => state.dapps.dappListApiUrl - -export const activeDappSelector = (state: RootState) => - state.dapps.dappsWebViewEnabled ? state.dapps.activeDapp : null - -export const dappsWebViewEnabledSelector = (state: RootState) => state.dapps.dappsWebViewEnabled +export const activeDappSelector = (state: RootState) => state.dapps.activeDapp export const dappsCategoriesSelector = (state: RootState) => state.dapps.dappsCategories diff --git a/packages/@divvi/mobile/src/dapps/slice.ts b/packages/@divvi/mobile/src/dapps/slice.ts index b8cab615272..d309bbfccea 100644 --- a/packages/@divvi/mobile/src/dapps/slice.ts +++ b/packages/@divvi/mobile/src/dapps/slice.ts @@ -1,15 +1,10 @@ import { createSlice, PayloadAction } from '@reduxjs/toolkit' -import { Actions as AppActions, UpdateConfigValuesAction } from 'src/app/actions' import { ActiveDapp, Dapp, DappCategory } from 'src/dapps/types' -import { REMOTE_CONFIG_VALUES_DEFAULTS } from 'src/firebase/remoteConfigValuesDefaults' import { getRehydratePayload, REHYDRATE, RehydrateAction } from 'src/redux/persist-helper' interface State { - dappsWebViewEnabled: boolean activeDapp: ActiveDapp | null - maxNumRecentDapps: number recentDappIds: string[] - dappListApiUrl: string | null dappsList: Dapp[] dappsListLoading: boolean dappsListError: string | null @@ -19,11 +14,8 @@ interface State { } const initialState: State = { - dappsWebViewEnabled: REMOTE_CONFIG_VALUES_DEFAULTS.dappsWebViewEnabled, activeDapp: null, - maxNumRecentDapps: REMOTE_CONFIG_VALUES_DEFAULTS.maxNumRecentDapps, recentDappIds: [], - dappListApiUrl: REMOTE_CONFIG_VALUES_DEFAULTS.dappListApiUrl, dappsList: [], dappsListLoading: false, dappsListError: null, @@ -97,21 +89,11 @@ export const slice = createSlice({ }, }, extraReducers: (builder) => { - builder - .addCase( - AppActions.UPDATE_REMOTE_CONFIG_VALUES, - (state, action: UpdateConfigValuesAction) => { - state.dappsWebViewEnabled = action.configValues.dappsWebViewEnabled - state.maxNumRecentDapps = action.configValues.maxNumRecentDapps - state.dappsWebViewEnabled = action.configValues.dappsWebViewEnabled - state.dappListApiUrl = action.configValues.dappListApiUrl - } - ) - .addCase(REHYDRATE, (state, action: RehydrateAction) => ({ - ...state, - ...getRehydratePayload(action, 'dapps'), - activeDapp: null, - })) + builder.addCase(REHYDRATE, (state, action: RehydrateAction) => ({ + ...state, + ...getRehydratePayload(action, 'dapps'), + activeDapp: null, + })) }, }) diff --git a/packages/@divvi/mobile/src/dappsExplorer/DappFeaturedActions.test.tsx b/packages/@divvi/mobile/src/dappsExplorer/DappFeaturedActions.test.tsx index ec8939677ef..73c01393817 100644 --- a/packages/@divvi/mobile/src/dappsExplorer/DappFeaturedActions.test.tsx +++ b/packages/@divvi/mobile/src/dappsExplorer/DappFeaturedActions.test.tsx @@ -23,7 +23,6 @@ describe('DappFeaturedActions', () => { { { @@ -100,7 +100,6 @@ describe('TabDiscover', () => { it('renders correctly when there are no favorite dapps', () => { const store = createMockStore({ dapps: { - dappListApiUrl: 'http://url.com', dappsList, dappsCategories, mostPopularDappIds, @@ -141,7 +140,6 @@ describe('TabDiscover', () => { it('renders correctly when there are <=2 favorite dapps', () => { const store = createMockStore({ dapps: { - dappListApiUrl: 'http://url.com', dappsList, dappsCategories, mostPopularDappIds, @@ -183,7 +181,6 @@ describe('TabDiscover', () => { it('renders correctly when there are >2 favorite dapps', () => { const store = createMockStore({ dapps: { - dappListApiUrl: 'http://url.com', dappsList, dappsCategories, mostPopularDappIds, @@ -216,7 +213,6 @@ describe('TabDiscover', () => { it('renders correctly when there are >5 favorite dapps', () => { const store = createMockStore({ dapps: { - dappListApiUrl: 'http://url.com', dappsList, dappsCategories, mostPopularDappIds, @@ -255,7 +251,6 @@ describe('TabDiscover', () => { it('fires event on favorite dapp press', () => { const store = createMockStore({ dapps: { - dappListApiUrl: 'http://url.com', dappsList, dappsCategories, mostPopularDappIds, @@ -285,7 +280,6 @@ describe('TabDiscover', () => { it('fires event on popular dapp press', () => { const store = createMockStore({ dapps: { - dappListApiUrl: 'http://url.com', dappsList, dappsCategories, mostPopularDappIds, @@ -318,7 +312,6 @@ describe('TabDiscover', () => { it('navigates to dapp screen on button press and fires event', () => { const store = createMockStore({ dapps: { - dappListApiUrl: 'http://url.com', dappsList, dappsCategories, mostPopularDappIds, @@ -356,7 +349,7 @@ describe('TabDiscover', () => { (featureGateName) => featureGateName === StatsigFeatureGates.SHOW_POSITIONS ) const store = createMockStore({ - dapps: { dappListApiUrl: 'http://url.com', dappsList, dappsCategories }, + dapps: { dappsList, dappsCategories }, tokens: { tokenBalances: { [mockAaveArbUsdcTokenId]: { diff --git a/packages/@divvi/mobile/src/earn/EarnEnterAmount.test.tsx b/packages/@divvi/mobile/src/earn/EarnEnterAmount.test.tsx index e66ced060cc..29018a3c188 100644 --- a/packages/@divvi/mobile/src/earn/EarnEnterAmount.test.tsx +++ b/packages/@divvi/mobile/src/earn/EarnEnterAmount.test.tsx @@ -12,7 +12,7 @@ import { Status as EarnStatus } from 'src/earn/slice' import { CICOFlow } from 'src/fiatExchanges/types' import { navigate } from 'src/navigator/NavigationService' import { Screens } from 'src/navigator/Screens' -import { getFeatureGate, getMultichainFeatures } from 'src/statsig' +import { getFeatureGate } from 'src/statsig' import { StatsigFeatureGates } from 'src/statsig/types' import { SwapTransaction } from 'src/swap/types' import { TokenBalance } from 'src/tokens/slice' @@ -45,13 +45,6 @@ import { jest.mock('src/earn/hooks') jest.mock('react-native-localize') jest.mock('src/statsig') // for cross chain swap and indirect use in hooksApiSelector -jest.mocked(getMultichainFeatures).mockReturnValue({ - showSwap: [ - NetworkId['arbitrum-sepolia'], - NetworkId['celo-alfajores'], - NetworkId['ethereum-sepolia'], - ], -}) const mockPreparedTransaction: PreparedTransactionsPossible = { type: 'possible' as const, diff --git a/packages/@divvi/mobile/src/earn/EarnEnterAmount.tsx b/packages/@divvi/mobile/src/earn/EarnEnterAmount.tsx index 6758ed9b653..818d3716305 100644 --- a/packages/@divvi/mobile/src/earn/EarnEnterAmount.tsx +++ b/packages/@divvi/mobile/src/earn/EarnEnterAmount.tsx @@ -513,6 +513,7 @@ export default function EarnEnterAmount({ route }: Props) { )} ({ getDynamicConfigParams: jest.fn().mockReturnValue({ enabled: true }), - getMultichainFeatures: jest.fn(), getFeatureGate: jest.fn(), })) @@ -69,10 +67,6 @@ const renderEarnPoolInfoScreen = (pool: EarnPosition) => describe('EarnPoolInfoScreen', () => { beforeEach(() => { jest.clearAllMocks() - jest.mocked(getMultichainFeatures).mockReturnValue({ - showCico: [NetworkId['arbitrum-sepolia']], - showSwap: [NetworkId['celo-alfajores'], NetworkId['arbitrum-sepolia']], - }) jest .mocked(getFeatureGate) .mockImplementation((gate) => gate === StatsigFeatureGates.ALLOW_CROSS_CHAIN_SWAPS) diff --git a/packages/@divvi/mobile/src/earn/poolInfoScreen/WithdrawBottomSheet.test.tsx b/packages/@divvi/mobile/src/earn/poolInfoScreen/WithdrawBottomSheet.test.tsx index ca3f85b5eed..e9a46e75e13 100644 --- a/packages/@divvi/mobile/src/earn/poolInfoScreen/WithdrawBottomSheet.test.tsx +++ b/packages/@divvi/mobile/src/earn/poolInfoScreen/WithdrawBottomSheet.test.tsx @@ -18,7 +18,6 @@ import { } from 'test/values' jest.mock('src/statsig', () => ({ - getMultichainFeatures: jest.fn(), getFeatureGate: jest.fn(), })) diff --git a/packages/@divvi/mobile/src/fiatExchanges/FiatExchangeCurrencyBottomSheet.test.tsx b/packages/@divvi/mobile/src/fiatExchanges/FiatExchangeCurrencyBottomSheet.test.tsx index 5909e6a20c2..e8410ebdfb9 100644 --- a/packages/@divvi/mobile/src/fiatExchanges/FiatExchangeCurrencyBottomSheet.test.tsx +++ b/packages/@divvi/mobile/src/fiatExchanges/FiatExchangeCurrencyBottomSheet.test.tsx @@ -3,14 +3,8 @@ import React from 'react' import { Provider } from 'react-redux' import FiatExchangeCurrencyBottomSheet from 'src/fiatExchanges/FiatExchangeCurrencyBottomSheet' import { FiatExchangeFlow } from 'src/fiatExchanges/types' -import { getDynamicConfigParams, getFeatureGate, getMultichainFeatures } from 'src/statsig' -import { DynamicConfigs } from 'src/statsig/constants' -import { - StatsigDynamicConfigs, - StatsigFeatureGates, - StatsigMultiNetworkDynamicConfig, -} from 'src/statsig/types' -import { NetworkId } from 'src/transactions/types' +import { getDynamicConfigParams, getFeatureGate } from 'src/statsig' +import { StatsigDynamicConfigs, StatsigFeatureGates } from 'src/statsig/types' import MockedNavigator from 'test/MockedNavigator' import { createMockStore } from 'test/utils' import { @@ -53,10 +47,6 @@ describe(FiatExchangeCurrencyBottomSheet, () => { beforeEach(() => { jest.clearAllMocks() jest.mocked(getFeatureGate).mockReturnValue(false) - jest.mocked(getMultichainFeatures).mockReturnValue({ - ...DynamicConfigs[StatsigMultiNetworkDynamicConfig.MULTI_CHAIN_FEATURES].defaultValues, - showCico: [NetworkId['celo-alfajores'], NetworkId['ethereum-sepolia']], - }) jest.mocked(getDynamicConfigParams).mockImplementation(({ configName, defaultValues }) => { switch (configName) { case StatsigDynamicConfigs.CICO_TOKEN_INFO: diff --git a/packages/@divvi/mobile/src/fiatExchanges/FiatExchangeCurrencyBottomSheet.tsx b/packages/@divvi/mobile/src/fiatExchanges/FiatExchangeCurrencyBottomSheet.tsx index ec77b884829..df763723010 100644 --- a/packages/@divvi/mobile/src/fiatExchanges/FiatExchangeCurrencyBottomSheet.tsx +++ b/packages/@divvi/mobile/src/fiatExchanges/FiatExchangeCurrencyBottomSheet.tsx @@ -9,7 +9,7 @@ import { navigate } from 'src/navigator/NavigationService' import { Screens } from 'src/navigator/Screens' import { StackParamList } from 'src/navigator/types' import { useDispatch, useSelector } from 'src/redux/hooks' -import { getDynamicConfigParams, getFeatureGate, getMultichainFeatures } from 'src/statsig' +import { getDynamicConfigParams, getFeatureGate } from 'src/statsig' import { DynamicConfigs } from 'src/statsig/constants' import { StatsigDynamicConfigs, StatsigFeatureGates } from 'src/statsig/types' import { useCashInTokens, useCashOutTokens, useSpendTokens } from 'src/tokens/hooks' @@ -18,6 +18,7 @@ import { TokenBalance } from 'src/tokens/slice' import { sortCicoTokens } from 'src/tokens/utils' import { NetworkId } from 'src/transactions/types' import { resolveCurrency } from 'src/utils/currencies' +import { getSupportedNetworkIds } from 'src/web3/utils' type Props = BottomSheetScreenProps @@ -37,7 +38,7 @@ function useFilterChips( if (flow !== FiatExchangeFlow.CashIn) { return [] } - const supportedNetworkIds = getMultichainFeatures().showCico + const supportedNetworkIds = getSupportedNetworkIds() // reuse the same popular tokens as for swap const popularTokenIds: string[] = getDynamicConfigParams( DynamicConfigs[StatsigDynamicConfigs.SWAP_CONFIG] diff --git a/packages/@divvi/mobile/src/firebase/firebase.ts b/packages/@divvi/mobile/src/firebase/firebase.ts index f34663c5919..1bf836a8685 100644 --- a/packages/@divvi/mobile/src/firebase/firebase.ts +++ b/packages/@divvi/mobile/src/firebase/firebase.ts @@ -271,35 +271,14 @@ export async function fetchRemoteConfigValues(): Promise & { - sentryNetworkErrors: string - dappListApiUrl: string - celoNews: string -} = { + 'fiatAccountSchemaCountryOverrides' +> = { inviteRewardsVersion: 'none', - walletConnectV2Enabled: true, - pincodeUseExpandedBlocklist: isE2EEnv ? true : false, - logPhoneNumberTypeEnabled: false, - allowOtaTranslations: false, - sentryTracesSampleRate: DEFAULT_SENTRY_TRACES_SAMPLE_RATE, - sentryNetworkErrors: DEFAULT_SENTRY_NETWORK_ERRORS.join(','), - maxNumRecentDapps: isE2EEnv ? 4 : 0, - dappsWebViewEnabled: isE2EEnv ? true : false, - dappListApiUrl: isE2EEnv - ? 'https://us-central1-celo-mobile-alfajores.cloudfunctions.net/dappList' - : '', fiatConnectCashInEnabled: false, fiatConnectCashOutEnabled: isE2EEnv ? true : false, - coinbasePayEnabled: false, - maxSwapSlippagePercentage: 2, - networkTimeoutSeconds: 30, - celoNews: JSON.stringify({} as RemoteConfigValues['celoNews']), - priceImpactWarningThreshold: 0.04, } diff --git a/packages/@divvi/mobile/src/home/TabHome.test.tsx b/packages/@divvi/mobile/src/home/TabHome.test.tsx index a46179a7bd8..cab8e815e5d 100644 --- a/packages/@divvi/mobile/src/home/TabHome.test.tsx +++ b/packages/@divvi/mobile/src/home/TabHome.test.tsx @@ -78,10 +78,6 @@ const mockBalances = { jest.mock('src/statsig', () => ({ getDynamicConfigParams: jest.fn().mockReturnValue({ enabled: true }), getFeatureGate: jest.fn().mockReturnValue(false), - getMultichainFeatures: jest.fn(() => ({ - showBalances: ['celo-alfajores'], - showTransfers: ['celo-alfajores'], - })), })) jest.mock('src/fiatExchanges/utils', () => ({ diff --git a/packages/@divvi/mobile/src/i18n/i18n.test.ts b/packages/@divvi/mobile/src/i18n/i18n.test.ts index f18a6679fa0..73887c36a0b 100644 --- a/packages/@divvi/mobile/src/i18n/i18n.test.ts +++ b/packages/@divvi/mobile/src/i18n/i18n.test.ts @@ -1,6 +1,6 @@ import i18next from 'i18next' -jest.mock('react-native-fs', () => { +jest.mock('@divvi/react-native-fs', () => { return { exists: jest.fn().mockResolvedValue(true), readFile: jest.fn().mockResolvedValue('{"en-US":{"someKey":"Hello!"}}'), diff --git a/packages/@divvi/mobile/src/i18n/index.ts b/packages/@divvi/mobile/src/i18n/index.ts index 460e784ee28..cf12f6a11d5 100644 --- a/packages/@divvi/mobile/src/i18n/index.ts +++ b/packages/@divvi/mobile/src/i18n/index.ts @@ -2,8 +2,8 @@ import hoistStatics from 'hoist-non-react-statics' import i18n, { Resource, ResourceLanguage } from 'i18next' import _ from 'lodash' import { - WithTranslation, initReactI18next, + WithTranslation, withTranslation as withTranslationI18Next, } from 'react-i18next' import DeviceInfo from 'react-native-device-info' diff --git a/packages/@divvi/mobile/src/i18n/otaTranslations.test.ts b/packages/@divvi/mobile/src/i18n/otaTranslations.test.ts index fd2bf816adf..e2172d21370 100644 --- a/packages/@divvi/mobile/src/i18n/otaTranslations.test.ts +++ b/packages/@divvi/mobile/src/i18n/otaTranslations.test.ts @@ -1,4 +1,4 @@ -import * as RNFS from 'react-native-fs' +import * as RNFS from '@divvi/react-native-fs' import { OTA_TRANSLATIONS_FILEPATH } from 'src/config' import { getOtaTranslations, saveOtaTranslations } from 'src/i18n/otaTranslations' diff --git a/packages/@divvi/mobile/src/i18n/otaTranslations.ts b/packages/@divvi/mobile/src/i18n/otaTranslations.ts index 6f3c4c483a1..036328553bc 100644 --- a/packages/@divvi/mobile/src/i18n/otaTranslations.ts +++ b/packages/@divvi/mobile/src/i18n/otaTranslations.ts @@ -1,5 +1,5 @@ +import * as RNFS from '@divvi/react-native-fs' import { Resource } from 'i18next' -import * as RNFS from 'react-native-fs' import { OTA_TRANSLATIONS_FILEPATH } from 'src/config' export function saveOtaTranslations(resource: Resource) { diff --git a/packages/@divvi/mobile/src/i18n/saga.test.ts b/packages/@divvi/mobile/src/i18n/saga.test.ts index 03d1c8cf7b6..58137d244c5 100644 --- a/packages/@divvi/mobile/src/i18n/saga.test.ts +++ b/packages/@divvi/mobile/src/i18n/saga.test.ts @@ -6,7 +6,6 @@ import { call, select } from 'redux-saga/effects' import { saveOtaTranslations } from 'src/i18n/otaTranslations' import { handleFetchOtaTranslations } from 'src/i18n/saga' import { - allowOtaTranslationsSelector, currentLanguageSelector, otaTranslationsAppVersionSelector, otaTranslationsLanguageSelector, @@ -44,7 +43,6 @@ describe('i18n sagas', () => { const mockedVersion = DeviceInfo.getVersion as jest.MockedFunction mockedVersion.mockImplementation(() => appVersion) const defaultProviders: (EffectProviders | StaticProvider)[] = [ - [select(allowOtaTranslationsSelector), true], [select(otaTranslationsAppVersionSelector), appVersion], [select(otaTranslationsLanguageSelector), 'en-US'], [select(currentLanguageSelector), 'en-US'], diff --git a/packages/@divvi/mobile/src/i18n/saga.ts b/packages/@divvi/mobile/src/i18n/saga.ts index 282679bf04c..96463dd5a40 100644 --- a/packages/@divvi/mobile/src/i18n/saga.ts +++ b/packages/@divvi/mobile/src/i18n/saga.ts @@ -2,11 +2,9 @@ import OtaClient from '@crowdin/ota-client' import i18n from 'i18next' import _ from 'lodash' import DeviceInfo from 'react-native-device-info' -import { Actions as AppActions } from 'src/app/actions' -import { CROWDIN_DISTRIBUTION_HASH } from 'src/config' +import { CROWDIN_DISTRIBUTION_HASH, ENABLE_OTA_TRANSLATIONS } from 'src/config' import { saveOtaTranslations } from 'src/i18n/otaTranslations' import { - allowOtaTranslationsSelector, currentLanguageSelector, otaTranslationsAppVersionSelector, otaTranslationsLanguageSelector, @@ -19,9 +17,9 @@ import { call, put, select, spawn, takeLatest } from 'typed-redux-saga' const TAG = 'i18n/saga' const otaClient = new OtaClient(CROWDIN_DISTRIBUTION_HASH) +const allowOtaTranslations = ENABLE_OTA_TRANSLATIONS export function* handleFetchOtaTranslations() { - const allowOtaTranslations = yield* select(allowOtaTranslationsSelector) if (allowOtaTranslations) { try { const currentLanguage = yield* select(currentLanguageSelector) @@ -67,10 +65,7 @@ export function* handleFetchOtaTranslations() { } export function* watchOtaTranslations() { - yield* takeLatest( - [setLanguage.type, AppActions.UPDATE_REMOTE_CONFIG_VALUES], - safely(handleFetchOtaTranslations) - ) + yield* takeLatest([setLanguage.type], safely(handleFetchOtaTranslations)) } export function* i18nSaga() { diff --git a/packages/@divvi/mobile/src/i18n/selectors.ts b/packages/@divvi/mobile/src/i18n/selectors.ts index ca44100ff6d..5a46009697d 100644 --- a/packages/@divvi/mobile/src/i18n/selectors.ts +++ b/packages/@divvi/mobile/src/i18n/selectors.ts @@ -2,8 +2,6 @@ import { RootState } from 'src/redux/reducers' export const currentLanguageSelector = (state: RootState) => state.i18n.language -export const allowOtaTranslationsSelector = (state: RootState) => state.i18n.allowOtaTranslations - export const otaTranslationsLastUpdateSelector = (state: RootState) => state.i18n.otaTranslationsLastUpdate diff --git a/packages/@divvi/mobile/src/i18n/slice.ts b/packages/@divvi/mobile/src/i18n/slice.ts index 8fbf2741184..d919f304ecd 100644 --- a/packages/@divvi/mobile/src/i18n/slice.ts +++ b/packages/@divvi/mobile/src/i18n/slice.ts @@ -1,11 +1,8 @@ import { createSlice, PayloadAction } from '@reduxjs/toolkit' -import { Actions as AppActions, UpdateConfigValuesAction } from 'src/app/actions' -import { REMOTE_CONFIG_VALUES_DEFAULTS } from 'src/firebase/remoteConfigValuesDefaults' import { getRehydratePayload, REHYDRATE, RehydrateAction } from 'src/redux/persist-helper' interface State { language: string | null - allowOtaTranslations: boolean otaTranslationsLastUpdate: number otaTranslationsAppVersion: string otaTranslationsLanguage: string @@ -13,7 +10,6 @@ interface State { const initialState: State = { language: null, - allowOtaTranslations: REMOTE_CONFIG_VALUES_DEFAULTS.allowOtaTranslations, otaTranslationsLastUpdate: 0, otaTranslationsAppVersion: '0', otaTranslationsLanguage: '', @@ -38,17 +34,10 @@ export const slice = createSlice({ }, }, extraReducers: (builder) => { - builder - .addCase( - AppActions.UPDATE_REMOTE_CONFIG_VALUES, - (state, action: UpdateConfigValuesAction) => { - state.allowOtaTranslations = action.configValues.allowOtaTranslations - } - ) - .addCase(REHYDRATE, (state, action: RehydrateAction) => ({ - ...state, - ...getRehydratePayload(action, 'i18n'), - })) + builder.addCase(REHYDRATE, (state, action: RehydrateAction) => ({ + ...state, + ...getRehydratePayload(action, 'i18n'), + })) }, }) diff --git a/packages/@divvi/mobile/src/keylessBackup/KeylessBackupProgress.test.tsx b/packages/@divvi/mobile/src/keylessBackup/KeylessBackupProgress.test.tsx index 64ee17be5f3..8703015a5e8 100644 --- a/packages/@divvi/mobile/src/keylessBackup/KeylessBackupProgress.test.tsx +++ b/packages/@divvi/mobile/src/keylessBackup/KeylessBackupProgress.test.tsx @@ -1,8 +1,8 @@ import { fireEvent, render, waitFor } from '@testing-library/react-native' import * as React from 'react' import { Provider } from 'react-redux' -import { KeylessBackupEvents } from 'src/analytics/Events' import AppAnalytics from 'src/analytics/AppAnalytics' +import { KeylessBackupEvents } from 'src/analytics/Events' import KeylessBackupProgress from 'src/keylessBackup/KeylessBackupProgress' import { keylessBackupAcceptZeroBalance, keylessBackupBail } from 'src/keylessBackup/slice' import { diff --git a/packages/@divvi/mobile/src/navigator/DemoModeAuthBlock.test.tsx b/packages/@divvi/mobile/src/navigator/DemoModeAuthBlock.test.tsx new file mode 100644 index 00000000000..1e199353eb3 --- /dev/null +++ b/packages/@divvi/mobile/src/navigator/DemoModeAuthBlock.test.tsx @@ -0,0 +1,60 @@ +import { fireEvent, render } from '@testing-library/react-native' +import React from 'react' +import { Provider } from 'react-redux' +import DemoModeAuthBlock from 'src/navigator/DemoModeAuthBlock' +import { navigateBack, navigateClearingStack } from 'src/navigator/NavigationService' +import { demoModeToggled } from 'src/web3/actions' +import { createMockStore } from 'test/utils' +import { mockAccount } from 'test/values' + +jest.mock('src/statsig') + +describe('DemoModeAuthBlock', () => { + beforeEach(() => { + jest.clearAllMocks() + }) + + it('renders correctly and executes the expected actions on button press', () => { + const store = createMockStore({ + web3: { + account: mockAccount, + }, + }) + const { getByText } = render( + + + + ) + + expect(getByText('demoMode.restrictedAccess.title')).toBeTruthy() + expect(getByText('demoMode.restrictedAccess.info')).toBeTruthy() + + fireEvent.press(getByText('demoMode.restrictedAccess.cta')) + + expect(store.getActions()).toEqual([demoModeToggled(false)]) + expect(navigateBack).toHaveBeenCalledTimes(1) + expect(navigateClearingStack).not.toHaveBeenCalled() + + fireEvent.press(getByText('dismiss')) + expect(navigateBack).toHaveBeenCalledTimes(2) + }) + + it('navigates to onboarding when exiting demo mode', () => { + const store = createMockStore({ + web3: { + account: null, // no wallet set up + }, + }) + const { getByText } = render( + + + + ) + + fireEvent.press(getByText('demoMode.restrictedAccess.cta')) + + expect(store.getActions()).toEqual([demoModeToggled(false)]) + expect(navigateBack).toHaveBeenCalled() + expect(navigateClearingStack).toHaveBeenCalled() + }) +}) diff --git a/packages/@divvi/mobile/src/navigator/DemoModeAuthBlock.tsx b/packages/@divvi/mobile/src/navigator/DemoModeAuthBlock.tsx new file mode 100644 index 00000000000..30c1674174c --- /dev/null +++ b/packages/@divvi/mobile/src/navigator/DemoModeAuthBlock.tsx @@ -0,0 +1,61 @@ +import React from 'react' +import { useTranslation } from 'react-i18next' +import { StyleSheet, Text } from 'react-native' +import BottomSheetScrollView from 'src/components/BottomSheetScrollView' +import Button, { BtnSizes, BtnTypes } from 'src/components/Button' +import { navigateBack, navigateClearingStack } from 'src/navigator/NavigationService' +import { Screens } from 'src/navigator/Screens' +import { useDispatch, useSelector } from 'src/redux/hooks' +import { typeScale } from 'src/styles/fonts' +import { Spacing } from 'src/styles/styles' +import { demoModeToggled } from 'src/web3/actions' +import { rawWalletAddressSelector } from 'src/web3/selectors' + +export default function DemoModeAuthBlock() { + const { t } = useTranslation() + const dispatch = useDispatch() + const originalWalletAddress = useSelector(rawWalletAddressSelector) + + const handleExitDemoMode = () => { + dispatch(demoModeToggled(false)) + navigateBack() // dismiss the bottom sheet + + if (!originalWalletAddress) { + navigateClearingStack(Screens.Welcome) + } + } + + return ( + + {t('demoMode.restrictedAccess.title')} + {t('demoMode.restrictedAccess.info')} +