diff --git a/single-factor-auth-ios/ios-aggregate-example/sfa-ios-aggregate-example.xcodeproj/project.pbxproj b/single-factor-auth-ios/ios-aggregate-example/sfa-ios-aggregate-example.xcodeproj/project.pbxproj new file mode 100644 index 00000000..981af57e --- /dev/null +++ b/single-factor-auth-ios/ios-aggregate-example/sfa-ios-aggregate-example.xcodeproj/project.pbxproj @@ -0,0 +1,475 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 56; + objects = { + +/* Begin PBXBuildFile section */ + 28D682972CA3AAAE00872DED /* SingleFactorAuth in Frameworks */ = {isa = PBXBuildFile; productRef = 28D682962CA3AAAE00872DED /* SingleFactorAuth */; }; + 28D6829A2CA3AB0A00872DED /* web3.swift in Frameworks */ = {isa = PBXBuildFile; productRef = 28D682992CA3AB0A00872DED /* web3.swift */; }; + 28D6829D2CA3AB2000872DED /* Auth0 in Frameworks */ = {isa = PBXBuildFile; productRef = 28D6829C2CA3AB2000872DED /* Auth0 */; }; + 28D682A02CA3AB2800872DED /* JWTDecode in Frameworks */ = {isa = PBXBuildFile; productRef = 28D6829F2CA3AB2800872DED /* JWTDecode */; }; + 28D682A22CA3B20D00872DED /* Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 28D682A12CA3B20D00872DED /* Extensions.swift */; }; + 28D682A52CA3BF7800872DED /* LoginView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 28D682A42CA3BF7800872DED /* LoginView.swift */; }; + 28D682A72CA3BFCA00872DED /* LoadingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 28D682A62CA3BFCA00872DED /* LoadingView.swift */; }; + 28D682A92CA3C03D00872DED /* HomeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 28D682A82CA3C03D00872DED /* HomeView.swift */; }; + 28DDAC452CA3269800D5C31A /* ios_aggregate_exampleApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 28DDAC442CA3269800D5C31A /* ios_aggregate_exampleApp.swift */; }; + 28DDAC472CA3269800D5C31A /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 28DDAC462CA3269800D5C31A /* ContentView.swift */; }; + 28DDAC492CA3269900D5C31A /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 28DDAC482CA3269900D5C31A /* Assets.xcassets */; }; + 28DDAC4C2CA3269900D5C31A /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 28DDAC4B2CA3269900D5C31A /* Preview Assets.xcassets */; }; + 28DDAC542CA3271000D5C31A /* EthereumClient.swift in Sources */ = {isa = PBXBuildFile; fileRef = 28DDAC532CA3271000D5C31A /* EthereumClient.swift */; }; + 28DDAC602CA3A52000D5C31A /* MainViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 28DDAC5F2CA3A52000D5C31A /* MainViewModel.swift */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 28D682A12CA3B20D00872DED /* Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Extensions.swift; sourceTree = ""; }; + 28D682A42CA3BF7800872DED /* LoginView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginView.swift; sourceTree = ""; }; + 28D682A62CA3BFCA00872DED /* LoadingView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoadingView.swift; sourceTree = ""; }; + 28D682A82CA3C03D00872DED /* HomeView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeView.swift; sourceTree = ""; }; + 28DDAC412CA3269800D5C31A /* ios-aggregate-example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "ios-aggregate-example.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 28DDAC442CA3269800D5C31A /* ios_aggregate_exampleApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ios_aggregate_exampleApp.swift; sourceTree = ""; }; + 28DDAC462CA3269800D5C31A /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = ""; }; + 28DDAC482CA3269900D5C31A /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 28DDAC4B2CA3269900D5C31A /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = ""; }; + 28DDAC532CA3271000D5C31A /* EthereumClient.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EthereumClient.swift; sourceTree = ""; }; + 28DDAC5F2CA3A52000D5C31A /* MainViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainViewModel.swift; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 28DDAC3E2CA3269800D5C31A /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 28D6829D2CA3AB2000872DED /* Auth0 in Frameworks */, + 28D6829A2CA3AB0A00872DED /* web3.swift in Frameworks */, + 28D682A02CA3AB2800872DED /* JWTDecode in Frameworks */, + 28D682972CA3AAAE00872DED /* SingleFactorAuth in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 28D682A32CA3BF0700872DED /* Views */ = { + isa = PBXGroup; + children = ( + 28DDAC462CA3269800D5C31A /* ContentView.swift */, + 28D682A42CA3BF7800872DED /* LoginView.swift */, + 28D682A62CA3BFCA00872DED /* LoadingView.swift */, + 28D682A82CA3C03D00872DED /* HomeView.swift */, + ); + path = Views; + sourceTree = ""; + }; + 28DDAC382CA3269800D5C31A = { + isa = PBXGroup; + children = ( + 28DDAC432CA3269800D5C31A /* ios-aggregate-example */, + 28DDAC422CA3269800D5C31A /* Products */, + ); + sourceTree = ""; + }; + 28DDAC422CA3269800D5C31A /* Products */ = { + isa = PBXGroup; + children = ( + 28DDAC412CA3269800D5C31A /* ios-aggregate-example.app */, + ); + name = Products; + sourceTree = ""; + }; + 28DDAC432CA3269800D5C31A /* ios-aggregate-example */ = { + isa = PBXGroup; + children = ( + 28D682A32CA3BF0700872DED /* Views */, + 28DDAC582CA3A3CE00D5C31A /* Models */, + 28DDAC522CA326EF00D5C31A /* Helpers */, + 28DDAC442CA3269800D5C31A /* ios_aggregate_exampleApp.swift */, + 28DDAC482CA3269900D5C31A /* Assets.xcassets */, + 28DDAC4A2CA3269900D5C31A /* Preview Content */, + ); + path = "ios-aggregate-example"; + sourceTree = ""; + }; + 28DDAC4A2CA3269900D5C31A /* Preview Content */ = { + isa = PBXGroup; + children = ( + 28DDAC4B2CA3269900D5C31A /* Preview Assets.xcassets */, + ); + path = "Preview Content"; + sourceTree = ""; + }; + 28DDAC522CA326EF00D5C31A /* Helpers */ = { + isa = PBXGroup; + children = ( + 28DDAC532CA3271000D5C31A /* EthereumClient.swift */, + 28D682A12CA3B20D00872DED /* Extensions.swift */, + ); + path = Helpers; + sourceTree = ""; + }; + 28DDAC582CA3A3CE00D5C31A /* Models */ = { + isa = PBXGroup; + children = ( + 28DDAC5F2CA3A52000D5C31A /* MainViewModel.swift */, + ); + path = Models; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 28DDAC402CA3269800D5C31A /* ios-aggregate-example */ = { + isa = PBXNativeTarget; + buildConfigurationList = 28DDAC4F2CA3269900D5C31A /* Build configuration list for PBXNativeTarget "ios-aggregate-example" */; + buildPhases = ( + 28DDAC3D2CA3269800D5C31A /* Sources */, + 28DDAC3E2CA3269800D5C31A /* Frameworks */, + 28DDAC3F2CA3269800D5C31A /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "ios-aggregate-example"; + packageProductDependencies = ( + 28D682962CA3AAAE00872DED /* SingleFactorAuth */, + 28D682992CA3AB0A00872DED /* web3.swift */, + 28D6829C2CA3AB2000872DED /* Auth0 */, + 28D6829F2CA3AB2800872DED /* JWTDecode */, + ); + productName = "ios-aggregate-example"; + productReference = 28DDAC412CA3269800D5C31A /* ios-aggregate-example.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 28DDAC392CA3269800D5C31A /* Project object */ = { + isa = PBXProject; + attributes = { + BuildIndependentTargetsInParallel = 1; + LastSwiftUpdateCheck = 1540; + LastUpgradeCheck = 1540; + TargetAttributes = { + 28DDAC402CA3269800D5C31A = { + CreatedOnToolsVersion = 15.4; + }; + }; + }; + buildConfigurationList = 28DDAC3C2CA3269800D5C31A /* Build configuration list for PBXProject "ios-aggregate-example" */; + compatibilityVersion = "Xcode 14.0"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 28DDAC382CA3269800D5C31A; + packageReferences = ( + 28D682952CA3AAAE00872DED /* XCRemoteSwiftPackageReference "single-factor-auth-swift" */, + 28D682982CA3AB0A00872DED /* XCRemoteSwiftPackageReference "web3" */, + 28D6829B2CA3AB2000872DED /* XCRemoteSwiftPackageReference "Auth0" */, + 28D6829E2CA3AB2800872DED /* XCRemoteSwiftPackageReference "JWTDecode" */, + ); + productRefGroup = 28DDAC422CA3269800D5C31A /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 28DDAC402CA3269800D5C31A /* ios-aggregate-example */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 28DDAC3F2CA3269800D5C31A /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 28DDAC4C2CA3269900D5C31A /* Preview Assets.xcassets in Resources */, + 28DDAC492CA3269900D5C31A /* Assets.xcassets in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 28DDAC3D2CA3269800D5C31A /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 28D682A52CA3BF7800872DED /* LoginView.swift in Sources */, + 28D682A22CA3B20D00872DED /* Extensions.swift in Sources */, + 28DDAC472CA3269800D5C31A /* ContentView.swift in Sources */, + 28DDAC452CA3269800D5C31A /* ios_aggregate_exampleApp.swift in Sources */, + 28DDAC542CA3271000D5C31A /* EthereumClient.swift in Sources */, + 28D682A92CA3C03D00872DED /* HomeView.swift in Sources */, + 28D682A72CA3BFCA00872DED /* LoadingView.swift in Sources */, + 28DDAC602CA3A52000D5C31A /* MainViewModel.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 28DDAC4D2CA3269900D5C31A /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + GCC_C_LANGUAGE_STANDARD = gnu17; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 17.5; + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 28DDAC4E2CA3269900D5C31A /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + GCC_C_LANGUAGE_STANDARD = gnu17; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 17.5; + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + SDKROOT = iphoneos; + SWIFT_COMPILATION_MODE = wholemodule; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 28DDAC502CA3269900D5C31A /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_ASSET_PATHS = "\"ios-aggregate-example/Preview Content\""; + DEVELOPMENT_TEAM = 2Q63NCPY55; + ENABLE_PREVIEWS = YES; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES; + INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; + INFOPLIST_KEY_UILaunchScreen_Generation = YES; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = "com.w3a.ios-aggregate-example"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 28DDAC512CA3269900D5C31A /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_ASSET_PATHS = "\"ios-aggregate-example/Preview Content\""; + DEVELOPMENT_TEAM = 2Q63NCPY55; + ENABLE_PREVIEWS = YES; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES; + INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; + INFOPLIST_KEY_UILaunchScreen_Generation = YES; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = "com.w3a.ios-aggregate-example"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 28DDAC3C2CA3269800D5C31A /* Build configuration list for PBXProject "ios-aggregate-example" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 28DDAC4D2CA3269900D5C31A /* Debug */, + 28DDAC4E2CA3269900D5C31A /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 28DDAC4F2CA3269900D5C31A /* Build configuration list for PBXNativeTarget "ios-aggregate-example" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 28DDAC502CA3269900D5C31A /* Debug */, + 28DDAC512CA3269900D5C31A /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + +/* Begin XCRemoteSwiftPackageReference section */ + 28D682952CA3AAAE00872DED /* XCRemoteSwiftPackageReference "single-factor-auth-swift" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/Web3Auth/single-factor-auth-swift"; + requirement = { + kind = upToNextMajorVersion; + minimumVersion = 8.0.0; + }; + }; + 28D682982CA3AB0A00872DED /* XCRemoteSwiftPackageReference "web3" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/argentlabs/web3.swift"; + requirement = { + kind = upToNextMajorVersion; + minimumVersion = 1.6.1; + }; + }; + 28D6829B2CA3AB2000872DED /* XCRemoteSwiftPackageReference "Auth0" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/auth0/Auth0.swift"; + requirement = { + kind = upToNextMajorVersion; + minimumVersion = 2.9.0; + }; + }; + 28D6829E2CA3AB2800872DED /* XCRemoteSwiftPackageReference "JWTDecode" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/auth0/JWTDecode.swift"; + requirement = { + kind = upToNextMajorVersion; + minimumVersion = 3.2.0; + }; + }; +/* End XCRemoteSwiftPackageReference section */ + +/* Begin XCSwiftPackageProductDependency section */ + 28D682962CA3AAAE00872DED /* SingleFactorAuth */ = { + isa = XCSwiftPackageProductDependency; + package = 28D682952CA3AAAE00872DED /* XCRemoteSwiftPackageReference "single-factor-auth-swift" */; + productName = SingleFactorAuth; + }; + 28D682992CA3AB0A00872DED /* web3.swift */ = { + isa = XCSwiftPackageProductDependency; + package = 28D682982CA3AB0A00872DED /* XCRemoteSwiftPackageReference "web3" */; + productName = web3.swift; + }; + 28D6829C2CA3AB2000872DED /* Auth0 */ = { + isa = XCSwiftPackageProductDependency; + package = 28D6829B2CA3AB2000872DED /* XCRemoteSwiftPackageReference "Auth0" */; + productName = Auth0; + }; + 28D6829F2CA3AB2800872DED /* JWTDecode */ = { + isa = XCSwiftPackageProductDependency; + package = 28D6829E2CA3AB2800872DED /* XCRemoteSwiftPackageReference "JWTDecode" */; + productName = JWTDecode; + }; +/* End XCSwiftPackageProductDependency section */ + }; + rootObject = 28DDAC392CA3269800D5C31A /* Project object */; +} diff --git a/single-factor-auth-ios/ios-aggregate-example/sfa-ios-aggregate-example.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/single-factor-auth-ios/ios-aggregate-example/sfa-ios-aggregate-example.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 00000000..919434a6 --- /dev/null +++ b/single-factor-auth-ios/ios-aggregate-example/sfa-ios-aggregate-example.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/single-factor-auth-ios/ios-aggregate-example/sfa-ios-aggregate-example.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/single-factor-auth-ios/ios-aggregate-example/sfa-ios-aggregate-example.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 00000000..18d98100 --- /dev/null +++ b/single-factor-auth-ios/ios-aggregate-example/sfa-ios-aggregate-example.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/single-factor-auth-ios/ios-aggregate-example/sfa-ios-aggregate-example.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/single-factor-auth-ios/ios-aggregate-example/sfa-ios-aggregate-example.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 00000000..0c67376e --- /dev/null +++ b/single-factor-auth-ios/ios-aggregate-example/sfa-ios-aggregate-example.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,5 @@ + + + + + diff --git a/single-factor-auth-ios/ios-aggregate-example/sfa-ios-aggregate-example.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/single-factor-auth-ios/ios-aggregate-example/sfa-ios-aggregate-example.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved new file mode 100644 index 00000000..a2b9b281 --- /dev/null +++ b/single-factor-auth-ios/ios-aggregate-example/sfa-ios-aggregate-example.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -0,0 +1,222 @@ +{ + "originHash" : "d527885300ea30dd77e93e69a0aa3f988977e7c7c5af64a87454c1f55028de15", + "pins" : [ + { + "identity" : "auth0.swift", + "kind" : "remoteSourceControl", + "location" : "https://github.com/auth0/Auth0.swift", + "state" : { + "revision" : "0d9c3f3241e3defad065409ac3a071ee1c5a7e8a", + "version" : "2.9.0" + } + }, + { + "identity" : "bigint", + "kind" : "remoteSourceControl", + "location" : "https://github.com/attaswift/BigInt.git", + "state" : { + "revision" : "793a7fac0bfc318e85994bf6900652e827aef33e", + "version" : "5.4.1" + } + }, + { + "identity" : "curvelib.swift", + "kind" : "remoteSourceControl", + "location" : "https://github.com/tkey/curvelib.swift", + "state" : { + "revision" : "9f88bd5e56d1df443a908f7a7e81ae4f4d9170ea", + "version" : "1.0.1" + } + }, + { + "identity" : "fetch-node-details-swift", + "kind" : "remoteSourceControl", + "location" : "https://github.com/torusresearch/fetch-node-details-swift.git", + "state" : { + "revision" : "4bd96c33ba8d02d9e27190c5c7cedf09cfdfd656", + "version" : "6.0.3" + } + }, + { + "identity" : "generic-json-swift", + "kind" : "remoteSourceControl", + "location" : "https://github.com/iwill/generic-json-swift", + "state" : { + "revision" : "0a06575f4038b504e78ac330913d920f1630f510", + "version" : "2.0.2" + } + }, + { + "identity" : "jwtdecode.swift", + "kind" : "remoteSourceControl", + "location" : "https://github.com/auth0/JWTDecode.swift.git", + "state" : { + "revision" : "1e153ef009969543191970c66b7c60163c0b4a65", + "version" : "3.2.0" + } + }, + { + "identity" : "keychain-swift", + "kind" : "remoteSourceControl", + "location" : "https://github.com/evgenyneu/keychain-swift.git", + "state" : { + "revision" : "d108a1fa6189e661f91560548ef48651ed8d93b9", + "version" : "20.0.0" + } + }, + { + "identity" : "secp256k1.swift", + "kind" : "remoteSourceControl", + "location" : "https://github.com/GigaBitcoin/secp256k1.swift.git", + "state" : { + "revision" : "9683e8e311c76d8114cd308b697dad2f9fc58fed", + "version" : "0.17.0" + } + }, + { + "identity" : "session-manager-swift", + "kind" : "remoteSourceControl", + "location" : "https://github.com/Web3Auth/session-manager-swift.git", + "state" : { + "revision" : "67d5f7db655d02778861057fb280ecf47c923b09", + "version" : "5.0.0" + } + }, + { + "identity" : "simplekeychain", + "kind" : "remoteSourceControl", + "location" : "https://github.com/auth0/SimpleKeychain.git", + "state" : { + "revision" : "b694f155907b189bc82e93586695a26f558c742f", + "version" : "1.2.0" + } + }, + { + "identity" : "single-factor-auth-swift", + "kind" : "remoteSourceControl", + "location" : "https://github.com/Web3Auth/single-factor-auth-swift", + "state" : { + "revision" : "44e222ea3fcec4faf17c5813f832cfc1d2d06d4b", + "version" : "8.0.0" + } + }, + { + "identity" : "swift-atomics", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-atomics.git", + "state" : { + "revision" : "cd142fd2f64be2100422d658e7411e39489da985", + "version" : "1.2.0" + } + }, + { + "identity" : "swift-collections", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-collections.git", + "state" : { + "revision" : "671108c96644956dddcd89dd59c203dcdb36cec7", + "version" : "1.1.4" + } + }, + { + "identity" : "swift-http-types", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-http-types", + "state" : { + "revision" : "ae67c8178eb46944fd85e4dc6dd970e1f3ed6ccd", + "version" : "1.3.0" + } + }, + { + "identity" : "swift-log", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-log.git", + "state" : { + "revision" : "9cb486020ebf03bfa5b5df985387a14a98744537", + "version" : "1.6.1" + } + }, + { + "identity" : "swift-nio", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-nio.git", + "state" : { + "revision" : "9746cf80e29edfef2a39924a66731249223f42a3", + "version" : "2.72.0" + } + }, + { + "identity" : "swift-nio-extras", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-nio-extras.git", + "state" : { + "revision" : "d1ead62745cc3269e482f1c51f27608057174379", + "version" : "1.24.0" + } + }, + { + "identity" : "swift-nio-http2", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-nio-http2.git", + "state" : { + "revision" : "b5f7062b60e4add1e8c343ba4eb8da2e324b3a94", + "version" : "1.34.0" + } + }, + { + "identity" : "swift-nio-ssl", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-nio-ssl.git", + "state" : { + "revision" : "7b84abbdcef69cc3be6573ac12440220789dcd69", + "version" : "2.27.2" + } + }, + { + "identity" : "swift-nio-transport-services", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-nio-transport-services.git", + "state" : { + "revision" : "38ac8221dd20674682148d6451367f89c2652980", + "version" : "1.21.0" + } + }, + { + "identity" : "swift-system", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-system.git", + "state" : { + "revision" : "d2ba781702a1d8285419c15ee62fd734a9437ff5", + "version" : "1.3.2" + } + }, + { + "identity" : "torus-utils-swift", + "kind" : "remoteSourceControl", + "location" : "https://github.com/torusresearch/torus-utils-swift.git", + "state" : { + "revision" : "eda55b8537a600e657d19d4c452c0a36f217883c", + "version" : "9.0.1" + } + }, + { + "identity" : "web3.swift", + "kind" : "remoteSourceControl", + "location" : "https://github.com/argentlabs/web3.swift", + "state" : { + "revision" : "1e75f98a5738c470b23bbfffa9314e9f788df76b", + "version" : "1.6.1" + } + }, + { + "identity" : "websocket-kit", + "kind" : "remoteSourceControl", + "location" : "https://github.com/vapor/websocket-kit.git", + "state" : { + "revision" : "4232d34efa49f633ba61afde365d3896fc7f8740", + "version" : "2.15.0" + } + } + ], + "version" : 3 +} diff --git a/single-factor-auth-ios/ios-aggregate-example/sfa-ios-aggregate-example.xcodeproj/project.xcworkspace/xcuserdata/ayushb.xcuserdatad/UserInterfaceState.xcuserstate b/single-factor-auth-ios/ios-aggregate-example/sfa-ios-aggregate-example.xcodeproj/project.xcworkspace/xcuserdata/ayushb.xcuserdatad/UserInterfaceState.xcuserstate new file mode 100644 index 00000000..eae3b683 Binary files /dev/null and b/single-factor-auth-ios/ios-aggregate-example/sfa-ios-aggregate-example.xcodeproj/project.xcworkspace/xcuserdata/ayushb.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/single-factor-auth-ios/ios-aggregate-example/sfa-ios-aggregate-example.xcodeproj/project.xcworkspace/xcuserdata/ayushb.xcuserdatad/WorkspaceSettings.xcsettings b/single-factor-auth-ios/ios-aggregate-example/sfa-ios-aggregate-example.xcodeproj/project.xcworkspace/xcuserdata/ayushb.xcuserdatad/WorkspaceSettings.xcsettings new file mode 100644 index 00000000..bbfef027 --- /dev/null +++ b/single-factor-auth-ios/ios-aggregate-example/sfa-ios-aggregate-example.xcodeproj/project.xcworkspace/xcuserdata/ayushb.xcuserdatad/WorkspaceSettings.xcsettings @@ -0,0 +1,14 @@ + + + + + BuildLocationStyle + UseAppPreferences + CustomBuildLocationType + RelativeToDerivedData + DerivedDataLocationStyle + Default + ShowSharedSchemesAutomaticallyEnabled + + + diff --git a/single-factor-auth-ios/ios-aggregate-example/sfa-ios-aggregate-example.xcodeproj/xcuserdata/ayushb.xcuserdatad/xcschemes/xcschememanagement.plist b/single-factor-auth-ios/ios-aggregate-example/sfa-ios-aggregate-example.xcodeproj/xcuserdata/ayushb.xcuserdatad/xcschemes/xcschememanagement.plist new file mode 100644 index 00000000..02879aad --- /dev/null +++ b/single-factor-auth-ios/ios-aggregate-example/sfa-ios-aggregate-example.xcodeproj/xcuserdata/ayushb.xcuserdatad/xcschemes/xcschememanagement.plist @@ -0,0 +1,140 @@ + + + + + SchemeUserState + + Demo (Playground) 1.xcscheme + + isShown + + orderHint + 5 + + Demo (Playground) 2.xcscheme + + isShown + + orderHint + 6 + + Demo (Playground) 3.xcscheme + + isShown + + orderHint + 17 + + Demo (Playground) 4.xcscheme + + isShown + + orderHint + 18 + + Demo (Playground) 5.xcscheme + + isShown + + orderHint + 19 + + Demo (Playground).xcscheme + + isShown + + orderHint + 4 + + JWTDecode (Playground) 1.xcscheme + + isShown + + orderHint + 8 + + JWTDecode (Playground) 2.xcscheme + + isShown + + orderHint + 9 + + JWTDecode (Playground) 3.xcscheme + + isShown + + orderHint + 11 + + JWTDecode (Playground) 4.xcscheme + + isShown + + orderHint + 12 + + JWTDecode (Playground) 5.xcscheme + + isShown + + orderHint + 13 + + JWTDecode (Playground).xcscheme + + isShown + + orderHint + 7 + + Playground (Playground) 1.xcscheme + + isShown + + orderHint + 2 + + Playground (Playground) 2.xcscheme + + isShown + + orderHint + 3 + + Playground (Playground) 3.xcscheme + + isShown + + orderHint + 14 + + Playground (Playground) 4.xcscheme + + isShown + + orderHint + 15 + + Playground (Playground) 5.xcscheme + + isShown + + orderHint + 16 + + Playground (Playground).xcscheme + + isShown + + orderHint + 1 + + ios-aggregate-example.xcscheme_^#shared#^_ + + orderHint + 0 + + + + diff --git a/single-factor-auth-ios/ios-aggregate-example/sfa-ios-aggregate-example/Assets.xcassets/AccentColor.colorset/Contents.json b/single-factor-auth-ios/ios-aggregate-example/sfa-ios-aggregate-example/Assets.xcassets/AccentColor.colorset/Contents.json new file mode 100644 index 00000000..eb878970 --- /dev/null +++ b/single-factor-auth-ios/ios-aggregate-example/sfa-ios-aggregate-example/Assets.xcassets/AccentColor.colorset/Contents.json @@ -0,0 +1,11 @@ +{ + "colors" : [ + { + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/single-factor-auth-ios/ios-aggregate-example/sfa-ios-aggregate-example/Assets.xcassets/AppIcon.appiconset/Contents.json b/single-factor-auth-ios/ios-aggregate-example/sfa-ios-aggregate-example/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 00000000..13613e3e --- /dev/null +++ b/single-factor-auth-ios/ios-aggregate-example/sfa-ios-aggregate-example/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,13 @@ +{ + "images" : [ + { + "idiom" : "universal", + "platform" : "ios", + "size" : "1024x1024" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/single-factor-auth-ios/ios-aggregate-example/sfa-ios-aggregate-example/Assets.xcassets/Contents.json b/single-factor-auth-ios/ios-aggregate-example/sfa-ios-aggregate-example/Assets.xcassets/Contents.json new file mode 100644 index 00000000..73c00596 --- /dev/null +++ b/single-factor-auth-ios/ios-aggregate-example/sfa-ios-aggregate-example/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/single-factor-auth-ios/ios-aggregate-example/sfa-ios-aggregate-example/Helpers/EthereumClient.swift b/single-factor-auth-ios/ios-aggregate-example/sfa-ios-aggregate-example/Helpers/EthereumClient.swift new file mode 100644 index 00000000..d69b7198 --- /dev/null +++ b/single-factor-auth-ios/ios-aggregate-example/sfa-ios-aggregate-example/Helpers/EthereumClient.swift @@ -0,0 +1,92 @@ +// +// EthereumClient.swift +// ios-aggregate-example +// +// Created by Ayush B on 24/09/24. +// + +import Foundation +import Foundation +import web3 +import BigInt + +struct EthereumClient { + let web3Client: EthereumHttpClient! + var networkId: String = "11155111" + + init() { + self.web3Client = EthereumHttpClient( + url: URL(string: "https://1rpc.io/sepolia")!, + network: .fromString(networkId) + ) + } + + func getNonce(address: EthereumAddress) async throws -> Int{ + do { + let nonce = try await web3Client.eth_getTransactionCount( + address: address, block: .Latest + ) + return nonce + } catch let error { + throw error + } + } + + func getGasPrice() async throws -> BigUInt { + do { + let gasPrice = try await web3Client.eth_gasPrice() + return gasPrice + } catch let error { + throw error + } + } + + func getGasLimit(transaction: EthereumTransaction) async throws -> BigUInt { + do { + let gasLimit = try await web3Client.eth_estimateGas(transaction) + return gasLimit + } catch let error { + throw error + } + } + + func getBalance(address: EthereumAddress) async throws -> String { + do { + let balanceResponse = try await web3Client.eth_getBalance(address: address, block: .Latest) + guard let decimalWei = Double(balanceResponse.description) else { + return 0.description + } + + let balance = decimalWei / pow(Double(10), 18) + return balance.description + } catch let error { + throw error + } + } + + func broadcastSignedTransaction(transaction: SignedTransaction) async throws -> String { + do { + guard let transactionHex = transaction.raw?.web3.hexString else { + throw EthereumClientError.encodeIssue + } + + let data = try await web3Client.networkProvider.send( + method: "eth_sendRawTransaction", + params: [transactionHex], + receive: String.self + ) + + if let hash = data as? String { + return hash + } else { + throw EthereumClientError.unexpectedReturnValue + } + } catch let error { + throw error + } + } + + func getChainId() -> String { + return networkId + } +} diff --git a/single-factor-auth-ios/ios-aggregate-example/sfa-ios-aggregate-example/Helpers/Extensions.swift b/single-factor-auth-ios/ios-aggregate-example/sfa-ios-aggregate-example/Helpers/Extensions.swift new file mode 100644 index 00000000..765850fa --- /dev/null +++ b/single-factor-auth-ios/ios-aggregate-example/sfa-ios-aggregate-example/Helpers/Extensions.swift @@ -0,0 +1,26 @@ +// +// Extensions.swift +// ios-aggregate-example +// +// Created by Ayush B on 25/09/24. +// + +import Foundation +import SingleFactorAuth +import web3 + +extension SFAKey: EthereumSingleKeyStorageProtocol { + public func storePrivateKey(key: Data) throws { + + } + + public func loadPrivateKey() throws -> Data { + guard let privKeyData = Data.init(hex: self.getPrivateKey()) else { + // Todo make custom error + return Data() + } + return privKeyData + + } + +} diff --git a/single-factor-auth-ios/ios-aggregate-example/sfa-ios-aggregate-example/Models/MainViewModel.swift b/single-factor-auth-ios/ios-aggregate-example/sfa-ios-aggregate-example/Models/MainViewModel.swift new file mode 100644 index 00000000..9ad050bf --- /dev/null +++ b/single-factor-auth-ios/ios-aggregate-example/sfa-ios-aggregate-example/Models/MainViewModel.swift @@ -0,0 +1,248 @@ +// +// MainViewModel.swift +// ios-aggregate-example +// +// Created by Ayush B on 25/09/24. +// + +import Foundation +import web3 +import UIKit +import Auth0 +import JWTDecode +import SingleFactorAuth + +class MainViewModel: ObservableObject { + @Published var isLoggedIn: Bool = false + @Published var showAlert: Bool = false + @Published var isLoaderVisible: Bool = false + @Published var balance: String = "0.0" + + var publicAddress: String! + + + private var mpcCoreKit: SingleFactorAuth! + private var ethereumClient: EthereumClient! + private var ethereumAccount: EthereumAccount! + private var sfaKey: SFAKey! + private var webAuth: WebAuth! + var userInfo: [String: Any]! + var alertContent: String = "" + var loaderContent: String = "" + + func initialize() { + mpcCoreKit = try! SingleFactorAuth( + params: .init( + web3AuthClientId: "BPi5PB_UiIZ-cPz1GtV5i1I2iOSOHuimiXBI0e-Oe_u6X3oVAbCiAZOTEBtTXw4tsluTITPqA8zMsfxIKMjiqNQ", + network: .sapphire(.SAPPHIRE_MAINNET) + ) + ) + webAuth = Auth0.webAuth(clientId: "hUVVf4SEsZT7syOiL0gLU9hFEtm2gQ6O", domain: "web3auth.au.auth0.com") + + ethereumClient = EthereumClient() + checkSession() + } + + // com.w3a.ios-aggregate-example://web3auth.au.auth0.com/ios/com.w3a.ios-aggregate-example/callback + // com.example.MyApp://example.us.auth0.com/ios/com.example.MyApp/callback + + func loginWithGoogle() { + Task { + do { + showLoader("Login in") + let auth0Creds = try await webAuth.connection("google-oauth2").start() + + let jwt = try decode(jwt: auth0Creds.idToken) + guard let sub = jwt.body["email"] as? String else { + throw "Email not found in JWT" + } + + sfaKey = try await mpcCoreKit.connect(loginParams: .init( + verifier: "sfa-mobile-aggregate-verifier", + verifierId: sub, + idToken: auth0Creds.idToken, + subVerifierInfoArray: [ + TorusSubVerifierInfo(verifier: "sfa-mobile-aggregate-auth0-google", idToken: auth0Creds.idToken) + ] + ) + ) + + userInfo = jwt.body + try await login() + + hideLoader() + } catch let error { + hideLoader() + print(error.localizedDescription) + } + } + } + + func loadBalance() { + Task { + do { + showLoader("Loading balance") + + let balanceResponse = try await ethereumClient.getBalance(address: ethereumAccount.address) + + // Step 4: Update the UI state + DispatchQueue.main.async { + self.balance = balanceResponse + } + + hideLoader() + + } catch let error { + hideLoader() + print("Error in loadAccount: \(error.localizedDescription)") + showAlert(message: error.localizedDescription) + } + } + } + + func loginWithEmailPasswordless() { + Task { + do { + showLoader("Login in") + let auth0Creds = try await webAuth.start() + + let jwt = try decode(jwt: auth0Creds.idToken) + guard let sub = jwt.body["email"] as? String else { + throw "Email not found in JWT" + } + + sfaKey = try await mpcCoreKit.connect(loginParams: .init( + verifier: "sfa-mobile-aggregate-verifier", + verifierId: sub, + idToken: auth0Creds.idToken, + subVerifierInfoArray: [ + TorusSubVerifierInfo(verifier: "sfa-mobile-aggergate-passwordless", idToken: auth0Creds.idToken) + ] + ) + ) + userInfo = jwt.body + try await login() + hideLoader() + } catch let error { + hideLoader() + print(error.localizedDescription) + } + } + } + + func checkSession() { + Task { + do { + showLoader("Checking Session") + sfaKey = try await mpcCoreKit.initialize() + try await login() + hideLoader() + } catch let error { + hideLoader() + print(error.localizedDescription) + } + } + } + + func showLoader(_ message: String) { + loaderContent = message + DispatchQueue.main.async { + self.isLoaderVisible = true + } + } + + func hideLoader() { + DispatchQueue.main.async { + self.isLoaderVisible = false + } + } + + func signMessage(onSigned: @escaping (_ signedMessage: String?, _ error: String?) -> ()){ + Task { + do { + showLoader("Signing Message") + let signature = try ethereumAccount.signMessage( + message: "Welcome to Web3Auth".data(using: .ascii)! + ) + hideLoader() + onSigned(signature, nil) + } catch let error { + hideLoader() + onSigned(nil, error.localizedDescription) + showAlert(message: error.localizedDescription) + } + } + } + + + func sendTransaction(onSend: @escaping (String?, String?) -> ()) { + Task { + do { + showLoader("Sending Transaction") + let address = EthereumAddress( + stringLiteral: self.publicAddress + ) + let transaction = EthereumTransaction.init( + to: address, + data: Data.init(hex: "0x00")! + ) + + let gasLimit = try await self.ethereumClient.getGasLimit( + transaction: transaction + ) + let gasPrice = try await self.ethereumClient.getGasPrice() + let nonce = try await self.ethereumClient.getNonce(address: address) + + let finalTransaction = EthereumTransaction( + from: address, + to: address, + value: 1000000000000, + data: transaction.data, + nonce: nonce, + gasPrice: gasPrice, + gasLimit: gasLimit, + chainId: Int(self.ethereumClient.getChainId()) + ) + + let signedTransaction = try ethereumAccount.sign( + transaction: finalTransaction + ) + + let hash = try await ethereumClient.broadcastSignedTransaction( + transaction: signedTransaction + ) + hideLoader() + onSend(hash, nil) + + + } catch let error { + hideLoader() + print(error.localizedDescription) + onSend(nil, error.localizedDescription) + showAlert(message: error.localizedDescription) + } + } + } + + + + private func login() async throws { + ethereumAccount = try EthereumAccount(keyStorage: sfaKey as EthereumSingleKeyStorageProtocol) + publicAddress = ethereumAccount.address.toChecksumAddress() + toggleIsLoggedIn() + } + + func showAlert(message: String) { + alertContent = message + DispatchQueue.main.async { + self.showAlert = true + } + } + + + func toggleIsLoggedIn() { + DispatchQueue.main.async { + self.isLoggedIn.toggle() + } + } +} diff --git a/single-factor-auth-ios/ios-aggregate-example/sfa-ios-aggregate-example/Preview Content/Preview Assets.xcassets/Contents.json b/single-factor-auth-ios/ios-aggregate-example/sfa-ios-aggregate-example/Preview Content/Preview Assets.xcassets/Contents.json new file mode 100644 index 00000000..73c00596 --- /dev/null +++ b/single-factor-auth-ios/ios-aggregate-example/sfa-ios-aggregate-example/Preview Content/Preview Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/single-factor-auth-ios/ios-aggregate-example/sfa-ios-aggregate-example/Views/ContentView.swift b/single-factor-auth-ios/ios-aggregate-example/sfa-ios-aggregate-example/Views/ContentView.swift new file mode 100644 index 00000000..972f9231 --- /dev/null +++ b/single-factor-auth-ios/ios-aggregate-example/sfa-ios-aggregate-example/Views/ContentView.swift @@ -0,0 +1,26 @@ +// +// ContentView.swift +// ios-aggregate-example +// +// Created by Ayush B on 24/09/24. +// + +import SwiftUI + +struct ContentView: View { + @StateObject var viewModel: MainViewModel + + var body: some View { + NavigationView { + if viewModel.isLoggedIn { + HomeView(viewModel: viewModel) + } else{ + LoginView(viewModel: viewModel) + } + } + } +} + +#Preview { + ContentView(viewModel: MainViewModel()) +} diff --git a/single-factor-auth-ios/ios-aggregate-example/sfa-ios-aggregate-example/Views/HomeView.swift b/single-factor-auth-ios/ios-aggregate-example/sfa-ios-aggregate-example/Views/HomeView.swift new file mode 100644 index 00000000..9fb7204b --- /dev/null +++ b/single-factor-auth-ios/ios-aggregate-example/sfa-ios-aggregate-example/Views/HomeView.swift @@ -0,0 +1,93 @@ +// +// HomeView.swift +// ios-aggregate-example +// +// Created by Ayush B on 25/09/24. +// + +import SwiftUI + +struct HomeView: View { + @StateObject var viewModel: MainViewModel + @State private var signedMessage: String? + @State private var hash: String? + + var body: some View { + NavigationView { + LoadingView(viewModel: viewModel, content: { + Form { + Section(header: Text("User Info")) { + Button( + action: { + viewModel.showAlert(message: "Address is copied to clipboard") + UIPasteboard.general.string = viewModel.publicAddress + }, label: { + Text(viewModel.publicAddress) + }) + + Button( + action: { + viewModel.showAlert(message: viewModel.userInfo.debugDescription) + }, label: { + Text("View User info") + }) + + Text("Balance: " + viewModel.balance) + + } + + + Section(header: Text("Chain Interactions")) { + Button( + action: { + viewModel.signMessage{ + result, error in + if result != nil { + signedMessage = result + } + } + }, + label: { + Text("Sign Message") + } + ) + + if signedMessage != nil { + Text(signedMessage!) + } + + Button( + action: { + viewModel.sendTransaction{ + result, error in + if result != nil { + hash = result + } + } + }, + label: { + Text("Send 0.001 ETH") + } + ) + + if(hash != nil) { + Link( + hash!, + destination: URL( + string: "https://sepolia.etherscan.io/tx/\(hash!)" + )! + ).underline() + } + + Text("The sample uses Eth Sepolia, you can choose any EVM network of your choice. Send 0.001 ETH will perform self transfer of ETH. You'll need to have Sepolia faucet to perform transaction.").font(.caption) + + } + } + }).onAppear { + viewModel.loadBalance() + } + }.alert(isPresented: $viewModel.showAlert, content: { + Alert(title: Text(viewModel.alertContent)) + }) + } +} diff --git a/single-factor-auth-ios/ios-aggregate-example/sfa-ios-aggregate-example/Views/LoadingView.swift b/single-factor-auth-ios/ios-aggregate-example/sfa-ios-aggregate-example/Views/LoadingView.swift new file mode 100644 index 00000000..6296724e --- /dev/null +++ b/single-factor-auth-ios/ios-aggregate-example/sfa-ios-aggregate-example/Views/LoadingView.swift @@ -0,0 +1,50 @@ +// +// LoadingView.swift +// ios-aggregate-example +// +// Created by Ayush B on 25/09/24. +// + +import SwiftUI + +struct ActivityIndicator: UIViewRepresentable { + + @Binding var isAnimating: Bool + let style: UIActivityIndicatorView.Style + + func makeUIView(context: UIViewRepresentableContext) -> UIActivityIndicatorView { + return UIActivityIndicatorView(style: style) + } + + func updateUIView(_ uiView: UIActivityIndicatorView, context: UIViewRepresentableContext) { + isAnimating ? uiView.startAnimating() : uiView.stopAnimating() + } +} + +struct LoadingView: View where Content: View { + @StateObject var viewModel: MainViewModel + var content: () -> Content + + var body: some View { + GeometryReader { geometry in + ZStack(alignment: .center) { + + self.content() + .disabled(viewModel.isLoaderVisible) + .blur(radius: viewModel.isLoaderVisible ? 3 : 0) + + VStack { + Text(viewModel.loaderContent) + ActivityIndicator(isAnimating: .constant(true), style: .large) + } + .frame(width: geometry.size.width / 2, + height: geometry.size.height / 5) + .background(Color.secondary.colorInvert()) + .foregroundColor(Color.primary) + .cornerRadius(20) + .opacity(viewModel.isLoaderVisible ? 1 : 0) + + } + } + } +} diff --git a/single-factor-auth-ios/ios-aggregate-example/sfa-ios-aggregate-example/Views/LoginView.swift b/single-factor-auth-ios/ios-aggregate-example/sfa-ios-aggregate-example/Views/LoginView.swift new file mode 100644 index 00000000..5ffe3299 --- /dev/null +++ b/single-factor-auth-ios/ios-aggregate-example/sfa-ios-aggregate-example/Views/LoginView.swift @@ -0,0 +1,60 @@ +// +// LoginView.swift +// ios-aggregate-example +// +// Created by Ayush B on 25/09/24. +// + +import Foundation +import SwiftUI + +struct LoginView: View { + @StateObject var viewModel: MainViewModel + + var body: some View { + NavigationView { + LoadingView(viewModel: viewModel, content: { + Form{ + Spacer() + Text( + "SFA iOS Aggregate Example" + ).font(.title) + .multilineTextAlignment(.center).frame( + maxWidth: .infinity, + alignment: .center + ) + + Button( + action: { + viewModel.loginWithGoogle() + }, + label: { + Text("Sign in with Google") + .frame( + maxWidth: .infinity, + alignment: .center + ) + } + ).buttonStyle(.bordered) + Button( + action: { + viewModel.loginWithEmailPasswordless() + }, + label: { + Text("Sign in with Email Passwordless") + .frame( + maxWidth: .infinity, + alignment: .center + ) + } + ).buttonStyle(.bordered) + Spacer() + }.onAppear { + viewModel.initialize() + }.formStyle(.columns).padding() + }) + }.alert(isPresented: $viewModel.showAlert, content: { + Alert(title: Text(viewModel.alertContent)) + }) + } +} diff --git a/single-factor-auth-ios/ios-aggregate-example/sfa-ios-aggregate-example/ios_aggregate_exampleApp.swift b/single-factor-auth-ios/ios-aggregate-example/sfa-ios-aggregate-example/ios_aggregate_exampleApp.swift new file mode 100644 index 00000000..47a80a1e --- /dev/null +++ b/single-factor-auth-ios/ios-aggregate-example/sfa-ios-aggregate-example/ios_aggregate_exampleApp.swift @@ -0,0 +1,17 @@ +// +// ios_aggregate_exampleApp.swift +// ios-aggregate-example +// +// Created by Ayush B on 24/09/24. +// + +import SwiftUI + +@main +struct ios_aggregate_exampleApp: App { + var body: some Scene { + WindowGroup { + ContentView(viewModel: MainViewModel()) + } + } +} diff --git a/single-factor-auth-ios/sfa-ios-aggregate-example/README.md b/single-factor-auth-ios/sfa-ios-aggregate-example/README.md new file mode 100644 index 00000000..5f5b1779 --- /dev/null +++ b/single-factor-auth-ios/sfa-ios-aggregate-example/README.md @@ -0,0 +1,32 @@ +# Web3Auth SFA iOS Aggregate Example + +[![Web3Auth](https://img.shields.io/badge/Web3Auth-SDK-blue)](https://web3auth.io/docs/sdk/core-kit/sfa-ios) +[![Web3Auth](https://img.shields.io/badge/Web3Auth-Community-cyan)](https://web3auth.io/community) + +[Join our Community Portal](https://web3auth.io/community) to get support and stay up to date with the latest news and updates. + +This example demonstrates how to use Web3Auth in iOS. + +## How to Use + +### Download Manually + +```bash +npx degit Web3Auth/web3auth-core-kit-examples/single-factor-auth-ios/sfa-ios-aggregate-example w3a-sfa-ios-aggregate-example +``` + +Install & Run: + +```bash +cd w3a-sfa-ios-aggregate-example +# run project in Xcode +``` + +## Important Links + +- [Website](https://web3auth.io) +- [Docs](https://web3auth.io/docs) +- [Guides](https://web3auth.io/docs/guides) +- [SDK / API References](https://web3auth.io/docs/sdk) +- [Pricing](https://web3auth.io/pricing.html) +- [Community Portal](https://community.web3auth.io) diff --git a/single-factor-auth-ios/sfa-ios-aggregate-example/sfa-ios-aggregate-example.xcodeproj/project.pbxproj b/single-factor-auth-ios/sfa-ios-aggregate-example/sfa-ios-aggregate-example.xcodeproj/project.pbxproj new file mode 100644 index 00000000..3b06f659 --- /dev/null +++ b/single-factor-auth-ios/sfa-ios-aggregate-example/sfa-ios-aggregate-example.xcodeproj/project.pbxproj @@ -0,0 +1,475 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 56; + objects = { + +/* Begin PBXBuildFile section */ + 28D682972CA3AAAE00872DED /* SingleFactorAuth in Frameworks */ = {isa = PBXBuildFile; productRef = 28D682962CA3AAAE00872DED /* SingleFactorAuth */; }; + 28D6829A2CA3AB0A00872DED /* web3.swift in Frameworks */ = {isa = PBXBuildFile; productRef = 28D682992CA3AB0A00872DED /* web3.swift */; }; + 28D6829D2CA3AB2000872DED /* Auth0 in Frameworks */ = {isa = PBXBuildFile; productRef = 28D6829C2CA3AB2000872DED /* Auth0 */; }; + 28D682A02CA3AB2800872DED /* JWTDecode in Frameworks */ = {isa = PBXBuildFile; productRef = 28D6829F2CA3AB2800872DED /* JWTDecode */; }; + 28D682A22CA3B20D00872DED /* Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 28D682A12CA3B20D00872DED /* Extensions.swift */; }; + 28D682A52CA3BF7800872DED /* LoginView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 28D682A42CA3BF7800872DED /* LoginView.swift */; }; + 28D682A72CA3BFCA00872DED /* LoadingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 28D682A62CA3BFCA00872DED /* LoadingView.swift */; }; + 28D682A92CA3C03D00872DED /* HomeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 28D682A82CA3C03D00872DED /* HomeView.swift */; }; + 28DDAC452CA3269800D5C31A /* ios_aggregate_exampleApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 28DDAC442CA3269800D5C31A /* ios_aggregate_exampleApp.swift */; }; + 28DDAC472CA3269800D5C31A /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 28DDAC462CA3269800D5C31A /* ContentView.swift */; }; + 28DDAC492CA3269900D5C31A /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 28DDAC482CA3269900D5C31A /* Assets.xcassets */; }; + 28DDAC4C2CA3269900D5C31A /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 28DDAC4B2CA3269900D5C31A /* Preview Assets.xcassets */; }; + 28DDAC542CA3271000D5C31A /* EthereumClient.swift in Sources */ = {isa = PBXBuildFile; fileRef = 28DDAC532CA3271000D5C31A /* EthereumClient.swift */; }; + 28DDAC602CA3A52000D5C31A /* MainViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 28DDAC5F2CA3A52000D5C31A /* MainViewModel.swift */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 28D682A12CA3B20D00872DED /* Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Extensions.swift; sourceTree = ""; }; + 28D682A42CA3BF7800872DED /* LoginView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginView.swift; sourceTree = ""; }; + 28D682A62CA3BFCA00872DED /* LoadingView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoadingView.swift; sourceTree = ""; }; + 28D682A82CA3C03D00872DED /* HomeView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeView.swift; sourceTree = ""; }; + 28DDAC412CA3269800D5C31A /* sfa-ios-aggregate-example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "sfa-ios-aggregate-example.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 28DDAC442CA3269800D5C31A /* ios_aggregate_exampleApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ios_aggregate_exampleApp.swift; sourceTree = ""; }; + 28DDAC462CA3269800D5C31A /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = ""; }; + 28DDAC482CA3269900D5C31A /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 28DDAC4B2CA3269900D5C31A /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = ""; }; + 28DDAC532CA3271000D5C31A /* EthereumClient.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EthereumClient.swift; sourceTree = ""; }; + 28DDAC5F2CA3A52000D5C31A /* MainViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainViewModel.swift; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 28DDAC3E2CA3269800D5C31A /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 28D6829D2CA3AB2000872DED /* Auth0 in Frameworks */, + 28D6829A2CA3AB0A00872DED /* web3.swift in Frameworks */, + 28D682A02CA3AB2800872DED /* JWTDecode in Frameworks */, + 28D682972CA3AAAE00872DED /* SingleFactorAuth in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 28D682A32CA3BF0700872DED /* Views */ = { + isa = PBXGroup; + children = ( + 28DDAC462CA3269800D5C31A /* ContentView.swift */, + 28D682A42CA3BF7800872DED /* LoginView.swift */, + 28D682A62CA3BFCA00872DED /* LoadingView.swift */, + 28D682A82CA3C03D00872DED /* HomeView.swift */, + ); + path = Views; + sourceTree = ""; + }; + 28DDAC382CA3269800D5C31A = { + isa = PBXGroup; + children = ( + 28DDAC432CA3269800D5C31A /* sfa-ios-aggregate-example */, + 28DDAC422CA3269800D5C31A /* Products */, + ); + sourceTree = ""; + }; + 28DDAC422CA3269800D5C31A /* Products */ = { + isa = PBXGroup; + children = ( + 28DDAC412CA3269800D5C31A /* sfa-ios-aggregate-example.app */, + ); + name = Products; + sourceTree = ""; + }; + 28DDAC432CA3269800D5C31A /* sfa-ios-aggregate-example */ = { + isa = PBXGroup; + children = ( + 28D682A32CA3BF0700872DED /* Views */, + 28DDAC582CA3A3CE00D5C31A /* Models */, + 28DDAC522CA326EF00D5C31A /* Helpers */, + 28DDAC442CA3269800D5C31A /* ios_aggregate_exampleApp.swift */, + 28DDAC482CA3269900D5C31A /* Assets.xcassets */, + 28DDAC4A2CA3269900D5C31A /* Preview Content */, + ); + path = "sfa-ios-aggregate-example"; + sourceTree = ""; + }; + 28DDAC4A2CA3269900D5C31A /* Preview Content */ = { + isa = PBXGroup; + children = ( + 28DDAC4B2CA3269900D5C31A /* Preview Assets.xcassets */, + ); + path = "Preview Content"; + sourceTree = ""; + }; + 28DDAC522CA326EF00D5C31A /* Helpers */ = { + isa = PBXGroup; + children = ( + 28DDAC532CA3271000D5C31A /* EthereumClient.swift */, + 28D682A12CA3B20D00872DED /* Extensions.swift */, + ); + path = Helpers; + sourceTree = ""; + }; + 28DDAC582CA3A3CE00D5C31A /* Models */ = { + isa = PBXGroup; + children = ( + 28DDAC5F2CA3A52000D5C31A /* MainViewModel.swift */, + ); + path = Models; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 28DDAC402CA3269800D5C31A /* sfa-ios-aggregate-example */ = { + isa = PBXNativeTarget; + buildConfigurationList = 28DDAC4F2CA3269900D5C31A /* Build configuration list for PBXNativeTarget "sfa-ios-aggregate-example" */; + buildPhases = ( + 28DDAC3D2CA3269800D5C31A /* Sources */, + 28DDAC3E2CA3269800D5C31A /* Frameworks */, + 28DDAC3F2CA3269800D5C31A /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "sfa-ios-aggregate-example"; + packageProductDependencies = ( + 28D682962CA3AAAE00872DED /* SingleFactorAuth */, + 28D682992CA3AB0A00872DED /* web3.swift */, + 28D6829C2CA3AB2000872DED /* Auth0 */, + 28D6829F2CA3AB2800872DED /* JWTDecode */, + ); + productName = "ios-aggregate-example"; + productReference = 28DDAC412CA3269800D5C31A /* sfa-ios-aggregate-example.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 28DDAC392CA3269800D5C31A /* Project object */ = { + isa = PBXProject; + attributes = { + BuildIndependentTargetsInParallel = 1; + LastSwiftUpdateCheck = 1540; + LastUpgradeCheck = 1540; + TargetAttributes = { + 28DDAC402CA3269800D5C31A = { + CreatedOnToolsVersion = 15.4; + }; + }; + }; + buildConfigurationList = 28DDAC3C2CA3269800D5C31A /* Build configuration list for PBXProject "sfa-ios-aggregate-example" */; + compatibilityVersion = "Xcode 14.0"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 28DDAC382CA3269800D5C31A; + packageReferences = ( + 28D682952CA3AAAE00872DED /* XCRemoteSwiftPackageReference "single-factor-auth-swift" */, + 28D682982CA3AB0A00872DED /* XCRemoteSwiftPackageReference "web3" */, + 28D6829B2CA3AB2000872DED /* XCRemoteSwiftPackageReference "Auth0" */, + 28D6829E2CA3AB2800872DED /* XCRemoteSwiftPackageReference "JWTDecode" */, + ); + productRefGroup = 28DDAC422CA3269800D5C31A /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 28DDAC402CA3269800D5C31A /* sfa-ios-aggregate-example */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 28DDAC3F2CA3269800D5C31A /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 28DDAC4C2CA3269900D5C31A /* Preview Assets.xcassets in Resources */, + 28DDAC492CA3269900D5C31A /* Assets.xcassets in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 28DDAC3D2CA3269800D5C31A /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 28D682A52CA3BF7800872DED /* LoginView.swift in Sources */, + 28D682A22CA3B20D00872DED /* Extensions.swift in Sources */, + 28DDAC472CA3269800D5C31A /* ContentView.swift in Sources */, + 28DDAC452CA3269800D5C31A /* ios_aggregate_exampleApp.swift in Sources */, + 28DDAC542CA3271000D5C31A /* EthereumClient.swift in Sources */, + 28D682A92CA3C03D00872DED /* HomeView.swift in Sources */, + 28D682A72CA3BFCA00872DED /* LoadingView.swift in Sources */, + 28DDAC602CA3A52000D5C31A /* MainViewModel.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 28DDAC4D2CA3269900D5C31A /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + GCC_C_LANGUAGE_STANDARD = gnu17; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 17.5; + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 28DDAC4E2CA3269900D5C31A /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + GCC_C_LANGUAGE_STANDARD = gnu17; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 17.5; + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + SDKROOT = iphoneos; + SWIFT_COMPILATION_MODE = wholemodule; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 28DDAC502CA3269900D5C31A /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_ASSET_PATHS = "\"sfa-ios-aggregate-example/Preview Content\""; + DEVELOPMENT_TEAM = 2Q63NCPY55; + ENABLE_PREVIEWS = YES; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES; + INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; + INFOPLIST_KEY_UILaunchScreen_Generation = YES; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = "com.w3a.ios-aggregate-example"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 28DDAC512CA3269900D5C31A /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_ASSET_PATHS = "\"sfa-ios-aggregate-example/Preview Content\""; + DEVELOPMENT_TEAM = 2Q63NCPY55; + ENABLE_PREVIEWS = YES; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES; + INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; + INFOPLIST_KEY_UILaunchScreen_Generation = YES; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = "com.w3a.ios-aggregate-example"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 28DDAC3C2CA3269800D5C31A /* Build configuration list for PBXProject "sfa-ios-aggregate-example" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 28DDAC4D2CA3269900D5C31A /* Debug */, + 28DDAC4E2CA3269900D5C31A /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 28DDAC4F2CA3269900D5C31A /* Build configuration list for PBXNativeTarget "sfa-ios-aggregate-example" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 28DDAC502CA3269900D5C31A /* Debug */, + 28DDAC512CA3269900D5C31A /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + +/* Begin XCRemoteSwiftPackageReference section */ + 28D682952CA3AAAE00872DED /* XCRemoteSwiftPackageReference "single-factor-auth-swift" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/Web3Auth/single-factor-auth-swift"; + requirement = { + kind = upToNextMajorVersion; + minimumVersion = 8.0.0; + }; + }; + 28D682982CA3AB0A00872DED /* XCRemoteSwiftPackageReference "web3" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/argentlabs/web3.swift"; + requirement = { + kind = upToNextMajorVersion; + minimumVersion = 1.6.1; + }; + }; + 28D6829B2CA3AB2000872DED /* XCRemoteSwiftPackageReference "Auth0" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/auth0/Auth0.swift"; + requirement = { + kind = upToNextMajorVersion; + minimumVersion = 2.9.0; + }; + }; + 28D6829E2CA3AB2800872DED /* XCRemoteSwiftPackageReference "JWTDecode" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/auth0/JWTDecode.swift"; + requirement = { + kind = upToNextMajorVersion; + minimumVersion = 3.2.0; + }; + }; +/* End XCRemoteSwiftPackageReference section */ + +/* Begin XCSwiftPackageProductDependency section */ + 28D682962CA3AAAE00872DED /* SingleFactorAuth */ = { + isa = XCSwiftPackageProductDependency; + package = 28D682952CA3AAAE00872DED /* XCRemoteSwiftPackageReference "single-factor-auth-swift" */; + productName = SingleFactorAuth; + }; + 28D682992CA3AB0A00872DED /* web3.swift */ = { + isa = XCSwiftPackageProductDependency; + package = 28D682982CA3AB0A00872DED /* XCRemoteSwiftPackageReference "web3" */; + productName = web3.swift; + }; + 28D6829C2CA3AB2000872DED /* Auth0 */ = { + isa = XCSwiftPackageProductDependency; + package = 28D6829B2CA3AB2000872DED /* XCRemoteSwiftPackageReference "Auth0" */; + productName = Auth0; + }; + 28D6829F2CA3AB2800872DED /* JWTDecode */ = { + isa = XCSwiftPackageProductDependency; + package = 28D6829E2CA3AB2800872DED /* XCRemoteSwiftPackageReference "JWTDecode" */; + productName = JWTDecode; + }; +/* End XCSwiftPackageProductDependency section */ + }; + rootObject = 28DDAC392CA3269800D5C31A /* Project object */; +} diff --git a/single-factor-auth-ios/sfa-ios-aggregate-example/sfa-ios-aggregate-example.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/single-factor-auth-ios/sfa-ios-aggregate-example/sfa-ios-aggregate-example.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 00000000..919434a6 --- /dev/null +++ b/single-factor-auth-ios/sfa-ios-aggregate-example/sfa-ios-aggregate-example.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/single-factor-auth-ios/sfa-ios-aggregate-example/sfa-ios-aggregate-example.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/single-factor-auth-ios/sfa-ios-aggregate-example/sfa-ios-aggregate-example.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 00000000..18d98100 --- /dev/null +++ b/single-factor-auth-ios/sfa-ios-aggregate-example/sfa-ios-aggregate-example.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/single-factor-auth-ios/sfa-ios-aggregate-example/sfa-ios-aggregate-example.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/single-factor-auth-ios/sfa-ios-aggregate-example/sfa-ios-aggregate-example.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 00000000..0c67376e --- /dev/null +++ b/single-factor-auth-ios/sfa-ios-aggregate-example/sfa-ios-aggregate-example.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,5 @@ + + + + + diff --git a/single-factor-auth-ios/sfa-ios-aggregate-example/sfa-ios-aggregate-example.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/single-factor-auth-ios/sfa-ios-aggregate-example/sfa-ios-aggregate-example.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved new file mode 100644 index 00000000..a2b9b281 --- /dev/null +++ b/single-factor-auth-ios/sfa-ios-aggregate-example/sfa-ios-aggregate-example.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -0,0 +1,222 @@ +{ + "originHash" : "d527885300ea30dd77e93e69a0aa3f988977e7c7c5af64a87454c1f55028de15", + "pins" : [ + { + "identity" : "auth0.swift", + "kind" : "remoteSourceControl", + "location" : "https://github.com/auth0/Auth0.swift", + "state" : { + "revision" : "0d9c3f3241e3defad065409ac3a071ee1c5a7e8a", + "version" : "2.9.0" + } + }, + { + "identity" : "bigint", + "kind" : "remoteSourceControl", + "location" : "https://github.com/attaswift/BigInt.git", + "state" : { + "revision" : "793a7fac0bfc318e85994bf6900652e827aef33e", + "version" : "5.4.1" + } + }, + { + "identity" : "curvelib.swift", + "kind" : "remoteSourceControl", + "location" : "https://github.com/tkey/curvelib.swift", + "state" : { + "revision" : "9f88bd5e56d1df443a908f7a7e81ae4f4d9170ea", + "version" : "1.0.1" + } + }, + { + "identity" : "fetch-node-details-swift", + "kind" : "remoteSourceControl", + "location" : "https://github.com/torusresearch/fetch-node-details-swift.git", + "state" : { + "revision" : "4bd96c33ba8d02d9e27190c5c7cedf09cfdfd656", + "version" : "6.0.3" + } + }, + { + "identity" : "generic-json-swift", + "kind" : "remoteSourceControl", + "location" : "https://github.com/iwill/generic-json-swift", + "state" : { + "revision" : "0a06575f4038b504e78ac330913d920f1630f510", + "version" : "2.0.2" + } + }, + { + "identity" : "jwtdecode.swift", + "kind" : "remoteSourceControl", + "location" : "https://github.com/auth0/JWTDecode.swift.git", + "state" : { + "revision" : "1e153ef009969543191970c66b7c60163c0b4a65", + "version" : "3.2.0" + } + }, + { + "identity" : "keychain-swift", + "kind" : "remoteSourceControl", + "location" : "https://github.com/evgenyneu/keychain-swift.git", + "state" : { + "revision" : "d108a1fa6189e661f91560548ef48651ed8d93b9", + "version" : "20.0.0" + } + }, + { + "identity" : "secp256k1.swift", + "kind" : "remoteSourceControl", + "location" : "https://github.com/GigaBitcoin/secp256k1.swift.git", + "state" : { + "revision" : "9683e8e311c76d8114cd308b697dad2f9fc58fed", + "version" : "0.17.0" + } + }, + { + "identity" : "session-manager-swift", + "kind" : "remoteSourceControl", + "location" : "https://github.com/Web3Auth/session-manager-swift.git", + "state" : { + "revision" : "67d5f7db655d02778861057fb280ecf47c923b09", + "version" : "5.0.0" + } + }, + { + "identity" : "simplekeychain", + "kind" : "remoteSourceControl", + "location" : "https://github.com/auth0/SimpleKeychain.git", + "state" : { + "revision" : "b694f155907b189bc82e93586695a26f558c742f", + "version" : "1.2.0" + } + }, + { + "identity" : "single-factor-auth-swift", + "kind" : "remoteSourceControl", + "location" : "https://github.com/Web3Auth/single-factor-auth-swift", + "state" : { + "revision" : "44e222ea3fcec4faf17c5813f832cfc1d2d06d4b", + "version" : "8.0.0" + } + }, + { + "identity" : "swift-atomics", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-atomics.git", + "state" : { + "revision" : "cd142fd2f64be2100422d658e7411e39489da985", + "version" : "1.2.0" + } + }, + { + "identity" : "swift-collections", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-collections.git", + "state" : { + "revision" : "671108c96644956dddcd89dd59c203dcdb36cec7", + "version" : "1.1.4" + } + }, + { + "identity" : "swift-http-types", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-http-types", + "state" : { + "revision" : "ae67c8178eb46944fd85e4dc6dd970e1f3ed6ccd", + "version" : "1.3.0" + } + }, + { + "identity" : "swift-log", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-log.git", + "state" : { + "revision" : "9cb486020ebf03bfa5b5df985387a14a98744537", + "version" : "1.6.1" + } + }, + { + "identity" : "swift-nio", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-nio.git", + "state" : { + "revision" : "9746cf80e29edfef2a39924a66731249223f42a3", + "version" : "2.72.0" + } + }, + { + "identity" : "swift-nio-extras", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-nio-extras.git", + "state" : { + "revision" : "d1ead62745cc3269e482f1c51f27608057174379", + "version" : "1.24.0" + } + }, + { + "identity" : "swift-nio-http2", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-nio-http2.git", + "state" : { + "revision" : "b5f7062b60e4add1e8c343ba4eb8da2e324b3a94", + "version" : "1.34.0" + } + }, + { + "identity" : "swift-nio-ssl", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-nio-ssl.git", + "state" : { + "revision" : "7b84abbdcef69cc3be6573ac12440220789dcd69", + "version" : "2.27.2" + } + }, + { + "identity" : "swift-nio-transport-services", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-nio-transport-services.git", + "state" : { + "revision" : "38ac8221dd20674682148d6451367f89c2652980", + "version" : "1.21.0" + } + }, + { + "identity" : "swift-system", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-system.git", + "state" : { + "revision" : "d2ba781702a1d8285419c15ee62fd734a9437ff5", + "version" : "1.3.2" + } + }, + { + "identity" : "torus-utils-swift", + "kind" : "remoteSourceControl", + "location" : "https://github.com/torusresearch/torus-utils-swift.git", + "state" : { + "revision" : "eda55b8537a600e657d19d4c452c0a36f217883c", + "version" : "9.0.1" + } + }, + { + "identity" : "web3.swift", + "kind" : "remoteSourceControl", + "location" : "https://github.com/argentlabs/web3.swift", + "state" : { + "revision" : "1e75f98a5738c470b23bbfffa9314e9f788df76b", + "version" : "1.6.1" + } + }, + { + "identity" : "websocket-kit", + "kind" : "remoteSourceControl", + "location" : "https://github.com/vapor/websocket-kit.git", + "state" : { + "revision" : "4232d34efa49f633ba61afde365d3896fc7f8740", + "version" : "2.15.0" + } + } + ], + "version" : 3 +} diff --git a/single-factor-auth-ios/sfa-ios-aggregate-example/sfa-ios-aggregate-example.xcodeproj/project.xcworkspace/xcuserdata/ayushb.xcuserdatad/UserInterfaceState.xcuserstate b/single-factor-auth-ios/sfa-ios-aggregate-example/sfa-ios-aggregate-example.xcodeproj/project.xcworkspace/xcuserdata/ayushb.xcuserdatad/UserInterfaceState.xcuserstate new file mode 100644 index 00000000..c6999aea Binary files /dev/null and b/single-factor-auth-ios/sfa-ios-aggregate-example/sfa-ios-aggregate-example.xcodeproj/project.xcworkspace/xcuserdata/ayushb.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/single-factor-auth-ios/sfa-ios-aggregate-example/sfa-ios-aggregate-example.xcodeproj/project.xcworkspace/xcuserdata/ayushb.xcuserdatad/WorkspaceSettings.xcsettings b/single-factor-auth-ios/sfa-ios-aggregate-example/sfa-ios-aggregate-example.xcodeproj/project.xcworkspace/xcuserdata/ayushb.xcuserdatad/WorkspaceSettings.xcsettings new file mode 100644 index 00000000..bbfef027 --- /dev/null +++ b/single-factor-auth-ios/sfa-ios-aggregate-example/sfa-ios-aggregate-example.xcodeproj/project.xcworkspace/xcuserdata/ayushb.xcuserdatad/WorkspaceSettings.xcsettings @@ -0,0 +1,14 @@ + + + + + BuildLocationStyle + UseAppPreferences + CustomBuildLocationType + RelativeToDerivedData + DerivedDataLocationStyle + Default + ShowSharedSchemesAutomaticallyEnabled + + + diff --git a/single-factor-auth-ios/sfa-ios-aggregate-example/sfa-ios-aggregate-example.xcodeproj/xcuserdata/ayushb.xcuserdatad/xcschemes/xcschememanagement.plist b/single-factor-auth-ios/sfa-ios-aggregate-example/sfa-ios-aggregate-example.xcodeproj/xcuserdata/ayushb.xcuserdatad/xcschemes/xcschememanagement.plist new file mode 100644 index 00000000..431a6203 --- /dev/null +++ b/single-factor-auth-ios/sfa-ios-aggregate-example/sfa-ios-aggregate-example.xcodeproj/xcuserdata/ayushb.xcuserdatad/xcschemes/xcschememanagement.plist @@ -0,0 +1,145 @@ + + + + + SchemeUserState + + Demo (Playground) 1.xcscheme + + isShown + + orderHint + 5 + + Demo (Playground) 2.xcscheme + + isShown + + orderHint + 6 + + Demo (Playground) 3.xcscheme + + isShown + + orderHint + 17 + + Demo (Playground) 4.xcscheme + + isShown + + orderHint + 18 + + Demo (Playground) 5.xcscheme + + isShown + + orderHint + 19 + + Demo (Playground).xcscheme + + isShown + + orderHint + 4 + + JWTDecode (Playground) 1.xcscheme + + isShown + + orderHint + 8 + + JWTDecode (Playground) 2.xcscheme + + isShown + + orderHint + 9 + + JWTDecode (Playground) 3.xcscheme + + isShown + + orderHint + 11 + + JWTDecode (Playground) 4.xcscheme + + isShown + + orderHint + 12 + + JWTDecode (Playground) 5.xcscheme + + isShown + + orderHint + 13 + + JWTDecode (Playground).xcscheme + + isShown + + orderHint + 7 + + Playground (Playground) 1.xcscheme + + isShown + + orderHint + 2 + + Playground (Playground) 2.xcscheme + + isShown + + orderHint + 3 + + Playground (Playground) 3.xcscheme + + isShown + + orderHint + 14 + + Playground (Playground) 4.xcscheme + + isShown + + orderHint + 15 + + Playground (Playground) 5.xcscheme + + isShown + + orderHint + 16 + + Playground (Playground).xcscheme + + isShown + + orderHint + 1 + + ios-aggregate-example.xcscheme_^#shared#^_ + + orderHint + 0 + + sfa-ios-aggregate-example.xcscheme_^#shared#^_ + + orderHint + 0 + + + + diff --git a/single-factor-auth-ios/sfa-ios-aggregate-example/sfa-ios-aggregate-example/Assets.xcassets/AccentColor.colorset/Contents.json b/single-factor-auth-ios/sfa-ios-aggregate-example/sfa-ios-aggregate-example/Assets.xcassets/AccentColor.colorset/Contents.json new file mode 100644 index 00000000..eb878970 --- /dev/null +++ b/single-factor-auth-ios/sfa-ios-aggregate-example/sfa-ios-aggregate-example/Assets.xcassets/AccentColor.colorset/Contents.json @@ -0,0 +1,11 @@ +{ + "colors" : [ + { + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/single-factor-auth-ios/sfa-ios-aggregate-example/sfa-ios-aggregate-example/Assets.xcassets/AppIcon.appiconset/Contents.json b/single-factor-auth-ios/sfa-ios-aggregate-example/sfa-ios-aggregate-example/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 00000000..13613e3e --- /dev/null +++ b/single-factor-auth-ios/sfa-ios-aggregate-example/sfa-ios-aggregate-example/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,13 @@ +{ + "images" : [ + { + "idiom" : "universal", + "platform" : "ios", + "size" : "1024x1024" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/single-factor-auth-ios/sfa-ios-aggregate-example/sfa-ios-aggregate-example/Assets.xcassets/Contents.json b/single-factor-auth-ios/sfa-ios-aggregate-example/sfa-ios-aggregate-example/Assets.xcassets/Contents.json new file mode 100644 index 00000000..73c00596 --- /dev/null +++ b/single-factor-auth-ios/sfa-ios-aggregate-example/sfa-ios-aggregate-example/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/single-factor-auth-ios/sfa-ios-aggregate-example/sfa-ios-aggregate-example/Helpers/EthereumClient.swift b/single-factor-auth-ios/sfa-ios-aggregate-example/sfa-ios-aggregate-example/Helpers/EthereumClient.swift new file mode 100644 index 00000000..d69b7198 --- /dev/null +++ b/single-factor-auth-ios/sfa-ios-aggregate-example/sfa-ios-aggregate-example/Helpers/EthereumClient.swift @@ -0,0 +1,92 @@ +// +// EthereumClient.swift +// ios-aggregate-example +// +// Created by Ayush B on 24/09/24. +// + +import Foundation +import Foundation +import web3 +import BigInt + +struct EthereumClient { + let web3Client: EthereumHttpClient! + var networkId: String = "11155111" + + init() { + self.web3Client = EthereumHttpClient( + url: URL(string: "https://1rpc.io/sepolia")!, + network: .fromString(networkId) + ) + } + + func getNonce(address: EthereumAddress) async throws -> Int{ + do { + let nonce = try await web3Client.eth_getTransactionCount( + address: address, block: .Latest + ) + return nonce + } catch let error { + throw error + } + } + + func getGasPrice() async throws -> BigUInt { + do { + let gasPrice = try await web3Client.eth_gasPrice() + return gasPrice + } catch let error { + throw error + } + } + + func getGasLimit(transaction: EthereumTransaction) async throws -> BigUInt { + do { + let gasLimit = try await web3Client.eth_estimateGas(transaction) + return gasLimit + } catch let error { + throw error + } + } + + func getBalance(address: EthereumAddress) async throws -> String { + do { + let balanceResponse = try await web3Client.eth_getBalance(address: address, block: .Latest) + guard let decimalWei = Double(balanceResponse.description) else { + return 0.description + } + + let balance = decimalWei / pow(Double(10), 18) + return balance.description + } catch let error { + throw error + } + } + + func broadcastSignedTransaction(transaction: SignedTransaction) async throws -> String { + do { + guard let transactionHex = transaction.raw?.web3.hexString else { + throw EthereumClientError.encodeIssue + } + + let data = try await web3Client.networkProvider.send( + method: "eth_sendRawTransaction", + params: [transactionHex], + receive: String.self + ) + + if let hash = data as? String { + return hash + } else { + throw EthereumClientError.unexpectedReturnValue + } + } catch let error { + throw error + } + } + + func getChainId() -> String { + return networkId + } +} diff --git a/single-factor-auth-ios/sfa-ios-aggregate-example/sfa-ios-aggregate-example/Helpers/Extensions.swift b/single-factor-auth-ios/sfa-ios-aggregate-example/sfa-ios-aggregate-example/Helpers/Extensions.swift new file mode 100644 index 00000000..765850fa --- /dev/null +++ b/single-factor-auth-ios/sfa-ios-aggregate-example/sfa-ios-aggregate-example/Helpers/Extensions.swift @@ -0,0 +1,26 @@ +// +// Extensions.swift +// ios-aggregate-example +// +// Created by Ayush B on 25/09/24. +// + +import Foundation +import SingleFactorAuth +import web3 + +extension SFAKey: EthereumSingleKeyStorageProtocol { + public func storePrivateKey(key: Data) throws { + + } + + public func loadPrivateKey() throws -> Data { + guard let privKeyData = Data.init(hex: self.getPrivateKey()) else { + // Todo make custom error + return Data() + } + return privKeyData + + } + +} diff --git a/single-factor-auth-ios/sfa-ios-aggregate-example/sfa-ios-aggregate-example/Models/MainViewModel.swift b/single-factor-auth-ios/sfa-ios-aggregate-example/sfa-ios-aggregate-example/Models/MainViewModel.swift new file mode 100644 index 00000000..049e9866 --- /dev/null +++ b/single-factor-auth-ios/sfa-ios-aggregate-example/sfa-ios-aggregate-example/Models/MainViewModel.swift @@ -0,0 +1,248 @@ +// +// MainViewModel.swift +// ios-aggregate-example +// +// Created by Ayush B on 25/09/24. +// + +import Foundation +import web3 +import UIKit +import Auth0 +import JWTDecode +import SingleFactorAuth + +class MainViewModel: ObservableObject { + @Published var isLoggedIn: Bool = false + @Published var showAlert: Bool = false + @Published var isLoaderVisible: Bool = false + @Published var balance: String = "0.0" + + var publicAddress: String! + + + private var mpcCoreKit: SingleFactorAuth! + private var ethereumClient: EthereumClient! + private var ethereumAccount: EthereumAccount! + private var sfaKey: SFAKey! + private var webAuth: WebAuth! + var userInfo: [String: Any]! + var alertContent: String = "" + var loaderContent: String = "" + + func initialize() { + mpcCoreKit = try! SingleFactorAuth( + params: .init( + web3AuthClientId: "BPi5PB_UiIZ-cPz1GtV5i1I2iOSOHuimiXBI0e-Oe_u6X3oVAbCiAZOTEBtTXw4tsluTITPqA8zMsfxIKMjiqNQ", + network: .sapphire(.SAPPHIRE_MAINNET) + ) + ) + webAuth = Auth0.webAuth(clientId: "hUVVf4SEsZT7syOiL0gLU9hFEtm2gQ6O", domain: "web3auth.au.auth0.com") + + ethereumClient = EthereumClient() + checkSession() + } + + // com.w3a.ios-aggregate-example://web3auth.au.auth0.com/ios/com.w3a.ios-aggregate-example/callback + // com.example.MyApp://example.us.auth0.com/ios/com.example.MyApp/callback + + func loginWithGoogle() { + Task { + do { + showLoader("Login in") + let auth0Creds = try await webAuth.connection("google-oauth2").start() + + let jwt = try decode(jwt: auth0Creds.idToken) + guard let sub = jwt.body["email"] as? String else { + throw "Email not found in JWT" + } + + sfaKey = try await mpcCoreKit.connect(loginParams: .init( + verifier: "sfa-mobile-aggregate-verifier", + verifierId: sub, + idToken: auth0Creds.idToken, + subVerifierInfoArray: [ + TorusSubVerifierInfo(verifier: "sfa-mobile-aggregate-auth0-google", idToken: auth0Creds.idToken) + ] + ) + ) + + userInfo = jwt.body + try await login() + + hideLoader() + } catch let error { + hideLoader() + print(error.localizedDescription) + } + } + } + + func loadBalance() { + Task { + do { + showLoader("Loading balance") + + let balanceResponse = try await ethereumClient.getBalance(address: ethereumAccount.address) + + // Step 4: Update the UI state + DispatchQueue.main.async { + self.balance = balanceResponse + } + + hideLoader() + + } catch let error { + hideLoader() + print("Error in loadAccount: \(error.localizedDescription)") + showAlert(message: error.localizedDescription) + } + } + } + + func loginWithEmailPasswordless() { + Task { + do { + showLoader("Logging in") + let auth0Creds = try await webAuth.connection("").start() + + let jwt = try decode(jwt: auth0Creds.idToken) + guard let sub = jwt.body["email"] as? String else { + throw "Email not found in JWT" + } + + sfaKey = try await mpcCoreKit.connect(loginParams: .init( + verifier: "sfa-mobile-aggregate-verifier", + verifierId: sub, + idToken: auth0Creds.idToken, + subVerifierInfoArray: [ + TorusSubVerifierInfo(verifier: "sfa-mobile-aggergate-passwordless", idToken: auth0Creds.idToken) + ] + ) + ) + userInfo = jwt.body + try await login() + hideLoader() + } catch let error { + hideLoader() + print(error.localizedDescription) + } + } + } + + func checkSession() { + Task { + do { + showLoader("Checking Session") + sfaKey = try await mpcCoreKit.initialize() + try await login() + hideLoader() + } catch let error { + hideLoader() + print(error.localizedDescription) + } + } + } + + func showLoader(_ message: String) { + loaderContent = message + DispatchQueue.main.async { + self.isLoaderVisible = true + } + } + + func hideLoader() { + DispatchQueue.main.async { + self.isLoaderVisible = false + } + } + + func signMessage(onSigned: @escaping (_ signedMessage: String?, _ error: String?) -> ()){ + Task { + do { + showLoader("Signing Message") + let signature = try ethereumAccount.signMessage( + message: "Welcome to Web3Auth".data(using: .ascii)! + ) + hideLoader() + onSigned(signature, nil) + } catch let error { + hideLoader() + onSigned(nil, error.localizedDescription) + showAlert(message: error.localizedDescription) + } + } + } + + + func sendTransaction(onSend: @escaping (String?, String?) -> ()) { + Task { + do { + showLoader("Sending Transaction") + let address = EthereumAddress( + stringLiteral: self.publicAddress + ) + let transaction = EthereumTransaction.init( + to: address, + data: Data.init(hex: "0x00")! + ) + + let gasLimit = try await self.ethereumClient.getGasLimit( + transaction: transaction + ) + let gasPrice = try await self.ethereumClient.getGasPrice() + let nonce = try await self.ethereumClient.getNonce(address: address) + + let finalTransaction = EthereumTransaction( + from: address, + to: address, + value: 1000000000000, + data: transaction.data, + nonce: nonce, + gasPrice: gasPrice, + gasLimit: gasLimit, + chainId: Int(self.ethereumClient.getChainId()) + ) + + let signedTransaction = try ethereumAccount.sign( + transaction: finalTransaction + ) + + let hash = try await ethereumClient.broadcastSignedTransaction( + transaction: signedTransaction + ) + hideLoader() + onSend(hash, nil) + + + } catch let error { + hideLoader() + print(error.localizedDescription) + onSend(nil, error.localizedDescription) + showAlert(message: error.localizedDescription) + } + } + } + + + + private func login() async throws { + ethereumAccount = try EthereumAccount(keyStorage: sfaKey as EthereumSingleKeyStorageProtocol) + publicAddress = ethereumAccount.address.toChecksumAddress() + toggleIsLoggedIn() + } + + func showAlert(message: String) { + alertContent = message + DispatchQueue.main.async { + self.showAlert = true + } + } + + + func toggleIsLoggedIn() { + DispatchQueue.main.async { + self.isLoggedIn.toggle() + } + } +} diff --git a/single-factor-auth-ios/sfa-ios-aggregate-example/sfa-ios-aggregate-example/Preview Content/Preview Assets.xcassets/Contents.json b/single-factor-auth-ios/sfa-ios-aggregate-example/sfa-ios-aggregate-example/Preview Content/Preview Assets.xcassets/Contents.json new file mode 100644 index 00000000..73c00596 --- /dev/null +++ b/single-factor-auth-ios/sfa-ios-aggregate-example/sfa-ios-aggregate-example/Preview Content/Preview Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/single-factor-auth-ios/sfa-ios-aggregate-example/sfa-ios-aggregate-example/Views/ContentView.swift b/single-factor-auth-ios/sfa-ios-aggregate-example/sfa-ios-aggregate-example/Views/ContentView.swift new file mode 100644 index 00000000..972f9231 --- /dev/null +++ b/single-factor-auth-ios/sfa-ios-aggregate-example/sfa-ios-aggregate-example/Views/ContentView.swift @@ -0,0 +1,26 @@ +// +// ContentView.swift +// ios-aggregate-example +// +// Created by Ayush B on 24/09/24. +// + +import SwiftUI + +struct ContentView: View { + @StateObject var viewModel: MainViewModel + + var body: some View { + NavigationView { + if viewModel.isLoggedIn { + HomeView(viewModel: viewModel) + } else{ + LoginView(viewModel: viewModel) + } + } + } +} + +#Preview { + ContentView(viewModel: MainViewModel()) +} diff --git a/single-factor-auth-ios/sfa-ios-aggregate-example/sfa-ios-aggregate-example/Views/HomeView.swift b/single-factor-auth-ios/sfa-ios-aggregate-example/sfa-ios-aggregate-example/Views/HomeView.swift new file mode 100644 index 00000000..9fb7204b --- /dev/null +++ b/single-factor-auth-ios/sfa-ios-aggregate-example/sfa-ios-aggregate-example/Views/HomeView.swift @@ -0,0 +1,93 @@ +// +// HomeView.swift +// ios-aggregate-example +// +// Created by Ayush B on 25/09/24. +// + +import SwiftUI + +struct HomeView: View { + @StateObject var viewModel: MainViewModel + @State private var signedMessage: String? + @State private var hash: String? + + var body: some View { + NavigationView { + LoadingView(viewModel: viewModel, content: { + Form { + Section(header: Text("User Info")) { + Button( + action: { + viewModel.showAlert(message: "Address is copied to clipboard") + UIPasteboard.general.string = viewModel.publicAddress + }, label: { + Text(viewModel.publicAddress) + }) + + Button( + action: { + viewModel.showAlert(message: viewModel.userInfo.debugDescription) + }, label: { + Text("View User info") + }) + + Text("Balance: " + viewModel.balance) + + } + + + Section(header: Text("Chain Interactions")) { + Button( + action: { + viewModel.signMessage{ + result, error in + if result != nil { + signedMessage = result + } + } + }, + label: { + Text("Sign Message") + } + ) + + if signedMessage != nil { + Text(signedMessage!) + } + + Button( + action: { + viewModel.sendTransaction{ + result, error in + if result != nil { + hash = result + } + } + }, + label: { + Text("Send 0.001 ETH") + } + ) + + if(hash != nil) { + Link( + hash!, + destination: URL( + string: "https://sepolia.etherscan.io/tx/\(hash!)" + )! + ).underline() + } + + Text("The sample uses Eth Sepolia, you can choose any EVM network of your choice. Send 0.001 ETH will perform self transfer of ETH. You'll need to have Sepolia faucet to perform transaction.").font(.caption) + + } + } + }).onAppear { + viewModel.loadBalance() + } + }.alert(isPresented: $viewModel.showAlert, content: { + Alert(title: Text(viewModel.alertContent)) + }) + } +} diff --git a/single-factor-auth-ios/sfa-ios-aggregate-example/sfa-ios-aggregate-example/Views/LoadingView.swift b/single-factor-auth-ios/sfa-ios-aggregate-example/sfa-ios-aggregate-example/Views/LoadingView.swift new file mode 100644 index 00000000..6296724e --- /dev/null +++ b/single-factor-auth-ios/sfa-ios-aggregate-example/sfa-ios-aggregate-example/Views/LoadingView.swift @@ -0,0 +1,50 @@ +// +// LoadingView.swift +// ios-aggregate-example +// +// Created by Ayush B on 25/09/24. +// + +import SwiftUI + +struct ActivityIndicator: UIViewRepresentable { + + @Binding var isAnimating: Bool + let style: UIActivityIndicatorView.Style + + func makeUIView(context: UIViewRepresentableContext) -> UIActivityIndicatorView { + return UIActivityIndicatorView(style: style) + } + + func updateUIView(_ uiView: UIActivityIndicatorView, context: UIViewRepresentableContext) { + isAnimating ? uiView.startAnimating() : uiView.stopAnimating() + } +} + +struct LoadingView: View where Content: View { + @StateObject var viewModel: MainViewModel + var content: () -> Content + + var body: some View { + GeometryReader { geometry in + ZStack(alignment: .center) { + + self.content() + .disabled(viewModel.isLoaderVisible) + .blur(radius: viewModel.isLoaderVisible ? 3 : 0) + + VStack { + Text(viewModel.loaderContent) + ActivityIndicator(isAnimating: .constant(true), style: .large) + } + .frame(width: geometry.size.width / 2, + height: geometry.size.height / 5) + .background(Color.secondary.colorInvert()) + .foregroundColor(Color.primary) + .cornerRadius(20) + .opacity(viewModel.isLoaderVisible ? 1 : 0) + + } + } + } +} diff --git a/single-factor-auth-ios/sfa-ios-aggregate-example/sfa-ios-aggregate-example/Views/LoginView.swift b/single-factor-auth-ios/sfa-ios-aggregate-example/sfa-ios-aggregate-example/Views/LoginView.swift new file mode 100644 index 00000000..5ffe3299 --- /dev/null +++ b/single-factor-auth-ios/sfa-ios-aggregate-example/sfa-ios-aggregate-example/Views/LoginView.swift @@ -0,0 +1,60 @@ +// +// LoginView.swift +// ios-aggregate-example +// +// Created by Ayush B on 25/09/24. +// + +import Foundation +import SwiftUI + +struct LoginView: View { + @StateObject var viewModel: MainViewModel + + var body: some View { + NavigationView { + LoadingView(viewModel: viewModel, content: { + Form{ + Spacer() + Text( + "SFA iOS Aggregate Example" + ).font(.title) + .multilineTextAlignment(.center).frame( + maxWidth: .infinity, + alignment: .center + ) + + Button( + action: { + viewModel.loginWithGoogle() + }, + label: { + Text("Sign in with Google") + .frame( + maxWidth: .infinity, + alignment: .center + ) + } + ).buttonStyle(.bordered) + Button( + action: { + viewModel.loginWithEmailPasswordless() + }, + label: { + Text("Sign in with Email Passwordless") + .frame( + maxWidth: .infinity, + alignment: .center + ) + } + ).buttonStyle(.bordered) + Spacer() + }.onAppear { + viewModel.initialize() + }.formStyle(.columns).padding() + }) + }.alert(isPresented: $viewModel.showAlert, content: { + Alert(title: Text(viewModel.alertContent)) + }) + } +} diff --git a/single-factor-auth-ios/sfa-ios-aggregate-example/sfa-ios-aggregate-example/ios_aggregate_exampleApp.swift b/single-factor-auth-ios/sfa-ios-aggregate-example/sfa-ios-aggregate-example/ios_aggregate_exampleApp.swift new file mode 100644 index 00000000..47a80a1e --- /dev/null +++ b/single-factor-auth-ios/sfa-ios-aggregate-example/sfa-ios-aggregate-example/ios_aggregate_exampleApp.swift @@ -0,0 +1,17 @@ +// +// ios_aggregate_exampleApp.swift +// ios-aggregate-example +// +// Created by Ayush B on 24/09/24. +// + +import SwiftUI + +@main +struct ios_aggregate_exampleApp: App { + var body: some Scene { + WindowGroup { + ContentView(viewModel: MainViewModel()) + } + } +}