diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index e8b91cf7..23bb8827 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -26,5 +26,8 @@ jobs: key: ${{ secrets.SSH_PRIVATE_KEY }} known_hosts: github.com + - name: Adding Known Hosts + run: ssh-keyscan -H github.com >> ~/.ssh/known_hosts + - name: Build run: xcodebuild build test -scheme "AtalaPRISMSDK-Package" -destination "platform=iOS Simulator,name=IPhone 14" diff --git a/.gitignore b/.gitignore index 7e9351f7..69a60578 100644 --- a/.gitignore +++ b/.gitignore @@ -26,12 +26,11 @@ Podfile.lock *.mode1v3 *.mode2v3 xcuserdata -*.xcworkspace -*.xcodeproj *.xcodeproj/project.xcworkspace/xcshareddata/ *.xcworkspace/xcshareddata/ *.xcworkspace/xcshareddata/xcschemes *.orig +.swiftpm /.project *.gcno *.gcda diff --git a/.swiftlint.yml b/.swiftlint.yml index 11b98b3a..944d06ae 100644 --- a/.swiftlint.yml +++ b/.swiftlint.yml @@ -90,6 +90,7 @@ excluded: - Pluto/Tests - Pollux/Tests - PrismAgent/Tests + - Sample line_length: ignores_comments: true ignores_urls: true diff --git a/Castor/Sources/Helpers/Base64+DIDMethodID.swift b/Castor/Sources/Helpers/Base64+DIDMethodID.swift deleted file mode 100644 index ff75619c..00000000 --- a/Castor/Sources/Helpers/Base64+DIDMethodID.swift +++ /dev/null @@ -1,12 +0,0 @@ -import Core -import Foundation - -extension Base64Utils { - func encodeMethodID(data: Data) -> String { - data.base64UrlEncodedString() - } - - func decodeMethodID(str: String) -> Data? { - return Data(fromBase64URL: str) - } -} diff --git a/Castor/Sources/Operations/CreatePrismDIDOperation.swift b/Castor/Sources/Operations/CreatePrismDIDOperation.swift index 59cf6b20..3f6b6822 100644 --- a/Castor/Sources/Operations/CreatePrismDIDOperation.swift +++ b/Castor/Sources/Operations/CreatePrismDIDOperation.swift @@ -47,10 +47,11 @@ struct CreatePrismDIDOperation { ) throws -> DID { let encodedState = try atalaOperation.serializedData() let stateHash = encodedState.sha256() + let base64State = encodedState.base64UrlEncodedString() let methodSpecificId = try PrismDIDMethodId( sections: [ stateHash, - Base64Utils().encodeMethodID(data: encodedState) + base64State ] ) return DID(method: method, methodId: methodSpecificId.description) diff --git a/Castor/Sources/Resolvers/LongFormPrismDIDResolver.swift b/Castor/Sources/Resolvers/LongFormPrismDIDResolver.swift index daf7ecf1..59521d10 100644 --- a/Castor/Sources/Resolvers/LongFormPrismDIDResolver.swift +++ b/Castor/Sources/Resolvers/LongFormPrismDIDResolver.swift @@ -8,7 +8,7 @@ struct LongFormPrismDIDResolver: DIDResolverDomain { func resolve(did: DID) throws -> DIDDocument { let prismDID = try LongFormPrismDID(did: did) guard - let data = Base64Utils().decodeMethodID(str: prismDID.encodedState) + let data = Data(fromBase64URL: prismDID.encodedState) else { throw CastorError.initialStateOfDIDChanged } let (verificationMethods, services) = try decodeState( @@ -42,7 +42,8 @@ struct LongFormPrismDIDResolver: DIDResolverDomain { stateHash: String, encodedData: Data ) throws -> ([String: DIDDocument.VerificationMethod], [DIDDocument.Service]) { - guard stateHash == encodedData.sha256() else { throw CastorError.initialStateOfDIDChanged } + let verifyEncodedState = encodedData.sha256() + guard stateHash == verifyEncodedState else { throw CastorError.initialStateOfDIDChanged } let operation = try Io_Iohk_Atala_Prism_Protos_AtalaOperation(serializedData: encodedData) let publicKeys = try operation.createDid.didData.publicKeys.map { try PrismDIDPublicKey(apollo: apollo, proto: $0) diff --git a/Core/Sources/Helpers/Base64Utils.swift b/Core/Sources/Helpers/Base64Utils.swift index fc33930c..7612a598 100644 --- a/Core/Sources/Helpers/Base64Utils.swift +++ b/Core/Sources/Helpers/Base64Utils.swift @@ -4,19 +4,24 @@ public struct Base64Utils { public init() {} public func encode(_ data: Data) -> String { - String(data.base64EncodedString() + let base64 = data.base64EncodedString() + return String(base64 .replacingOccurrences(of: "/", with: "_") .replacingOccurrences(of: "+", with: "-") .trimingTrailing(while: CharacterSet(charactersIn: "="))) } public func decode(_ src: String) -> Data? { - let expectedLength = (src.count + 3) / 4 * 4 - let base64Encoded = src + let expectedLength = src.count % 4 + let replaced = src .replacingOccurrences(of: "_", with: "/") .replacingOccurrences(of: "-", with: "+") - .appending(String(repeating: .init("="), count: expectedLength)) - return Data(base64Encoded: base64Encoded) + + if expectedLength > 0 { + return Data(base64Encoded: replaced + String(repeating: "=", count: 4 - expectedLength)) + } else { + return Data(base64Encoded:replaced) + } } } diff --git a/Core/Sources/Helpers/Date+Miliseconds.swift b/Core/Sources/Helpers/Date+Miliseconds.swift index c23315c1..22c37a31 100644 --- a/Core/Sources/Helpers/Date+Miliseconds.swift +++ b/Core/Sources/Helpers/Date+Miliseconds.swift @@ -1,11 +1,11 @@ import Foundation -extension Date { - public var millisecondsSince1970: UInt64 { - UInt64((self.timeIntervalSince1970 * 1000.0).rounded()) +public extension Date { + var millisecondsSince1970: UInt64 { + UInt64((self.timeIntervalSince1970 * 1_000.0).rounded()) } - public init(milliseconds: UInt64) { - self = Date(timeIntervalSince1970: TimeInterval(milliseconds) / 1000) + init(milliseconds: UInt64) { + self = Date(timeIntervalSince1970: TimeInterval(milliseconds) / 1_000) } } diff --git a/Core/Sources/Helpers/Future+AsynAwait.swift b/Core/Sources/Helpers/Future+AsynAwait.swift index 0604e135..e137ffc1 100644 --- a/Core/Sources/Helpers/Future+AsynAwait.swift +++ b/Core/Sources/Helpers/Future+AsynAwait.swift @@ -1,7 +1,7 @@ import Combine -extension Future where Failure == Error { - public convenience init(operation: @escaping () async throws -> Output) { +public extension Future where Failure == Error { + convenience init(operation: @escaping () async throws -> Output) { self.init { promise in Task { do { diff --git a/Core/Sources/Helpers/Map+AsyncAwait.swift b/Core/Sources/Helpers/Map+AsyncAwait.swift index e2874407..dd1437a2 100644 --- a/Core/Sources/Helpers/Map+AsyncAwait.swift +++ b/Core/Sources/Helpers/Map+AsyncAwait.swift @@ -1,5 +1,5 @@ public extension Sequence { - public func asyncMap( + func asyncMap( _ transform: (Element) async throws -> T ) async rethrows -> [T] { var values = [T]() diff --git a/Package.swift b/Package.swift index 4165e37b..1ccf0296 100644 --- a/Package.swift +++ b/Package.swift @@ -50,7 +50,7 @@ let package = Package( from: "1.4.4" ), // This doesnt seem to be working properly on command line, removing for now -// .package(url: "https://github.com/realm/SwiftLint.git", branch: "main"), +// .package(url: "https://github.com/realm/SwiftLint.git", branch: "main"), .package(url: "https://github.com/apple/swift-protobuf", from: "1.7.0"), .package(url: "https://github.com/antlr/antlr4", branch: "master"), .package(url: "https://github.com/input-output-hk/atala-prism-didcomm-swift", from: "0.3.4"), diff --git a/Pluto/Tests/CDDIDPairDAOTests.swift b/Pluto/Tests/CDDIDPairDAOTests.swift index 85c017f2..8f76546d 100644 --- a/Pluto/Tests/CDDIDPairDAOTests.swift +++ b/Pluto/Tests/CDDIDPairDAOTests.swift @@ -9,7 +9,7 @@ final class CDDIDPairDAOTests: XCTestCase { override func setUpWithError() throws { try super.setUpWithError() coreDataManager = CoreDataManager(setup: .init( - modelPath: .storeName("PrismPluto", ModelKit.bundle), + modelPath: .storeName("PrismPluto"), storeType: .memory )) privateKeyDao = CDDIDPrivateKeyDAO( diff --git a/Pluto/Tests/CDDIDPrivateKeyDAOTests.swift b/Pluto/Tests/CDDIDPrivateKeyDAOTests.swift index fde3cd84..79988608 100644 --- a/Pluto/Tests/CDDIDPrivateKeyDAOTests.swift +++ b/Pluto/Tests/CDDIDPrivateKeyDAOTests.swift @@ -8,7 +8,7 @@ final class CDDIDPrivateKeyDAOTestsTests: XCTestCase { override func setUpWithError() throws { try super.setUpWithError() coreDataManager = CoreDataManager(setup: .init( - modelPath: .storeName("PrismPluto", ModelKit.bundle), + modelPath: .storeName("PrismPluto"), storeType: .memory )) } diff --git a/Pluto/Tests/CDMessagesDAOTests.swift b/Pluto/Tests/CDMessagesDAOTests.swift index ac3b67ea..8c4ccf77 100644 --- a/Pluto/Tests/CDMessagesDAOTests.swift +++ b/Pluto/Tests/CDMessagesDAOTests.swift @@ -10,7 +10,7 @@ final class CDMessagesDAOTests: XCTestCase { override func setUpWithError() throws { try super.setUpWithError() coreDataManager = CoreDataManager(setup: .init( - modelPath: .storeName("PrismPluto", ModelKit.bundle), + modelPath: .storeName("PrismPluto"), storeType: .memory )) privateDAO = CDDIDPrivateKeyDAO( diff --git a/Pluto/Tests/CDRegisteredDIDDaoTests.swift b/Pluto/Tests/CDRegisteredDIDDaoTests.swift index ceabde9f..660e1479 100644 --- a/Pluto/Tests/CDRegisteredDIDDaoTests.swift +++ b/Pluto/Tests/CDRegisteredDIDDaoTests.swift @@ -8,7 +8,7 @@ final class CDRegisteredDIDDaoTests: XCTestCase { override func setUpWithError() throws { try super.setUpWithError() coreDataManager = CoreDataManager(setup: .init( - modelPath: .storeName("PrismPluto", ModelKit.bundle), + modelPath: .storeName("PrismPluto"), storeType: .memory )) } diff --git a/PrismAgent/Sources/Error.swift b/PrismAgent/Sources/Error.swift deleted file mode 100644 index 72bfca55..00000000 --- a/PrismAgent/Sources/Error.swift +++ /dev/null @@ -1,3 +0,0 @@ -public enum PrismAgentError: Error { - case invalidURLError -} diff --git a/Sample/AtalaPrismChallengerAppDemo/atala-prism-challenger-app.xcodeproj/project.pbxproj b/Sample/AtalaPrismChallengerAppDemo/atala-prism-challenger-app.xcodeproj/project.pbxproj new file mode 100644 index 00000000..03ff687f --- /dev/null +++ b/Sample/AtalaPrismChallengerAppDemo/atala-prism-challenger-app.xcodeproj/project.pbxproj @@ -0,0 +1,416 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 56; + objects = { + +/* Begin PBXBuildFile section */ + EE98B46E29103EB500EA978C /* atala_prism_challenger_appApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE98B46D29103EB500EA978C /* atala_prism_challenger_appApp.swift */; }; + EE98B47029103EB500EA978C /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE98B46F29103EB500EA978C /* ContentView.swift */; }; + EE98B47229103EB600EA978C /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = EE98B47129103EB600EA978C /* Assets.xcassets */; }; + EE98B47629103EB600EA978C /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = EE98B47529103EB600EA978C /* Preview Assets.xcassets */; }; + EE98B47F291047D800EA978C /* ContentViewModelImpl.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE98B47E291047D800EA978C /* ContentViewModelImpl.swift */; }; + EE98B487291050C200EA978C /* EmptyNavigationLink.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE98B486291050C200EA978C /* EmptyNavigationLink.swift */; }; + EE98B4892910561600EA978C /* LoggedInView.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE98B4882910561600EA978C /* LoggedInView.swift */; }; + EE98B48B2910563800EA978C /* ContentRouterImpl.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE98B48A2910563800EA978C /* ContentRouterImpl.swift */; }; + EEE2A2D029246B2700288428 /* Authenticate in Frameworks */ = {isa = PBXBuildFile; productRef = EEE2A2CF29246B2700288428 /* Authenticate */; }; + EEE2A2D229246C6800288428 /* Domain in Frameworks */ = {isa = PBXBuildFile; productRef = EEE2A2D129246C6800288428 /* Domain */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + EE38134C2938D35A00A3A710 /* atala-prism-swift-sdk */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = "atala-prism-swift-sdk"; path = ../..; sourceTree = ""; }; + EE98B46A29103EB500EA978C /* atala-prism-challenger-app.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "atala-prism-challenger-app.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + EE98B46D29103EB500EA978C /* atala_prism_challenger_appApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = atala_prism_challenger_appApp.swift; sourceTree = ""; }; + EE98B46F29103EB500EA978C /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = ""; }; + EE98B47129103EB600EA978C /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + EE98B47329103EB600EA978C /* atala_prism_challenger_app.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = atala_prism_challenger_app.entitlements; sourceTree = ""; }; + EE98B47529103EB600EA978C /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = ""; }; + EE98B47E291047D800EA978C /* ContentViewModelImpl.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentViewModelImpl.swift; sourceTree = ""; }; + EE98B480291049F600EA978C /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Info.plist; sourceTree = ""; }; + EE98B486291050C200EA978C /* EmptyNavigationLink.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmptyNavigationLink.swift; sourceTree = ""; }; + EE98B4882910561600EA978C /* LoggedInView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoggedInView.swift; sourceTree = ""; }; + EE98B48A2910563800EA978C /* ContentRouterImpl.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentRouterImpl.swift; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + EE98B46729103EB500EA978C /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + EEE2A2D229246C6800288428 /* Domain in Frameworks */, + EEE2A2D029246B2700288428 /* Authenticate in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + EE38134B2938D35A00A3A710 /* Packages */ = { + isa = PBXGroup; + children = ( + EE38134C2938D35A00A3A710 /* atala-prism-swift-sdk */, + ); + name = Packages; + sourceTree = ""; + }; + EE98B46129103EB500EA978C = { + isa = PBXGroup; + children = ( + EE38134B2938D35A00A3A710 /* Packages */, + EE98B46C29103EB500EA978C /* atala-prism-challenger-app */, + EE98B46B29103EB500EA978C /* Products */, + EE98B48129104A0000EA978C /* Frameworks */, + ); + sourceTree = ""; + }; + EE98B46B29103EB500EA978C /* Products */ = { + isa = PBXGroup; + children = ( + EE98B46A29103EB500EA978C /* atala-prism-challenger-app.app */, + ); + name = Products; + sourceTree = ""; + }; + EE98B46C29103EB500EA978C /* atala-prism-challenger-app */ = { + isa = PBXGroup; + children = ( + EE98B480291049F600EA978C /* Info.plist */, + EE98B46D29103EB500EA978C /* atala_prism_challenger_appApp.swift */, + EE98B46F29103EB500EA978C /* ContentView.swift */, + EE98B47129103EB600EA978C /* Assets.xcassets */, + EE98B47329103EB600EA978C /* atala_prism_challenger_app.entitlements */, + EE98B47429103EB600EA978C /* Preview Content */, + EE98B47E291047D800EA978C /* ContentViewModelImpl.swift */, + EE98B486291050C200EA978C /* EmptyNavigationLink.swift */, + EE98B4882910561600EA978C /* LoggedInView.swift */, + EE98B48A2910563800EA978C /* ContentRouterImpl.swift */, + ); + path = "atala-prism-challenger-app"; + sourceTree = ""; + }; + EE98B47429103EB600EA978C /* Preview Content */ = { + isa = PBXGroup; + children = ( + EE98B47529103EB600EA978C /* Preview Assets.xcassets */, + ); + path = "Preview Content"; + sourceTree = ""; + }; + EE98B48129104A0000EA978C /* Frameworks */ = { + isa = PBXGroup; + children = ( + ); + name = Frameworks; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + EE98B46929103EB500EA978C /* atala-prism-challenger-app */ = { + isa = PBXNativeTarget; + buildConfigurationList = EE98B47929103EB600EA978C /* Build configuration list for PBXNativeTarget "atala-prism-challenger-app" */; + buildPhases = ( + EE98B46629103EB500EA978C /* Sources */, + EE98B46729103EB500EA978C /* Frameworks */, + EE98B46829103EB500EA978C /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "atala-prism-challenger-app"; + packageProductDependencies = ( + EEE2A2CF29246B2700288428 /* Authenticate */, + EEE2A2D129246C6800288428 /* Domain */, + ); + productName = "atala-prism-challenger-app"; + productReference = EE98B46A29103EB500EA978C /* atala-prism-challenger-app.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + EE98B46229103EB500EA978C /* Project object */ = { + isa = PBXProject; + attributes = { + BuildIndependentTargetsInParallel = 1; + LastSwiftUpdateCheck = 1400; + LastUpgradeCheck = 1400; + TargetAttributes = { + EE98B46929103EB500EA978C = { + CreatedOnToolsVersion = 14.0; + }; + }; + }; + buildConfigurationList = EE98B46529103EB500EA978C /* Build configuration list for PBXProject "atala-prism-challenger-app" */; + compatibilityVersion = "Xcode 14.0"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = EE98B46129103EB500EA978C; + packageReferences = ( + ); + productRefGroup = EE98B46B29103EB500EA978C /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + EE98B46929103EB500EA978C /* atala-prism-challenger-app */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + EE98B46829103EB500EA978C /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + EE98B47629103EB600EA978C /* Preview Assets.xcassets in Resources */, + EE98B47229103EB600EA978C /* Assets.xcassets in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + EE98B46629103EB500EA978C /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + EE98B4892910561600EA978C /* LoggedInView.swift in Sources */, + EE98B47029103EB500EA978C /* ContentView.swift in Sources */, + EE98B48B2910563800EA978C /* ContentRouterImpl.swift in Sources */, + EE98B487291050C200EA978C /* EmptyNavigationLink.swift in Sources */, + EE98B47F291047D800EA978C /* ContentViewModelImpl.swift in Sources */, + EE98B46E29103EB500EA978C /* atala_prism_challenger_appApp.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + EE98B47729103EB600EA978C /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + 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; + GCC_C_LANGUAGE_STANDARD = gnu11; + 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; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + EE98B47829103EB600EA978C /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + 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; + GCC_C_LANGUAGE_STANDARD = gnu11; + 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; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + }; + name = Release; + }; + EE98B47A29103EB600EA978C /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CODE_SIGN_ENTITLEMENTS = "atala-prism-challenger-app/atala_prism_challenger_app.entitlements"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_ASSET_PATHS = "\"atala-prism-challenger-app/Preview Content\""; + DEVELOPMENT_TEAM = 89TW38X994; + ENABLE_PREVIEWS = YES; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_FILE = "atala-prism-challenger-app/Info.plist"; + "INFOPLIST_KEY_UIApplicationSceneManifest_Generation[sdk=iphoneos*]" = YES; + "INFOPLIST_KEY_UIApplicationSceneManifest_Generation[sdk=iphonesimulator*]" = YES; + "INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents[sdk=iphoneos*]" = YES; + "INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents[sdk=iphonesimulator*]" = YES; + "INFOPLIST_KEY_UILaunchScreen_Generation[sdk=iphoneos*]" = YES; + "INFOPLIST_KEY_UILaunchScreen_Generation[sdk=iphonesimulator*]" = YES; + "INFOPLIST_KEY_UIStatusBarStyle[sdk=iphoneos*]" = UIStatusBarStyleDefault; + "INFOPLIST_KEY_UIStatusBarStyle[sdk=iphonesimulator*]" = UIStatusBarStyleDefault; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + IPHONEOS_DEPLOYMENT_TARGET = 16.0; + LD_RUNPATH_SEARCH_PATHS = "@executable_path/Frameworks"; + "LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = "@executable_path/../Frameworks"; + MACOSX_DEPLOYMENT_TARGET = 12.3; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = io.atala.prism.sdk.wallet.atalachallengerdemo; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = auto; + SUPPORTED_PLATFORMS = "iphoneos iphonesimulator macosx"; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + EE98B47B29103EB600EA978C /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CODE_SIGN_ENTITLEMENTS = "atala-prism-challenger-app/atala_prism_challenger_app.entitlements"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_ASSET_PATHS = "\"atala-prism-challenger-app/Preview Content\""; + DEVELOPMENT_TEAM = 89TW38X994; + ENABLE_PREVIEWS = YES; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_FILE = "atala-prism-challenger-app/Info.plist"; + "INFOPLIST_KEY_UIApplicationSceneManifest_Generation[sdk=iphoneos*]" = YES; + "INFOPLIST_KEY_UIApplicationSceneManifest_Generation[sdk=iphonesimulator*]" = YES; + "INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents[sdk=iphoneos*]" = YES; + "INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents[sdk=iphonesimulator*]" = YES; + "INFOPLIST_KEY_UILaunchScreen_Generation[sdk=iphoneos*]" = YES; + "INFOPLIST_KEY_UILaunchScreen_Generation[sdk=iphonesimulator*]" = YES; + "INFOPLIST_KEY_UIStatusBarStyle[sdk=iphoneos*]" = UIStatusBarStyleDefault; + "INFOPLIST_KEY_UIStatusBarStyle[sdk=iphonesimulator*]" = UIStatusBarStyleDefault; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + IPHONEOS_DEPLOYMENT_TARGET = 16.0; + LD_RUNPATH_SEARCH_PATHS = "@executable_path/Frameworks"; + "LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = "@executable_path/../Frameworks"; + MACOSX_DEPLOYMENT_TARGET = 12.3; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = io.atala.prism.sdk.wallet.atalachallengerdemo; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = auto; + SUPPORTED_PLATFORMS = "iphoneos iphonesimulator macosx"; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + EE98B46529103EB500EA978C /* Build configuration list for PBXProject "atala-prism-challenger-app" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + EE98B47729103EB600EA978C /* Debug */, + EE98B47829103EB600EA978C /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + EE98B47929103EB600EA978C /* Build configuration list for PBXNativeTarget "atala-prism-challenger-app" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + EE98B47A29103EB600EA978C /* Debug */, + EE98B47B29103EB600EA978C /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + +/* Begin XCSwiftPackageProductDependency section */ + EEE2A2CF29246B2700288428 /* Authenticate */ = { + isa = XCSwiftPackageProductDependency; + productName = Authenticate; + }; + EEE2A2D129246C6800288428 /* Domain */ = { + isa = XCSwiftPackageProductDependency; + productName = Domain; + }; +/* End XCSwiftPackageProductDependency section */ + }; + rootObject = EE98B46229103EB500EA978C /* Project object */; +} diff --git a/Sample/AtalaPrismChallengerAppDemo/atala-prism-challenger-app.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Sample/AtalaPrismChallengerAppDemo/atala-prism-challenger-app.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 00000000..919434a6 --- /dev/null +++ b/Sample/AtalaPrismChallengerAppDemo/atala-prism-challenger-app.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Sample/AtalaPrismChallengerAppDemo/atala-prism-challenger-app.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/Sample/AtalaPrismChallengerAppDemo/atala-prism-challenger-app.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 00000000..18d98100 --- /dev/null +++ b/Sample/AtalaPrismChallengerAppDemo/atala-prism-challenger-app.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/Sample/AtalaPrismChallengerAppDemo/atala-prism-challenger-app/Assets.xcassets/AccentColor.colorset/Contents.json b/Sample/AtalaPrismChallengerAppDemo/atala-prism-challenger-app/Assets.xcassets/AccentColor.colorset/Contents.json new file mode 100644 index 00000000..eb878970 --- /dev/null +++ b/Sample/AtalaPrismChallengerAppDemo/atala-prism-challenger-app/Assets.xcassets/AccentColor.colorset/Contents.json @@ -0,0 +1,11 @@ +{ + "colors" : [ + { + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Sample/AtalaPrismChallengerAppDemo/atala-prism-challenger-app/Assets.xcassets/AppIcon.appiconset/Contents.json b/Sample/AtalaPrismChallengerAppDemo/atala-prism-challenger-app/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 00000000..532cd729 --- /dev/null +++ b/Sample/AtalaPrismChallengerAppDemo/atala-prism-challenger-app/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,63 @@ +{ + "images" : [ + { + "idiom" : "universal", + "platform" : "ios", + "size" : "1024x1024" + }, + { + "idiom" : "mac", + "scale" : "1x", + "size" : "16x16" + }, + { + "idiom" : "mac", + "scale" : "2x", + "size" : "16x16" + }, + { + "idiom" : "mac", + "scale" : "1x", + "size" : "32x32" + }, + { + "idiom" : "mac", + "scale" : "2x", + "size" : "32x32" + }, + { + "idiom" : "mac", + "scale" : "1x", + "size" : "128x128" + }, + { + "idiom" : "mac", + "scale" : "2x", + "size" : "128x128" + }, + { + "idiom" : "mac", + "scale" : "1x", + "size" : "256x256" + }, + { + "idiom" : "mac", + "scale" : "2x", + "size" : "256x256" + }, + { + "idiom" : "mac", + "scale" : "1x", + "size" : "512x512" + }, + { + "idiom" : "mac", + "scale" : "2x", + "size" : "512x512" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Sample/AtalaPrismChallengerAppDemo/atala-prism-challenger-app/Assets.xcassets/Contents.json b/Sample/AtalaPrismChallengerAppDemo/atala-prism-challenger-app/Assets.xcassets/Contents.json new file mode 100644 index 00000000..73c00596 --- /dev/null +++ b/Sample/AtalaPrismChallengerAppDemo/atala-prism-challenger-app/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Sample/AtalaPrismChallengerAppDemo/atala-prism-challenger-app/Assets.xcassets/FacebookLogo.imageset/Contents.json b/Sample/AtalaPrismChallengerAppDemo/atala-prism-challenger-app/Assets.xcassets/FacebookLogo.imageset/Contents.json new file mode 100644 index 00000000..76355036 --- /dev/null +++ b/Sample/AtalaPrismChallengerAppDemo/atala-prism-challenger-app/Assets.xcassets/FacebookLogo.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "pngwing.com-2.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Sample/AtalaPrismChallengerAppDemo/atala-prism-challenger-app/Assets.xcassets/FacebookLogo.imageset/pngwing.com-2.png b/Sample/AtalaPrismChallengerAppDemo/atala-prism-challenger-app/Assets.xcassets/FacebookLogo.imageset/pngwing.com-2.png new file mode 100644 index 00000000..3edc3be9 Binary files /dev/null and b/Sample/AtalaPrismChallengerAppDemo/atala-prism-challenger-app/Assets.xcassets/FacebookLogo.imageset/pngwing.com-2.png differ diff --git a/Sample/AtalaPrismChallengerAppDemo/atala-prism-challenger-app/Assets.xcassets/GoogleLogo.imageset/Contents.json b/Sample/AtalaPrismChallengerAppDemo/atala-prism-challenger-app/Assets.xcassets/GoogleLogo.imageset/Contents.json new file mode 100644 index 00000000..708b6752 --- /dev/null +++ b/Sample/AtalaPrismChallengerAppDemo/atala-prism-challenger-app/Assets.xcassets/GoogleLogo.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "pngwing.com-3.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Sample/AtalaPrismChallengerAppDemo/atala-prism-challenger-app/Assets.xcassets/GoogleLogo.imageset/pngwing.com-3.png b/Sample/AtalaPrismChallengerAppDemo/atala-prism-challenger-app/Assets.xcassets/GoogleLogo.imageset/pngwing.com-3.png new file mode 100644 index 00000000..e1fe4899 Binary files /dev/null and b/Sample/AtalaPrismChallengerAppDemo/atala-prism-challenger-app/Assets.xcassets/GoogleLogo.imageset/pngwing.com-3.png differ diff --git a/Sample/AtalaPrismChallengerAppDemo/atala-prism-challenger-app/ContentRouterImpl.swift b/Sample/AtalaPrismChallengerAppDemo/atala-prism-challenger-app/ContentRouterImpl.swift new file mode 100644 index 00000000..88c33f2c --- /dev/null +++ b/Sample/AtalaPrismChallengerAppDemo/atala-prism-challenger-app/ContentRouterImpl.swift @@ -0,0 +1,8 @@ +import SwiftUI + +struct ContentRouterImpl: ContentRouter { + + func routeToLoggedInView() -> some View { + LoggedInView() + } +} diff --git a/Sample/AtalaPrismChallengerAppDemo/atala-prism-challenger-app/ContentView.swift b/Sample/AtalaPrismChallengerAppDemo/atala-prism-challenger-app/ContentView.swift new file mode 100644 index 00000000..1ecee8bd --- /dev/null +++ b/Sample/AtalaPrismChallengerAppDemo/atala-prism-challenger-app/ContentView.swift @@ -0,0 +1,108 @@ +import SwiftUI + +protocol ContentViewModel: ObservableObject { + var did: String { get set } + var isLoggedIn: Bool { get set } + func login(name: String) async + func verifyChallenge(url: URL) async +} + +protocol ContentRouter { + associatedtype LoggedInV: View + + func routeToLoggedInView() -> LoggedInV +} + +struct ContentView: View { + + enum Website: Int { + case google + case facebook + + var string: String { + switch self { + case .google: + return "Google" + case .facebook: + return "Facebook" + } + } + + var image: String { + switch self { + case .google: + return "GoogleLogo" + case .facebook: + return "FacebookLogo" + + } + } + + var color: Color { + switch self { + case .google: + return Color.red + case .facebook: + return Color(uiColor: UIColor(red: 66 / 255, green: 103 / 255, blue: 178 / 255, alpha: 1)) + } + } + } + + @StateObject var viewModel: ViewModel + let router: Router + let website = Website(rawValue: Int.random(in: 0...1))! + + var body: some View { + NavigationView { + VStack { + Image(website.image) + .resizable() + .scaledToFit() + Text("Please insert DID to Login:") + TextField("DID", text: $viewModel.did) + .textFieldStyle(.roundedBorder) + Button("Login with DID") { + Task { + await viewModel.login(name: website.string) + } + } + .padding(20) + .background(website.color) + .tint(.white) + .clipShape(Capsule(style: .continuous)) + EmptyNavigationLink( + isActive: $viewModel.isLoggedIn, + destination: { router.routeToLoggedInView() } + ) + } + .padding() + } + .onOpenURL {url in + Task { + await viewModel.verifyChallenge(url: url) + } + } + } +} + +struct ContentView_Previews: PreviewProvider { + + class ViewModel: ContentViewModel { + var isLoggedIn: Bool = false + var did: String = "" + + func login(name: String) {} + func verifyChallenge(url: URL) {} + } + + struct Router: ContentRouter { + + func routeToLoggedInView() -> some View { + Text("Empty") + } + } + + static var previews: some View { + ContentView(viewModel: ViewModel(), router: Router()) + } +} diff --git a/Sample/AtalaPrismChallengerAppDemo/atala-prism-challenger-app/ContentViewModelImpl.swift b/Sample/AtalaPrismChallengerAppDemo/atala-prism-challenger-app/ContentViewModelImpl.swift new file mode 100644 index 00000000..335ce6fe --- /dev/null +++ b/Sample/AtalaPrismChallengerAppDemo/atala-prism-challenger-app/ContentViewModelImpl.swift @@ -0,0 +1,78 @@ +import Foundation +import Domain +import Builders +import Authenticate +import UIKit + +class ContentViewModelImpl: ContentViewModel { + private let apollo: Apollo + private let castor: Castor + private let authenticate: AuthenticateChallenger + private let storage = UserDefaults.standard + private let seedKey = "Seed" + private let privateKeyKey = "PrivateKey" + var did: String = "" + var isLoggedIn: Bool = false + + init() { + self.apollo = ApolloBuilder().build() + self.castor = CastorBuilder(apollo: apollo).build() + self.authenticate = .init( + castor: castor, + apollo: apollo, + scheme: .init( + scheme: "ChallengeApp", + host: "submitChallenge" + ), + deepLinkPusher: UIApplication.shared + ) + } + + func login(name: String) async { + do { + let keyPair = apollo.createKeyPair(seed: createOrGetSeed(), index: 0) + let challenge = try authenticate.processChallengeForAuthenticate( + did: try castor.parseDID(str: did), + challengerName: name, + challengerPublicKey: keyPair.publicKey, + challenge: UUID().uuidString + ) + + try await authenticate.startAuthenticateWithPrism(challengeObject: challenge) + } catch { + print(error.localizedDescription) + } + } + + func verifyChallenge(url: URL) { + Task { + do { + let submited = try authenticate.submitedPrismChallenge(url: url) + let verification = try await authenticate.verifyChallenge(submitedChallengeResponse: submited) + isLoggedIn = verification + } + catch { + print(error.localizedDescription) + } + } + } + + private func getPrivateKey() -> Data? { + storage.data(forKey: privateKeyKey) + } + + private func createOrGetSeed() -> Seed { + guard let seed = storage.data(forKey: seedKey) else { + let (_, seed) = apollo.createRandomSeed() + storage.set(seed.value, forKey: seedKey) + return seed + } + return Seed(value: seed) + } +} + +extension UIApplication: DeepLinkPusher { + public func openDeepLink(url: URL) async throws -> Bool { + await open(url) + } +} diff --git a/Sample/AtalaPrismChallengerAppDemo/atala-prism-challenger-app/EmptyNavigationLink.swift b/Sample/AtalaPrismChallengerAppDemo/atala-prism-challenger-app/EmptyNavigationLink.swift new file mode 100644 index 00000000..6a41a346 --- /dev/null +++ b/Sample/AtalaPrismChallengerAppDemo/atala-prism-challenger-app/EmptyNavigationLink.swift @@ -0,0 +1,16 @@ +import SwiftUI + +struct EmptyNavigationLink: View { + let isActive: Binding + @ViewBuilder var destination: () -> Destination + + var body: some View { + NavigationLink( + isActive: isActive + ) { + self.destination() + } label: { + EmptyView() + } + } +} diff --git a/Sample/AtalaPrismChallengerAppDemo/atala-prism-challenger-app/Info.plist b/Sample/AtalaPrismChallengerAppDemo/atala-prism-challenger-app/Info.plist new file mode 100644 index 00000000..d1ddbea8 --- /dev/null +++ b/Sample/AtalaPrismChallengerAppDemo/atala-prism-challenger-app/Info.plist @@ -0,0 +1,20 @@ + + + + + CFBundleURLTypes + + + CFBundleTypeRole + Editor + CFBundleURLName + submitChallenge + CFBundleURLSchemes + + ChallengeApp + + + + + + diff --git a/Sample/AtalaPrismChallengerAppDemo/atala-prism-challenger-app/LoggedInView.swift b/Sample/AtalaPrismChallengerAppDemo/atala-prism-challenger-app/LoggedInView.swift new file mode 100644 index 00000000..a0dd646d --- /dev/null +++ b/Sample/AtalaPrismChallengerAppDemo/atala-prism-challenger-app/LoggedInView.swift @@ -0,0 +1,24 @@ +// +// LoggedInView.swift +// atala-prism-challenger-app +// +// Created by Goncalo Frade IOHK on 31/10/2022. +// + +import SwiftUI + +struct LoggedInView: View { + var body: some View { + VStack { + Text("🚀🎉 Congrats 🎉🚀") + .font(.title) + Text("You successfully Logged In with your ") + Text("DID").bold() + } + } +} + +struct LoggedInView_Previews: PreviewProvider { + static var previews: some View { + LoggedInView() + } +} diff --git a/Sample/AtalaPrismChallengerAppDemo/atala-prism-challenger-app/Preview Content/Preview Assets.xcassets/Contents.json b/Sample/AtalaPrismChallengerAppDemo/atala-prism-challenger-app/Preview Content/Preview Assets.xcassets/Contents.json new file mode 100644 index 00000000..73c00596 --- /dev/null +++ b/Sample/AtalaPrismChallengerAppDemo/atala-prism-challenger-app/Preview Content/Preview Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Sample/AtalaPrismChallengerAppDemo/atala-prism-challenger-app/atala_prism_challenger_app.entitlements b/Sample/AtalaPrismChallengerAppDemo/atala-prism-challenger-app/atala_prism_challenger_app.entitlements new file mode 100644 index 00000000..f2ef3ae0 --- /dev/null +++ b/Sample/AtalaPrismChallengerAppDemo/atala-prism-challenger-app/atala_prism_challenger_app.entitlements @@ -0,0 +1,10 @@ + + + + + com.apple.security.app-sandbox + + com.apple.security.files.user-selected.read-only + + + diff --git a/Sample/AtalaPrismChallengerAppDemo/atala-prism-challenger-app/atala_prism_challenger_appApp.swift b/Sample/AtalaPrismChallengerAppDemo/atala-prism-challenger-app/atala_prism_challenger_appApp.swift new file mode 100644 index 00000000..82969fc2 --- /dev/null +++ b/Sample/AtalaPrismChallengerAppDemo/atala-prism-challenger-app/atala_prism_challenger_appApp.swift @@ -0,0 +1,18 @@ +// +// atala_prism_challenger_appApp.swift +// atala-prism-challenger-app +// +// Created by Goncalo Frade IOHK on 31/10/2022. +// + +import SwiftUI + +@main +struct atala_prism_challenger_appApp: App { + var body: some Scene { + WindowGroup { + ContentView(viewModel: ContentViewModelImpl(), router: ContentRouterImpl()) + .environment(\.colorScheme, .light) + } + } +} diff --git a/Sample/AtalaPrismWalletDemo/AtalaPrismWalletDemo.xcodeproj/project.pbxproj b/Sample/AtalaPrismWalletDemo/AtalaPrismWalletDemo.xcodeproj/project.pbxproj new file mode 100644 index 00000000..91779eee --- /dev/null +++ b/Sample/AtalaPrismWalletDemo/AtalaPrismWalletDemo.xcodeproj/project.pbxproj @@ -0,0 +1,520 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 56; + objects = { + +/* Begin PBXBuildFile section */ + EE3813502938D5B100A3A710 /* Apollo in Frameworks */ = {isa = PBXBuildFile; productRef = EE38134F2938D5B100A3A710 /* Apollo */; }; + EE3813522938D5B100A3A710 /* Authenticate in Frameworks */ = {isa = PBXBuildFile; productRef = EE3813512938D5B100A3A710 /* Authenticate */; }; + EE3813542938D5B100A3A710 /* Builders in Frameworks */ = {isa = PBXBuildFile; productRef = EE3813532938D5B100A3A710 /* Builders */; }; + EE3813562938D5B100A3A710 /* Castor in Frameworks */ = {isa = PBXBuildFile; productRef = EE3813552938D5B100A3A710 /* Castor */; }; + EE3813582938D5B100A3A710 /* Domain in Frameworks */ = {isa = PBXBuildFile; productRef = EE3813572938D5B100A3A710 /* Domain */; }; + EE38135A2938D5B100A3A710 /* Mercury in Frameworks */ = {isa = PBXBuildFile; productRef = EE3813592938D5B100A3A710 /* Mercury */; }; + EE38135C2938D5B100A3A710 /* Pluto in Frameworks */ = {isa = PBXBuildFile; productRef = EE38135B2938D5B100A3A710 /* Pluto */; }; + EE38135E2938D5B100A3A710 /* Pollux in Frameworks */ = {isa = PBXBuildFile; productRef = EE38135D2938D5B100A3A710 /* Pollux */; }; + EE3813602938D5B100A3A710 /* PrismAgent in Frameworks */ = {isa = PBXBuildFile; productRef = EE38135F2938D5B100A3A710 /* PrismAgent */; }; + EEE61FBA2937CA280053AE52 /* AtalaPrismWalletDemoApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = EEE61FB92937CA280053AE52 /* AtalaPrismWalletDemoApp.swift */; }; + EEE61FBC2937CA280053AE52 /* FuncionalitiesList.swift in Sources */ = {isa = PBXBuildFile; fileRef = EEE61FBB2937CA280053AE52 /* FuncionalitiesList.swift */; }; + EEE61FBE2937CA2A0053AE52 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = EEE61FBD2937CA2A0053AE52 /* Assets.xcassets */; }; + EEE61FC12937CA2A0053AE52 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = EEE61FC02937CA2A0053AE52 /* Preview Assets.xcassets */; }; + EEE61FDD2937CD7A0053AE52 /* SeedFuncionalitiesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = EEE61FDC2937CD7A0053AE52 /* SeedFuncionalitiesView.swift */; }; + EEE61FE02937CEAA0053AE52 /* SeedViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EEE61FDF2937CEAA0053AE52 /* SeedViewModel.swift */; }; + EEE61FE42937D5560053AE52 /* DIDFuncionalitiesViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EEE61FE32937D5560053AE52 /* DIDFuncionalitiesViewModel.swift */; }; + EEE61FE82937D7EE0053AE52 /* DIDFuncionalitiesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = EEE61FE72937D7EE0053AE52 /* DIDFuncionalitiesView.swift */; }; + EEE620132937F1D40053AE52 /* PrintObjects.swift in Sources */ = {isa = PBXBuildFile; fileRef = EEE620122937F1D40053AE52 /* PrintObjects.swift */; }; + EEE620162937F3110053AE52 /* SigningVerificationViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EEE620152937F3110053AE52 /* SigningVerificationViewModel.swift */; }; + EEE620182937F6870053AE52 /* SigningVerificationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = EEE620172937F6870053AE52 /* SigningVerificationView.swift */; }; + EEE6202F2937FDE50053AE52 /* AuthenticateWalletView.swift in Sources */ = {isa = PBXBuildFile; fileRef = EEE6202D2937FDE50053AE52 /* AuthenticateWalletView.swift */; }; + EEE620302937FDE50053AE52 /* AuthenticateWalletViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EEE6202E2937FDE50053AE52 /* AuthenticateWalletViewModel.swift */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + EE38134E2938D55D00A3A710 /* atala-prism-swift-sdk */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = "atala-prism-swift-sdk"; path = ../..; sourceTree = ""; }; + EEE61FB62937CA280053AE52 /* AtalaPrismWalletDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = AtalaPrismWalletDemo.app; sourceTree = BUILT_PRODUCTS_DIR; }; + EEE61FB92937CA280053AE52 /* AtalaPrismWalletDemoApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AtalaPrismWalletDemoApp.swift; sourceTree = ""; }; + EEE61FBB2937CA280053AE52 /* FuncionalitiesList.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FuncionalitiesList.swift; sourceTree = ""; }; + EEE61FBD2937CA2A0053AE52 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + EEE61FC02937CA2A0053AE52 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = ""; }; + EEE61FDC2937CD7A0053AE52 /* SeedFuncionalitiesView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SeedFuncionalitiesView.swift; sourceTree = ""; }; + EEE61FDF2937CEAA0053AE52 /* SeedViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SeedViewModel.swift; sourceTree = ""; }; + EEE61FE32937D5560053AE52 /* DIDFuncionalitiesViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DIDFuncionalitiesViewModel.swift; sourceTree = ""; }; + EEE61FE72937D7EE0053AE52 /* DIDFuncionalitiesView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DIDFuncionalitiesView.swift; sourceTree = ""; }; + EEE620122937F1D40053AE52 /* PrintObjects.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrintObjects.swift; sourceTree = ""; }; + EEE620152937F3110053AE52 /* SigningVerificationViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SigningVerificationViewModel.swift; sourceTree = ""; }; + EEE620172937F6870053AE52 /* SigningVerificationView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SigningVerificationView.swift; sourceTree = ""; }; + EEE6202D2937FDE50053AE52 /* AuthenticateWalletView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AuthenticateWalletView.swift; sourceTree = ""; }; + EEE6202E2937FDE50053AE52 /* AuthenticateWalletViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AuthenticateWalletViewModel.swift; sourceTree = ""; }; + EEE620312937FF2C0053AE52 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Info.plist; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + EEE61FB32937CA280053AE52 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + EE38135A2938D5B100A3A710 /* Mercury in Frameworks */, + EE3813582938D5B100A3A710 /* Domain in Frameworks */, + EE38135E2938D5B100A3A710 /* Pollux in Frameworks */, + EE38135C2938D5B100A3A710 /* Pluto in Frameworks */, + EE3813602938D5B100A3A710 /* PrismAgent in Frameworks */, + EE3813542938D5B100A3A710 /* Builders in Frameworks */, + EE3813502938D5B100A3A710 /* Apollo in Frameworks */, + EE3813562938D5B100A3A710 /* Castor in Frameworks */, + EE3813522938D5B100A3A710 /* Authenticate in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + EE38134D2938D55D00A3A710 /* Packages */ = { + isa = PBXGroup; + children = ( + EE38134E2938D55D00A3A710 /* atala-prism-swift-sdk */, + ); + name = Packages; + sourceTree = ""; + }; + EEE61FAD2937CA280053AE52 = { + isa = PBXGroup; + children = ( + EE38134D2938D55D00A3A710 /* Packages */, + EEE61FB82937CA280053AE52 /* AtalaPrismWalletDemo */, + EEE61FB72937CA280053AE52 /* Products */, + EEE61FEB2937DCBE0053AE52 /* Frameworks */, + ); + sourceTree = ""; + }; + EEE61FB72937CA280053AE52 /* Products */ = { + isa = PBXGroup; + children = ( + EEE61FB62937CA280053AE52 /* AtalaPrismWalletDemo.app */, + ); + name = Products; + sourceTree = ""; + }; + EEE61FB82937CA280053AE52 /* AtalaPrismWalletDemo */ = { + isa = PBXGroup; + children = ( + EEE620312937FF2C0053AE52 /* Info.plist */, + EEE620112937F1C30053AE52 /* Helper */, + EEE61FDE2937CE970053AE52 /* Modules */, + EEE61FB92937CA280053AE52 /* AtalaPrismWalletDemoApp.swift */, + EEE61FBB2937CA280053AE52 /* FuncionalitiesList.swift */, + EEE61FBD2937CA2A0053AE52 /* Assets.xcassets */, + EEE61FBF2937CA2A0053AE52 /* Preview Content */, + ); + path = AtalaPrismWalletDemo; + sourceTree = ""; + }; + EEE61FBF2937CA2A0053AE52 /* Preview Content */ = { + isa = PBXGroup; + children = ( + EEE61FC02937CA2A0053AE52 /* Preview Assets.xcassets */, + ); + path = "Preview Content"; + sourceTree = ""; + }; + EEE61FDE2937CE970053AE52 /* Modules */ = { + isa = PBXGroup; + children = ( + EEE6202C2937FD4B0053AE52 /* AuthenticateWallet */, + EEE620142937F2C80053AE52 /* SigningVerification */, + EEE61FE22937D5140053AE52 /* DID */, + EEE61FE12937D5090053AE52 /* Seed */, + ); + path = Modules; + sourceTree = ""; + }; + EEE61FE12937D5090053AE52 /* Seed */ = { + isa = PBXGroup; + children = ( + EEE61FDF2937CEAA0053AE52 /* SeedViewModel.swift */, + EEE61FDC2937CD7A0053AE52 /* SeedFuncionalitiesView.swift */, + ); + path = Seed; + sourceTree = ""; + }; + EEE61FE22937D5140053AE52 /* DID */ = { + isa = PBXGroup; + children = ( + EEE61FE32937D5560053AE52 /* DIDFuncionalitiesViewModel.swift */, + EEE61FE72937D7EE0053AE52 /* DIDFuncionalitiesView.swift */, + ); + path = DID; + sourceTree = ""; + }; + EEE61FEB2937DCBE0053AE52 /* Frameworks */ = { + isa = PBXGroup; + children = ( + ); + name = Frameworks; + sourceTree = ""; + }; + EEE620112937F1C30053AE52 /* Helper */ = { + isa = PBXGroup; + children = ( + EEE620122937F1D40053AE52 /* PrintObjects.swift */, + ); + path = Helper; + sourceTree = ""; + }; + EEE620142937F2C80053AE52 /* SigningVerification */ = { + isa = PBXGroup; + children = ( + EEE620152937F3110053AE52 /* SigningVerificationViewModel.swift */, + EEE620172937F6870053AE52 /* SigningVerificationView.swift */, + ); + path = SigningVerification; + sourceTree = ""; + }; + EEE6202C2937FD4B0053AE52 /* AuthenticateWallet */ = { + isa = PBXGroup; + children = ( + EEE6202D2937FDE50053AE52 /* AuthenticateWalletView.swift */, + EEE6202E2937FDE50053AE52 /* AuthenticateWalletViewModel.swift */, + ); + path = AuthenticateWallet; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + EEE61FB52937CA280053AE52 /* AtalaPrismWalletDemo */ = { + isa = PBXNativeTarget; + buildConfigurationList = EEE61FC42937CA2A0053AE52 /* Build configuration list for PBXNativeTarget "AtalaPrismWalletDemo" */; + buildPhases = ( + EEE61FB22937CA280053AE52 /* Sources */, + EEE61FB32937CA280053AE52 /* Frameworks */, + EEE61FB42937CA280053AE52 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = AtalaPrismWalletDemo; + packageProductDependencies = ( + EE38134F2938D5B100A3A710 /* Apollo */, + EE3813512938D5B100A3A710 /* Authenticate */, + EE3813532938D5B100A3A710 /* Builders */, + EE3813552938D5B100A3A710 /* Castor */, + EE3813572938D5B100A3A710 /* Domain */, + EE3813592938D5B100A3A710 /* Mercury */, + EE38135B2938D5B100A3A710 /* Pluto */, + EE38135D2938D5B100A3A710 /* Pollux */, + EE38135F2938D5B100A3A710 /* PrismAgent */, + ); + productName = AtalaPrismWalletDemo; + productReference = EEE61FB62937CA280053AE52 /* AtalaPrismWalletDemo.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + EEE61FAE2937CA280053AE52 /* Project object */ = { + isa = PBXProject; + attributes = { + BuildIndependentTargetsInParallel = 1; + LastSwiftUpdateCheck = 1400; + LastUpgradeCheck = 1400; + TargetAttributes = { + EEE61FB52937CA280053AE52 = { + CreatedOnToolsVersion = 14.0; + }; + }; + }; + buildConfigurationList = EEE61FB12937CA280053AE52 /* Build configuration list for PBXProject "AtalaPrismWalletDemo" */; + compatibilityVersion = "Xcode 14.0"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = EEE61FAD2937CA280053AE52; + packageReferences = ( + ); + productRefGroup = EEE61FB72937CA280053AE52 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + EEE61FB52937CA280053AE52 /* AtalaPrismWalletDemo */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + EEE61FB42937CA280053AE52 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + EEE61FC12937CA2A0053AE52 /* Preview Assets.xcassets in Resources */, + EEE61FBE2937CA2A0053AE52 /* Assets.xcassets in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + EEE61FB22937CA280053AE52 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + EEE620132937F1D40053AE52 /* PrintObjects.swift in Sources */, + EEE620302937FDE50053AE52 /* AuthenticateWalletViewModel.swift in Sources */, + EEE61FE02937CEAA0053AE52 /* SeedViewModel.swift in Sources */, + EEE61FE82937D7EE0053AE52 /* DIDFuncionalitiesView.swift in Sources */, + EEE61FBC2937CA280053AE52 /* FuncionalitiesList.swift in Sources */, + EEE61FDD2937CD7A0053AE52 /* SeedFuncionalitiesView.swift in Sources */, + EEE61FE42937D5560053AE52 /* DIDFuncionalitiesViewModel.swift in Sources */, + EEE6202F2937FDE50053AE52 /* AuthenticateWalletView.swift in Sources */, + EEE620182937F6870053AE52 /* SigningVerificationView.swift in Sources */, + EEE61FBA2937CA280053AE52 /* AtalaPrismWalletDemoApp.swift in Sources */, + EEE620162937F3110053AE52 /* SigningVerificationViewModel.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + EEE61FC22937CA2A0053AE52 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + 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; + GCC_C_LANGUAGE_STANDARD = gnu11; + 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 = 16.0; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + EEE61FC32937CA2A0053AE52 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + 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; + GCC_C_LANGUAGE_STANDARD = gnu11; + 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 = 16.0; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + SDKROOT = iphoneos; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + EEE61FC52937CA2A0053AE52 /* 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 = "\"AtalaPrismWalletDemo/Preview Content\""; + DEVELOPMENT_TEAM = 89TW38X994; + ENABLE_PREVIEWS = YES; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_FILE = AtalaPrismWalletDemo/Info.plist; + 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 = io.atala.prism.demo.wallet.AtalaPrismWalletDemo; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + EEE61FC62937CA2A0053AE52 /* 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 = "\"AtalaPrismWalletDemo/Preview Content\""; + DEVELOPMENT_TEAM = 89TW38X994; + ENABLE_PREVIEWS = YES; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_FILE = AtalaPrismWalletDemo/Info.plist; + 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 = io.atala.prism.demo.wallet.AtalaPrismWalletDemo; + 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 */ + EEE61FB12937CA280053AE52 /* Build configuration list for PBXProject "AtalaPrismWalletDemo" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + EEE61FC22937CA2A0053AE52 /* Debug */, + EEE61FC32937CA2A0053AE52 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + EEE61FC42937CA2A0053AE52 /* Build configuration list for PBXNativeTarget "AtalaPrismWalletDemo" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + EEE61FC52937CA2A0053AE52 /* Debug */, + EEE61FC62937CA2A0053AE52 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + +/* Begin XCSwiftPackageProductDependency section */ + EE38134F2938D5B100A3A710 /* Apollo */ = { + isa = XCSwiftPackageProductDependency; + productName = Apollo; + }; + EE3813512938D5B100A3A710 /* Authenticate */ = { + isa = XCSwiftPackageProductDependency; + productName = Authenticate; + }; + EE3813532938D5B100A3A710 /* Builders */ = { + isa = XCSwiftPackageProductDependency; + productName = Builders; + }; + EE3813552938D5B100A3A710 /* Castor */ = { + isa = XCSwiftPackageProductDependency; + productName = Castor; + }; + EE3813572938D5B100A3A710 /* Domain */ = { + isa = XCSwiftPackageProductDependency; + productName = Domain; + }; + EE3813592938D5B100A3A710 /* Mercury */ = { + isa = XCSwiftPackageProductDependency; + productName = Mercury; + }; + EE38135B2938D5B100A3A710 /* Pluto */ = { + isa = XCSwiftPackageProductDependency; + productName = Pluto; + }; + EE38135D2938D5B100A3A710 /* Pollux */ = { + isa = XCSwiftPackageProductDependency; + productName = Pollux; + }; + EE38135F2938D5B100A3A710 /* PrismAgent */ = { + isa = XCSwiftPackageProductDependency; + productName = PrismAgent; + }; +/* End XCSwiftPackageProductDependency section */ + }; + rootObject = EEE61FAE2937CA280053AE52 /* Project object */; +} diff --git a/Sample/AtalaPrismWalletDemo/AtalaPrismWalletDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Sample/AtalaPrismWalletDemo/AtalaPrismWalletDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 00000000..919434a6 --- /dev/null +++ b/Sample/AtalaPrismWalletDemo/AtalaPrismWalletDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Sample/AtalaPrismWalletDemo/AtalaPrismWalletDemo.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/Sample/AtalaPrismWalletDemo/AtalaPrismWalletDemo.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 00000000..18d98100 --- /dev/null +++ b/Sample/AtalaPrismWalletDemo/AtalaPrismWalletDemo.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/Sample/AtalaPrismWalletDemo/AtalaPrismWalletDemo/Assets.xcassets/AccentColor.colorset/Contents.json b/Sample/AtalaPrismWalletDemo/AtalaPrismWalletDemo/Assets.xcassets/AccentColor.colorset/Contents.json new file mode 100644 index 00000000..eb878970 --- /dev/null +++ b/Sample/AtalaPrismWalletDemo/AtalaPrismWalletDemo/Assets.xcassets/AccentColor.colorset/Contents.json @@ -0,0 +1,11 @@ +{ + "colors" : [ + { + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Sample/AtalaPrismWalletDemo/AtalaPrismWalletDemo/Assets.xcassets/AppIcon.appiconset/Contents.json b/Sample/AtalaPrismWalletDemo/AtalaPrismWalletDemo/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 00000000..13613e3e --- /dev/null +++ b/Sample/AtalaPrismWalletDemo/AtalaPrismWalletDemo/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/Sample/AtalaPrismWalletDemo/AtalaPrismWalletDemo/Assets.xcassets/Contents.json b/Sample/AtalaPrismWalletDemo/AtalaPrismWalletDemo/Assets.xcassets/Contents.json new file mode 100644 index 00000000..73c00596 --- /dev/null +++ b/Sample/AtalaPrismWalletDemo/AtalaPrismWalletDemo/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Sample/AtalaPrismWalletDemo/AtalaPrismWalletDemo/AtalaPrismWalletDemoApp.swift b/Sample/AtalaPrismWalletDemo/AtalaPrismWalletDemo/AtalaPrismWalletDemoApp.swift new file mode 100644 index 00000000..6bbef8ba --- /dev/null +++ b/Sample/AtalaPrismWalletDemo/AtalaPrismWalletDemo/AtalaPrismWalletDemoApp.swift @@ -0,0 +1,10 @@ +import SwiftUI + +@main +struct AtalaPrismWalletDemoApp: App { + var body: some Scene { + WindowGroup { + FuncionalitiesList() + } + } +} diff --git a/Sample/AtalaPrismWalletDemo/AtalaPrismWalletDemo/FuncionalitiesList.swift b/Sample/AtalaPrismWalletDemo/AtalaPrismWalletDemo/FuncionalitiesList.swift new file mode 100644 index 00000000..387374fd --- /dev/null +++ b/Sample/AtalaPrismWalletDemo/AtalaPrismWalletDemo/FuncionalitiesList.swift @@ -0,0 +1,20 @@ +import SwiftUI + +struct FuncionalitiesList: View { + var body: some View { + NavigationView { + List { + NavigationLink("Seed Funcionalities", destination: SeedFuncionalitiesView(model: .init())) + NavigationLink("DID Funcionalities", destination: DIDFuncionalitiesView(model: .init())) + NavigationLink("Signing/Verification Funcionalities", destination: SigningVerificationView(model: .init())) + NavigationLink("Authenticate Wallet Side", destination: AuthenticateWalletView(viewModel: AuthenticateWalletViewModelImpl())) + } + } + } +} + +struct ContentView_Previews: PreviewProvider { + static var previews: some View { + FuncionalitiesList() + } +} diff --git a/Sample/AtalaPrismWalletDemo/AtalaPrismWalletDemo/Helper/PrintObjects.swift b/Sample/AtalaPrismWalletDemo/AtalaPrismWalletDemo/Helper/PrintObjects.swift new file mode 100644 index 00000000..e6a9f04f --- /dev/null +++ b/Sample/AtalaPrismWalletDemo/AtalaPrismWalletDemo/Helper/PrintObjects.swift @@ -0,0 +1,27 @@ +import Foundation + +public protocol ReflectedStringConvertible : CustomStringConvertible { } + +extension ReflectedStringConvertible { + public var description: String { + let mirror = Mirror(reflecting: self) + + var str = "\(mirror.subjectType)(" + var first = true + for (label, value) in mirror.children { + if let label = label { + if first { + first = false + } else { + str += ", " + } + str += label + str += ": " + str += "\(value)" + } + } + str += ")" + + return str + } +} diff --git a/Sample/AtalaPrismWalletDemo/AtalaPrismWalletDemo/Info.plist b/Sample/AtalaPrismWalletDemo/AtalaPrismWalletDemo/Info.plist new file mode 100644 index 00000000..db53a6f5 --- /dev/null +++ b/Sample/AtalaPrismWalletDemo/AtalaPrismWalletDemo/Info.plist @@ -0,0 +1,19 @@ + + + + + CFBundleURLTypes + + + CFBundleTypeRole + Editor + CFBundleURLName + challenge + CFBundleURLSchemes + + walletX + + + + + diff --git a/Sample/AtalaPrismWalletDemo/AtalaPrismWalletDemo/Modules/AuthenticateWallet/AuthenticateWalletView.swift b/Sample/AtalaPrismWalletDemo/AtalaPrismWalletDemo/Modules/AuthenticateWallet/AuthenticateWalletView.swift new file mode 100644 index 00000000..4aa00380 --- /dev/null +++ b/Sample/AtalaPrismWalletDemo/AtalaPrismWalletDemo/Modules/AuthenticateWallet/AuthenticateWalletView.swift @@ -0,0 +1,146 @@ +import SwiftUI + +protocol AuthenticateWalletViewModel: ObservableObject { + var did: String { get } + var challenge: Challenge? { get } + var error: Error? { get } + + func createPrismDID() + func createPeerDID() + func didReceiveChallenge(url: URL) + func acceptChallenge() async + func refuseChallenge() async + func reset() +} + +struct Challenge { + let challenger: String + let challenge: String + let challengeAccepted: Bool +} + +struct AuthenticateWalletView: View { + + @StateObject var viewModel: ViewModel + + var body: some View { + VStack(spacing: 30) { + Image("img_logo_horizontal") + .resizable() + .scaledToFit() + HStack { + if viewModel.did.isEmpty { + Text("Please create a DID") + .font(.title) + } else { + Text("\(viewModel.did)") + .textSelection(.enabled) + .font(.system(.footnote, weight: .ultraLight)) + } + } + HStack { + Button("Create Prism DID") { + viewModel.createPrismDID() + } + .padding() + .frame(maxWidth: .infinity) + .background(Color.red) + .tint(.white) + .clipShape(Capsule(style: .continuous)) + + Button("Create Peer DID") { + viewModel.createPeerDID() + } + .padding() + .frame(maxWidth: .infinity) + .background(Color.red) + .tint(.white) + .clipShape(Capsule(style: .continuous)) + } + Button("Reset") { + viewModel.reset() + } + .padding() + .frame(maxWidth: .infinity) + .background(Color.red) + .tint(.white) + .clipShape(Capsule(style: .continuous)) + if let challenge = viewModel.challenge { + VStack { + VStack(alignment: .center, spacing: 10) { + Text("You received an authentication challenge from:") + Text("\(challenge.challenger)") + .font(.system(size: 22, weight: .thin)) + } + HStack { + Button("Accept Challenge") { + Task { + await viewModel.acceptChallenge() + } + + } + .padding() + .frame(maxWidth: .infinity) + .background(Color.red) + .tint(.white) + .clipShape(Capsule(style: .continuous)) + Button("Refuse Challenge") { + Task { + await viewModel.refuseChallenge() + } + } + .padding() + .frame(maxWidth: .infinity) + .background(Color.red) + .tint(.white) + .clipShape(Capsule(style: .continuous)) + } + } + } + Spacer() + } + .padding() + .onOpenURL { + viewModel.didReceiveChallenge(url: $0) + } + } +} + +struct AuthenticateWalletView_Previews: PreviewProvider { + static var previews: some View { + AuthenticateWalletView(viewModel: ViewModel()) + } +} + +private class ViewModel: AuthenticateWalletViewModel { + var did: String = "" + var challenge: Challenge? = .init(challenger: "challenger", challenge: "challenge", challengeAccepted: false) + var error: Error? + func createPrismDID() { + did = "did:prism:1234" + } + + func createPeerDID() { + did = "did:peer:1234" + } + + func didReceiveChallenge(url: URL) {} + + func acceptChallenge() async { + guard + let aux = challenge, + !aux.challengeAccepted + else { return } + challenge = .init( + challenger: aux.challenger, + challenge: aux.challenge, + challengeAccepted: true + ) + } + + func refuseChallenge() async { + challenge = nil + } + + func reset() {} +} diff --git a/Sample/AtalaPrismWalletDemo/AtalaPrismWalletDemo/Modules/AuthenticateWallet/AuthenticateWalletViewModel.swift b/Sample/AtalaPrismWalletDemo/AtalaPrismWalletDemo/Modules/AuthenticateWallet/AuthenticateWalletViewModel.swift new file mode 100644 index 00000000..f7fe61c1 --- /dev/null +++ b/Sample/AtalaPrismWalletDemo/AtalaPrismWalletDemo/Modules/AuthenticateWallet/AuthenticateWalletViewModel.swift @@ -0,0 +1,130 @@ +import Foundation +import Domain +import Builders +import Authenticate +import UIKit + +class AuthenticateWalletViewModelImpl: AuthenticateWalletViewModel { + + private let seedKey = "Seed" + private let privateKeyKey = "PrivateKey" + private let privateKeyCurveKey = "PrivateKeyCurve" + private let didKey = "DID" + private let storage = UserDefaults.standard + private let castor: Castor + private let apollo: Apollo + private let authenticate: AuthenticateChallenged + private var challengeObject: ChallengeObject? { + didSet { + challenge = challengeObject.map { + Challenge( + challenger: $0.challengerName, + challenge: $0.challenge, + challengeAccepted: false + ) + } + } + } + + @Published var did: String { + didSet { + storage.set(did, forKey: didKey) + } + } + @Published var challenge: Challenge? = nil + @Published var error: Error? + + init(did: String = "", challenge: Challenge? = nil) { + if did.isEmpty { + self.did = storage.string(forKey: didKey) ?? "" + } else { + self.did = did + } + self.challenge = challenge + self.apollo = ApolloBuilder().build() + self.castor = CastorBuilder(apollo: apollo).build() + self.authenticate = AuthenticateChallenged( + castor: castor, + apollo: apollo, + scheme: .init(scheme: "walletX", host: "challenge"), + deepLinkPusher: UIApplication.shared + ) + } + + func createPrismDID() { + // Wallet logic side + let seed = createOrGetSeed() + let keyPair = apollo.createKeyPair(seed: seed, index: 0) + setPrivateKey(privateKey: keyPair.privateKey) + + // Integration with Atala Prism side + do { + did = try authenticate.createPrismDIDForAuthenticate(publicKey: keyPair.publicKey).string + } catch { + self.error = error + } + } + + func createPeerDID() { + // Wallet logic side + } + + func didReceiveChallenge(url: URL) { + do { + self.challengeObject = try authenticate.receivedPrismChallenge(url: url) + } catch { + print(error.localizedDescription) + } + } + + func acceptChallenge() async { + do { + guard let challengeObject, let privateKey = getPrivateKey() else { return } + let submitObject = try authenticate.acceptChallenge(challenge: challengeObject, privateKey: privateKey) + try await authenticate.submitChallengeAnswer(submitedChallenge: submitObject) + } catch { + print(error.localizedDescription) + } + } + + func refuseChallenge() { + challenge = nil + } + + func reset() { + did = "" + storage.set(nil, forKey: seedKey) + storage.set(nil, forKey: privateKeyKey) + storage.set(nil, forKey: privateKeyCurveKey) + + } + + private func getPrivateKey() -> PrivateKey? { + guard + let data = storage.data(forKey: privateKeyKey), + let curve = storage.string(forKey: privateKeyCurveKey) + else { return nil } + + return PrivateKey(curve: curve, value: data) + } + + private func setPrivateKey(privateKey: PrivateKey) { + storage.set(privateKey.value, forKey: privateKeyKey) + storage.set(privateKey.curve, forKey: privateKeyCurveKey) + } + + private func createOrGetSeed() -> Seed { + guard let seed = storage.data(forKey: seedKey) else { + let (_, seed) = apollo.createRandomSeed() + storage.set(seed.value, forKey: seedKey) + return seed + } + return Seed(value: seed) + } +} + +extension UIApplication: DeepLinkPusher { + public func openDeepLink(url: URL) async throws -> Bool { + await self.open(url) + } +} diff --git a/Sample/AtalaPrismWalletDemo/AtalaPrismWalletDemo/Modules/DID/DIDFuncionalitiesView.swift b/Sample/AtalaPrismWalletDemo/AtalaPrismWalletDemo/Modules/DID/DIDFuncionalitiesView.swift new file mode 100644 index 00000000..28821d7d --- /dev/null +++ b/Sample/AtalaPrismWalletDemo/AtalaPrismWalletDemo/Modules/DID/DIDFuncionalitiesView.swift @@ -0,0 +1,47 @@ +import SwiftUI + +struct DIDFuncionalitiesView: View { + @StateObject var model: DIDFuncionalitiesViewModel + var body: some View { + ScrollView { + VStack(spacing: 12) { + Button("Create DID") { + Task { + await self.model.createPrismDID() + } + } + .padding() + .overlay(Capsule() + .stroke( + Color.black, + lineWidth: 2 + )) + if let str = model.createdDID?.string { + Text(str) + Button("Resolve DID") { + Task { + await self.model.resolveDID() + } + } + .padding() + .overlay(Capsule() + .stroke( + Color.black, + lineWidth: 2 + )) + if let document = model.resolvedDID { + Text(document.description) + } + } + Spacer() + } + .padding() + } + } +} + +struct DIDFuncionalitiesView_Previews: PreviewProvider { + static var previews: some View { + DIDFuncionalitiesView(model: .init()) + } +} diff --git a/Sample/AtalaPrismWalletDemo/AtalaPrismWalletDemo/Modules/DID/DIDFuncionalitiesViewModel.swift b/Sample/AtalaPrismWalletDemo/AtalaPrismWalletDemo/Modules/DID/DIDFuncionalitiesViewModel.swift new file mode 100644 index 00000000..bc64b2be --- /dev/null +++ b/Sample/AtalaPrismWalletDemo/AtalaPrismWalletDemo/Modules/DID/DIDFuncionalitiesViewModel.swift @@ -0,0 +1,52 @@ +import Builders +import Domain +import Foundation +import PrismAgent + +final class DIDFuncionalitiesViewModel: ObservableObject { + private let castor: Castor + private let agent: PrismAgent + + init() { + self.castor = CastorBuilder( + apollo: ApolloBuilder().build() + ).build() + self.agent = PrismAgent() + } + + @Published var createdDID: DID? + @Published var resolvedDID: DIDDocument? + + func createPrismDID() async { + // Creates new PRISM DID + let did = try? await agent.createNewPrismDID( + // Add this if you want to provide a IndexPath + // keyPathIndex: <#T##Int?#> + // Add this if you want to provide an alias for this DID + // alias: <#T##String?#> + // Add any services available in the DID + services: [ .init( + id: "DemoID", + type: ["DemoType"], + serviceEndpoint: .init(uri: "DemoServiceEndpoint") + ) + ]) + + await MainActor.run { + self.createdDID = did + } + } + + func resolveDID() async { + guard let did = createdDID else { return } + + // Resolves a DID and returns a DIDDocument + let document = try? await castor.resolveDID(did: did) + + await MainActor.run { + self.resolvedDID = document + } + } +} + +extension DIDDocument: ReflectedStringConvertible {} diff --git a/Sample/AtalaPrismWalletDemo/AtalaPrismWalletDemo/Modules/Seed/SeedFuncionalitiesView.swift b/Sample/AtalaPrismWalletDemo/AtalaPrismWalletDemo/Modules/Seed/SeedFuncionalitiesView.swift new file mode 100644 index 00000000..1d11978d --- /dev/null +++ b/Sample/AtalaPrismWalletDemo/AtalaPrismWalletDemo/Modules/Seed/SeedFuncionalitiesView.swift @@ -0,0 +1,46 @@ +import SwiftUI + +struct SeedFuncionalitiesView: View { + @StateObject var model: SeedViewModel + + var body: some View { + VStack(spacing: 12) { + Text("Mnemonics:") + .bold() + Text(model.randomMnemonics.joined(separator: ", ")) + if + let seed = model.createdSeed + { + Text("Seed created from mnemonics") + .bold() + Text(seed.value.base64EncodedString()) + } + HStack(alignment: .center, spacing: 16) { + Button("Refresh mnemonics") { + self.model.refreshMnemonics() + } + .padding() + .overlay(Capsule() + .stroke( + Color.black, + lineWidth: 2 + )) + Spacer() + Button("Create Seed") { + self.model.createSeed() + } + .padding() + .overlay(Capsule() + .stroke(Color.black, lineWidth: 2)) + } + Spacer() + } + .padding() + } +} + +struct SeedView_Previews: PreviewProvider { + static var previews: some View { + SeedFuncionalitiesView(model: SeedViewModel()) + } +} diff --git a/Sample/AtalaPrismWalletDemo/AtalaPrismWalletDemo/Modules/Seed/SeedViewModel.swift b/Sample/AtalaPrismWalletDemo/AtalaPrismWalletDemo/Modules/Seed/SeedViewModel.swift new file mode 100644 index 00000000..022adcc4 --- /dev/null +++ b/Sample/AtalaPrismWalletDemo/AtalaPrismWalletDemo/Modules/Seed/SeedViewModel.swift @@ -0,0 +1,27 @@ +import Builders +import Domain +import Foundation + +final class SeedViewModel: ObservableObject { + + private let apollo: Apollo + @Published var createdSeed: Seed? + @Published var randomMnemonics: [String] + + init() { + self.apollo = ApolloBuilder().build() + self.randomMnemonics = apollo.createRandomMnemonics() + } + + func createSeed() { + // Create a seed given mnemonics and optionally passphrase + createdSeed = try? apollo.createSeed(mnemonics: randomMnemonics, passphrase: "") + } + + func refreshMnemonics() { + createdSeed = nil + + // Rendomises valid mnemonics + randomMnemonics = apollo.createRandomMnemonics() + } +} diff --git a/Sample/AtalaPrismWalletDemo/AtalaPrismWalletDemo/Modules/SigningVerification/SigningVerificationView.swift b/Sample/AtalaPrismWalletDemo/AtalaPrismWalletDemo/Modules/SigningVerification/SigningVerificationView.swift new file mode 100644 index 00000000..04e0b46b --- /dev/null +++ b/Sample/AtalaPrismWalletDemo/AtalaPrismWalletDemo/Modules/SigningVerification/SigningVerificationView.swift @@ -0,0 +1,75 @@ +// +// SigningVerificationView.swift +// AtalaPrismWalletDemo +// +// Created by Goncalo Frade IOHK on 30/11/2022. +// + +import SwiftUI + +struct SigningVerificationView: View { + @StateObject var model: SigningVerificationViewModel + var body: some View { + ScrollView { + VStack(spacing: 12) { + Button("Create DID") { + Task { + await self.model.createPrismDID() + } + } + .padding() + .overlay(Capsule() + .stroke( + Color.black, + lineWidth: 2 + )) + if let str = model.createdDID?.string { + Text(str) + Text("Write a message:") + .bold() + .padding(.top) + TextField("Message", text: $model.message) + .textFieldStyle(.roundedBorder) + .padding() + Button("Sign message") { + Task { + await self.model.signMessageWithDID() + } + } + .padding() + .overlay(Capsule() + .stroke( + Color.black, + lineWidth: 2 + )) + if let str = model.signedMessage?.description { + Text(str) + Button("Verify message") { + Task { + await self.model.verifyMessage() + } + } + .padding() + .overlay(Capsule() + .stroke( + Color.black, + lineWidth: 2 + )) + if let verification = model.verifiedMessage { + Text("Verification " + (verification ? "Success" : "Failed")) + .foregroundColor(verification ? .green : .red) + } + } + } + Spacer() + } + .padding() + } + } +} + +struct SigningVerificationView_Previews: PreviewProvider { + static var previews: some View { + SigningVerificationView(model: SigningVerificationViewModel()) + } +} diff --git a/Sample/AtalaPrismWalletDemo/AtalaPrismWalletDemo/Modules/SigningVerification/SigningVerificationViewModel.swift b/Sample/AtalaPrismWalletDemo/AtalaPrismWalletDemo/Modules/SigningVerification/SigningVerificationViewModel.swift new file mode 100644 index 00000000..6afb8acf --- /dev/null +++ b/Sample/AtalaPrismWalletDemo/AtalaPrismWalletDemo/Modules/SigningVerification/SigningVerificationViewModel.swift @@ -0,0 +1,71 @@ +import Builders +import Domain +import Foundation +import PrismAgent + +final class SigningVerificationViewModel: ObservableObject { + private let castor: Castor + private let agent: PrismAgent + + init() { + self.castor = CastorBuilder( + apollo: ApolloBuilder().build() + ).build() + self.agent = PrismAgent() + } + + @Published var createdDID: DID? + @Published var message: String = "" + @Published var signedMessage: Signature? + @Published var verifiedMessage: Bool? + + func createPrismDID() async { + + // Creates new PRISM DID + let did = try? await agent.createNewPrismDID( + // Add this if you want to provide a IndexPath + // keyPathIndex: <#T##Int?#> + // Add this if you want to provide an alias for this DID + // alias: <#T##String?#> + // Add any services available in the DID + services: [ .init( + id: "DemoID", + type: ["DemoType"], + serviceEndpoint: .init(uri: "DemoServiceEndpoint") + ) + ]) + await MainActor.run { + self.createdDID = did + self.verifiedMessage = nil + } + } + + func signMessageWithDID() async { + guard + let did = createdDID, + let messageData = message.data(using: .utf8) + else { return } + + // Signs with a valid DID that was created by the agent + let signature = try? await agent.signWith(did: did, message: messageData) + await MainActor.run { + self.signedMessage = signature + } + } + + func verifyMessage() async { + guard + let did = createdDID, + let messageData = message.data(using: .utf8), + let signedMessage + else { return } + + // Verifies a message signature given a DID + let verifiedMessage = try? await castor.verifySignature(did: did, challenge: messageData, signature: signedMessage.value) + await MainActor.run { + self.verifiedMessage = verifiedMessage + } + } +} + +extension Signature: ReflectedStringConvertible {} diff --git a/Sample/AtalaPrismWalletDemo/AtalaPrismWalletDemo/Preview Content/Preview Assets.xcassets/Contents.json b/Sample/AtalaPrismWalletDemo/AtalaPrismWalletDemo/Preview Content/Preview Assets.xcassets/Contents.json new file mode 100644 index 00000000..73c00596 --- /dev/null +++ b/Sample/AtalaPrismWalletDemo/AtalaPrismWalletDemo/Preview Content/Preview Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +}