From 85acbf3b3fc30b2d0119afa8e816d2cc768d6dde Mon Sep 17 00:00:00 2001 From: Artur Guseinov Date: Thu, 24 Nov 2022 14:21:13 +0500 Subject: [PATCH 01/30] Web3 package removed --- Package.swift | 6 ++---- WalletConnectSwiftV2.podspec | 1 - 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/Package.swift b/Package.swift index 5ea3fe03c..17c119b64 100644 --- a/Package.swift +++ b/Package.swift @@ -32,9 +32,7 @@ let package = Package( name: "WalletConnectNetworking", targets: ["WalletConnectNetworking"]) ], - dependencies: [ - .package(url: "https://github.com/WalletConnect/Web3.swift", .exact("1.0.0")) - ], + dependencies: [], targets: [ .target( name: "WalletConnectSign", @@ -46,7 +44,7 @@ let package = Package( path: "Sources/Chat"), .target( name: "Auth", - dependencies: ["WalletConnectPairing", .product(name: "Web3", package: "Web3.swift")], + dependencies: ["WalletConnectPairing"], path: "Sources/Auth"), .target( name: "WalletConnectPush", diff --git a/WalletConnectSwiftV2.podspec b/WalletConnectSwiftV2.podspec index 256509ece..881bfe09c 100644 --- a/WalletConnectSwiftV2.podspec +++ b/WalletConnectSwiftV2.podspec @@ -82,7 +82,6 @@ Pod::Spec.new do |spec| spec.subspec 'WalletConnectAuth' do |ss| ss.source_files = 'Sources/Auth/**/*' ss.dependency 'WalletConnectSwiftV2/WalletConnectPairing' - ss.dependency "WalletConnectWeb3", "1.0.1" end spec.subspec 'WalletConnectChat' do |ss| From 0fb33278512594e36f83930e33e57c2fb0c2d1e6 Mon Sep 17 00:00:00 2001 From: Artur Guseinov Date: Thu, 24 Nov 2022 15:41:56 +0500 Subject: [PATCH 02/30] SignerFactory --- Sources/Auth/Auth.swift | 11 +++- Sources/Auth/AuthClientFactory.swift | 62 +++++++++++++++---- Sources/Auth/AuthConfig.swift | 1 + .../Signer/EIP191/EIP191Verifier.swift | 36 ----------- .../EIP1271/EIP1271Verifier.swift | 0 .../{ => Ethereum}/EIP1271/RPCService.swift | 0 .../EIP1271/ValidSignatureMethod.swift | 0 .../Ethereum/EIP191/EIP191Verifier.swift | 28 +++++++++ .../Signer/Ethereum/EthereumPublicKey.swift | 13 ++++ .../Signer/Ethereum/EthereumSignature.swift | 27 ++++++++ .../Signer/Ethereum/EthereumSigner.swift | 6 ++ .../Auth/Services/Signer/MessageSigner.swift | 7 +-- .../Signer/MessageSignerFactory.swift | 14 +++-- Sources/Auth/Services/Signer/Signer.swift | 19 ------ .../Auth/Services/Signer/SignerFactory.swift | 5 ++ 15 files changed, 150 insertions(+), 79 deletions(-) delete mode 100644 Sources/Auth/Services/Signer/EIP191/EIP191Verifier.swift rename Sources/Auth/Services/Signer/{ => Ethereum}/EIP1271/EIP1271Verifier.swift (100%) rename Sources/Auth/Services/Signer/{ => Ethereum}/EIP1271/RPCService.swift (100%) rename Sources/Auth/Services/Signer/{ => Ethereum}/EIP1271/ValidSignatureMethod.swift (100%) create mode 100644 Sources/Auth/Services/Signer/Ethereum/EIP191/EIP191Verifier.swift create mode 100644 Sources/Auth/Services/Signer/Ethereum/EthereumPublicKey.swift create mode 100644 Sources/Auth/Services/Signer/Ethereum/EthereumSignature.swift create mode 100644 Sources/Auth/Services/Signer/Ethereum/EthereumSigner.swift delete mode 100644 Sources/Auth/Services/Signer/Signer.swift create mode 100644 Sources/Auth/Services/Signer/SignerFactory.swift diff --git a/Sources/Auth/Auth.swift b/Sources/Auth/Auth.swift index 52bda894a..a4986ea59 100644 --- a/Sources/Auth/Auth.swift +++ b/Sources/Auth/Auth.swift @@ -16,10 +16,14 @@ public class Auth { /// Auth client instance public static var instance: AuthClient = { + guard let config = Auth.config else { + fatalError("Error - you must call Auth.configure(_:) before accessing the shared instance.") + } return AuthClientFactory.create( metadata: Pair.metadata, - account: config?.account, + account: config.account, projectId: Networking.projectId, + signerFactory: config.signerFactory, networkingClient: Networking.interactor, pairingRegisterer: Pair.registerer ) @@ -32,7 +36,8 @@ public class Auth { /// Auth instance wallet config method /// - Parameters: /// - account: account that wallet will be authenticating with. - static public func configure(account: Account) { - Auth.config = Auth.Config(account: account) + /// - signerFactory: Multichain signers factory + static public func configure(account: Account, signerFactory: SignerFactory) { + Auth.config = Auth.Config(account: account, signerFactory: signerFactory) } } diff --git a/Sources/Auth/AuthClientFactory.swift b/Sources/Auth/AuthClientFactory.swift index 89816a70f..9a84c4f17 100644 --- a/Sources/Auth/AuthClientFactory.swift +++ b/Sources/Auth/AuthClientFactory.swift @@ -2,33 +2,69 @@ import Foundation public struct AuthClientFactory { - public static func create(metadata: AppMetadata, account: Account?, projectId: String, networkingClient: NetworkingInteractor, pairingRegisterer: PairingRegisterer) -> AuthClient { + public static func create( + metadata: AppMetadata, + account: Account?, + projectId: String, + signerFactory: SignerFactory, + networkingClient: NetworkingInteractor, + pairingRegisterer: PairingRegisterer + ) -> AuthClient { + let logger = ConsoleLogger(loggingLevel: .off) let keyValueStorage = UserDefaults.standard let keychainStorage = KeychainStorage(serviceIdentifier: "com.walletconnect.sdk") - return AuthClientFactory.create(metadata: metadata, account: account, projectId: projectId, logger: logger, keyValueStorage: keyValueStorage, keychainStorage: keychainStorage, networkingClient: networkingClient, pairingRegisterer: pairingRegisterer, iatProvider: DefaultIATProvider()) + let iatProvider = DefaultIATProvider() + + return AuthClientFactory.create( + metadata: metadata, + account: account, + projectId: projectId, + signerFactory: signerFactory, + logger: logger, + keyValueStorage: keyValueStorage, + keychainStorage: keychainStorage, + networkingClient: networkingClient, + pairingRegisterer: pairingRegisterer, + iatProvider: iatProvider + ) } - static func create(metadata: AppMetadata, account: Account?, projectId: String, logger: ConsoleLogging, keyValueStorage: KeyValueStorage, keychainStorage: KeychainStorageProtocol, networkingClient: NetworkingInteractor, pairingRegisterer: PairingRegisterer, iatProvider: IATProvider) -> AuthClient { + static func create( + metadata: AppMetadata, + account: Account?, + projectId: String, + signerFactory: SignerFactory, + logger: ConsoleLogging, + keyValueStorage: KeyValueStorage, + keychainStorage: KeychainStorageProtocol, + networkingClient: NetworkingInteractor, + pairingRegisterer: PairingRegisterer, + iatProvider: IATProvider + ) -> AuthClient { + let kms = KeyManagementService(keychain: keychainStorage) let history = RPCHistoryFactory.createForNetwork(keyValueStorage: keyValueStorage) let messageFormatter = SIWEMessageFormatter() let appRequestService = AppRequestService(networkingInteractor: networkingClient, kms: kms, appMetadata: metadata, logger: logger, iatProvader: iatProvider) - let messageSigner = MessageSignerFactory.create(projectId: projectId) + let messageSignerFactory = MessageSignerFactory(signerFactory: signerFactory) + let messageSigner = messageSignerFactory.create(projectId: projectId) let appRespondSubscriber = AppRespondSubscriber(networkingInteractor: networkingClient, logger: logger, rpcHistory: history, signatureVerifier: messageSigner, pairingRegisterer: pairingRegisterer, messageFormatter: messageFormatter) let walletErrorResponder = WalletErrorResponder(networkingInteractor: networkingClient, logger: logger, kms: kms, rpcHistory: history) let walletRequestSubscriber = WalletRequestSubscriber(networkingInteractor: networkingClient, logger: logger, kms: kms, messageFormatter: messageFormatter, address: account?.address, walletErrorResponder: walletErrorResponder, pairingRegisterer: pairingRegisterer) let walletRespondService = WalletRespondService(networkingInteractor: networkingClient, logger: logger, kms: kms, rpcHistory: history, walletErrorResponder: walletErrorResponder) let pendingRequestsProvider = PendingRequestsProvider(rpcHistory: history) - return AuthClient(appRequestService: appRequestService, - appRespondSubscriber: appRespondSubscriber, - walletRequestSubscriber: walletRequestSubscriber, - walletRespondService: walletRespondService, - account: account, - pendingRequestsProvider: pendingRequestsProvider, - logger: logger, - socketConnectionStatusPublisher: networkingClient.socketConnectionStatusPublisher, - pairingRegisterer: pairingRegisterer) + return AuthClient( + appRequestService: appRequestService, + appRespondSubscriber: appRespondSubscriber, + walletRequestSubscriber: walletRequestSubscriber, + walletRespondService: walletRespondService, + account: account, + pendingRequestsProvider: pendingRequestsProvider, + logger: logger, + socketConnectionStatusPublisher: networkingClient.socketConnectionStatusPublisher, + pairingRegisterer: pairingRegisterer + ) } } diff --git a/Sources/Auth/AuthConfig.swift b/Sources/Auth/AuthConfig.swift index 00a98faed..472d2b267 100644 --- a/Sources/Auth/AuthConfig.swift +++ b/Sources/Auth/AuthConfig.swift @@ -3,5 +3,6 @@ import Foundation extension Auth { struct Config { let account: Account? + let signerFactory: SignerFactory } } diff --git a/Sources/Auth/Services/Signer/EIP191/EIP191Verifier.swift b/Sources/Auth/Services/Signer/EIP191/EIP191Verifier.swift deleted file mode 100644 index 7622cae14..000000000 --- a/Sources/Auth/Services/Signer/EIP191/EIP191Verifier.swift +++ /dev/null @@ -1,36 +0,0 @@ -import Foundation -import Web3 - -actor EIP191Verifier { - - func verify(signature: Data, message: Data, address: String) async throws { - let sig = decompose(signature: signature) - let publicKey = try EthereumPublicKey.init( - message: message.bytes, - v: EthereumQuantity(quantity: BigUInt(sig.v)), - r: EthereumQuantity(sig.r), - s: EthereumQuantity(sig.s) - ) - try verifyPublicKey(publicKey, address: address) - } - - private func decompose(signature: Data) -> Signer.Signature { - let v = signature.bytes[signature.count-1] - let r = signature.bytes[0..<32] - let s = signature.bytes[32..<64] - return (UInt(v), [UInt8](r), [UInt8](s)) - } - - private func verifyPublicKey(_ publicKey: EthereumPublicKey, address: String) throws { - guard publicKey.address.hex(eip55: false) == address.lowercased() else { - throw Errors.invalidSignature - } - } -} - -extension EIP191Verifier { - - enum Errors: Error { - case invalidSignature - } -} diff --git a/Sources/Auth/Services/Signer/EIP1271/EIP1271Verifier.swift b/Sources/Auth/Services/Signer/Ethereum/EIP1271/EIP1271Verifier.swift similarity index 100% rename from Sources/Auth/Services/Signer/EIP1271/EIP1271Verifier.swift rename to Sources/Auth/Services/Signer/Ethereum/EIP1271/EIP1271Verifier.swift diff --git a/Sources/Auth/Services/Signer/EIP1271/RPCService.swift b/Sources/Auth/Services/Signer/Ethereum/EIP1271/RPCService.swift similarity index 100% rename from Sources/Auth/Services/Signer/EIP1271/RPCService.swift rename to Sources/Auth/Services/Signer/Ethereum/EIP1271/RPCService.swift diff --git a/Sources/Auth/Services/Signer/EIP1271/ValidSignatureMethod.swift b/Sources/Auth/Services/Signer/Ethereum/EIP1271/ValidSignatureMethod.swift similarity index 100% rename from Sources/Auth/Services/Signer/EIP1271/ValidSignatureMethod.swift rename to Sources/Auth/Services/Signer/Ethereum/EIP1271/ValidSignatureMethod.swift diff --git a/Sources/Auth/Services/Signer/Ethereum/EIP191/EIP191Verifier.swift b/Sources/Auth/Services/Signer/Ethereum/EIP191/EIP191Verifier.swift new file mode 100644 index 000000000..ea4a85677 --- /dev/null +++ b/Sources/Auth/Services/Signer/Ethereum/EIP191/EIP191Verifier.swift @@ -0,0 +1,28 @@ +import Foundation + +actor EIP191Verifier { + + let signer: EthereumSigner + + init(signer: EthereumSigner) { + self.signer = signer + } + + func verify(signature: Data, message: Data, address: String) async throws { + let sig = EthereumSignature(serialized: signature) + let publicKey = try signer.recover(signature: sig) + try verifyPublicKey(publicKey, address: address) + } + + private func verifyPublicKey(_ publicKey: EthereumPublicKey, address: String) throws { + guard publicKey.hex() == address.lowercased() else { + throw Errors.invalidSignature + } + } +} + +extension EIP191Verifier { + enum Errors: Error { + case invalidSignature + } +} diff --git a/Sources/Auth/Services/Signer/Ethereum/EthereumPublicKey.swift b/Sources/Auth/Services/Signer/Ethereum/EthereumPublicKey.swift new file mode 100644 index 000000000..a13518e76 --- /dev/null +++ b/Sources/Auth/Services/Signer/Ethereum/EthereumPublicKey.swift @@ -0,0 +1,13 @@ +import Foundation + +public struct EthereumPublicKey { + public let data: [UInt8] + + public init(data: [UInt8]) { + self.data = data + } + + public func hex() -> String { + return "0x" + data.toHexString() + } +} diff --git a/Sources/Auth/Services/Signer/Ethereum/EthereumSignature.swift b/Sources/Auth/Services/Signer/Ethereum/EthereumSignature.swift new file mode 100644 index 000000000..5625c491c --- /dev/null +++ b/Sources/Auth/Services/Signer/Ethereum/EthereumSignature.swift @@ -0,0 +1,27 @@ +import Foundation + +public struct EthereumSignature { + public let v: UInt8 + public let r: [UInt8] + public let s: [UInt8] + + public init(v: UInt8, r: [UInt8], s: [UInt8]) { + self.v = v + self.r = r + self.s = s + } + + public init(serialized: Data) { + v = UInt8(serialized.bytes[serialized.count-1]) + r = [UInt8](serialized.bytes[0..<32]) + s = [UInt8](serialized.bytes[32..<64]) + } + + public var serialized: Data { + return Data(r + s + [UInt8(v)]) + } + + public func hex() -> String { + return "0x" + serialized.toHexString() + } +} diff --git a/Sources/Auth/Services/Signer/Ethereum/EthereumSigner.swift b/Sources/Auth/Services/Signer/Ethereum/EthereumSigner.swift new file mode 100644 index 000000000..61608258b --- /dev/null +++ b/Sources/Auth/Services/Signer/Ethereum/EthereumSigner.swift @@ -0,0 +1,6 @@ +import Foundation + +public protocol EthereumSigner { + func sign(message: Data, with key: Data) throws -> EthereumSignature + func recover(signature: EthereumSignature) throws -> EthereumPublicKey +} diff --git a/Sources/Auth/Services/Signer/MessageSigner.swift b/Sources/Auth/Services/Signer/MessageSigner.swift index fd4ffffbb..a53ebea78 100644 --- a/Sources/Auth/Services/Signer/MessageSigner.swift +++ b/Sources/Auth/Services/Signer/MessageSigner.swift @@ -14,11 +14,11 @@ struct MessageSigner: MessageSignatureVerifying, MessageSigning { case utf8EncodingFailed } - private let signer: Signer + private let signer: EthereumSigner private let eip191Verifier: EIP191Verifier private let eip1271Verifier: EIP1271Verifier - init(signer: Signer, eip191Verifier: EIP191Verifier, eip1271Verifier: EIP1271Verifier) { + init(signer: EthereumSigner, eip191Verifier: EIP191Verifier, eip1271Verifier: EIP1271Verifier) { self.signer = signer self.eip191Verifier = eip191Verifier self.eip1271Verifier = eip1271Verifier @@ -27,8 +27,7 @@ struct MessageSigner: MessageSignatureVerifying, MessageSigning { func sign(message: String, privateKey: Data, type: CacaoSignatureType) throws -> CacaoSignature { guard let messageData = message.data(using: .utf8) else { throw Errors.utf8EncodingFailed } let signature = try signer.sign(message: prefixed(messageData), with: privateKey) - let prefixedHexSignature = "0x" + signature.toHexString() - return CacaoSignature(t: type, s: prefixedHexSignature) + return CacaoSignature(t: type, s: signature.hex()) } func verify(signature: CacaoSignature, message: String, address: String, chainId: String) async throws { diff --git a/Sources/Auth/Services/Signer/MessageSignerFactory.swift b/Sources/Auth/Services/Signer/MessageSignerFactory.swift index 85dd7d780..bc9de85f2 100644 --- a/Sources/Auth/Services/Signer/MessageSignerFactory.swift +++ b/Sources/Auth/Services/Signer/MessageSignerFactory.swift @@ -2,14 +2,20 @@ import Foundation public struct MessageSignerFactory { - public static func create() -> MessageSigning & MessageSignatureVerifying { + public let signerFactory: SignerFactory + + public init(signerFactory: SignerFactory) { + self.signerFactory = signerFactory + } + + public func create() -> MessageSigning & MessageSignatureVerifying { return create(projectId: Networking.projectId) } - static func create(projectId: String) -> MessageSigning & MessageSignatureVerifying { + func create(projectId: String) -> MessageSigning & MessageSignatureVerifying { return MessageSigner( - signer: Signer(), - eip191Verifier: EIP191Verifier(), + signer: signerFactory.createEthereum(), + eip191Verifier: EIP191Verifier(signer: signerFactory.createEthereum()), eip1271Verifier: EIP1271Verifier( projectId: projectId, httpClient: HTTPNetworkClient(host: "rpc.walletconnect.com") diff --git a/Sources/Auth/Services/Signer/Signer.swift b/Sources/Auth/Services/Signer/Signer.swift deleted file mode 100644 index cbd56ca89..000000000 --- a/Sources/Auth/Services/Signer/Signer.swift +++ /dev/null @@ -1,19 +0,0 @@ -import Foundation -import Web3 - -struct Signer { - - typealias Signature = (v: UInt, r: [UInt8], s: [UInt8]) - - init() {} - - func sign(message: Data, with key: Data) throws -> Data { - let privateKey = try EthereumPrivateKey(privateKey: key.bytes) - let signature = try privateKey.sign(message: message.bytes) - return serialized(signature: signature) - } - - private func serialized(signature: Signature) -> Data { - return Data(signature.r + signature.s + [UInt8(signature.v)]) - } -} diff --git a/Sources/Auth/Services/Signer/SignerFactory.swift b/Sources/Auth/Services/Signer/SignerFactory.swift new file mode 100644 index 000000000..080cf9f89 --- /dev/null +++ b/Sources/Auth/Services/Signer/SignerFactory.swift @@ -0,0 +1,5 @@ +import Foundation + +public protocol SignerFactory { + func createEthereum() -> EthereumSigner +} From 27834d37f3abe13a0e3878117916a88e74828488 Mon Sep 17 00:00:00 2001 From: Artur Guseinov Date: Thu, 24 Nov 2022 23:32:46 +0500 Subject: [PATCH 03/30] Integration tests repaired --- Example/ExampleApp.xcodeproj/project.pbxproj | 14 ++++- .../xcshareddata/swiftpm/Package.resolved | 4 +- Example/IntegrationTests/Auth/AuthTests.swift | 4 +- .../Stubs/SignerFactory.swift | 36 ++++++++++++ Sources/Auth/Extensions/Data+Keccak256.swift | 9 --- .../Ethereum/EIP1271/EIP1271Verifier.swift | 7 ++- .../Ethereum/EIP191/EIP191Verifier.swift | 4 +- ...umPublicKey.swift => EthereumPubKey.swift} | 2 +- .../Signer/Ethereum/EthereumSignature.swift | 7 ++- .../Signer/Ethereum/EthereumSigner.swift | 3 +- .../Signer/MessageSignerFactory.swift | 3 +- .../WalletConnectUtils/Data+Extension.swift | 56 ------------------- .../WalletConnectUtils/Extensions/Data.swift | 56 +++++++++++++++++-- ...ing+Extension.swift => String+CAIPs.swift} | 0 .../WalletConnectUtils/Extensions/UInt8.swift | 15 +++++ Tests/AuthTests/SignerTests.swift | 2 - 16 files changed, 137 insertions(+), 85 deletions(-) create mode 100644 Example/IntegrationTests/Stubs/SignerFactory.swift delete mode 100644 Sources/Auth/Extensions/Data+Keccak256.swift rename Sources/Auth/Services/Signer/Ethereum/{EthereumPublicKey.swift => EthereumPubKey.swift} (85%) delete mode 100644 Sources/WalletConnectUtils/Data+Extension.swift rename Sources/WalletConnectUtils/Extensions/{String+Extension.swift => String+CAIPs.swift} (100%) create mode 100644 Sources/WalletConnectUtils/Extensions/UInt8.swift diff --git a/Example/ExampleApp.xcodeproj/project.pbxproj b/Example/ExampleApp.xcodeproj/project.pbxproj index fc6357d2b..002883dd7 100644 --- a/Example/ExampleApp.xcodeproj/project.pbxproj +++ b/Example/ExampleApp.xcodeproj/project.pbxproj @@ -120,6 +120,7 @@ A58E7D432872EE320082D443 /* MessageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A58E7D422872EE320082D443 /* MessageView.swift */; }; A58E7D452872EE570082D443 /* ContentMessageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A58E7D442872EE570082D443 /* ContentMessageView.swift */; }; A58E7D482872EF610082D443 /* MessageViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = A58E7D472872EF610082D443 /* MessageViewModel.swift */; }; + A59CF4F6292F83D50031A42F /* SignerFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = A59CF4F5292F83D50031A42F /* SignerFactory.swift */; }; A59EBEF828B54A2A003EDAAF /* AuthRequestModule.swift in Sources */ = {isa = PBXBuildFile; fileRef = A59EBEF328B54A2A003EDAAF /* AuthRequestModule.swift */; }; A59EBEF928B54A2A003EDAAF /* AuthRequestPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = A59EBEF428B54A2A003EDAAF /* AuthRequestPresenter.swift */; }; A59EBEFA28B54A2A003EDAAF /* AuthRequestRouter.swift in Sources */ = {isa = PBXBuildFile; fileRef = A59EBEF528B54A2A003EDAAF /* AuthRequestRouter.swift */; }; @@ -161,6 +162,7 @@ A5C2022B287EB89A007E3188 /* WelcomeInteractor.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5C2022A287EB89A007E3188 /* WelcomeInteractor.swift */; }; A5C2022D287EC3F0007E3188 /* RegisterService.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5C2022C287EC3F0007E3188 /* RegisterService.swift */; }; A5C4DD8728A2DE88006A626D /* WalletConnectRouter in Frameworks */ = {isa = PBXBuildFile; productRef = A5C4DD8628A2DE88006A626D /* WalletConnectRouter */; }; + A5C8BE85292FE20B006CC85C /* Web3 in Frameworks */ = {isa = PBXBuildFile; productRef = A5C8BE84292FE20B006CC85C /* Web3 */; }; A5D85226286333D500DAF5C3 /* Starscream in Frameworks */ = {isa = PBXBuildFile; productRef = A5D85225286333D500DAF5C3 /* Starscream */; }; A5D85228286333E300DAF5C3 /* Starscream in Frameworks */ = {isa = PBXBuildFile; productRef = A5D85227286333E300DAF5C3 /* Starscream */; }; A5E03DF52864651200888481 /* Starscream in Frameworks */ = {isa = PBXBuildFile; productRef = A5E03DF42864651200888481 /* Starscream */; }; @@ -315,6 +317,7 @@ A58E7D422872EE320082D443 /* MessageView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageView.swift; sourceTree = ""; }; A58E7D442872EE570082D443 /* ContentMessageView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentMessageView.swift; sourceTree = ""; }; A58E7D472872EF610082D443 /* MessageViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageViewModel.swift; sourceTree = ""; }; + A59CF4F5292F83D50031A42F /* SignerFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SignerFactory.swift; sourceTree = ""; }; A59EBEF328B54A2A003EDAAF /* AuthRequestModule.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthRequestModule.swift; sourceTree = ""; }; A59EBEF428B54A2A003EDAAF /* AuthRequestPresenter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthRequestPresenter.swift; sourceTree = ""; }; A59EBEF528B54A2A003EDAAF /* AuthRequestRouter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthRequestRouter.swift; sourceTree = ""; }; @@ -417,6 +420,7 @@ A5E03DFF2864662500888481 /* WalletConnect in Frameworks */, A5E03DF52864651200888481 /* Starscream in Frameworks */, 847CF3AF28E3141700F1D760 /* WalletConnectPush in Frameworks */, + A5C8BE85292FE20B006CC85C /* Web3 in Frameworks */, 84DDB4ED28ABB663003D66ED /* WalletConnectAuth in Frameworks */, A5E03E01286466EA00888481 /* WalletConnectChat in Frameworks */, ); @@ -1097,6 +1101,7 @@ A518B31328E33A6500A2CE93 /* InputConfig.swift */, A5E03E1028646F8000888481 /* KeychainStorageMock.swift */, A5E03E0E28646D8A00888481 /* WebSocketFactory.swift */, + A59CF4F5292F83D50031A42F /* SignerFactory.swift */, A5E03DFC286465D100888481 /* Stubs.swift */, 84FE684528ACDB4700C893FF /* RequestParams.swift */, ); @@ -1237,6 +1242,7 @@ A5E03E00286466EA00888481 /* WalletConnectChat */, 84DDB4EC28ABB663003D66ED /* WalletConnectAuth */, 847CF3AE28E3141700F1D760 /* WalletConnectPush */, + A5C8BE84292FE20B006CC85C /* Web3 */, ); productName = IntegrationTests; productReference = A5E03DED286464DB00888481 /* IntegrationTests.xctest */; @@ -1510,6 +1516,7 @@ 84CEC64628D89D6B00D081A8 /* PairingTests.swift in Sources */, 767DC83528997F8E00080FA9 /* EthSendTransaction.swift in Sources */, A518B31428E33A6500A2CE93 /* InputConfig.swift in Sources */, + A59CF4F6292F83D50031A42F /* SignerFactory.swift in Sources */, A5E03E03286466F400888481 /* ChatTests.swift in Sources */, 84D2A66628A4F51E0088AE09 /* AuthTests.swift in Sources */, 84FE684628ACDB4700C893FF /* RequestParams.swift in Sources */, @@ -2016,7 +2023,7 @@ repositoryURL = "https://github.com/WalletConnect/Web3.swift"; requirement = { kind = exactVersion; - version = 1.0.0; + version = 1.0.1; }; }; A5D85224286333D500DAF5C3 /* XCRemoteSwiftPackageReference "Starscream" */ = { @@ -2082,6 +2089,11 @@ isa = XCSwiftPackageProductDependency; productName = WalletConnectRouter; }; + A5C8BE84292FE20B006CC85C /* Web3 */ = { + isa = XCSwiftPackageProductDependency; + package = A5AE354528A1A2AC0059AE8A /* XCRemoteSwiftPackageReference "Web3" */; + productName = Web3; + }; A5D85225286333D500DAF5C3 /* Starscream */ = { isa = XCSwiftPackageProductDependency; package = A5D85224286333D500DAF5C3 /* XCRemoteSwiftPackageReference "Starscream" */; diff --git a/Example/ExampleApp.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/Example/ExampleApp.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 8893d902d..46b8c5b28 100644 --- a/Example/ExampleApp.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/Example/ExampleApp.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -78,8 +78,8 @@ "repositoryURL": "https://github.com/WalletConnect/Web3.swift", "state": { "branch": null, - "revision": "bdaaed96eee3a9bf7f341165f89a94288961d14c", - "version": "1.0.0" + "revision": "5042fbdaf0674e973a374fca6e66e19683f6437e", + "version": "1.0.1" } } ] diff --git a/Example/IntegrationTests/Auth/AuthTests.swift b/Example/IntegrationTests/Auth/AuthTests.swift index ea165a98f..97a59d692 100644 --- a/Example/IntegrationTests/Auth/AuthTests.swift +++ b/Example/IntegrationTests/Auth/AuthTests.swift @@ -50,6 +50,7 @@ final class AuthTests: XCTestCase { metadata: AppMetadata(name: name, description: "", url: "", icons: [""]), account: account, projectId: InputConfig.projectId, + signerFactory: MultichainSignerFactory(), logger: logger, keyValueStorage: keyValueStorage, keychainStorage: keychain, @@ -80,7 +81,8 @@ final class AuthTests: XCTestCase { try! await walletPairingClient.pair(uri: uri) walletAuthClient.authRequestPublisher.sink { [unowned self] request in Task(priority: .high) { - let signer = MessageSignerFactory.create(projectId: InputConfig.projectId) + let signerFactory = MultichainSignerFactory() + let signer = MessageSignerFactory(signerFactory: signerFactory).create(projectId: InputConfig.projectId) let signature = try! signer.sign(message: request.message, privateKey: prvKey, type: .eip191) try! await walletAuthClient.respond(requestId: request.id, signature: signature) } diff --git a/Example/IntegrationTests/Stubs/SignerFactory.swift b/Example/IntegrationTests/Stubs/SignerFactory.swift new file mode 100644 index 000000000..1332f06fb --- /dev/null +++ b/Example/IntegrationTests/Stubs/SignerFactory.swift @@ -0,0 +1,36 @@ +import Foundation +import CryptoSwift +import Web3 +import Auth + +public struct MultichainSignerFactory: SignerFactory { + + public func createEthereum() -> EthereumSigner { + return Web3Signer() + } +} + +public struct Web3Signer: EthereumSigner { + + public func sign(message: Data, with key: Data) throws -> EthereumSignature { + let privateKey = try EthereumPrivateKey(privateKey: [UInt8](key)) + let signature = try privateKey.sign(message: message.bytes) + return EthereumSignature(v: UInt8(signature.v), r: signature.r, s: signature.s) + } + + public func recover(signature: EthereumSignature, message: Data) throws -> EthereumPubKey { + let publicKey = try EthereumPublicKey( + message: message.bytes, + v: EthereumQuantity(quantity: BigUInt(signature.v)), + r: EthereumQuantity(signature.r), + s: EthereumQuantity(signature.s) + ) + return EthereumPubKey(data: publicKey.rawPublicKey) + } + + public func keccak256(_ data: Data) -> Data { + let digest = SHA3(variant: .keccak256) + let hash = digest.calculate(for: [UInt8](data)) + return Data(hash) + } +} diff --git a/Sources/Auth/Extensions/Data+Keccak256.swift b/Sources/Auth/Extensions/Data+Keccak256.swift deleted file mode 100644 index 1bfbc1b8b..000000000 --- a/Sources/Auth/Extensions/Data+Keccak256.swift +++ /dev/null @@ -1,9 +0,0 @@ -import Foundation -import CryptoSwift - -extension Data { - - var keccak256: Data { - return sha3(.keccak256) - } -} diff --git a/Sources/Auth/Services/Signer/Ethereum/EIP1271/EIP1271Verifier.swift b/Sources/Auth/Services/Signer/Ethereum/EIP1271/EIP1271Verifier.swift index a3e6d527c..a3b70ae8b 100644 --- a/Sources/Auth/Services/Signer/Ethereum/EIP1271/EIP1271Verifier.swift +++ b/Sources/Auth/Services/Signer/Ethereum/EIP1271/EIP1271Verifier.swift @@ -3,14 +3,17 @@ import Foundation actor EIP1271Verifier { private let projectId: String private let httpClient: HTTPClient + private let signer: EthereumSigner - init(projectId: String, httpClient: HTTPClient) { + init(projectId: String, httpClient: HTTPClient, signer: EthereumSigner) { self.projectId = projectId self.httpClient = httpClient + self.signer = signer } func verify(signature: Data, message: Data, address: String, chainId: String) async throws { - let encoder = ValidSignatureMethod(signature: signature, messageHash: message.keccak256) + let messageHash = signer.keccak256(message) + let encoder = ValidSignatureMethod(signature: signature, messageHash: messageHash) let call = EthCall(to: address, data: encoder.encode()) let params = AnyCodable([AnyCodable(call), AnyCodable("latest")]) let request = RPCRequest(method: "eth_call", params: params) diff --git a/Sources/Auth/Services/Signer/Ethereum/EIP191/EIP191Verifier.swift b/Sources/Auth/Services/Signer/Ethereum/EIP191/EIP191Verifier.swift index ea4a85677..90644eb4d 100644 --- a/Sources/Auth/Services/Signer/Ethereum/EIP191/EIP191Verifier.swift +++ b/Sources/Auth/Services/Signer/Ethereum/EIP191/EIP191Verifier.swift @@ -10,11 +10,11 @@ actor EIP191Verifier { func verify(signature: Data, message: Data, address: String) async throws { let sig = EthereumSignature(serialized: signature) - let publicKey = try signer.recover(signature: sig) + let publicKey = try signer.recover(signature: sig, message: message) try verifyPublicKey(publicKey, address: address) } - private func verifyPublicKey(_ publicKey: EthereumPublicKey, address: String) throws { + private func verifyPublicKey(_ publicKey: EthereumPubKey, address: String) throws { guard publicKey.hex() == address.lowercased() else { throw Errors.invalidSignature } diff --git a/Sources/Auth/Services/Signer/Ethereum/EthereumPublicKey.swift b/Sources/Auth/Services/Signer/Ethereum/EthereumPubKey.swift similarity index 85% rename from Sources/Auth/Services/Signer/Ethereum/EthereumPublicKey.swift rename to Sources/Auth/Services/Signer/Ethereum/EthereumPubKey.swift index a13518e76..09c165682 100644 --- a/Sources/Auth/Services/Signer/Ethereum/EthereumPublicKey.swift +++ b/Sources/Auth/Services/Signer/Ethereum/EthereumPubKey.swift @@ -1,6 +1,6 @@ import Foundation -public struct EthereumPublicKey { +public struct EthereumPubKey { public let data: [UInt8] public init(data: [UInt8]) { diff --git a/Sources/Auth/Services/Signer/Ethereum/EthereumSignature.swift b/Sources/Auth/Services/Signer/Ethereum/EthereumSignature.swift index 5625c491c..2a7d145cf 100644 --- a/Sources/Auth/Services/Signer/Ethereum/EthereumSignature.swift +++ b/Sources/Auth/Services/Signer/Ethereum/EthereumSignature.swift @@ -12,9 +12,10 @@ public struct EthereumSignature { } public init(serialized: Data) { - v = UInt8(serialized.bytes[serialized.count-1]) - r = [UInt8](serialized.bytes[0..<32]) - s = [UInt8](serialized.bytes[32..<64]) + let bytes = [UInt8](serialized) + v = UInt8(bytes[serialized.count-1]) + r = [UInt8](bytes[0..<32]) + s = [UInt8](bytes[32..<64]) } public var serialized: Data { diff --git a/Sources/Auth/Services/Signer/Ethereum/EthereumSigner.swift b/Sources/Auth/Services/Signer/Ethereum/EthereumSigner.swift index 61608258b..1a1d4c540 100644 --- a/Sources/Auth/Services/Signer/Ethereum/EthereumSigner.swift +++ b/Sources/Auth/Services/Signer/Ethereum/EthereumSigner.swift @@ -2,5 +2,6 @@ import Foundation public protocol EthereumSigner { func sign(message: Data, with key: Data) throws -> EthereumSignature - func recover(signature: EthereumSignature) throws -> EthereumPublicKey + func recover(signature: EthereumSignature, message: Data) throws -> EthereumPubKey + func keccak256(_ data: Data) -> Data } diff --git a/Sources/Auth/Services/Signer/MessageSignerFactory.swift b/Sources/Auth/Services/Signer/MessageSignerFactory.swift index bc9de85f2..314b20fc9 100644 --- a/Sources/Auth/Services/Signer/MessageSignerFactory.swift +++ b/Sources/Auth/Services/Signer/MessageSignerFactory.swift @@ -18,7 +18,8 @@ public struct MessageSignerFactory { eip191Verifier: EIP191Verifier(signer: signerFactory.createEthereum()), eip1271Verifier: EIP1271Verifier( projectId: projectId, - httpClient: HTTPNetworkClient(host: "rpc.walletconnect.com") + httpClient: HTTPNetworkClient(host: "rpc.walletconnect.com"), + signer: signerFactory.createEthereum() ) ) } diff --git a/Sources/WalletConnectUtils/Data+Extension.swift b/Sources/WalletConnectUtils/Data+Extension.swift deleted file mode 100644 index 88624109f..000000000 --- a/Sources/WalletConnectUtils/Data+Extension.swift +++ /dev/null @@ -1,56 +0,0 @@ -import Foundation - -// MARK: - Random data generation - -extension Data { - - public static func randomBytes(count: Int) -> Data { - var buffer = [UInt8](repeating: 0, count: count) - let status = SecRandomCopyBytes(kSecRandomDefault, count, &buffer) - guard status == errSecSuccess else { - fatalError("Failed to generate secure random data of size \(count).") - } - return Data(buffer) - } -} - -// MARK: - Hexadecimal string conversion - -extension Data { - - static func value(of nibble: UInt8) -> UInt8? { - guard let letter = String(bytes: [nibble], encoding: .ascii) else { return nil } - return UInt8(letter, radix: 16) - } - - public init(hex: String) { - var data = Data() - let string = hex.hasPrefix("0x") ? String(hex.dropFirst(2)) : hex - - // Convert the string to bytes for better performance - guard - let stringData = string.data(using: .ascii, allowLossyConversion: true) - else { - self = data - return - } - - let stringBytes = Array(stringData) - for idx in stride(from: 0, to: stringBytes.count, by: 2) { - guard let high = Data.value(of: stringBytes[idx]) else { - data.removeAll() - break - } - if idx < stringBytes.count - 1, let low = Data.value(of: stringBytes[idx + 1]) { - data.append((high << 4) | low) - } else { - data.append(high) - } - } - self = data - } - - public func toHexString() -> String { - return map({ String(format: "%02x", $0) }).joined() - } -} diff --git a/Sources/WalletConnectUtils/Extensions/Data.swift b/Sources/WalletConnectUtils/Extensions/Data.swift index 90236854f..88624109f 100644 --- a/Sources/WalletConnectUtils/Extensions/Data.swift +++ b/Sources/WalletConnectUtils/Extensions/Data.swift @@ -1,8 +1,56 @@ import Foundation -public extension UInt8 { - var data: Data { - var int = self - return Data(bytes: &int, count: MemoryLayout.size) +// MARK: - Random data generation + +extension Data { + + public static func randomBytes(count: Int) -> Data { + var buffer = [UInt8](repeating: 0, count: count) + let status = SecRandomCopyBytes(kSecRandomDefault, count, &buffer) + guard status == errSecSuccess else { + fatalError("Failed to generate secure random data of size \(count).") + } + return Data(buffer) + } +} + +// MARK: - Hexadecimal string conversion + +extension Data { + + static func value(of nibble: UInt8) -> UInt8? { + guard let letter = String(bytes: [nibble], encoding: .ascii) else { return nil } + return UInt8(letter, radix: 16) + } + + public init(hex: String) { + var data = Data() + let string = hex.hasPrefix("0x") ? String(hex.dropFirst(2)) : hex + + // Convert the string to bytes for better performance + guard + let stringData = string.data(using: .ascii, allowLossyConversion: true) + else { + self = data + return + } + + let stringBytes = Array(stringData) + for idx in stride(from: 0, to: stringBytes.count, by: 2) { + guard let high = Data.value(of: stringBytes[idx]) else { + data.removeAll() + break + } + if idx < stringBytes.count - 1, let low = Data.value(of: stringBytes[idx + 1]) { + data.append((high << 4) | low) + } else { + data.append(high) + } + } + self = data + } + + public func toHexString() -> String { + return map({ String(format: "%02x", $0) }).joined() } } diff --git a/Sources/WalletConnectUtils/Extensions/String+Extension.swift b/Sources/WalletConnectUtils/Extensions/String+CAIPs.swift similarity index 100% rename from Sources/WalletConnectUtils/Extensions/String+Extension.swift rename to Sources/WalletConnectUtils/Extensions/String+CAIPs.swift diff --git a/Sources/WalletConnectUtils/Extensions/UInt8.swift b/Sources/WalletConnectUtils/Extensions/UInt8.swift new file mode 100644 index 000000000..c147c544f --- /dev/null +++ b/Sources/WalletConnectUtils/Extensions/UInt8.swift @@ -0,0 +1,15 @@ +import Foundation + +public extension UInt8 { + var data: Data { + var int = self + return Data(bytes: &int, count: MemoryLayout.size) + } +} + +public extension Array where Element == UInt8 { + + func toHexString() -> String { + return Data(self).toHexString() + } +} diff --git a/Tests/AuthTests/SignerTests.swift b/Tests/AuthTests/SignerTests.swift index 80b19ecfb..5d34a504b 100644 --- a/Tests/AuthTests/SignerTests.swift +++ b/Tests/AuthTests/SignerTests.swift @@ -1,8 +1,6 @@ import Foundation import XCTest @testable import Auth -import secp256k1 -import Web3 import WalletConnectUtils import WalletConnectRelay From c761e5521960afc8a13ac54f323a2a128fb7fefc Mon Sep 17 00:00:00 2001 From: Artur Guseinov Date: Thu, 24 Nov 2022 23:59:41 +0500 Subject: [PATCH 04/30] EthereumAddress generation --- Example/IntegrationTests/Stubs/SignerFactory.swift | 4 ++-- .../Signer/Ethereum/EIP191/EIP191Verifier.swift | 10 +++++++--- .../Services/Signer/Ethereum/EthereumPubKey.swift | 13 ------------- .../Services/Signer/Ethereum/EthereumSigner.swift | 2 +- 4 files changed, 10 insertions(+), 19 deletions(-) delete mode 100644 Sources/Auth/Services/Signer/Ethereum/EthereumPubKey.swift diff --git a/Example/IntegrationTests/Stubs/SignerFactory.swift b/Example/IntegrationTests/Stubs/SignerFactory.swift index 1332f06fb..b8174c2f2 100644 --- a/Example/IntegrationTests/Stubs/SignerFactory.swift +++ b/Example/IntegrationTests/Stubs/SignerFactory.swift @@ -18,14 +18,14 @@ public struct Web3Signer: EthereumSigner { return EthereumSignature(v: UInt8(signature.v), r: signature.r, s: signature.s) } - public func recover(signature: EthereumSignature, message: Data) throws -> EthereumPubKey { + public func recoverPubKey(signature: EthereumSignature, message: Data) throws -> Data { let publicKey = try EthereumPublicKey( message: message.bytes, v: EthereumQuantity(quantity: BigUInt(signature.v)), r: EthereumQuantity(signature.r), s: EthereumQuantity(signature.s) ) - return EthereumPubKey(data: publicKey.rawPublicKey) + return Data(publicKey.rawPublicKey) } public func keccak256(_ data: Data) -> Data { diff --git a/Sources/Auth/Services/Signer/Ethereum/EIP191/EIP191Verifier.swift b/Sources/Auth/Services/Signer/Ethereum/EIP191/EIP191Verifier.swift index 90644eb4d..d826878cb 100644 --- a/Sources/Auth/Services/Signer/Ethereum/EIP191/EIP191Verifier.swift +++ b/Sources/Auth/Services/Signer/Ethereum/EIP191/EIP191Verifier.swift @@ -10,12 +10,16 @@ actor EIP191Verifier { func verify(signature: Data, message: Data, address: String) async throws { let sig = EthereumSignature(serialized: signature) - let publicKey = try signer.recover(signature: sig, message: message) + let publicKey = try signer.recoverPubKey(signature: sig, message: message) try verifyPublicKey(publicKey, address: address) } - private func verifyPublicKey(_ publicKey: EthereumPubKey, address: String) throws { - guard publicKey.hex() == address.lowercased() else { + private func verifyPublicKey(_ publicKey: Data, address: String) throws { + let address = "0x" + signer.keccak256(publicKey) + .suffix(20) + .toHexString() + + guard address == address.lowercased() else { throw Errors.invalidSignature } } diff --git a/Sources/Auth/Services/Signer/Ethereum/EthereumPubKey.swift b/Sources/Auth/Services/Signer/Ethereum/EthereumPubKey.swift deleted file mode 100644 index 09c165682..000000000 --- a/Sources/Auth/Services/Signer/Ethereum/EthereumPubKey.swift +++ /dev/null @@ -1,13 +0,0 @@ -import Foundation - -public struct EthereumPubKey { - public let data: [UInt8] - - public init(data: [UInt8]) { - self.data = data - } - - public func hex() -> String { - return "0x" + data.toHexString() - } -} diff --git a/Sources/Auth/Services/Signer/Ethereum/EthereumSigner.swift b/Sources/Auth/Services/Signer/Ethereum/EthereumSigner.swift index 1a1d4c540..9865b04c3 100644 --- a/Sources/Auth/Services/Signer/Ethereum/EthereumSigner.swift +++ b/Sources/Auth/Services/Signer/Ethereum/EthereumSigner.swift @@ -2,6 +2,6 @@ import Foundation public protocol EthereumSigner { func sign(message: Data, with key: Data) throws -> EthereumSignature - func recover(signature: EthereumSignature, message: Data) throws -> EthereumPubKey + func recoverPubKey(signature: EthereumSignature, message: Data) throws -> Data func keccak256(_ data: Data) -> Data } From 0abd0c6ec852497ec1c90098f1518ea313df4312 Mon Sep 17 00:00:00 2001 From: Artur Guseinov Date: Fri, 25 Nov 2022 16:04:42 +0500 Subject: [PATCH 05/30] ShowcaseApp connected --- Example/ExampleApp.xcodeproj/project.pbxproj | 12 +++++++ .../Configurator/ThirdPartyConfigurator.swift | 3 +- .../MultichainSignerFactory.swift | 36 +++++++++++++++++++ .../AuthRequest/AuthRequestInteractor.swift | 2 +- 4 files changed, 51 insertions(+), 2 deletions(-) create mode 100644 Example/Showcase/Classes/DomainLayer/SignerFactory/MultichainSignerFactory.swift diff --git a/Example/ExampleApp.xcodeproj/project.pbxproj b/Example/ExampleApp.xcodeproj/project.pbxproj index 002883dd7..3306b2868 100644 --- a/Example/ExampleApp.xcodeproj/project.pbxproj +++ b/Example/ExampleApp.xcodeproj/project.pbxproj @@ -181,6 +181,7 @@ A5E22D222840C8D300E36487 /* WalletEngine.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5E22D212840C8D300E36487 /* WalletEngine.swift */; }; A5E22D242840C8DB00E36487 /* SafariEngine.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5E22D232840C8DB00E36487 /* SafariEngine.swift */; }; A5E22D2C2840EAC300E36487 /* XCUIElement.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5E22D2B2840EAC300E36487 /* XCUIElement.swift */; }; + A5EA27542930D7830094D272 /* MultichainSignerFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5EA27532930D7830094D272 /* MultichainSignerFactory.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -369,6 +370,7 @@ A5E22D212840C8D300E36487 /* WalletEngine.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WalletEngine.swift; sourceTree = ""; }; A5E22D232840C8DB00E36487 /* SafariEngine.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SafariEngine.swift; sourceTree = ""; }; A5E22D2B2840EAC300E36487 /* XCUIElement.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = XCUIElement.swift; sourceTree = ""; }; + A5EA27532930D7830094D272 /* MultichainSignerFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MultichainSignerFactory.swift; sourceTree = ""; }; A5F48A0528E43D3F0034CBFB /* Configuration.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Configuration.xcconfig; path = ../Configuration.xcconfig; sourceTree = ""; }; /* End PBXFileReference section */ @@ -660,6 +662,7 @@ A5629AA42876A19D00094373 /* DomainLayer */ = { isa = PBXGroup; children = ( + A5EA27522930D7760094D272 /* SignerFactory */, A5C20227287EB342007E3188 /* AccountStorage */, A5629AEE2877F72B00094373 /* SocketFactory */, A5629AEB2877F69C00094373 /* Chat */, @@ -1132,6 +1135,14 @@ path = Extensions; sourceTree = ""; }; + A5EA27522930D7760094D272 /* SignerFactory */ = { + isa = PBXGroup; + children = ( + A5EA27532930D7830094D272 /* MultichainSignerFactory.swift */, + ); + path = SignerFactory; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -1458,6 +1469,7 @@ A59F877128B53EA000A9CD80 /* WalletRouter.swift in Sources */, A5C20226287EB099007E3188 /* AccountNameResolver.swift in Sources */, A5C2020D287D9DEE007E3188 /* WelcomeRouter.swift in Sources */, + A5EA27542930D7830094D272 /* MultichainSignerFactory.swift in Sources */, A55CAAB328B92AFF00844382 /* ScanInteractor.swift in Sources */, A55CAABA28B92B4600844382 /* ScanTargetView.swift in Sources */, A578FA372873D8EE00AA7720 /* UIColor.swift in Sources */, diff --git a/Example/Showcase/Classes/ApplicationLayer/Configurator/ThirdPartyConfigurator.swift b/Example/Showcase/Classes/ApplicationLayer/Configurator/ThirdPartyConfigurator.swift index a8936517a..cb454420c 100644 --- a/Example/Showcase/Classes/ApplicationLayer/Configurator/ThirdPartyConfigurator.swift +++ b/Example/Showcase/Classes/ApplicationLayer/Configurator/ThirdPartyConfigurator.swift @@ -15,7 +15,8 @@ struct ThirdPartyConfigurator: Configurator { )) Auth.configure( - account: Account("eip155:1:0xe5EeF1368781911d265fDB6946613dA61915a501")! + account: Account("eip155:1:0xe5EeF1368781911d265fDB6946613dA61915a501")!, + signerFactory: MultichainSignerFactory() ) } } diff --git a/Example/Showcase/Classes/DomainLayer/SignerFactory/MultichainSignerFactory.swift b/Example/Showcase/Classes/DomainLayer/SignerFactory/MultichainSignerFactory.swift new file mode 100644 index 000000000..b8174c2f2 --- /dev/null +++ b/Example/Showcase/Classes/DomainLayer/SignerFactory/MultichainSignerFactory.swift @@ -0,0 +1,36 @@ +import Foundation +import CryptoSwift +import Web3 +import Auth + +public struct MultichainSignerFactory: SignerFactory { + + public func createEthereum() -> EthereumSigner { + return Web3Signer() + } +} + +public struct Web3Signer: EthereumSigner { + + public func sign(message: Data, with key: Data) throws -> EthereumSignature { + let privateKey = try EthereumPrivateKey(privateKey: [UInt8](key)) + let signature = try privateKey.sign(message: message.bytes) + return EthereumSignature(v: UInt8(signature.v), r: signature.r, s: signature.s) + } + + public func recoverPubKey(signature: EthereumSignature, message: Data) throws -> Data { + let publicKey = try EthereumPublicKey( + message: message.bytes, + v: EthereumQuantity(quantity: BigUInt(signature.v)), + r: EthereumQuantity(signature.r), + s: EthereumQuantity(signature.s) + ) + return Data(publicKey.rawPublicKey) + } + + public func keccak256(_ data: Data) -> Data { + let digest = SHA3(variant: .keccak256) + let hash = digest.calculate(for: [UInt8](data)) + return Data(hash) + } +} diff --git a/Example/Showcase/Classes/PresentationLayer/Wallet/AuthRequest/AuthRequestInteractor.swift b/Example/Showcase/Classes/PresentationLayer/Wallet/AuthRequest/AuthRequestInteractor.swift index c0c3a8bd3..29ea3a477 100644 --- a/Example/Showcase/Classes/PresentationLayer/Wallet/AuthRequest/AuthRequestInteractor.swift +++ b/Example/Showcase/Classes/PresentationLayer/Wallet/AuthRequest/AuthRequestInteractor.swift @@ -6,7 +6,7 @@ final class AuthRequestInteractor { func approve(request: AuthRequest) async throws { let privateKey = Data(hex: "e56da0e170b5e09a8bb8f1b693392c7d56c3739a9c75740fbc558a2877868540") - let signer = MessageSignerFactory.create() + let signer = MessageSignerFactory(signerFactory: MultichainSignerFactory()).create() let signature = try signer.sign(message: request.message, privateKey: privateKey, type: .eip191) try await Auth.instance.respond(requestId: request.id, signature: signature) } From da2e0259dad0e1b7eaa2e99ab45bf836debd10ed Mon Sep 17 00:00:00 2001 From: Artur Guseinov Date: Mon, 28 Nov 2022 16:55:51 +0500 Subject: [PATCH 06/30] Signer UnitTests moved to IntegrationTests --- Example/ExampleApp.xcodeproj/project.pbxproj | 24 ++++++++++++ .../Auth/Signer}/CacaoSignerTests.swift | 4 +- .../Auth/Signer/EIP1271VerifierTests.swift | 39 +++++++++++++++++++ .../Auth/Signer}/EIP191VerifierTests.swift | 3 +- .../Auth/Signer}/SignerTests.swift | 7 ++-- .../Ethereum/EIP191/EIP191Verifier.swift | 4 +- .../AuthTests/AppRespondSubscriberTests.swift | 2 +- Tests/AuthTests/EIP1271VerifierTests.swift | 38 ------------------ Tests/AuthTests/Mocks/SignerFactoryMock.swift | 24 ++++++++++++ 9 files changed, 96 insertions(+), 49 deletions(-) rename {Tests/AuthTests => Example/IntegrationTests/Auth/Signer}/CacaoSignerTests.swift (90%) create mode 100644 Example/IntegrationTests/Auth/Signer/EIP1271VerifierTests.swift rename {Tests/AuthTests => Example/IntegrationTests/Auth/Signer}/EIP191VerifierTests.swift (95%) rename {Tests/AuthTests => Example/IntegrationTests/Auth/Signer}/SignerTests.swift (79%) delete mode 100644 Tests/AuthTests/EIP1271VerifierTests.swift create mode 100644 Tests/AuthTests/Mocks/SignerFactoryMock.swift diff --git a/Example/ExampleApp.xcodeproj/project.pbxproj b/Example/ExampleApp.xcodeproj/project.pbxproj index 3306b2868..0b6daa8c9 100644 --- a/Example/ExampleApp.xcodeproj/project.pbxproj +++ b/Example/ExampleApp.xcodeproj/project.pbxproj @@ -57,6 +57,10 @@ A51AC0D928E436A3001BACF9 /* InputConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = A51AC0D828E436A3001BACF9 /* InputConfig.swift */; }; A51AC0DD28E43727001BACF9 /* InputConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = A51AC0DB28E436E6001BACF9 /* InputConfig.swift */; }; A51AC0DF28E4379F001BACF9 /* InputConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = A51AC0DE28E4379F001BACF9 /* InputConfig.swift */; }; + A541959E2934BFEF0035AD19 /* CacaoSignerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A541959A2934BFEF0035AD19 /* CacaoSignerTests.swift */; }; + A541959F2934BFEF0035AD19 /* SignerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A541959B2934BFEF0035AD19 /* SignerTests.swift */; }; + A54195A02934BFEF0035AD19 /* EIP1271VerifierTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A541959C2934BFEF0035AD19 /* EIP1271VerifierTests.swift */; }; + A54195A12934BFEF0035AD19 /* EIP191VerifierTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A541959D2934BFEF0035AD19 /* EIP191VerifierTests.swift */; }; A5434023291E6A270068F706 /* SolanaSwift in Frameworks */ = {isa = PBXBuildFile; productRef = A5434022291E6A270068F706 /* SolanaSwift */; }; A55CAAB028B92AFF00844382 /* ScanModule.swift in Sources */ = {isa = PBXBuildFile; fileRef = A55CAAAB28B92AFF00844382 /* ScanModule.swift */; }; A55CAAB128B92AFF00844382 /* ScanPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = A55CAAAC28B92AFF00844382 /* ScanPresenter.swift */; }; @@ -256,6 +260,10 @@ A51AC0D828E436A3001BACF9 /* InputConfig.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InputConfig.swift; sourceTree = ""; }; A51AC0DB28E436E6001BACF9 /* InputConfig.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InputConfig.swift; sourceTree = ""; }; A51AC0DE28E4379F001BACF9 /* InputConfig.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InputConfig.swift; sourceTree = ""; }; + A541959A2934BFEF0035AD19 /* CacaoSignerTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CacaoSignerTests.swift; sourceTree = ""; }; + A541959B2934BFEF0035AD19 /* SignerTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SignerTests.swift; sourceTree = ""; }; + A541959C2934BFEF0035AD19 /* EIP1271VerifierTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EIP1271VerifierTests.swift; sourceTree = ""; }; + A541959D2934BFEF0035AD19 /* EIP191VerifierTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EIP191VerifierTests.swift; sourceTree = ""; }; A55CAAAB28B92AFF00844382 /* ScanModule.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScanModule.swift; sourceTree = ""; }; A55CAAAC28B92AFF00844382 /* ScanPresenter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScanPresenter.swift; sourceTree = ""; }; A55CAAAD28B92AFF00844382 /* ScanRouter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScanRouter.swift; sourceTree = ""; }; @@ -615,6 +623,7 @@ 84D2A66728A4F5260088AE09 /* Auth */ = { isa = PBXGroup; children = ( + A54195992934BFDD0035AD19 /* Signer */, 84D2A66528A4F51E0088AE09 /* AuthTests.swift */, ); path = Auth; @@ -636,6 +645,17 @@ path = Common; sourceTree = ""; }; + A54195992934BFDD0035AD19 /* Signer */ = { + isa = PBXGroup; + children = ( + A541959A2934BFEF0035AD19 /* CacaoSignerTests.swift */, + A541959D2934BFEF0035AD19 /* EIP191VerifierTests.swift */, + A541959C2934BFEF0035AD19 /* EIP1271VerifierTests.swift */, + A541959B2934BFEF0035AD19 /* SignerTests.swift */, + ); + path = Signer; + sourceTree = ""; + }; A55CAAAA28B92AF200844382 /* Scan */ = { isa = PBXGroup; children = ( @@ -1528,14 +1548,18 @@ 84CEC64628D89D6B00D081A8 /* PairingTests.swift in Sources */, 767DC83528997F8E00080FA9 /* EthSendTransaction.swift in Sources */, A518B31428E33A6500A2CE93 /* InputConfig.swift in Sources */, + A541959E2934BFEF0035AD19 /* CacaoSignerTests.swift in Sources */, A59CF4F6292F83D50031A42F /* SignerFactory.swift in Sources */, A5E03E03286466F400888481 /* ChatTests.swift in Sources */, 84D2A66628A4F51E0088AE09 /* AuthTests.swift in Sources */, 84FE684628ACDB4700C893FF /* RequestParams.swift in Sources */, 7694A5262874296A0001257E /* RegistryTests.swift in Sources */, + A541959F2934BFEF0035AD19 /* SignerTests.swift in Sources */, A50C036528AAD32200FE72D3 /* ClientDelegate.swift in Sources */, A5E03E0D28646AD200888481 /* RelayClientEndToEndTests.swift in Sources */, A5E03DFA286465C700888481 /* SignClientTests.swift in Sources */, + A54195A02934BFEF0035AD19 /* EIP1271VerifierTests.swift in Sources */, + A54195A12934BFEF0035AD19 /* EIP191VerifierTests.swift in Sources */, A5E03E0F28646D8A00888481 /* WebSocketFactory.swift in Sources */, 84AA01DB28CF0CD7005D48D8 /* XCTest.swift in Sources */, A5E03E1128646F8000888481 /* KeychainStorageMock.swift in Sources */, diff --git a/Tests/AuthTests/CacaoSignerTests.swift b/Example/IntegrationTests/Auth/Signer/CacaoSignerTests.swift similarity index 90% rename from Tests/AuthTests/CacaoSignerTests.swift rename to Example/IntegrationTests/Auth/Signer/CacaoSignerTests.swift index 95a01a538..6112a9a95 100644 --- a/Tests/AuthTests/CacaoSignerTests.swift +++ b/Example/IntegrationTests/Auth/Signer/CacaoSignerTests.swift @@ -1,11 +1,11 @@ import Foundation import XCTest @testable import Auth -import TestingUtils class CacaoSignerTest: XCTestCase { - let signer = MessageSignerFactory.create(projectId: "project-id") + let signer = MessageSignerFactory(signerFactory: MultichainSignerFactory()) + .create(projectId: InputConfig.projectId) let privateKey = Data(hex: "305c6cde3846927892cd32762f6120539f3ec74c9e3a16b9b798b1e85351ae2a") diff --git a/Example/IntegrationTests/Auth/Signer/EIP1271VerifierTests.swift b/Example/IntegrationTests/Auth/Signer/EIP1271VerifierTests.swift new file mode 100644 index 000000000..e43f2789d --- /dev/null +++ b/Example/IntegrationTests/Auth/Signer/EIP1271VerifierTests.swift @@ -0,0 +1,39 @@ +import Foundation +import XCTest +@testable import Auth +import JSONRPC + +class EIP1271VerifierTests: XCTestCase { + + let signature = Data(hex: "c1505719b2504095116db01baaf276361efd3a73c28cf8cc28dabefa945b8d536011289ac0a3b048600c1e692ff173ca944246cf7ceb319ac2262d27b395c82b1c") + + let message = Data(hex: "19457468657265756d205369676e6564204d6573736167653a0a3235326c6f63616c686f73742077616e747320796f7520746f207369676e20696e207769746820796f757220457468657265756d206163636f756e743a0a3078326661663833633534326236386631623463646330653737306538636239663536376230386637310a0a5552493a20687474703a2f2f6c6f63616c686f73743a333030302f0a56657273696f6e3a20310a436861696e2049443a20310a4e6f6e63653a20313636353434333031353730300a4973737565642041743a20323032322d31302d31305432333a30333a33352e3730305a0a45787069726174696f6e2054696d653a20323032322d31302d31315432333a30333a33352e3730305a") + + let address = "0x2faf83c542b68f1b4cdc0e770e8cb9f567b08f71" + let chainId = "eip155:1" + + func testSuccessVerify() async throws { + let httpClient = HTTPNetworkClient(host: "rpc.walletconnect.com") + let signer = MultichainSignerFactory().createEthereum() + let verifier = EIP1271Verifier(projectId: InputConfig.projectId, httpClient: httpClient, signer: signer) + try await verifier.verify( + signature: signature, + message: message, + address: address, + chainId: chainId + ) + } + + func testFailureVerify() async throws { + let httpClient = HTTPNetworkClient(host: "rpc.walletconnect.com") + let signer = MultichainSignerFactory().createEthereum() + let verifier = EIP1271Verifier(projectId: InputConfig.projectId, httpClient: httpClient, signer: signer) + + await XCTAssertThrowsErrorAsync(try await verifier.verify( + signature: Data("deadbeaf"), + message: message, + address: address, + chainId: chainId + )) + } +} diff --git a/Tests/AuthTests/EIP191VerifierTests.swift b/Example/IntegrationTests/Auth/Signer/EIP191VerifierTests.swift similarity index 95% rename from Tests/AuthTests/EIP191VerifierTests.swift rename to Example/IntegrationTests/Auth/Signer/EIP191VerifierTests.swift index 7b683ab14..318ea7de0 100644 --- a/Tests/AuthTests/EIP191VerifierTests.swift +++ b/Example/IntegrationTests/Auth/Signer/EIP191VerifierTests.swift @@ -1,11 +1,10 @@ import Foundation import XCTest -import TestingUtils @testable import Auth class EIP191VerifierTests: XCTestCase { - private let verifier = EIP191Verifier() + private let verifier = EIP191Verifier(signer: MultichainSignerFactory().createEthereum()) private let address = "0x15bca56b6e2728aec2532df9d436bd1600e86688" private let message = "\u{19}Ethereum Signed Message:\n7Message".data(using: .utf8)! diff --git a/Tests/AuthTests/SignerTests.swift b/Example/IntegrationTests/Auth/Signer/SignerTests.swift similarity index 79% rename from Tests/AuthTests/SignerTests.swift rename to Example/IntegrationTests/Auth/Signer/SignerTests.swift index 5d34a504b..ba9a8b7e3 100644 --- a/Tests/AuthTests/SignerTests.swift +++ b/Example/IntegrationTests/Auth/Signer/SignerTests.swift @@ -1,22 +1,21 @@ import Foundation import XCTest @testable import Auth -import WalletConnectUtils import WalletConnectRelay class SignerTest: XCTestCase { - private let signer = Signer() + private let signer = MultichainSignerFactory().createEthereum() private let message = "\u{19}Ethereum Signed Message:\n7Message".data(using: .utf8)! private let privateKey = Data(hex: "305c6cde3846927892cd32762f6120539f3ec74c9e3a16b9b798b1e85351ae2a") - private let signature = Data(hex: "66121e60cccc01fbf7fcba694a1e08ac5db35fb4ec6c045bedba7860445b95c021cad2c595f0bf68ff896964c7c02bb2f3a3e9540e8e4595c98b737ce264cc541b") + private let signature = "0x66121e60cccc01fbf7fcba694a1e08ac5db35fb4ec6c045bedba7860445b95c021cad2c595f0bf68ff896964c7c02bb2f3a3e9540e8e4595c98b737ce264cc541b" private var address = "0x15bca56b6e2728aec2532df9d436bd1600e86688" func testValidSignature() throws { let result = try signer.sign(message: message, with: privateKey) - XCTAssertEqual(signature.toHexString(), result.toHexString()) + XCTAssertEqual(signature, result.hex()) } private func prefixed(_ message: Data) -> Data { diff --git a/Sources/Auth/Services/Signer/Ethereum/EIP191/EIP191Verifier.swift b/Sources/Auth/Services/Signer/Ethereum/EIP191/EIP191Verifier.swift index d826878cb..9517e0831 100644 --- a/Sources/Auth/Services/Signer/Ethereum/EIP191/EIP191Verifier.swift +++ b/Sources/Auth/Services/Signer/Ethereum/EIP191/EIP191Verifier.swift @@ -15,11 +15,11 @@ actor EIP191Verifier { } private func verifyPublicKey(_ publicKey: Data, address: String) throws { - let address = "0x" + signer.keccak256(publicKey) + let recovered = "0x" + signer.keccak256(publicKey) .suffix(20) .toHexString() - guard address == address.lowercased() else { + guard recovered == address.lowercased() else { throw Errors.invalidSignature } } diff --git a/Tests/AuthTests/AppRespondSubscriberTests.swift b/Tests/AuthTests/AppRespondSubscriberTests.swift index 07492323e..1cf14a850 100644 --- a/Tests/AuthTests/AppRespondSubscriberTests.swift +++ b/Tests/AuthTests/AppRespondSubscriberTests.swift @@ -22,7 +22,7 @@ class AppRespondSubscriberTests: XCTestCase { override func setUp() { networkingInteractor = NetworkingInteractorMock() messageFormatter = SIWEMessageFormatter() - messageSigner = MessageSignerFactory.create(projectId: "project-id") + messageSigner = MessageSignerFactory(signerFactory: SignerFactoryMock()).create(projectId: "project-id") rpcHistory = RPCHistoryFactory.createForNetwork(keyValueStorage: RuntimeKeyValueStorage()) pairingStorage = WCPairingStorageMock() pairingRegisterer = PairingRegistererMock() diff --git a/Tests/AuthTests/EIP1271VerifierTests.swift b/Tests/AuthTests/EIP1271VerifierTests.swift deleted file mode 100644 index 796c146ff..000000000 --- a/Tests/AuthTests/EIP1271VerifierTests.swift +++ /dev/null @@ -1,38 +0,0 @@ -import Foundation -import XCTest -@testable import Auth -import JSONRPC -import TestingUtils - -class EIP1271VerifierTests: XCTestCase { - - let signature = Data(hex: "c1505719b2504095116db01baaf276361efd3a73c28cf8cc28dabefa945b8d536011289ac0a3b048600c1e692ff173ca944246cf7ceb319ac2262d27b395c82b1c") - let message = Data(hex: "3aaa8393796c7388e4e062861d8238503de7584c977676fe9d8d551c30e11f84") - let address = "0x2faf83c542b68f1b4cdc0e770e8cb9f567b08f71" - let chainId = "eip155:1" - - func testSuccessVerify() async throws { - let response = RPCResponse(id: "1", result: "0x1626ba7e00000000000000000000000000000000000000000000000000000000") - let httpClient = HTTPClientMock(object: response) - let verifier = EIP1271Verifier(projectId: "project-id", httpClient: httpClient) - try await verifier.verify( - signature: signature, - message: message, - address: address, - chainId: chainId - ) - } - - func testFailureVerify() async throws { - let response = RPCResponse(id: "1", error: .internalError) - let httpClient = HTTPClientMock(object: response) - let verifier = EIP1271Verifier(projectId: "project-id", httpClient: httpClient) - - await XCTAssertThrowsErrorAsync(try await verifier.verify( - signature: signature, - message: message, - address: address, - chainId: chainId - )) - } -} diff --git a/Tests/AuthTests/Mocks/SignerFactoryMock.swift b/Tests/AuthTests/Mocks/SignerFactoryMock.swift new file mode 100644 index 000000000..9d9246de4 --- /dev/null +++ b/Tests/AuthTests/Mocks/SignerFactoryMock.swift @@ -0,0 +1,24 @@ +import Foundation +import Auth + +struct SignerFactoryMock: SignerFactory { + + func createEthereum() -> EthereumSigner { + return EthereumSignerMock() + } +} + +struct EthereumSignerMock: EthereumSigner { + + func sign(message: Data, with key: Data) throws -> EthereumSignature { + return EthereumSignature(v: 0, r: [], s: []) + } + + func recoverPubKey(signature: EthereumSignature, message: Data) throws -> Data { + return Data() + } + + func keccak256(_ data: Data) -> Data { + return Data() + } +} From 03232704d5cde35b5f86f9985d14b050b4868860 Mon Sep 17 00:00:00 2001 From: Artur Guseinov Date: Mon, 28 Nov 2022 18:04:27 +0500 Subject: [PATCH 07/30] EIP-155 constant removed from Web3.swift --- Example/DApp/SceneDelegate.swift | 2 ++ Example/DApp/SignerFactory.swift | 36 +++++++++++++++++++ Example/ExampleApp.xcodeproj/project.pbxproj | 14 +++++++- .../xcshareddata/swiftpm/Package.resolved | 4 +-- Sources/Auth/Auth.swift | 9 ++++- .../Signer/Ethereum/EthereumSignature.swift | 18 +++++++--- 6 files changed, 75 insertions(+), 8 deletions(-) create mode 100644 Example/DApp/SignerFactory.swift diff --git a/Example/DApp/SceneDelegate.swift b/Example/DApp/SceneDelegate.swift index afeca0dce..6513b9940 100644 --- a/Example/DApp/SceneDelegate.swift +++ b/Example/DApp/SceneDelegate.swift @@ -1,5 +1,6 @@ import UIKit import Starscream +import Auth import WalletConnectRelay import WalletConnectNetworking @@ -20,6 +21,7 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { Networking.configure(projectId: InputConfig.projectId, socketFactory: SocketFactory()) + Auth.configure(signerFactory: MultichainSignerFactory()) setupWindow(scene: scene) } diff --git a/Example/DApp/SignerFactory.swift b/Example/DApp/SignerFactory.swift new file mode 100644 index 000000000..b8174c2f2 --- /dev/null +++ b/Example/DApp/SignerFactory.swift @@ -0,0 +1,36 @@ +import Foundation +import CryptoSwift +import Web3 +import Auth + +public struct MultichainSignerFactory: SignerFactory { + + public func createEthereum() -> EthereumSigner { + return Web3Signer() + } +} + +public struct Web3Signer: EthereumSigner { + + public func sign(message: Data, with key: Data) throws -> EthereumSignature { + let privateKey = try EthereumPrivateKey(privateKey: [UInt8](key)) + let signature = try privateKey.sign(message: message.bytes) + return EthereumSignature(v: UInt8(signature.v), r: signature.r, s: signature.s) + } + + public func recoverPubKey(signature: EthereumSignature, message: Data) throws -> Data { + let publicKey = try EthereumPublicKey( + message: message.bytes, + v: EthereumQuantity(quantity: BigUInt(signature.v)), + r: EthereumQuantity(signature.r), + s: EthereumQuantity(signature.s) + ) + return Data(publicKey.rawPublicKey) + } + + public func keccak256(_ data: Data) -> Data { + let digest = SHA3(variant: .keccak256) + let hash = digest.calculate(for: [UInt8](data)) + return Data(hash) + } +} diff --git a/Example/ExampleApp.xcodeproj/project.pbxproj b/Example/ExampleApp.xcodeproj/project.pbxproj index 0b6daa8c9..6282da0e0 100644 --- a/Example/ExampleApp.xcodeproj/project.pbxproj +++ b/Example/ExampleApp.xcodeproj/project.pbxproj @@ -61,6 +61,8 @@ A541959F2934BFEF0035AD19 /* SignerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A541959B2934BFEF0035AD19 /* SignerTests.swift */; }; A54195A02934BFEF0035AD19 /* EIP1271VerifierTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A541959C2934BFEF0035AD19 /* EIP1271VerifierTests.swift */; }; A54195A12934BFEF0035AD19 /* EIP191VerifierTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A541959D2934BFEF0035AD19 /* EIP191VerifierTests.swift */; }; + A54195A32934E7EC0035AD19 /* SignerFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = A54195A22934E7EC0035AD19 /* SignerFactory.swift */; }; + A54195A52934E83F0035AD19 /* Web3 in Frameworks */ = {isa = PBXBuildFile; productRef = A54195A42934E83F0035AD19 /* Web3 */; }; A5434023291E6A270068F706 /* SolanaSwift in Frameworks */ = {isa = PBXBuildFile; productRef = A5434022291E6A270068F706 /* SolanaSwift */; }; A55CAAB028B92AFF00844382 /* ScanModule.swift in Sources */ = {isa = PBXBuildFile; fileRef = A55CAAAB28B92AFF00844382 /* ScanModule.swift */; }; A55CAAB128B92AFF00844382 /* ScanPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = A55CAAAC28B92AFF00844382 /* ScanPresenter.swift */; }; @@ -264,6 +266,7 @@ A541959B2934BFEF0035AD19 /* SignerTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SignerTests.swift; sourceTree = ""; }; A541959C2934BFEF0035AD19 /* EIP1271VerifierTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EIP1271VerifierTests.swift; sourceTree = ""; }; A541959D2934BFEF0035AD19 /* EIP191VerifierTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EIP191VerifierTests.swift; sourceTree = ""; }; + A54195A22934E7EC0035AD19 /* SignerFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SignerFactory.swift; sourceTree = ""; }; A55CAAAB28B92AFF00844382 /* ScanModule.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScanModule.swift; sourceTree = ""; }; A55CAAAC28B92AFF00844382 /* ScanPresenter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScanPresenter.swift; sourceTree = ""; }; A55CAAAD28B92AFF00844382 /* ScanRouter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScanRouter.swift; sourceTree = ""; }; @@ -400,6 +403,7 @@ buildActionMask = 2147483647; files = ( 8448F1D427E4726F0000B866 /* WalletConnect in Frameworks */, + A54195A52934E83F0035AD19 /* Web3 in Frameworks */, A5D85228286333E300DAF5C3 /* Starscream in Frameworks */, A5BB7FA328B6A50400707FC6 /* WalletConnectAuth in Frameworks */, ); @@ -567,6 +571,7 @@ A5BB7FAB28B6AA7100707FC6 /* Common */, 84CE641E27981DED00142511 /* AppDelegate.swift */, 84CE642027981DED00142511 /* SceneDelegate.swift */, + A54195A22934E7EC0035AD19 /* SignerFactory.swift */, A5BB7FAA28B6A64A00707FC6 /* Sign */, A5BB7FA528B6A5DC00707FC6 /* Auth */, 84CE642727981DF000142511 /* Assets.xcassets */, @@ -1207,6 +1212,7 @@ 8448F1D327E4726F0000B866 /* WalletConnect */, A5D85227286333E300DAF5C3 /* Starscream */, A5BB7FA228B6A50400707FC6 /* WalletConnectAuth */, + A54195A42934E83F0035AD19 /* Web3 */, ); productName = DApp; productReference = 84CE641C27981DED00142511 /* DApp.app */; @@ -1421,6 +1427,7 @@ 84CE645527A29D4D00142511 /* ResponseViewController.swift in Sources */, 84CE641F27981DED00142511 /* AppDelegate.swift in Sources */, A5BB7FAD28B6AA7D00707FC6 /* QRCodeGenerator.swift in Sources */, + A54195A32934E7EC0035AD19 /* SignerFactory.swift in Sources */, A51AC0D928E436A3001BACF9 /* InputConfig.swift in Sources */, A5BB7FA928B6A5FD00707FC6 /* AuthViewModel.swift in Sources */, 84CE6452279ED42B00142511 /* ConnectView.swift in Sources */, @@ -2059,7 +2066,7 @@ repositoryURL = "https://github.com/WalletConnect/Web3.swift"; requirement = { kind = exactVersion; - version = 1.0.1; + version = 1.0.2; }; }; A5D85224286333D500DAF5C3 /* XCRemoteSwiftPackageReference "Starscream" */ = { @@ -2089,6 +2096,11 @@ isa = XCSwiftPackageProductDependency; productName = WalletConnectAuth; }; + A54195A42934E83F0035AD19 /* Web3 */ = { + isa = XCSwiftPackageProductDependency; + package = A5AE354528A1A2AC0059AE8A /* XCRemoteSwiftPackageReference "Web3" */; + productName = Web3; + }; A5434022291E6A270068F706 /* SolanaSwift */ = { isa = XCSwiftPackageProductDependency; package = A5434021291E6A270068F706 /* XCRemoteSwiftPackageReference "solana-swift" */; diff --git a/Example/ExampleApp.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/Example/ExampleApp.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 46b8c5b28..4dc474e71 100644 --- a/Example/ExampleApp.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/Example/ExampleApp.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -78,8 +78,8 @@ "repositoryURL": "https://github.com/WalletConnect/Web3.swift", "state": { "branch": null, - "revision": "5042fbdaf0674e973a374fca6e66e19683f6437e", - "version": "1.0.1" + "revision": "569255adcfff0b37e4cb8004aea29d0e2d6266df", + "version": "1.0.2" } } ] diff --git a/Sources/Auth/Auth.swift b/Sources/Auth/Auth.swift index a4986ea59..26e31bc78 100644 --- a/Sources/Auth/Auth.swift +++ b/Sources/Auth/Auth.swift @@ -33,11 +33,18 @@ public class Auth { private init() { } - /// Auth instance wallet config method + /// Auth instance wallet config method. For Wallet usage /// - Parameters: /// - account: account that wallet will be authenticating with. /// - signerFactory: Multichain signers factory static public func configure(account: Account, signerFactory: SignerFactory) { Auth.config = Auth.Config(account: account, signerFactory: signerFactory) } + + /// Auth instance wallet config method. For DApp usage + /// - Parameters: + /// - signerFactory: Multichain signers factory + static public func configure(signerFactory: SignerFactory) { + Auth.config = Auth.Config(account: nil, signerFactory: signerFactory) + } } diff --git a/Sources/Auth/Services/Signer/Ethereum/EthereumSignature.swift b/Sources/Auth/Services/Signer/Ethereum/EthereumSignature.swift index 2a7d145cf..e992023ff 100644 --- a/Sources/Auth/Services/Signer/Ethereum/EthereumSignature.swift +++ b/Sources/Auth/Services/Signer/Ethereum/EthereumSignature.swift @@ -13,13 +13,23 @@ public struct EthereumSignature { public init(serialized: Data) { let bytes = [UInt8](serialized) - v = UInt8(bytes[serialized.count-1]) - r = [UInt8](bytes[0..<32]) - s = [UInt8](bytes[32..<64]) + + var v = bytes[bytes.count-1] + if v >= 27 && v <= 30 { + v -= 27 + } else if v >= 31 && v <= 34 { + v -= 31 + } else if v >= 35 && v <= 38 { + v -= 35 + } + + self.v = v + self.r = [UInt8](bytes[0..<32]) + self.s = [UInt8](bytes[32..<64]) } public var serialized: Data { - return Data(r + s + [UInt8(v)]) + return Data(r + s + [UInt8(v + 27)]) } public func hex() -> String { From 17dae047bf09122109ed8484ccc5cc8b504bd949 Mon Sep 17 00:00:00 2001 From: Artur Guseinov Date: Fri, 25 Nov 2022 15:18:16 +0500 Subject: [PATCH 08/30] GH token from secrets --- .github/workflows/set-user-agent.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/set-user-agent.yml b/.github/workflows/set-user-agent.yml index 1919088d5..a08089f8a 100644 --- a/.github/workflows/set-user-agent.yml +++ b/.github/workflows/set-user-agent.yml @@ -17,6 +17,9 @@ jobs: runs-on: macos-latest steps: - uses: actions/checkout@v2 + with: + token: ${{ secrets.GH_TOKEN }} + - name: Set User Agent shell: bash run: ./.github/scripts/set-user-agent.sh From d0704e40219b3ccc4f8894c8a5e13b03ac76f3e4 Mon Sep 17 00:00:00 2001 From: Artur Guseinov Date: Tue, 29 Nov 2022 16:48:42 +0500 Subject: [PATCH 09/30] AuthSignerFactory --- Example/DApp/SceneDelegate.swift | 2 +- Example/DApp/SignerFactory.swift | 4 ++-- Example/ExampleApp.xcodeproj/project.pbxproj | 8 ++++---- Example/IntegrationTests/Auth/AuthTests.swift | 4 ++-- .../IntegrationTests/Auth/Signer/CacaoSignerTests.swift | 2 +- .../Auth/Signer/EIP1271VerifierTests.swift | 4 ++-- .../Auth/Signer/EIP191VerifierTests.swift | 2 +- Example/IntegrationTests/Auth/Signer/SignerTests.swift | 2 +- Example/IntegrationTests/Stubs/SignerFactory.swift | 4 ++-- .../Configurator/ThirdPartyConfigurator.swift | 2 +- ...tichainSignerFactory.swift => AuthSignerFactory.swift} | 4 ++-- .../Wallet/AuthRequest/AuthRequestInteractor.swift | 2 +- Sources/Auth/Auth.swift | 4 ++-- Sources/Auth/Services/Signer/MessageSignerFactory.swift | 6 +++--- Sources/Auth/Services/Signer/SignerFactory.swift | 2 +- Tests/AuthTests/Mocks/SignerFactoryMock.swift | 2 +- 16 files changed, 27 insertions(+), 27 deletions(-) rename Example/Showcase/Classes/DomainLayer/SignerFactory/{MultichainSignerFactory.swift => AuthSignerFactory.swift} (90%) diff --git a/Example/DApp/SceneDelegate.swift b/Example/DApp/SceneDelegate.swift index 6513b9940..2a76d1510 100644 --- a/Example/DApp/SceneDelegate.swift +++ b/Example/DApp/SceneDelegate.swift @@ -21,7 +21,7 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { Networking.configure(projectId: InputConfig.projectId, socketFactory: SocketFactory()) - Auth.configure(signerFactory: MultichainSignerFactory()) + Auth.configure(signerFactory: AuthSignerFactory()) setupWindow(scene: scene) } diff --git a/Example/DApp/SignerFactory.swift b/Example/DApp/SignerFactory.swift index b8174c2f2..b7e41afd0 100644 --- a/Example/DApp/SignerFactory.swift +++ b/Example/DApp/SignerFactory.swift @@ -3,9 +3,9 @@ import CryptoSwift import Web3 import Auth -public struct MultichainSignerFactory: SignerFactory { +public struct AuthSignerFactory: SignerFactory { - public func createEthereum() -> EthereumSigner { + public func createEthereumSigner() -> EthereumSigner { return Web3Signer() } } diff --git a/Example/ExampleApp.xcodeproj/project.pbxproj b/Example/ExampleApp.xcodeproj/project.pbxproj index 6282da0e0..0e5e0c329 100644 --- a/Example/ExampleApp.xcodeproj/project.pbxproj +++ b/Example/ExampleApp.xcodeproj/project.pbxproj @@ -57,6 +57,7 @@ A51AC0D928E436A3001BACF9 /* InputConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = A51AC0D828E436A3001BACF9 /* InputConfig.swift */; }; A51AC0DD28E43727001BACF9 /* InputConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = A51AC0DB28E436E6001BACF9 /* InputConfig.swift */; }; A51AC0DF28E4379F001BACF9 /* InputConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = A51AC0DE28E4379F001BACF9 /* InputConfig.swift */; }; + A51BD530293628D400484060 /* AuthSignerFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = A51BD52F293628D400484060 /* AuthSignerFactory.swift */; }; A541959E2934BFEF0035AD19 /* CacaoSignerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A541959A2934BFEF0035AD19 /* CacaoSignerTests.swift */; }; A541959F2934BFEF0035AD19 /* SignerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A541959B2934BFEF0035AD19 /* SignerTests.swift */; }; A54195A02934BFEF0035AD19 /* EIP1271VerifierTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A541959C2934BFEF0035AD19 /* EIP1271VerifierTests.swift */; }; @@ -187,7 +188,6 @@ A5E22D222840C8D300E36487 /* WalletEngine.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5E22D212840C8D300E36487 /* WalletEngine.swift */; }; A5E22D242840C8DB00E36487 /* SafariEngine.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5E22D232840C8DB00E36487 /* SafariEngine.swift */; }; A5E22D2C2840EAC300E36487 /* XCUIElement.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5E22D2B2840EAC300E36487 /* XCUIElement.swift */; }; - A5EA27542930D7830094D272 /* MultichainSignerFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5EA27532930D7830094D272 /* MultichainSignerFactory.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -262,6 +262,7 @@ A51AC0D828E436A3001BACF9 /* InputConfig.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InputConfig.swift; sourceTree = ""; }; A51AC0DB28E436E6001BACF9 /* InputConfig.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InputConfig.swift; sourceTree = ""; }; A51AC0DE28E4379F001BACF9 /* InputConfig.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InputConfig.swift; sourceTree = ""; }; + A51BD52F293628D400484060 /* AuthSignerFactory.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AuthSignerFactory.swift; sourceTree = ""; }; A541959A2934BFEF0035AD19 /* CacaoSignerTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CacaoSignerTests.swift; sourceTree = ""; }; A541959B2934BFEF0035AD19 /* SignerTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SignerTests.swift; sourceTree = ""; }; A541959C2934BFEF0035AD19 /* EIP1271VerifierTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EIP1271VerifierTests.swift; sourceTree = ""; }; @@ -381,7 +382,6 @@ A5E22D212840C8D300E36487 /* WalletEngine.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WalletEngine.swift; sourceTree = ""; }; A5E22D232840C8DB00E36487 /* SafariEngine.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SafariEngine.swift; sourceTree = ""; }; A5E22D2B2840EAC300E36487 /* XCUIElement.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = XCUIElement.swift; sourceTree = ""; }; - A5EA27532930D7830094D272 /* MultichainSignerFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MultichainSignerFactory.swift; sourceTree = ""; }; A5F48A0528E43D3F0034CBFB /* Configuration.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Configuration.xcconfig; path = ../Configuration.xcconfig; sourceTree = ""; }; /* End PBXFileReference section */ @@ -1163,7 +1163,7 @@ A5EA27522930D7760094D272 /* SignerFactory */ = { isa = PBXGroup; children = ( - A5EA27532930D7830094D272 /* MultichainSignerFactory.swift */, + A51BD52F293628D400484060 /* AuthSignerFactory.swift */, ); path = SignerFactory; sourceTree = ""; @@ -1496,7 +1496,6 @@ A59F877128B53EA000A9CD80 /* WalletRouter.swift in Sources */, A5C20226287EB099007E3188 /* AccountNameResolver.swift in Sources */, A5C2020D287D9DEE007E3188 /* WelcomeRouter.swift in Sources */, - A5EA27542930D7830094D272 /* MultichainSignerFactory.swift in Sources */, A55CAAB328B92AFF00844382 /* ScanInteractor.swift in Sources */, A55CAABA28B92B4600844382 /* ScanTargetView.swift in Sources */, A578FA372873D8EE00AA7720 /* UIColor.swift in Sources */, @@ -1515,6 +1514,7 @@ A5629AF02877F73000094373 /* SocketFactory.swift in Sources */, A55CAAB228B92AFF00844382 /* ScanRouter.swift in Sources */, A5C20221287EA5B8007E3188 /* TextFieldView.swift in Sources */, + A51BD530293628D400484060 /* AuthSignerFactory.swift in Sources */, A5C2022B287EB89A007E3188 /* WelcomeInteractor.swift in Sources */, A5C2020C287D9DEE007E3188 /* WelcomePresenter.swift in Sources */, A58E7D1D2872A57B0082D443 /* Configurator.swift in Sources */, diff --git a/Example/IntegrationTests/Auth/AuthTests.swift b/Example/IntegrationTests/Auth/AuthTests.swift index 97a59d692..7b48e601b 100644 --- a/Example/IntegrationTests/Auth/AuthTests.swift +++ b/Example/IntegrationTests/Auth/AuthTests.swift @@ -50,7 +50,7 @@ final class AuthTests: XCTestCase { metadata: AppMetadata(name: name, description: "", url: "", icons: [""]), account: account, projectId: InputConfig.projectId, - signerFactory: MultichainSignerFactory(), + signerFactory: AuthSignerFactory(), logger: logger, keyValueStorage: keyValueStorage, keychainStorage: keychain, @@ -81,7 +81,7 @@ final class AuthTests: XCTestCase { try! await walletPairingClient.pair(uri: uri) walletAuthClient.authRequestPublisher.sink { [unowned self] request in Task(priority: .high) { - let signerFactory = MultichainSignerFactory() + let signerFactory = AuthSignerFactory() let signer = MessageSignerFactory(signerFactory: signerFactory).create(projectId: InputConfig.projectId) let signature = try! signer.sign(message: request.message, privateKey: prvKey, type: .eip191) try! await walletAuthClient.respond(requestId: request.id, signature: signature) diff --git a/Example/IntegrationTests/Auth/Signer/CacaoSignerTests.swift b/Example/IntegrationTests/Auth/Signer/CacaoSignerTests.swift index 6112a9a95..4c96a63a3 100644 --- a/Example/IntegrationTests/Auth/Signer/CacaoSignerTests.swift +++ b/Example/IntegrationTests/Auth/Signer/CacaoSignerTests.swift @@ -4,7 +4,7 @@ import XCTest class CacaoSignerTest: XCTestCase { - let signer = MessageSignerFactory(signerFactory: MultichainSignerFactory()) + let signer = MessageSignerFactory(signerFactory: AuthSignerFactory()) .create(projectId: InputConfig.projectId) let privateKey = Data(hex: "305c6cde3846927892cd32762f6120539f3ec74c9e3a16b9b798b1e85351ae2a") diff --git a/Example/IntegrationTests/Auth/Signer/EIP1271VerifierTests.swift b/Example/IntegrationTests/Auth/Signer/EIP1271VerifierTests.swift index e43f2789d..57c834f80 100644 --- a/Example/IntegrationTests/Auth/Signer/EIP1271VerifierTests.swift +++ b/Example/IntegrationTests/Auth/Signer/EIP1271VerifierTests.swift @@ -14,7 +14,7 @@ class EIP1271VerifierTests: XCTestCase { func testSuccessVerify() async throws { let httpClient = HTTPNetworkClient(host: "rpc.walletconnect.com") - let signer = MultichainSignerFactory().createEthereum() + let signer = AuthSignerFactory().createEthereumSigner() let verifier = EIP1271Verifier(projectId: InputConfig.projectId, httpClient: httpClient, signer: signer) try await verifier.verify( signature: signature, @@ -26,7 +26,7 @@ class EIP1271VerifierTests: XCTestCase { func testFailureVerify() async throws { let httpClient = HTTPNetworkClient(host: "rpc.walletconnect.com") - let signer = MultichainSignerFactory().createEthereum() + let signer = AuthSignerFactory().createEthereumSigner() let verifier = EIP1271Verifier(projectId: InputConfig.projectId, httpClient: httpClient, signer: signer) await XCTAssertThrowsErrorAsync(try await verifier.verify( diff --git a/Example/IntegrationTests/Auth/Signer/EIP191VerifierTests.swift b/Example/IntegrationTests/Auth/Signer/EIP191VerifierTests.swift index 318ea7de0..3e14c46cd 100644 --- a/Example/IntegrationTests/Auth/Signer/EIP191VerifierTests.swift +++ b/Example/IntegrationTests/Auth/Signer/EIP191VerifierTests.swift @@ -4,7 +4,7 @@ import XCTest class EIP191VerifierTests: XCTestCase { - private let verifier = EIP191Verifier(signer: MultichainSignerFactory().createEthereum()) + private let verifier = EIP191Verifier(signer: AuthSignerFactory().createEthereumSigner()) private let address = "0x15bca56b6e2728aec2532df9d436bd1600e86688" private let message = "\u{19}Ethereum Signed Message:\n7Message".data(using: .utf8)! diff --git a/Example/IntegrationTests/Auth/Signer/SignerTests.swift b/Example/IntegrationTests/Auth/Signer/SignerTests.swift index ba9a8b7e3..20e26b7fb 100644 --- a/Example/IntegrationTests/Auth/Signer/SignerTests.swift +++ b/Example/IntegrationTests/Auth/Signer/SignerTests.swift @@ -5,7 +5,7 @@ import WalletConnectRelay class SignerTest: XCTestCase { - private let signer = MultichainSignerFactory().createEthereum() + private let signer = AuthSignerFactory().createEthereumSigner() private let message = "\u{19}Ethereum Signed Message:\n7Message".data(using: .utf8)! private let privateKey = Data(hex: "305c6cde3846927892cd32762f6120539f3ec74c9e3a16b9b798b1e85351ae2a") diff --git a/Example/IntegrationTests/Stubs/SignerFactory.swift b/Example/IntegrationTests/Stubs/SignerFactory.swift index b8174c2f2..b7e41afd0 100644 --- a/Example/IntegrationTests/Stubs/SignerFactory.swift +++ b/Example/IntegrationTests/Stubs/SignerFactory.swift @@ -3,9 +3,9 @@ import CryptoSwift import Web3 import Auth -public struct MultichainSignerFactory: SignerFactory { +public struct AuthSignerFactory: SignerFactory { - public func createEthereum() -> EthereumSigner { + public func createEthereumSigner() -> EthereumSigner { return Web3Signer() } } diff --git a/Example/Showcase/Classes/ApplicationLayer/Configurator/ThirdPartyConfigurator.swift b/Example/Showcase/Classes/ApplicationLayer/Configurator/ThirdPartyConfigurator.swift index cb454420c..35e964b07 100644 --- a/Example/Showcase/Classes/ApplicationLayer/Configurator/ThirdPartyConfigurator.swift +++ b/Example/Showcase/Classes/ApplicationLayer/Configurator/ThirdPartyConfigurator.swift @@ -16,7 +16,7 @@ struct ThirdPartyConfigurator: Configurator { Auth.configure( account: Account("eip155:1:0xe5EeF1368781911d265fDB6946613dA61915a501")!, - signerFactory: MultichainSignerFactory() + signerFactory: AuthSignerFactory() ) } } diff --git a/Example/Showcase/Classes/DomainLayer/SignerFactory/MultichainSignerFactory.swift b/Example/Showcase/Classes/DomainLayer/SignerFactory/AuthSignerFactory.swift similarity index 90% rename from Example/Showcase/Classes/DomainLayer/SignerFactory/MultichainSignerFactory.swift rename to Example/Showcase/Classes/DomainLayer/SignerFactory/AuthSignerFactory.swift index b8174c2f2..b7e41afd0 100644 --- a/Example/Showcase/Classes/DomainLayer/SignerFactory/MultichainSignerFactory.swift +++ b/Example/Showcase/Classes/DomainLayer/SignerFactory/AuthSignerFactory.swift @@ -3,9 +3,9 @@ import CryptoSwift import Web3 import Auth -public struct MultichainSignerFactory: SignerFactory { +public struct AuthSignerFactory: SignerFactory { - public func createEthereum() -> EthereumSigner { + public func createEthereumSigner() -> EthereumSigner { return Web3Signer() } } diff --git a/Example/Showcase/Classes/PresentationLayer/Wallet/AuthRequest/AuthRequestInteractor.swift b/Example/Showcase/Classes/PresentationLayer/Wallet/AuthRequest/AuthRequestInteractor.swift index 29ea3a477..5ed599c26 100644 --- a/Example/Showcase/Classes/PresentationLayer/Wallet/AuthRequest/AuthRequestInteractor.swift +++ b/Example/Showcase/Classes/PresentationLayer/Wallet/AuthRequest/AuthRequestInteractor.swift @@ -6,7 +6,7 @@ final class AuthRequestInteractor { func approve(request: AuthRequest) async throws { let privateKey = Data(hex: "e56da0e170b5e09a8bb8f1b693392c7d56c3739a9c75740fbc558a2877868540") - let signer = MessageSignerFactory(signerFactory: MultichainSignerFactory()).create() + let signer = MessageSignerFactory(signerFactory: AuthSignerFactory()).create() let signature = try signer.sign(message: request.message, privateKey: privateKey, type: .eip191) try await Auth.instance.respond(requestId: request.id, signature: signature) } diff --git a/Sources/Auth/Auth.swift b/Sources/Auth/Auth.swift index 26e31bc78..0f0c4c4f8 100644 --- a/Sources/Auth/Auth.swift +++ b/Sources/Auth/Auth.swift @@ -36,14 +36,14 @@ public class Auth { /// Auth instance wallet config method. For Wallet usage /// - Parameters: /// - account: account that wallet will be authenticating with. - /// - signerFactory: Multichain signers factory + /// - signerFactory: Auth signers factory static public func configure(account: Account, signerFactory: SignerFactory) { Auth.config = Auth.Config(account: account, signerFactory: signerFactory) } /// Auth instance wallet config method. For DApp usage /// - Parameters: - /// - signerFactory: Multichain signers factory + /// - signerFactory: Auth signers factory static public func configure(signerFactory: SignerFactory) { Auth.config = Auth.Config(account: nil, signerFactory: signerFactory) } diff --git a/Sources/Auth/Services/Signer/MessageSignerFactory.swift b/Sources/Auth/Services/Signer/MessageSignerFactory.swift index 314b20fc9..7441b2f16 100644 --- a/Sources/Auth/Services/Signer/MessageSignerFactory.swift +++ b/Sources/Auth/Services/Signer/MessageSignerFactory.swift @@ -14,12 +14,12 @@ public struct MessageSignerFactory { func create(projectId: String) -> MessageSigning & MessageSignatureVerifying { return MessageSigner( - signer: signerFactory.createEthereum(), - eip191Verifier: EIP191Verifier(signer: signerFactory.createEthereum()), + signer: signerFactory.createEthereumSigner(), + eip191Verifier: EIP191Verifier(signer: signerFactory.createEthereumSigner()), eip1271Verifier: EIP1271Verifier( projectId: projectId, httpClient: HTTPNetworkClient(host: "rpc.walletconnect.com"), - signer: signerFactory.createEthereum() + signer: signerFactory.createEthereumSigner() ) ) } diff --git a/Sources/Auth/Services/Signer/SignerFactory.swift b/Sources/Auth/Services/Signer/SignerFactory.swift index 080cf9f89..8f26baf15 100644 --- a/Sources/Auth/Services/Signer/SignerFactory.swift +++ b/Sources/Auth/Services/Signer/SignerFactory.swift @@ -1,5 +1,5 @@ import Foundation public protocol SignerFactory { - func createEthereum() -> EthereumSigner + func createEthereumSigner() -> EthereumSigner } diff --git a/Tests/AuthTests/Mocks/SignerFactoryMock.swift b/Tests/AuthTests/Mocks/SignerFactoryMock.swift index 9d9246de4..f8110b951 100644 --- a/Tests/AuthTests/Mocks/SignerFactoryMock.swift +++ b/Tests/AuthTests/Mocks/SignerFactoryMock.swift @@ -3,7 +3,7 @@ import Auth struct SignerFactoryMock: SignerFactory { - func createEthereum() -> EthereumSigner { + func createEthereumSigner() -> EthereumSigner { return EthereumSignerMock() } } From 0d9eb196e1cf972370f2e1136bf85c4890c47671 Mon Sep 17 00:00:00 2001 From: Artur Guseinov Date: Wed, 30 Nov 2022 16:29:02 +0500 Subject: [PATCH 10/30] Update README.md --- README.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/README.md b/README.md index 32b7736dd..3b269c948 100644 --- a/README.md +++ b/README.md @@ -25,6 +25,16 @@ dependencies: [ .package(url: "https://github.com/WalletConnect/WalletConnectSwiftV2", .branch("main")), ], ``` +### Cocoapods +Add pod to your Podfile: + +```Ruby +pod 'WalletConnectSwiftV2' +``` +If you encounter any problems during package installation, you can specify the exact path to the repository +```Ruby +pod 'WalletConnectSwiftV2', :git => 'https://github.com/WalletConnect/WalletConnectSwiftV2.git', :tag => '1.0.5' +``` ## Setting Project ID Follow instructions from *Configuration.xcconfig* and configure PROJECT_ID with your ID from WalletConnect Dashboard ``` From 174d3c3961d278435aed7547123d8acad0386678 Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Wed, 9 Nov 2022 11:51:40 +0100 Subject: [PATCH 11/30] savepoint --- .../xcschemes/WalletConnectVerify.xcscheme | 67 +++++++++++++++++++ Package.swift | 8 ++- .../WalletConnectVerify/VerifyClient.swift | 50 ++++++++++++++ 3 files changed, 124 insertions(+), 1 deletion(-) create mode 100644 .swiftpm/xcode/xcshareddata/xcschemes/WalletConnectVerify.xcscheme create mode 100644 Sources/WalletConnectVerify/VerifyClient.swift diff --git a/.swiftpm/xcode/xcshareddata/xcschemes/WalletConnectVerify.xcscheme b/.swiftpm/xcode/xcshareddata/xcschemes/WalletConnectVerify.xcscheme new file mode 100644 index 000000000..b5ef0e1c9 --- /dev/null +++ b/.swiftpm/xcode/xcshareddata/xcschemes/WalletConnectVerify.xcscheme @@ -0,0 +1,67 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Package.swift b/Package.swift index 5ea3fe03c..a122ebad5 100644 --- a/Package.swift +++ b/Package.swift @@ -30,7 +30,10 @@ let package = Package( targets: ["WalletConnectRouter"]), .library( name: "WalletConnectNetworking", - targets: ["WalletConnectNetworking"]) + targets: ["WalletConnectNetworking"]), + .library( + name: "WalletConnectVerify", + targets: ["WalletConnectVerify"]) ], dependencies: [ .package(url: "https://github.com/WalletConnect/Web3.swift", .exact("1.0.0")) @@ -79,6 +82,9 @@ let package = Package( .target( name: "WalletConnectRouter", dependencies: []), + .target( + name: "WalletConnectVerify", + dependencies: []), .testTarget( name: "WalletConnectSignTests", dependencies: ["WalletConnectSign", "TestingUtils"]), diff --git a/Sources/WalletConnectVerify/VerifyClient.swift b/Sources/WalletConnectVerify/VerifyClient.swift new file mode 100644 index 000000000..f2dfc2064 --- /dev/null +++ b/Sources/WalletConnectVerify/VerifyClient.swift @@ -0,0 +1,50 @@ + +import Foundation + +public class VerifyClient { + + + public func verifyOrigin() async throws { + + } + + public func registerAttestation() async throws { + + } + + public func registerOriginProof() async throws { + + } + +} + +import DeviceCheck +import WalletConnectUtils + +@available(iOS 14.0, *) +@available(macOS 11.0, *) +class AppAttestationRegistrer { + enum Errors: Error { + case attestationNotSupported + } + private let service: DCAppAttestService + private let logger: ConsoleLogging + + init(logger: ConsoleLogging) throws { + self.service = DCAppAttestService.shared + self.logger = logger + if !service.isSupported { + throw Errors.attestationNotSupported + } + // TODO - check if attestation already performed + generateKeys() + } + + private func generateKeys() { + service.generateKey { keyId, error in + guard error == nil else {logger.debug } + + // Cache keyId for subsequent operations. + } + } +} From d039b89140b0e1eee9ef7e46a34be8941b1d0705 Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Thu, 10 Nov 2022 09:21:35 +0100 Subject: [PATCH 12/30] savepoint --- Package.swift | 2 +- .../AppAttestationRegistrer.swift | 94 +++++++++++++++++++ .../AssertionRegistrer.swift | 6 ++ .../WalletConnectVerify/OriginVerifier.swift | 7 ++ .../WalletConnectVerify/VerifyClient.swift | 50 ++++------ 5 files changed, 124 insertions(+), 35 deletions(-) create mode 100644 Sources/WalletConnectVerify/AppAttestationRegistrer.swift create mode 100644 Sources/WalletConnectVerify/AssertionRegistrer.swift create mode 100644 Sources/WalletConnectVerify/OriginVerifier.swift diff --git a/Package.swift b/Package.swift index a122ebad5..645b135b7 100644 --- a/Package.swift +++ b/Package.swift @@ -84,7 +84,7 @@ let package = Package( dependencies: []), .target( name: "WalletConnectVerify", - dependencies: []), + dependencies: ["WalletConnectUtils"]), .testTarget( name: "WalletConnectSignTests", dependencies: ["WalletConnectSign", "TestingUtils"]), diff --git a/Sources/WalletConnectVerify/AppAttestationRegistrer.swift b/Sources/WalletConnectVerify/AppAttestationRegistrer.swift new file mode 100644 index 000000000..7bd3d9a51 --- /dev/null +++ b/Sources/WalletConnectVerify/AppAttestationRegistrer.swift @@ -0,0 +1,94 @@ +import Foundation +import DeviceCheck +import WalletConnectUtils + +@available(iOS 14.0, *) +@available(macOS 11.0, *) +class AppAttestationRegistrer { + enum Errors: Error { + case attestationNotSupported + } + private let service: DCAppAttestService + private let logger: ConsoleLogging + + let AttestKeyGenerator: AttestKeyGenerator + let AttestChallengeProvider: AttestChallengeProvider + let KeyAttestationService: KeyAttestationService + + init(logger: ConsoleLogging) throws { + self.service = DCAppAttestService.shared + self.logger = logger + if !service.isSupported { + throw Errors.attestationNotSupported + } + // TODO - check if attestation already performed + generateKeys() + } + + func registerAttestation() async throws { + + } + + private func generateKeys() { + + } + + private func getChallenge() { + + } + + private func attestKey() { + + } +} + +protocol AttestKeyGenerating { + func generateKeys() -> String +} + +class AttestKeyGenerator: AttestKeyGenerating { + func generateKeys() -> String { +// service.generateKey { [unowned self] keyId, error in +// guard error == nil else { +// logger.debug(error!.localizedDescription) +// return +// } +// +// // Cache keyId for subsequent operations. +// } + fatalError("not implemented") + } + + +} +protocol AttestChallengeProviding { + func getChallenge() async throws -> String +} + +class AttestChallengeProvider: AttestChallengeProviding { + func getChallenge() async throws -> String { + fatalError("not implemented") + } +} + +protocol KeyAttesting { + + func attestKey(keyId: String, clientDataHash: String) +} + +class KeyAttestationService: KeyAttesting { + // If the method, which accesses a remote Apple server, returns the serverUnavailable error, try attestation again later with the same key. For any other error, discard the key identifier and create a new key when you want to try again. Otherwise, send the completion handler’s attestation object and the keyId to your server for processing. + func attestKey(keyId: String, clientDataHash: String) { + fatalError("not implemented") + + service.attestKey(keyId, clientDataHash: hash) { attestation, error in + guard error == nil else { /* Handle error and return. */ } + + // Send the attestation object to your server for verification. + } + let attestationString = attestation?.base64EncodedString() + + } + + +} diff --git a/Sources/WalletConnectVerify/AssertionRegistrer.swift b/Sources/WalletConnectVerify/AssertionRegistrer.swift new file mode 100644 index 000000000..2cf2289ad --- /dev/null +++ b/Sources/WalletConnectVerify/AssertionRegistrer.swift @@ -0,0 +1,6 @@ + +import Foundation + +class AssertionRegistrer { + func registerAssertion() async throws {} +} diff --git a/Sources/WalletConnectVerify/OriginVerifier.swift b/Sources/WalletConnectVerify/OriginVerifier.swift new file mode 100644 index 000000000..de33c5fff --- /dev/null +++ b/Sources/WalletConnectVerify/OriginVerifier.swift @@ -0,0 +1,7 @@ + +import Foundation + +class OriginVerifier { + func verifyOrigin() async throws {} +} + diff --git a/Sources/WalletConnectVerify/VerifyClient.swift b/Sources/WalletConnectVerify/VerifyClient.swift index f2dfc2064..1941c0481 100644 --- a/Sources/WalletConnectVerify/VerifyClient.swift +++ b/Sources/WalletConnectVerify/VerifyClient.swift @@ -1,8 +1,21 @@ import Foundation -public class VerifyClient { - +@available(iOS 14.0, *) +@available(macOS 11.0, *) +public actor VerifyClient { + + let originVerifier: OriginVerifier + let assertionRegistrer: AssertionRegistrer + let appAttestationRegistrer: AppAttestationRegistrer + + init(originVerifier: OriginVerifier, + assertionRegistrer: AssertionRegistrer, + appAttestationRegistrer: AppAttestationRegistrer) { + self.originVerifier = originVerifier + self.assertionRegistrer = assertionRegistrer + self.appAttestationRegistrer = appAttestationRegistrer + } public func verifyOrigin() async throws { @@ -12,39 +25,8 @@ public class VerifyClient { } - public func registerOriginProof() async throws { + public func registerAssertion() async throws { } } - -import DeviceCheck -import WalletConnectUtils - -@available(iOS 14.0, *) -@available(macOS 11.0, *) -class AppAttestationRegistrer { - enum Errors: Error { - case attestationNotSupported - } - private let service: DCAppAttestService - private let logger: ConsoleLogging - - init(logger: ConsoleLogging) throws { - self.service = DCAppAttestService.shared - self.logger = logger - if !service.isSupported { - throw Errors.attestationNotSupported - } - // TODO - check if attestation already performed - generateKeys() - } - - private func generateKeys() { - service.generateKey { keyId, error in - guard error == nil else {logger.debug } - - // Cache keyId for subsequent operations. - } - } -} From 1522993a13c3fcf45110bb7e7c61254791855567 Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Thu, 10 Nov 2022 13:04:22 +0100 Subject: [PATCH 13/30] split files --- .../AppAttestationRegistrer.swift | 64 ++----------------- .../AttestChallengeProvider.swift | 11 ++++ .../AttestKeyGenerator.swift | 24 +++++++ .../KeyAttestationService.swift | 24 +++++++ .../WalletConnectVerify/VerifyClient.swift | 11 +++- 5 files changed, 71 insertions(+), 63 deletions(-) create mode 100644 Sources/WalletConnectVerify/AttestChallengeProvider.swift create mode 100644 Sources/WalletConnectVerify/AttestKeyGenerator.swift create mode 100644 Sources/WalletConnectVerify/KeyAttestationService.swift diff --git a/Sources/WalletConnectVerify/AppAttestationRegistrer.swift b/Sources/WalletConnectVerify/AppAttestationRegistrer.swift index 7bd3d9a51..f2a48bcad 100644 --- a/Sources/WalletConnectVerify/AppAttestationRegistrer.swift +++ b/Sources/WalletConnectVerify/AppAttestationRegistrer.swift @@ -5,22 +5,17 @@ import WalletConnectUtils @available(iOS 14.0, *) @available(macOS 11.0, *) class AppAttestationRegistrer { - enum Errors: Error { - case attestationNotSupported - } + private let service: DCAppAttestService private let logger: ConsoleLogging - let AttestKeyGenerator: AttestKeyGenerator - let AttestChallengeProvider: AttestChallengeProvider - let KeyAttestationService: KeyAttestationService + let AttestKeyGenerator: AttestKeyGenerating + let AttestChallengeProvider: AttestChallengeProviding + let KeyAttestationService: KeyAttesting init(logger: ConsoleLogging) throws { self.service = DCAppAttestService.shared self.logger = logger - if !service.isSupported { - throw Errors.attestationNotSupported - } // TODO - check if attestation already performed generateKeys() } @@ -41,54 +36,3 @@ class AppAttestationRegistrer { } } - -protocol AttestKeyGenerating { - func generateKeys() -> String -} - -class AttestKeyGenerator: AttestKeyGenerating { - func generateKeys() -> String { -// service.generateKey { [unowned self] keyId, error in -// guard error == nil else { -// logger.debug(error!.localizedDescription) -// return -// } -// -// // Cache keyId for subsequent operations. -// } - fatalError("not implemented") - } - - -} -protocol AttestChallengeProviding { - func getChallenge() async throws -> String -} - -class AttestChallengeProvider: AttestChallengeProviding { - func getChallenge() async throws -> String { - fatalError("not implemented") - } -} - -protocol KeyAttesting { - - func attestKey(keyId: String, clientDataHash: String) -} - -class KeyAttestationService: KeyAttesting { - // If the method, which accesses a remote Apple server, returns the serverUnavailable error, try attestation again later with the same key. For any other error, discard the key identifier and create a new key when you want to try again. Otherwise, send the completion handler’s attestation object and the keyId to your server for processing. - func attestKey(keyId: String, clientDataHash: String) { - fatalError("not implemented") - - service.attestKey(keyId, clientDataHash: hash) { attestation, error in - guard error == nil else { /* Handle error and return. */ } - - // Send the attestation object to your server for verification. - } - let attestationString = attestation?.base64EncodedString() - - } - - -} diff --git a/Sources/WalletConnectVerify/AttestChallengeProvider.swift b/Sources/WalletConnectVerify/AttestChallengeProvider.swift new file mode 100644 index 000000000..d74f5ee22 --- /dev/null +++ b/Sources/WalletConnectVerify/AttestChallengeProvider.swift @@ -0,0 +1,11 @@ +import Foundation + +protocol AttestChallengeProviding { + func getChallenge() async throws -> String +} + +class AttestChallengeProvider: AttestChallengeProviding { + func getChallenge() async throws -> String { + fatalError("not implemented") + } +} diff --git a/Sources/WalletConnectVerify/AttestKeyGenerator.swift b/Sources/WalletConnectVerify/AttestKeyGenerator.swift new file mode 100644 index 000000000..5a908703a --- /dev/null +++ b/Sources/WalletConnectVerify/AttestKeyGenerator.swift @@ -0,0 +1,24 @@ +import DeviceCheck +import Foundation + +protocol AttestKeyGenerating { + func generateKeys() -> String +} + +@available(iOS 14.0, *) +@available(macOS 11.0, *) +class AttestKeyGenerator: AttestKeyGenerating { + private let service = DCAppAttestService.shared + + func generateKeys() -> String { + service.generateKey { [unowned self] keyId, error in + guard error == nil else { + logger.debug(error!.localizedDescription) + return + } + + // Cache keyId for subsequent operations. + } + fatalError("not implemented") + } +} diff --git a/Sources/WalletConnectVerify/KeyAttestationService.swift b/Sources/WalletConnectVerify/KeyAttestationService.swift new file mode 100644 index 000000000..cd5c15f16 --- /dev/null +++ b/Sources/WalletConnectVerify/KeyAttestationService.swift @@ -0,0 +1,24 @@ +import Foundation +import DeviceCheck + +protocol KeyAttesting { + func attestKey(keyId: String, clientDataHash: String) +} + +@available(iOS 14.0, *) +@available(macOS 11.0, *) +class KeyAttestationService: KeyAttesting { + private let service = DCAppAttestService.shared + // If the method, which accesses a remote Apple server, returns the serverUnavailable error, try attestation again later with the same key. For any other error, discard the key identifier and create a new key when you want to try again. Otherwise, send the completion handler’s attestation object and the keyId to your server for processing. + func attestKey(keyId: String, clientDataHash: String) { + fatalError("not implemented") + + service.attestKey(keyId, clientDataHash: hash) { attestation, error in + guard error == nil else { /* Handle error and return. */ } + + // Send the attestation object to your server for verification. + } + let attestationString = attestation?.base64EncodedString() + + } +} diff --git a/Sources/WalletConnectVerify/VerifyClient.swift b/Sources/WalletConnectVerify/VerifyClient.swift index 1941c0481..c629fdc57 100644 --- a/Sources/WalletConnectVerify/VerifyClient.swift +++ b/Sources/WalletConnectVerify/VerifyClient.swift @@ -1,17 +1,22 @@ - +import DeviceCheck import Foundation @available(iOS 14.0, *) @available(macOS 11.0, *) public actor VerifyClient { - + enum Errors: Error { + case attestationNotSupported + } let originVerifier: OriginVerifier let assertionRegistrer: AssertionRegistrer let appAttestationRegistrer: AppAttestationRegistrer init(originVerifier: OriginVerifier, assertionRegistrer: AssertionRegistrer, - appAttestationRegistrer: AppAttestationRegistrer) { + appAttestationRegistrer: AppAttestationRegistrer) throws { + if !DCAppAttestService.shared.isSupported { + throw Errors.attestationNotSupported + } self.originVerifier = originVerifier self.assertionRegistrer = assertionRegistrer self.appAttestationRegistrer = appAttestationRegistrer From ad4fb6292c5d5ec1c3ca3d14a795cfe2c157f882 Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Tue, 15 Nov 2022 08:21:08 +0100 Subject: [PATCH 14/30] implement AppAttestationRegistrer --- Package.swift | 3 ++ .../AppAttestationRegistrer.swift | 46 ++++++++++++------- .../AttestKeyGenerator.swift | 4 +- .../WalletConnectVerify/VerifyClient.swift | 11 +++-- .../AppAttestationRegistrerTests.swift | 11 +++++ 5 files changed, 51 insertions(+), 24 deletions(-) create mode 100644 Tests/VerifyTests/AppAttestationRegistrerTests.swift diff --git a/Package.swift b/Package.swift index 645b135b7..50bc98300 100644 --- a/Package.swift +++ b/Package.swift @@ -100,6 +100,9 @@ let package = Package( .testTarget( name: "RelayerTests", dependencies: ["WalletConnectRelay", "WalletConnectUtils", "TestingUtils"]), + .testTarget( + name: "VerifyTests", + dependencies: ["WalletConnectVerify"]), .testTarget( name: "WalletConnectKMSTests", dependencies: ["WalletConnectKMS", "WalletConnectUtils", "TestingUtils"]), diff --git a/Sources/WalletConnectVerify/AppAttestationRegistrer.swift b/Sources/WalletConnectVerify/AppAttestationRegistrer.swift index f2a48bcad..3a787d1fb 100644 --- a/Sources/WalletConnectVerify/AppAttestationRegistrer.swift +++ b/Sources/WalletConnectVerify/AppAttestationRegistrer.swift @@ -5,34 +5,46 @@ import WalletConnectUtils @available(iOS 14.0, *) @available(macOS 11.0, *) class AppAttestationRegistrer { - + private let keyIdStorageKey = "attested_key_id" private let service: DCAppAttestService private let logger: ConsoleLogging - - let AttestKeyGenerator: AttestKeyGenerating - let AttestChallengeProvider: AttestChallengeProviding - let KeyAttestationService: KeyAttesting - - init(logger: ConsoleLogging) throws { + private let keyIdStorage: CodableStore + + let attestKeyGenerator: AttestKeyGenerating + let attestChallengeProvider: AttestChallengeProviding + let keyAttestationService: KeyAttesting + + init(logger: ConsoleLogging, + keyIdStorage: CodableStore, + attestKeyGenerator: AttestKeyGenerating, + attestChallengeProvider: AttestChallengeProviding, + keyAttestationService: KeyAttesting + ) throws { self.service = DCAppAttestService.shared self.logger = logger - // TODO - check if attestation already performed - generateKeys() + self.keyIdStorage = keyIdStorage + self.attestKeyGenerator = attestKeyGenerator + self.attestChallengeProvider = attestChallengeProvider + self.keyAttestationService = keyAttestationService } - func registerAttestation() async throws { - + func registerAttestationIfNeeded() async throws { + guard keyIdStorage.get(key: keyIdStorageKey) == nil else { return } + let keyId = generateKeys() + let challenge = try await getChallenge() + let hash = Data(SHA256.hash(data: challenge)) + attestKey(keyId: keyId, clientDataHash: hash) } - private func generateKeys() { - + private func generateKeys() async throws -> String { + try await attestKeyGenerator.generateKeys() } - private func getChallenge() { - + private func getChallenge() async throws { + try await attestChallengeProvider.getChallenge() } - private func attestKey() { - + private func attestKey(keyId: String, clientDataHash: Data) async throws { + try await keyAttestationService.attestKey(keyId: keyId, clientDataHash: clientDataHash) } } diff --git a/Sources/WalletConnectVerify/AttestKeyGenerator.swift b/Sources/WalletConnectVerify/AttestKeyGenerator.swift index 5a908703a..8aa0f52f7 100644 --- a/Sources/WalletConnectVerify/AttestKeyGenerator.swift +++ b/Sources/WalletConnectVerify/AttestKeyGenerator.swift @@ -2,7 +2,7 @@ import DeviceCheck import Foundation protocol AttestKeyGenerating { - func generateKeys() -> String + func generateKeys() async throws -> String } @available(iOS 14.0, *) @@ -10,7 +10,7 @@ protocol AttestKeyGenerating { class AttestKeyGenerator: AttestKeyGenerating { private let service = DCAppAttestService.shared - func generateKeys() -> String { + func generateKeys() async throws -> String { service.generateKey { [unowned self] keyId, error in guard error == nil else { logger.debug(error!.localizedDescription) diff --git a/Sources/WalletConnectVerify/VerifyClient.swift b/Sources/WalletConnectVerify/VerifyClient.swift index c629fdc57..2cfc7eab3 100644 --- a/Sources/WalletConnectVerify/VerifyClient.swift +++ b/Sources/WalletConnectVerify/VerifyClient.swift @@ -22,16 +22,17 @@ public actor VerifyClient { self.appAttestationRegistrer = appAttestationRegistrer } - public func verifyOrigin() async throws { - + private func registerAttestationIfNeeded() async throws { + try await appAttestationRegistrer.registerAttestationIfNeeded()() } - public func registerAttestation() async throws { - + public func verifyOrigin() async throws { + originVerifier.verifyOrigin() } - public func registerAssertion() async throws { + public func registerAssertion() async throws { + assertionRegistrer.registerAssertion() } } diff --git a/Tests/VerifyTests/AppAttestationRegistrerTests.swift b/Tests/VerifyTests/AppAttestationRegistrerTests.swift new file mode 100644 index 000000000..b608149ec --- /dev/null +++ b/Tests/VerifyTests/AppAttestationRegistrerTests.swift @@ -0,0 +1,11 @@ + +import Foundation +import XCTest +@testable import WalletConnectVerify + +class AppAttestationRegistrer: XCTestCase { + + func testAttestation() {} + + func testAttestationAlreadyRegistered() {} +} From 9f84bb36407c7c05cccef9f20cd40171a5827f27 Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Tue, 15 Nov 2022 08:33:57 +0100 Subject: [PATCH 15/30] fix build errors --- .../WalletConnectVerify/AppAttestationRegistrer.swift | 9 +++++---- .../WalletConnectVerify/AttestChallengeProvider.swift | 4 ++-- .../WalletConnectVerify/KeyAttestationService.swift | 4 ++-- Tests/VerifyTests/AppAttestationRegistrerTests.swift | 10 +++++++++- 4 files changed, 18 insertions(+), 9 deletions(-) diff --git a/Sources/WalletConnectVerify/AppAttestationRegistrer.swift b/Sources/WalletConnectVerify/AppAttestationRegistrer.swift index 3a787d1fb..a7c59d87a 100644 --- a/Sources/WalletConnectVerify/AppAttestationRegistrer.swift +++ b/Sources/WalletConnectVerify/AppAttestationRegistrer.swift @@ -1,6 +1,7 @@ import Foundation import DeviceCheck import WalletConnectUtils +import CryptoKit @available(iOS 14.0, *) @available(macOS 11.0, *) @@ -29,18 +30,18 @@ class AppAttestationRegistrer { } func registerAttestationIfNeeded() async throws { - guard keyIdStorage.get(key: keyIdStorageKey) == nil else { return } - let keyId = generateKeys() + if let _ = try? keyIdStorage.get(key: keyIdStorageKey) { return } + let keyId = try await generateKeys() let challenge = try await getChallenge() let hash = Data(SHA256.hash(data: challenge)) - attestKey(keyId: keyId, clientDataHash: hash) + try await attestKey(keyId: keyId, clientDataHash: hash) } private func generateKeys() async throws -> String { try await attestKeyGenerator.generateKeys() } - private func getChallenge() async throws { + private func getChallenge() async throws -> Data { try await attestChallengeProvider.getChallenge() } diff --git a/Sources/WalletConnectVerify/AttestChallengeProvider.swift b/Sources/WalletConnectVerify/AttestChallengeProvider.swift index d74f5ee22..ac9a0eaa3 100644 --- a/Sources/WalletConnectVerify/AttestChallengeProvider.swift +++ b/Sources/WalletConnectVerify/AttestChallengeProvider.swift @@ -1,11 +1,11 @@ import Foundation protocol AttestChallengeProviding { - func getChallenge() async throws -> String + func getChallenge() async throws -> Data } class AttestChallengeProvider: AttestChallengeProviding { - func getChallenge() async throws -> String { + func getChallenge() async throws -> Data { fatalError("not implemented") } } diff --git a/Sources/WalletConnectVerify/KeyAttestationService.swift b/Sources/WalletConnectVerify/KeyAttestationService.swift index cd5c15f16..a27fb40e0 100644 --- a/Sources/WalletConnectVerify/KeyAttestationService.swift +++ b/Sources/WalletConnectVerify/KeyAttestationService.swift @@ -2,7 +2,7 @@ import Foundation import DeviceCheck protocol KeyAttesting { - func attestKey(keyId: String, clientDataHash: String) + func attestKey(keyId: String, clientDataHash: Data) async throws } @available(iOS 14.0, *) @@ -10,7 +10,7 @@ protocol KeyAttesting { class KeyAttestationService: KeyAttesting { private let service = DCAppAttestService.shared // If the method, which accesses a remote Apple server, returns the serverUnavailable error, try attestation again later with the same key. For any other error, discard the key identifier and create a new key when you want to try again. Otherwise, send the completion handler’s attestation object and the keyId to your server for processing. - func attestKey(keyId: String, clientDataHash: String) { + func attestKey(keyId: String, clientDataHash: Data) async throws { fatalError("not implemented") service.attestKey(keyId, clientDataHash: hash) { attestation, error in diff --git a/Tests/VerifyTests/AppAttestationRegistrerTests.swift b/Tests/VerifyTests/AppAttestationRegistrerTests.swift index b608149ec..337b9d175 100644 --- a/Tests/VerifyTests/AppAttestationRegistrerTests.swift +++ b/Tests/VerifyTests/AppAttestationRegistrerTests.swift @@ -4,8 +4,16 @@ import XCTest @testable import WalletConnectVerify class AppAttestationRegistrer: XCTestCase { + var sut: AppAttestationRegistrer! - func testAttestation() {} + override func setUp() async throws { + + sut = AppAttestationRegistrer() + } + + func testAttestation() { + + } func testAttestationAlreadyRegistered() {} } From 75256391631f447f3f4b34c2b97120e28d9b5902 Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Tue, 15 Nov 2022 09:29:29 +0100 Subject: [PATCH 16/30] add test attestation --- Package.swift | 2 +- .../AppAttestationRegistrer.swift | 2 +- .../AttestKeyGenerator.swift | 11 ++---- .../KeyAttestationService.swift | 8 ++--- .../WalletConnectVerify/VerifyClient.swift | 6 ++-- .../AppAttestationRegistrerTests.swift | 34 +++++++++++++++---- .../Mocks/AttestChallengeProvidingMock.swift | 12 +++++++ .../Mocks/AttestKeyGeneratingMock.swift | 13 +++++++ .../VerifyTests/Mocks/KeyAttestingMock.swift | 10 ++++++ 9 files changed, 72 insertions(+), 26 deletions(-) create mode 100644 Tests/VerifyTests/Mocks/AttestChallengeProvidingMock.swift create mode 100644 Tests/VerifyTests/Mocks/AttestKeyGeneratingMock.swift create mode 100644 Tests/VerifyTests/Mocks/KeyAttestingMock.swift diff --git a/Package.swift b/Package.swift index 50bc98300..2f3f29212 100644 --- a/Package.swift +++ b/Package.swift @@ -102,7 +102,7 @@ let package = Package( dependencies: ["WalletConnectRelay", "WalletConnectUtils", "TestingUtils"]), .testTarget( name: "VerifyTests", - dependencies: ["WalletConnectVerify"]), + dependencies: ["WalletConnectVerify", "TestingUtils"]), .testTarget( name: "WalletConnectKMSTests", dependencies: ["WalletConnectKMS", "WalletConnectUtils", "TestingUtils"]), diff --git a/Sources/WalletConnectVerify/AppAttestationRegistrer.swift b/Sources/WalletConnectVerify/AppAttestationRegistrer.swift index a7c59d87a..69a6d6021 100644 --- a/Sources/WalletConnectVerify/AppAttestationRegistrer.swift +++ b/Sources/WalletConnectVerify/AppAttestationRegistrer.swift @@ -20,7 +20,7 @@ class AppAttestationRegistrer { attestKeyGenerator: AttestKeyGenerating, attestChallengeProvider: AttestChallengeProviding, keyAttestationService: KeyAttesting - ) throws { + ) { self.service = DCAppAttestService.shared self.logger = logger self.keyIdStorage = keyIdStorage diff --git a/Sources/WalletConnectVerify/AttestKeyGenerator.swift b/Sources/WalletConnectVerify/AttestKeyGenerator.swift index 8aa0f52f7..804882a5b 100644 --- a/Sources/WalletConnectVerify/AttestKeyGenerator.swift +++ b/Sources/WalletConnectVerify/AttestKeyGenerator.swift @@ -11,14 +11,7 @@ class AttestKeyGenerator: AttestKeyGenerating { private let service = DCAppAttestService.shared func generateKeys() async throws -> String { - service.generateKey { [unowned self] keyId, error in - guard error == nil else { - logger.debug(error!.localizedDescription) - return - } - - // Cache keyId for subsequent operations. - } - fatalError("not implemented") + try await service.generateKey() + //TODO Cache keyId for subsequent operations. } } diff --git a/Sources/WalletConnectVerify/KeyAttestationService.swift b/Sources/WalletConnectVerify/KeyAttestationService.swift index a27fb40e0..c40ba6fea 100644 --- a/Sources/WalletConnectVerify/KeyAttestationService.swift +++ b/Sources/WalletConnectVerify/KeyAttestationService.swift @@ -11,14 +11,10 @@ class KeyAttestationService: KeyAttesting { private let service = DCAppAttestService.shared // If the method, which accesses a remote Apple server, returns the serverUnavailable error, try attestation again later with the same key. For any other error, discard the key identifier and create a new key when you want to try again. Otherwise, send the completion handler’s attestation object and the keyId to your server for processing. func attestKey(keyId: String, clientDataHash: Data) async throws { - fatalError("not implemented") - service.attestKey(keyId, clientDataHash: hash) { attestation, error in - guard error == nil else { /* Handle error and return. */ } + try await service.attestKey(keyId, clientDataHash: clientDataHash) - // Send the attestation object to your server for verification. - } - let attestationString = attestation?.base64EncodedString() + //TODO - Send the attestation object to your server for verification. handle errors } } diff --git a/Sources/WalletConnectVerify/VerifyClient.swift b/Sources/WalletConnectVerify/VerifyClient.swift index 2cfc7eab3..bb03a3aac 100644 --- a/Sources/WalletConnectVerify/VerifyClient.swift +++ b/Sources/WalletConnectVerify/VerifyClient.swift @@ -23,16 +23,16 @@ public actor VerifyClient { } private func registerAttestationIfNeeded() async throws { - try await appAttestationRegistrer.registerAttestationIfNeeded()() + try await appAttestationRegistrer.registerAttestationIfNeeded() } public func verifyOrigin() async throws { - originVerifier.verifyOrigin() + try await originVerifier.verifyOrigin() } public func registerAssertion() async throws { - assertionRegistrer.registerAssertion() + try await assertionRegistrer.registerAssertion() } } diff --git a/Tests/VerifyTests/AppAttestationRegistrerTests.swift b/Tests/VerifyTests/AppAttestationRegistrerTests.swift index 337b9d175..b3c0f9632 100644 --- a/Tests/VerifyTests/AppAttestationRegistrerTests.swift +++ b/Tests/VerifyTests/AppAttestationRegistrerTests.swift @@ -1,19 +1,41 @@ import Foundation import XCTest +import WalletConnectUtils +import TestingUtils @testable import WalletConnectVerify -class AppAttestationRegistrer: XCTestCase { +@available(iOS 14.0, *) +@available(macOS 11.0, *) +class AppAttestationRegistrerTests: XCTestCase { + var attestKeyGenerator: AttestKeyGeneratingMock! + var attestChallengeProvider: AttestChallengeProvidingMock! + var keyAttestationService: KeyAttestingMock! var sut: AppAttestationRegistrer! - override func setUp() async throws { + override func setUp() { + let kvStorage = RuntimeKeyValueStorage() - sut = AppAttestationRegistrer() - } + attestKeyGenerator = AttestKeyGeneratingMock() + attestChallengeProvider = AttestChallengeProvidingMock() + keyAttestationService = KeyAttestingMock() - func testAttestation() { + sut = AppAttestationRegistrer( + logger: ConsoleLoggerMock(), + keyIdStorage: CodableStore(defaults: kvStorage, identifier: ""), + attestKeyGenerator: attestKeyGenerator, + attestChallengeProvider: attestChallengeProvider, + keyAttestationService: keyAttestationService) + } + func testAttestation() async { + try! await sut.registerAttestationIfNeeded() + XCTAssertTrue(attestKeyGenerator.keysGenerated) + XCTAssertTrue(attestChallengeProvider.challengeProvided) + XCTAssertTrue(keyAttestationService.keyAttested) } - func testAttestationAlreadyRegistered() {} + func testAttestationAlreadyRegistered() { + + } } diff --git a/Tests/VerifyTests/Mocks/AttestChallengeProvidingMock.swift b/Tests/VerifyTests/Mocks/AttestChallengeProvidingMock.swift new file mode 100644 index 000000000..4ef7852dc --- /dev/null +++ b/Tests/VerifyTests/Mocks/AttestChallengeProvidingMock.swift @@ -0,0 +1,12 @@ +// + +import Foundation +@testable import WalletConnectVerify + +class AttestChallengeProvidingMock: AttestChallengeProviding { + var challengeProvided = false + func getChallenge() async throws -> Data { + challengeProvided = true + return Data() + } +} diff --git a/Tests/VerifyTests/Mocks/AttestKeyGeneratingMock.swift b/Tests/VerifyTests/Mocks/AttestKeyGeneratingMock.swift new file mode 100644 index 000000000..1bbe31c7a --- /dev/null +++ b/Tests/VerifyTests/Mocks/AttestKeyGeneratingMock.swift @@ -0,0 +1,13 @@ +// + +import Foundation +@testable import WalletConnectVerify + + +class AttestKeyGeneratingMock: AttestKeyGenerating { + var keysGenerated = false + func generateKeys() async throws -> String { + keysGenerated = true + return "" + } +} diff --git a/Tests/VerifyTests/Mocks/KeyAttestingMock.swift b/Tests/VerifyTests/Mocks/KeyAttestingMock.swift new file mode 100644 index 000000000..63398e336 --- /dev/null +++ b/Tests/VerifyTests/Mocks/KeyAttestingMock.swift @@ -0,0 +1,10 @@ +// +@testable import WalletConnectVerify +import Foundation + +class KeyAttestingMock: KeyAttesting { + var keyAttested = false + func attestKey(keyId: String, clientDataHash: Data) async throws { + keyAttested = true + } +} From 1e1cda03c74330184b4eba6b4f53ff7d6d319dd1 Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Tue, 15 Nov 2022 09:37:06 +0100 Subject: [PATCH 17/30] update tests --- .../AppAttestationRegistrer.swift | 1 + Tests/VerifyTests/AppAttestationRegistrerTests.swift | 12 +++++++++--- .../Mocks/AttestChallengeProvidingMock.swift | 1 - .../VerifyTests/Mocks/AttestKeyGeneratingMock.swift | 1 - Tests/VerifyTests/Mocks/KeyAttestingMock.swift | 1 - 5 files changed, 10 insertions(+), 6 deletions(-) diff --git a/Sources/WalletConnectVerify/AppAttestationRegistrer.swift b/Sources/WalletConnectVerify/AppAttestationRegistrer.swift index 69a6d6021..3d263d76b 100644 --- a/Sources/WalletConnectVerify/AppAttestationRegistrer.swift +++ b/Sources/WalletConnectVerify/AppAttestationRegistrer.swift @@ -31,6 +31,7 @@ class AppAttestationRegistrer { func registerAttestationIfNeeded() async throws { if let _ = try? keyIdStorage.get(key: keyIdStorageKey) { return } + print(keyIdStorage.getAll()) let keyId = try await generateKeys() let challenge = try await getChallenge() let hash = Data(SHA256.hash(data: challenge)) diff --git a/Tests/VerifyTests/AppAttestationRegistrerTests.swift b/Tests/VerifyTests/AppAttestationRegistrerTests.swift index b3c0f9632..e1e81bc40 100644 --- a/Tests/VerifyTests/AppAttestationRegistrerTests.swift +++ b/Tests/VerifyTests/AppAttestationRegistrerTests.swift @@ -12,17 +12,19 @@ class AppAttestationRegistrerTests: XCTestCase { var attestChallengeProvider: AttestChallengeProvidingMock! var keyAttestationService: KeyAttestingMock! var sut: AppAttestationRegistrer! + var keyIdStorage: CodableStore! override func setUp() { let kvStorage = RuntimeKeyValueStorage() + keyIdStorage = CodableStore(defaults: kvStorage, identifier: "") attestKeyGenerator = AttestKeyGeneratingMock() attestChallengeProvider = AttestChallengeProvidingMock() keyAttestationService = KeyAttestingMock() sut = AppAttestationRegistrer( logger: ConsoleLoggerMock(), - keyIdStorage: CodableStore(defaults: kvStorage, identifier: ""), + keyIdStorage: keyIdStorage, attestKeyGenerator: attestKeyGenerator, attestChallengeProvider: attestChallengeProvider, keyAttestationService: keyAttestationService) @@ -35,7 +37,11 @@ class AppAttestationRegistrerTests: XCTestCase { XCTAssertTrue(keyAttestationService.keyAttested) } - func testAttestationAlreadyRegistered() { - + func testAttestationAlreadyRegistered() async { + keyIdStorage.set("123", forKey: "attested_key_id") + try! await sut.registerAttestationIfNeeded() + XCTAssertFalse(attestKeyGenerator.keysGenerated) + XCTAssertFalse(attestChallengeProvider.challengeProvided) + XCTAssertFalse(keyAttestationService.keyAttested) } } diff --git a/Tests/VerifyTests/Mocks/AttestChallengeProvidingMock.swift b/Tests/VerifyTests/Mocks/AttestChallengeProvidingMock.swift index 4ef7852dc..1bc958055 100644 --- a/Tests/VerifyTests/Mocks/AttestChallengeProvidingMock.swift +++ b/Tests/VerifyTests/Mocks/AttestChallengeProvidingMock.swift @@ -1,4 +1,3 @@ -// import Foundation @testable import WalletConnectVerify diff --git a/Tests/VerifyTests/Mocks/AttestKeyGeneratingMock.swift b/Tests/VerifyTests/Mocks/AttestKeyGeneratingMock.swift index 1bbe31c7a..a44916d56 100644 --- a/Tests/VerifyTests/Mocks/AttestKeyGeneratingMock.swift +++ b/Tests/VerifyTests/Mocks/AttestKeyGeneratingMock.swift @@ -1,4 +1,3 @@ -// import Foundation @testable import WalletConnectVerify diff --git a/Tests/VerifyTests/Mocks/KeyAttestingMock.swift b/Tests/VerifyTests/Mocks/KeyAttestingMock.swift index 63398e336..d68057125 100644 --- a/Tests/VerifyTests/Mocks/KeyAttestingMock.swift +++ b/Tests/VerifyTests/Mocks/KeyAttestingMock.swift @@ -1,4 +1,3 @@ -// @testable import WalletConnectVerify import Foundation From 95d206a9d610b89d03efb739c9ca7662bed84f91 Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Tue, 15 Nov 2022 09:49:17 +0100 Subject: [PATCH 18/30] remove print statement --- Sources/WalletConnectVerify/AppAttestationRegistrer.swift | 1 - 1 file changed, 1 deletion(-) diff --git a/Sources/WalletConnectVerify/AppAttestationRegistrer.swift b/Sources/WalletConnectVerify/AppAttestationRegistrer.swift index 3d263d76b..69a6d6021 100644 --- a/Sources/WalletConnectVerify/AppAttestationRegistrer.swift +++ b/Sources/WalletConnectVerify/AppAttestationRegistrer.swift @@ -31,7 +31,6 @@ class AppAttestationRegistrer { func registerAttestationIfNeeded() async throws { if let _ = try? keyIdStorage.get(key: keyIdStorageKey) { return } - print(keyIdStorage.getAll()) let keyId = try await generateKeys() let challenge = try await getChallenge() let hash = Data(SHA256.hash(data: challenge)) From 99e0ca6306b764eb0f3f117f2f3459a98e41fdbd Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Thu, 17 Nov 2022 13:20:38 +0100 Subject: [PATCH 19/30] implement AttestKeyGenerator --- .../AppAttestationRegistrer.swift | 6 ++---- .../WalletConnectVerify/AttestKeyGenerator.swift | 16 ++++++++++++++-- Sources/WalletConnectVerify/Constants.swift | 5 +++++ 3 files changed, 21 insertions(+), 6 deletions(-) create mode 100644 Sources/WalletConnectVerify/Constants.swift diff --git a/Sources/WalletConnectVerify/AppAttestationRegistrer.swift b/Sources/WalletConnectVerify/AppAttestationRegistrer.swift index 69a6d6021..04e7cd819 100644 --- a/Sources/WalletConnectVerify/AppAttestationRegistrer.swift +++ b/Sources/WalletConnectVerify/AppAttestationRegistrer.swift @@ -3,11 +3,10 @@ import DeviceCheck import WalletConnectUtils import CryptoKit + @available(iOS 14.0, *) @available(macOS 11.0, *) class AppAttestationRegistrer { - private let keyIdStorageKey = "attested_key_id" - private let service: DCAppAttestService private let logger: ConsoleLogging private let keyIdStorage: CodableStore @@ -21,7 +20,6 @@ class AppAttestationRegistrer { attestChallengeProvider: AttestChallengeProviding, keyAttestationService: KeyAttesting ) { - self.service = DCAppAttestService.shared self.logger = logger self.keyIdStorage = keyIdStorage self.attestKeyGenerator = attestKeyGenerator @@ -30,7 +28,7 @@ class AppAttestationRegistrer { } func registerAttestationIfNeeded() async throws { - if let _ = try? keyIdStorage.get(key: keyIdStorageKey) { return } + if let _ = try? keyIdStorage.get(key: Constants.keyIdStorageKey) { return } let keyId = try await generateKeys() let challenge = try await getChallenge() let hash = Data(SHA256.hash(data: challenge)) diff --git a/Sources/WalletConnectVerify/AttestKeyGenerator.swift b/Sources/WalletConnectVerify/AttestKeyGenerator.swift index 804882a5b..166d84a01 100644 --- a/Sources/WalletConnectVerify/AttestKeyGenerator.swift +++ b/Sources/WalletConnectVerify/AttestKeyGenerator.swift @@ -1,5 +1,6 @@ import DeviceCheck import Foundation +import WalletConnectUtils protocol AttestKeyGenerating { func generateKeys() async throws -> String @@ -9,9 +10,20 @@ protocol AttestKeyGenerating { @available(macOS 11.0, *) class AttestKeyGenerator: AttestKeyGenerating { private let service = DCAppAttestService.shared + private let logger: ConsoleLogging + private let keyIdStorage: CodableStore + + + init(logger: ConsoleLogging, + keyIdStorage: CodableStore + ) { + self.logger = logger + self.keyIdStorage = keyIdStorage + } func generateKeys() async throws -> String { - try await service.generateKey() - //TODO Cache keyId for subsequent operations. + let keyId = try await service.generateKey() + keyIdStorage.set(keyId, forKey: Constants.keyIdStorageKey) + return keyId } } diff --git a/Sources/WalletConnectVerify/Constants.swift b/Sources/WalletConnectVerify/Constants.swift new file mode 100644 index 000000000..47e31f2ab --- /dev/null +++ b/Sources/WalletConnectVerify/Constants.swift @@ -0,0 +1,5 @@ +import Foundation + +enum Constants { + static let keyIdStorageKey = "attested_key_id" +} From d2a38a9c4dbf6cd1359eb9cef20ad9b5a2ed7a0f Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Fri, 18 Nov 2022 08:51:36 +0100 Subject: [PATCH 20/30] add verify client factory --- Example/ExampleApp.xcodeproj/project.pbxproj | 7 ++++++ Example/ExampleApp/AppDelegate.swift | 8 +++++-- .../AttestChallengeProvider.swift | 1 + .../KeyAttestationService.swift | 10 ++++++-- .../WalletConnectVerify/VerifyClient.swift | 4 ++-- .../VerifyClientFactory.swift | 24 +++++++++++++++++++ .../VerifyStorageIdentifier.swift | 5 ++++ 7 files changed, 53 insertions(+), 6 deletions(-) create mode 100644 Sources/WalletConnectVerify/VerifyClientFactory.swift create mode 100644 Sources/WalletConnectVerify/VerifyStorageIdentifier.swift diff --git a/Example/ExampleApp.xcodeproj/project.pbxproj b/Example/ExampleApp.xcodeproj/project.pbxproj index fc6357d2b..58d7f757c 100644 --- a/Example/ExampleApp.xcodeproj/project.pbxproj +++ b/Example/ExampleApp.xcodeproj/project.pbxproj @@ -31,6 +31,7 @@ 84494388278D9C1B00CC26BB /* UIAlertController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84494387278D9C1B00CC26BB /* UIAlertController.swift */; }; 8460DCFC274F98A10081F94C /* RequestViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8460DCFB274F98A10081F94C /* RequestViewController.swift */; }; 847CF3AF28E3141700F1D760 /* WalletConnectPush in Frameworks */ = {isa = PBXBuildFile; productRef = 847CF3AE28E3141700F1D760 /* WalletConnectPush */; settings = {ATTRIBUTES = (Required, ); }; }; + 849D7A90292665D3006A2BD4 /* WalletConnectVerify in Frameworks */ = {isa = PBXBuildFile; productRef = 849D7A8F292665D3006A2BD4 /* WalletConnectVerify */; }; 84AA01DB28CF0CD7005D48D8 /* XCTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84AA01DA28CF0CD7005D48D8 /* XCTest.swift */; }; 84CE641F27981DED00142511 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84CE641E27981DED00142511 /* AppDelegate.swift */; }; 84CE642127981DED00142511 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84CE642027981DED00142511 /* SceneDelegate.swift */; }; @@ -376,6 +377,7 @@ files = ( A5AE354728A1A2AC0059AE8A /* Web3 in Frameworks */, A5434023291E6A270068F706 /* SolanaSwift in Frameworks */, + 849D7A90292665D3006A2BD4 /* WalletConnectVerify in Frameworks */, 764E1D5826F8DBAB00A1FB15 /* WalletConnect in Frameworks */, A5D85226286333D500DAF5C3 /* Starscream in Frameworks */, A5C4DD8728A2DE88006A626D /* WalletConnectRouter in Frameworks */, @@ -1149,6 +1151,7 @@ A5AE354628A1A2AC0059AE8A /* Web3 */, A5C4DD8628A2DE88006A626D /* WalletConnectRouter */, A5434022291E6A270068F706 /* SolanaSwift */, + 849D7A8F292665D3006A2BD4 /* WalletConnectVerify */, ); productName = ExampleApp; productReference = 764E1D3C26F8D3FC00A1FB15 /* WalletConnect Wallet.app */; @@ -2042,6 +2045,10 @@ isa = XCSwiftPackageProductDependency; productName = WalletConnectPush; }; + 849D7A8F292665D3006A2BD4 /* WalletConnectVerify */ = { + isa = XCSwiftPackageProductDependency; + productName = WalletConnectVerify; + }; 84DDB4EC28ABB663003D66ED /* WalletConnectAuth */ = { isa = XCSwiftPackageProductDependency; productName = WalletConnectAuth; diff --git a/Example/ExampleApp/AppDelegate.swift b/Example/ExampleApp/AppDelegate.swift index 8476d254c..e0fde0e35 100644 --- a/Example/ExampleApp/AppDelegate.swift +++ b/Example/ExampleApp/AppDelegate.swift @@ -1,9 +1,13 @@ import UIKit - +import WalletConnectVerify @main class AppDelegate: UIResponder, UIApplicationDelegate { - + let cl = try! VerifyClientFactory.create() func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { + Task{ + try await cl.registerAttestationIfNeeded() + + } return true } diff --git a/Sources/WalletConnectVerify/AttestChallengeProvider.swift b/Sources/WalletConnectVerify/AttestChallengeProvider.swift index ac9a0eaa3..5d2891e67 100644 --- a/Sources/WalletConnectVerify/AttestChallengeProvider.swift +++ b/Sources/WalletConnectVerify/AttestChallengeProvider.swift @@ -6,6 +6,7 @@ protocol AttestChallengeProviding { class AttestChallengeProvider: AttestChallengeProviding { func getChallenge() async throws -> Data { + return Data() fatalError("not implemented") } } diff --git a/Sources/WalletConnectVerify/KeyAttestationService.swift b/Sources/WalletConnectVerify/KeyAttestationService.swift index c40ba6fea..ce0833d81 100644 --- a/Sources/WalletConnectVerify/KeyAttestationService.swift +++ b/Sources/WalletConnectVerify/KeyAttestationService.swift @@ -9,12 +9,18 @@ protocol KeyAttesting { @available(macOS 11.0, *) class KeyAttestationService: KeyAttesting { private let service = DCAppAttestService.shared - // If the method, which accesses a remote Apple server, returns the serverUnavailable error, try attestation again later with the same key. For any other error, discard the key identifier and create a new key when you want to try again. Otherwise, send the completion handler’s attestation object and the keyId to your server for processing. + // If the method, which accesses a remote Apple server, returns the serverUnavailable error, + // try attestation again later with the same key. For any other error, + //discard the key identifier and create a new key when you want to try again. + //Otherwise, send the completion handler’s attestation object and the keyId to your server for processing. func attestKey(keyId: String, clientDataHash: Data) async throws { try await service.attestKey(keyId, clientDataHash: clientDataHash) - //TODO - Send the attestation object to your server for verification. handle errors } + + private func sendAttestationToVerifyServer() async throws { + + } } diff --git a/Sources/WalletConnectVerify/VerifyClient.swift b/Sources/WalletConnectVerify/VerifyClient.swift index bb03a3aac..0936d9da0 100644 --- a/Sources/WalletConnectVerify/VerifyClient.swift +++ b/Sources/WalletConnectVerify/VerifyClient.swift @@ -1,5 +1,6 @@ import DeviceCheck import Foundation +import WalletConnectUtils @available(iOS 14.0, *) @available(macOS 11.0, *) @@ -22,7 +23,7 @@ public actor VerifyClient { self.appAttestationRegistrer = appAttestationRegistrer } - private func registerAttestationIfNeeded() async throws { + public func registerAttestationIfNeeded() async throws { try await appAttestationRegistrer.registerAttestationIfNeeded() } @@ -30,7 +31,6 @@ public actor VerifyClient { try await originVerifier.verifyOrigin() } - public func registerAssertion() async throws { try await assertionRegistrer.registerAssertion() } diff --git a/Sources/WalletConnectVerify/VerifyClientFactory.swift b/Sources/WalletConnectVerify/VerifyClientFactory.swift new file mode 100644 index 000000000..7554a3189 --- /dev/null +++ b/Sources/WalletConnectVerify/VerifyClientFactory.swift @@ -0,0 +1,24 @@ +import Foundation +import WalletConnectUtils + +@available(iOS 14.0, *) +@available(macOS 11.0, *) +public class VerifyClientFactory { + + public static func create() throws -> VerifyClient { + let originVerifier = OriginVerifier() + let assertionRegistrer = AssertionRegistrer() + let logger = ConsoleLogger(loggingLevel: .off) + let keyValueStorage = UserDefaults.standard + let keyIdStorage = CodableStore(defaults: keyValueStorage, identifier: VerifyStorageIdentifier.keyId) + let attestKeyGenerator = AttestKeyGenerator(logger: logger, keyIdStorage: keyIdStorage) + let attestChallengeProvider = AttestChallengeProvider() + let keyAttestationService = KeyAttestationService() + let appAttestationRegistrer = AppAttestationRegistrer(logger: logger, + keyIdStorage: keyIdStorage, + attestKeyGenerator: attestKeyGenerator, + attestChallengeProvider: attestChallengeProvider, + keyAttestationService: keyAttestationService) + return try VerifyClient(originVerifier: originVerifier, assertionRegistrer: assertionRegistrer, appAttestationRegistrer: appAttestationRegistrer) + } +} diff --git a/Sources/WalletConnectVerify/VerifyStorageIdentifier.swift b/Sources/WalletConnectVerify/VerifyStorageIdentifier.swift new file mode 100644 index 000000000..18b6484dd --- /dev/null +++ b/Sources/WalletConnectVerify/VerifyStorageIdentifier.swift @@ -0,0 +1,5 @@ +import Foundation + +enum VerifyStorageIdentifier { + static let keyId = "com.walletconnect.sdk.keyId" +} From 89d20e2cda883b3a454210a98bbe1a7ef451b5a1 Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Fri, 18 Nov 2022 08:52:17 +0100 Subject: [PATCH 21/30] remove testing code from app delegate --- Example/ExampleApp/AppDelegate.swift | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/Example/ExampleApp/AppDelegate.swift b/Example/ExampleApp/AppDelegate.swift index e0fde0e35..8476d254c 100644 --- a/Example/ExampleApp/AppDelegate.swift +++ b/Example/ExampleApp/AppDelegate.swift @@ -1,13 +1,9 @@ import UIKit -import WalletConnectVerify + @main class AppDelegate: UIResponder, UIApplicationDelegate { - let cl = try! VerifyClientFactory.create() - func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { - Task{ - try await cl.registerAttestationIfNeeded() - } + func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { return true } From 52fc4c042f0613861aad041aebbe988460bbedb8 Mon Sep 17 00:00:00 2001 From: Artur Guseinov Date: Fri, 2 Dec 2022 17:00:19 +0500 Subject: [PATCH 22/30] Shared folder for Default Signer and Websockets --- Example/DApp/SceneDelegate.swift | 13 +--- Example/ExampleApp.xcodeproj/project.pbxproj | 78 ++++++++----------- Example/ExampleApp/SceneDelegate.swift | 11 +-- .../{EthereumSigner.swift => ETHSigner.swift} | 2 +- .../{SolanaSigner.swift => SOLSigner.swift} | 2 +- Example/ExampleApp/Shared/Signer/Signer.swift | 8 +- .../Wallet/WalletViewController.swift | 4 +- Example/IntegrationTests/Auth/AuthTests.swift | 6 +- .../Auth/Signer/CacaoSignerTests.swift | 2 +- .../Auth/Signer/EIP1271VerifierTests.swift | 4 +- .../Auth/Signer/EIP191VerifierTests.swift | 2 +- .../Auth/Signer/SignerTests.swift | 2 +- Example/IntegrationTests/Chat/ChatTests.swift | 2 +- .../Pairing/PairingTests.swift | 4 +- .../Sign/SignClientTests.swift | 2 +- .../Stubs/SignerFactory.swift | 36 --------- .../Stubs/WebSocketFactory.swift | 14 ---- .../DefaultSignerFactory.swift} | 2 +- .../DefaultSocketFactory.swift} | 2 +- .../Configurator/ThirdPartyConfigurator.swift | 4 +- .../SignerFactory/AuthSignerFactory.swift | 36 --------- .../AuthRequest/AuthRequestInteractor.swift | 2 +- 22 files changed, 62 insertions(+), 176 deletions(-) rename Example/ExampleApp/Shared/Signer/{EthereumSigner.swift => ETHSigner.swift} (98%) rename Example/ExampleApp/Shared/Signer/{SolanaSigner.swift => SOLSigner.swift} (98%) delete mode 100644 Example/IntegrationTests/Stubs/SignerFactory.swift delete mode 100644 Example/IntegrationTests/Stubs/WebSocketFactory.swift rename Example/{DApp/SignerFactory.swift => Shared/DefaultSignerFactory.swift} (95%) rename Example/{Showcase/Classes/DomainLayer/SocketFactory/SocketFactory.swift => Shared/DefaultSocketFactory.swift} (81%) delete mode 100644 Example/Showcase/Classes/DomainLayer/SignerFactory/AuthSignerFactory.swift diff --git a/Example/DApp/SceneDelegate.swift b/Example/DApp/SceneDelegate.swift index 2a76d1510..c1ea35937 100644 --- a/Example/DApp/SceneDelegate.swift +++ b/Example/DApp/SceneDelegate.swift @@ -1,17 +1,8 @@ import UIKit -import Starscream import Auth import WalletConnectRelay import WalletConnectNetworking -extension WebSocket: WebSocketConnecting { } - -struct SocketFactory: WebSocketFactory { - func create(with url: URL) -> WebSocketConnecting { - return WebSocket(url: url) - } -} - class SceneDelegate: UIResponder, UIWindowSceneDelegate { var window: UIWindow? @@ -20,8 +11,8 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { private let authCoordinator = AuthCoordinator() func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { - Networking.configure(projectId: InputConfig.projectId, socketFactory: SocketFactory()) - Auth.configure(signerFactory: AuthSignerFactory()) + Networking.configure(projectId: InputConfig.projectId, socketFactory: DefaultSocketFactory()) + Auth.configure(signerFactory: DefaultSignerFactory()) setupWindow(scene: scene) } diff --git a/Example/ExampleApp.xcodeproj/project.pbxproj b/Example/ExampleApp.xcodeproj/project.pbxproj index 0e5e0c329..c47de1a78 100644 --- a/Example/ExampleApp.xcodeproj/project.pbxproj +++ b/Example/ExampleApp.xcodeproj/project.pbxproj @@ -57,12 +57,10 @@ A51AC0D928E436A3001BACF9 /* InputConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = A51AC0D828E436A3001BACF9 /* InputConfig.swift */; }; A51AC0DD28E43727001BACF9 /* InputConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = A51AC0DB28E436E6001BACF9 /* InputConfig.swift */; }; A51AC0DF28E4379F001BACF9 /* InputConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = A51AC0DE28E4379F001BACF9 /* InputConfig.swift */; }; - A51BD530293628D400484060 /* AuthSignerFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = A51BD52F293628D400484060 /* AuthSignerFactory.swift */; }; A541959E2934BFEF0035AD19 /* CacaoSignerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A541959A2934BFEF0035AD19 /* CacaoSignerTests.swift */; }; A541959F2934BFEF0035AD19 /* SignerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A541959B2934BFEF0035AD19 /* SignerTests.swift */; }; A54195A02934BFEF0035AD19 /* EIP1271VerifierTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A541959C2934BFEF0035AD19 /* EIP1271VerifierTests.swift */; }; A54195A12934BFEF0035AD19 /* EIP191VerifierTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A541959D2934BFEF0035AD19 /* EIP191VerifierTests.swift */; }; - A54195A32934E7EC0035AD19 /* SignerFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = A54195A22934E7EC0035AD19 /* SignerFactory.swift */; }; A54195A52934E83F0035AD19 /* Web3 in Frameworks */ = {isa = PBXBuildFile; productRef = A54195A42934E83F0035AD19 /* Web3 */; }; A5434023291E6A270068F706 /* SolanaSwift in Frameworks */ = {isa = PBXBuildFile; productRef = A5434022291E6A270068F706 /* SolanaSwift */; }; A55CAAB028B92AFF00844382 /* ScanModule.swift in Sources */ = {isa = PBXBuildFile; fileRef = A55CAAAB28B92AFF00844382 /* ScanModule.swift */; }; @@ -92,15 +90,14 @@ A5629AE42876E6D200094373 /* ThreadViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5629AE32876E6D200094373 /* ThreadViewModel.swift */; }; A5629AE828772A0100094373 /* InviteViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5629AE728772A0100094373 /* InviteViewModel.swift */; }; A5629AEA2877F2D600094373 /* WalletConnectChat in Frameworks */ = {isa = PBXBuildFile; productRef = A5629AE92877F2D600094373 /* WalletConnectChat */; }; - A5629AF02877F73000094373 /* SocketFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5629AEF2877F73000094373 /* SocketFactory.swift */; }; A5629AF22877F75100094373 /* Starscream in Frameworks */ = {isa = PBXBuildFile; productRef = A5629AF12877F75100094373 /* Starscream */; }; A578FA322873036400AA7720 /* InputView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A578FA312873036400AA7720 /* InputView.swift */; }; A578FA35287304A300AA7720 /* Color.swift in Sources */ = {isa = PBXBuildFile; fileRef = A578FA34287304A300AA7720 /* Color.swift */; }; A578FA372873D8EE00AA7720 /* UIColor.swift in Sources */ = {isa = PBXBuildFile; fileRef = A578FA362873D8EE00AA7720 /* UIColor.swift */; }; A578FA392873FCE000AA7720 /* ChatScrollView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A578FA382873FCE000AA7720 /* ChatScrollView.swift */; }; A578FA3D2874002400AA7720 /* View.swift in Sources */ = {isa = PBXBuildFile; fileRef = A578FA3C2874002400AA7720 /* View.swift */; }; - A57E71A6291CF76400325797 /* EthereumSigner.swift in Sources */ = {isa = PBXBuildFile; fileRef = A57E71A5291CF76400325797 /* EthereumSigner.swift */; }; - A57E71A8291CF8A500325797 /* SolanaSigner.swift in Sources */ = {isa = PBXBuildFile; fileRef = A57E71A7291CF8A500325797 /* SolanaSigner.swift */; }; + A57E71A6291CF76400325797 /* ETHSigner.swift in Sources */ = {isa = PBXBuildFile; fileRef = A57E71A5291CF76400325797 /* ETHSigner.swift */; }; + A57E71A8291CF8A500325797 /* SOLSigner.swift in Sources */ = {isa = PBXBuildFile; fileRef = A57E71A7291CF8A500325797 /* SOLSigner.swift */; }; A58E7CEB28729F550082D443 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = A58E7CEA28729F550082D443 /* AppDelegate.swift */; }; A58E7CED28729F550082D443 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = A58E7CEC28729F550082D443 /* SceneDelegate.swift */; }; A58E7CF428729F550082D443 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = A58E7CF328729F550082D443 /* Assets.xcassets */; }; @@ -127,7 +124,7 @@ A58E7D432872EE320082D443 /* MessageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A58E7D422872EE320082D443 /* MessageView.swift */; }; A58E7D452872EE570082D443 /* ContentMessageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A58E7D442872EE570082D443 /* ContentMessageView.swift */; }; A58E7D482872EF610082D443 /* MessageViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = A58E7D472872EF610082D443 /* MessageViewModel.swift */; }; - A59CF4F6292F83D50031A42F /* SignerFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = A59CF4F5292F83D50031A42F /* SignerFactory.swift */; }; + A59CF4F6292F83D50031A42F /* DefaultSignerFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = A59CF4F5292F83D50031A42F /* DefaultSignerFactory.swift */; }; A59EBEF828B54A2A003EDAAF /* AuthRequestModule.swift in Sources */ = {isa = PBXBuildFile; fileRef = A59EBEF328B54A2A003EDAAF /* AuthRequestModule.swift */; }; A59EBEF928B54A2A003EDAAF /* AuthRequestPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = A59EBEF428B54A2A003EDAAF /* AuthRequestPresenter.swift */; }; A59EBEFA28B54A2A003EDAAF /* AuthRequestRouter.swift in Sources */ = {isa = PBXBuildFile; fileRef = A59EBEF528B54A2A003EDAAF /* AuthRequestRouter.swift */; }; @@ -146,6 +143,12 @@ A5A4FC5C283D1F6700BBEC1E /* SessionDetailViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5A4FC5B283D1F6700BBEC1E /* SessionDetailViewController.swift */; }; A5A4FC5E283D23CA00BBEC1E /* Array.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5A4FC5D283D23CA00BBEC1E /* Array.swift */; }; A5A4FC772840C12C00BBEC1E /* RegressionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5A4FC762840C12C00BBEC1E /* RegressionTests.swift */; }; + A5A8E47A293A1C9B00FEB97D /* DefaultSocketFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5629AEF2877F73000094373 /* DefaultSocketFactory.swift */; }; + A5A8E47B293A1CFE00FEB97D /* DefaultSocketFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5629AEF2877F73000094373 /* DefaultSocketFactory.swift */; }; + A5A8E47D293A1CFE00FEB97D /* DefaultSocketFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5629AEF2877F73000094373 /* DefaultSocketFactory.swift */; }; + A5A8E47E293A1CFE00FEB97D /* DefaultSignerFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = A59CF4F5292F83D50031A42F /* DefaultSignerFactory.swift */; }; + A5A8E47F293A1D0000FEB97D /* DefaultSocketFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5629AEF2877F73000094373 /* DefaultSocketFactory.swift */; }; + A5A8E480293A1D0000FEB97D /* DefaultSignerFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = A59CF4F5292F83D50031A42F /* DefaultSignerFactory.swift */; }; A5AE354728A1A2AC0059AE8A /* Web3 in Frameworks */ = {isa = PBXBuildFile; productRef = A5AE354628A1A2AC0059AE8A /* Web3 */; }; A5BB7F9F28B69B7100707FC6 /* SignCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5BB7F9E28B69B7100707FC6 /* SignCoordinator.swift */; }; A5BB7FA128B69F3400707FC6 /* AuthCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5BB7FA028B69F3400707FC6 /* AuthCoordinator.swift */; }; @@ -179,7 +182,6 @@ A5E03E01286466EA00888481 /* WalletConnectChat in Frameworks */ = {isa = PBXBuildFile; productRef = A5E03E00286466EA00888481 /* WalletConnectChat */; }; A5E03E03286466F400888481 /* ChatTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5E03E02286466F400888481 /* ChatTests.swift */; }; A5E03E0D28646AD200888481 /* RelayClientEndToEndTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5E03E0C28646AD200888481 /* RelayClientEndToEndTests.swift */; }; - A5E03E0F28646D8A00888481 /* WebSocketFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5E03E0E28646D8A00888481 /* WebSocketFactory.swift */; }; A5E03E1128646F8000888481 /* KeychainStorageMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5E03E1028646F8000888481 /* KeychainStorageMock.swift */; }; A5E22D1A2840C62A00E36487 /* Engine.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5E22D192840C62A00E36487 /* Engine.swift */; }; A5E22D1C2840C85D00E36487 /* App.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5E22D1B2840C85D00E36487 /* App.swift */; }; @@ -262,12 +264,10 @@ A51AC0D828E436A3001BACF9 /* InputConfig.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InputConfig.swift; sourceTree = ""; }; A51AC0DB28E436E6001BACF9 /* InputConfig.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InputConfig.swift; sourceTree = ""; }; A51AC0DE28E4379F001BACF9 /* InputConfig.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InputConfig.swift; sourceTree = ""; }; - A51BD52F293628D400484060 /* AuthSignerFactory.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AuthSignerFactory.swift; sourceTree = ""; }; A541959A2934BFEF0035AD19 /* CacaoSignerTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CacaoSignerTests.swift; sourceTree = ""; }; A541959B2934BFEF0035AD19 /* SignerTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SignerTests.swift; sourceTree = ""; }; A541959C2934BFEF0035AD19 /* EIP1271VerifierTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EIP1271VerifierTests.swift; sourceTree = ""; }; A541959D2934BFEF0035AD19 /* EIP191VerifierTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EIP191VerifierTests.swift; sourceTree = ""; }; - A54195A22934E7EC0035AD19 /* SignerFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SignerFactory.swift; sourceTree = ""; }; A55CAAAB28B92AFF00844382 /* ScanModule.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScanModule.swift; sourceTree = ""; }; A55CAAAC28B92AFF00844382 /* ScanPresenter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScanPresenter.swift; sourceTree = ""; }; A55CAAAD28B92AFF00844382 /* ScanRouter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScanRouter.swift; sourceTree = ""; }; @@ -294,14 +294,14 @@ A5629ADD2876CC6E00094373 /* InviteListView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InviteListView.swift; sourceTree = ""; }; A5629AE32876E6D200094373 /* ThreadViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThreadViewModel.swift; sourceTree = ""; }; A5629AE728772A0100094373 /* InviteViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InviteViewModel.swift; sourceTree = ""; }; - A5629AEF2877F73000094373 /* SocketFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SocketFactory.swift; sourceTree = ""; }; + A5629AEF2877F73000094373 /* DefaultSocketFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DefaultSocketFactory.swift; sourceTree = ""; }; A578FA312873036400AA7720 /* InputView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InputView.swift; sourceTree = ""; }; A578FA34287304A300AA7720 /* Color.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Color.swift; sourceTree = ""; }; A578FA362873D8EE00AA7720 /* UIColor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIColor.swift; sourceTree = ""; }; A578FA382873FCE000AA7720 /* ChatScrollView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatScrollView.swift; sourceTree = ""; }; A578FA3C2874002400AA7720 /* View.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = View.swift; sourceTree = ""; }; - A57E71A5291CF76400325797 /* EthereumSigner.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EthereumSigner.swift; sourceTree = ""; }; - A57E71A7291CF8A500325797 /* SolanaSigner.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SolanaSigner.swift; sourceTree = ""; }; + A57E71A5291CF76400325797 /* ETHSigner.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ETHSigner.swift; sourceTree = ""; }; + A57E71A7291CF8A500325797 /* SOLSigner.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SOLSigner.swift; sourceTree = ""; }; A58E7CE828729F550082D443 /* Showcase.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Showcase.app; sourceTree = BUILT_PRODUCTS_DIR; }; A58E7CEA28729F550082D443 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; A58E7CEC28729F550082D443 /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; }; @@ -330,7 +330,7 @@ A58E7D422872EE320082D443 /* MessageView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageView.swift; sourceTree = ""; }; A58E7D442872EE570082D443 /* ContentMessageView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentMessageView.swift; sourceTree = ""; }; A58E7D472872EF610082D443 /* MessageViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageViewModel.swift; sourceTree = ""; }; - A59CF4F5292F83D50031A42F /* SignerFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SignerFactory.swift; sourceTree = ""; }; + A59CF4F5292F83D50031A42F /* DefaultSignerFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DefaultSignerFactory.swift; sourceTree = ""; }; A59EBEF328B54A2A003EDAAF /* AuthRequestModule.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthRequestModule.swift; sourceTree = ""; }; A59EBEF428B54A2A003EDAAF /* AuthRequestPresenter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthRequestPresenter.swift; sourceTree = ""; }; A59EBEF528B54A2A003EDAAF /* AuthRequestRouter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthRequestRouter.swift; sourceTree = ""; }; @@ -373,7 +373,6 @@ A5E03DFC286465D100888481 /* Stubs.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Stubs.swift; sourceTree = ""; }; A5E03E02286466F400888481 /* ChatTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatTests.swift; sourceTree = ""; }; A5E03E0C28646AD200888481 /* RelayClientEndToEndTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RelayClientEndToEndTests.swift; sourceTree = ""; }; - A5E03E0E28646D8A00888481 /* WebSocketFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WebSocketFactory.swift; sourceTree = ""; }; A5E03E1028646F8000888481 /* KeychainStorageMock.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = KeychainStorageMock.swift; sourceTree = ""; }; A5E22D192840C62A00E36487 /* Engine.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Engine.swift; sourceTree = ""; }; A5E22D1B2840C85D00E36487 /* App.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = App.swift; sourceTree = ""; }; @@ -483,6 +482,7 @@ 764E1D3326F8D3FC00A1FB15 = { isa = PBXGroup; children = ( + A5A8E479293A1C4400FEB97D /* Shared */, A5F48A0528E43D3F0034CBFB /* Configuration.xcconfig */, 84CE6453279FFE1100142511 /* Wallet.entitlements */, 764E1D3E26F8D3FC00A1FB15 /* ExampleApp */, @@ -571,7 +571,6 @@ A5BB7FAB28B6AA7100707FC6 /* Common */, 84CE641E27981DED00142511 /* AppDelegate.swift */, 84CE642027981DED00142511 /* SceneDelegate.swift */, - A54195A22934E7EC0035AD19 /* SignerFactory.swift */, A5BB7FAA28B6A64A00707FC6 /* Sign */, A5BB7FA528B6A5DC00707FC6 /* Auth */, 84CE642727981DF000142511 /* Assets.xcassets */, @@ -687,9 +686,7 @@ A5629AA42876A19D00094373 /* DomainLayer */ = { isa = PBXGroup; children = ( - A5EA27522930D7760094D272 /* SignerFactory */, A5C20227287EB342007E3188 /* AccountStorage */, - A5629AEE2877F72B00094373 /* SocketFactory */, A5629AEB2877F69C00094373 /* Chat */, ); path = DomainLayer; @@ -759,14 +756,6 @@ path = Chat; sourceTree = ""; }; - A5629AEE2877F72B00094373 /* SocketFactory */ = { - isa = PBXGroup; - children = ( - A5629AEF2877F73000094373 /* SocketFactory.swift */, - ); - path = SocketFactory; - sourceTree = ""; - }; A578FA332873049400AA7720 /* Style */ = { isa = PBXGroup; children = ( @@ -797,8 +786,8 @@ isa = PBXGroup; children = ( 84F568C1279582D200D0A289 /* Signer.swift */, - A57E71A5291CF76400325797 /* EthereumSigner.swift */, - A57E71A7291CF8A500325797 /* SolanaSigner.swift */, + A57E71A5291CF76400325797 /* ETHSigner.swift */, + A57E71A7291CF8A500325797 /* SOLSigner.swift */, ); path = Signer; sourceTree = ""; @@ -1018,6 +1007,15 @@ path = Engine; sourceTree = ""; }; + A5A8E479293A1C4400FEB97D /* Shared */ = { + isa = PBXGroup; + children = ( + A5629AEF2877F73000094373 /* DefaultSocketFactory.swift */, + A59CF4F5292F83D50031A42F /* DefaultSignerFactory.swift */, + ); + path = Shared; + sourceTree = ""; + }; A5BB7FA528B6A5DC00707FC6 /* Auth */ = { isa = PBXGroup; children = ( @@ -1128,8 +1126,6 @@ children = ( A518B31328E33A6500A2CE93 /* InputConfig.swift */, A5E03E1028646F8000888481 /* KeychainStorageMock.swift */, - A5E03E0E28646D8A00888481 /* WebSocketFactory.swift */, - A59CF4F5292F83D50031A42F /* SignerFactory.swift */, A5E03DFC286465D100888481 /* Stubs.swift */, 84FE684528ACDB4700C893FF /* RequestParams.swift */, ); @@ -1160,14 +1156,6 @@ path = Extensions; sourceTree = ""; }; - A5EA27522930D7760094D272 /* SignerFactory */ = { - isa = PBXGroup; - children = ( - A51BD52F293628D400484060 /* AuthSignerFactory.swift */, - ); - path = SignerFactory; - sourceTree = ""; - }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -1400,11 +1388,12 @@ 76235E8B28201C9C004ED0AA /* Utilities.swift in Sources */, 76744CF726FE4D5400B77ED9 /* ActiveSessionItem.swift in Sources */, A5A4FC5A283CC08600BBEC1E /* SessionNamespaceViewModel.swift in Sources */, - A57E71A8291CF8A500325797 /* SolanaSigner.swift in Sources */, + A5A8E47B293A1CFE00FEB97D /* DefaultSocketFactory.swift in Sources */, + A57E71A8291CF8A500325797 /* SOLSigner.swift in Sources */, 764E1D4226F8D3FC00A1FB15 /* SceneDelegate.swift in Sources */, 84F568C2279582D200D0A289 /* Signer.swift in Sources */, A5A4FC56283CBB7800BBEC1E /* SessionDetailView.swift in Sources */, - A57E71A6291CF76400325797 /* EthereumSigner.swift in Sources */, + A57E71A6291CF76400325797 /* ETHSigner.swift in Sources */, 7600223B2819FC0B0011DD38 /* ProposalView.swift in Sources */, 761248172819F9E600CB6D48 /* WalletView.swift in Sources */, A5A4FC58283CBB9F00BBEC1E /* SessionDetailViewModel.swift in Sources */, @@ -1426,11 +1415,12 @@ A5BB7FA128B69F3400707FC6 /* AuthCoordinator.swift in Sources */, 84CE645527A29D4D00142511 /* ResponseViewController.swift in Sources */, 84CE641F27981DED00142511 /* AppDelegate.swift in Sources */, + A5A8E47D293A1CFE00FEB97D /* DefaultSocketFactory.swift in Sources */, A5BB7FAD28B6AA7D00707FC6 /* QRCodeGenerator.swift in Sources */, - A54195A32934E7EC0035AD19 /* SignerFactory.swift in Sources */, A51AC0D928E436A3001BACF9 /* InputConfig.swift in Sources */, A5BB7FA928B6A5FD00707FC6 /* AuthViewModel.swift in Sources */, 84CE6452279ED42B00142511 /* ConnectView.swift in Sources */, + A5A8E47E293A1CFE00FEB97D /* DefaultSignerFactory.swift in Sources */, 84CE6448279AE68600142511 /* AccountRequestViewController.swift in Sources */, A5BB7F9F28B69B7100707FC6 /* SignCoordinator.swift in Sources */, 84CE642127981DED00142511 /* SceneDelegate.swift in Sources */, @@ -1508,13 +1498,13 @@ A5629AC02876CBC000094373 /* ChatListInteractor.swift in Sources */, A55CAAB428B92AFF00844382 /* ScanView.swift in Sources */, A5629AE22876CC6E00094373 /* InviteListView.swift in Sources */, + A5A8E47F293A1D0000FEB97D /* DefaultSocketFactory.swift in Sources */, A578FA3D2874002400AA7720 /* View.swift in Sources */, A5629AD72876CC5700094373 /* InviteView.swift in Sources */, A59EBEFA28B54A2A003EDAAF /* AuthRequestRouter.swift in Sources */, - A5629AF02877F73000094373 /* SocketFactory.swift in Sources */, A55CAAB228B92AFF00844382 /* ScanRouter.swift in Sources */, A5C20221287EA5B8007E3188 /* TextFieldView.swift in Sources */, - A51BD530293628D400484060 /* AuthSignerFactory.swift in Sources */, + A5A8E480293A1D0000FEB97D /* DefaultSignerFactory.swift in Sources */, A5C2022B287EB89A007E3188 /* WelcomeInteractor.swift in Sources */, A5C2020C287D9DEE007E3188 /* WelcomePresenter.swift in Sources */, A58E7D1D2872A57B0082D443 /* Configurator.swift in Sources */, @@ -1556,7 +1546,7 @@ 767DC83528997F8E00080FA9 /* EthSendTransaction.swift in Sources */, A518B31428E33A6500A2CE93 /* InputConfig.swift in Sources */, A541959E2934BFEF0035AD19 /* CacaoSignerTests.swift in Sources */, - A59CF4F6292F83D50031A42F /* SignerFactory.swift in Sources */, + A59CF4F6292F83D50031A42F /* DefaultSignerFactory.swift in Sources */, A5E03E03286466F400888481 /* ChatTests.swift in Sources */, 84D2A66628A4F51E0088AE09 /* AuthTests.swift in Sources */, 84FE684628ACDB4700C893FF /* RequestParams.swift in Sources */, @@ -1567,10 +1557,10 @@ A5E03DFA286465C700888481 /* SignClientTests.swift in Sources */, A54195A02934BFEF0035AD19 /* EIP1271VerifierTests.swift in Sources */, A54195A12934BFEF0035AD19 /* EIP191VerifierTests.swift in Sources */, - A5E03E0F28646D8A00888481 /* WebSocketFactory.swift in Sources */, 84AA01DB28CF0CD7005D48D8 /* XCTest.swift in Sources */, A5E03E1128646F8000888481 /* KeychainStorageMock.swift in Sources */, A5E03DFD286465D100888481 /* Stubs.swift in Sources */, + A5A8E47A293A1C9B00FEB97D /* DefaultSocketFactory.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/Example/ExampleApp/SceneDelegate.swift b/Example/ExampleApp/SceneDelegate.swift index 0037fb05b..c3ddd5743 100644 --- a/Example/ExampleApp/SceneDelegate.swift +++ b/Example/ExampleApp/SceneDelegate.swift @@ -5,15 +5,6 @@ import WalletConnectSign import WalletConnectNetworking import WalletConnectRelay import WalletConnectPairing -import Starscream - -extension WebSocket: WebSocketConnecting { } - -struct SocketFactory: WebSocketFactory { - func create(with url: URL) -> WebSocketConnecting { - return WebSocket(url: url) - } -} class SceneDelegate: UIResponder, UIWindowSceneDelegate { @@ -27,7 +18,7 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { url: "example.wallet", icons: ["https://avatars.githubusercontent.com/u/37784886"]) - Networking.configure(projectId: InputConfig.projectId, socketFactory: SocketFactory()) + Networking.configure(projectId: InputConfig.projectId, socketFactory: DefaultSocketFactory()) Pair.configure(metadata: metadata) #if DEBUG if CommandLine.arguments.contains("-cleanInstall") { diff --git a/Example/ExampleApp/Shared/Signer/EthereumSigner.swift b/Example/ExampleApp/Shared/Signer/ETHSigner.swift similarity index 98% rename from Example/ExampleApp/Shared/Signer/EthereumSigner.swift rename to Example/ExampleApp/Shared/Signer/ETHSigner.swift index 6f1178872..3d1e0e743 100644 --- a/Example/ExampleApp/Shared/Signer/EthereumSigner.swift +++ b/Example/ExampleApp/Shared/Signer/ETHSigner.swift @@ -2,7 +2,7 @@ import Foundation import Commons import Web3 -struct EthereumSigner { +struct ETHSigner { private init() {} diff --git a/Example/ExampleApp/Shared/Signer/SolanaSigner.swift b/Example/ExampleApp/Shared/Signer/SOLSigner.swift similarity index 98% rename from Example/ExampleApp/Shared/Signer/SolanaSigner.swift rename to Example/ExampleApp/Shared/Signer/SOLSigner.swift index c65ec83f1..557d0177f 100644 --- a/Example/ExampleApp/Shared/Signer/SolanaSigner.swift +++ b/Example/ExampleApp/Shared/Signer/SOLSigner.swift @@ -3,7 +3,7 @@ import Commons import SolanaSwift import TweetNacl -struct SolanaSigner { +struct SOLSigner { static var address: String { return account.publicKey.base58EncodedString diff --git a/Example/ExampleApp/Shared/Signer/Signer.swift b/Example/ExampleApp/Shared/Signer/Signer.swift index dde8e101f..d22d863da 100644 --- a/Example/ExampleApp/Shared/Signer/Signer.swift +++ b/Example/ExampleApp/Shared/Signer/Signer.swift @@ -9,16 +9,16 @@ class Signer { static func sign(request: Request) -> AnyCodable { switch request.method { case "personal_sign": - return EthereumSigner.personalSign(request.params) + return ETHSigner.personalSign(request.params) case "eth_signTypedData": - return EthereumSigner.signTypedData(request.params) + return ETHSigner.signTypedData(request.params) case "eth_sendTransaction": - return EthereumSigner.sendTransaction(request.params) + return ETHSigner.sendTransaction(request.params) case "solana_signTransaction": - return SolanaSigner.signTransaction(request.params) + return SOLSigner.signTransaction(request.params) default: fatalError("not implemented") } diff --git a/Example/ExampleApp/Wallet/WalletViewController.swift b/Example/ExampleApp/Wallet/WalletViewController.swift index 034998740..b20a21ea0 100644 --- a/Example/ExampleApp/Wallet/WalletViewController.swift +++ b/Example/ExampleApp/Wallet/WalletViewController.swift @@ -9,8 +9,8 @@ import Combine final class WalletViewController: UIViewController { lazy var accounts = [ - "eip155": EthereumSigner.address, - "solana": SolanaSigner.address + "eip155": ETHSigner.address, + "solana": SOLSigner.address ] var sessionItems: [ActiveSessionItem] = [] diff --git a/Example/IntegrationTests/Auth/AuthTests.swift b/Example/IntegrationTests/Auth/AuthTests.swift index 7b48e601b..94b9abab2 100644 --- a/Example/IntegrationTests/Auth/AuthTests.swift +++ b/Example/IntegrationTests/Auth/AuthTests.swift @@ -31,7 +31,7 @@ final class AuthTests: XCTestCase { func makeClients(prefix: String, account: Account? = nil, iatProvider: IATProvider) -> (PairingClient, AuthClient) { let logger = ConsoleLogger(suffix: prefix, loggingLevel: .debug) let keychain = KeychainStorageMock() - let relayClient = RelayClient(relayHost: InputConfig.relayHost, projectId: InputConfig.projectId, keychainStorage: keychain, socketFactory: SocketFactory(), logger: logger) + let relayClient = RelayClient(relayHost: InputConfig.relayHost, projectId: InputConfig.projectId, keychainStorage: keychain, socketFactory: DefaultSocketFactory(), logger: logger) let keyValueStorage = RuntimeKeyValueStorage() let networkingClient = NetworkingClientFactory.create( @@ -50,7 +50,7 @@ final class AuthTests: XCTestCase { metadata: AppMetadata(name: name, description: "", url: "", icons: [""]), account: account, projectId: InputConfig.projectId, - signerFactory: AuthSignerFactory(), + signerFactory: DefaultSignerFactory(), logger: logger, keyValueStorage: keyValueStorage, keychainStorage: keychain, @@ -81,7 +81,7 @@ final class AuthTests: XCTestCase { try! await walletPairingClient.pair(uri: uri) walletAuthClient.authRequestPublisher.sink { [unowned self] request in Task(priority: .high) { - let signerFactory = AuthSignerFactory() + let signerFactory = DefaultSignerFactory() let signer = MessageSignerFactory(signerFactory: signerFactory).create(projectId: InputConfig.projectId) let signature = try! signer.sign(message: request.message, privateKey: prvKey, type: .eip191) try! await walletAuthClient.respond(requestId: request.id, signature: signature) diff --git a/Example/IntegrationTests/Auth/Signer/CacaoSignerTests.swift b/Example/IntegrationTests/Auth/Signer/CacaoSignerTests.swift index 4c96a63a3..23a3db381 100644 --- a/Example/IntegrationTests/Auth/Signer/CacaoSignerTests.swift +++ b/Example/IntegrationTests/Auth/Signer/CacaoSignerTests.swift @@ -4,7 +4,7 @@ import XCTest class CacaoSignerTest: XCTestCase { - let signer = MessageSignerFactory(signerFactory: AuthSignerFactory()) + let signer = MessageSignerFactory(signerFactory: DefaultSignerFactory()) .create(projectId: InputConfig.projectId) let privateKey = Data(hex: "305c6cde3846927892cd32762f6120539f3ec74c9e3a16b9b798b1e85351ae2a") diff --git a/Example/IntegrationTests/Auth/Signer/EIP1271VerifierTests.swift b/Example/IntegrationTests/Auth/Signer/EIP1271VerifierTests.swift index 57c834f80..45c5c1bdd 100644 --- a/Example/IntegrationTests/Auth/Signer/EIP1271VerifierTests.swift +++ b/Example/IntegrationTests/Auth/Signer/EIP1271VerifierTests.swift @@ -14,7 +14,7 @@ class EIP1271VerifierTests: XCTestCase { func testSuccessVerify() async throws { let httpClient = HTTPNetworkClient(host: "rpc.walletconnect.com") - let signer = AuthSignerFactory().createEthereumSigner() + let signer = DefaultSignerFactory().createEthereumSigner() let verifier = EIP1271Verifier(projectId: InputConfig.projectId, httpClient: httpClient, signer: signer) try await verifier.verify( signature: signature, @@ -26,7 +26,7 @@ class EIP1271VerifierTests: XCTestCase { func testFailureVerify() async throws { let httpClient = HTTPNetworkClient(host: "rpc.walletconnect.com") - let signer = AuthSignerFactory().createEthereumSigner() + let signer = DefaultSignerFactory().createEthereumSigner() let verifier = EIP1271Verifier(projectId: InputConfig.projectId, httpClient: httpClient, signer: signer) await XCTAssertThrowsErrorAsync(try await verifier.verify( diff --git a/Example/IntegrationTests/Auth/Signer/EIP191VerifierTests.swift b/Example/IntegrationTests/Auth/Signer/EIP191VerifierTests.swift index 3e14c46cd..2e5c9c1f3 100644 --- a/Example/IntegrationTests/Auth/Signer/EIP191VerifierTests.swift +++ b/Example/IntegrationTests/Auth/Signer/EIP191VerifierTests.swift @@ -4,7 +4,7 @@ import XCTest class EIP191VerifierTests: XCTestCase { - private let verifier = EIP191Verifier(signer: AuthSignerFactory().createEthereumSigner()) + private let verifier = EIP191Verifier(signer: DefaultSignerFactory().createEthereumSigner()) private let address = "0x15bca56b6e2728aec2532df9d436bd1600e86688" private let message = "\u{19}Ethereum Signed Message:\n7Message".data(using: .utf8)! diff --git a/Example/IntegrationTests/Auth/Signer/SignerTests.swift b/Example/IntegrationTests/Auth/Signer/SignerTests.swift index 20e26b7fb..2a8f49b2d 100644 --- a/Example/IntegrationTests/Auth/Signer/SignerTests.swift +++ b/Example/IntegrationTests/Auth/Signer/SignerTests.swift @@ -5,7 +5,7 @@ import WalletConnectRelay class SignerTest: XCTestCase { - private let signer = AuthSignerFactory().createEthereumSigner() + private let signer = DefaultSignerFactory().createEthereumSigner() private let message = "\u{19}Ethereum Signed Message:\n7Message".data(using: .utf8)! private let privateKey = Data(hex: "305c6cde3846927892cd32762f6120539f3ec74c9e3a16b9b798b1e85351ae2a") diff --git a/Example/IntegrationTests/Chat/ChatTests.swift b/Example/IntegrationTests/Chat/ChatTests.swift index 4c305a88f..0f7d770ce 100644 --- a/Example/IntegrationTests/Chat/ChatTests.swift +++ b/Example/IntegrationTests/Chat/ChatTests.swift @@ -21,7 +21,7 @@ final class ChatTests: XCTestCase { func makeClient(prefix: String) -> ChatClient { let logger = ConsoleLogger(suffix: prefix, loggingLevel: .debug) let keychain = KeychainStorageMock() - let relayClient = RelayClient(relayHost: InputConfig.relayHost, projectId: InputConfig.projectId, keychainStorage: keychain, socketFactory: SocketFactory(), logger: logger) + let relayClient = RelayClient(relayHost: InputConfig.relayHost, projectId: InputConfig.projectId, keychainStorage: keychain, socketFactory: DefaultSocketFactory(), logger: logger) return ChatClientFactory.create(registry: registry, relayClient: relayClient, kms: KeyManagementService(keychain: keychain), logger: logger, keyValueStorage: RuntimeKeyValueStorage()) } diff --git a/Example/IntegrationTests/Pairing/PairingTests.swift b/Example/IntegrationTests/Pairing/PairingTests.swift index dce08c134..a3724cb67 100644 --- a/Example/IntegrationTests/Pairing/PairingTests.swift +++ b/Example/IntegrationTests/Pairing/PairingTests.swift @@ -34,7 +34,7 @@ final class PairingTests: XCTestCase { projectId: InputConfig.projectId, keyValueStorage: RuntimeKeyValueStorage(), keychainStorage: keychain, - socketFactory: SocketFactory(), + socketFactory: DefaultSocketFactory(), logger: relayLogger) let networkingClient = NetworkingClientFactory.create( @@ -68,7 +68,7 @@ final class PairingTests: XCTestCase { relayHost: InputConfig.relayHost, projectId: InputConfig.projectId, keychainStorage: keychain, - socketFactory: SocketFactory(), + socketFactory: DefaultSocketFactory(), logger: logger) let networkingClient = NetworkingClientFactory.create( diff --git a/Example/IntegrationTests/Sign/SignClientTests.swift b/Example/IntegrationTests/Sign/SignClientTests.swift index acbfbb728..a429d0884 100644 --- a/Example/IntegrationTests/Sign/SignClientTests.swift +++ b/Example/IntegrationTests/Sign/SignClientTests.swift @@ -19,7 +19,7 @@ final class SignClientTests: XCTestCase { projectId: InputConfig.projectId, keyValueStorage: RuntimeKeyValueStorage(), keychainStorage: keychain, - socketFactory: SocketFactory(), + socketFactory: DefaultSocketFactory(), socketConnectionType: .automatic, logger: logger ) diff --git a/Example/IntegrationTests/Stubs/SignerFactory.swift b/Example/IntegrationTests/Stubs/SignerFactory.swift deleted file mode 100644 index b7e41afd0..000000000 --- a/Example/IntegrationTests/Stubs/SignerFactory.swift +++ /dev/null @@ -1,36 +0,0 @@ -import Foundation -import CryptoSwift -import Web3 -import Auth - -public struct AuthSignerFactory: SignerFactory { - - public func createEthereumSigner() -> EthereumSigner { - return Web3Signer() - } -} - -public struct Web3Signer: EthereumSigner { - - public func sign(message: Data, with key: Data) throws -> EthereumSignature { - let privateKey = try EthereumPrivateKey(privateKey: [UInt8](key)) - let signature = try privateKey.sign(message: message.bytes) - return EthereumSignature(v: UInt8(signature.v), r: signature.r, s: signature.s) - } - - public func recoverPubKey(signature: EthereumSignature, message: Data) throws -> Data { - let publicKey = try EthereumPublicKey( - message: message.bytes, - v: EthereumQuantity(quantity: BigUInt(signature.v)), - r: EthereumQuantity(signature.r), - s: EthereumQuantity(signature.s) - ) - return Data(publicKey.rawPublicKey) - } - - public func keccak256(_ data: Data) -> Data { - let digest = SHA3(variant: .keccak256) - let hash = digest.calculate(for: [UInt8](data)) - return Data(hash) - } -} diff --git a/Example/IntegrationTests/Stubs/WebSocketFactory.swift b/Example/IntegrationTests/Stubs/WebSocketFactory.swift deleted file mode 100644 index 22f45a8cb..000000000 --- a/Example/IntegrationTests/Stubs/WebSocketFactory.swift +++ /dev/null @@ -1,14 +0,0 @@ -import Foundation -import Starscream -import WalletConnectRelay - -extension WebSocket: WebSocketConnecting { } - -public struct SocketFactory: WebSocketFactory { - - public init() { } - - public func create(with url: URL) -> WebSocketConnecting { - return WebSocket(url: url) - } -} diff --git a/Example/DApp/SignerFactory.swift b/Example/Shared/DefaultSignerFactory.swift similarity index 95% rename from Example/DApp/SignerFactory.swift rename to Example/Shared/DefaultSignerFactory.swift index b7e41afd0..ac720452d 100644 --- a/Example/DApp/SignerFactory.swift +++ b/Example/Shared/DefaultSignerFactory.swift @@ -3,7 +3,7 @@ import CryptoSwift import Web3 import Auth -public struct AuthSignerFactory: SignerFactory { +public struct DefaultSignerFactory: SignerFactory { public func createEthereumSigner() -> EthereumSigner { return Web3Signer() diff --git a/Example/Showcase/Classes/DomainLayer/SocketFactory/SocketFactory.swift b/Example/Shared/DefaultSocketFactory.swift similarity index 81% rename from Example/Showcase/Classes/DomainLayer/SocketFactory/SocketFactory.swift rename to Example/Shared/DefaultSocketFactory.swift index d22a5ef48..14bb1ed98 100644 --- a/Example/Showcase/Classes/DomainLayer/SocketFactory/SocketFactory.swift +++ b/Example/Shared/DefaultSocketFactory.swift @@ -4,7 +4,7 @@ import WalletConnectRelay extension WebSocket: WebSocketConnecting { } -struct SocketFactory: WebSocketFactory { +struct DefaultSocketFactory: WebSocketFactory { func create(with url: URL) -> WebSocketConnecting { return WebSocket(url: url) } diff --git a/Example/Showcase/Classes/ApplicationLayer/Configurator/ThirdPartyConfigurator.swift b/Example/Showcase/Classes/ApplicationLayer/Configurator/ThirdPartyConfigurator.swift index 35e964b07..deced1e52 100644 --- a/Example/Showcase/Classes/ApplicationLayer/Configurator/ThirdPartyConfigurator.swift +++ b/Example/Showcase/Classes/ApplicationLayer/Configurator/ThirdPartyConfigurator.swift @@ -5,7 +5,7 @@ import Auth struct ThirdPartyConfigurator: Configurator { func configure() { - Networking.configure(projectId: InputConfig.projectId, socketFactory: SocketFactory()) + Networking.configure(projectId: InputConfig.projectId, socketFactory: DefaultSocketFactory()) Pair.configure( metadata: AppMetadata( name: "Showcase App", @@ -16,7 +16,7 @@ struct ThirdPartyConfigurator: Configurator { Auth.configure( account: Account("eip155:1:0xe5EeF1368781911d265fDB6946613dA61915a501")!, - signerFactory: AuthSignerFactory() + signerFactory: DefaultSignerFactory() ) } } diff --git a/Example/Showcase/Classes/DomainLayer/SignerFactory/AuthSignerFactory.swift b/Example/Showcase/Classes/DomainLayer/SignerFactory/AuthSignerFactory.swift deleted file mode 100644 index b7e41afd0..000000000 --- a/Example/Showcase/Classes/DomainLayer/SignerFactory/AuthSignerFactory.swift +++ /dev/null @@ -1,36 +0,0 @@ -import Foundation -import CryptoSwift -import Web3 -import Auth - -public struct AuthSignerFactory: SignerFactory { - - public func createEthereumSigner() -> EthereumSigner { - return Web3Signer() - } -} - -public struct Web3Signer: EthereumSigner { - - public func sign(message: Data, with key: Data) throws -> EthereumSignature { - let privateKey = try EthereumPrivateKey(privateKey: [UInt8](key)) - let signature = try privateKey.sign(message: message.bytes) - return EthereumSignature(v: UInt8(signature.v), r: signature.r, s: signature.s) - } - - public func recoverPubKey(signature: EthereumSignature, message: Data) throws -> Data { - let publicKey = try EthereumPublicKey( - message: message.bytes, - v: EthereumQuantity(quantity: BigUInt(signature.v)), - r: EthereumQuantity(signature.r), - s: EthereumQuantity(signature.s) - ) - return Data(publicKey.rawPublicKey) - } - - public func keccak256(_ data: Data) -> Data { - let digest = SHA3(variant: .keccak256) - let hash = digest.calculate(for: [UInt8](data)) - return Data(hash) - } -} diff --git a/Example/Showcase/Classes/PresentationLayer/Wallet/AuthRequest/AuthRequestInteractor.swift b/Example/Showcase/Classes/PresentationLayer/Wallet/AuthRequest/AuthRequestInteractor.swift index 5ed599c26..ce787b638 100644 --- a/Example/Showcase/Classes/PresentationLayer/Wallet/AuthRequest/AuthRequestInteractor.swift +++ b/Example/Showcase/Classes/PresentationLayer/Wallet/AuthRequest/AuthRequestInteractor.swift @@ -6,7 +6,7 @@ final class AuthRequestInteractor { func approve(request: AuthRequest) async throws { let privateKey = Data(hex: "e56da0e170b5e09a8bb8f1b693392c7d56c3739a9c75740fbc558a2877868540") - let signer = MessageSignerFactory(signerFactory: AuthSignerFactory()).create() + let signer = MessageSignerFactory(signerFactory: DefaultSignerFactory()).create() let signature = try signer.sign(message: request.message, privateKey: privateKey, type: .eip191) try await Auth.instance.respond(requestId: request.id, signature: signature) } From 9a308eb576db41fd5a6f63f1f4b4e562f6f3118e Mon Sep 17 00:00:00 2001 From: Artur Guseinov Date: Wed, 30 Nov 2022 21:39:01 +0500 Subject: [PATCH 23/30] Auth Multiaccount Interfaces --- .../Configurator/ThirdPartyConfigurator.swift | 5 +- .../AuthRequest/AuthRequestInteractor.swift | 16 +++++- .../AuthRequest/AuthRequestPresenter.swift | 2 +- Sources/Auth/Auth.swift | 11 ---- Sources/Auth/AuthClient.swift | 12 +--- Sources/Auth/AuthClientFactory.swift | 6 +- Sources/Auth/AuthConfig.swift | 8 --- .../Common/SIWEMessageFormatter.swift | 4 +- .../Auth/Services/Signer/MessageSigner.swift | 55 ++++++++++++++++--- .../Signer/MessageSignerFactory.swift | 7 ++- .../Wallet/PendingRequestsProvider.swift | 5 +- .../Wallet/WalletRequestSubscriber.swift | 28 +++------- Sources/Auth/Types/AuthPayload.swift | 28 +++++----- .../ProtocolRPCParams/AuthRequestParams.swift | 8 +-- Sources/Auth/Types/Public/AuthRequest.swift | 3 +- 15 files changed, 101 insertions(+), 97 deletions(-) delete mode 100644 Sources/Auth/AuthConfig.swift diff --git a/Example/Showcase/Classes/ApplicationLayer/Configurator/ThirdPartyConfigurator.swift b/Example/Showcase/Classes/ApplicationLayer/Configurator/ThirdPartyConfigurator.swift index deced1e52..f71b9de3e 100644 --- a/Example/Showcase/Classes/ApplicationLayer/Configurator/ThirdPartyConfigurator.swift +++ b/Example/Showcase/Classes/ApplicationLayer/Configurator/ThirdPartyConfigurator.swift @@ -14,9 +14,6 @@ struct ThirdPartyConfigurator: Configurator { icons: ["https://avatars.githubusercontent.com/u/37784886"] )) - Auth.configure( - account: Account("eip155:1:0xe5EeF1368781911d265fDB6946613dA61915a501")!, - signerFactory: DefaultSignerFactory() - ) + Auth.configure(signerFactory: DefaultSignerFactory()) } } diff --git a/Example/Showcase/Classes/PresentationLayer/Wallet/AuthRequest/AuthRequestInteractor.swift b/Example/Showcase/Classes/PresentationLayer/Wallet/AuthRequest/AuthRequestInteractor.swift index ce787b638..84eba3103 100644 --- a/Example/Showcase/Classes/PresentationLayer/Wallet/AuthRequest/AuthRequestInteractor.swift +++ b/Example/Showcase/Classes/PresentationLayer/Wallet/AuthRequest/AuthRequestInteractor.swift @@ -4,14 +4,24 @@ import WalletConnectUtils final class AuthRequestInteractor { + private let signer = MessageSignerFactory(signerFactory: DefaultSignerFactory()).create() + private let account = Account("eip155:1:0xe5EeF1368781911d265fDB6946613dA61915a501")! + func approve(request: AuthRequest) async throws { let privateKey = Data(hex: "e56da0e170b5e09a8bb8f1b693392c7d56c3739a9c75740fbc558a2877868540") - let signer = MessageSignerFactory(signerFactory: DefaultSignerFactory()).create() - let signature = try signer.sign(message: request.message, privateKey: privateKey, type: .eip191) - try await Auth.instance.respond(requestId: request.id, signature: signature) + let signature = try signer.sign( + request: request, + address: account.address, + privateKey: privateKey, + type: .eip191) + try await Auth.instance.respond(requestId: request.id, signature: signature, from: account) } func reject(request: AuthRequest) async throws { try await Auth.instance.reject(requestId: request.id) } + + func formatted(request: AuthRequest) -> String { + return try! signer.format(request: request, address: account.address) + } } diff --git a/Example/Showcase/Classes/PresentationLayer/Wallet/AuthRequest/AuthRequestPresenter.swift b/Example/Showcase/Classes/PresentationLayer/Wallet/AuthRequest/AuthRequestPresenter.swift index f70700e86..3aece0e97 100644 --- a/Example/Showcase/Classes/PresentationLayer/Wallet/AuthRequest/AuthRequestPresenter.swift +++ b/Example/Showcase/Classes/PresentationLayer/Wallet/AuthRequest/AuthRequestPresenter.swift @@ -17,7 +17,7 @@ final class AuthRequestPresenter: ObservableObject { } var message: String { - return request.message + return interactor.formatted(request: request) } @MainActor diff --git a/Sources/Auth/Auth.swift b/Sources/Auth/Auth.swift index 0f0c4c4f8..461e721c9 100644 --- a/Sources/Auth/Auth.swift +++ b/Sources/Auth/Auth.swift @@ -21,7 +21,6 @@ public class Auth { } return AuthClientFactory.create( metadata: Pair.metadata, - account: config.account, projectId: Networking.projectId, signerFactory: config.signerFactory, networkingClient: Networking.interactor, @@ -29,18 +28,8 @@ public class Auth { ) }() - private static var config: Config? - private init() { } - /// Auth instance wallet config method. For Wallet usage - /// - Parameters: - /// - account: account that wallet will be authenticating with. - /// - signerFactory: Auth signers factory - static public func configure(account: Account, signerFactory: SignerFactory) { - Auth.config = Auth.Config(account: account, signerFactory: signerFactory) - } - /// Auth instance wallet config method. For DApp usage /// - Parameters: /// - signerFactory: Auth signers factory diff --git a/Sources/Auth/AuthClient.swift b/Sources/Auth/AuthClient.swift index 1de34a126..6dcc9827e 100644 --- a/Sources/Auth/AuthClient.swift +++ b/Sources/Auth/AuthClient.swift @@ -7,9 +7,6 @@ import Combine /// /// Access via `Auth.instance` public class AuthClient { - enum Errors: Error { - case unknownWalletAddress - } // MARK: - Public Properties @@ -46,13 +43,11 @@ public class AuthClient { private let walletRequestSubscriber: WalletRequestSubscriber private let walletRespondService: WalletRespondService private let pendingRequestsProvider: PendingRequestsProvider - private var account: Account? init(appRequestService: AppRequestService, appRespondSubscriber: AppRespondSubscriber, walletRequestSubscriber: WalletRequestSubscriber, walletRespondService: WalletRespondService, - account: Account?, pendingRequestsProvider: PendingRequestsProvider, logger: ConsoleLogging, socketConnectionStatusPublisher: AnyPublisher, @@ -62,7 +57,6 @@ public class AuthClient { self.walletRequestSubscriber = walletRequestSubscriber self.walletRespondService = walletRespondService self.appRespondSubscriber = appRespondSubscriber - self.account = account self.pendingRequestsProvider = pendingRequestsProvider self.logger = logger self.socketConnectionStatusPublisher = socketConnectionStatusPublisher @@ -83,8 +77,7 @@ public class AuthClient { /// - Parameters: /// - requestId: authentication request id /// - signature: CACAO signature of requested message - public func respond(requestId: RPCID, signature: CacaoSignature) async throws { - guard let account = account else { throw Errors.unknownWalletAddress } + public func respond(requestId: RPCID, signature: CacaoSignature, from account: Account) async throws { try await walletRespondService.respond(requestId: requestId, signature: signature, account: account) } @@ -96,8 +89,7 @@ public class AuthClient { /// Query pending authentication requests /// - Returns: Pending authentication requests - public func getPendingRequests() throws -> [AuthRequest] { - guard let account = account else { throw Errors.unknownWalletAddress } + public func getPendingRequests(account: Account) throws -> [AuthRequest] { return try pendingRequestsProvider.getPendingRequests(account: account) } diff --git a/Sources/Auth/AuthClientFactory.swift b/Sources/Auth/AuthClientFactory.swift index 9a84c4f17..5fc6cb188 100644 --- a/Sources/Auth/AuthClientFactory.swift +++ b/Sources/Auth/AuthClientFactory.swift @@ -4,7 +4,6 @@ public struct AuthClientFactory { public static func create( metadata: AppMetadata, - account: Account?, projectId: String, signerFactory: SignerFactory, networkingClient: NetworkingInteractor, @@ -18,7 +17,6 @@ public struct AuthClientFactory { return AuthClientFactory.create( metadata: metadata, - account: account, projectId: projectId, signerFactory: signerFactory, logger: logger, @@ -32,7 +30,6 @@ public struct AuthClientFactory { static func create( metadata: AppMetadata, - account: Account?, projectId: String, signerFactory: SignerFactory, logger: ConsoleLogging, @@ -51,7 +48,7 @@ public struct AuthClientFactory { let messageSigner = messageSignerFactory.create(projectId: projectId) let appRespondSubscriber = AppRespondSubscriber(networkingInteractor: networkingClient, logger: logger, rpcHistory: history, signatureVerifier: messageSigner, pairingRegisterer: pairingRegisterer, messageFormatter: messageFormatter) let walletErrorResponder = WalletErrorResponder(networkingInteractor: networkingClient, logger: logger, kms: kms, rpcHistory: history) - let walletRequestSubscriber = WalletRequestSubscriber(networkingInteractor: networkingClient, logger: logger, kms: kms, messageFormatter: messageFormatter, address: account?.address, walletErrorResponder: walletErrorResponder, pairingRegisterer: pairingRegisterer) + let walletRequestSubscriber = WalletRequestSubscriber(networkingInteractor: networkingClient, logger: logger, kms: kms, walletErrorResponder: walletErrorResponder, pairingRegisterer: pairingRegisterer) let walletRespondService = WalletRespondService(networkingInteractor: networkingClient, logger: logger, kms: kms, rpcHistory: history, walletErrorResponder: walletErrorResponder) let pendingRequestsProvider = PendingRequestsProvider(rpcHistory: history) @@ -60,7 +57,6 @@ public struct AuthClientFactory { appRespondSubscriber: appRespondSubscriber, walletRequestSubscriber: walletRequestSubscriber, walletRespondService: walletRespondService, - account: account, pendingRequestsProvider: pendingRequestsProvider, logger: logger, socketConnectionStatusPublisher: networkingClient.socketConnectionStatusPublisher, diff --git a/Sources/Auth/AuthConfig.swift b/Sources/Auth/AuthConfig.swift deleted file mode 100644 index 472d2b267..000000000 --- a/Sources/Auth/AuthConfig.swift +++ /dev/null @@ -1,8 +0,0 @@ -import Foundation - -extension Auth { - struct Config { - let account: Account? - let signerFactory: SignerFactory - } -} diff --git a/Sources/Auth/Services/Common/SIWEMessageFormatter.swift b/Sources/Auth/Services/Common/SIWEMessageFormatter.swift index 5c69caa90..6661955b9 100644 --- a/Sources/Auth/Services/Common/SIWEMessageFormatter.swift +++ b/Sources/Auth/Services/Common/SIWEMessageFormatter.swift @@ -7,13 +7,13 @@ protocol SIWEMessageFormatting { struct SIWEMessageFormatter: SIWEMessageFormatting { func formatMessage(from payload: AuthPayload, address: String) -> String? { - guard let chain = Blockchain(payload.chainId) else {return nil} + guard let chain = Blockchain(payload.chainId) else { return nil } let message = SIWEMessage(domain: payload.domain, uri: payload.aud, address: address, version: payload.version, nonce: payload.nonce, - chainId: chain.reference, + chainId: chain.reference, iat: payload.iat, nbf: payload.nbf, exp: payload.exp, diff --git a/Sources/Auth/Services/Signer/MessageSigner.swift b/Sources/Auth/Services/Signer/MessageSigner.swift index a53ebea78..5f6b0593c 100644 --- a/Sources/Auth/Services/Signer/MessageSigner.swift +++ b/Sources/Auth/Services/Signer/MessageSigner.swift @@ -1,36 +1,77 @@ import Foundation public protocol MessageSignatureVerifying { - func verify(signature: CacaoSignature, message: String, address: String, chainId: String) async throws + func verify(signature: CacaoSignature, + message: String, + address: String, + chainId: String + ) async throws } public protocol MessageSigning { - func sign(message: String, privateKey: Data, type: CacaoSignatureType) throws -> CacaoSignature + func sign(request: AuthRequest, + address: String, + privateKey: Data, + type: CacaoSignatureType + ) throws -> CacaoSignature } -struct MessageSigner: MessageSignatureVerifying, MessageSigning { +public protocol MessageFormatting { + func format(request: AuthRequest, address: String) throws -> String +} + +public typealias AuthMessageSigner = MessageSignatureVerifying & MessageSigning & MessageFormatting + +struct MessageSigner: AuthMessageSigner { enum Errors: Error { case utf8EncodingFailed + case malformedRequestParams } private let signer: EthereumSigner private let eip191Verifier: EIP191Verifier private let eip1271Verifier: EIP1271Verifier + private let messageFormatter: SIWEMessageFormatting - init(signer: EthereumSigner, eip191Verifier: EIP191Verifier, eip1271Verifier: EIP1271Verifier) { + init(signer: Signer, eip191Verifier: EIP191Verifier, eip1271Verifier: EIP1271Verifier, messageFormatter: SIWEMessageFormatting) { self.signer = signer self.eip191Verifier = eip191Verifier self.eip1271Verifier = eip1271Verifier + self.messageFormatter = messageFormatter + } + + func format(request: AuthRequest, address: String) throws -> String { + guard let message = messageFormatter.formatMessage( + from: request.params.payloadParams, + address: address + ) else { throw Errors.malformedRequestParams } + + return message } - func sign(message: String, privateKey: Data, type: CacaoSignatureType) throws -> CacaoSignature { - guard let messageData = message.data(using: .utf8) else { throw Errors.utf8EncodingFailed } + func sign(request: AuthRequest, + address: String, + privateKey: Data, + type: CacaoSignatureType + ) throws -> CacaoSignature { + + let message = try format(request: request, address: address) + + guard let messageData = message.data(using: .utf8)else { + throw Errors.utf8EncodingFailed + } + let signature = try signer.sign(message: prefixed(messageData), with: privateKey) return CacaoSignature(t: type, s: signature.hex()) } - func verify(signature: CacaoSignature, message: String, address: String, chainId: String) async throws { + func verify(signature: CacaoSignature, + message: String, + address: String, + chainId: String + ) async throws { + guard let messageData = message.data(using: .utf8) else { throw Errors.utf8EncodingFailed } diff --git a/Sources/Auth/Services/Signer/MessageSignerFactory.swift b/Sources/Auth/Services/Signer/MessageSignerFactory.swift index 7441b2f16..5ce135e6c 100644 --- a/Sources/Auth/Services/Signer/MessageSignerFactory.swift +++ b/Sources/Auth/Services/Signer/MessageSignerFactory.swift @@ -8,18 +8,19 @@ public struct MessageSignerFactory { self.signerFactory = signerFactory } - public func create() -> MessageSigning & MessageSignatureVerifying { + public func create() -> AuthMessageSigner { return create(projectId: Networking.projectId) } - func create(projectId: String) -> MessageSigning & MessageSignatureVerifying { + func create(projectId: String) -> AuthMessageSigner { return MessageSigner( signer: signerFactory.createEthereumSigner(), eip191Verifier: EIP191Verifier(signer: signerFactory.createEthereumSigner()), eip1271Verifier: EIP1271Verifier( projectId: projectId, httpClient: HTTPNetworkClient(host: "rpc.walletconnect.com"), - signer: signerFactory.createEthereumSigner() + signer: signerFactory.createEthereumSigner(), + messageFormatter: SIWEMessageFormatter() ) ) } diff --git a/Sources/Auth/Services/Wallet/PendingRequestsProvider.swift b/Sources/Auth/Services/Wallet/PendingRequestsProvider.swift index 35bb47265..e13b827ff 100644 --- a/Sources/Auth/Services/Wallet/PendingRequestsProvider.swift +++ b/Sources/Auth/Services/Wallet/PendingRequestsProvider.swift @@ -11,9 +11,8 @@ class PendingRequestsProvider { let pendingRequests: [AuthRequest] = rpcHistory.getPending() .filter {$0.request.method == "wc_authRequest"} .compactMap { - guard let params = try? $0.request.params?.get(AuthRequestParams.self), - let message = SIWEMessageFormatter().formatMessage(from: params.payloadParams, address: account.address) else {return nil} - return AuthRequest(id: $0.request.id!, message: message) + guard let params = try? $0.request.params?.get(AuthRequestParams.self) else { return nil } + return AuthRequest(id: $0.request.id!, params: params) } return pendingRequests } diff --git a/Sources/Auth/Services/Wallet/WalletRequestSubscriber.swift b/Sources/Auth/Services/Wallet/WalletRequestSubscriber.swift index d2bb83ef2..fc5ac15a0 100644 --- a/Sources/Auth/Services/Wallet/WalletRequestSubscriber.swift +++ b/Sources/Auth/Services/Wallet/WalletRequestSubscriber.swift @@ -5,44 +5,32 @@ class WalletRequestSubscriber { private let networkingInteractor: NetworkInteracting private let logger: ConsoleLogging private let kms: KeyManagementServiceProtocol - private let address: String? private var publishers = [AnyCancellable]() - private let messageFormatter: SIWEMessageFormatting private let walletErrorResponder: WalletErrorResponder private let pairingRegisterer: PairingRegisterer var onRequest: ((AuthRequest) -> Void)? - init(networkingInteractor: NetworkInteracting, - logger: ConsoleLogging, - kms: KeyManagementServiceProtocol, - messageFormatter: SIWEMessageFormatting, - address: String?, - walletErrorResponder: WalletErrorResponder, - pairingRegisterer: PairingRegisterer) { + init( + networkingInteractor: NetworkInteracting, + logger: ConsoleLogging, + kms: KeyManagementServiceProtocol, + walletErrorResponder: WalletErrorResponder, + pairingRegisterer: PairingRegisterer) + { self.networkingInteractor = networkingInteractor self.logger = logger self.kms = kms - self.address = address - self.messageFormatter = messageFormatter self.walletErrorResponder = walletErrorResponder self.pairingRegisterer = pairingRegisterer subscribeForRequest() } private func subscribeForRequest() { - guard let address = address else { return } - pairingRegisterer.register(method: AuthRequestProtocolMethod()) .sink { [unowned self] (payload: RequestSubscriptionPayload) in logger.debug("WalletRequestSubscriber: Received request") - guard let message = messageFormatter.formatMessage(from: payload.request.payloadParams, address: address) else { - Task(priority: .high) { - try? await walletErrorResponder.respondError(AuthError.malformedRequestParams, requestId: payload.id) - } - return - } pairingRegisterer.activate(pairingTopic: payload.topic) - onRequest?(.init(id: payload.id, message: message)) + onRequest?(AuthRequest(id: payload.id, params: payload.request)) }.store(in: &publishers) } } diff --git a/Sources/Auth/Types/AuthPayload.swift b/Sources/Auth/Types/AuthPayload.swift index 1329f5265..d3f893394 100644 --- a/Sources/Auth/Types/AuthPayload.swift +++ b/Sources/Auth/Types/AuthPayload.swift @@ -1,20 +1,20 @@ import Foundation -struct AuthPayload: Codable, Equatable { - let domain: String - let aud: String - let version: String - let nonce: String - let chainId: String - let type: String - let iat: String - let nbf: String? - let exp: String? - let statement: String? - let requestId: String? - let resources: [String]? +public struct AuthPayload: Codable, Equatable { + public let domain: String + public let aud: String + public let version: String + public let nonce: String + public let chainId: String + public let type: String + public let iat: String + public let nbf: String? + public let exp: String? + public let statement: String? + public let requestId: String? + public let resources: [String]? - init(requestParams: RequestParams, iat: String) { + public init(requestParams: RequestParams, iat: String) { self.type = "eip4361" self.chainId = requestParams.chainId self.domain = requestParams.domain diff --git a/Sources/Auth/Types/ProtocolRPCParams/AuthRequestParams.swift b/Sources/Auth/Types/ProtocolRPCParams/AuthRequestParams.swift index 427b29303..bebe206c3 100644 --- a/Sources/Auth/Types/ProtocolRPCParams/AuthRequestParams.swift +++ b/Sources/Auth/Types/ProtocolRPCParams/AuthRequestParams.swift @@ -1,13 +1,13 @@ import Foundation /// wc_authRequest RPC method request param -struct AuthRequestParams: Codable, Equatable { - let requester: Requester - let payloadParams: AuthPayload +public struct AuthRequestParams: Codable, Equatable { + public let requester: Requester + public let payloadParams: AuthPayload } extension AuthRequestParams { - struct Requester: Codable, Equatable { + public struct Requester: Codable, Equatable { let publicKey: String let metadata: AppMetadata } diff --git a/Sources/Auth/Types/Public/AuthRequest.swift b/Sources/Auth/Types/Public/AuthRequest.swift index f431ccb4d..c0a23041e 100644 --- a/Sources/Auth/Types/Public/AuthRequest.swift +++ b/Sources/Auth/Types/Public/AuthRequest.swift @@ -2,6 +2,5 @@ import Foundation public struct AuthRequest: Equatable, Codable { public let id: RPCID - /// EIP-4361: Sign-In with Ethereum message - public let message: String + public let params: AuthRequestParams } From 63ffd0d364d37f4f97b8fedb49960d5d212d8d5d Mon Sep 17 00:00:00 2001 From: Artur Guseinov Date: Fri, 2 Dec 2022 18:51:54 +0500 Subject: [PATCH 24/30] Formatting moved out of MessageSigner --- Example/IntegrationTests/Auth/AuthTests.swift | 22 ++++++++-------- .../Auth/Signer/CacaoSignerTests.swift | 1 + .../AuthRequest/AuthRequestInteractor.swift | 7 +++-- Sources/Auth/Auth.swift | 4 ++- Sources/Auth/AuthConfig.swift | 7 +++++ .../Common/SIWEMessageFormatter.swift | 7 +++-- .../Auth/Services/Signer/MessageSigner.swift | 26 ++++++------------- .../Signer/MessageSignerFactory.swift | 6 ++--- .../Wallet/PendingRequestsProvider.swift | 2 +- .../Wallet/WalletRequestSubscriber.swift | 4 ++- Sources/Auth/Types/AuthPayload.swift | 2 +- .../ProtocolRPCParams/AuthRequestParams.swift | 8 +++--- Sources/Auth/Types/Public/AuthRequest.swift | 2 +- 13 files changed, 53 insertions(+), 45 deletions(-) create mode 100644 Sources/Auth/AuthConfig.swift diff --git a/Example/IntegrationTests/Auth/AuthTests.swift b/Example/IntegrationTests/Auth/AuthTests.swift index 94b9abab2..4e69eb973 100644 --- a/Example/IntegrationTests/Auth/AuthTests.swift +++ b/Example/IntegrationTests/Auth/AuthTests.swift @@ -14,6 +14,8 @@ final class AuthTests: XCTestCase { var appAuthClient: AuthClient! var walletAuthClient: AuthClient! + + let walletAccount = Account(chainIdentifier: "eip155:1", address: "0x724d0D2DaD3fbB0C168f947B87Fa5DBe36F1A8bf")! let prvKey = Data(hex: "462c1dad6832d7d96ccf87bd6a686a4110e114aaaebd5512e552c0e3a87b480f") let eip1271Signature = "0xc1505719b2504095116db01baaf276361efd3a73c28cf8cc28dabefa945b8d536011289ac0a3b048600c1e692ff173ca944246cf7ceb319ac2262d27b395c82b1c" private var publishers = [AnyCancellable]() @@ -22,13 +24,12 @@ final class AuthTests: XCTestCase { setupClients() } - private func setupClients(address: String = "0x724d0D2DaD3fbB0C168f947B87Fa5DBe36F1A8bf", iatProvider: IATProvider = DefaultIATProvider()) { - let walletAccount = Account(chainIdentifier: "eip155:1", address: address)! + private func setupClients(iatProvider: IATProvider = DefaultIATProvider()) { (appPairingClient, appAuthClient) = makeClients(prefix: "🤖 App", iatProvider: iatProvider) - (walletPairingClient, walletAuthClient) = makeClients(prefix: "🐶 Wallet", account: walletAccount, iatProvider: iatProvider) + (walletPairingClient, walletAuthClient) = makeClients(prefix: "🐶 Wallet", iatProvider: iatProvider) } - func makeClients(prefix: String, account: Account? = nil, iatProvider: IATProvider) -> (PairingClient, AuthClient) { + func makeClients(prefix: String, iatProvider: IATProvider) -> (PairingClient, AuthClient) { let logger = ConsoleLogger(suffix: prefix, loggingLevel: .debug) let keychain = KeychainStorageMock() let relayClient = RelayClient(relayHost: InputConfig.relayHost, projectId: InputConfig.projectId, keychainStorage: keychain, socketFactory: DefaultSocketFactory(), logger: logger) @@ -48,7 +49,6 @@ final class AuthTests: XCTestCase { let authClient = AuthClientFactory.create( metadata: AppMetadata(name: name, description: "", url: "", icons: [""]), - account: account, projectId: InputConfig.projectId, signerFactory: DefaultSignerFactory(), logger: logger, @@ -83,8 +83,8 @@ final class AuthTests: XCTestCase { Task(priority: .high) { let signerFactory = DefaultSignerFactory() let signer = MessageSignerFactory(signerFactory: signerFactory).create(projectId: InputConfig.projectId) - let signature = try! signer.sign(message: request.message, privateKey: prvKey, type: .eip191) - try! await walletAuthClient.respond(requestId: request.id, signature: signature) + let signature = try! signer.sign(request: request, address: walletAccount.address, privateKey: prvKey, type: .eip191) + try! await walletAuthClient.respond(requestId: request.id, signature: signature, from: walletAccount) } } .store(in: &publishers) @@ -97,7 +97,7 @@ final class AuthTests: XCTestCase { } func testEIP1271RespondSuccess() async { - setupClients(address: "0x2faf83c542b68f1b4cdc0e770e8cb9f567b08f71", iatProvider: IATProviderMock()) + let account = Account(chainIdentifier: "eip155:1", address: "0x2faf83c542b68f1b4cdc0e770e8cb9f567b08f71")! let responseExpectation = expectation(description: "successful response delivered") let uri = try! await appPairingClient.create() @@ -117,7 +117,7 @@ final class AuthTests: XCTestCase { walletAuthClient.authRequestPublisher.sink { [unowned self] request in Task(priority: .high) { let signature = CacaoSignature(t: .eip1271, s: eip1271Signature) - try! await walletAuthClient.respond(requestId: request.id, signature: signature) + try! await walletAuthClient.respond(requestId: request.id, signature: signature, from: account) } } .store(in: &publishers) @@ -138,7 +138,7 @@ final class AuthTests: XCTestCase { walletAuthClient.authRequestPublisher.sink { [unowned self] request in Task(priority: .high) { let signature = CacaoSignature(t: .eip1271, s: eip1271Signature) - try! await walletAuthClient.respond(requestId: request.id, signature: signature) + try! await walletAuthClient.respond(requestId: request.id, signature: signature, from: walletAccount) } } .store(in: &publishers) @@ -181,7 +181,7 @@ final class AuthTests: XCTestCase { Task(priority: .high) { let invalidSignature = "438effc459956b57fcd9f3dac6c675f9cee88abf21acab7305e8e32aa0303a883b06dcbd956279a7a2ca21ffa882ff55cc22e8ab8ec0f3fe90ab45f306938cfa1b" let cacaoSignature = CacaoSignature(t: .eip191, s: invalidSignature) - try! await walletAuthClient.respond(requestId: request.id, signature: cacaoSignature) + try! await walletAuthClient.respond(requestId: request.id, signature: cacaoSignature, from: walletAccount) } } .store(in: &publishers) diff --git a/Example/IntegrationTests/Auth/Signer/CacaoSignerTests.swift b/Example/IntegrationTests/Auth/Signer/CacaoSignerTests.swift index 23a3db381..df61c26c7 100644 --- a/Example/IntegrationTests/Auth/Signer/CacaoSignerTests.swift +++ b/Example/IntegrationTests/Auth/Signer/CacaoSignerTests.swift @@ -29,6 +29,7 @@ class CacaoSignerTest: XCTestCase { let signature = CacaoSignature(t: .eip191, s: "0x438effc459956b57fcd9f3dac6c675f9cee88abf21acab7305e8e32aa0303a883b06dcbd956279a7a2ca21ffa882ff55cc22e8ab8ec0f3fe90ab45f306938cfa1b") func testCacaoSign() throws { + let request = XCTAssertEqual(try signer.sign(message: message, privateKey: privateKey, type: .eip191), signature) } diff --git a/Example/Showcase/Classes/PresentationLayer/Wallet/AuthRequest/AuthRequestInteractor.swift b/Example/Showcase/Classes/PresentationLayer/Wallet/AuthRequest/AuthRequestInteractor.swift index 84eba3103..21bd6541c 100644 --- a/Example/Showcase/Classes/PresentationLayer/Wallet/AuthRequest/AuthRequestInteractor.swift +++ b/Example/Showcase/Classes/PresentationLayer/Wallet/AuthRequest/AuthRequestInteractor.swift @@ -10,7 +10,7 @@ final class AuthRequestInteractor { func approve(request: AuthRequest) async throws { let privateKey = Data(hex: "e56da0e170b5e09a8bb8f1b693392c7d56c3739a9c75740fbc558a2877868540") let signature = try signer.sign( - request: request, + payload: request.payload, address: account.address, privateKey: privateKey, type: .eip191) @@ -22,6 +22,9 @@ final class AuthRequestInteractor { } func formatted(request: AuthRequest) -> String { - return try! signer.format(request: request, address: account.address) + return SIWEMessageFormatter().formatMessage( + from: request.payload, + address: account.address + )! } } diff --git a/Sources/Auth/Auth.swift b/Sources/Auth/Auth.swift index 461e721c9..263e742e6 100644 --- a/Sources/Auth/Auth.swift +++ b/Sources/Auth/Auth.swift @@ -28,12 +28,14 @@ public class Auth { ) }() + private static var config: Config? + private init() { } /// Auth instance wallet config method. For DApp usage /// - Parameters: /// - signerFactory: Auth signers factory static public func configure(signerFactory: SignerFactory) { - Auth.config = Auth.Config(account: nil, signerFactory: signerFactory) + Auth.config = Auth.Config(signerFactory: signerFactory) } } diff --git a/Sources/Auth/AuthConfig.swift b/Sources/Auth/AuthConfig.swift new file mode 100644 index 000000000..bf5c09c24 --- /dev/null +++ b/Sources/Auth/AuthConfig.swift @@ -0,0 +1,7 @@ +import Foundation + +extension Auth { + struct Config { + let signerFactory: SignerFactory + } +} diff --git a/Sources/Auth/Services/Common/SIWEMessageFormatter.swift b/Sources/Auth/Services/Common/SIWEMessageFormatter.swift index 6661955b9..a9c5b8ed2 100644 --- a/Sources/Auth/Services/Common/SIWEMessageFormatter.swift +++ b/Sources/Auth/Services/Common/SIWEMessageFormatter.swift @@ -5,8 +5,11 @@ protocol SIWEMessageFormatting { func formatMessage(from payload: CacaoPayload) throws -> String } -struct SIWEMessageFormatter: SIWEMessageFormatting { - func formatMessage(from payload: AuthPayload, address: String) -> String? { +public struct SIWEMessageFormatter: SIWEMessageFormatting { + + public init() { } + + public func formatMessage(from payload: AuthPayload, address: String) -> String? { guard let chain = Blockchain(payload.chainId) else { return nil } let message = SIWEMessage(domain: payload.domain, uri: payload.aud, diff --git a/Sources/Auth/Services/Signer/MessageSigner.swift b/Sources/Auth/Services/Signer/MessageSigner.swift index 5f6b0593c..a58d6dfbd 100644 --- a/Sources/Auth/Services/Signer/MessageSigner.swift +++ b/Sources/Auth/Services/Signer/MessageSigner.swift @@ -9,18 +9,14 @@ public protocol MessageSignatureVerifying { } public protocol MessageSigning { - func sign(request: AuthRequest, + func sign(payload: AuthPayload, address: String, privateKey: Data, type: CacaoSignatureType ) throws -> CacaoSignature } -public protocol MessageFormatting { - func format(request: AuthRequest, address: String) throws -> String -} - -public typealias AuthMessageSigner = MessageSignatureVerifying & MessageSigning & MessageFormatting +public typealias AuthMessageSigner = MessageSignatureVerifying & MessageSigning struct MessageSigner: AuthMessageSigner { @@ -34,29 +30,23 @@ struct MessageSigner: AuthMessageSigner { private let eip1271Verifier: EIP1271Verifier private let messageFormatter: SIWEMessageFormatting - init(signer: Signer, eip191Verifier: EIP191Verifier, eip1271Verifier: EIP1271Verifier, messageFormatter: SIWEMessageFormatting) { + init(signer: EthereumSigner, eip191Verifier: EIP191Verifier, eip1271Verifier: EIP1271Verifier, messageFormatter: SIWEMessageFormatting) { self.signer = signer self.eip191Verifier = eip191Verifier self.eip1271Verifier = eip1271Verifier self.messageFormatter = messageFormatter } - func format(request: AuthRequest, address: String) throws -> String { - guard let message = messageFormatter.formatMessage( - from: request.params.payloadParams, - address: address - ) else { throw Errors.malformedRequestParams } - - return message - } - - func sign(request: AuthRequest, + func sign(payload: AuthPayload, address: String, privateKey: Data, type: CacaoSignatureType ) throws -> CacaoSignature { - let message = try format(request: request, address: address) + guard let message = messageFormatter.formatMessage( + from: payload, + address: address + ) else { throw Errors.malformedRequestParams } guard let messageData = message.data(using: .utf8)else { throw Errors.utf8EncodingFailed diff --git a/Sources/Auth/Services/Signer/MessageSignerFactory.swift b/Sources/Auth/Services/Signer/MessageSignerFactory.swift index 5ce135e6c..88d56d374 100644 --- a/Sources/Auth/Services/Signer/MessageSignerFactory.swift +++ b/Sources/Auth/Services/Signer/MessageSignerFactory.swift @@ -19,9 +19,9 @@ public struct MessageSignerFactory { eip1271Verifier: EIP1271Verifier( projectId: projectId, httpClient: HTTPNetworkClient(host: "rpc.walletconnect.com"), - signer: signerFactory.createEthereumSigner(), - messageFormatter: SIWEMessageFormatter() - ) + signer: signerFactory.createEthereumSigner() + ), + messageFormatter: SIWEMessageFormatter() ) } } diff --git a/Sources/Auth/Services/Wallet/PendingRequestsProvider.swift b/Sources/Auth/Services/Wallet/PendingRequestsProvider.swift index e13b827ff..4aa8c04c0 100644 --- a/Sources/Auth/Services/Wallet/PendingRequestsProvider.swift +++ b/Sources/Auth/Services/Wallet/PendingRequestsProvider.swift @@ -12,7 +12,7 @@ class PendingRequestsProvider { .filter {$0.request.method == "wc_authRequest"} .compactMap { guard let params = try? $0.request.params?.get(AuthRequestParams.self) else { return nil } - return AuthRequest(id: $0.request.id!, params: params) + return AuthRequest(id: $0.request.id!, payload: params.payloadParams) } return pendingRequests } diff --git a/Sources/Auth/Services/Wallet/WalletRequestSubscriber.swift b/Sources/Auth/Services/Wallet/WalletRequestSubscriber.swift index fc5ac15a0..b47f1cbf2 100644 --- a/Sources/Auth/Services/Wallet/WalletRequestSubscriber.swift +++ b/Sources/Auth/Services/Wallet/WalletRequestSubscriber.swift @@ -30,7 +30,9 @@ class WalletRequestSubscriber { .sink { [unowned self] (payload: RequestSubscriptionPayload) in logger.debug("WalletRequestSubscriber: Received request") pairingRegisterer.activate(pairingTopic: payload.topic) - onRequest?(AuthRequest(id: payload.id, params: payload.request)) + + let request = AuthRequest(id: payload.id, payload: payload.request.payloadParams) + onRequest?(request) }.store(in: &publishers) } } diff --git a/Sources/Auth/Types/AuthPayload.swift b/Sources/Auth/Types/AuthPayload.swift index d3f893394..621df1ea3 100644 --- a/Sources/Auth/Types/AuthPayload.swift +++ b/Sources/Auth/Types/AuthPayload.swift @@ -14,7 +14,7 @@ public struct AuthPayload: Codable, Equatable { public let requestId: String? public let resources: [String]? - public init(requestParams: RequestParams, iat: String) { + init(requestParams: RequestParams, iat: String) { self.type = "eip4361" self.chainId = requestParams.chainId self.domain = requestParams.domain diff --git a/Sources/Auth/Types/ProtocolRPCParams/AuthRequestParams.swift b/Sources/Auth/Types/ProtocolRPCParams/AuthRequestParams.swift index bebe206c3..427b29303 100644 --- a/Sources/Auth/Types/ProtocolRPCParams/AuthRequestParams.swift +++ b/Sources/Auth/Types/ProtocolRPCParams/AuthRequestParams.swift @@ -1,13 +1,13 @@ import Foundation /// wc_authRequest RPC method request param -public struct AuthRequestParams: Codable, Equatable { - public let requester: Requester - public let payloadParams: AuthPayload +struct AuthRequestParams: Codable, Equatable { + let requester: Requester + let payloadParams: AuthPayload } extension AuthRequestParams { - public struct Requester: Codable, Equatable { + struct Requester: Codable, Equatable { let publicKey: String let metadata: AppMetadata } diff --git a/Sources/Auth/Types/Public/AuthRequest.swift b/Sources/Auth/Types/Public/AuthRequest.swift index c0a23041e..b5095751c 100644 --- a/Sources/Auth/Types/Public/AuthRequest.swift +++ b/Sources/Auth/Types/Public/AuthRequest.swift @@ -2,5 +2,5 @@ import Foundation public struct AuthRequest: Equatable, Codable { public let id: RPCID - public let params: AuthRequestParams + public let payload: AuthPayload } From bf32779061337daa0b0f28f66d77aff22ed9a985 Mon Sep 17 00:00:00 2001 From: Artur Guseinov Date: Fri, 2 Dec 2022 19:09:58 +0500 Subject: [PATCH 25/30] IntegrationTests --- Example/IntegrationTests/Auth/AuthTests.swift | 4 +++- .../Auth/Signer/CacaoSignerTests.swift | 24 +++++++++++++++++-- 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/Example/IntegrationTests/Auth/AuthTests.swift b/Example/IntegrationTests/Auth/AuthTests.swift index 4e69eb973..8bede13a1 100644 --- a/Example/IntegrationTests/Auth/AuthTests.swift +++ b/Example/IntegrationTests/Auth/AuthTests.swift @@ -83,7 +83,7 @@ final class AuthTests: XCTestCase { Task(priority: .high) { let signerFactory = DefaultSignerFactory() let signer = MessageSignerFactory(signerFactory: signerFactory).create(projectId: InputConfig.projectId) - let signature = try! signer.sign(request: request, address: walletAccount.address, privateKey: prvKey, type: .eip191) + let signature = try! signer.sign(payload: request.payload, address: walletAccount.address, privateKey: prvKey, type: .eip191) try! await walletAuthClient.respond(requestId: request.id, signature: signature, from: walletAccount) } } @@ -97,6 +97,8 @@ final class AuthTests: XCTestCase { } func testEIP1271RespondSuccess() async { + setupClients(iatProvider: IATProviderMock()) + let account = Account(chainIdentifier: "eip155:1", address: "0x2faf83c542b68f1b4cdc0e770e8cb9f567b08f71")! let responseExpectation = expectation(description: "successful response delivered") diff --git a/Example/IntegrationTests/Auth/Signer/CacaoSignerTests.swift b/Example/IntegrationTests/Auth/Signer/CacaoSignerTests.swift index df61c26c7..137b8cb5d 100644 --- a/Example/IntegrationTests/Auth/Signer/CacaoSignerTests.swift +++ b/Example/IntegrationTests/Auth/Signer/CacaoSignerTests.swift @@ -26,11 +26,31 @@ class CacaoSignerTest: XCTestCase { - https://example.com/my-web2-claim.json """ + let payload = AuthPayload(requestParams: RequestParams( + domain: "service.invalid", + chainId: "eip155:1", + nonce: "32891756", + aud: "https://service.invalid/login", + nbf: nil, + exp: nil, + statement: "I accept the ServiceOrg Terms of Service: https://service.invalid/tos", + requestId: nil, + resources: [ + "ipfs://bafybeiemxf5abjwjbikoz4mc3a3dla6ual3jsgpdr4cjr3oz3evfyavhwq/", + "https://example.com/my-web2-claim.json" + ] + ), iat: "2021-09-30T16:25:24Z") + let signature = CacaoSignature(t: .eip191, s: "0x438effc459956b57fcd9f3dac6c675f9cee88abf21acab7305e8e32aa0303a883b06dcbd956279a7a2ca21ffa882ff55cc22e8ab8ec0f3fe90ab45f306938cfa1b") func testCacaoSign() throws { - let request = - XCTAssertEqual(try signer.sign(message: message, privateKey: privateKey, type: .eip191), signature) + let address = "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2" + let formatted = SIWEMessageFormatter().formatMessage( + from: payload, + address: address + ) + XCTAssertEqual(formatted, message) + XCTAssertEqual(try signer.sign(payload: payload, address: address, privateKey: privateKey, type: .eip191), signature) } func testCacaoVerify() async throws { From 7b64bce2b37259f06374ae4b34ad8b81a2e73c89 Mon Sep 17 00:00:00 2001 From: Artur Guseinov Date: Fri, 2 Dec 2022 19:43:12 +0500 Subject: [PATCH 26/30] UnitTests repaired --- .../AuthTests/AppRespondSubscriberTests.swift | 24 +++++++++++-------- Tests/AuthTests/Stubs/MessageSignerMock.swift | 21 ++++++++++++++++ .../Stubs/RequestSubscriptionPayload.swift | 5 ++-- .../WalletRequestSubscriberTests.swift | 20 ++++++++-------- 4 files changed, 47 insertions(+), 23 deletions(-) create mode 100644 Tests/AuthTests/Stubs/MessageSignerMock.swift diff --git a/Tests/AuthTests/AppRespondSubscriberTests.swift b/Tests/AuthTests/AppRespondSubscriberTests.swift index 1cf14a850..72f3f4f51 100644 --- a/Tests/AuthTests/AppRespondSubscriberTests.swift +++ b/Tests/AuthTests/AppRespondSubscriberTests.swift @@ -8,21 +8,20 @@ import XCTest import JSONRPC class AppRespondSubscriberTests: XCTestCase { + var networkingInteractor: NetworkingInteractorMock! var sut: AppRespondSubscriber! var messageFormatter: SIWEMessageFormatter! var rpcHistory: RPCHistory! let defaultTimeout: TimeInterval = 0.01 - let walletAccount = Account(chainIdentifier: "eip155:1", address: "0x724d0D2DaD3fbB0C168f947B87Fa5DBe36F1A8bf")! - let prvKey = Data(hex: "462c1dad6832d7d96ccf87bd6a686a4110e114aaaebd5512e552c0e3a87b480f") - var messageSigner: (MessageSigning & MessageSignatureVerifying)! + var messageSigner: AuthMessageSigner! var pairingStorage: WCPairingStorageMock! var pairingRegisterer: PairingRegistererMock! override func setUp() { networkingInteractor = NetworkingInteractorMock() messageFormatter = SIWEMessageFormatter() - messageSigner = MessageSignerFactory(signerFactory: SignerFactoryMock()).create(projectId: "project-id") + messageSigner = MessageSignerMock() rpcHistory = RPCHistoryFactory.createForNetwork(keyValueStorage: RuntimeKeyValueStorage()) pairingStorage = WCPairingStorageMock() pairingRegisterer = PairingRegistererMock() @@ -41,6 +40,12 @@ class AppRespondSubscriberTests: XCTestCase { // set history record for a request let topic = "topic" let requestId: RPCID = RPCID(1234) + + let params = AuthRequestParams.stub() + let compromissedParams = AuthRequestParams.stub(nonce: "Compromissed nonce") + + XCTAssertNotEqual(params.payloadParams, compromissedParams.payloadParams) + let request = RPCRequest(method: "wc_authRequest", params: AuthRequestParams.stub(), id: requestId.right!) try! rpcHistory.set(request, forTopic: topic, emmitedBy: .local) @@ -53,13 +58,12 @@ class AppRespondSubscriberTests: XCTestCase { } // subscribe on compromised cacao - let header = CacaoHeader(t: "eip4361") - let payload = CacaoPayload(params: AuthPayload.stub(nonce: "compromised nonce"), didpkh: DIDPKH(account: walletAccount)) - - let message = try! messageFormatter.formatMessage(from: payload) - let cacaoSignature = try! messageSigner.sign(message: message, privateKey: prvKey, type: .eip191) + let account = Account(chainIdentifier: "eip155:1", address: "0x724d0D2DaD3fbB0C168f947B87Fa5DBe36F1A8bf")! + let cacaoHeader = CacaoHeader(t: "eip4361") + let cacaoPayload = CacaoPayload(params: compromissedParams.payloadParams, didpkh: DIDPKH(account: account)) + let cacaoSignature = CacaoSignature(t: .eip191, s: "") - let cacao = Cacao(h: header, p: payload, s: cacaoSignature) + let cacao = Cacao(h: cacaoHeader, p: cacaoPayload, s: cacaoSignature) let response = RPCResponse(id: requestId, result: cacao) networkingInteractor.responsePublisherSubject.send((topic, request, response)) diff --git a/Tests/AuthTests/Stubs/MessageSignerMock.swift b/Tests/AuthTests/Stubs/MessageSignerMock.swift new file mode 100644 index 000000000..4275cd1b9 --- /dev/null +++ b/Tests/AuthTests/Stubs/MessageSignerMock.swift @@ -0,0 +1,21 @@ +import Foundation +import Auth + +struct MessageSignerMock: AuthMessageSigner { + + func verify(signature: CacaoSignature, + message: String, + address: String, + chainId: String + ) async throws { + + } + + func sign(payload: AuthPayload, + address: String, + privateKey: Data, + type: CacaoSignatureType + ) throws -> CacaoSignature { + return CacaoSignature(t: .eip191, s: "") + } +} diff --git a/Tests/AuthTests/Stubs/RequestSubscriptionPayload.swift b/Tests/AuthTests/Stubs/RequestSubscriptionPayload.swift index 7944b241b..baf9546bf 100644 --- a/Tests/AuthTests/Stubs/RequestSubscriptionPayload.swift +++ b/Tests/AuthTests/Stubs/RequestSubscriptionPayload.swift @@ -4,11 +4,10 @@ import WalletConnectNetworking @testable import Auth extension AuthRequestParams { - static func stub(id: RPCID) -> AuthRequestParams { + static func stub(id: RPCID, iat: String) -> AuthRequestParams { let appMetadata = AppMetadata(name: "", description: "", url: "", icons: []) let requester = AuthRequestParams.Requester(publicKey: "", metadata: appMetadata) - let issueAt = ISO8601DateFormatter().string(from: Date()) - let payload = AuthPayload(requestParams: RequestParams.stub(), iat: issueAt) + let payload = AuthPayload(requestParams: RequestParams.stub(), iat: iat) return AuthRequestParams(requester: requester, payloadParams: payload) } } diff --git a/Tests/AuthTests/WalletRequestSubscriberTests.swift b/Tests/AuthTests/WalletRequestSubscriberTests.swift index de7dbe28d..d94567432 100644 --- a/Tests/AuthTests/WalletRequestSubscriberTests.swift +++ b/Tests/AuthTests/WalletRequestSubscriberTests.swift @@ -23,31 +23,31 @@ class WalletRequestSubscriberTests: XCTestCase { sut = WalletRequestSubscriber(networkingInteractor: networkingInteractor, logger: ConsoleLoggerMock(), kms: KeyManagementServiceMock(), - messageFormatter: messageFormatter, address: "", walletErrorResponder: walletErrorResponder, pairingRegisterer: pairingRegisterer) } func testSubscribeRequest() { - let expectedMessage = "Expected Message" + let iat = ISO8601DateFormatter().string(from: Date()) + let expectedPayload = AuthPayload(requestParams: .stub(), iat: iat) let expectedRequestId: RPCID = RPCID(1234) let messageExpectation = expectation(description: "receives formatted message") - messageFormatter.formattedMessage = expectedMessage - var messageId: RPCID! - var message: String! + + var requestId: RPCID! + var requestPayload: AuthPayload! sut.onRequest = { request in - messageId = request.id - message = request.message + requestId = request.id + requestPayload = request.payload messageExpectation.fulfill() } - let payload = RequestSubscriptionPayload(id: expectedRequestId, topic: "123", request: AuthRequestParams.stub(id: expectedRequestId)) + let payload = RequestSubscriptionPayload(id: expectedRequestId, topic: "123", request: AuthRequestParams.stub(id: expectedRequestId, iat: iat)) pairingRegisterer.subject.send(payload) wait(for: [messageExpectation], timeout: defaultTimeout) XCTAssertTrue(pairingRegisterer.isActivateCalled) - XCTAssertEqual(message, expectedMessage) - XCTAssertEqual(messageId, expectedRequestId) + XCTAssertEqual(requestPayload, expectedPayload) + XCTAssertEqual(requestId, expectedRequestId) } } From 327e44b2cf51b03bd1ce470654dca970e8b8effe Mon Sep 17 00:00:00 2001 From: Artur Guseinov Date: Mon, 5 Dec 2022 12:54:02 +0500 Subject: [PATCH 27/30] version bump --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8ff4a9a95..a71b4ce7e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -28,7 +28,7 @@ jobs: - name: Setup Xcode Version uses: maxim-lobanov/setup-xcode@v1 with: - xcode-version: '13.4.1' + xcode-version: 14.1 - uses: actions/cache@v2 with: From ed8372b3b05962667552257f12f02d7279aa3b74 Mon Sep 17 00:00:00 2001 From: Artur Guseinov Date: Wed, 7 Dec 2022 14:29:38 +0500 Subject: [PATCH 28/30] Format message public interface --- .../Auth/Signer/CacaoSignerTests.swift | 2 +- .../AuthRequest/AuthRequestInteractor.swift | 6 +-- Sources/Auth/AuthClient.swift | 4 ++ .../Services/App/AppRespondSubscriber.swift | 6 ++- .../Common/SIWEMessageFormatter.swift | 37 +++++++++++-------- .../Auth/Services/Signer/MessageSigner.swift | 6 +-- .../Mocks/SIWEMessageFormatterMock.swift | 2 +- .../AuthTests/SIWEMessageFormatterTests.swift | 16 ++++---- 8 files changed, 45 insertions(+), 34 deletions(-) diff --git a/Example/IntegrationTests/Auth/Signer/CacaoSignerTests.swift b/Example/IntegrationTests/Auth/Signer/CacaoSignerTests.swift index 137b8cb5d..c6481015b 100644 --- a/Example/IntegrationTests/Auth/Signer/CacaoSignerTests.swift +++ b/Example/IntegrationTests/Auth/Signer/CacaoSignerTests.swift @@ -45,7 +45,7 @@ class CacaoSignerTest: XCTestCase { func testCacaoSign() throws { let address = "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2" - let formatted = SIWEMessageFormatter().formatMessage( + let formatted = try SIWEMessageFormatter().formatMessage( from: payload, address: address ) diff --git a/Example/Showcase/Classes/PresentationLayer/Wallet/AuthRequest/AuthRequestInteractor.swift b/Example/Showcase/Classes/PresentationLayer/Wallet/AuthRequest/AuthRequestInteractor.swift index 21bd6541c..816d0b398 100644 --- a/Example/Showcase/Classes/PresentationLayer/Wallet/AuthRequest/AuthRequestInteractor.swift +++ b/Example/Showcase/Classes/PresentationLayer/Wallet/AuthRequest/AuthRequestInteractor.swift @@ -22,9 +22,9 @@ final class AuthRequestInteractor { } func formatted(request: AuthRequest) -> String { - return SIWEMessageFormatter().formatMessage( - from: request.payload, + return try! Auth.instance.formatMessage( + payload: request.payload, address: account.address - )! + ) } } diff --git a/Sources/Auth/AuthClient.swift b/Sources/Auth/AuthClient.swift index 6dcc9827e..43847d3ef 100644 --- a/Sources/Auth/AuthClient.swift +++ b/Sources/Auth/AuthClient.swift @@ -93,6 +93,10 @@ public class AuthClient { return try pendingRequestsProvider.getPendingRequests(account: account) } + public func formatMessage(payload: AuthPayload, address: String) throws -> String { + return try SIWEMessageFormatter().formatMessage(from: payload, address: address) + } + private func setUpPublishers() { appRespondSubscriber.onResponse = { [unowned self] (id, result) in authResponsePublisherSubject.send((id, result)) diff --git a/Sources/Auth/Services/App/AppRespondSubscriber.swift b/Sources/Auth/Services/App/AppRespondSubscriber.swift index 99b8410b8..2aaaba9e9 100644 --- a/Sources/Auth/Services/App/AppRespondSubscriber.swift +++ b/Sources/Auth/Services/App/AppRespondSubscriber.swift @@ -49,7 +49,11 @@ class AppRespondSubscriber { let message = try? messageFormatter.formatMessage(from: cacao.p) else { self.onResponse?(requestId, .failure(.malformedResponseParams)); return } - guard messageFormatter.formatMessage(from: requestPayload.payloadParams, address: address) == message + guard + let recovered = try? messageFormatter.formatMessage( + from: requestPayload.payloadParams, + address: address + ), recovered == message else { self.onResponse?(requestId, .failure(.messageCompromised)); return } Task(priority: .high) { diff --git a/Sources/Auth/Services/Common/SIWEMessageFormatter.swift b/Sources/Auth/Services/Common/SIWEMessageFormatter.swift index a9c5b8ed2..5e8c82d57 100644 --- a/Sources/Auth/Services/Common/SIWEMessageFormatter.swift +++ b/Sources/Auth/Services/Common/SIWEMessageFormatter.swift @@ -1,28 +1,35 @@ import Foundation protocol SIWEMessageFormatting { - func formatMessage(from authPayload: AuthPayload, address: String) -> String? + func formatMessage(from payload: AuthPayload, address: String) throws -> String func formatMessage(from payload: CacaoPayload) throws -> String } public struct SIWEMessageFormatter: SIWEMessageFormatting { + enum Errors: Error { + case invalidChainID + } + public init() { } - public func formatMessage(from payload: AuthPayload, address: String) -> String? { - guard let chain = Blockchain(payload.chainId) else { return nil } - let message = SIWEMessage(domain: payload.domain, - uri: payload.aud, - address: address, - version: payload.version, - nonce: payload.nonce, - chainId: chain.reference, - iat: payload.iat, - nbf: payload.nbf, - exp: payload.exp, - statement: payload.statement, - requestId: payload.requestId, - resources: payload.resources + public func formatMessage(from payload: AuthPayload, address: String) throws -> String { + guard let chain = Blockchain(payload.chainId) else { + throw Errors.invalidChainID + } + let message = SIWEMessage( + domain: payload.domain, + uri: payload.aud, + address: address, + version: payload.version, + nonce: payload.nonce, + chainId: chain.reference, + iat: payload.iat, + nbf: payload.nbf, + exp: payload.exp, + statement: payload.statement, + requestId: payload.requestId, + resources: payload.resources ) return message.formatted } diff --git a/Sources/Auth/Services/Signer/MessageSigner.swift b/Sources/Auth/Services/Signer/MessageSigner.swift index a58d6dfbd..7af8792a2 100644 --- a/Sources/Auth/Services/Signer/MessageSigner.swift +++ b/Sources/Auth/Services/Signer/MessageSigner.swift @@ -22,7 +22,6 @@ struct MessageSigner: AuthMessageSigner { enum Errors: Error { case utf8EncodingFailed - case malformedRequestParams } private let signer: EthereumSigner @@ -43,10 +42,7 @@ struct MessageSigner: AuthMessageSigner { type: CacaoSignatureType ) throws -> CacaoSignature { - guard let message = messageFormatter.formatMessage( - from: payload, - address: address - ) else { throw Errors.malformedRequestParams } + let message = try messageFormatter.formatMessage(from: payload, address: address) guard let messageData = message.data(using: .utf8)else { throw Errors.utf8EncodingFailed diff --git a/Tests/AuthTests/Mocks/SIWEMessageFormatterMock.swift b/Tests/AuthTests/Mocks/SIWEMessageFormatterMock.swift index e15d682be..64adc7c96 100644 --- a/Tests/AuthTests/Mocks/SIWEMessageFormatterMock.swift +++ b/Tests/AuthTests/Mocks/SIWEMessageFormatterMock.swift @@ -4,7 +4,7 @@ import Foundation class SIWEMessageFormatterMock: SIWEMessageFormatting { var formattedMessage: String! - func formatMessage(from authPayload: AuthPayload, address: String) -> String? { + func formatMessage(from authPayload: AuthPayload, address: String) throws -> String { return formattedMessage } diff --git a/Tests/AuthTests/SIWEMessageFormatterTests.swift b/Tests/AuthTests/SIWEMessageFormatterTests.swift index 1b14c21a4..859b2cf41 100644 --- a/Tests/AuthTests/SIWEMessageFormatterTests.swift +++ b/Tests/AuthTests/SIWEMessageFormatterTests.swift @@ -10,7 +10,7 @@ class SIWEMessageFormatterTests: XCTestCase { sut = SIWEMessageFormatter() } - func testFormatMessage() { + func testFormatMessage() throws { let expectedMessage = """ service.invalid wants you to sign in with your Ethereum account: @@ -27,11 +27,11 @@ class SIWEMessageFormatterTests: XCTestCase { - ipfs://bafybeiemxf5abjwjbikoz4mc3a3dla6ual3jsgpdr4cjr3oz3evfyavhwq/ - https://example.com/my-web2-claim.json """ - let message = sut.formatMessage(from: AuthPayload.stub(), address: address) + let message = try sut.formatMessage(from: AuthPayload.stub(), address: address) XCTAssertEqual(message, expectedMessage) } - func testNilStatement() { + func testNilStatement() throws { let expectedMessage = """ service.invalid wants you to sign in with your Ethereum account: @@ -46,14 +46,14 @@ class SIWEMessageFormatterTests: XCTestCase { - ipfs://bafybeiemxf5abjwjbikoz4mc3a3dla6ual3jsgpdr4cjr3oz3evfyavhwq/ - https://example.com/my-web2-claim.json """ - let message = sut.formatMessage( + let message = try sut.formatMessage( from: AuthPayload.stub( requestParams: RequestParams.stub(statement: nil)), address: address) XCTAssertEqual(message, expectedMessage) } - func testNilResources() { + func testNilResources() throws { let expectedMessage = """ service.invalid wants you to sign in with your Ethereum account: @@ -67,14 +67,14 @@ class SIWEMessageFormatterTests: XCTestCase { Nonce: 32891756 Issued At: 2021-09-30T16:25:24Z """ - let message = sut.formatMessage( + let message = try sut.formatMessage( from: AuthPayload.stub( requestParams: RequestParams.stub(resources: nil)), address: address) XCTAssertEqual(message, expectedMessage) } - func testNilAllOptionalParams() { + func testNilAllOptionalParams() throws { let expectedMessage = """ service.invalid wants you to sign in with your Ethereum account: @@ -86,7 +86,7 @@ class SIWEMessageFormatterTests: XCTestCase { Nonce: 32891756 Issued At: 2021-09-30T16:25:24Z """ - let message = sut.formatMessage( + let message = try sut.formatMessage( from: AuthPayload.stub( requestParams: RequestParams.stub(statement: nil, resources: nil)), From 7afcc2241b972e35ee3b858ce8c8337622c338c2 Mon Sep 17 00:00:00 2001 From: flypaper0 Date: Wed, 7 Dec 2022 11:28:06 +0000 Subject: [PATCH 29/30] Set User Agent --- Sources/WalletConnectRelay/PackageConfig.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/WalletConnectRelay/PackageConfig.json b/Sources/WalletConnectRelay/PackageConfig.json index 4a5b368a0..4a72d8551 100644 --- a/Sources/WalletConnectRelay/PackageConfig.json +++ b/Sources/WalletConnectRelay/PackageConfig.json @@ -1 +1 @@ -{"version": "1.0.6"} +{"version": "1.0.7"} From 6a02605b1968739cb4d2c48d70b1d309de43f603 Mon Sep 17 00:00:00 2001 From: Artur Guseinov Date: Wed, 7 Dec 2022 17:13:48 +0500 Subject: [PATCH 30/30] Set User Agent --- Sources/WalletConnectRelay/PackageConfig.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/WalletConnectRelay/PackageConfig.json b/Sources/WalletConnectRelay/PackageConfig.json index 4a72d8551..48f893bf2 100644 --- a/Sources/WalletConnectRelay/PackageConfig.json +++ b/Sources/WalletConnectRelay/PackageConfig.json @@ -1 +1 @@ -{"version": "1.0.7"} +{"version": "1.1.0"}