diff --git a/CHANGELOG.md b/CHANGELOG.md index de0a6b61a23..908b7c2ddcb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,18 @@ and this project adheres to [Semantic Versioning](http://semver.org/) ### Fixed +## [1.9.46] (https://github.com/rainbow-me/rainbow/releases/tag/v1.9.46) + +### Changed + +- Remove unused environment configurations (#6254) +- Added a null check guard to the claimable flow (#6257) + +### Fixed + +- Fixed an issue in our approve and swap flow that should help overall swap success (#6259) +- Changed the way we handle flashbots gas so less transactions should fail due to insufficent gas (#6265) + ## [1.9.45] (https://github.com/rainbow-me/rainbow/releases/tag/v1.9.45) ### Added diff --git a/android/app/build.gradle b/android/app/build.gradle index 89ea9e3d1eb..7dc564ab243 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -135,8 +135,8 @@ android { applicationId "me.rainbow" minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 239 - versionName "1.9.46" + versionCode 240 + versionName "1.9.47" missingDimensionStrategy 'react-native-camera', 'general' renderscriptTargetApi 23 renderscriptSupportModeEnabled true diff --git a/android/app/src/main/java/me/rainbow/MainApplication.kt b/android/app/src/main/java/me/rainbow/MainApplication.kt index 3ae4700549d..57c8995051e 100644 --- a/android/app/src/main/java/me/rainbow/MainApplication.kt +++ b/android/app/src/main/java/me/rainbow/MainApplication.kt @@ -19,7 +19,6 @@ import me.rainbow.NativeModules.Haptics.RNHapticsPackage import me.rainbow.NativeModules.Internals.InternalPackage import me.rainbow.NativeModules.RNBackHandler.RNBackHandlerPackage import me.rainbow.NativeModules.RNBip39.RNBip39Package -import me.rainbow.NativeModules.RNReview.RNReviewPackage import me.rainbow.NativeModules.RNStartTime.RNStartTimePackage import me.rainbow.NativeModules.RNTextAnimatorPackage.RNTextAnimatorPackage import me.rainbow.NativeModules.RNZoomableButton.RNZoomableButtonPackage @@ -36,7 +35,6 @@ class MainApplication : Application(), ReactApplication { val packages: MutableList = PackageList(this).packages // Packages that cannot be autolinked yet can be added manually here, for example: packages.add(RNBip39Package()) - packages.add(RNReviewPackage()) packages.add(SystemNavigationBarPackage()) packages.add(RNBackHandlerPackage()) packages.add(RNTextAnimatorPackage()) diff --git a/android/app/src/main/java/me/rainbow/NativeModules/RNReview/RNReviewModule.java b/android/app/src/main/java/me/rainbow/NativeModules/RNReview/RNReviewModule.java deleted file mode 100644 index 4e365d9c372..00000000000 --- a/android/app/src/main/java/me/rainbow/NativeModules/RNReview/RNReviewModule.java +++ /dev/null @@ -1,54 +0,0 @@ -package me.rainbow.NativeModules.RNReview; - -import android.app.Activity; -import com.facebook.react.bridge.Promise; -import com.facebook.react.bridge.ReactApplicationContext; -import com.facebook.react.bridge.ReactContextBaseJavaModule; -import com.facebook.react.bridge.ReactMethod; -import com.google.android.play.core.review.ReviewInfo; -import com.google.android.play.core.review.ReviewManager; -import com.google.android.play.core.review.ReviewManagerFactory; -import com.google.android.gms.tasks.Task; - -public class RNReviewModule extends ReactContextBaseJavaModule { - private final ReactApplicationContext reactContext; - - public RNReviewModule(ReactApplicationContext reactContext) { - super(reactContext); - this.reactContext = reactContext; - } - - @Override - public String getName() { - return "RNReview"; - } - - @ReactMethod - - public void show(final Promise promise) { - final Activity activity = reactContext.getCurrentActivity(); - if (activity == null) { - promise.reject("E_ACTIVITY_DOES_NOT_EXIST", "Activity doesn't exist"); - return; - } - - ReviewManager manager = ReviewManagerFactory.create(reactContext); - Task request = manager.requestReviewFlow(); - request.addOnCompleteListener(task -> { - if (task.isSuccessful()) { - // We can get the ReviewInfo object - ReviewInfo reviewInfo = task.getResult(); - Task flow = manager.launchReviewFlow(activity, reviewInfo); - flow.addOnCompleteListener(task1 -> { - if (task1.isSuccessful()) { - promise.resolve(null); - } else { - promise.reject("E_REVIEW_FLOW_FAILED", "Review flow failed"); - } - }); - } else { - promise.reject("E_REQUEST_REVIEW_FAILED", "Request review flow failed"); - } - }); - } -} diff --git a/android/app/src/main/java/me/rainbow/NativeModules/RNReview/RNReviewPackage.java b/android/app/src/main/java/me/rainbow/NativeModules/RNReview/RNReviewPackage.java deleted file mode 100644 index 7317def905b..00000000000 --- a/android/app/src/main/java/me/rainbow/NativeModules/RNReview/RNReviewPackage.java +++ /dev/null @@ -1,22 +0,0 @@ -package me.rainbow.NativeModules.RNReview; - -import com.facebook.react.ReactPackage; -import com.facebook.react.bridge.NativeModule; -import com.facebook.react.bridge.ReactApplicationContext; -import com.facebook.react.uimanager.ViewManager; - -import java.util.Arrays; -import java.util.Collections; -import java.util.List; - -public class RNReviewPackage implements ReactPackage { - @Override - public List createNativeModules(ReactApplicationContext reactContext) { - return Arrays.asList(new RNReviewModule(reactContext)); - } - - @Override - public List createViewManagers(ReactApplicationContext reactContext) { - return Collections.emptyList(); - } -} diff --git a/ios/Extensions.swift b/ios/Extensions.swift index 152095f9c95..8d6fcaf65ce 100644 --- a/ios/Extensions.swift +++ b/ios/Extensions.swift @@ -53,10 +53,6 @@ extension UIScreen { extension UIView { - open override var canBecomeFirstResponder: Bool { - return true - } - static func fromNib() -> T { return Bundle(for: T.self).loadNibNamed(String(describing: T.self), owner: nil, options: nil)![0] as! T } diff --git a/ios/Podfile.lock b/ios/Podfile.lock index af7eb5f5407..2282338ff8a 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -43,6 +43,8 @@ PODS: - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core - Yoga + - ExpoStoreReview (7.0.2): + - ExpoModulesCore - FasterImage (1.6.2): - FasterImage/Nuke (= 1.6.2) - FasterImage/NukeUI (= 1.6.2) @@ -1876,6 +1878,27 @@ PODS: - TOCropViewController (2.7.4) - ToolTipMenu (5.2.1): - React + - TurboHaptics (1.0.4): + - DoubleConversion + - glog + - hermes-engine + - RCT-Folly (= 2024.01.01.00) + - RCTRequired + - RCTTypeSafety + - React-Codegen + - React-Core + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-ImageManager + - React-NativeModulesApple + - React-RCTFabric + - React-rendererdebug + - React-utils + - ReactCommon/turbomodule/bridging + - ReactCommon/turbomodule/core + - Yoga - VisionCamera (4.4.2): - VisionCamera/Core (= 4.4.2) - VisionCamera/React (= 4.4.2) @@ -1895,6 +1918,7 @@ DEPENDENCIES: - ExpoFont (from `../node_modules/expo-font/ios`) - ExpoKeepAwake (from `../node_modules/expo-keep-awake/ios`) - ExpoModulesCore (from `../node_modules/expo-modules-core`) + - ExpoStoreReview (from `../node_modules/expo-store-review/ios`) - "FasterImage (from `../node_modules/@candlefinance/faster-image`)" - FBLazyVector (from `../node_modules/react-native/Libraries/FBLazyVector`) - Firebase @@ -2035,6 +2059,7 @@ DEPENDENCIES: - TcpSockets (from `../node_modules/react-native-tcp`) - TOCropViewController (~> 2.7.4) - ToolTipMenu (from `../node_modules/react-native-tooltip`) + - TurboHaptics (from `../node_modules/react-native-turbo-haptics`) - VisionCamera (from `../node_modules/react-native-vision-camera`) - Yoga (from `../node_modules/react-native/ReactCommon/yoga`) @@ -2097,6 +2122,8 @@ EXTERNAL SOURCES: :path: "../node_modules/expo-keep-awake/ios" ExpoModulesCore: :path: "../node_modules/expo-modules-core" + ExpoStoreReview: + :path: "../node_modules/expo-store-review/ios" FasterImage: :path: "../node_modules/@candlefinance/faster-image" FBLazyVector: @@ -2345,6 +2372,8 @@ EXTERNAL SOURCES: :path: "../node_modules/react-native-tcp" ToolTipMenu: :path: "../node_modules/react-native-tooltip" + TurboHaptics: + :path: "../node_modules/react-native-turbo-haptics" VisionCamera: :path: "../node_modules/react-native-vision-camera" Yoga: @@ -2369,6 +2398,7 @@ SPEC CHECKSUMS: ExpoFont: 00756e6c796d8f7ee8d211e29c8b619e75cbf238 ExpoKeepAwake: 3b8815d9dd1d419ee474df004021c69fdd316d08 ExpoModulesCore: f30a203ff1863bab3dd9f4421e7fc1564797f18a + ExpoStoreReview: 15f9a636b62ff00bb21cbe9a9fe22f0239da4481 FasterImage: af05a76f042ca3654c962b658fdb01cb4d31caee FBLazyVector: 7e977dd099937dc5458851233141583abba49ff2 Firebase: 26b040b20866a55f55eb3611b9fcf3ae64816b86 @@ -2524,6 +2554,7 @@ SPEC CHECKSUMS: TcpSockets: bd31674146c0931a064fc254a59812dfd1a73ae0 TOCropViewController: 80b8985ad794298fb69d3341de183f33d1853654 ToolTipMenu: 8ac61aded0fbc4acfe7e84a7d0c9479d15a9a382 + TurboHaptics: 6381613d33ab97aeb30d9b15c3df94dc616a25e4 VisionCamera: 2af28201c3de77245f8c58b7a5274d5979df70df Yoga: 04f1db30bb810187397fa4c37dd1868a27af229c diff --git a/ios/Rainbow.xcodeproj/project.pbxproj b/ios/Rainbow.xcodeproj/project.pbxproj index 4efa7ebea0f..da6540f510b 100644 --- a/ios/Rainbow.xcodeproj/project.pbxproj +++ b/ios/Rainbow.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 46; + objectVersion = 54; objects = { /* Begin PBXBuildFile section */ @@ -25,18 +25,17 @@ 15E531D5242B28EF00797B89 /* UIImageViewWithPersistentAnimations.swift in Sources */ = {isa = PBXBuildFile; fileRef = 15E531D4242B28EF00797B89 /* UIImageViewWithPersistentAnimations.swift */; }; 15E531DA242DAB7100797B89 /* NotificationManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 15E531D9242DAB7100797B89 /* NotificationManager.m */; }; 24979E8920F84250007EB0DA /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 24979E7720F84004007EB0DA /* GoogleService-Info.plist */; }; + 2D28BB8F1ECF8D127306A3F1 /* libPods-Rainbow.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 556FE6D2BA19BF19B2185138 /* libPods-Rainbow.a */; }; + 35F6F98CBC0BF1DA6049CF57 /* libPods-ImageNotification.a in Frameworks */ = {isa = PBXBuildFile; fileRef = BF5C675494B8453FBFF6274D /* libPods-ImageNotification.a */; }; 4D098C2F2811A9A5006A801A /* RNStartTime.m in Sources */ = {isa = PBXBuildFile; fileRef = 4D098C2E2811A9A5006A801A /* RNStartTime.m */; }; 6630540924A38A1900E5B030 /* RainbowText.m in Sources */ = {isa = PBXBuildFile; fileRef = 6630540824A38A1900E5B030 /* RainbowText.m */; }; - 6635730624939991006ACFA6 /* SafeStoreReview.m in Sources */ = {isa = PBXBuildFile; fileRef = 6635730524939991006ACFA6 /* SafeStoreReview.m */; }; 6655FFB425BB2B0700642961 /* ThemeModule.m in Sources */ = {isa = PBXBuildFile; fileRef = 6655FFB325BB2B0700642961 /* ThemeModule.m */; }; 66A1FEB424AB641100C3F539 /* RNCMScreenStack.m in Sources */ = {isa = PBXBuildFile; fileRef = 66A1FEB024AB641100C3F539 /* RNCMScreenStack.m */; }; 66A1FEB524AB641100C3F539 /* UIViewController+slack.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66A1FEB124AB641100C3F539 /* UIViewController+slack.swift */; }; 66A1FEB624AB641100C3F539 /* RNCMScreen.m in Sources */ = {isa = PBXBuildFile; fileRef = 66A1FEB324AB641100C3F539 /* RNCMScreen.m */; }; 66A1FEBC24ACBBE600C3F539 /* RNCMPortal.m in Sources */ = {isa = PBXBuildFile; fileRef = 66A1FEBB24ACBBE600C3F539 /* RNCMPortal.m */; }; 66A28EB024CAF1B500410A88 /* TestFlight.m in Sources */ = {isa = PBXBuildFile; fileRef = 66A28EAF24CAF1B500410A88 /* TestFlight.m */; }; - 7A797FC31B46D54B061D99E5 /* libPods-SelectTokenIntent.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3AB8606AB30216E96A75779E /* libPods-SelectTokenIntent.a */; }; - 8AB133C6A6757CF6A2AA5009 /* libPods-ImageNotification.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 33486EF423B2585D9BBA09F4 /* libPods-ImageNotification.a */; }; - 91C397E1FD7D8F76707B8740 /* libPods-PriceWidgetExtension.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D8779D7AB4A3E9DD8487D527 /* libPods-PriceWidgetExtension.a */; }; + 722CA40E2535AB7E254A42CF /* libPods-SelectTokenIntent.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5AEA6AA218AB3145D55FC87F /* libPods-SelectTokenIntent.a */; }; A4277D9F23CBD1910042BAF4 /* Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = A4277D9E23CBD1910042BAF4 /* Extensions.swift */; }; A4277DA323CFE85F0042BAF4 /* Theme.swift in Sources */ = {isa = PBXBuildFile; fileRef = A4277DA223CFE85F0042BAF4 /* Theme.swift */; }; A4D04BA923D12F99008C1DEC /* Button.swift in Sources */ = {isa = PBXBuildFile; fileRef = A4D04BA823D12F99008C1DEC /* Button.swift */; }; @@ -49,6 +48,7 @@ AA6228F124272F510078BDAA /* SF-Pro-Rounded-Medium.otf in Resources */ = {isa = PBXBuildFile; fileRef = AA6228ED24272B200078BDAA /* SF-Pro-Rounded-Medium.otf */; }; AA6228F224272F510078BDAA /* SF-Pro-Rounded-Regular.otf in Resources */ = {isa = PBXBuildFile; fileRef = AA6228EE24272B200078BDAA /* SF-Pro-Rounded-Regular.otf */; }; AA6228F324272F510078BDAA /* SF-Pro-Rounded-Semibold.otf in Resources */ = {isa = PBXBuildFile; fileRef = AA6228EA24272B200078BDAA /* SF-Pro-Rounded-Semibold.otf */; }; + B1966F3C5FD8C13025CC777F /* libPods-PriceWidgetExtension.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5D4CACE48DAEED3BC05B8AE6 /* libPods-PriceWidgetExtension.a */; }; B50C9AEB2A9D18DC00EB0019 /* adworld@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = B50C9AE92A9D18DC00EB0019 /* adworld@3x.png */; }; B50C9AEC2A9D18DC00EB0019 /* adworld@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = B50C9AEA2A9D18DC00EB0019 /* adworld@2x.png */; }; B52242E628B1B11F0024D19D /* smol@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = B52242E428B1B11F0024D19D /* smol@2x.png */; }; @@ -140,7 +140,6 @@ C9B378BE2C515A860085E5D0 /* Base in Resources */ = {isa = PBXBuildFile; fileRef = C9B378BD2C515A860085E5D0 /* Base */; }; C9B378C22C515A860085E5D0 /* ShareWithRainbow.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = C9B378B82C515A860085E5D0 /* ShareWithRainbow.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; E8D2945956C9619768A8D361 /* ExpoModulesProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43C92E589571C27FFE89AB10 /* ExpoModulesProvider.swift */; }; - E9A0F69C0DB42A80F16CDBD5 /* libPods-Rainbow.a in Frameworks */ = {isa = PBXBuildFile; fileRef = C0DE5565B77A45B108F28413 /* libPods-Rainbow.a */; }; ED2971652150620600B7C4FE /* JavaScriptCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = ED2971642150620600B7C4FE /* JavaScriptCore.framework */; }; /* End PBXBuildFile section */ @@ -234,7 +233,6 @@ 15E531D4242B28EF00797B89 /* UIImageViewWithPersistentAnimations.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIImageViewWithPersistentAnimations.swift; sourceTree = ""; }; 15E531D8242DAB7100797B89 /* NotificationManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = NotificationManager.h; sourceTree = ""; }; 15E531D9242DAB7100797B89 /* NotificationManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = NotificationManager.m; sourceTree = ""; }; - 208F04ABC0ACD249A8EDFA1A /* Pods-ImageNotification.staging.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ImageNotification.staging.xcconfig"; path = "Target Support Files/Pods-ImageNotification/Pods-ImageNotification.staging.xcconfig"; sourceTree = ""; }; 24979E3620F84003007EB0DA /* Protobuf.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Protobuf.framework; path = Frameworks/Protobuf.framework; sourceTree = ""; }; 24979E7420F84004007EB0DA /* FirebaseAnalytics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = FirebaseAnalytics.framework; path = Frameworks/FirebaseAnalytics.framework; sourceTree = ""; }; 24979E7520F84004007EB0DA /* FirebaseCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = FirebaseCore.framework; path = Frameworks/FirebaseCore.framework; sourceTree = ""; }; @@ -247,16 +245,19 @@ 24979E7C20F84004007EB0DA /* FirebaseCoreDiagnostics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = FirebaseCoreDiagnostics.framework; path = Frameworks/FirebaseCoreDiagnostics.framework; sourceTree = ""; }; 24979E7D20F84005007EB0DA /* module.modulemap */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = "sourcecode.module-map"; name = module.modulemap; path = Frameworks/module.modulemap; sourceTree = ""; }; 24979E7E20F84005007EB0DA /* nanopb.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = nanopb.framework; path = Frameworks/nanopb.framework; sourceTree = ""; }; - 2FA1FCE6D3B56B8902BEFC47 /* Pods-SelectTokenIntent.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SelectTokenIntent.release.xcconfig"; path = "Target Support Files/Pods-SelectTokenIntent/Pods-SelectTokenIntent.release.xcconfig"; sourceTree = ""; }; - 33486EF423B2585D9BBA09F4 /* libPods-ImageNotification.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-ImageNotification.a"; sourceTree = BUILT_PRODUCTS_DIR; }; - 390E0879CC9C88D0DBF50690 /* Pods-SelectTokenIntent.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SelectTokenIntent.debug.xcconfig"; path = "Target Support Files/Pods-SelectTokenIntent/Pods-SelectTokenIntent.debug.xcconfig"; sourceTree = ""; }; - 3AB8606AB30216E96A75779E /* libPods-SelectTokenIntent.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-SelectTokenIntent.a"; sourceTree = BUILT_PRODUCTS_DIR; }; + 28A977B84F9AEE8B8145111F /* Pods-SelectTokenIntent.staging.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SelectTokenIntent.staging.xcconfig"; path = "Target Support Files/Pods-SelectTokenIntent/Pods-SelectTokenIntent.staging.xcconfig"; sourceTree = ""; }; + 37CD6BE2DF575F4B683F5BD7 /* Pods-ImageNotification.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ImageNotification.debug.xcconfig"; path = "Target Support Files/Pods-ImageNotification/Pods-ImageNotification.debug.xcconfig"; sourceTree = ""; }; 3C379D5D20FD1F92009AF81F /* Rainbow.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; name = Rainbow.entitlements; path = Rainbow/Rainbow.entitlements; sourceTree = ""; }; 3CBE29CB2381E43800BE05AC /* Rainbow-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Rainbow-Bridging-Header.h"; sourceTree = ""; }; 43C92E589571C27FFE89AB10 /* ExpoModulesProvider.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ExpoModulesProvider.swift; path = "Pods/Target Support Files/Pods-Rainbow/ExpoModulesProvider.swift"; sourceTree = ""; }; + 497293F5BEE93B0A096E5C56 /* Pods-ImageNotification.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ImageNotification.release.xcconfig"; path = "Target Support Files/Pods-ImageNotification/Pods-ImageNotification.release.xcconfig"; sourceTree = ""; }; + 4CA6FC1DE5EB5ED82E7E1F54 /* Pods-Rainbow.localrelease.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Rainbow.localrelease.xcconfig"; path = "Target Support Files/Pods-Rainbow/Pods-Rainbow.localrelease.xcconfig"; sourceTree = ""; }; 4D098C2D2811A979006A801A /* RNStartTime.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RNStartTime.h; sourceTree = ""; }; 4D098C2E2811A9A5006A801A /* RNStartTime.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNStartTime.m; sourceTree = ""; }; - 59D20A56C5C8F6DD51C60C16 /* Pods-Rainbow.localrelease.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Rainbow.localrelease.xcconfig"; path = "Target Support Files/Pods-Rainbow/Pods-Rainbow.localrelease.xcconfig"; sourceTree = ""; }; + 4F41B555E9F2BDC11F67C4B5 /* Pods-PriceWidgetExtension.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-PriceWidgetExtension.debug.xcconfig"; path = "Target Support Files/Pods-PriceWidgetExtension/Pods-PriceWidgetExtension.debug.xcconfig"; sourceTree = ""; }; + 556FE6D2BA19BF19B2185138 /* libPods-Rainbow.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Rainbow.a"; sourceTree = BUILT_PRODUCTS_DIR; }; + 5AEA6AA218AB3145D55FC87F /* libPods-SelectTokenIntent.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-SelectTokenIntent.a"; sourceTree = BUILT_PRODUCTS_DIR; }; + 5D4CACE48DAEED3BC05B8AE6 /* libPods-PriceWidgetExtension.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-PriceWidgetExtension.a"; sourceTree = BUILT_PRODUCTS_DIR; }; 6630540824A38A1900E5B030 /* RainbowText.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RainbowText.m; sourceTree = ""; }; 6635730524939991006ACFA6 /* SafeStoreReview.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SafeStoreReview.m; sourceTree = ""; }; 664612EC2748489B00B43F5A /* PriceWidgetExtension.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = PriceWidgetExtension.entitlements; sourceTree = ""; }; @@ -272,17 +273,18 @@ 66A1FEBB24ACBBE600C3F539 /* RNCMPortal.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = RNCMPortal.m; path = "../src/react-native-cool-modals/ios/RNCMPortal.m"; sourceTree = ""; }; 66A28EAF24CAF1B500410A88 /* TestFlight.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = TestFlight.m; sourceTree = ""; }; 66A29CCA2511074500481F4A /* ReaHeader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ReaHeader.h; sourceTree = SOURCE_ROOT; }; - 71C4AACC71462B12A43FDDE5 /* Pods-PriceWidgetExtension.localrelease.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-PriceWidgetExtension.localrelease.xcconfig"; path = "Target Support Files/Pods-PriceWidgetExtension/Pods-PriceWidgetExtension.localrelease.xcconfig"; sourceTree = ""; }; + 732C3F4923CF572688475536 /* Pods-SelectTokenIntent.localrelease.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SelectTokenIntent.localrelease.xcconfig"; path = "Target Support Files/Pods-SelectTokenIntent/Pods-SelectTokenIntent.localrelease.xcconfig"; sourceTree = ""; }; + 86D738C44C2C571736190D2D /* Pods-Rainbow.staging.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Rainbow.staging.xcconfig"; path = "Target Support Files/Pods-Rainbow/Pods-Rainbow.staging.xcconfig"; sourceTree = ""; }; + 9092BB627D60D1C7E65EAD39 /* Pods-PriceWidgetExtension.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-PriceWidgetExtension.release.xcconfig"; path = "Target Support Files/Pods-PriceWidgetExtension/Pods-PriceWidgetExtension.release.xcconfig"; sourceTree = ""; }; + 928D80AC880326A5C93E8682 /* Pods-SelectTokenIntent.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SelectTokenIntent.release.xcconfig"; path = "Target Support Files/Pods-SelectTokenIntent/Pods-SelectTokenIntent.release.xcconfig"; sourceTree = ""; }; + 9787D6F106B2967888575DF6 /* Pods-SelectTokenIntent.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SelectTokenIntent.debug.xcconfig"; path = "Target Support Files/Pods-SelectTokenIntent/Pods-SelectTokenIntent.debug.xcconfig"; sourceTree = ""; }; 98AED33BAB4247CEBEF8464D /* libz.tbd */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libz.tbd; path = usr/lib/libz.tbd; sourceTree = SDKROOT; }; 9DEADFA4826D4D0BAA950D21 /* libRNFIRMessaging.a */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = archive.ar; path = libRNFIRMessaging.a; sourceTree = ""; }; - 9E8BEFB6422BEB906DEB3C7E /* Pods-SelectTokenIntent.staging.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SelectTokenIntent.staging.xcconfig"; path = "Target Support Files/Pods-SelectTokenIntent/Pods-SelectTokenIntent.staging.xcconfig"; sourceTree = ""; }; - A0B1D87220C90A9004D035C7 /* Pods-PriceWidgetExtension.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-PriceWidgetExtension.release.xcconfig"; path = "Target Support Files/Pods-PriceWidgetExtension/Pods-PriceWidgetExtension.release.xcconfig"; sourceTree = ""; }; + A019C130957DC7A038F8059E /* Pods-Rainbow.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Rainbow.debug.xcconfig"; path = "Target Support Files/Pods-Rainbow/Pods-Rainbow.debug.xcconfig"; sourceTree = ""; }; A4277D9E23CBD1910042BAF4 /* Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Extensions.swift; sourceTree = ""; }; A4277DA223CFE85F0042BAF4 /* Theme.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Theme.swift; sourceTree = ""; }; A4D04BA823D12F99008C1DEC /* Button.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Button.swift; sourceTree = ""; }; A4D04BAB23D12FD5008C1DEC /* ButtonManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ButtonManager.m; sourceTree = ""; }; - A5ACEBEDC5DFEC3A33504769 /* Pods-ImageNotification.localrelease.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ImageNotification.localrelease.xcconfig"; path = "Target Support Files/Pods-ImageNotification/Pods-ImageNotification.localrelease.xcconfig"; sourceTree = ""; }; - A6402205793DFA897132D7A9 /* Pods-ImageNotification.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ImageNotification.release.xcconfig"; path = "Target Support Files/Pods-ImageNotification/Pods-ImageNotification.release.xcconfig"; sourceTree = ""; }; AA0B1CB82B00C5E100EAF77D /* SF-Mono-Semibold.otf */ = {isa = PBXFileReference; lastKnownFileType = file; name = "SF-Mono-Semibold.otf"; path = "../src/assets/fonts/SF-Mono-Semibold.otf"; sourceTree = ""; }; AA0B1CB92B00C5E100EAF77D /* SF-Mono-Bold.otf */ = {isa = PBXFileReference; lastKnownFileType = file; name = "SF-Mono-Bold.otf"; path = "../src/assets/fonts/SF-Mono-Bold.otf"; sourceTree = ""; }; AA0B1CBA2B00C5E100EAF77D /* SF-Pro-Rounded-Black.otf */ = {isa = PBXFileReference; lastKnownFileType = file; name = "SF-Pro-Rounded-Black.otf"; path = "../src/assets/fonts/SF-Pro-Rounded-Black.otf"; sourceTree = ""; }; @@ -293,6 +295,7 @@ AA6228EE24272B200078BDAA /* SF-Pro-Rounded-Regular.otf */ = {isa = PBXFileReference; lastKnownFileType = file; name = "SF-Pro-Rounded-Regular.otf"; path = "../src/assets/fonts/SF-Pro-Rounded-Regular.otf"; sourceTree = ""; }; AAA0EF342BF5A4AD00A19A53 /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = PrivacyInfo.xcprivacy; sourceTree = ""; }; B0C692B061D7430D8194DC98 /* ToolTipMenuTests.xctest */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = wrapper.cfbundle; path = ToolTipMenuTests.xctest; sourceTree = ""; }; + B3A1BB88E4834A09CEE6A23C /* Pods-ImageNotification.staging.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ImageNotification.staging.xcconfig"; path = "Target Support Files/Pods-ImageNotification/Pods-ImageNotification.staging.xcconfig"; sourceTree = ""; }; B50C9AE92A9D18DC00EB0019 /* adworld@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "adworld@3x.png"; sourceTree = ""; }; B50C9AEA2A9D18DC00EB0019 /* adworld@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "adworld@2x.png"; sourceTree = ""; }; B52242E428B1B11F0024D19D /* smol@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "smol@2x.png"; sourceTree = ""; }; @@ -313,10 +316,8 @@ B5CE8FFD29A5758100EB1EFA /* pooly@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "pooly@3x.png"; sourceTree = ""; }; B5D7F2EE29E8D41D003D6A54 /* finiliar@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "finiliar@3x.png"; sourceTree = ""; }; B5D7F2EF29E8D41E003D6A54 /* finiliar@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "finiliar@2x.png"; sourceTree = ""; }; - B726AE9AC9612098B9AE1E8C /* Pods-Rainbow.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Rainbow.release.xcconfig"; path = "Target Support Files/Pods-Rainbow/Pods-Rainbow.release.xcconfig"; sourceTree = ""; }; - B72F672E1C1931C1EFA69240 /* Pods-Rainbow.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Rainbow.debug.xcconfig"; path = "Target Support Files/Pods-Rainbow/Pods-Rainbow.debug.xcconfig"; sourceTree = ""; }; + BF5C675494B8453FBFF6274D /* libPods-ImageNotification.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-ImageNotification.a"; sourceTree = BUILT_PRODUCTS_DIR; }; C04D10EF25AFC8C1003BEF7A /* Extras.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = Extras.json; sourceTree = ""; }; - C0DE5565B77A45B108F28413 /* libPods-Rainbow.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Rainbow.a"; sourceTree = BUILT_PRODUCTS_DIR; }; C11640E7274DC10B00C9120A /* UIColor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIColor.swift; sourceTree = ""; }; C1272389274EBBB6006AC743 /* CurrencyDetails.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CurrencyDetails.swift; sourceTree = ""; }; C151287D2739F676006517AB /* IconProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IconProvider.swift; sourceTree = ""; }; @@ -355,15 +356,13 @@ C9B378BA2C515A860085E5D0 /* ShareViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShareViewController.swift; sourceTree = ""; }; C9B378BD2C515A860085E5D0 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/MainInterface.storyboard; sourceTree = ""; }; C9B378BF2C515A860085E5D0 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - CE6C46FE0C9D0C9504C025AC /* Pods-ImageNotification.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ImageNotification.debug.xcconfig"; path = "Target Support Files/Pods-ImageNotification/Pods-ImageNotification.debug.xcconfig"; sourceTree = ""; }; D755E71324B04FEE9C691D14 /* libRNFirebase.a */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = archive.ar; path = libRNFirebase.a; sourceTree = ""; }; - D8779D7AB4A3E9DD8487D527 /* libPods-PriceWidgetExtension.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-PriceWidgetExtension.a"; sourceTree = BUILT_PRODUCTS_DIR; }; - D8FA6FF97E16AF1841C65403 /* Pods-PriceWidgetExtension.staging.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-PriceWidgetExtension.staging.xcconfig"; path = "Target Support Files/Pods-PriceWidgetExtension/Pods-PriceWidgetExtension.staging.xcconfig"; sourceTree = ""; }; - DF978C7B693121BE46F2053C /* Pods-Rainbow.staging.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Rainbow.staging.xcconfig"; path = "Target Support Files/Pods-Rainbow/Pods-Rainbow.staging.xcconfig"; sourceTree = ""; }; + D8909C8CDF72D43F8537B004 /* Pods-PriceWidgetExtension.staging.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-PriceWidgetExtension.staging.xcconfig"; path = "Target Support Files/Pods-PriceWidgetExtension/Pods-PriceWidgetExtension.staging.xcconfig"; sourceTree = ""; }; + DE432693F1E564C16827671F /* Pods-Rainbow.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Rainbow.release.xcconfig"; path = "Target Support Files/Pods-Rainbow/Pods-Rainbow.release.xcconfig"; sourceTree = ""; }; ED297162215061F000B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; }; ED2971642150620600B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = Platforms/AppleTVOS.platform/Developer/SDKs/AppleTVOS12.0.sdk/System/Library/Frameworks/JavaScriptCore.framework; sourceTree = DEVELOPER_DIR; }; - EEDFB87C7DC0A55503B643C5 /* Pods-PriceWidgetExtension.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-PriceWidgetExtension.debug.xcconfig"; path = "Target Support Files/Pods-PriceWidgetExtension/Pods-PriceWidgetExtension.debug.xcconfig"; sourceTree = ""; }; - FD9E17465EF9D8CDA62027EE /* Pods-SelectTokenIntent.localrelease.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SelectTokenIntent.localrelease.xcconfig"; path = "Target Support Files/Pods-SelectTokenIntent/Pods-SelectTokenIntent.localrelease.xcconfig"; sourceTree = ""; }; + F265EA2D4A622F9E493BCA9A /* Pods-ImageNotification.localrelease.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ImageNotification.localrelease.xcconfig"; path = "Target Support Files/Pods-ImageNotification/Pods-ImageNotification.localrelease.xcconfig"; sourceTree = ""; }; + FC4825CCDBA2CACA5A469C41 /* Pods-PriceWidgetExtension.localrelease.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-PriceWidgetExtension.localrelease.xcconfig"; path = "Target Support Files/Pods-PriceWidgetExtension/Pods-PriceWidgetExtension.localrelease.xcconfig"; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -371,7 +370,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 8AB133C6A6757CF6A2AA5009 /* libPods-ImageNotification.a in Frameworks */, + 35F6F98CBC0BF1DA6049CF57 /* libPods-ImageNotification.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -381,7 +380,7 @@ files = ( ED2971652150620600B7C4FE /* JavaScriptCore.framework in Frameworks */, C72F456C99A646399192517D /* libz.tbd in Frameworks */, - E9A0F69C0DB42A80F16CDBD5 /* libPods-Rainbow.a in Frameworks */, + 2D28BB8F1ECF8D127306A3F1 /* libPods-Rainbow.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -391,7 +390,7 @@ files = ( C16DCF60272BA6EF00FF5C78 /* SwiftUI.framework in Frameworks */, C16DCF5E272BA6EF00FF5C78 /* WidgetKit.framework in Frameworks */, - 91C397E1FD7D8F76707B8740 /* libPods-PriceWidgetExtension.a in Frameworks */, + B1966F3C5FD8C13025CC777F /* libPods-PriceWidgetExtension.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -400,7 +399,7 @@ buildActionMask = 2147483647; files = ( C16DCF81272BAB9500FF5C78 /* Intents.framework in Frameworks */, - 7A797FC31B46D54B061D99E5 /* libPods-SelectTokenIntent.a in Frameworks */, + 722CA40E2535AB7E254A42CF /* libPods-SelectTokenIntent.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -577,10 +576,10 @@ C16DCF80272BAB9500FF5C78 /* Intents.framework */, C16DCF8B272BAB9600FF5C78 /* IntentsUI.framework */, C9B378A12C5159880085E5D0 /* UniformTypeIdentifiers.framework */, - 33486EF423B2585D9BBA09F4 /* libPods-ImageNotification.a */, - D8779D7AB4A3E9DD8487D527 /* libPods-PriceWidgetExtension.a */, - C0DE5565B77A45B108F28413 /* libPods-Rainbow.a */, - 3AB8606AB30216E96A75779E /* libPods-SelectTokenIntent.a */, + BF5C675494B8453FBFF6274D /* libPods-ImageNotification.a */, + 5D4CACE48DAEED3BC05B8AE6 /* libPods-PriceWidgetExtension.a */, + 556FE6D2BA19BF19B2185138 /* libPods-Rainbow.a */, + 5AEA6AA218AB3145D55FC87F /* libPods-SelectTokenIntent.a */, ); name = Frameworks; sourceTree = ""; @@ -744,22 +743,22 @@ C640359C0E6575CE0A7ECD73 /* Pods */ = { isa = PBXGroup; children = ( - CE6C46FE0C9D0C9504C025AC /* Pods-ImageNotification.debug.xcconfig */, - A6402205793DFA897132D7A9 /* Pods-ImageNotification.release.xcconfig */, - A5ACEBEDC5DFEC3A33504769 /* Pods-ImageNotification.localrelease.xcconfig */, - 208F04ABC0ACD249A8EDFA1A /* Pods-ImageNotification.staging.xcconfig */, - EEDFB87C7DC0A55503B643C5 /* Pods-PriceWidgetExtension.debug.xcconfig */, - A0B1D87220C90A9004D035C7 /* Pods-PriceWidgetExtension.release.xcconfig */, - 71C4AACC71462B12A43FDDE5 /* Pods-PriceWidgetExtension.localrelease.xcconfig */, - D8FA6FF97E16AF1841C65403 /* Pods-PriceWidgetExtension.staging.xcconfig */, - B72F672E1C1931C1EFA69240 /* Pods-Rainbow.debug.xcconfig */, - B726AE9AC9612098B9AE1E8C /* Pods-Rainbow.release.xcconfig */, - 59D20A56C5C8F6DD51C60C16 /* Pods-Rainbow.localrelease.xcconfig */, - DF978C7B693121BE46F2053C /* Pods-Rainbow.staging.xcconfig */, - 390E0879CC9C88D0DBF50690 /* Pods-SelectTokenIntent.debug.xcconfig */, - 2FA1FCE6D3B56B8902BEFC47 /* Pods-SelectTokenIntent.release.xcconfig */, - FD9E17465EF9D8CDA62027EE /* Pods-SelectTokenIntent.localrelease.xcconfig */, - 9E8BEFB6422BEB906DEB3C7E /* Pods-SelectTokenIntent.staging.xcconfig */, + 37CD6BE2DF575F4B683F5BD7 /* Pods-ImageNotification.debug.xcconfig */, + 497293F5BEE93B0A096E5C56 /* Pods-ImageNotification.release.xcconfig */, + F265EA2D4A622F9E493BCA9A /* Pods-ImageNotification.localrelease.xcconfig */, + B3A1BB88E4834A09CEE6A23C /* Pods-ImageNotification.staging.xcconfig */, + 4F41B555E9F2BDC11F67C4B5 /* Pods-PriceWidgetExtension.debug.xcconfig */, + 9092BB627D60D1C7E65EAD39 /* Pods-PriceWidgetExtension.release.xcconfig */, + FC4825CCDBA2CACA5A469C41 /* Pods-PriceWidgetExtension.localrelease.xcconfig */, + D8909C8CDF72D43F8537B004 /* Pods-PriceWidgetExtension.staging.xcconfig */, + A019C130957DC7A038F8059E /* Pods-Rainbow.debug.xcconfig */, + DE432693F1E564C16827671F /* Pods-Rainbow.release.xcconfig */, + 4CA6FC1DE5EB5ED82E7E1F54 /* Pods-Rainbow.localrelease.xcconfig */, + 86D738C44C2C571736190D2D /* Pods-Rainbow.staging.xcconfig */, + 9787D6F106B2967888575DF6 /* Pods-SelectTokenIntent.debug.xcconfig */, + 928D80AC880326A5C93E8682 /* Pods-SelectTokenIntent.release.xcconfig */, + 732C3F4923CF572688475536 /* Pods-SelectTokenIntent.localrelease.xcconfig */, + 28A977B84F9AEE8B8145111F /* Pods-SelectTokenIntent.staging.xcconfig */, ); path = Pods; sourceTree = ""; @@ -815,11 +814,11 @@ isa = PBXNativeTarget; buildConfigurationList = 0299CE842886202800B5C7E7 /* Build configuration list for PBXNativeTarget "ImageNotification" */; buildPhases = ( - 078827AE1BEEEA04DAC20404 /* [CP] Check Pods Manifest.lock */, + A335CA8DADB34A6C700490B1 /* [CP] Check Pods Manifest.lock */, 0299CE732886202800B5C7E7 /* Sources */, 0299CE742886202800B5C7E7 /* Frameworks */, 0299CE752886202800B5C7E7 /* Resources */, - C7D37804C0351A4706E50397 /* [CP] Copy Pods Resources */, + D0878465338E9D74C411A233 /* [CP] Copy Pods Resources */, ); buildRules = ( ); @@ -834,16 +833,16 @@ isa = PBXNativeTarget; buildConfigurationList = 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "Rainbow" */; buildPhases = ( - 605B2B3AD17EEB5D331577A2 /* [CP] Check Pods Manifest.lock */, + CA41397D34D37C4E04486001 /* [CP] Check Pods Manifest.lock */, AEAD56A917FF4051986EE3E6 /* [Expo] Configure project */, 13B07F871A680F5B00A75B9A /* Sources */, 13B07F8C1A680F5B00A75B9A /* Frameworks */, 13B07F8E1A680F5B00A75B9A /* Resources */, 00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */, 668ADB3225A4E3A40050859D /* Embed App Extensions */, - DF087C9CDB1CD1620D06CFDD /* [CP] Embed Pods Frameworks */, - 88311050F78AB0C097772AD8 /* [CP] Copy Pods Resources */, - 44BD1D1BE00D0E7C7327AD89 /* [CP-User] [RNFB] Core Configuration */, + 4861C25B22213AF9D7850D7C /* [CP] Embed Pods Frameworks */, + 27FA39EAC393B792409D4238 /* [CP] Copy Pods Resources */, + 0BB7B26C270F1595DD2B55CA /* [CP-User] [RNFB] Core Configuration */, ); buildRules = ( ); @@ -863,11 +862,11 @@ isa = PBXNativeTarget; buildConfigurationList = C16DCF6E272BA6F100FF5C78 /* Build configuration list for PBXNativeTarget "PriceWidgetExtension" */; buildPhases = ( - 559EA91D42B3296394BED964 /* [CP] Check Pods Manifest.lock */, + 42E8FB19BDC53811720095AA /* [CP] Check Pods Manifest.lock */, C16DCF58272BA6EF00FF5C78 /* Sources */, C16DCF59272BA6EF00FF5C78 /* Frameworks */, C16DCF5A272BA6EF00FF5C78 /* Resources */, - C69A614502B03804F13C83B4 /* [CP] Copy Pods Resources */, + CDE2538FAA43DCC2AC2E0DD2 /* [CP] Copy Pods Resources */, ); buildRules = ( ); @@ -882,11 +881,11 @@ isa = PBXNativeTarget; buildConfigurationList = C16DCF9F272BAB9600FF5C78 /* Build configuration list for PBXNativeTarget "SelectTokenIntent" */; buildPhases = ( - DB9668693166D9CD6F405FF2 /* [CP] Check Pods Manifest.lock */, + 44B37C36592E1F9E0233D347 /* [CP] Check Pods Manifest.lock */, C16DCF7B272BAB9500FF5C78 /* Sources */, C16DCF7C272BAB9500FF5C78 /* Frameworks */, C16DCF7D272BAB9500FF5C78 /* Resources */, - AD4DD19E5F95A8F47FFFFDDE /* [CP] Copy Pods Resources */, + 4887D3B9132AE790C8FB5047 /* [CP] Copy Pods Resources */, ); buildRules = ( ); @@ -943,13 +942,9 @@ TargetAttributes = { 0299CE762886202800B5C7E7 = { CreatedOnToolsVersion = 13.3.1; - DevelopmentTeam = L74NQAQB8H; - ProvisioningStyle = Manual; }; 13B07F861A680F5B00A75B9A = { - DevelopmentTeam = L74NQAQB8H; LastSwiftMigration = 1120; - ProvisioningStyle = Manual; SystemCapabilities = { com.apple.Push = { enabled = 1; @@ -961,23 +956,15 @@ }; C16DCF5B272BA6EF00FF5C78 = { CreatedOnToolsVersion = 12.5.1; - DevelopmentTeam = L74NQAQB8H; - ProvisioningStyle = Manual; }; C16DCF7E272BAB9500FF5C78 = { CreatedOnToolsVersion = 12.5.1; - DevelopmentTeam = L74NQAQB8H; - ProvisioningStyle = Manual; }; C9B3789F2C5159880085E5D0 = { CreatedOnToolsVersion = 15.4; - DevelopmentTeam = L74NQAQB8H; - ProvisioningStyle = Manual; }; C9B378B72C515A860085E5D0 = { CreatedOnToolsVersion = 15.4; - DevelopmentTeam = L74NQAQB8H; - ProvisioningStyle = Manual; }; }; }; @@ -1117,29 +1104,7 @@ shellScript = "if [[ -f \"$PODS_ROOT/../.xcode.env\" ]]; then\n source \"$PODS_ROOT/../.xcode.env\"\nfi\nif [[ -f \"$PODS_ROOT/../.xcode.env.local\" ]]; then\n source \"$PODS_ROOT/../.xcode.env.local\"\nfi\n\n# The project root by default is one level up from the ios directory\nexport PROJECT_ROOT=\"$PROJECT_DIR\"/..\n\nif [[ \"$CONFIGURATION\" = *Debug* ]]; then\n export SKIP_BUNDLING=1\nfi\nif [[ -z \"$ENTRY_FILE\" ]]; then\n # Set the entry JS file using the bundler's entry resolution.\n export ENTRY_FILE=\"$(\"$NODE_BINARY\" -e \"require('expo/scripts/resolveAppEntry')\" \"$PROJECT_ROOT\" ios absolute | tail -n 1)\"\nfi\n\nif [[ -z \"$CLI_PATH\" ]]; then\n # Use Expo CLI\n export CLI_PATH=\"$(\"$NODE_BINARY\" --print \"require.resolve('@expo/cli')\")\"\nfi\nif [[ -z \"$BUNDLE_COMMAND\" ]]; then\n # Default Expo CLI command for bundling\n export BUNDLE_COMMAND=\"export:embed\"\nfi\n\n`\"$NODE_BINARY\" --print \"require('path').dirname(require.resolve('react-native/package.json')) + '/scripts/react-native-xcode.sh'\"`\n"; showEnvVarsInLog = 0; }; - 078827AE1BEEEA04DAC20404 /* [CP] Check Pods Manifest.lock */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - ); - inputPaths = ( - "${PODS_PODFILE_DIR_PATH}/Podfile.lock", - "${PODS_ROOT}/Manifest.lock", - ); - name = "[CP] Check Pods Manifest.lock"; - outputFileListPaths = ( - ); - outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-ImageNotification-checkManifestLockResult.txt", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; - showEnvVarsInLog = 0; - }; - 44BD1D1BE00D0E7C7327AD89 /* [CP-User] [RNFB] Core Configuration */ = { + 0BB7B26C270F1595DD2B55CA /* [CP-User] [RNFB] Core Configuration */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( @@ -1152,51 +1117,7 @@ shellPath = /bin/sh; shellScript = "#!/usr/bin/env bash\n#\n# Copyright (c) 2016-present Invertase Limited & Contributors\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this library except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\n\n##########################################################################\n##########################################################################\n#\n# NOTE THAT IF YOU CHANGE THIS FILE YOU MUST RUN pod install AFTERWARDS\n#\n# This file is installed as an Xcode build script in the project file\n# by cocoapods, and you will not see your changes until you pod install\n#\n##########################################################################\n##########################################################################\n\nset -e\n\n_MAX_LOOKUPS=2;\n_SEARCH_RESULT=''\n_RN_ROOT_EXISTS=''\n_CURRENT_LOOKUPS=1\n_JSON_ROOT=\"'react-native'\"\n_JSON_FILE_NAME='firebase.json'\n_JSON_OUTPUT_BASE64='e30=' # { }\n_CURRENT_SEARCH_DIR=${PROJECT_DIR}\n_PLIST_BUDDY=/usr/libexec/PlistBuddy\n_TARGET_PLIST=\"${BUILT_PRODUCTS_DIR}/${INFOPLIST_PATH}\"\n_DSYM_PLIST=\"${DWARF_DSYM_FOLDER_PATH}/${DWARF_DSYM_FILE_NAME}/Contents/Info.plist\"\n\n# plist arrays\n_PLIST_ENTRY_KEYS=()\n_PLIST_ENTRY_TYPES=()\n_PLIST_ENTRY_VALUES=()\n\nfunction setPlistValue {\n echo \"info: setting plist entry '$1' of type '$2' in file '$4'\"\n ${_PLIST_BUDDY} -c \"Add :$1 $2 '$3'\" $4 || echo \"info: '$1' already exists\"\n}\n\nfunction getFirebaseJsonKeyValue () {\n if [[ ${_RN_ROOT_EXISTS} ]]; then\n ruby -Ku -e \"require 'rubygems';require 'json'; output=JSON.parse('$1'); puts output[$_JSON_ROOT]['$2']\"\n else\n echo \"\"\n fi;\n}\n\nfunction jsonBoolToYesNo () {\n if [[ $1 == \"false\" ]]; then\n echo \"NO\"\n elif [[ $1 == \"true\" ]]; then\n echo \"YES\"\n else echo \"NO\"\n fi\n}\n\necho \"info: -> RNFB build script started\"\necho \"info: 1) Locating ${_JSON_FILE_NAME} file:\"\n\nif [[ -z ${_CURRENT_SEARCH_DIR} ]]; then\n _CURRENT_SEARCH_DIR=$(pwd)\nfi;\n\nwhile true; do\n _CURRENT_SEARCH_DIR=$(dirname \"$_CURRENT_SEARCH_DIR\")\n if [[ \"$_CURRENT_SEARCH_DIR\" == \"/\" ]] || [[ ${_CURRENT_LOOKUPS} -gt ${_MAX_LOOKUPS} ]]; then break; fi;\n echo \"info: ($_CURRENT_LOOKUPS of $_MAX_LOOKUPS) Searching in '$_CURRENT_SEARCH_DIR' for a ${_JSON_FILE_NAME} file.\"\n _SEARCH_RESULT=$(find \"$_CURRENT_SEARCH_DIR\" -maxdepth 2 -name ${_JSON_FILE_NAME} -print | /usr/bin/head -n 1)\n if [[ ${_SEARCH_RESULT} ]]; then\n echo \"info: ${_JSON_FILE_NAME} found at $_SEARCH_RESULT\"\n break;\n fi;\n _CURRENT_LOOKUPS=$((_CURRENT_LOOKUPS+1))\ndone\n\nif [[ ${_SEARCH_RESULT} ]]; then\n _JSON_OUTPUT_RAW=$(cat \"${_SEARCH_RESULT}\")\n _RN_ROOT_EXISTS=$(ruby -Ku -e \"require 'rubygems';require 'json'; output=JSON.parse('$_JSON_OUTPUT_RAW'); puts output[$_JSON_ROOT]\" || echo '')\n\n if [[ ${_RN_ROOT_EXISTS} ]]; then\n if ! python3 --version >/dev/null 2>&1; then echo \"python3 not found, firebase.json file processing error.\" && exit 1; fi\n _JSON_OUTPUT_BASE64=$(python3 -c 'import json,sys,base64;print(base64.b64encode(bytes(json.dumps(json.loads(open('\"'${_SEARCH_RESULT}'\"', '\"'rb'\"').read())['${_JSON_ROOT}']), '\"'utf-8'\"')).decode())' || echo \"e30=\")\n fi\n\n _PLIST_ENTRY_KEYS+=(\"firebase_json_raw\")\n _PLIST_ENTRY_TYPES+=(\"string\")\n _PLIST_ENTRY_VALUES+=(\"$_JSON_OUTPUT_BASE64\")\n\n # config.app_data_collection_default_enabled\n _APP_DATA_COLLECTION_ENABLED=$(getFirebaseJsonKeyValue \"$_JSON_OUTPUT_RAW\" \"app_data_collection_default_enabled\")\n if [[ $_APP_DATA_COLLECTION_ENABLED ]]; then\n _PLIST_ENTRY_KEYS+=(\"FirebaseDataCollectionDefaultEnabled\")\n _PLIST_ENTRY_TYPES+=(\"bool\")\n _PLIST_ENTRY_VALUES+=(\"$(jsonBoolToYesNo \"$_APP_DATA_COLLECTION_ENABLED\")\")\n fi\n\n # config.analytics_auto_collection_enabled\n _ANALYTICS_AUTO_COLLECTION=$(getFirebaseJsonKeyValue \"$_JSON_OUTPUT_RAW\" \"analytics_auto_collection_enabled\")\n if [[ $_ANALYTICS_AUTO_COLLECTION ]]; then\n _PLIST_ENTRY_KEYS+=(\"FIREBASE_ANALYTICS_COLLECTION_ENABLED\")\n _PLIST_ENTRY_TYPES+=(\"bool\")\n _PLIST_ENTRY_VALUES+=(\"$(jsonBoolToYesNo \"$_ANALYTICS_AUTO_COLLECTION\")\")\n fi\n\n # config.analytics_collection_deactivated\n _ANALYTICS_DEACTIVATED=$(getFirebaseJsonKeyValue \"$_JSON_OUTPUT_RAW\" \"analytics_collection_deactivated\")\n if [[ $_ANALYTICS_DEACTIVATED ]]; then\n _PLIST_ENTRY_KEYS+=(\"FIREBASE_ANALYTICS_COLLECTION_DEACTIVATED\")\n _PLIST_ENTRY_TYPES+=(\"bool\")\n _PLIST_ENTRY_VALUES+=(\"$(jsonBoolToYesNo \"$_ANALYTICS_DEACTIVATED\")\")\n fi\n\n # config.analytics_idfv_collection_enabled\n _ANALYTICS_IDFV_COLLECTION=$(getFirebaseJsonKeyValue \"$_JSON_OUTPUT_RAW\" \"analytics_idfv_collection_enabled\")\n if [[ $_ANALYTICS_IDFV_COLLECTION ]]; then\n _PLIST_ENTRY_KEYS+=(\"GOOGLE_ANALYTICS_IDFV_COLLECTION_ENABLED\")\n _PLIST_ENTRY_TYPES+=(\"bool\")\n _PLIST_ENTRY_VALUES+=(\"$(jsonBoolToYesNo \"$_ANALYTICS_IDFV_COLLECTION\")\")\n fi\n\n # config.analytics_default_allow_analytics_storage\n _ANALYTICS_STORAGE=$(getFirebaseJsonKeyValue \"$_JSON_OUTPUT_RAW\" \"analytics_default_allow_analytics_storage\")\n if [[ $_ANALYTICS_STORAGE ]]; then\n _PLIST_ENTRY_KEYS+=(\"GOOGLE_ANALYTICS_DEFAULT_ALLOW_ANALYTICS_STORAGE\")\n _PLIST_ENTRY_TYPES+=(\"bool\")\n _PLIST_ENTRY_VALUES+=(\"$(jsonBoolToYesNo \"$_ANALYTICS_STORAGE\")\")\n fi\n\n # config.analytics_default_allow_ad_storage\n _ANALYTICS_AD_STORAGE=$(getFirebaseJsonKeyValue \"$_JSON_OUTPUT_RAW\" \"analytics_default_allow_ad_storage\")\n if [[ $_ANALYTICS_AD_STORAGE ]]; then\n _PLIST_ENTRY_KEYS+=(\"GOOGLE_ANALYTICS_DEFAULT_ALLOW_AD_STORAGE\")\n _PLIST_ENTRY_TYPES+=(\"bool\")\n _PLIST_ENTRY_VALUES+=(\"$(jsonBoolToYesNo \"$_ANALYTICS_AD_STORAGE\")\")\n fi\n\n # config.analytics_default_allow_ad_user_data\n _ANALYTICS_AD_USER_DATA=$(getFirebaseJsonKeyValue \"$_JSON_OUTPUT_RAW\" \"analytics_default_allow_ad_user_data\")\n if [[ $_ANALYTICS_AD_USER_DATA ]]; then\n _PLIST_ENTRY_KEYS+=(\"GOOGLE_ANALYTICS_DEFAULT_ALLOW_AD_USER_DATA\")\n _PLIST_ENTRY_TYPES+=(\"bool\")\n _PLIST_ENTRY_VALUES+=(\"$(jsonBoolToYesNo \"$_ANALYTICS_AD_USER_DATA\")\")\n fi\n\n # config.analytics_default_allow_ad_personalization_signals\n _ANALYTICS_PERSONALIZATION=$(getFirebaseJsonKeyValue \"$_JSON_OUTPUT_RAW\" \"analytics_default_allow_ad_personalization_signals\")\n if [[ $_ANALYTICS_PERSONALIZATION ]]; then\n _PLIST_ENTRY_KEYS+=(\"GOOGLE_ANALYTICS_DEFAULT_ALLOW_AD_PERSONALIZATION_SIGNALS\")\n _PLIST_ENTRY_TYPES+=(\"bool\")\n _PLIST_ENTRY_VALUES+=(\"$(jsonBoolToYesNo \"$_ANALYTICS_PERSONALIZATION\")\")\n fi\n\n # config.analytics_registration_with_ad_network_enabled\n _ANALYTICS_REGISTRATION_WITH_AD_NETWORK=$(getFirebaseJsonKeyValue \"$_JSON_OUTPUT_RAW\" \"google_analytics_registration_with_ad_network_enabled\")\n if [[ $_ANALYTICS_REGISTRATION_WITH_AD_NETWORK ]]; then\n _PLIST_ENTRY_KEYS+=(\"GOOGLE_ANALYTICS_REGISTRATION_WITH_AD_NETWORK_ENABLED\")\n _PLIST_ENTRY_TYPES+=(\"bool\")\n _PLIST_ENTRY_VALUES+=(\"$(jsonBoolToYesNo \"$_ANALYTICS_REGISTRATION_WITH_AD_NETWORK\")\")\n fi\n\n # config.google_analytics_automatic_screen_reporting_enabled\n _ANALYTICS_AUTO_SCREEN_REPORTING=$(getFirebaseJsonKeyValue \"$_JSON_OUTPUT_RAW\" \"google_analytics_automatic_screen_reporting_enabled\")\n if [[ $_ANALYTICS_AUTO_SCREEN_REPORTING ]]; then\n _PLIST_ENTRY_KEYS+=(\"FirebaseAutomaticScreenReportingEnabled\")\n _PLIST_ENTRY_TYPES+=(\"bool\")\n _PLIST_ENTRY_VALUES+=(\"$(jsonBoolToYesNo \"$_ANALYTICS_AUTO_SCREEN_REPORTING\")\")\n fi\n\n # config.perf_auto_collection_enabled\n _PERF_AUTO_COLLECTION=$(getFirebaseJsonKeyValue \"$_JSON_OUTPUT_RAW\" \"perf_auto_collection_enabled\")\n if [[ $_PERF_AUTO_COLLECTION ]]; then\n _PLIST_ENTRY_KEYS+=(\"firebase_performance_collection_enabled\")\n _PLIST_ENTRY_TYPES+=(\"bool\")\n _PLIST_ENTRY_VALUES+=(\"$(jsonBoolToYesNo \"$_PERF_AUTO_COLLECTION\")\")\n fi\n\n # config.perf_collection_deactivated\n _PERF_DEACTIVATED=$(getFirebaseJsonKeyValue \"$_JSON_OUTPUT_RAW\" \"perf_collection_deactivated\")\n if [[ $_PERF_DEACTIVATED ]]; then\n _PLIST_ENTRY_KEYS+=(\"firebase_performance_collection_deactivated\")\n _PLIST_ENTRY_TYPES+=(\"bool\")\n _PLIST_ENTRY_VALUES+=(\"$(jsonBoolToYesNo \"$_PERF_DEACTIVATED\")\")\n fi\n\n # config.messaging_auto_init_enabled\n _MESSAGING_AUTO_INIT=$(getFirebaseJsonKeyValue \"$_JSON_OUTPUT_RAW\" \"messaging_auto_init_enabled\")\n if [[ $_MESSAGING_AUTO_INIT ]]; then\n _PLIST_ENTRY_KEYS+=(\"FirebaseMessagingAutoInitEnabled\")\n _PLIST_ENTRY_TYPES+=(\"bool\")\n _PLIST_ENTRY_VALUES+=(\"$(jsonBoolToYesNo \"$_MESSAGING_AUTO_INIT\")\")\n fi\n\n # config.in_app_messaging_auto_colllection_enabled\n _FIAM_AUTO_INIT=$(getFirebaseJsonKeyValue \"$_JSON_OUTPUT_RAW\" \"in_app_messaging_auto_collection_enabled\")\n if [[ $_FIAM_AUTO_INIT ]]; then\n _PLIST_ENTRY_KEYS+=(\"FirebaseInAppMessagingAutomaticDataCollectionEnabled\")\n _PLIST_ENTRY_TYPES+=(\"bool\")\n _PLIST_ENTRY_VALUES+=(\"$(jsonBoolToYesNo \"$_FIAM_AUTO_INIT\")\")\n fi\n\n # config.app_check_token_auto_refresh\n _APP_CHECK_TOKEN_AUTO_REFRESH=$(getFirebaseJsonKeyValue \"$_JSON_OUTPUT_RAW\" \"app_check_token_auto_refresh\")\n if [[ $_APP_CHECK_TOKEN_AUTO_REFRESH ]]; then\n _PLIST_ENTRY_KEYS+=(\"FirebaseAppCheckTokenAutoRefreshEnabled\")\n _PLIST_ENTRY_TYPES+=(\"bool\")\n _PLIST_ENTRY_VALUES+=(\"$(jsonBoolToYesNo \"$_APP_CHECK_TOKEN_AUTO_REFRESH\")\")\n fi\n\n # config.crashlytics_disable_auto_disabler - undocumented for now - mainly for debugging, document if becomes useful\n _CRASHLYTICS_AUTO_DISABLE_ENABLED=$(getFirebaseJsonKeyValue \"$_JSON_OUTPUT_RAW\" \"crashlytics_disable_auto_disabler\")\n if [[ $_CRASHLYTICS_AUTO_DISABLE_ENABLED == \"true\" ]]; then\n echo \"Disabled Crashlytics auto disabler.\" # do nothing\n else\n _PLIST_ENTRY_KEYS+=(\"FirebaseCrashlyticsCollectionEnabled\")\n _PLIST_ENTRY_TYPES+=(\"bool\")\n _PLIST_ENTRY_VALUES+=(\"NO\")\n fi\nelse\n _PLIST_ENTRY_KEYS+=(\"firebase_json_raw\")\n _PLIST_ENTRY_TYPES+=(\"string\")\n _PLIST_ENTRY_VALUES+=(\"$_JSON_OUTPUT_BASE64\")\n echo \"warning: A firebase.json file was not found, whilst this file is optional it is recommended to include it to configure firebase services in React Native Firebase.\"\nfi;\n\necho \"info: 2) Injecting Info.plist entries: \"\n\n# Log out the keys we're adding\nfor i in \"${!_PLIST_ENTRY_KEYS[@]}\"; do\n echo \" -> $i) ${_PLIST_ENTRY_KEYS[$i]}\" \"${_PLIST_ENTRY_TYPES[$i]}\" \"${_PLIST_ENTRY_VALUES[$i]}\"\ndone\n\nfor plist in \"${_TARGET_PLIST}\" \"${_DSYM_PLIST}\" ; do\n if [[ -f \"${plist}\" ]]; then\n\n # paths with spaces break the call to setPlistValue. temporarily modify\n # the shell internal field separator variable (IFS), which normally\n # includes spaces, to consist only of line breaks\n oldifs=$IFS\n IFS=\"\n\"\n\n for i in \"${!_PLIST_ENTRY_KEYS[@]}\"; do\n setPlistValue \"${_PLIST_ENTRY_KEYS[$i]}\" \"${_PLIST_ENTRY_TYPES[$i]}\" \"${_PLIST_ENTRY_VALUES[$i]}\" \"${plist}\"\n done\n\n # restore the original internal field separator value\n IFS=$oldifs\n else\n echo \"warning: A Info.plist build output file was not found (${plist})\"\n fi\ndone\n\necho \"info: <- RNFB build script finished\"\n"; }; - 559EA91D42B3296394BED964 /* [CP] Check Pods Manifest.lock */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - ); - inputPaths = ( - "${PODS_PODFILE_DIR_PATH}/Podfile.lock", - "${PODS_ROOT}/Manifest.lock", - ); - name = "[CP] Check Pods Manifest.lock"; - outputFileListPaths = ( - ); - outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-PriceWidgetExtension-checkManifestLockResult.txt", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; - showEnvVarsInLog = 0; - }; - 605B2B3AD17EEB5D331577A2 /* [CP] Check Pods Manifest.lock */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - ); - inputPaths = ( - "${PODS_PODFILE_DIR_PATH}/Podfile.lock", - "${PODS_ROOT}/Manifest.lock", - ); - name = "[CP] Check Pods Manifest.lock"; - outputFileListPaths = ( - ); - outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-Rainbow-checkManifestLockResult.txt", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; - showEnvVarsInLog = 0; - }; - 88311050F78AB0C097772AD8 /* [CP] Copy Pods Resources */ = { + 27FA39EAC393B792409D4238 /* [CP] Copy Pods Resources */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( @@ -1258,7 +1179,69 @@ shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Rainbow/Pods-Rainbow-resources.sh\"\n"; showEnvVarsInLog = 0; }; - AD4DD19E5F95A8F47FFFFDDE /* [CP] Copy Pods Resources */ = { + 42E8FB19BDC53811720095AA /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-PriceWidgetExtension-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; + 44B37C36592E1F9E0233D347 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-SelectTokenIntent-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; + 4861C25B22213AF9D7850D7C /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Rainbow/Pods-Rainbow-frameworks.sh", + "${PODS_XCFRAMEWORKS_BUILD_DIR}/hermes-engine/Pre-built/hermes.framework/hermes", + ); + name = "[CP] Embed Pods Frameworks"; + outputPaths = ( + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/hermes.framework", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Rainbow/Pods-Rainbow-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; + 4887D3B9132AE790C8FB5047 /* [CP] Copy Pods Resources */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( @@ -1294,6 +1277,28 @@ shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-SelectTokenIntent/Pods-SelectTokenIntent-resources.sh\"\n"; showEnvVarsInLog = 0; }; + A335CA8DADB34A6C700490B1 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-ImageNotification-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; AEAD56A917FF4051986EE3E6 /* [Expo] Configure project */ = { isa = PBXShellScriptBuildPhase; alwaysOutOfDate = 1; @@ -1313,7 +1318,29 @@ shellPath = /bin/sh; shellScript = "# This script configures Expo modules and generates the modules provider file.\nbash -l -c \"./Pods/Target\\ Support\\ Files/Pods-Rainbow/expo-configure-project.sh\"\n"; }; - C69A614502B03804F13C83B4 /* [CP] Copy Pods Resources */ = { + CA41397D34D37C4E04486001 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Rainbow-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; + CDE2538FAA43DCC2AC2E0DD2 /* [CP] Copy Pods Resources */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( @@ -1349,7 +1376,7 @@ shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-PriceWidgetExtension/Pods-PriceWidgetExtension-resources.sh\"\n"; showEnvVarsInLog = 0; }; - C7D37804C0351A4706E50397 /* [CP] Copy Pods Resources */ = { + D0878465338E9D74C411A233 /* [CP] Copy Pods Resources */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( @@ -1387,46 +1414,6 @@ shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-ImageNotification/Pods-ImageNotification-resources.sh\"\n"; showEnvVarsInLog = 0; }; - DB9668693166D9CD6F405FF2 /* [CP] Check Pods Manifest.lock */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - ); - inputPaths = ( - "${PODS_PODFILE_DIR_PATH}/Podfile.lock", - "${PODS_ROOT}/Manifest.lock", - ); - name = "[CP] Check Pods Manifest.lock"; - outputFileListPaths = ( - ); - outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-SelectTokenIntent-checkManifestLockResult.txt", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; - showEnvVarsInLog = 0; - }; - DF087C9CDB1CD1620D06CFDD /* [CP] Embed Pods Frameworks */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-Rainbow/Pods-Rainbow-frameworks.sh", - "${PODS_XCFRAMEWORKS_BUILD_DIR}/hermes-engine/Pre-built/hermes.framework/hermes", - ); - name = "[CP] Embed Pods Frameworks"; - outputPaths = ( - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/hermes.framework", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Rainbow/Pods-Rainbow-frameworks.sh\"\n"; - showEnvVarsInLog = 0; - }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ @@ -1449,7 +1436,6 @@ C18FCD42273C64E10079CE28 /* TokenProvider.swift in Sources */, 13B07FBC1A68108700A75B9A /* AppDelegate.mm in Sources */, C18FCD39273C64C90079CE28 /* TokenData.swift in Sources */, - 6635730624939991006ACFA6 /* SafeStoreReview.m in Sources */, 13B07FC11A68108700A75B9A /* main.m in Sources */, 15E531DA242DAB7100797B89 /* NotificationManager.m in Sources */, 66A1FEB524AB641100C3F539 /* UIViewController+slack.swift in Sources */, @@ -1613,7 +1599,7 @@ /* Begin XCBuildConfiguration section */ 0299CE802886202800B5C7E7 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = CE6C46FE0C9D0C9504C025AC /* Pods-ImageNotification.debug.xcconfig */; + baseConfigurationReference = 37CD6BE2DF575F4B683F5BD7 /* Pods-ImageNotification.debug.xcconfig */; buildSettings = { APPLICATION_EXTENSION_API_ONLY = YES; CLANG_ANALYZER_NONNULL = YES; @@ -1632,8 +1618,8 @@ CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CODE_SIGN_IDENTITY = "iPhone Developer"; - CODE_SIGN_STYLE = Manual; + CODE_SIGN_IDENTITY = "Apple Development"; + CODE_SIGN_STYLE = Automatic; COPY_PHASE_STRIP = NO; CURRENT_PROJECT_VERSION = 1; DEBUG_INFORMATION_FORMAT = dwarf; @@ -1647,14 +1633,18 @@ INFOPLIST_KEY_CFBundleDisplayName = ImageNotification; INFOPLIST_KEY_NSHumanReadableCopyright = "Copyright © 2022 Rainbow. All rights reserved."; IPHONEOS_DEPLOYMENT_TARGET = 15.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@executable_path/../../Frameworks", + ); MARKETING_VERSION = 1.0; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_DEBUG"; PRODUCT_BUNDLE_IDENTIFIER = me.rainbow.ImageNotification; PRODUCT_NAME = "$(TARGET_NAME)"; - PROVISIONING_PROFILE_SPECIFIER = "match Development me.rainbow.ImageNotification"; + PROVISIONING_PROFILE_SPECIFIER = ""; SKIP_INSTALL = YES; SWIFT_EMIT_LOC_STRINGS = YES; SWIFT_PRECOMPILE_BRIDGING_HEADER = NO; @@ -1664,7 +1654,7 @@ }; 0299CE812886202800B5C7E7 /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = A6402205793DFA897132D7A9 /* Pods-ImageNotification.release.xcconfig */; + baseConfigurationReference = 497293F5BEE93B0A096E5C56 /* Pods-ImageNotification.release.xcconfig */; buildSettings = { APPLICATION_EXTENSION_API_ONLY = YES; CLANG_ANALYZER_NONNULL = YES; @@ -1699,7 +1689,11 @@ INFOPLIST_KEY_CFBundleDisplayName = ImageNotification; INFOPLIST_KEY_NSHumanReadableCopyright = "Copyright © 2022 Rainbow. All rights reserved."; IPHONEOS_DEPLOYMENT_TARGET = 15.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@executable_path/../../Frameworks", + ); MARKETING_VERSION = 1.0; MTL_FAST_MATH = YES; OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_RELEASE"; @@ -1716,7 +1710,7 @@ }; 0299CE822886202800B5C7E7 /* LocalRelease */ = { isa = XCBuildConfiguration; - baseConfigurationReference = A5ACEBEDC5DFEC3A33504769 /* Pods-ImageNotification.localrelease.xcconfig */; + baseConfigurationReference = F265EA2D4A622F9E493BCA9A /* Pods-ImageNotification.localrelease.xcconfig */; buildSettings = { APPLICATION_EXTENSION_API_ONLY = YES; CLANG_ANALYZER_NONNULL = YES; @@ -1735,8 +1729,8 @@ CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CODE_SIGN_IDENTITY = "iPhone Developer"; - CODE_SIGN_STYLE = Manual; + CODE_SIGN_IDENTITY = "Apple Development"; + CODE_SIGN_STYLE = Automatic; COPY_PHASE_STRIP = NO; CURRENT_PROJECT_VERSION = 1; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; @@ -1749,13 +1743,17 @@ INFOPLIST_KEY_CFBundleDisplayName = ImageNotification; INFOPLIST_KEY_NSHumanReadableCopyright = "Copyright © 2022 Rainbow. All rights reserved."; IPHONEOS_DEPLOYMENT_TARGET = 15.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@executable_path/../../Frameworks", + ); MARKETING_VERSION = 1.0; MTL_FAST_MATH = YES; OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_RELEASE"; PRODUCT_BUNDLE_IDENTIFIER = me.rainbow.ImageNotification; PRODUCT_NAME = "$(TARGET_NAME)"; - PROVISIONING_PROFILE_SPECIFIER = "match Development me.rainbow.ImageNotification"; + PROVISIONING_PROFILE_SPECIFIER = ""; SKIP_INSTALL = YES; SWIFT_EMIT_LOC_STRINGS = YES; SWIFT_PRECOMPILE_BRIDGING_HEADER = NO; @@ -1765,7 +1763,7 @@ }; 0299CE832886202800B5C7E7 /* Staging */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 208F04ABC0ACD249A8EDFA1A /* Pods-ImageNotification.staging.xcconfig */; + baseConfigurationReference = B3A1BB88E4834A09CEE6A23C /* Pods-ImageNotification.staging.xcconfig */; buildSettings = { APPLICATION_EXTENSION_API_ONLY = YES; CLANG_ANALYZER_NONNULL = YES; @@ -1784,8 +1782,8 @@ CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CODE_SIGN_IDENTITY = "iPhone Developer"; - CODE_SIGN_STYLE = Manual; + CODE_SIGN_IDENTITY = "Apple Development"; + CODE_SIGN_STYLE = Automatic; COPY_PHASE_STRIP = NO; CURRENT_PROJECT_VERSION = 1; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; @@ -1798,13 +1796,17 @@ INFOPLIST_KEY_CFBundleDisplayName = ImageNotification; INFOPLIST_KEY_NSHumanReadableCopyright = "Copyright © 2022 Rainbow. All rights reserved."; IPHONEOS_DEPLOYMENT_TARGET = 15.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@executable_path/../../Frameworks", + ); MARKETING_VERSION = 1.0; MTL_FAST_MATH = YES; OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_RELEASE"; PRODUCT_BUNDLE_IDENTIFIER = me.rainbow.ImageNotification; PRODUCT_NAME = "$(TARGET_NAME)"; - PROVISIONING_PROFILE_SPECIFIER = "match Development me.rainbow.ImageNotification"; + PROVISIONING_PROFILE_SPECIFIER = ""; SKIP_INSTALL = YES; SWIFT_EMIT_LOC_STRINGS = YES; SWIFT_PRECOMPILE_BRIDGING_HEADER = NO; @@ -1814,7 +1816,7 @@ }; 13B07F941A680F5B00A75B9A /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = B72F672E1C1931C1EFA69240 /* Pods-Rainbow.debug.xcconfig */; + baseConfigurationReference = A019C130957DC7A038F8059E /* Pods-Rainbow.debug.xcconfig */; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; APPLICATION_EXTENSION_API_ONLY = NO; @@ -1824,8 +1826,8 @@ ASSETCATALOG_COMPILER_OPTIMIZATION = time; CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = Rainbow/RainbowDebug.entitlements; - CODE_SIGN_IDENTITY = "iPhone Developer"; - CODE_SIGN_STYLE = Manual; + CODE_SIGN_IDENTITY = "Apple Development"; + CODE_SIGN_STYLE = Automatic; COPY_PHASE_STRIP = NO; CURRENT_PROJECT_VERSION = 1; DEAD_CODE_STRIPPING = YES; @@ -1863,14 +1865,17 @@ INFOPLIST_FILE = Rainbow/Info.plist; INTENTS_CODEGEN_LANGUAGE = "Objective-C"; IPHONEOS_DEPLOYMENT_TARGET = 15.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); LIBRARY_SEARCH_PATHS = ( "$(SDKROOT)/usr/lib/swift", "$(inherited)", "$(PROJECT_DIR)", ); LLVM_LTO = YES; - MARKETING_VERSION = 1.9.46; + MARKETING_VERSION = 1.9.47; OTHER_CFLAGS = "$(inherited)"; OTHER_LDFLAGS = ( "$(inherited)", @@ -1881,7 +1886,7 @@ PRODUCT_BUNDLE_IDENTIFIER = me.rainbow; PRODUCT_NAME = Rainbow; PROVISIONING_PROFILE = ""; - PROVISIONING_PROFILE_SPECIFIER = "match Development me.rainbow"; + PROVISIONING_PROFILE_SPECIFIER = ""; SWIFT_OBJC_BRIDGING_HEADER = "Rainbow-Bridging-Header.h"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_PRECOMPILE_BRIDGING_HEADER = NO; @@ -1892,7 +1897,7 @@ }; 13B07F951A680F5B00A75B9A /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = B726AE9AC9612098B9AE1E8C /* Pods-Rainbow.release.xcconfig */; + baseConfigurationReference = DE432693F1E564C16827671F /* Pods-Rainbow.release.xcconfig */; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; APPLICATION_EXTENSION_API_ONLY = NO; @@ -1928,14 +1933,17 @@ INFOPLIST_FILE = Rainbow/Info.plist; INTENTS_CODEGEN_LANGUAGE = "Objective-C"; IPHONEOS_DEPLOYMENT_TARGET = 15.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); LIBRARY_SEARCH_PATHS = ( "$(SDKROOT)/usr/lib/swift", "$(inherited)", "$(PROJECT_DIR)", ); LLVM_LTO = YES; - MARKETING_VERSION = 1.9.46; + MARKETING_VERSION = 1.9.47; OTHER_CFLAGS = "$(inherited)"; OTHER_LDFLAGS = ( "$(inherited)", @@ -2013,7 +2021,7 @@ }; 2C6A799821127ED9003AFB37 /* Staging */ = { isa = XCBuildConfiguration; - baseConfigurationReference = DF978C7B693121BE46F2053C /* Pods-Rainbow.staging.xcconfig */; + baseConfigurationReference = 86D738C44C2C571736190D2D /* Pods-Rainbow.staging.xcconfig */; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; APPLICATION_EXTENSION_API_ONLY = NO; @@ -2023,11 +2031,11 @@ ASSETCATALOG_COMPILER_OPTIMIZATION = ""; CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = Rainbow/Rainbow.entitlements; - CODE_SIGN_IDENTITY = "iPhone Developer"; - CODE_SIGN_STYLE = Manual; + CODE_SIGN_IDENTITY = "Apple Development"; + CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - DEVELOPMENT_TEAM = L74NQAQB8H; + DEVELOPMENT_TEAM = 2897MY7R2W; ENABLE_BITCODE = NO; "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = arm64; FRAMEWORK_SEARCH_PATHS = ( @@ -2046,14 +2054,17 @@ INFOPLIST_FILE = Rainbow/Info.plist; INTENTS_CODEGEN_LANGUAGE = "Objective-C"; IPHONEOS_DEPLOYMENT_TARGET = 15.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); LIBRARY_SEARCH_PATHS = ( "$(SDKROOT)/usr/lib/swift", "$(inherited)", "$(PROJECT_DIR)", ); LLVM_LTO = YES; - MARKETING_VERSION = 1.9.46; + MARKETING_VERSION = 1.9.47; OTHER_CFLAGS = "$(inherited)"; OTHER_LDFLAGS = ( "$(inherited)", @@ -2064,7 +2075,7 @@ PRODUCT_BUNDLE_IDENTIFIER = me.rainbow; PRODUCT_NAME = Rainbow; PROVISIONING_PROFILE = ""; - PROVISIONING_PROFILE_SPECIFIER = "match Development me.rainbow"; + PROVISIONING_PROFILE_SPECIFIER = ""; SWIFT_OBJC_BRIDGING_HEADER = "Rainbow-Bridging-Header.h"; SWIFT_PRECOMPILE_BRIDGING_HEADER = NO; SWIFT_VERSION = 5.0; @@ -2130,7 +2141,7 @@ }; 2C87B79A2197FA1900682EC4 /* LocalRelease */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 59D20A56C5C8F6DD51C60C16 /* Pods-Rainbow.localrelease.xcconfig */; + baseConfigurationReference = 4CA6FC1DE5EB5ED82E7E1F54 /* Pods-Rainbow.localrelease.xcconfig */; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; APPLICATION_EXTENSION_API_ONLY = NO; @@ -2140,11 +2151,11 @@ ASSETCATALOG_COMPILER_OPTIMIZATION = time; CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = Rainbow/Rainbow.entitlements; - CODE_SIGN_IDENTITY = "iPhone Developer"; - CODE_SIGN_STYLE = Manual; + CODE_SIGN_IDENTITY = "Apple Development"; + CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - DEVELOPMENT_TEAM = L74NQAQB8H; + DEVELOPMENT_TEAM = 2897MY7R2W; ENABLE_BITCODE = NO; "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = arm64; FRAMEWORK_SEARCH_PATHS = ( @@ -2163,14 +2174,17 @@ INFOPLIST_FILE = Rainbow/Info.plist; INTENTS_CODEGEN_LANGUAGE = "Objective-C"; IPHONEOS_DEPLOYMENT_TARGET = 15.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); LIBRARY_SEARCH_PATHS = ( "$(SDKROOT)/usr/lib/swift", "$(inherited)", "$(PROJECT_DIR)", ); LLVM_LTO = YES; - MARKETING_VERSION = 1.9.46; + MARKETING_VERSION = 1.9.47; OTHER_CFLAGS = "$(inherited)"; OTHER_LDFLAGS = ( "$(inherited)", @@ -2181,7 +2195,7 @@ PRODUCT_BUNDLE_IDENTIFIER = me.rainbow; PRODUCT_NAME = Rainbow; PROVISIONING_PROFILE = ""; - PROVISIONING_PROFILE_SPECIFIER = "match Development me.rainbow"; + PROVISIONING_PROFILE_SPECIFIER = ""; SWIFT_OBJC_BRIDGING_HEADER = "Rainbow-Bridging-Header.h"; SWIFT_PRECOMPILE_BRIDGING_HEADER = NO; SWIFT_VERSION = 5.0; @@ -2304,7 +2318,7 @@ }; C16DCF6A272BA6F100FF5C78 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = EEDFB87C7DC0A55503B643C5 /* Pods-PriceWidgetExtension.debug.xcconfig */; + baseConfigurationReference = 4F41B555E9F2BDC11F67C4B5 /* Pods-PriceWidgetExtension.debug.xcconfig */; buildSettings = { APPLICATION_EXTENSION_API_ONLY = YES; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; @@ -2326,8 +2340,8 @@ CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CODE_SIGN_ENTITLEMENTS = PriceWidgetExtension.entitlements; - CODE_SIGN_IDENTITY = "iPhone Developer"; - CODE_SIGN_STYLE = Manual; + CODE_SIGN_IDENTITY = "Apple Development"; + CODE_SIGN_STYLE = Automatic; DEBUG_INFORMATION_FORMAT = dwarf; DEVELOPMENT_TEAM = L74NQAQB8H; ENABLE_TESTABILITY = YES; @@ -2336,13 +2350,17 @@ GCC_NO_COMMON_BLOCKS = YES; INFOPLIST_FILE = PriceWidget/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 15.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@executable_path/../../Frameworks", + ); MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_DEBUG"; PRODUCT_BUNDLE_IDENTIFIER = me.rainbow.PriceWidget; PRODUCT_NAME = "$(TARGET_NAME)"; - PROVISIONING_PROFILE_SPECIFIER = "match Development me.rainbow.PriceWidget"; + PROVISIONING_PROFILE_SPECIFIER = ""; SKIP_INSTALL = YES; SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; @@ -2354,7 +2372,7 @@ }; C16DCF6B272BA6F100FF5C78 /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = A0B1D87220C90A9004D035C7 /* Pods-PriceWidgetExtension.release.xcconfig */; + baseConfigurationReference = 9092BB627D60D1C7E65EAD39 /* Pods-PriceWidgetExtension.release.xcconfig */; buildSettings = { APPLICATION_EXTENSION_API_ONLY = YES; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; @@ -2388,7 +2406,11 @@ GCC_NO_COMMON_BLOCKS = YES; INFOPLIST_FILE = PriceWidget/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 15.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@executable_path/../../Frameworks", + ); MTL_FAST_MATH = YES; OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_RELEASE"; PRODUCT_BUNDLE_IDENTIFIER = me.rainbow.PriceWidget; @@ -2396,7 +2418,8 @@ PROVISIONING_PROFILE_SPECIFIER = ""; "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "match AppStore me.rainbow.PriceWidget"; SKIP_INSTALL = YES; - SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; SWIFT_PRECOMPILE_BRIDGING_HEADER = NO; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; @@ -2405,7 +2428,7 @@ }; C16DCF6C272BA6F100FF5C78 /* LocalRelease */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 71C4AACC71462B12A43FDDE5 /* Pods-PriceWidgetExtension.localrelease.xcconfig */; + baseConfigurationReference = FC4825CCDBA2CACA5A469C41 /* Pods-PriceWidgetExtension.localrelease.xcconfig */; buildSettings = { APPLICATION_EXTENSION_API_ONLY = YES; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; @@ -2427,8 +2450,8 @@ CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CODE_SIGN_ENTITLEMENTS = PriceWidgetExtension.entitlements; - CODE_SIGN_IDENTITY = "iPhone Developer"; - CODE_SIGN_STYLE = Manual; + CODE_SIGN_IDENTITY = "Apple Development"; + CODE_SIGN_STYLE = Automatic; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEVELOPMENT_TEAM = L74NQAQB8H; @@ -2437,14 +2460,19 @@ GCC_NO_COMMON_BLOCKS = YES; INFOPLIST_FILE = PriceWidget/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 15.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@executable_path/../../Frameworks", + ); MTL_FAST_MATH = YES; OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_RELEASE"; PRODUCT_BUNDLE_IDENTIFIER = me.rainbow.PriceWidget; PRODUCT_NAME = "$(TARGET_NAME)"; - PROVISIONING_PROFILE_SPECIFIER = "match Development me.rainbow.PriceWidget"; + PROVISIONING_PROFILE_SPECIFIER = ""; SKIP_INSTALL = YES; - SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; SWIFT_PRECOMPILE_BRIDGING_HEADER = NO; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; @@ -2453,7 +2481,7 @@ }; C16DCF6D272BA6F100FF5C78 /* Staging */ = { isa = XCBuildConfiguration; - baseConfigurationReference = D8FA6FF97E16AF1841C65403 /* Pods-PriceWidgetExtension.staging.xcconfig */; + baseConfigurationReference = D8909C8CDF72D43F8537B004 /* Pods-PriceWidgetExtension.staging.xcconfig */; buildSettings = { APPLICATION_EXTENSION_API_ONLY = YES; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; @@ -2485,14 +2513,19 @@ GCC_NO_COMMON_BLOCKS = YES; INFOPLIST_FILE = PriceWidget/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 15.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@executable_path/../../Frameworks", + ); MTL_FAST_MATH = YES; OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_RELEASE"; PRODUCT_BUNDLE_IDENTIFIER = me.rainbow.PriceWidget; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; SKIP_INSTALL = YES; - SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; SWIFT_PRECOMPILE_BRIDGING_HEADER = NO; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; @@ -2501,7 +2534,7 @@ }; C16DCFA0272BAB9600FF5C78 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 390E0879CC9C88D0DBF50690 /* Pods-SelectTokenIntent.debug.xcconfig */; + baseConfigurationReference = 9787D6F106B2967888575DF6 /* Pods-SelectTokenIntent.debug.xcconfig */; buildSettings = { APPLICATION_EXTENSION_API_ONLY = YES; CLANG_ANALYZER_NONNULL = YES; @@ -2521,8 +2554,8 @@ CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CODE_SIGN_ENTITLEMENTS = SelectTokenIntent/SelectTokenIntent.entitlements; - CODE_SIGN_IDENTITY = "iPhone Developer"; - CODE_SIGN_STYLE = Manual; + CODE_SIGN_IDENTITY = "Apple Development"; + CODE_SIGN_STYLE = Automatic; DEBUG_INFORMATION_FORMAT = dwarf; DEVELOPMENT_TEAM = L74NQAQB8H; ENABLE_TESTABILITY = YES; @@ -2531,13 +2564,17 @@ GCC_NO_COMMON_BLOCKS = YES; INFOPLIST_FILE = SelectTokenIntent/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 15.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@executable_path/../../Frameworks", + ); MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_DEBUG"; PRODUCT_BUNDLE_IDENTIFIER = me.rainbow.SelectTokenIntent; PRODUCT_NAME = "$(TARGET_NAME)"; - PROVISIONING_PROFILE_SPECIFIER = "match Development me.rainbow.SelectTokenIntent"; + PROVISIONING_PROFILE_SPECIFIER = ""; SKIP_INSTALL = YES; SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; @@ -2549,7 +2586,7 @@ }; C16DCFA1272BAB9600FF5C78 /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 2FA1FCE6D3B56B8902BEFC47 /* Pods-SelectTokenIntent.release.xcconfig */; + baseConfigurationReference = 928D80AC880326A5C93E8682 /* Pods-SelectTokenIntent.release.xcconfig */; buildSettings = { APPLICATION_EXTENSION_API_ONLY = YES; CLANG_ANALYZER_NONNULL = YES; @@ -2581,7 +2618,11 @@ GCC_NO_COMMON_BLOCKS = YES; INFOPLIST_FILE = SelectTokenIntent/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 15.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@executable_path/../../Frameworks", + ); MTL_FAST_MATH = YES; OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_RELEASE"; PRODUCT_BUNDLE_IDENTIFIER = me.rainbow.SelectTokenIntent; @@ -2589,7 +2630,8 @@ PROVISIONING_PROFILE_SPECIFIER = ""; "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "match AppStore me.rainbow.SelectTokenIntent"; SKIP_INSTALL = YES; - SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; SWIFT_PRECOMPILE_BRIDGING_HEADER = NO; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; @@ -2598,7 +2640,7 @@ }; C16DCFA2272BAB9600FF5C78 /* LocalRelease */ = { isa = XCBuildConfiguration; - baseConfigurationReference = FD9E17465EF9D8CDA62027EE /* Pods-SelectTokenIntent.localrelease.xcconfig */; + baseConfigurationReference = 732C3F4923CF572688475536 /* Pods-SelectTokenIntent.localrelease.xcconfig */; buildSettings = { APPLICATION_EXTENSION_API_ONLY = YES; CLANG_ANALYZER_NONNULL = YES; @@ -2618,8 +2660,8 @@ CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CODE_SIGN_ENTITLEMENTS = SelectTokenIntent/SelectTokenIntent.entitlements; - CODE_SIGN_IDENTITY = "iPhone Developer"; - CODE_SIGN_STYLE = Manual; + CODE_SIGN_IDENTITY = "Apple Development"; + CODE_SIGN_STYLE = Automatic; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEVELOPMENT_TEAM = L74NQAQB8H; @@ -2628,14 +2670,19 @@ GCC_NO_COMMON_BLOCKS = YES; INFOPLIST_FILE = SelectTokenIntent/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 15.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@executable_path/../../Frameworks", + ); MTL_FAST_MATH = YES; OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_RELEASE"; PRODUCT_BUNDLE_IDENTIFIER = me.rainbow.SelectTokenIntent; PRODUCT_NAME = "$(TARGET_NAME)"; - PROVISIONING_PROFILE_SPECIFIER = "match Development me.rainbow.SelectTokenIntent"; + PROVISIONING_PROFILE_SPECIFIER = ""; SKIP_INSTALL = YES; - SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; SWIFT_PRECOMPILE_BRIDGING_HEADER = NO; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; @@ -2644,7 +2691,7 @@ }; C16DCFA3272BAB9600FF5C78 /* Staging */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 9E8BEFB6422BEB906DEB3C7E /* Pods-SelectTokenIntent.staging.xcconfig */; + baseConfigurationReference = 28A977B84F9AEE8B8145111F /* Pods-SelectTokenIntent.staging.xcconfig */; buildSettings = { APPLICATION_EXTENSION_API_ONLY = YES; CLANG_ANALYZER_NONNULL = YES; @@ -2674,14 +2721,19 @@ GCC_NO_COMMON_BLOCKS = YES; INFOPLIST_FILE = SelectTokenIntent/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 15.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@executable_path/../../Frameworks", + ); MTL_FAST_MATH = YES; OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_RELEASE"; PRODUCT_BUNDLE_IDENTIFIER = me.rainbow.SelectTokenIntent; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; SKIP_INSTALL = YES; - SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; SWIFT_PRECOMPILE_BRIDGING_HEADER = NO; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; @@ -2710,12 +2762,11 @@ CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CODE_SIGN_IDENTITY = "iPhone Developer"; - CODE_SIGN_STYLE = Manual; + CODE_SIGN_IDENTITY = "Apple Development"; + CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; DEBUG_INFORMATION_FORMAT = dwarf; - DEVELOPMENT_TEAM = ""; - "DEVELOPMENT_TEAM[sdk=iphoneos*]" = L74NQAQB8H; + DEVELOPMENT_TEAM = L74NQAQB8H; ENABLE_TESTABILITY = YES; ENABLE_USER_SCRIPT_SANDBOXING = YES; GCC_C_LANGUAGE_STANDARD = gnu17; @@ -2729,7 +2780,11 @@ INFOPLIST_KEY_CFBundleDisplayName = "Open in Rainbow"; INFOPLIST_KEY_NSHumanReadableCopyright = "Copyright © 2024 Rainbow. All rights reserved."; IPHONEOS_DEPLOYMENT_TARGET = 17.5; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@executable_path/../../Frameworks", + ); LOCALIZATION_PREFERS_STRING_CATALOGS = YES; MARKETING_VERSION = 1.0; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; @@ -2738,7 +2793,6 @@ PRODUCT_BUNDLE_IDENTIFIER = me.rainbow.OpenInRainbow; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; - "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "match Development me.rainbow.OpenInRainbow"; SKIP_INSTALL = YES; SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)"; SWIFT_EMIT_LOC_STRINGS = YES; @@ -2786,7 +2840,11 @@ INFOPLIST_KEY_CFBundleDisplayName = "Open in Rainbow"; INFOPLIST_KEY_NSHumanReadableCopyright = "Copyright © 2024 Rainbow. All rights reserved."; IPHONEOS_DEPLOYMENT_TARGET = 17.5; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@executable_path/../../Frameworks", + ); LOCALIZATION_PREFERS_STRING_CATALOGS = YES; MARKETING_VERSION = 1.0; MTL_FAST_MATH = YES; @@ -2825,13 +2883,12 @@ CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CODE_SIGN_IDENTITY = "iPhone Developer"; - CODE_SIGN_STYLE = Manual; + CODE_SIGN_IDENTITY = "Apple Development"; + CODE_SIGN_STYLE = Automatic; COPY_PHASE_STRIP = NO; CURRENT_PROJECT_VERSION = 1; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - DEVELOPMENT_TEAM = ""; - "DEVELOPMENT_TEAM[sdk=iphoneos*]" = L74NQAQB8H; + DEVELOPMENT_TEAM = L74NQAQB8H; ENABLE_USER_SCRIPT_SANDBOXING = YES; GCC_C_LANGUAGE_STANDARD = gnu17; GCC_NO_COMMON_BLOCKS = YES; @@ -2840,7 +2897,11 @@ INFOPLIST_KEY_CFBundleDisplayName = "Open in Rainbow"; INFOPLIST_KEY_NSHumanReadableCopyright = "Copyright © 2024 Rainbow. All rights reserved."; IPHONEOS_DEPLOYMENT_TARGET = 17.5; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@executable_path/../../Frameworks", + ); LOCALIZATION_PREFERS_STRING_CATALOGS = YES; MARKETING_VERSION = 1.0; MTL_FAST_MATH = YES; @@ -2848,7 +2909,6 @@ PRODUCT_BUNDLE_IDENTIFIER = me.rainbow.OpenInRainbow; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; - "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "match Development me.rainbow.OpenInRainbow"; SKIP_INSTALL = YES; SWIFT_COMPILATION_MODE = wholemodule; SWIFT_EMIT_LOC_STRINGS = YES; @@ -2879,13 +2939,12 @@ CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CODE_SIGN_IDENTITY = "iPhone Developer"; - CODE_SIGN_STYLE = Manual; + CODE_SIGN_IDENTITY = "Apple Development"; + CODE_SIGN_STYLE = Automatic; COPY_PHASE_STRIP = NO; CURRENT_PROJECT_VERSION = 1; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - DEVELOPMENT_TEAM = ""; - "DEVELOPMENT_TEAM[sdk=iphoneos*]" = L74NQAQB8H; + DEVELOPMENT_TEAM = L74NQAQB8H; ENABLE_USER_SCRIPT_SANDBOXING = YES; GCC_C_LANGUAGE_STANDARD = gnu17; GCC_NO_COMMON_BLOCKS = YES; @@ -2894,7 +2953,11 @@ INFOPLIST_KEY_CFBundleDisplayName = "Open in Rainbow"; INFOPLIST_KEY_NSHumanReadableCopyright = "Copyright © 2024 Rainbow. All rights reserved."; IPHONEOS_DEPLOYMENT_TARGET = 17.5; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@executable_path/../../Frameworks", + ); LOCALIZATION_PREFERS_STRING_CATALOGS = YES; MARKETING_VERSION = 1.0; MTL_FAST_MATH = YES; @@ -2902,7 +2965,6 @@ PRODUCT_BUNDLE_IDENTIFIER = me.rainbow.OpenInRainbow; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; - "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "match Development me.rainbow.OpenInRainbow"; SKIP_INSTALL = YES; SWIFT_COMPILATION_MODE = wholemodule; SWIFT_EMIT_LOC_STRINGS = YES; @@ -2933,12 +2995,11 @@ CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CODE_SIGN_IDENTITY = "iPhone Developer"; - CODE_SIGN_STYLE = Manual; + CODE_SIGN_IDENTITY = "Apple Development"; + CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; DEBUG_INFORMATION_FORMAT = dwarf; - DEVELOPMENT_TEAM = ""; - "DEVELOPMENT_TEAM[sdk=iphoneos*]" = L74NQAQB8H; + DEVELOPMENT_TEAM = L74NQAQB8H; ENABLE_TESTABILITY = YES; ENABLE_USER_SCRIPT_SANDBOXING = YES; GCC_C_LANGUAGE_STANDARD = gnu17; @@ -2952,7 +3013,11 @@ INFOPLIST_KEY_CFBundleDisplayName = ShareWithRainbow; INFOPLIST_KEY_NSHumanReadableCopyright = "Copyright © 2024 Rainbow. All rights reserved."; IPHONEOS_DEPLOYMENT_TARGET = 17.5; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@executable_path/../../Frameworks", + ); LOCALIZATION_PREFERS_STRING_CATALOGS = YES; MARKETING_VERSION = 1.0; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; @@ -2961,7 +3026,6 @@ PRODUCT_BUNDLE_IDENTIFIER = me.rainbow.ShareWithRainbow; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; - "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "match Development me.rainbow.ShareWithRainbow"; SKIP_INSTALL = YES; SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)"; SWIFT_EMIT_LOC_STRINGS = YES; @@ -3009,7 +3073,11 @@ INFOPLIST_KEY_CFBundleDisplayName = ShareWithRainbow; INFOPLIST_KEY_NSHumanReadableCopyright = "Copyright © 2024 Rainbow. All rights reserved."; IPHONEOS_DEPLOYMENT_TARGET = 17.5; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@executable_path/../../Frameworks", + ); LOCALIZATION_PREFERS_STRING_CATALOGS = YES; MARKETING_VERSION = 1.0; MTL_FAST_MATH = YES; @@ -3048,13 +3116,12 @@ CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CODE_SIGN_IDENTITY = "iPhone Developer"; - CODE_SIGN_STYLE = Manual; + CODE_SIGN_IDENTITY = "Apple Development"; + CODE_SIGN_STYLE = Automatic; COPY_PHASE_STRIP = NO; CURRENT_PROJECT_VERSION = 1; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - DEVELOPMENT_TEAM = ""; - "DEVELOPMENT_TEAM[sdk=iphoneos*]" = L74NQAQB8H; + DEVELOPMENT_TEAM = L74NQAQB8H; ENABLE_USER_SCRIPT_SANDBOXING = YES; GCC_C_LANGUAGE_STANDARD = gnu17; GCC_NO_COMMON_BLOCKS = YES; @@ -3063,7 +3130,11 @@ INFOPLIST_KEY_CFBundleDisplayName = ShareWithRainbow; INFOPLIST_KEY_NSHumanReadableCopyright = "Copyright © 2024 Rainbow. All rights reserved."; IPHONEOS_DEPLOYMENT_TARGET = 17.5; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@executable_path/../../Frameworks", + ); LOCALIZATION_PREFERS_STRING_CATALOGS = YES; MARKETING_VERSION = 1.0; MTL_FAST_MATH = YES; @@ -3071,7 +3142,6 @@ PRODUCT_BUNDLE_IDENTIFIER = me.rainbow.ShareWithRainbow; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; - "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "match Development me.rainbow.ShareWithRainbow"; SKIP_INSTALL = YES; SWIFT_COMPILATION_MODE = wholemodule; SWIFT_EMIT_LOC_STRINGS = YES; @@ -3102,13 +3172,12 @@ CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CODE_SIGN_IDENTITY = "iPhone Developer"; - CODE_SIGN_STYLE = Manual; + CODE_SIGN_IDENTITY = "Apple Development"; + CODE_SIGN_STYLE = Automatic; COPY_PHASE_STRIP = NO; CURRENT_PROJECT_VERSION = 1; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - DEVELOPMENT_TEAM = ""; - "DEVELOPMENT_TEAM[sdk=iphoneos*]" = L74NQAQB8H; + DEVELOPMENT_TEAM = L74NQAQB8H; ENABLE_USER_SCRIPT_SANDBOXING = YES; GCC_C_LANGUAGE_STANDARD = gnu17; GCC_NO_COMMON_BLOCKS = YES; @@ -3117,7 +3186,11 @@ INFOPLIST_KEY_CFBundleDisplayName = ShareWithRainbow; INFOPLIST_KEY_NSHumanReadableCopyright = "Copyright © 2024 Rainbow. All rights reserved."; IPHONEOS_DEPLOYMENT_TARGET = 17.5; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@executable_path/../../Frameworks", + ); LOCALIZATION_PREFERS_STRING_CATALOGS = YES; MARKETING_VERSION = 1.0; MTL_FAST_MATH = YES; @@ -3125,7 +3198,6 @@ PRODUCT_BUNDLE_IDENTIFIER = me.rainbow.ShareWithRainbow; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; - "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "match Development me.rainbow.ShareWithRainbow"; SKIP_INSTALL = YES; SWIFT_COMPILATION_MODE = wholemodule; SWIFT_EMIT_LOC_STRINGS = YES; diff --git a/ios/SafeStoreReview.m b/ios/SafeStoreReview.m deleted file mode 100644 index 88fcee44d25..00000000000 --- a/ios/SafeStoreReview.m +++ /dev/null @@ -1,124 +0,0 @@ -// -// SafeStoreReview.m -// Rainbow -// -// Created by Michał Osadnik on 12/06/2020. -// Copyright © 2020 Rainbow. All rights reserved. -// - -#import -#import -#import -#import - - - -@interface UIWindow (DismissNotification) - -+ (void)load; - -@end - -@implementation UIWindow (DismissNotification) - - - -static NSString* UIWindowDidBecomeVisibleReviewNotification = @"UIWindowDidBecomeVisibleNotification"; -static NSString* monitorObjectKey = @"monitorKey"; -static NSString* partialDescForStoreReviewWindow = @"SKStore"; -+ (void)load -{ - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - Class class = [self class]; - - SEL originalSelector = @selector(setWindowLevel:); - SEL swizzledSelector = @selector(setWindowLevel_notify:); - - Method originalMethod = class_getInstanceMethod(class, originalSelector); - Method swizzledMethod = class_getInstanceMethod(class, swizzledSelector); - - BOOL didAddMethod = - class_addMethod(class, - originalSelector, - method_getImplementation(swizzledMethod), - method_getTypeEncoding(swizzledMethod)); - - if (didAddMethod) { - class_replaceMethod(class, - swizzledSelector, - method_getImplementation(originalMethod), - method_getTypeEncoding(originalMethod)); - } else { - method_exchangeImplementations(originalMethod, swizzledMethod); - } - }); -} - - -#pragma mark - Method Swizzling - -- (void)setWindowLevel_notify:(int)level{ - [self setWindowLevel_notify:level]; - - if([self.description containsString:partialDescForStoreReviewWindow]) - { - [[NSNotificationCenter defaultCenter] postNotificationName:UIWindowDidBecomeVisibleReviewNotification object:self]; - } -} - -@end - - -@interface RainbowRequestReviewManager : NSObject -@end - -@implementation RainbowRequestReviewManager { - RCTResponseSenderBlock _callback; -} - -+ (BOOL)requiresMainQueueSetup -{ - return NO; -} - - -- (dispatch_queue_t)methodQueue { - return dispatch_get_main_queue(); -} - -- (instancetype)init -{ - self = [super init]; - if (self) { - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(windowDidBecomeVisibleNotification:) - name:UIWindowDidBecomeVisibleReviewNotification - object:nil]; - } - return self; -} - -- (void)windowDidBecomeVisibleNotification:(NSNotification *)notification -{ - if (_callback != nil) { - _callback(@[[[NSNumber alloc] initWithBool:YES]]); - _callback = nil; - } -} - - -RCT_EXPORT_MODULE(RainbowRequestReview); - -RCT_EXPORT_METHOD(requestReview:(RCTResponseSenderBlock)callback) { - [SKStoreReviewController requestReview]; - _callback = callback; - dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 0.01 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{ - if (_callback != nil) { - _callback(@[[[NSNumber alloc] initWithBool:NO]]); - _callback = nil; - } - }); -} - -@end diff --git a/package.json b/package.json index bf21af4bac6..a5afabc3812 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "Rainbow", - "version": "1.9.46-1", + "version": "1.9.47-1", "private": true, "scripts": { "setup": "yarn graphql-codegen:install && yarn ds:install && yarn allow-scripts && yarn postinstall && yarn graphql-codegen && yarn fetch:networks", @@ -176,6 +176,7 @@ "ethereumjs-wallet": "1.0.1", "events": "3.3.0", "expo": "51.0.33", + "expo-store-review": "7.0.2", "fast-text-encoding": "1.0.4", "global": "4.4.0", "grapheme-splitter": "1.0.4", @@ -272,6 +273,7 @@ "react-native-text-size": "rainbow-me/react-native-text-size#15b21c9f88c6df0d1b5e0f2ba792fe59b5dc255a", "react-native-tooltip": "rainbow-me/react-native-tooltip#e0e88d212b5b7f350e5eabba87f588a32e0f2590", "react-native-tooltips": "rainbow-me/react-native-tooltips#fdafbc7ba33ee231229f5d3f58b29d0d1c55ddfa", + "react-native-turbo-haptics": "1.0.4", "react-native-udp": "2.7.0", "react-native-url-polyfill": "2.0.0", "react-native-version-number": "0.3.6", diff --git a/src/App.tsx b/src/App.tsx index 3d4cc1d7cc2..a0121bab7f2 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -17,17 +17,15 @@ import { designSystemPlaygroundEnabled, reactNativeDisableYellowBox, showNetwork import monitorNetwork from '@/debugging/network'; import { Playground } from '@/design-system/playground/Playground'; import RainbowContextWrapper from '@/helpers/RainbowContext'; -import * as keychain from '@/model/keychain'; import { Navigation } from '@/navigation'; import { PersistQueryClientProvider, persistOptions, queryClient } from '@/react-query'; import store, { AppDispatch, type AppState } from '@/redux/store'; import { MainThemeProvider } from '@/theme/ThemeContext'; -import { addressKey } from '@/utils/keychainConstants'; import { SharedValuesProvider } from '@/helpers/SharedValuesContext'; import { InitialRouteContext } from '@/navigation/initialRoute'; import { NotificationsHandler } from '@/notifications/NotificationsHandler'; import { analyticsV2 } from '@/analytics'; -import { getOrCreateDeviceId, securelyHashWalletAddress } from '@/analytics/utils'; +import { getOrCreateDeviceId } from '@/analytics/utils'; import { logger, RainbowError } from '@/logger'; import * as ls from '@/storage'; import { migrate } from '@/migrations'; @@ -36,7 +34,6 @@ import { ReviewPromptAction } from '@/storage/schema'; import { initializeRemoteConfig } from '@/model/remoteConfig'; import { NavigationContainerRef } from '@react-navigation/native'; import { RootStackParamList } from '@/navigation/types'; -import { Address } from 'viem'; import { IS_ANDROID, IS_DEV } from '@/env'; import { prefetchDefaultFavorites } from '@/resources/favorites'; import Routes from '@/navigation/Routes'; @@ -110,27 +107,11 @@ function Root() { const isReturningUser = ls.device.get(['isReturningUser']); const [deviceId, deviceIdWasJustCreated] = await getOrCreateDeviceId(); - const currentWalletAddress = await keychain.loadString(addressKey); - const currentWalletAddressHash = - typeof currentWalletAddress === 'string' ? securelyHashWalletAddress(currentWalletAddress as Address) : undefined; - Sentry.setUser({ - id: deviceId, - currentWalletAddress: currentWalletAddressHash, - }); - - /** - * Add helpful values to `analyticsV2` instance - */ + // Initial telemetry; amended with wallet context later in `useInitializeWallet` + Sentry.setUser({ id: deviceId }); analyticsV2.setDeviceId(deviceId); - if (currentWalletAddressHash) { - analyticsV2.setCurrentWalletAddressHash(currentWalletAddressHash); - } - - /** - * `analyticsv2` has all it needs to function. - */ - analyticsV2.identify({}); + analyticsV2.identify(); const isReviewInitialized = ls.review.get(['initialized']); if (!isReviewInitialized) { diff --git a/src/__swaps__/screens/Swap/components/SearchInputButton.tsx b/src/__swaps__/screens/Swap/components/SearchInputButton.tsx index aa89ce65023..9e2b328fa64 100644 --- a/src/__swaps__/screens/Swap/components/SearchInputButton.tsx +++ b/src/__swaps__/screens/Swap/components/SearchInputButton.tsx @@ -2,6 +2,7 @@ import React, { useCallback } from 'react'; import { GestureHandlerButton } from './GestureHandlerButton'; import { AnimatedText, Box } from '@/design-system'; import Animated, { SharedValue, runOnJS, useAnimatedStyle, useDerivedValue, withTiming } from 'react-native-reanimated'; +import { triggerHaptics } from 'react-native-turbo-haptics'; import { NavigationSteps, useSwapContext } from '@/__swaps__/screens/Swap/providers/swap-provider'; import Clipboard from '@react-native-clipboard/clipboard'; import { useSwapsStore } from '@/state/swaps/swapsStore'; @@ -9,7 +10,6 @@ import * as i18n from '@/languages'; import { THICK_BORDER_WIDTH } from '../constants'; import { useClipboard } from '@/hooks'; import { TIMING_CONFIGS } from '@/components/animations/animationConfigs'; -import { triggerHapticFeedback } from '@/screens/points/constants'; import { IS_ANDROID } from '@/env'; const CANCEL_LABEL = i18n.t(i18n.l.button.cancel); @@ -54,22 +54,14 @@ export const SearchInputButton = ({ return PASTE_LABEL; }); - const onPaste = useCallback( - (isPasteDisabled: boolean) => { - if (isPasteDisabled) { - triggerHapticFeedback('notificationError'); - return; - } - - Clipboard.getString().then(text => { - // Slice the pasted text to the length of an ETH address - const v = text.trim().slice(0, 42); - pastedSearchInputValue.value = v; - useSwapsStore.setState({ outputSearchQuery: v }); - }); - }, - [pastedSearchInputValue] - ); + const onPaste = useCallback(() => { + Clipboard.getString().then(text => { + // Slice the pasted text to the length of an ETH address + const v = text.trim().slice(0, 42); + pastedSearchInputValue.value = v; + useSwapsStore.setState({ outputSearchQuery: v }); + }); + }, [pastedSearchInputValue]); const buttonInfo = useDerivedValue(() => { const isInputSearchFocused = inputProgress.value === NavigationSteps.SEARCH_FOCUSED; @@ -106,7 +98,11 @@ export const SearchInputButton = ({ onPressWorklet={() => { 'worklet'; if (output && outputProgress.value === NavigationSteps.TOKEN_LIST_FOCUSED && !internalSelectedOutputAsset.value) { - runOnJS(onPaste)(buttonInfo.value.isPasteDisabled); + if (buttonInfo.value.isPasteDisabled) { + triggerHaptics('notificationError'); + } else { + runOnJS(onPaste)(); + } } if (isSearchFocused.value || (output && internalSelectedOutputAsset.value) || (!output && internalSelectedInputAsset.value)) { diff --git a/src/__swaps__/screens/Swap/components/SwapBottomPanel.tsx b/src/__swaps__/screens/Swap/components/SwapBottomPanel.tsx index 1bb554d9617..5f85f146be7 100644 --- a/src/__swaps__/screens/Swap/components/SwapBottomPanel.tsx +++ b/src/__swaps__/screens/Swap/components/SwapBottomPanel.tsx @@ -5,15 +5,8 @@ import { Box, Separator, globalColors, useColorMode } from '@/design-system'; import React from 'react'; import { StyleSheet } from 'react-native'; import { PanGestureHandler } from 'react-native-gesture-handler'; -import Animated, { - Easing, - runOnJS, - useAnimatedStyle, - useDerivedValue, - useSharedValue, - withSpring, - withTiming, -} from 'react-native-reanimated'; +import Animated, { Easing, useAnimatedStyle, useDerivedValue, useSharedValue, withSpring, withTiming } from 'react-native-reanimated'; +import { triggerHaptics } from 'react-native-turbo-haptics'; import { useBottomPanelGestureHandler } from '../hooks/useBottomPanelGestureHandler'; import { GasButton } from './GasButton'; import { GasPanel } from './GasPanel'; @@ -21,7 +14,6 @@ import { ReviewPanel } from './ReviewPanel'; import { SwapActionButton } from './SwapActionButton'; import { SettingsPanel } from './SettingsPanel'; import { SPRING_CONFIGS } from '@/components/animations/animationConfigs'; -import { triggerHapticFeedback } from '@/screens/points/constants'; const HOLD_TO_SWAP_DURATION_MS = 400; @@ -123,7 +115,7 @@ export function SwapBottomPanel() { onLongPressWorklet={() => { 'worklet'; if (type.value === 'hold') { - runOnJS(triggerHapticFeedback)('notificationSuccess'); + triggerHaptics('notificationSuccess'); SwapNavigation.handleSwapAction(); } }} diff --git a/src/__swaps__/screens/Swap/components/SwapSlider.tsx b/src/__swaps__/screens/Swap/components/SwapSlider.tsx index a845fb8b25c..572f9eb6e80 100644 --- a/src/__swaps__/screens/Swap/components/SwapSlider.tsx +++ b/src/__swaps__/screens/Swap/components/SwapSlider.tsx @@ -18,10 +18,10 @@ import Animated, { withSpring, withTiming, } from 'react-native-reanimated'; +import { triggerHaptics } from 'react-native-turbo-haptics'; import { SPRING_CONFIGS, TIMING_CONFIGS } from '@/components/animations/animationConfigs'; import { AnimatedText, Bleed, Box, Column, Columns, Inline, globalColors, useColorMode, useForegroundColor } from '@/design-system'; import { IS_IOS } from '@/env'; -import { triggerHapticFeedback } from '@/screens/points/constants'; import { greaterThanWorklet } from '@/safe-math/SafeMath'; import { SCRUBBER_WIDTH, @@ -124,10 +124,10 @@ export const SwapSlider = ({ (current, previous) => { if (current !== previous && SwapInputController.inputMethod.value === 'slider') { if (current.x >= width * 0.995 && previous?.x && previous?.x < width * 0.995) { - runOnJS(triggerHapticFeedback)('impactMedium'); + triggerHaptics('impactMedium'); } if (current.x < width * 0.005 && previous?.x && previous?.x >= width * 0.005) { - runOnJS(triggerHapticFeedback)('impactLight'); + triggerHaptics('impactLight'); } } }, @@ -160,7 +160,7 @@ export const SwapSlider = ({ ctx.exceedsMax = true; isQuoteStale.value = 1; sliderXPosition.value = width * 0.999; - runOnJS(triggerHapticFeedback)('impactMedium'); + triggerHaptics('impactMedium'); } } diff --git a/src/__swaps__/screens/Swap/hooks/useSwapEstimatedGasLimit.ts b/src/__swaps__/screens/Swap/hooks/useSwapEstimatedGasLimit.ts index bc9b301a87b..d061ca5fe3f 100644 --- a/src/__swaps__/screens/Swap/hooks/useSwapEstimatedGasLimit.ts +++ b/src/__swaps__/screens/Swap/hooks/useSwapEstimatedGasLimit.ts @@ -3,8 +3,8 @@ import { useQuery } from '@tanstack/react-query'; import { ParsedSearchAsset } from '@/__swaps__/types/assets'; import { ChainId } from '@/chains/types'; -import { estimateUnlockAndCrosschainSwap } from '@/raps/unlockAndCrosschainSwap'; -import { estimateUnlockAndSwap } from '@/raps/unlockAndSwap'; +import { estimateUnlockAndCrosschainSwap } from '@/raps/actions/crosschainSwap'; +import { estimateUnlockAndSwap } from '@/raps/actions/swap'; import { QueryConfigWithSelect, QueryFunctionArgs, QueryFunctionResult, createQueryKey } from '@/react-query'; import { gasUnits } from '@/references/gasUnits'; diff --git a/src/__swaps__/screens/Swap/hooks/useSwapInputsController.ts b/src/__swaps__/screens/Swap/hooks/useSwapInputsController.ts index 6472a89fbf7..68be42a67f5 100644 --- a/src/__swaps__/screens/Swap/hooks/useSwapInputsController.ts +++ b/src/__swaps__/screens/Swap/hooks/useSwapInputsController.ts @@ -32,11 +32,11 @@ import { externalTokenQueryKey, fetchExternalToken, } from '@/resources/assets/externalAssetsQuery'; -import { triggerHapticFeedback } from '@/screens/points/constants'; import { swapsStore } from '@/state/swaps/swapsStore'; import { CrosschainQuote, Quote, QuoteError, getCrosschainQuote, getQuote } from '@rainbow-me/swaps'; import { useCallback } from 'react'; import { SharedValue, runOnJS, runOnUI, useAnimatedReaction, useDerivedValue, useSharedValue, withSpring } from 'react-native-reanimated'; +import { triggerHaptics } from 'react-native-turbo-haptics'; import { useDebouncedCallback } from 'use-debounce'; import { NavigationSteps } from './useSwapNavigation'; import { deepEqualWorklet } from '@/worklets/comparisons'; @@ -584,7 +584,7 @@ export function useSwapInputsController({ const exceedsMax = maxSwappableAmount ? greaterThanWorklet(currentInputValue, maxSwappableAmount) : false; if (isAlreadyMax) { - runOnJS(triggerHapticFeedback)('impactMedium'); + triggerHaptics('impactMedium'); } else { quoteFetchingInterval.stop(); diff --git a/src/__swaps__/screens/Swap/providers/swap-provider.tsx b/src/__swaps__/screens/Swap/providers/swap-provider.tsx index 7197e5c0d04..9d82264a1d5 100644 --- a/src/__swaps__/screens/Swap/providers/swap-provider.tsx +++ b/src/__swaps__/screens/Swap/providers/swap-provider.tsx @@ -44,6 +44,8 @@ import { queryClient } from '@/react-query'; import { userAssetsQueryKey } from '@/resources/assets/UserAssetsQuery'; import { userAssetsStore } from '@/state/assets/userAssets'; import { swapsStore } from '@/state/swaps/swapsStore'; +import { getNextNonce } from '@/state/nonces'; + import { haptics } from '@/utils'; import { CrosschainQuote, Quote, QuoteError, SwapType } from '@rainbow-me/swaps'; @@ -202,7 +204,7 @@ export const SwapProvider = ({ children }: SwapProviderProps) => { const provider = parameters.flashbots && supportedFlashbotsChainIds.includes(parameters.chainId) - ? await getFlashbotsProvider() + ? getFlashbotsProvider() : getProvider({ chainId: parameters.chainId }); const connectedToHardhat = useConnectedToHardhatStore.getState().connectedToHardhat; @@ -261,6 +263,8 @@ export const SwapProvider = ({ children }: SwapProviderProps) => { } const chainId = connectedToHardhat ? ChainId.hardhat : parameters.chainId; + const nonce = await getNextNonce({ address: parameters.quote.from, chainId }); + const { errorMessage } = await performanceTracking.getState().executeFn({ fn: walletExecuteRap, screen: Screens.SWAPS, @@ -270,6 +274,7 @@ export const SwapProvider = ({ children }: SwapProviderProps) => { }, })(wallet, type, { ...parameters, + nonce, chainId, gasParams, // @ts-expect-error - collision between old gas types and new diff --git a/src/analytics/__mocks__/index.ts b/src/analytics/__mocks__/index.ts index a53a6fd8fa6..71f987845ab 100644 --- a/src/analytics/__mocks__/index.ts +++ b/src/analytics/__mocks__/index.ts @@ -9,7 +9,7 @@ export const analyticsV2 = { screen: jest.fn(), track: jest.fn(), setDeviceId: jest.fn(), - setCurrentWalletAddressHash: jest.fn(), + setWalletContext: jest.fn(), enable: jest.fn(), disable: jest.fn(), event, diff --git a/src/analytics/__tests__/index.test.ts b/src/analytics/__tests__/index.test.ts index 248f5b86da5..94a2624510a 100644 --- a/src/analytics/__tests__/index.test.ts +++ b/src/analytics/__tests__/index.test.ts @@ -18,7 +18,7 @@ describe.skip('@/analytics', () => { test('track', () => { const analytics = new Analytics(); - analytics.setCurrentWalletAddressHash('hash'); + analytics.setWalletContext({ walletAddressHash: 'hash', walletType: 'owned' }); analytics.track(analytics.event.pressedButton); expect(analytics.client.track).toHaveBeenCalledWith(analytics.event.pressedButton, { @@ -29,7 +29,7 @@ describe.skip('@/analytics', () => { test('identify', () => { const analytics = new Analytics(); - analytics.setCurrentWalletAddressHash('hash'); + analytics.setWalletContext({ walletAddressHash: 'hash', walletType: 'owned' }); analytics.setDeviceId('id'); analytics.identify({ currency: 'USD' }); @@ -42,7 +42,7 @@ describe.skip('@/analytics', () => { test('screen', () => { const analytics = new Analytics(); - analytics.setCurrentWalletAddressHash('hash'); + analytics.setWalletContext({ walletAddressHash: 'hash', walletType: 'owned' }); analytics.screen(Routes.BACKUP_SHEET); expect(analytics.client.screen).toHaveBeenCalledWith(Routes.BACKUP_SHEET, { diff --git a/src/analytics/__tests__/utils.test.ts b/src/analytics/__tests__/utils.test.ts index 7d507f61b54..2f01fb4dd26 100644 --- a/src/analytics/__tests__/utils.test.ts +++ b/src/analytics/__tests__/utils.test.ts @@ -8,6 +8,8 @@ jest.mock('@/model/keychain', () => ({ loadString: jest.fn(), })); +jest.mock('@/redux/store'); + jest.mock('@sentry/react-native', () => ({ setUser: jest.fn(), })); diff --git a/src/analytics/index.ts b/src/analytics/index.ts index 6bbd722edb8..222cf513b34 100644 --- a/src/analytics/index.ts +++ b/src/analytics/index.ts @@ -5,13 +5,15 @@ import { EventProperties, event } from '@/analytics/event'; import { UserProperties } from '@/analytics/userProperties'; import { logger, RainbowError } from '@/logger'; import { device } from '@/storage'; +import { WalletContext } from './utils'; const isTesting = IS_TESTING === 'true'; export class Analytics { - client: any; - currentWalletAddressHash?: string; + client: typeof rudderClient; deviceId?: string; + walletAddressHash?: WalletContext['walletAddressHash']; + walletType?: WalletContext['walletType']; event = event; disabled: boolean; @@ -30,22 +32,27 @@ export class Analytics { * here. This uses the `deviceId` as the identifier, and attaches the hashed * wallet address as a property, if available. */ - identify(userProperties: UserProperties) { + identify(userProperties?: UserProperties) { if (this.disabled) return; const metadata = this.getDefaultMetadata(); - this.client.identify(this.deviceId, { - ...userProperties, - ...metadata, - }); + this.client.identify( + this.deviceId as string, + { + ...metadata, + ...userProperties, + }, + {} + ); } /** * Sends a `screen` event. */ - screen(routeName: string, params: Record = {}): void { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + screen(routeName: string, params: Record = {}, walletContext?: WalletContext): void { if (this.disabled) return; const metadata = this.getDefaultMetadata(); - this.client.screen(routeName, { ...params, ...metadata }); + this.client.screen(routeName, { ...metadata, ...walletContext, ...params }); } /** @@ -53,15 +60,16 @@ export class Analytics { * `@/analytics/event`, and if properties are associated with it, they must * be defined as part of `EventProperties` in the same file */ - track(event: T, params?: EventProperties[T]) { + track(event: T, params?: EventProperties[T], walletContext?: WalletContext) { if (this.disabled) return; const metadata = this.getDefaultMetadata(); - this.client.track(event, { ...params, ...metadata }); + this.client.track(event, { ...metadata, ...walletContext, ...params }); } private getDefaultMetadata() { return { - walletAddressHash: this.currentWalletAddressHash, + walletAddressHash: this.walletAddressHash, + walletType: this.walletType, }; } @@ -80,17 +88,18 @@ export class Analytics { * `identify()`, you must do that on your own. */ setDeviceId(deviceId: string) { - logger.debug(`[Analytics]: Set deviceId on analytics instance`); this.deviceId = deviceId; + logger.debug(`[Analytics]: Set deviceId on analytics instance`); } /** - * Set `currentWalletAddressHash` for use in events. This DOES NOT call + * Set `walletAddressHash` and `walletType` for use in events. This DOES NOT call * `identify()`, you must do that on your own. */ - setCurrentWalletAddressHash(currentWalletAddressHash: string) { - logger.debug(`[Analytics]: Set currentWalletAddressHash on analytics instance`); - this.currentWalletAddressHash = currentWalletAddressHash; + setWalletContext(walletContext: WalletContext) { + this.walletAddressHash = walletContext.walletAddressHash; + this.walletType = walletContext.walletType; + logger.debug(`[Analytics]: Set walletAddressHash on analytics instance`); } /** diff --git a/src/analytics/utils.ts b/src/analytics/utils.ts index 450ed5666ff..042edf95da2 100644 --- a/src/analytics/utils.ts +++ b/src/analytics/utils.ts @@ -1,11 +1,15 @@ import { nanoid } from 'nanoid/non-secure'; import { SECURE_WALLET_HASH_KEY } from 'react-native-dotenv'; +import type { Address } from 'viem'; import * as ls from '@/storage'; import * as keychain from '@/model/keychain'; import { analyticsUserIdentifier } from '@/utils/keychainConstants'; import { logger, RainbowError } from '@/logger'; import { computeHmac, SupportedAlgorithm } from '@ethersproject/sha2'; +import { findWalletWithAccount } from '@/helpers/findWalletWithAccount'; +import store from '@/redux/store'; +import { EthereumWalletType } from '@/helpers/walletTypes'; /** * Returns the device id in a type-safe manner. It will throw if no device ID @@ -58,7 +62,7 @@ export async function getOrCreateDeviceId(): Promise<[string, boolean]> { } } -export function securelyHashWalletAddress(walletAddress: `0x${string}`): string | undefined { +function securelyHashWalletAddress(walletAddress: Address): string | undefined { if (!SECURE_WALLET_HASH_KEY) { logger.error(new RainbowError(`[securelyHashWalletAddress]: Required .env variable SECURE_WALLET_HASH_KEY does not exist`)); } @@ -80,3 +84,33 @@ export function securelyHashWalletAddress(walletAddress: `0x${string}`): string logger.error(new RainbowError(`[securelyHashWalletAddress]: Wallet address hashing failed`)); } } + +export type WalletContext = { + walletType?: 'owned' | 'hardware' | 'watched'; + walletAddressHash?: string; +}; + +export async function getWalletContext(address: Address): Promise { + // currentAddressStore address is initialized to '' + if (!address || address === ('' as Address)) return {}; + + // walletType maybe undefined after initial wallet creation + const { wallets } = store.getState(); + const wallet = findWalletWithAccount(wallets.wallets || {}, address); + + const walletType = ( + { + [EthereumWalletType.mnemonic]: 'owned', + [EthereumWalletType.privateKey]: 'owned', + [EthereumWalletType.seed]: 'owned', + [EthereumWalletType.readOnly]: 'watched', + [EthereumWalletType.bluetooth]: 'hardware', + } as const + )[wallet?.type!]; + const walletAddressHash = securelyHashWalletAddress(address); + + return { + walletType, + walletAddressHash, + }; +} diff --git a/src/components/DappBrowser/BrowserTab.tsx b/src/components/DappBrowser/BrowserTab.tsx index 02cca1a6425..ac17646ff46 100644 --- a/src/components/DappBrowser/BrowserTab.tsx +++ b/src/components/DappBrowser/BrowserTab.tsx @@ -1,7 +1,7 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ import React, { useCallback, useEffect, useLayoutEffect, useRef } from 'react'; import { Freeze } from 'react-freeze'; -import { StyleSheet } from 'react-native'; +import { Linking, StyleSheet } from 'react-native'; import { PanGestureHandler, PanGestureHandlerGestureEvent, @@ -52,7 +52,7 @@ import { useAnimatedTab } from './hooks/useAnimatedTab'; import { useTabScreenshotProvider } from './hooks/useTabScreenshotProvider'; import { freezeWebsite, getWebsiteMetadata, unfreezeWebsite } from './scripts'; import { BrowserTabProps, ScreenshotType } from './types'; -import { normalizeUrlForRecents } from './utils'; +import { isValidAppStoreUrl } from './utils'; export const BrowserTab = React.memo(function BrowserTab({ addRecent, setLogo, setTitle, tabId }: BrowserTabProps) { const { isDarkMode } = useColorMode(); @@ -309,6 +309,12 @@ const FreezableWebViewComponent = ({ (syntheticEvent: { nativeEvent: { targetUrl: string } }) => { const { nativeEvent } = syntheticEvent; const { targetUrl } = nativeEvent; + + if (isValidAppStoreUrl(targetUrl)) { + Linking.openURL(targetUrl); + return; + } + setParams({ url: targetUrl }); }, [setParams] diff --git a/src/components/DappBrowser/constants.ts b/src/components/DappBrowser/constants.ts index c3e29fd02cd..907f0faf194 100644 --- a/src/components/DappBrowser/constants.ts +++ b/src/components/DappBrowser/constants.ts @@ -6,6 +6,11 @@ export const HTTP = 'http://'; export const HTTPS = 'https://'; export const RAINBOW_HOME = 'RAINBOW_HOME'; +export const IOS_APP_STORE_URL_PREFIXES = ['itms-apps://', 'itms-appss://', 'https://itunes.apple.com', 'https://apps.apple.com']; +export const ANDROID_APP_STORE_URL_PREFIXES = ['market://', 'https://play.google.com/store']; + +export const APP_STORE_URL_PREFIXES = [...IOS_APP_STORE_URL_PREFIXES, ...ANDROID_APP_STORE_URL_PREFIXES]; + export const USER_AGENT = { IOS: 'Mozilla/5.0 (iPhone; CPU iPhone OS 17_4_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.4.1 Mobile/15E148 Safari/604.1', ANDROID: 'Mozilla/5.0 (Linux; Android 14) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.6533.103 Mobile Safari/537.36', diff --git a/src/components/DappBrowser/search/Search.tsx b/src/components/DappBrowser/search/Search.tsx index df2ef1470db..d8f2983f1fc 100644 --- a/src/components/DappBrowser/search/Search.tsx +++ b/src/components/DappBrowser/search/Search.tsx @@ -7,11 +7,11 @@ import React, { useCallback } from 'react'; import { StyleSheet, View } from 'react-native'; import Animated, { SharedValue, runOnJS, useAnimatedStyle, useSharedValue, withSpring } from 'react-native-reanimated'; import { useBrowserContext } from '../BrowserContext'; -import { GOOGLE_SEARCH_URL, HTTP, HTTPS } from '../constants'; +import { GOOGLE_SEARCH_URL, HTTPS } from '../constants'; import { AccountIcon } from '../search-input/AccountIcon'; import { SearchInput } from '../search-input/SearchInput'; import { TabButton } from '../search-input/TabButton'; -import { isValidURL, isValidURLWorklet } from '../utils'; +import { isMissingValidProtocolWorklet, isValidURLWorklet } from '../utils'; import { DEVICE_WIDTH } from '@/utils/deviceUtils'; import { useBrowserWorkletsContext } from '../BrowserWorkletsContext'; import { SearchResults } from './results/SearchResults'; @@ -70,9 +70,9 @@ export const Search = () => { (updatedUrl: string) => { let newUrl = updatedUrl; - if (!isValidURL(newUrl)) { + if (!isValidURLWorklet(newUrl)) { newUrl = GOOGLE_SEARCH_URL + newUrl; - } else if (!newUrl.startsWith(HTTP) && !newUrl.startsWith(HTTPS)) { + } else if (isMissingValidProtocolWorklet(newUrl)) { newUrl = HTTPS + newUrl; } @@ -94,7 +94,7 @@ export const Search = () => { if (!isValidURLWorklet(newUrl)) { newUrl = GOOGLE_SEARCH_URL + newUrl; - } else if (!newUrl.startsWith(HTTP) && !newUrl.startsWith(HTTPS)) { + } else if (isMissingValidProtocolWorklet(newUrl)) { newUrl = HTTPS + newUrl; } diff --git a/src/components/DappBrowser/utils.ts b/src/components/DappBrowser/utils.ts index 7d1d885311b..93ce83b5fe3 100644 --- a/src/components/DappBrowser/utils.ts +++ b/src/components/DappBrowser/utils.ts @@ -1,7 +1,7 @@ import { Share } from 'react-native'; import { WebViewNavigationEvent } from 'react-native-webview/lib/RNCWebViewNativeComponent'; import { RainbowError, logger } from '@/logger'; -import { HTTP, HTTPS, RAINBOW_HOME } from './constants'; +import { HTTP, HTTPS, RAINBOW_HOME, APP_STORE_URL_PREFIXES } from './constants'; // ---------------------------------------------------------------------------- // // URL validation regex breakdown here: https://mathiasbynens.be/demo/url-regex @@ -12,44 +12,35 @@ import { HTTP, HTTPS, RAINBOW_HOME } from './constants'; const URL_PATTERN_REGEX = /^(?:(?:(?:https?):)?\/\/)(?:\S+(?::\S*)?@)?(?:(?!(?:10|127)(?:\.\d{1,3}){3})(?!(?:169\.254|192\.168)(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z0-9\u00a1-\uffff][a-z0-9\u00a1-\uffff_-]{0,62})?[a-z0-9\u00a1-\uffff]\.)+(?:[a-z\u00a1-\uffff]{2,}\.?))(?::\d{2,5})?(?:[/?#]\S*)?$/i; -export function isValidURL(url: string): boolean { - let urlForValidation = url.trim(); - if (!urlForValidation.startsWith(HTTP) && !urlForValidation.startsWith(HTTPS)) { - urlForValidation = HTTPS + urlForValidation; - } - return URL_PATTERN_REGEX.test(urlForValidation); +export function isMissingValidProtocol(url: string): boolean { + return !url.startsWith(HTTP) && !url.startsWith(HTTPS); +} + +export function isMissingValidProtocolWorklet(url: string): boolean { + 'worklet'; + return !url.startsWith(HTTP) && !url.startsWith(HTTPS); +} + +export function isValidAppStoreUrl(url: string): boolean { + return APP_STORE_URL_PREFIXES.some(prefix => url.startsWith(prefix)); } export function isValidURLWorklet(url: string): boolean { 'worklet'; let urlForValidation = url.trim(); - if (!urlForValidation.startsWith(HTTP) && !urlForValidation.startsWith(HTTPS)) { + if (isMissingValidProtocolWorklet(urlForValidation)) { urlForValidation = HTTPS + urlForValidation; } return URL_PATTERN_REGEX.test(urlForValidation); } -export const normalizeUrl = (url: string): string => { - if (!url) { - return ''; - } - let normalizedUrl = url; - if (!normalizedUrl.startsWith(HTTP) && !normalizedUrl.startsWith(HTTPS)) { - normalizedUrl = HTTPS + normalizedUrl; - } - if (!normalizedUrl.endsWith('/') && !normalizedUrl.includes('?')) { - normalizedUrl += '/'; - } - return normalizedUrl; -}; - export const normalizeUrlWorklet = (url: string): string => { 'worklet'; if (!url) { return ''; } let normalizedUrl = url; - if (!normalizedUrl.startsWith(HTTP) && !normalizedUrl.startsWith(HTTPS)) { + if (isMissingValidProtocolWorklet(normalizedUrl)) { normalizedUrl = HTTPS + normalizedUrl; } if (!normalizedUrl.endsWith('/') && !normalizedUrl.includes('?')) { @@ -88,12 +79,6 @@ export const formatUrl = (url: string, formatSearches = true, prettifyUrl = true return formattedValue; }; -export const generateUniqueId = (): string => { - const timestamp = Date.now().toString(36); - const randomString = Math.random().toString(36).slice(2, 7); - return `${timestamp}${randomString}`; -}; - export function generateUniqueIdWorklet(): string { 'worklet'; const timestamp = Date.now().toString(36); diff --git a/src/handlers/swap.ts b/src/handlers/swap.ts index 8dacc675b13..9a537286856 100644 --- a/src/handlers/swap.ts +++ b/src/handlers/swap.ts @@ -1,14 +1,6 @@ import { BigNumberish } from '@ethersproject/bignumber'; import { Block, StaticJsonRpcProvider } from '@ethersproject/providers'; -import { - CrosschainQuote, - getQuoteExecutionDetails, - getRainbowRouterContractAddress, - getWrappedAssetMethod, - PermitSupportedTokenList, - Quote, - SwapType, -} from '@rainbow-me/swaps'; +import { CrosschainQuote, getQuoteExecutionDetails, getRainbowRouterContractAddress, Quote } from '@rainbow-me/swaps'; import { Contract } from '@ethersproject/contracts'; import { MaxUint256 } from '@ethersproject/constants'; import { IS_TESTING } from 'react-native-dotenv'; @@ -184,73 +176,6 @@ export const getSwapGasLimitWithFakeApproval = async ( return getDefaultGasLimitForTrade(tradeDetails, chainId); }; -export const estimateSwapGasLimit = async ({ - chainId, - requiresApprove, - tradeDetails, -}: { - chainId: ChainId; - requiresApprove?: boolean; - tradeDetails: Quote | null; -}): Promise => { - const provider = getProvider({ chainId }); - if (!provider || !tradeDetails) { - return ethereumUtils.getBasicSwapGasLimit(Number(chainId)); - } - const isWrapNativeAsset = tradeDetails.swapType === SwapType.wrap; - const isUnwrapNativeAsset = tradeDetails.swapType === SwapType.unwrap; - - // Wrap / Unwrap Eth - if (isWrapNativeAsset || isUnwrapNativeAsset) { - const default_estimate = isWrapNativeAsset ? ethUnits.weth_wrap : ethUnits.weth_unwrap; - try { - const gasLimit = await estimateGasWithPadding( - { - from: tradeDetails.from, - value: isWrapNativeAsset ? tradeDetails.buyAmount : '0', - }, - getWrappedAssetMethod(isWrapNativeAsset ? 'deposit' : 'withdraw', provider, chainId as number), - // @ts-ignore - isUnwrapNativeAsset ? [tradeDetails.buyAmount] : null, - provider, - 1.002 - ); - - return gasLimit || tradeDetails?.defaultGasLimit || default_estimate; - } catch (e) { - return tradeDetails?.defaultGasLimit || default_estimate; - } - // Swap - } else { - try { - const { params, method, methodArgs } = getQuoteExecutionDetails(tradeDetails, { from: tradeDetails.from }, provider); - - if (requiresApprove) { - if (CHAIN_IDS_WITH_TRACE_SUPPORT.includes(chainId) && IS_TESTING !== 'true') { - try { - const gasLimitWithFakeApproval = await getSwapGasLimitWithFakeApproval(chainId, provider, tradeDetails); - logger.debug('[swap]: Got gasLimitWithFakeApproval!', { - gasLimitWithFakeApproval, - }); - return gasLimitWithFakeApproval; - } catch (e) { - logger.error(new RainbowError('[swap]: Error estimating swap gas limit with approval'), { - error: e, - }); - } - } - - return getDefaultGasLimitForTrade(tradeDetails, chainId); - } - - const gasLimit = await estimateGasWithPadding(params, method, methodArgs as any, provider, SWAP_GAS_PADDING); - return gasLimit || getDefaultGasLimitForTrade(tradeDetails, chainId); - } catch (error) { - return getDefaultGasLimitForTrade(tradeDetails, chainId); - } - } -}; - export const estimateCrosschainSwapGasLimit = async ({ chainId, requiresApprove, diff --git a/src/handlers/tokenSearch.ts b/src/handlers/tokenSearch.ts index 6626776c55a..e03d7452837 100644 --- a/src/handlers/tokenSearch.ts +++ b/src/handlers/tokenSearch.ts @@ -1,17 +1,15 @@ import { isAddress } from '@ethersproject/address'; import { qs } from 'url-parse'; import { RainbowFetchClient } from '../rainbow-fetch'; -import { TokenSearchThreshold, TokenSearchTokenListId, TokenSearchUniswapAssetKey } from '@/entities'; +import { TokenSearchThreshold, TokenSearchTokenListId } from '@/entities'; import { logger, RainbowError } from '@/logger'; -import { EthereumAddress } from '@rainbow-me/swaps'; import { RainbowToken, TokenSearchToken } from '@/entities/tokens'; import { chainsName } from '@/chains'; +import { ChainId } from '@/chains/types'; -type TokenSearchApiResponse = { - data: TokenSearchToken[]; -}; +const ALL_VERIFIED_TOKENS_PARAM = '/?list=verifiedAssets'; -const tokenSearchApi = new RainbowFetchClient({ +const tokenSearchHttp = new RainbowFetchClient({ baseURL: 'https://token-search.rainbow.me/v2', headers: { 'Accept': 'application/json', @@ -20,50 +18,77 @@ const tokenSearchApi = new RainbowFetchClient({ timeout: 30000, }); +function parseTokenSearch(assets: TokenSearchToken[]): RainbowToken[] { + return assets.map(token => { + const networkKeys = Object.keys(token.networks); + const chainId = Number(networkKeys[0]); + const network = chainsName[chainId]; + return { + ...token, + chainId, + address: token.networks['1']?.address || token.networks[chainId]?.address, + network, + mainnet_address: token.networks['1']?.address, + }; + }); +} + export const tokenSearch = async (searchParams: { - chainId: number; + chainId: ChainId; fromChainId?: number | ''; - keys: TokenSearchUniswapAssetKey[]; + keys: (keyof RainbowToken)[]; list: TokenSearchTokenListId; threshold: TokenSearchThreshold; query: string; }): Promise => { const queryParams: { - keys: TokenSearchUniswapAssetKey[]; + keys: string; list: TokenSearchTokenListId; threshold: TokenSearchThreshold; query?: string; fromChainId?: number; } = { - keys: searchParams.keys, + keys: searchParams.keys.join(','), list: searchParams.list, threshold: searchParams.threshold, query: searchParams.query, }; + const { chainId, query } = searchParams; + + const isAddressSearch = query && isAddress(query); + + if (isAddressSearch) { + queryParams.keys = `networks.${chainId}.address`; + } + + const url = `/?${qs.stringify(queryParams)}`; + const isSearchingVerifiedAssets = queryParams.list === 'verifiedAssets'; + try { - if (isAddress(searchParams.query)) { - // @ts-ignore - params.keys = `networks.${searchParams.chainId}.address`; + const tokenSearch = await tokenSearchHttp.get<{ data: TokenSearchToken[] }>(url); + + if (isAddressSearch && isSearchingVerifiedAssets) { + if (tokenSearch && tokenSearch.data.data.length > 0) { + return parseTokenSearch(tokenSearch.data.data); + } + + const allVerifiedTokens = await tokenSearchHttp.get<{ data: TokenSearchToken[] }>(ALL_VERIFIED_TOKENS_PARAM); + + const addressQuery = query.trim().toLowerCase(); + + const addressMatchesOnOtherChains = allVerifiedTokens.data.data.filter(a => + Object.values(a.networks).some(n => n?.address === addressQuery) + ); + + return parseTokenSearch(addressMatchesOnOtherChains); } - const url = `/?${qs.stringify(queryParams)}`; - const tokenSearch = await tokenSearchApi.get(url); + if (!tokenSearch.data?.data) { return []; } - return tokenSearch.data.data.map(token => { - const networkKeys = Object.keys(token.networks); - const chainId = Number(networkKeys[0]); - const network = chainsName[chainId]; - return { - ...token, - chainId, - address: token.networks['1']?.address || token.networks[chainId]?.address, - network, - mainnet_address: token.networks['1']?.address, - }; - }); + return parseTokenSearch(tokenSearch.data.data); } catch (e: any) { logger.error(new RainbowError(`[tokenSearch]: An error occurred while searching for query`), { query: searchParams.query, diff --git a/src/handlers/web3.ts b/src/handlers/web3.ts index ec3244df2ab..fd5ad561fd4 100644 --- a/src/handlers/web3.ts +++ b/src/handlers/web3.ts @@ -103,8 +103,8 @@ export const isTestnetChain = ({ chainId = ChainId.mainnet }: { chainId?: ChainI return !!defaultChains[chainId].testnet; }; -// shoudl figure out better way to include this in networks -export const getFlashbotsProvider = async () => { +// TODO: should figure out better way to include this in networks +export const getFlashbotsProvider = () => { return new StaticJsonRpcProvider( proxyCustomRpcEndpoint( ChainId.mainnet, diff --git a/src/hooks/useInitializeWallet.ts b/src/hooks/useInitializeWallet.ts index bf7348f4791..80aa4e903ea 100644 --- a/src/hooks/useInitializeWallet.ts +++ b/src/hooks/useInitializeWallet.ts @@ -19,6 +19,10 @@ import { WrappedAlert as Alert } from '@/helpers/alert'; import { PROFILES, useExperimentalFlag } from '@/config'; import { runKeychainIntegrityChecks } from '@/handlers/walletReadyEvents'; import { RainbowError, logger } from '@/logger'; +import { getOrCreateDeviceId, getWalletContext } from '@/analytics/utils'; +import * as Sentry from '@sentry/react-native'; +import { analyticsV2 } from '@/analytics'; +import { Address } from 'viem'; export default function useInitializeWallet() { const dispatch = useDispatch(); @@ -82,6 +86,22 @@ export default function useInitializeWallet() { walletAddress, }); + // Capture wallet context in telemetry + // walletType maybe undefied after initial wallet creation + const { walletType, walletAddressHash } = await getWalletContext(walletAddress as Address); + const [deviceId] = await getOrCreateDeviceId(); + + Sentry.setUser({ + id: deviceId, + walletAddressHash, + walletType, + }); + + // Allows calling telemetry before currentAddress is available (i.e. onboarding) + if (walletType || walletAddressHash) analyticsV2.setWalletContext({ walletAddressHash, walletType }); + analyticsV2.setDeviceId(deviceId); + analyticsV2.identify(); + if (!switching) { // Run keychain integrity checks right after walletInit // Except when switching wallets! diff --git a/src/raps/actions/crosschainSwap.ts b/src/raps/actions/crosschainSwap.ts index 6df8f65cf40..4ce949d8582 100644 --- a/src/raps/actions/crosschainSwap.ts +++ b/src/raps/actions/crosschainSwap.ts @@ -2,6 +2,8 @@ import { Signer } from '@ethersproject/abstract-signer'; import { CrosschainQuote, fillCrosschainQuote } from '@rainbow-me/swaps'; import { Address } from 'viem'; import { estimateGasWithPadding, getProvider, toHex } from '@/handlers/web3'; +import { add } from '@/helpers/utilities'; +import { assetNeedsUnlocking, estimateApprove } from './unlock'; import { REFERRER, gasUnits, ReferrerType } from '@/references'; import { ChainId } from '@/chains/types'; @@ -10,7 +12,8 @@ import { addNewTransaction } from '@/state/pendingTransactions'; import { RainbowError, logger } from '@/logger'; import { TransactionGasParams, TransactionLegacyGasParams } from '@/__swaps__/types/gas'; -import { ActionProps, RapActionResult } from '../references'; +import { ActionProps, RapActionResult, RapSwapActionParameters } from '../references'; + import { CHAIN_IDS_WITH_TRACE_SUPPORT, SWAP_GAS_PADDING, @@ -27,6 +30,65 @@ import { chainsName } from '@/chains'; const getCrosschainSwapDefaultGasLimit = (quote: CrosschainQuote) => quote?.routes?.[0]?.userTxs?.[0]?.gasFees?.gasLimit; +export const estimateUnlockAndCrosschainSwap = async ({ + sellAmount, + quote, + chainId, + assetToSell, +}: Pick, 'sellAmount' | 'quote' | 'chainId' | 'assetToSell'>) => { + const { + from: accountAddress, + sellTokenAddress, + allowanceTarget, + allowanceNeeded, + } = quote as { + from: Address; + sellTokenAddress: Address; + allowanceTarget: Address; + allowanceNeeded: boolean; + }; + + let gasLimits: (string | number)[] = []; + let swapAssetNeedsUnlocking = false; + + if (allowanceNeeded) { + swapAssetNeedsUnlocking = await assetNeedsUnlocking({ + owner: accountAddress, + amount: sellAmount, + assetToUnlock: assetToSell, + spender: allowanceTarget, + chainId, + }); + } + + if (swapAssetNeedsUnlocking) { + const unlockGasLimit = await estimateApprove({ + owner: accountAddress, + tokenAddress: sellTokenAddress, + spender: allowanceTarget, + chainId, + }); + gasLimits = gasLimits.concat(unlockGasLimit); + } + + const swapGasLimit = await estimateCrosschainSwapGasLimit({ + chainId, + requiresApprove: swapAssetNeedsUnlocking, + quote, + }); + + if (swapGasLimit === null || swapGasLimit === undefined || isNaN(Number(swapGasLimit))) { + return getCrosschainSwapDefaultGasLimit(quote) || getDefaultGasLimitForTrade(quote, chainId); + } + + const gasLimit = gasLimits.concat(swapGasLimit).reduce((acc, limit) => add(acc, limit), '0'); + if (isNaN(Number(gasLimit))) { + return getCrosschainSwapDefaultGasLimit(quote) || getDefaultGasLimitForTrade(quote, chainId); + } + + return gasLimit.toString(); +}; + export const estimateCrosschainSwapGasLimit = async ({ chainId, requiresApprove, @@ -112,7 +174,7 @@ export const crosschainSwap = async ({ gasParams, gasFeeParamsBySpeed, }: ActionProps<'crosschainSwap'>): Promise => { - const { quote, chainId, requiresApprove } = parameters; + const { assetToSell, sellAmount, quote, chainId } = parameters; let gasParamsToUse = gasParams; if (currentRap.actions.length - 1 > index) { @@ -125,10 +187,11 @@ export const crosschainSwap = async ({ let gasLimit; try { - gasLimit = await estimateCrosschainSwapGasLimit({ - chainId, - requiresApprove, + gasLimit = await estimateUnlockAndCrosschainSwap({ + sellAmount, quote, + chainId, + assetToSell, }); } catch (e) { logger.error(new RainbowError('[raps/crosschainSwap]: error estimateCrosschainSwapGasLimit'), { @@ -187,7 +250,7 @@ export const crosschainSwap = async ({ price: nativePriceForAssetToBuy, } satisfies ParsedAsset; - const assetToSell = { + const updatedAssetToSell = { ...parameters.assetToSell, network: chainsName[parameters.assetToSell.chainId], networks: parameters.assetToSell.networks as Record, @@ -206,7 +269,7 @@ export const crosschainSwap = async ({ { direction: TransactionDirection.OUT, asset: { - ...assetToSell, + ...updatedAssetToSell, native: undefined, }, value: quote.sellAmount.toString(), diff --git a/src/raps/actions/swap.ts b/src/raps/actions/swap.ts index 12164beb055..cc0c6d35550 100644 --- a/src/raps/actions/swap.ts +++ b/src/raps/actions/swap.ts @@ -24,7 +24,7 @@ import { RainbowError, logger } from '@/logger'; import { gasUnits, REFERRER } from '@/references'; import { TransactionGasParams, TransactionLegacyGasParams } from '@/__swaps__/types/gas'; -import { ActionProps, RapActionResult } from '../references'; +import { ActionProps, RapActionResult, RapSwapActionParameters } from '../references'; import { CHAIN_IDS_WITH_TRACE_SUPPORT, SWAP_GAS_PADDING, @@ -34,7 +34,7 @@ import { populateSwap, } from '../utils'; -import { populateApprove } from './unlock'; +import { assetNeedsUnlocking, estimateApprove, populateApprove } from './unlock'; import { TokenColors } from '@/graphql/__generated__/metadata'; import { swapMetadataStorage } from '../common'; import { AddysNetworkDetails, ParsedAsset } from '@/resources/assets/types'; @@ -45,6 +45,73 @@ import { chainsName } from '@/chains'; const WRAP_GAS_PADDING = 1.002; +export const estimateUnlockAndSwap = async ({ + sellAmount, + quote, + chainId, + assetToSell, +}: Pick, 'sellAmount' | 'quote' | 'chainId' | 'assetToSell'>) => { + const { + from: accountAddress, + sellTokenAddress, + allowanceNeeded, + } = quote as { + from: Address; + sellTokenAddress: Address; + allowanceNeeded: boolean; + }; + + let gasLimits: (string | number)[] = []; + let swapAssetNeedsUnlocking = false; + + if (allowanceNeeded) { + swapAssetNeedsUnlocking = await assetNeedsUnlocking({ + owner: accountAddress, + amount: sellAmount, + assetToUnlock: assetToSell, + spender: getRainbowRouterContractAddress(chainId), + chainId, + }); + } + + if (swapAssetNeedsUnlocking) { + const gasLimitFromMetadata = await estimateUnlockAndSwapFromMetadata({ + swapAssetNeedsUnlocking, + chainId, + accountAddress, + sellTokenAddress, + quote, + }); + if (gasLimitFromMetadata) { + return gasLimitFromMetadata; + } + const unlockGasLimit = await estimateApprove({ + owner: accountAddress, + tokenAddress: sellTokenAddress, + spender: getRainbowRouterContractAddress(chainId), + chainId, + }); + gasLimits = gasLimits.concat(unlockGasLimit); + } + + const swapGasLimit = await estimateSwapGasLimit({ + chainId, + requiresApprove: swapAssetNeedsUnlocking, + quote, + }); + + if (swapGasLimit === null || swapGasLimit === undefined || isNaN(Number(swapGasLimit))) { + return getDefaultGasLimitForTrade(quote, chainId); + } + + const gasLimit = gasLimits.concat(swapGasLimit).reduce((acc, limit) => add(acc, limit), '0'); + if (isNaN(Number(gasLimit))) { + return getDefaultGasLimitForTrade(quote, chainId); + } + + return gasLimit.toString(); +}; + export const estimateSwapGasLimit = async ({ chainId, requiresApprove, @@ -238,7 +305,7 @@ export const swap = async ({ }: ActionProps<'swap'>): Promise => { let gasParamsToUse = gasParams; - const { quote, chainId, requiresApprove } = parameters; + const { assetToSell, quote, chainId, sellAmount } = parameters; // if swap isn't the last action, use fast gas or custom (whatever is faster) if (currentRap.actions.length - 1 > index) { @@ -251,9 +318,10 @@ export const swap = async ({ let gasLimit; try { - gasLimit = await estimateSwapGasLimit({ + gasLimit = await estimateUnlockAndSwap({ + sellAmount, + assetToSell, chainId, - requiresApprove, quote, }); } catch (e) { @@ -313,7 +381,7 @@ export const swap = async ({ price: nativePriceForAssetToBuy, } satisfies ParsedAsset; - const assetToSell = { + const updatedAssetToSell = { ...parameters.assetToSell, network: chainsName[parameters.assetToSell.chainId], networks: parameters.assetToSell.networks as Record, @@ -332,7 +400,7 @@ export const swap = async ({ { direction: TransactionDirection.OUT, asset: { - ...assetToSell, + ...updatedAssetToSell, native: undefined, }, value: quote.sellAmount.toString(), diff --git a/src/raps/unlockAndCrosschainSwap.ts b/src/raps/unlockAndCrosschainSwap.ts index f5d9ab1371d..d92b2265aec 100644 --- a/src/raps/unlockAndCrosschainSwap.ts +++ b/src/raps/unlockAndCrosschainSwap.ts @@ -1,71 +1,9 @@ import { Address } from 'viem'; -import { add } from '@/helpers/utilities'; - -import { assetNeedsUnlocking, estimateApprove } from './actions'; -import { estimateCrosschainSwapGasLimit } from './actions/crosschainSwap'; +import { assetNeedsUnlocking } from './actions'; import { createNewAction, createNewRap } from './common'; import { RapAction, RapSwapActionParameters, RapUnlockActionParameters } from './references'; -export const estimateUnlockAndCrosschainSwap = async ({ - sellAmount, - quote, - chainId, - assetToSell, -}: Pick, 'sellAmount' | 'quote' | 'chainId' | 'assetToSell'>) => { - const { - from: accountAddress, - sellTokenAddress, - allowanceTarget, - allowanceNeeded, - } = quote as { - from: Address; - sellTokenAddress: Address; - allowanceTarget: Address; - allowanceNeeded: boolean; - }; - - let gasLimits: (string | number)[] = []; - let swapAssetNeedsUnlocking = false; - - if (allowanceNeeded) { - swapAssetNeedsUnlocking = await assetNeedsUnlocking({ - owner: accountAddress, - amount: sellAmount, - assetToUnlock: assetToSell, - spender: allowanceTarget, - chainId, - }); - } - - if (swapAssetNeedsUnlocking) { - const unlockGasLimit = await estimateApprove({ - owner: accountAddress, - tokenAddress: sellTokenAddress, - spender: allowanceTarget, - chainId, - }); - gasLimits = gasLimits.concat(unlockGasLimit); - } - - const swapGasLimit = await estimateCrosschainSwapGasLimit({ - chainId, - requiresApprove: swapAssetNeedsUnlocking, - quote, - }); - - if (swapGasLimit === null || swapGasLimit === undefined || isNaN(Number(swapGasLimit))) { - return null; - } - - const gasLimit = gasLimits.concat(swapGasLimit).reduce((acc, limit) => add(acc, limit), '0'); - if (isNaN(Number(gasLimit))) { - return null; - } - - return gasLimit.toString(); -}; - export const createUnlockAndCrosschainSwapRap = async (swapParameters: RapSwapActionParameters<'crosschainSwap'>) => { let actions: RapAction<'crosschainSwap' | 'unlock'>[] = []; const { sellAmount, assetToBuy, quote, chainId, assetToSell } = swapParameters; diff --git a/src/raps/unlockAndSwap.ts b/src/raps/unlockAndSwap.ts index bdf1f9fb9f6..573397b1daf 100644 --- a/src/raps/unlockAndSwap.ts +++ b/src/raps/unlockAndSwap.ts @@ -1,80 +1,9 @@ import { getRainbowRouterContractAddress } from '@rainbow-me/swaps'; import { Address } from 'viem'; - -import { add } from '@/helpers/utilities'; - -import { assetNeedsUnlocking, estimateApprove, estimateSwapGasLimit } from './actions'; -import { estimateUnlockAndSwapFromMetadata } from './actions/swap'; +import { assetNeedsUnlocking } from './actions'; import { createNewAction, createNewRap } from './common'; import { RapAction, RapSwapActionParameters, RapUnlockActionParameters } from './references'; -export const estimateUnlockAndSwap = async ({ - sellAmount, - quote, - chainId, - assetToSell, -}: Pick, 'sellAmount' | 'quote' | 'chainId' | 'assetToSell'>) => { - const { - from: accountAddress, - sellTokenAddress, - allowanceNeeded, - } = quote as { - from: Address; - sellTokenAddress: Address; - allowanceNeeded: boolean; - }; - - let gasLimits: (string | number)[] = []; - let swapAssetNeedsUnlocking = false; - - if (allowanceNeeded) { - swapAssetNeedsUnlocking = await assetNeedsUnlocking({ - owner: accountAddress, - amount: sellAmount, - assetToUnlock: assetToSell, - spender: getRainbowRouterContractAddress(chainId), - chainId, - }); - } - - if (swapAssetNeedsUnlocking) { - const gasLimitFromMetadata = await estimateUnlockAndSwapFromMetadata({ - swapAssetNeedsUnlocking, - chainId, - accountAddress, - sellTokenAddress, - quote, - }); - if (gasLimitFromMetadata) { - return gasLimitFromMetadata; - } - const unlockGasLimit = await estimateApprove({ - owner: accountAddress, - tokenAddress: sellTokenAddress, - spender: getRainbowRouterContractAddress(chainId), - chainId, - }); - gasLimits = gasLimits.concat(unlockGasLimit); - } - - const swapGasLimit = await estimateSwapGasLimit({ - chainId, - requiresApprove: swapAssetNeedsUnlocking, - quote, - }); - - if (swapGasLimit === null || swapGasLimit === undefined || isNaN(Number(swapGasLimit))) { - return null; - } - - const gasLimit = gasLimits.concat(swapGasLimit).reduce((acc, limit) => add(acc, limit), '0'); - if (isNaN(Number(gasLimit))) { - return null; - } - - return gasLimit.toString(); -}; - export const createUnlockAndSwapRap = async (swapParameters: RapSwapActionParameters<'swap'>) => { let actions: RapAction<'swap' | 'unlock'>[] = []; diff --git a/src/raps/utils.ts b/src/raps/utils.ts index 284596be057..6da90630263 100644 --- a/src/raps/utils.ts +++ b/src/raps/utils.ts @@ -70,7 +70,7 @@ const getStateDiff = async (provider: Provider, quote: Quote | CrosschainQuote): value: '0x0', }, ['stateDiff'], - blockNumber - TRACE_CALL_BLOCK_NUMBER_OFFSET, + toHexNoLeadingZeros(blockNumber - TRACE_CALL_BLOCK_NUMBER_OFFSET), ]; const trace = await (provider as StaticJsonRpcProvider).send('trace_call', callParams); diff --git a/src/redux/__mocks__/store.ts b/src/redux/__mocks__/store.ts index ec0224288a3..e0f04cc705d 100644 --- a/src/redux/__mocks__/store.ts +++ b/src/redux/__mocks__/store.ts @@ -1,4 +1,4 @@ -export default { - getState: jest.fn(), - dispatch: jest.fn(), -}; +import { jest } from '@jest/globals'; + +export const getState = jest.fn(); +export const dispatch = jest.fn(); diff --git a/src/screens/SpeedUpAndCancelSheet.tsx b/src/screens/SpeedUpAndCancelSheet.tsx index 352df10fd8e..8fda0f1441a 100644 --- a/src/screens/SpeedUpAndCancelSheet.tsx +++ b/src/screens/SpeedUpAndCancelSheet.tsx @@ -312,19 +312,15 @@ export default function SpeedUpAndCancelSheet() { useEffect(() => { if (currentChainId) { startPollingGasFees(currentChainId, tx.flashbots); - const updateProvider = async () => { - let provider; - if (supportedFlashbotsChainIds.includes(tx.chainId || ChainId.mainnet) && tx.flashbots) { - logger.debug(`[SpeedUpAndCancelSheet]: using flashbots provider for chainId ${tx?.chainId}`); - provider = await getFlashbotsProvider(); - } else { - logger.debug(`[SpeedUpAndCancelSheet]: using provider for network ${tx?.chainId}`); - provider = getProvider({ chainId: currentChainId }); - } - setCurrentProvider(provider); - }; - - updateProvider(); + let provider; + if (supportedFlashbotsChainIds.includes(tx.chainId || ChainId.mainnet) && tx.flashbots) { + logger.debug(`[SpeedUpAndCancelSheet]: using flashbots provider for chainId ${tx?.chainId}`); + provider = getFlashbotsProvider(); + } else { + logger.debug(`[SpeedUpAndCancelSheet]: using provider for network ${tx?.chainId}`); + provider = getProvider({ chainId: currentChainId }); + } + setCurrentProvider(provider); return () => { stopPollingGasFees(); diff --git a/src/screens/points/components/AnimatedText.tsx b/src/screens/points/components/AnimatedText.tsx index 87aa1e7a2fc..4e1980357ce 100644 --- a/src/screens/points/components/AnimatedText.tsx +++ b/src/screens/points/components/AnimatedText.tsx @@ -1,7 +1,7 @@ import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'; -import { HapticFeedbackType } from '@/utils/haptics'; import { Bleed } from '@/design-system'; import { Text as RNText, StyleSheet } from 'react-native'; +import { HapticType, triggerHaptics } from 'react-native-turbo-haptics'; import { useTheme } from '@/theme'; import { useAnimationContext } from '../contexts/AnimationContext'; import { @@ -14,7 +14,7 @@ import { withSequence, withTiming, } from 'react-native-reanimated'; -import { generateRainbowColors, triggerHapticFeedback } from '../constants'; +import { generateRainbowColors } from '../constants'; import { fonts } from '@/styles'; type AnimatedTextProps = { @@ -22,7 +22,7 @@ type AnimatedTextProps = { delayStart?: number; disableShadow?: boolean; enableHapticTyping?: boolean; - hapticType?: HapticFeedbackType; + hapticType?: HapticType; multiline?: boolean; onComplete?: () => void; opacity?: number; @@ -145,7 +145,7 @@ export const AnimatedText = ({ runOnJS(setDisplayedText)(newText); if (enableHapticTyping && Math.round(current.displayedValue) && newText[newText.length - 1] !== ' ') { - runOnJS(triggerHapticFeedback)(hapticType); + triggerHaptics(hapticType); } } } diff --git a/src/screens/points/constants.ts b/src/screens/points/constants.ts index 2c83b2f3800..b1bd9e0b52b 100644 --- a/src/screens/points/constants.ts +++ b/src/screens/points/constants.ts @@ -1,5 +1,3 @@ -import ReactNativeHapticFeedback from 'react-native-haptic-feedback'; -import { HapticFeedbackType } from '@/utils/haptics'; import { safeAreaInsetValues } from '@/utils'; import { OnboardPointsMutation, PointsOnboardingCategory } from '@/graphql/__generated__/metadata'; import * as i18n from '@/languages'; @@ -69,8 +67,6 @@ export const generateRainbowColors = (text: string): Array<{ text: string; shado return colors; }; -export const triggerHapticFeedback = (hapticType: HapticFeedbackType) => ReactNativeHapticFeedback?.trigger(hapticType); - const BASE_URL = `https://twitter.com/intent/tweet?text=`; const NEWLINE_OR_SPACE = IS_IOS ? '\n\n' : ' '; export const buildTwitterIntentMessage = ( diff --git a/src/state/browser/browserStore.ts b/src/state/browser/browserStore.ts index ee3bf8f7be3..9133add6988 100644 --- a/src/state/browser/browserStore.ts +++ b/src/state/browser/browserStore.ts @@ -4,7 +4,7 @@ import { create } from 'zustand'; import { PersistStorage, StorageValue, persist, subscribeWithSelector } from 'zustand/middleware'; import { RAINBOW_HOME } from '@/components/DappBrowser/constants'; import { TabData, TabId } from '@/components/DappBrowser/types'; -import { generateUniqueId, normalizeUrl } from '@/components/DappBrowser/utils'; +import { generateUniqueIdWorklet, normalizeUrlWorklet } from '@/components/DappBrowser/utils'; import { RainbowError, logger } from '@/logger'; const BROWSER_STORAGE_ID = 'browserStore'; @@ -104,7 +104,7 @@ const persistedBrowserStorage: PersistStorage = { }; const INITIAL_ACTIVE_TAB_INDEX = 0; -const INITIAL_TAB_IDS = [generateUniqueId()]; +const INITIAL_TAB_IDS = [generateUniqueIdWorklet()]; const INITIAL_TABS_DATA = new Map([[INITIAL_TAB_IDS[0], { url: RAINBOW_HOME }]]); const INITIAL_PERSISTED_TAB_URLS: Record = { [INITIAL_TAB_IDS[0]]: RAINBOW_HOME }; @@ -154,7 +154,7 @@ export const useBrowserStore = create()( const existingTabData = state.tabsData.get(tabIdToUse); if (existingTabData?.url !== url) { const newTabsData = new Map(state.tabsData); - newTabsData.set(tabIdToUse, { ...existingTabData, url: normalizeUrl(url) }); + newTabsData.set(tabIdToUse, { ...existingTabData, url: normalizeUrlWorklet(url) }); return { tabsData: newTabsData }; } return state; diff --git a/src/utils/reviewAlert.ts b/src/utils/reviewAlert.ts index 4deef6eb9c9..dfbda01e918 100644 --- a/src/utils/reviewAlert.ts +++ b/src/utils/reviewAlert.ts @@ -1,13 +1,10 @@ import lang from 'i18n-js'; import * as ls from '@/storage'; -import { Linking, NativeModules } from 'react-native'; import { WrappedAlert as Alert } from '@/helpers/alert'; import { ReviewPromptAction } from '@/storage/schema'; -import { IS_IOS } from '@/env'; -import { logger } from '@/logger'; +import { logger, RainbowError } from '@/logger'; import { IS_TESTING } from 'react-native-dotenv'; - -const { RainbowRequestReview, RNReview } = NativeModules; +import * as StoreReview from 'expo-store-review'; export const AppleReviewAddress = 'itms-apps://itunes.apple.com/us/app/appName/id1457119021?mt=8&action=write-review'; @@ -78,17 +75,14 @@ export const handleReviewPromptAction = async (action: ReviewPromptAction) => { export const promptForReview = async () => { Alert.alert(lang.t('review.alert.are_you_enjoying_rainbow'), lang.t('review.alert.leave_a_review'), [ { - onPress: () => { - ls.review.set(['hasReviewed'], true); - - if (IS_IOS) { - RainbowRequestReview?.requestReview((handled: boolean) => { - if (!handled) { - Linking.openURL(AppleReviewAddress); - } + onPress: async () => { + try { + ls.review.set(['hasReviewed'], true); + await StoreReview.requestReview(); + } catch (e) { + logger.error(new RainbowError('[reviewAlert]: Failed to request review'), { + error: e, }); - } else { - RNReview.show(); } }, text: lang.t('review.alert.yes'), diff --git a/yarn.lock b/yarn.lock index cb5669f2082..52507af2276 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9300,6 +9300,7 @@ __metadata: ethereumjs-wallet: "npm:1.0.1" events: "npm:3.3.0" expo: "npm:51.0.33" + expo-store-review: "npm:7.0.2" fast-text-encoding: "npm:1.0.4" global: "npm:4.4.0" grapheme-splitter: "npm:1.0.4" @@ -9404,6 +9405,7 @@ __metadata: react-native-text-size: "rainbow-me/react-native-text-size#15b21c9f88c6df0d1b5e0f2ba792fe59b5dc255a" react-native-tooltip: "rainbow-me/react-native-tooltip#e0e88d212b5b7f350e5eabba87f588a32e0f2590" react-native-tooltips: "rainbow-me/react-native-tooltips#fdafbc7ba33ee231229f5d3f58b29d0d1c55ddfa" + react-native-turbo-haptics: "npm:1.0.4" react-native-udp: "npm:2.7.0" react-native-url-polyfill: "npm:2.0.0" react-native-version-number: "npm:0.3.6" @@ -15027,6 +15029,15 @@ __metadata: languageName: node linkType: hard +"expo-store-review@npm:7.0.2": + version: 7.0.2 + resolution: "expo-store-review@npm:7.0.2" + peerDependencies: + expo: "*" + checksum: 10c0/8a2e0622a0876bcdfdedcfda8a518cfa04c568007ff02d89e2409de00df00c8783fdf668aafada67bb1788b88e87113885355c2a0d5d07499d39bec357ca71f3 + languageName: node + linkType: hard + "expo@npm:51.0.33": version: 51.0.33 resolution: "expo@npm:51.0.33" @@ -23734,6 +23745,16 @@ react-native-safe-area-view@rainbow-me/react-native-safe-area-view: languageName: node linkType: hard +"react-native-turbo-haptics@npm:1.0.4": + version: 1.0.4 + resolution: "react-native-turbo-haptics@npm:1.0.4" + peerDependencies: + react: ^18.2.0 + react-native: ">=0.72.0" + checksum: 10c0/1c65d3c6380a438e55540cbdc82d865f26aa2b6c24364d2be5092c87f347115471162f8a61c8f9c71324d88bf392da7fbe19c4a489e74a8394bbbdf0664da24e + languageName: node + linkType: hard + "react-native-udp@npm:2.7.0": version: 2.7.0 resolution: "react-native-udp@npm:2.7.0"