diff --git a/.swiftpm/xcode/xcshareddata/xcschemes/WalletConnect.xcscheme b/.swiftpm/xcode/xcshareddata/xcschemes/WalletConnect.xcscheme index 138656d6e..5bb6db710 100644 --- a/.swiftpm/xcode/xcshareddata/xcschemes/WalletConnect.xcscheme +++ b/.swiftpm/xcode/xcshareddata/xcschemes/WalletConnect.xcscheme @@ -76,6 +76,34 @@ ReferencedContainer = "container:"> + + + + + + + + + + + + + + + + String { - let data = try JSONEncoder().encode(self) - guard let string = String(data: data, encoding: .utf8) else { - throw DataConversionError.dataToStringFailed - } - return string - } -} diff --git a/Sources/WalletConnect/Engine/PairingEngine.swift b/Sources/WalletConnect/Engine/PairingEngine.swift index 7335a723b..714aec988 100644 --- a/Sources/WalletConnect/Engine/PairingEngine.swift +++ b/Sources/WalletConnect/Engine/PairingEngine.swift @@ -1,10 +1,9 @@ import Foundation import Combine import WalletConnectUtils - +import WalletConnectKMS final class PairingEngine { - var onApprovalAcknowledgement: ((Pairing) -> Void)? var onSessionProposal: ((SessionProposal)->())? var onPairingApproved: ((Pairing, SessionPermissions, RelayProtocolOptions)->())? @@ -12,7 +11,7 @@ final class PairingEngine { private let wcSubscriber: WCSubscribing private let relayer: WalletConnectRelaying - private let crypto: CryptoStorageProtocol + private let kms: KeyManagementServiceProtocol private let sequencesStore: PairingSequenceStorage private var appMetadata: AppMetadata private var publishers = [AnyCancellable]() @@ -21,14 +20,14 @@ final class PairingEngine { private let topicInitializer: () -> String? init(relay: WalletConnectRelaying, - crypto: CryptoStorageProtocol, + kms: KeyManagementServiceProtocol, subscriber: WCSubscribing, sequencesStore: PairingSequenceStorage, metadata: AppMetadata, logger: ConsoleLogging, topicGenerator: @escaping () -> String? = String.generateTopic) { self.relayer = relay - self.crypto = crypto + self.kms = kms self.wcSubscriber = subscriber self.appMetadata = metadata self.sequencesStore = sequencesStore @@ -65,7 +64,7 @@ final class PairingEngine { return nil } - let publicKey = try! crypto.createX25519KeyPair() + let publicKey = try! kms.createX25519KeyPair() let relay = RelayProtocolOptions(protocol: "waku", params: nil) let uri = WalletConnectURI(topic: topic, publicKey: publicKey.hexRepresentation, isController: false, relay: relay) @@ -86,8 +85,8 @@ final class PairingEngine { throw WalletConnectError.internal(.pairWithExistingPairingForbidden) } - let selfPublicKey = try! crypto.createX25519KeyPair() - let agreementKeys = try! crypto.performKeyAgreement(selfPublicKey: selfPublicKey, peerPublicKey: proposal.proposer.publicKey) + let selfPublicKey = try! kms.createX25519KeyPair() + let agreementKeys = try! kms.performKeyAgreement(selfPublicKey: selfPublicKey, peerPublicKey: proposal.proposer.publicKey) let settledTopic = agreementKeys.derivedTopic() let pendingPairing = PairingSequence.buildResponded(proposal: proposal, agreementKeys: agreementKeys) @@ -98,7 +97,7 @@ final class PairingEngine { wcSubscriber.setSubscription(topic: settledTopic) sequencesStore.setSequence(settledPairing) - try? crypto.setAgreementSecret(agreementKeys, topic: settledTopic) + try? kms.setAgreementSecret(agreementKeys, topic: settledTopic) let approval = PairingType.ApprovalParams( relay: proposal.relay, @@ -186,10 +185,10 @@ final class PairingEngine { return } - let agreementKeys = try! crypto.performKeyAgreement(selfPublicKey: try! pairing.getPublicKey(), peerPublicKey: approveParams.responder.publicKey) + let agreementKeys = try! kms.performKeyAgreement(selfPublicKey: try! pairing.getPublicKey(), peerPublicKey: approveParams.responder.publicKey) let settledTopic = agreementKeys.sharedSecret.sha256().toHexString() - try? crypto.setAgreementSecret(agreementKeys, topic: settledTopic) + try? kms.setAgreementSecret(agreementKeys, topic: settledTopic) let proposal = pendingPairing.proposal let settledPairing = PairingSequence.buildAcknowledged(approval: approveParams, proposal: proposal, agreementKeys: agreementKeys) @@ -237,8 +236,8 @@ final class PairingEngine { } let sessionProposal = payloadParams.request.params do { - if let pairingAgreementSecret = try crypto.getAgreementSecret(for: sessionProposal.signal.params.topic) { - try crypto.setAgreementSecret(pairingAgreementSecret, topic: sessionProposal.topic) + if let pairingAgreementSecret = try kms.getAgreementSecret(for: sessionProposal.signal.params.topic) { + try kms.setAgreementSecret(pairingAgreementSecret, topic: sessionProposal.topic) } else { relayer.respondError(for: payload, reason: .missingOrInvalid("agreement keys")) return @@ -274,8 +273,8 @@ final class PairingEngine { private func setupExpirationHandling() { sequencesStore.onSequenceExpiration = { [weak self] topic, publicKey in - self?.crypto.deletePrivateKey(for: publicKey) - self?.crypto.deleteAgreementSecret(for: topic) + self?.kms.deletePrivateKey(for: publicKey) + self?.kms.deleteAgreementSecret(for: topic) } } diff --git a/Sources/WalletConnect/Engine/SessionEngine.swift b/Sources/WalletConnect/Engine/SessionEngine.swift index a6ac0be19..e9c24ed2d 100644 --- a/Sources/WalletConnect/Engine/SessionEngine.swift +++ b/Sources/WalletConnect/Engine/SessionEngine.swift @@ -1,6 +1,7 @@ import Foundation import Combine import WalletConnectUtils +import WalletConnectKMS final class SessionEngine { var onSessionPayloadRequest: ((Request)->())? @@ -16,21 +17,21 @@ final class SessionEngine { private let sequencesStore: SessionSequenceStorage private let wcSubscriber: WCSubscribing private let relayer: WalletConnectRelaying - private let crypto: CryptoStorageProtocol + private let kms: KeyManagementServiceProtocol private var metadata: AppMetadata private var publishers = [AnyCancellable]() private let logger: ConsoleLogging private let topicInitializer: () -> String? init(relay: WalletConnectRelaying, - crypto: CryptoStorageProtocol, + kms: KeyManagementServiceProtocol, subscriber: WCSubscribing, sequencesStore: SessionSequenceStorage, metadata: AppMetadata, logger: ConsoleLogging, topicGenerator: @escaping () -> String? = String.generateTopic) { self.relayer = relay - self.crypto = crypto + self.kms = kms self.metadata = metadata self.wcSubscriber = subscriber self.sequencesStore = sequencesStore @@ -64,7 +65,7 @@ final class SessionEngine { } logger.debug("Propose Session on topic: \(pendingSessionTopic)") - let publicKey = try! crypto.createX25519KeyPair() + let publicKey = try! kms.createX25519KeyPair() let proposal = SessionProposal( topic: pendingSessionTopic, @@ -78,8 +79,8 @@ final class SessionEngine { sequencesStore.setSequence(pendingSession) wcSubscriber.setSubscription(topic: pendingSessionTopic) - let pairingAgreementSecret = try! crypto.getAgreementSecret(for: settledPairing.topic)! - try! crypto.setAgreementSecret(pairingAgreementSecret, topic: proposal.topic) + let pairingAgreementSecret = try! kms.getAgreementSecret(for: settledPairing.topic)! + try! kms.setAgreementSecret(pairingAgreementSecret, topic: proposal.topic) let request = PairingType.PayloadParams.Request(method: .sessionPropose, params: proposal) let pairingPayloadParams = PairingType.PayloadParams(request: request) @@ -97,8 +98,8 @@ final class SessionEngine { func approve(proposal: SessionProposal, accounts: Set) { logger.debug("Approve session") - let selfPublicKey = try! crypto.createX25519KeyPair() - let agreementKeys = try! crypto.performKeyAgreement(selfPublicKey: selfPublicKey, peerPublicKey: proposal.proposer.publicKey) + let selfPublicKey = try! kms.createX25519KeyPair() + let agreementKeys = try! kms.performKeyAgreement(selfPublicKey: selfPublicKey, peerPublicKey: proposal.proposer.publicKey) let settledTopic = agreementKeys.derivedTopic() let pendingSession = SessionSequence.buildResponded(proposal: proposal, agreementKeys: agreementKeys, metadata: metadata) @@ -115,7 +116,7 @@ final class SessionEngine { sequencesStore.setSequence(pendingSession) wcSubscriber.setSubscription(topic: proposal.topic) - try! crypto.setAgreementSecret(agreementKeys, topic: settledTopic) + try! kms.setAgreementSecret(agreementKeys, topic: settledTopic) sequencesStore.setSequence(settledSession) wcSubscriber.setSubscription(topic: settledTopic) @@ -295,9 +296,9 @@ final class SessionEngine { let agreementKeys: AgreementSecret do { let publicKey = try session.getPublicKey() - agreementKeys = try crypto.performKeyAgreement(selfPublicKey: publicKey, peerPublicKey: approveParams.responder.publicKey) + agreementKeys = try kms.performKeyAgreement(selfPublicKey: publicKey, peerPublicKey: approveParams.responder.publicKey) settledTopic = agreementKeys.derivedTopic() - try crypto.setAgreementSecret(agreementKeys, topic: settledTopic) + try kms.setAgreementSecret(agreementKeys, topic: settledTopic) } catch { relayer.respondError(for: payload, reason: .missingOrInvalid("agreement keys")) return @@ -449,8 +450,8 @@ final class SessionEngine { private func setupExpirationHandling() { sequencesStore.onSequenceExpiration = { [weak self] topic, publicKey in - self?.crypto.deletePrivateKey(for: publicKey) - self?.crypto.deleteAgreementSecret(for: topic) + self?.kms.deletePrivateKey(for: publicKey) + self?.kms.deleteAgreementSecret(for: topic) } } @@ -487,8 +488,8 @@ final class SessionEngine { break case .error: wcSubscriber.removeSubscription(topic: proposeParams.topic) - crypto.deletePrivateKey(for: proposeParams.proposer.publicKey) - crypto.deleteAgreementSecret(for: topic) + kms.deletePrivateKey(for: proposeParams.proposer.publicKey) + kms.deleteAgreementSecret(for: topic) sequencesStore.delete(topic: proposeParams.topic) } } @@ -504,7 +505,7 @@ final class SessionEngine { switch result { case .response: guard let settledSession = sequencesStore.getSequence(forTopic: settledTopic) else {return} - crypto.deleteAgreementSecret(for: topic) + kms.deleteAgreementSecret(for: topic) wcSubscriber.removeSubscription(topic: topic) sequencesStore.delete(topic: topic) let sessionSuccess = Session( @@ -519,9 +520,9 @@ final class SessionEngine { wcSubscriber.removeSubscription(topic: settledTopic) sequencesStore.delete(topic: topic) sequencesStore.delete(topic: settledTopic) - crypto.deleteAgreementSecret(for: topic) - crypto.deleteAgreementSecret(for: settledTopic) - crypto.deletePrivateKey(for: pendingSession.publicKey) + kms.deleteAgreementSecret(for: topic) + kms.deleteAgreementSecret(for: settledTopic) + kms.deletePrivateKey(for: pendingSession.publicKey) } } diff --git a/Sources/WalletConnect/Extensions/String.swift b/Sources/WalletConnect/Extensions/String.swift index 6d27e68dc..4ce9e7d55 100644 --- a/Sources/WalletConnect/Extensions/String.swift +++ b/Sources/WalletConnect/Extensions/String.swift @@ -44,23 +44,3 @@ extension String { } } -extension String { - func toHexEncodedString(uppercase: Bool = true, prefix: String = "", separator: String = "") -> String { - return unicodeScalars.map { prefix + .init($0.value, radix: 16, uppercase: uppercase) } .joined(separator: separator) - } -} - -extension String: GenericPasswordConvertible { - - init(rawRepresentation data: D) throws where D : ContiguousBytes { - let bytes = data.withUnsafeBytes { Data(Array($0)) } - guard let string = String(data: bytes, encoding: .utf8) else { - fatalError() // FIXME: Throw error - } - self = string - } - - var rawRepresentation: Data { - self.data(using: .utf8) ?? Data() - } -} diff --git a/Sources/WalletConnect/KeyManagementServiceProtocol.swift b/Sources/WalletConnect/KeyManagementServiceProtocol.swift new file mode 100644 index 000000000..906a5c8cd --- /dev/null +++ b/Sources/WalletConnect/KeyManagementServiceProtocol.swift @@ -0,0 +1,17 @@ + +import Foundation +import WalletConnectKMS + +// TODO: Come up with better naming conventions +public protocol KeyManagementServiceProtocol { + func createX25519KeyPair() throws -> AgreementPublicKey + func setPrivateKey(_ privateKey: AgreementPrivateKey) throws + func setAgreementSecret(_ agreementSecret: AgreementSecret, topic: String) throws + func getPrivateKey(for publicKey: AgreementPublicKey) throws -> AgreementPrivateKey? + func getAgreementSecret(for topic: String) throws -> AgreementSecret? + func deletePrivateKey(for publicKey: String) + func deleteAgreementSecret(for topic: String) + func performKeyAgreement(selfPublicKey: AgreementPublicKey, peerPublicKey hexRepresentation: String) throws -> AgreementSecret +} + +extension KeyManagementService: KeyManagementServiceProtocol {} diff --git a/Sources/WalletConnect/Relay/WalletConnectRelay.swift b/Sources/WalletConnect/Relay/WalletConnectRelay.swift index 64d25655b..19451eb77 100644 --- a/Sources/WalletConnect/Relay/WalletConnectRelay.swift +++ b/Sources/WalletConnect/Relay/WalletConnectRelay.swift @@ -2,6 +2,7 @@ import Foundation import Combine import WalletConnectUtils +import WalletConnectKMS struct WCResponse { let topic: String @@ -37,7 +38,7 @@ class WalletConnectRelay: WalletConnectRelaying { var onResponse: ((WCResponse) -> Void)? private var networkRelayer: NetworkRelaying - private let jsonRpcSerializer: JSONRPCSerializing + private let serializer: Serializing private let jsonRpcHistory: JsonRpcHistoryRecording var transportConnectionPublisher: AnyPublisher { @@ -58,11 +59,11 @@ class WalletConnectRelay: WalletConnectRelaying { let logger: ConsoleLogging init(networkRelayer: NetworkRelaying, - jsonRpcSerializer: JSONRPCSerializing, + serializer: Serializing, logger: ConsoleLogging, jsonRpcHistory: JsonRpcHistoryRecording) { self.networkRelayer = networkRelayer - self.jsonRpcSerializer = jsonRpcSerializer + self.serializer = serializer self.logger = logger self.jsonRpcHistory = jsonRpcHistory setUpPublishers() @@ -75,7 +76,7 @@ class WalletConnectRelay: WalletConnectRelaying { func request(topic: String, payload: WCRequest, completion: ((Result, JSONRPCErrorResponse>)->())?) { do { try jsonRpcHistory.set(topic: topic, request: payload, chainId: getChainId(payload)) - let message = try jsonRpcSerializer.serialize(topic: topic, encodable: payload) + let message = try serializer.serialize(topic: topic, encodable: payload) networkRelayer.publish(topic: topic, payload: message) { [weak self] error in guard let self = self else {return} if let error = error { @@ -108,7 +109,7 @@ class WalletConnectRelay: WalletConnectRelaying { do { _ = try jsonRpcHistory.resolve(response: response) - let message = try jsonRpcSerializer.serialize(topic: topic, encodable: response.value) + let message = try serializer.serialize(topic: topic, encodable: response.value) logger.debug("Responding....topic: \(topic)") networkRelayer.publish(topic: topic, payload: message) { error in completion(error) @@ -159,11 +160,11 @@ class WalletConnectRelay: WalletConnectRelaying { } private func manageSubscription(_ topic: String, _ message: String) { - if let deserializedJsonRpcRequest: WCRequest = jsonRpcSerializer.tryDeserialize(topic: topic, message: message) { + if let deserializedJsonRpcRequest: WCRequest = serializer.tryDeserialize(topic: topic, message: message) { handleWCRequest(topic: topic, request: deserializedJsonRpcRequest) - } else if let deserializedJsonRpcResponse: JSONRPCResponse = jsonRpcSerializer.tryDeserialize(topic: topic, message: message) { + } else if let deserializedJsonRpcResponse: JSONRPCResponse = serializer.tryDeserialize(topic: topic, message: message) { handleJsonRpcResponse(response: deserializedJsonRpcResponse) - } else if let deserializedJsonRpcError: JSONRPCErrorResponse = jsonRpcSerializer.tryDeserialize(topic: topic, message: message) { + } else if let deserializedJsonRpcError: JSONRPCErrorResponse = serializer.tryDeserialize(topic: topic, message: message) { handleJsonRpcErrorResponse(response: deserializedJsonRpcError) } else { logger.warn("Warning: WalletConnect Relay - Received unknown object type from networking relay") diff --git a/Sources/WalletConnect/Serialiser/JSONRPCSerialiserError.swift b/Sources/WalletConnect/Serialiser/JSONRPCSerialiserError.swift deleted file mode 100644 index 87b10edf9..000000000 --- a/Sources/WalletConnect/Serialiser/JSONRPCSerialiserError.swift +++ /dev/null @@ -1,7 +0,0 @@ -// - -import Foundation - -enum JSONRPCSerializerError: String, Error { - case messageToShort = "Error: message is too short" -} diff --git a/Sources/WalletConnect/Serializing.swift b/Sources/WalletConnect/Serializing.swift new file mode 100644 index 000000000..abcf159b6 --- /dev/null +++ b/Sources/WalletConnect/Serializing.swift @@ -0,0 +1,10 @@ + +import Foundation +import WalletConnectKMS + +public protocol Serializing { + func serialize(topic: String, encodable: Encodable) throws -> String + func tryDeserialize(topic: String, message: String) -> T? +} + +extension Serializer: Serializing {} diff --git a/Sources/WalletConnect/Types/Pairing/PairingSequence.swift b/Sources/WalletConnect/Types/Pairing/PairingSequence.swift index 4f0be00c9..bc153adc1 100644 --- a/Sources/WalletConnect/Types/Pairing/PairingSequence.swift +++ b/Sources/WalletConnect/Types/Pairing/PairingSequence.swift @@ -1,4 +1,5 @@ import Foundation +import WalletConnectKMS struct PairingSequence: ExpirableSequence { let topic: String diff --git a/Sources/WalletConnect/Types/Session/SessionSequence.swift b/Sources/WalletConnect/Types/Session/SessionSequence.swift index 0ae11da31..f5734d256 100644 --- a/Sources/WalletConnect/Types/Session/SessionSequence.swift +++ b/Sources/WalletConnect/Types/Session/SessionSequence.swift @@ -1,4 +1,5 @@ import Foundation +import WalletConnectKMS struct SessionSequence: ExpirableSequence { diff --git a/Sources/WalletConnect/WalletConnectClient.swift b/Sources/WalletConnect/WalletConnectClient.swift index 089e249c5..0659746aa 100644 --- a/Sources/WalletConnect/WalletConnectClient.swift +++ b/Sources/WalletConnect/WalletConnectClient.swift @@ -2,6 +2,7 @@ import Foundation import Relayer import WalletConnectUtils +import WalletConnectKMS #if os(iOS) import UIKit #endif @@ -25,7 +26,7 @@ public final class WalletConnectClient { private let pairingEngine: PairingEngine private let sessionEngine: SessionEngine private let relay: WalletConnectRelaying - private let crypto: Crypto + private let kms: KeyManagementService private let pairingQueue = DispatchQueue(label: "com.walletconnect.sdk.client.pairing", qos: .userInitiated) private let history: JsonRpcHistory @@ -41,23 +42,23 @@ public final class WalletConnectClient { /// /// WalletConnect Client is not a singleton but once you create an instance, you should not deinitialize it. Usually only one instance of a client is required in the application. public convenience init(metadata: AppMetadata, projectId: String, relayHost: String, keyValueStorage: KeyValueStorage = UserDefaults.standard) { - self.init(metadata: metadata, projectId: projectId, relayHost: relayHost, logger: ConsoleLogger(loggingLevel: .off), keychain: KeychainStorage(), keyValueStorage: keyValueStorage) + self.init(metadata: metadata, projectId: projectId, relayHost: relayHost, logger: ConsoleLogger(loggingLevel: .off), kms: KeyManagementService(serviceIdentifier: "com.walletconnect.sdk"), keyValueStorage: keyValueStorage) } - init(metadata: AppMetadata, projectId: String, relayHost: String, logger: ConsoleLogging, keychain: KeychainStorage, keyValueStorage: KeyValueStorage) { + init(metadata: AppMetadata, projectId: String, relayHost: String, logger: ConsoleLogging, kms: KeyManagementService, keyValueStorage: KeyValueStorage) { self.metadata = metadata self.logger = logger // try? keychain.deleteAll() // Use for cleanup while lifecycles are not handled yet, but FIXME whenever - self.crypto = Crypto(keychain: keychain) + self.kms = kms let relayer = Relayer(relayHost: relayHost, projectId: projectId, keyValueStorage: keyValueStorage, logger: logger) - let serializer = JSONRPCSerializer(crypto: crypto) + let serializer = Serializer(kms: kms) self.history = JsonRpcHistory(logger: logger, keyValueStore: KeyValueStore(defaults: keyValueStorage, identifier: StorageDomainIdentifiers.jsonRpcHistory.rawValue)) - self.relay = WalletConnectRelay(networkRelayer: relayer, jsonRpcSerializer: serializer, logger: logger, jsonRpcHistory: history) + self.relay = WalletConnectRelay(networkRelayer: relayer, serializer: serializer, logger: logger, jsonRpcHistory: history) let pairingSequencesStore = PairingStorage(storage: SequenceStore(storage: keyValueStorage, identifier: StorageDomainIdentifiers.pairings.rawValue)) let sessionSequencesStore = SessionStorage(storage: SequenceStore(storage: keyValueStorage, identifier: StorageDomainIdentifiers.sessions.rawValue)) - self.pairingEngine = PairingEngine(relay: relay, crypto: crypto, subscriber: WCSubscriber(relay: relay, logger: logger), sequencesStore: pairingSequencesStore, metadata: metadata, logger: logger) + self.pairingEngine = PairingEngine(relay: relay, kms: kms, subscriber: WCSubscriber(relay: relay, logger: logger), sequencesStore: pairingSequencesStore, metadata: metadata, logger: logger) - self.sessionEngine = SessionEngine(relay: relay, crypto: crypto, subscriber: WCSubscriber(relay: relay, logger: logger), sequencesStore: sessionSequencesStore, metadata: metadata, logger: logger) + self.sessionEngine = SessionEngine(relay: relay, kms: kms, subscriber: WCSubscriber(relay: relay, logger: logger), sequencesStore: sessionSequencesStore, metadata: metadata, logger: logger) setUpEnginesCallbacks() } @@ -70,21 +71,21 @@ public final class WalletConnectClient { /// /// WalletConnect Client is not a singleton but once you create an instance, you should not deinitialize it. Usually only one instance of a client is required in the application. public convenience init(metadata: AppMetadata, relayer: Relayer, keyValueStorage: KeyValueStorage = UserDefaults.standard) { - self.init(metadata: metadata, relayer: relayer, logger: ConsoleLogger(loggingLevel: .off), keychain: KeychainStorage(), keyValueStorage: keyValueStorage) + self.init(metadata: metadata, relayer: relayer, logger: ConsoleLogger(loggingLevel: .off), kms: KeyManagementService(serviceIdentifier: "com.walletconnect.sdk"), keyValueStorage: keyValueStorage) } - init(metadata: AppMetadata, relayer: Relayer, logger: ConsoleLogging, keychain: KeychainStorage, keyValueStorage: KeyValueStorage) { + init(metadata: AppMetadata, relayer: Relayer, logger: ConsoleLogging, kms: KeyManagementService, keyValueStorage: KeyValueStorage) { self.metadata = metadata self.logger = logger // try? keychain.deleteAll() // Use for cleanup while lifecycles are not handled yet, but FIXME whenever - self.crypto = Crypto(keychain: keychain) - let serializer = JSONRPCSerializer(crypto: crypto) + self.kms = kms + let serializer = Serializer(kms: kms) self.history = JsonRpcHistory(logger: logger, keyValueStore: KeyValueStore(defaults: keyValueStorage, identifier: StorageDomainIdentifiers.jsonRpcHistory.rawValue)) - self.relay = WalletConnectRelay(networkRelayer: relayer, jsonRpcSerializer: serializer, logger: logger, jsonRpcHistory: history) + self.relay = WalletConnectRelay(networkRelayer: relayer, serializer: serializer, logger: logger, jsonRpcHistory: history) let pairingSequencesStore = PairingStorage(storage: SequenceStore(storage: keyValueStorage, identifier: StorageDomainIdentifiers.pairings.rawValue)) let sessionSequencesStore = SessionStorage(storage: SequenceStore(storage: keyValueStorage, identifier: StorageDomainIdentifiers.sessions.rawValue)) - self.pairingEngine = PairingEngine(relay: relay, crypto: crypto, subscriber: WCSubscriber(relay: relay, logger: logger), sequencesStore: pairingSequencesStore, metadata: metadata, logger: logger) - self.sessionEngine = SessionEngine(relay: relay, crypto: crypto, subscriber: WCSubscriber(relay: relay, logger: logger), sequencesStore: sessionSequencesStore, metadata: metadata, logger: logger) + self.pairingEngine = PairingEngine(relay: relay, kms: kms, subscriber: WCSubscriber(relay: relay, logger: logger), sequencesStore: pairingSequencesStore, metadata: metadata, logger: logger) + self.sessionEngine = SessionEngine(relay: relay, kms: kms, subscriber: WCSubscriber(relay: relay, logger: logger), sequencesStore: sessionSequencesStore, metadata: metadata, logger: logger) setUpEnginesCallbacks() } diff --git a/Sources/WalletConnect/Codec/AES_256_CBC_HMAC_SHA256_Codec.swift b/Sources/WalletConnectKMS/Codec/AES_256_CBC_HMAC_SHA256_Codec.swift similarity index 100% rename from Sources/WalletConnect/Codec/AES_256_CBC_HMAC_SHA256_Codec.swift rename to Sources/WalletConnectKMS/Codec/AES_256_CBC_HMAC_SHA256_Codec.swift diff --git a/Sources/WalletConnect/Codec/AES_CBC/CBC.swift b/Sources/WalletConnectKMS/Codec/AES_CBC/CBC.swift similarity index 100% rename from Sources/WalletConnect/Codec/AES_CBC/CBC.swift rename to Sources/WalletConnectKMS/Codec/AES_CBC/CBC.swift diff --git a/Sources/WalletConnect/Codec/AES_CBC/CBCError.swift b/Sources/WalletConnectKMS/Codec/AES_CBC/CBCError.swift similarity index 100% rename from Sources/WalletConnect/Codec/AES_CBC/CBCError.swift rename to Sources/WalletConnectKMS/Codec/AES_CBC/CBCError.swift diff --git a/Sources/WalletConnect/Codec/AES_CBC/Cipher.swift b/Sources/WalletConnectKMS/Codec/AES_CBC/Cipher.swift similarity index 100% rename from Sources/WalletConnect/Codec/AES_CBC/Cipher.swift rename to Sources/WalletConnectKMS/Codec/AES_CBC/Cipher.swift diff --git a/Sources/WalletConnect/Codec/CodecError.swift b/Sources/WalletConnectKMS/Codec/CodecError.swift similarity index 100% rename from Sources/WalletConnect/Codec/CodecError.swift rename to Sources/WalletConnectKMS/Codec/CodecError.swift diff --git a/Sources/WalletConnect/Codec/EncryptionPayload.swift b/Sources/WalletConnectKMS/Codec/EncryptionPayload.swift similarity index 100% rename from Sources/WalletConnect/Codec/EncryptionPayload.swift rename to Sources/WalletConnectKMS/Codec/EncryptionPayload.swift diff --git a/Sources/WalletConnect/Codec/HMACAuthenticator.swift b/Sources/WalletConnectKMS/Codec/HMACAuthenticator.swift similarity index 100% rename from Sources/WalletConnect/Codec/HMACAuthenticator.swift rename to Sources/WalletConnectKMS/Codec/HMACAuthenticator.swift diff --git a/Sources/WalletConnect/Codec/HMACAuthenticatorError.swift b/Sources/WalletConnectKMS/Codec/HMACAuthenticatorError.swift similarity index 100% rename from Sources/WalletConnect/Codec/HMACAuthenticatorError.swift rename to Sources/WalletConnectKMS/Codec/HMACAuthenticatorError.swift diff --git a/Sources/WalletConnect/Crypto/AgreementSecret.swift b/Sources/WalletConnectKMS/Crypto/AgreementSecret.swift similarity index 64% rename from Sources/WalletConnect/Crypto/AgreementSecret.swift rename to Sources/WalletConnectKMS/Crypto/AgreementSecret.swift index a175307cb..45b0a5736 100644 --- a/Sources/WalletConnect/Crypto/AgreementSecret.swift +++ b/Sources/WalletConnectKMS/Crypto/AgreementSecret.swift @@ -1,18 +1,18 @@ import Foundation -struct AgreementSecret: Equatable { +public struct AgreementSecret: Equatable { - let sharedSecret: Data - let publicKey: AgreementPublicKey + public let sharedSecret: Data + public let publicKey: AgreementPublicKey - func derivedTopic() -> String { + public func derivedTopic() -> String { sharedSecret.sha256().toHexString() } } extension AgreementSecret: GenericPasswordConvertible { - init(rawRepresentation data: D) throws where D : ContiguousBytes { + public init(rawRepresentation data: D) throws where D : ContiguousBytes { let buffer = data.withUnsafeBytes { Data($0) } guard buffer.count == 64 else { fatalError() // TODO: Handle error @@ -21,7 +21,7 @@ extension AgreementSecret: GenericPasswordConvertible { self.publicKey = try AgreementPublicKey(rawRepresentation: buffer.subdata(in: 32..<64)) } - var rawRepresentation: Data { + public var rawRepresentation: Data { sharedSecret + publicKey.rawRepresentation } } diff --git a/Sources/WalletConnect/Crypto/CryptoKitWrapper.swift b/Sources/WalletConnectKMS/Crypto/CryptoKitWrapper.swift similarity index 76% rename from Sources/WalletConnect/Crypto/CryptoKitWrapper.swift rename to Sources/WalletConnectKMS/Crypto/CryptoKitWrapper.swift index dc93d4727..cb78e15f5 100644 --- a/Sources/WalletConnect/Crypto/CryptoKitWrapper.swift +++ b/Sources/WalletConnectKMS/Crypto/CryptoKitWrapper.swift @@ -17,7 +17,7 @@ extension Curve25519.KeyAgreement.PrivateKey: Equatable { // MARK: - Public Key -struct AgreementPublicKey: Equatable { +public struct AgreementPublicKey: Equatable { fileprivate let key: Curve25519.KeyAgreement.PublicKey @@ -25,27 +25,27 @@ struct AgreementPublicKey: Equatable { self.key = publicKey } - init(rawRepresentation data: D) throws where D: ContiguousBytes { + public init(rawRepresentation data: D) throws where D: ContiguousBytes { self.key = try Curve25519.KeyAgreement.PublicKey(rawRepresentation: data) } - var rawRepresentation: Data { + public var rawRepresentation: Data { key.rawRepresentation } - var hexRepresentation: String { + public var hexRepresentation: String { key.rawRepresentation.toHexString() } } extension AgreementPublicKey: Codable { - func encode(to encoder: Encoder) throws { + public func encode(to encoder: Encoder) throws { var container = encoder.singleValueContainer() try container.encode(key.rawRepresentation) } - init(from decoder: Decoder) throws { + public init(from decoder: Decoder) throws { let container = try decoder.singleValueContainer() let buffer = try container.decode(Data.self) try self.init(rawRepresentation: buffer) @@ -54,23 +54,23 @@ extension AgreementPublicKey: Codable { // MARK: - Private Key -struct AgreementPrivateKey: GenericPasswordConvertible, Equatable { +public struct AgreementPrivateKey: GenericPasswordConvertible, Equatable { private let key: Curve25519.KeyAgreement.PrivateKey - init() { + public init() { self.key = Curve25519.KeyAgreement.PrivateKey() } - init(rawRepresentation: D) throws where D : ContiguousBytes { + public init(rawRepresentation: D) throws where D : ContiguousBytes { self.key = try Curve25519.KeyAgreement.PrivateKey(rawRepresentation: rawRepresentation) } - var rawRepresentation: Data { + public var rawRepresentation: Data { key.rawRepresentation } - var publicKey: AgreementPublicKey { + public var publicKey: AgreementPublicKey { AgreementPublicKey(publicKey: key.publicKey) } diff --git a/Sources/WalletConnect/Crypto/Hash.swift b/Sources/WalletConnectKMS/Crypto/Hash.swift similarity index 100% rename from Sources/WalletConnect/Crypto/Hash.swift rename to Sources/WalletConnectKMS/Crypto/Hash.swift diff --git a/Sources/WalletConnect/Crypto/Crypto.swift b/Sources/WalletConnectKMS/Crypto/KeyManagementService.swift similarity index 57% rename from Sources/WalletConnect/Crypto/Crypto.swift rename to Sources/WalletConnectKMS/Crypto/KeyManagementService.swift index 287ddcd74..3733b97c9 100644 --- a/Sources/WalletConnect/Crypto/Crypto.swift +++ b/Sources/WalletConnectKMS/Crypto/KeyManagementService.swift @@ -1,40 +1,35 @@ import Foundation -// TODO: Come up with better naming conventions -protocol CryptoStorageProtocol { - func createX25519KeyPair() throws -> AgreementPublicKey - func setPrivateKey(_ privateKey: AgreementPrivateKey) throws - func setAgreementSecret(_ agreementSecret: AgreementSecret, topic: String) throws - func getPrivateKey(for publicKey: AgreementPublicKey) throws -> AgreementPrivateKey? - func getAgreementSecret(for topic: String) throws -> AgreementSecret? - func deletePrivateKey(for publicKey: String) - func deleteAgreementSecret(for topic: String) - func performKeyAgreement(selfPublicKey: AgreementPublicKey, peerPublicKey hexRepresentation: String) throws -> AgreementSecret -} - -class Crypto: CryptoStorageProtocol { +public class KeyManagementService { + enum Error: Swift.Error { + case keyNotFound + } private var keychain: KeychainStorageProtocol + public init(serviceIdentifier: String) { + self.keychain = KeychainStorage(serviceIdentifier: serviceIdentifier) + } + init(keychain: KeychainStorageProtocol) { self.keychain = keychain } - func createX25519KeyPair() throws -> AgreementPublicKey { + public func createX25519KeyPair() throws -> AgreementPublicKey { let privateKey = AgreementPrivateKey() try setPrivateKey(privateKey) return privateKey.publicKey } - func setPrivateKey(_ privateKey: AgreementPrivateKey) throws { + public func setPrivateKey(_ privateKey: AgreementPrivateKey) throws { try keychain.add(privateKey, forKey: privateKey.publicKey.hexRepresentation) } - func setAgreementSecret(_ agreementSecret: AgreementSecret, topic: String) throws { + public func setAgreementSecret(_ agreementSecret: AgreementSecret, topic: String) throws { try keychain.add(agreementSecret, forKey: topic) } - func getPrivateKey(for publicKey: AgreementPublicKey) throws -> AgreementPrivateKey? { + public func getPrivateKey(for publicKey: AgreementPublicKey) throws -> AgreementPrivateKey? { do { return try keychain.read(key: publicKey.hexRepresentation) as AgreementPrivateKey } catch let error where (error as? KeychainError)?.status == errSecItemNotFound { @@ -44,7 +39,7 @@ class Crypto: CryptoStorageProtocol { } } - func getAgreementSecret(for topic: String) throws -> AgreementSecret? { + public func getAgreementSecret(for topic: String) throws -> AgreementSecret? { do { return try keychain.read(key: topic) as AgreementSecret } catch let error where (error as? KeychainError)?.status == errSecItemNotFound { @@ -54,7 +49,7 @@ class Crypto: CryptoStorageProtocol { } } - func deletePrivateKey(for publicKey: String) { + public func deletePrivateKey(for publicKey: String) { do { try keychain.delete(key: publicKey) } catch { @@ -62,7 +57,7 @@ class Crypto: CryptoStorageProtocol { } } - func deleteAgreementSecret(for topic: String) { + public func deleteAgreementSecret(for topic: String) { do { try keychain.delete(key: topic) } catch { @@ -70,12 +65,12 @@ class Crypto: CryptoStorageProtocol { } } - func performKeyAgreement(selfPublicKey: AgreementPublicKey, peerPublicKey hexRepresentation: String) throws -> AgreementSecret { + public func performKeyAgreement(selfPublicKey: AgreementPublicKey, peerPublicKey hexRepresentation: String) throws -> AgreementSecret { guard let privateKey = try getPrivateKey(for: selfPublicKey) else { print("Key Agreement Error: Private key not found for public key: \(selfPublicKey.hexRepresentation)") - throw WalletConnectError.internal(.keyNotFound) + throw KeyManagementService.Error.keyNotFound } - return try Crypto.generateAgreementSecret(from: privateKey, peerPublicKey: hexRepresentation) + return try KeyManagementService.generateAgreementSecret(from: privateKey, peerPublicKey: hexRepresentation) } static func generateAgreementSecret(from privateKey: AgreementPrivateKey, peerPublicKey hexRepresentation: String) throws -> AgreementSecret { diff --git a/Sources/WalletConnect/Crypto/Random.swift b/Sources/WalletConnectKMS/Crypto/Random.swift similarity index 100% rename from Sources/WalletConnect/Crypto/Random.swift rename to Sources/WalletConnectKMS/Crypto/Random.swift diff --git a/Sources/WalletConnectKMS/Extensions/String.swift b/Sources/WalletConnectKMS/Extensions/String.swift new file mode 100644 index 000000000..9ce711fe1 --- /dev/null +++ b/Sources/WalletConnectKMS/Extensions/String.swift @@ -0,0 +1,19 @@ + + +import Foundation + + +extension String: GenericPasswordConvertible { + + public init(rawRepresentation data: D) throws where D : ContiguousBytes { + let bytes = data.withUnsafeBytes { Data(Array($0)) } + guard let string = String(data: bytes, encoding: .utf8) else { + fatalError() // FIXME: Throw error + } + self = string + } + + public var rawRepresentation: Data { + self.data(using: .utf8) ?? Data() + } +} diff --git a/Sources/WalletConnect/Storage/GenericPasswordConvertible.swift b/Sources/WalletConnectKMS/Keychain/GenericPasswordConvertible.swift similarity index 74% rename from Sources/WalletConnect/Storage/GenericPasswordConvertible.swift rename to Sources/WalletConnectKMS/Keychain/GenericPasswordConvertible.swift index 86114f392..4db1e32fa 100644 --- a/Sources/WalletConnect/Storage/GenericPasswordConvertible.swift +++ b/Sources/WalletConnectKMS/Keychain/GenericPasswordConvertible.swift @@ -1,6 +1,6 @@ import Foundation -protocol GenericPasswordConvertible { +public protocol GenericPasswordConvertible { init(rawRepresentation data: D) throws where D: ContiguousBytes var rawRepresentation: Data { get } } diff --git a/Sources/WalletConnect/Storage/KeychainError.swift b/Sources/WalletConnectKMS/Keychain/KeychainError.swift similarity index 100% rename from Sources/WalletConnect/Storage/KeychainError.swift rename to Sources/WalletConnectKMS/Keychain/KeychainError.swift diff --git a/Sources/WalletConnect/Storage/KeychainService.swift b/Sources/WalletConnectKMS/Keychain/KeychainService.swift similarity index 100% rename from Sources/WalletConnect/Storage/KeychainService.swift rename to Sources/WalletConnectKMS/Keychain/KeychainService.swift diff --git a/Sources/WalletConnect/Storage/KeychainStorage.swift b/Sources/WalletConnectKMS/Keychain/KeychainStorage.swift similarity index 96% rename from Sources/WalletConnect/Storage/KeychainStorage.swift rename to Sources/WalletConnectKMS/Keychain/KeychainStorage.swift index d797fa1ba..d91051c41 100644 --- a/Sources/WalletConnect/Storage/KeychainStorage.swift +++ b/Sources/WalletConnectKMS/Keychain/KeychainStorage.swift @@ -12,9 +12,9 @@ final class KeychainStorage: KeychainStorageProtocol { private let secItem: KeychainServiceProtocol - init(keychainService: KeychainServiceProtocol = KeychainServiceWrapper(), uniqueIdentifier: String? = nil) { + init(keychainService: KeychainServiceProtocol = KeychainServiceWrapper(), serviceIdentifier: String) { self.secItem = keychainService - service = "com.walletconnect.sdk.\(uniqueIdentifier ?? "")" + service = serviceIdentifier } func add(_ item: T, forKey key: String) throws where T : GenericPasswordConvertible { diff --git a/Sources/WalletConnect/Serialiser/JSONRPCSerializing.swift b/Sources/WalletConnectKMS/Serialiser/Serializer.swift similarity index 50% rename from Sources/WalletConnect/Serialiser/JSONRPCSerializing.swift rename to Sources/WalletConnectKMS/Serialiser/Serializer.swift index 6be4a9a2f..4ddc9e38d 100644 --- a/Sources/WalletConnect/Serialiser/JSONRPCSerializing.swift +++ b/Sources/WalletConnectKMS/Serialiser/Serializer.swift @@ -1,25 +1,33 @@ import Foundation +import WalletConnectUtils -protocol JSONRPCSerializing { - func serialize(topic: String, encodable: Encodable) throws -> String - func tryDeserialize(topic: String, message: String) -> T? - var codec: Codec {get} -} -class JSONRPCSerializer: JSONRPCSerializing { - - private let crypto: Crypto - let codec: Codec +public class Serializer { + enum Error: String, Swift.Error { + case messageToShort = "Error: message is too short" + } + private let kms: KeyManagementService + private let codec: Codec - init(crypto: Crypto, codec: Codec = AES_256_CBC_HMAC_SHA256_Codec()) { - self.crypto = crypto + init(kms: KeyManagementService, codec: Codec = AES_256_CBC_HMAC_SHA256_Codec()) { + self.kms = kms self.codec = codec } - func serialize(topic: String, encodable: Encodable) throws -> String { + public init(kms: KeyManagementService) { + self.kms = kms + self.codec = AES_256_CBC_HMAC_SHA256_Codec() + } + + /// Encrypts and serializes an object into (iv + publicKey + mac + cipherText) formatted sting + /// - Parameters: + /// - topic: Topic that is associated with a symetric key for encrypting particular codable object + /// - message: Message to encrypt and serialize + /// - Returns: Serialized String + public func serialize(topic: String, encodable: Encodable) throws -> String { let messageJson = try encodable.json() var message: String - if let agreementKeys = try? crypto.getAgreementSecret(for: topic) { + if let agreementKeys = try? kms.getAgreementSecret(for: topic) { message = try encrypt(json: messageJson, agreementKeys: agreementKeys) } else { message = messageJson.toHexEncodedString(uppercase: false) @@ -27,25 +35,29 @@ class JSONRPCSerializer: JSONRPCSerializing { return message } - func tryDeserialize(topic: String, message: String) -> T? { + /// Deserializes and decrypts an object from (iv + publicKey + mac + cipherText) formatted sting + /// - Parameters: + /// - topic: Topic that is associated with a symetric key for decrypting particular codable object + /// - message: Message to deserialize and decrypt + /// - Returns: Deserialized object + public func tryDeserialize(topic: String, message: String) -> T? { do { - let deserializedJsonRpcRequest: T - if let agreementKeys = try? crypto.getAgreementSecret(for: topic) { - deserializedJsonRpcRequest = try deserialize(message: message, symmetricKey: agreementKeys.sharedSecret) + let deserializedCodable: T + if let agreementKeys = try? kms.getAgreementSecret(for: topic) { + deserializedCodable = try deserialize(message: message, symmetricKey: agreementKeys.sharedSecret) } else { let jsonData = Data(hex: message) - deserializedJsonRpcRequest = try JSONDecoder().decode(T.self, from: jsonData) + deserializedCodable = try JSONDecoder().decode(T.self, from: jsonData) } - return deserializedJsonRpcRequest + return deserializedCodable } catch { -// logger.debug("Type \(T.self) does not match the payload") return nil } } func deserialize(message: String, symmetricKey: Data) throws -> T { - let JSONRPCData = try decrypt(message: message, symmetricKey: symmetricKey) - return try JSONDecoder().decode(T.self, from: JSONRPCData) + let decryptedData = try decrypt(message: message, symmetricKey: symmetricKey) + return try JSONDecoder().decode(T.self, from: decryptedData) } func encrypt(json: String, agreementKeys: AgreementSecret) throws -> String { @@ -59,17 +71,17 @@ class JSONRPCSerializer: JSONRPCSerializing { private func decrypt(message: String, symmetricKey: Data) throws -> Data { let encryptionPayload = try deserializeIntoPayload(message: message) - let decryptedJSONRPC = try codec.decode(payload: encryptionPayload, sharedSecret: symmetricKey) - guard let JSONRPCData = decryptedJSONRPC.data(using: .utf8) else { + let decryptedString = try codec.decode(payload: encryptionPayload, sharedSecret: symmetricKey) + guard let decryptedData = decryptedString.data(using: .utf8) else { throw DataConversionError.stringToDataFailed } - return JSONRPCData + return decryptedData } private func deserializeIntoPayload(message: String) throws -> EncryptionPayload { let data = Data(hex: message) guard data.count > EncryptionPayload.ivLength + EncryptionPayload.publicKeyLength + EncryptionPayload.macLength else { - throw JSONRPCSerializerError.messageToShort + throw Error.messageToShort } let pubKeyRangeStartIndex = EncryptionPayload.ivLength let macStartIndex = pubKeyRangeStartIndex + EncryptionPayload.publicKeyLength diff --git a/Sources/WalletConnect/Extensions/Encodable.swift b/Sources/WalletConnectUtils/Encodable.swift similarity index 82% rename from Sources/WalletConnect/Extensions/Encodable.swift rename to Sources/WalletConnectUtils/Encodable.swift index 3b8d38cc5..604d58eda 100644 --- a/Sources/WalletConnect/Extensions/Encodable.swift +++ b/Sources/WalletConnectUtils/Encodable.swift @@ -2,12 +2,12 @@ import Foundation -enum DataConversionError: Error { +public enum DataConversionError: Error { case stringToDataFailed case dataToStringFailed } -extension Encodable { +public extension Encodable { func json() throws -> String { let data = try JSONEncoder().encode(self) guard let string = String(data: data, encoding: .utf8) else { diff --git a/Sources/WalletConnectUtils/String.swift b/Sources/WalletConnectUtils/String.swift new file mode 100644 index 000000000..14362c747 --- /dev/null +++ b/Sources/WalletConnectUtils/String.swift @@ -0,0 +1,9 @@ + + +import Foundation + +public extension String { + func toHexEncodedString(uppercase: Bool = true, prefix: String = "", separator: String = "") -> String { + return unicodeScalars.map { prefix + .init($0.value, radix: 16, uppercase: uppercase) } .joined(separator: separator) + } +} diff --git a/Tests/IntegrationTests/ClientTest.swift b/Tests/IntegrationTests/ClientTest.swift index e17e4ea0e..667db180d 100644 --- a/Tests/IntegrationTests/ClientTest.swift +++ b/Tests/IntegrationTests/ClientTest.swift @@ -4,6 +4,7 @@ import XCTest import WalletConnectUtils import TestingUtils @testable import WalletConnect +@testable import WalletConnectKMS fileprivate extension Session.Permissions { static func stub(methods: Set = [], notifications: [String] = []) -> Session.Permissions { @@ -27,12 +28,13 @@ final class ClientTests: XCTestCase { static func makeClientDelegate(isController: Bool, relayHost: String, prefix: String, projectId: String) -> ClientDelegate { let logger = ConsoleLogger(suffix: prefix, loggingLevel: .debug) + let keychain = KeychainStorage(keychainService: KeychainServiceFake(), serviceIdentifier: "") let client = WalletConnectClient( metadata: AppMetadata(name: nil, description: nil, url: nil, icons: nil), projectId: projectId, relayHost: relayHost, logger: logger, - keychain: KeychainStorage(keychainService: KeychainServiceFake()), + kms: KeyManagementService(keychain: keychain), keyValueStorage: RuntimeKeyValueStorage()) return ClientDelegate(client: client) } diff --git a/Tests/IntegrationTests/KeychainServiceFake.swift b/Tests/IntegrationTests/Mocks/KeychainServiceFake.swift similarity index 98% rename from Tests/IntegrationTests/KeychainServiceFake.swift rename to Tests/IntegrationTests/Mocks/KeychainServiceFake.swift index 36f2823bb..2c012b7df 100644 --- a/Tests/IntegrationTests/KeychainServiceFake.swift +++ b/Tests/IntegrationTests/Mocks/KeychainServiceFake.swift @@ -1,5 +1,6 @@ import Foundation @testable import WalletConnect +@testable import WalletConnectKMS // This file is a copy from the one in unit tests target, would be nice to figure out a way to share it between targets. final class KeychainServiceFake: KeychainServiceProtocol { diff --git a/Tests/WalletConnectTests/Mocks/MockedCodec.swift b/Tests/IntegrationTests/Mocks/MockedCodec.swift similarity index 94% rename from Tests/WalletConnectTests/Mocks/MockedCodec.swift rename to Tests/IntegrationTests/Mocks/MockedCodec.swift index 8d863201e..2e02fd6a0 100644 --- a/Tests/WalletConnectTests/Mocks/MockedCodec.swift +++ b/Tests/IntegrationTests/Mocks/MockedCodec.swift @@ -1,7 +1,7 @@ -// + import Foundation -@testable import WalletConnect +@testable import WalletConnectKMS class MockedCodec: Codec { var hmacAuthenticator: HMACAuthenticating diff --git a/Tests/WalletConnectTests/JSONRPCSerialiserTests.swift b/Tests/IntegrationTests/Mocks/SerialiserTests.swift similarity index 84% rename from Tests/WalletConnectTests/JSONRPCSerialiserTests.swift rename to Tests/IntegrationTests/Mocks/SerialiserTests.swift index f2d4f212b..434c01af4 100644 --- a/Tests/WalletConnectTests/JSONRPCSerialiserTests.swift +++ b/Tests/IntegrationTests/Mocks/SerialiserTests.swift @@ -3,14 +3,16 @@ import Foundation import XCTest +@testable import WalletConnectKMS @testable import WalletConnect +@testable import TestingUtils -final class JSONRPCSerializerTests: XCTestCase { - var serializer: JSONRPCSerializer! +final class SerializerTests: XCTestCase { + var serializer: Serializer! var codec: MockedCodec! override func setUp() { codec = MockedCodec() - self.serializer = JSONRPCSerializer(crypto: Crypto(keychain: KeychainStorageMock()), codec: codec) + self.serializer = Serializer(kms: KeyManagementService(keychain: KeychainStorageMock()), codec: codec) } override func tearDown() { @@ -26,7 +28,7 @@ final class JSONRPCSerializerTests: XCTestCase { let serializedMessageSample = SerializerTestData.serializedMessage XCTAssertEqual(serializedMessage, serializedMessageSample) } - + func testDeserialize() { let serializedMessageSample = SerializerTestData.serializedMessage codec.decodedJson = SerializerTestData.pairingApproveJSON diff --git a/Tests/WalletConnectTests/TestsData/SerialiserTestData.swift b/Tests/IntegrationTests/SerialiserTestData.swift similarity index 98% rename from Tests/WalletConnectTests/TestsData/SerialiserTestData.swift rename to Tests/IntegrationTests/SerialiserTestData.swift index 452c9eed1..7ea018ac7 100644 --- a/Tests/WalletConnectTests/TestsData/SerialiserTestData.swift +++ b/Tests/IntegrationTests/SerialiserTestData.swift @@ -1,6 +1,7 @@ // import Foundation +@testable import WalletConnectKMS @testable import WalletConnect enum SerializerTestData { @@ -11,23 +12,7 @@ enum SerializerTestData { static let cipherText = Data(hex: "14aa7f6034dd0213be5901b472f461769855ac1e2f6bec6a8ed1157a9da3b2df08802cbd6e0d030d86ff99011040cfc831eec3636c1d46bfc22cbe055560fea3") static let serializedMessage = "f0d00d4274a7e9711e4e0f21820b887745c59ad0c053925072f4503a39fe579ca8b7b8fa6bf0c7297e6db8f6585ee77ffc6d3106fa827043279f9db08cd2e29a988c7272fa3cfdb739163bb9606822c714aa7f6034dd0213be5901b472f461769855ac1e2f6bec6a8ed1157a9da3b2df08802cbd6e0d030d86ff99011040cfc831eec3636c1d46bfc22cbe055560fea3" - static let pairingApproveJSONRPCRequest = WCRequest( - id: 0, - jsonrpc: "2.0", - method: WCRequest.Method.pairingApprove, - params: WCRequest.Params.pairingApprove( - PairingType.ApprovalParams( - relay: RelayProtocolOptions( - protocol: "waku", - params: nil), - responder: PairingParticipant(publicKey: "be9225978b6287a02d259ee0d9d1bcb683082d8386b7fb14b58ac95b93b2ef43"), - expiry: 1632742217, - state: PairingState(metadata: AppMetadata( - name: "iOS", - description: nil, - url: nil, - icons: nil)))) - ) + static let pairingApproveJSON = """ { @@ -51,5 +36,23 @@ enum SerializerTestData { } } """ + + static let pairingApproveJSONRPCRequest = WCRequest( + id: 0, + jsonrpc: "2.0", + method: WCRequest.Method.pairingApprove, + params: WCRequest.Params.pairingApprove( + PairingType.ApprovalParams( + relay: RelayProtocolOptions( + protocol: "waku", + params: nil), + responder: PairingParticipant(publicKey: "be9225978b6287a02d259ee0d9d1bcb683082d8386b7fb14b58ac95b93b2ef43"), + expiry: 1632742217, + state: PairingState(metadata: AppMetadata( + name: "iOS", + description: nil, + url: nil, + icons: nil)))) + ) } diff --git a/Tests/WalletConnectTests/Mocks/KeychainStorageMock.swift b/Tests/TestingUtils/Mocks/KeychainStorageMock.swift similarity index 95% rename from Tests/WalletConnectTests/Mocks/KeychainStorageMock.swift rename to Tests/TestingUtils/Mocks/KeychainStorageMock.swift index a5a41ef58..0d281f21d 100644 --- a/Tests/WalletConnectTests/Mocks/KeychainStorageMock.swift +++ b/Tests/TestingUtils/Mocks/KeychainStorageMock.swift @@ -1,5 +1,5 @@ import Foundation -@testable import WalletConnect +@testable import WalletConnectKMS final class KeychainStorageMock: KeychainStorageProtocol { diff --git a/Tests/WalletConnectTests/AES_256_CBC_HMAC_SHA256_Codec_Test.swift b/Tests/WalletConnectKMSTests/AES_256_CBC_HMAC_SHA256_Codec_Test.swift similarity index 97% rename from Tests/WalletConnectTests/AES_256_CBC_HMAC_SHA256_Codec_Test.swift rename to Tests/WalletConnectKMSTests/AES_256_CBC_HMAC_SHA256_Codec_Test.swift index 619251324..abf74624d 100644 --- a/Tests/WalletConnectTests/AES_256_CBC_HMAC_SHA256_Codec_Test.swift +++ b/Tests/WalletConnectKMSTests/AES_256_CBC_HMAC_SHA256_Codec_Test.swift @@ -1,7 +1,7 @@ import Foundation import XCTest -@testable import WalletConnect +@testable import WalletConnectKMS class AES_256_CBC_HMAC_SHA256_Codec_Test: XCTestCase { let message = "Test Message" diff --git a/Tests/WalletConnectKMSTests/AgreementSecret+Stub.swift b/Tests/WalletConnectKMSTests/AgreementSecret+Stub.swift new file mode 100644 index 000000000..b7161a665 --- /dev/null +++ b/Tests/WalletConnectKMSTests/AgreementSecret+Stub.swift @@ -0,0 +1,9 @@ +import Foundation +@testable import WalletConnectKMS + +extension AgreementSecret { + + static func stub() -> AgreementSecret { + AgreementSecret(sharedSecret: Data.randomBytes(32), publicKey: AgreementPrivateKey().publicKey) + } +} diff --git a/Tests/WalletConnectTests/TestsData/CryptoTestData.swift b/Tests/WalletConnectKMSTests/CryptoTestData.swift similarity index 100% rename from Tests/WalletConnectTests/TestsData/CryptoTestData.swift rename to Tests/WalletConnectKMSTests/CryptoTestData.swift diff --git a/Tests/WalletConnectTests/CryptoTests.swift b/Tests/WalletConnectKMSTests/CryptoTests.swift similarity index 76% rename from Tests/WalletConnectTests/CryptoTests.swift rename to Tests/WalletConnectKMSTests/CryptoTests.swift index bd3af9ed6..8c5f495d5 100644 --- a/Tests/WalletConnectTests/CryptoTests.swift +++ b/Tests/WalletConnectKMSTests/CryptoTests.swift @@ -1,19 +1,20 @@ import XCTest -@testable import WalletConnect +@testable import WalletConnectKMS +@testable import TestingUtils fileprivate extension Error { var isKeyNotFoundError: Bool { - guard case .internal(.keyNotFound) = self as? WalletConnectError else { return false } + guard case .keyNotFound = self as? KeyManagementService.Error else { return false } return true } } class CryptoTests: XCTestCase { - var crypto: Crypto! + var crypto: KeyManagementService! override func setUp() { - crypto = Crypto(keychain: KeychainStorageMock()) + crypto = KeyManagementService(keychain: KeychainStorageMock()) } override func tearDown() { @@ -64,8 +65,8 @@ class CryptoTests: XCTestCase { func testGenerateX25519Agreement() throws { let privateKeyA = try AgreementPrivateKey(rawRepresentation: CryptoTestData._privateKeyA) let privateKeyB = try AgreementPrivateKey(rawRepresentation: CryptoTestData._privateKeyB) - let agreementSecretA = try Crypto.generateAgreementSecret(from: privateKeyA, peerPublicKey: privateKeyB.publicKey.hexRepresentation) - let agreementSecretB = try Crypto.generateAgreementSecret(from: privateKeyB, peerPublicKey: privateKeyA.publicKey.hexRepresentation) + let agreementSecretA = try KeyManagementService.generateAgreementSecret(from: privateKeyA, peerPublicKey: privateKeyB.publicKey.hexRepresentation) + let agreementSecretB = try KeyManagementService.generateAgreementSecret(from: privateKeyB, peerPublicKey: privateKeyA.publicKey.hexRepresentation) XCTAssertEqual(agreementSecretA.sharedSecret, agreementSecretB.sharedSecret) XCTAssertEqual(agreementSecretA.sharedSecret, CryptoTestData.expectedSharedSecret) } @@ -73,15 +74,15 @@ class CryptoTests: XCTestCase { func testGenerateX25519AgreementRandomKeys() throws { let privateKeyA = AgreementPrivateKey() let privateKeyB = AgreementPrivateKey() - let agreementSecretA = try Crypto.generateAgreementSecret(from: privateKeyA, peerPublicKey: privateKeyB.publicKey.hexRepresentation) - let agreementSecretB = try Crypto.generateAgreementSecret(from: privateKeyB, peerPublicKey: privateKeyA.publicKey.hexRepresentation) + let agreementSecretA = try KeyManagementService.generateAgreementSecret(from: privateKeyA, peerPublicKey: privateKeyB.publicKey.hexRepresentation) + let agreementSecretB = try KeyManagementService.generateAgreementSecret(from: privateKeyB, peerPublicKey: privateKeyA.publicKey.hexRepresentation) XCTAssertEqual(agreementSecretA.sharedSecret, agreementSecretB.sharedSecret) } func testPerformKeyAgreement() throws { let privateKeySelf = AgreementPrivateKey() let privateKeyPeer = AgreementPrivateKey() - let peerSecret = try Crypto.generateAgreementSecret(from: privateKeyPeer, peerPublicKey: privateKeySelf.publicKey.hexRepresentation) + let peerSecret = try KeyManagementService.generateAgreementSecret(from: privateKeyPeer, peerPublicKey: privateKeySelf.publicKey.hexRepresentation) try crypto.setPrivateKey(privateKeySelf) let selfSecret = try crypto.performKeyAgreement(selfPublicKey: privateKeySelf.publicKey, peerPublicKey: privateKeyPeer.publicKey.hexRepresentation) XCTAssertEqual(selfSecret.sharedSecret, peerSecret.sharedSecret) diff --git a/Tests/WalletConnectTests/HMACAuthenticatorTests.swift b/Tests/WalletConnectKMSTests/HMACAuthenticatorTests.swift similarity index 96% rename from Tests/WalletConnectTests/HMACAuthenticatorTests.swift rename to Tests/WalletConnectKMSTests/HMACAuthenticatorTests.swift index 7f4b0520a..9ed6fb4bd 100644 --- a/Tests/WalletConnectTests/HMACAuthenticatorTests.swift +++ b/Tests/WalletConnectKMSTests/HMACAuthenticatorTests.swift @@ -2,7 +2,7 @@ import Foundation import XCTest -@testable import WalletConnect +@testable import WalletConnectKMS class HMACAuthenticatorTests: XCTestCase { let authenticationKey = Data(hex: "da4e6a3641db794441206145d6610d30bd5b403c624a5a4f69feb370cc59924d") diff --git a/Tests/WalletConnectTests/Mocks/KeychainServiceFake.swift b/Tests/WalletConnectKMSTests/KeychainServiceFake.swift similarity index 98% rename from Tests/WalletConnectTests/Mocks/KeychainServiceFake.swift rename to Tests/WalletConnectKMSTests/KeychainServiceFake.swift index 41189fee5..49f18d171 100644 --- a/Tests/WalletConnectTests/Mocks/KeychainServiceFake.swift +++ b/Tests/WalletConnectKMSTests/KeychainServiceFake.swift @@ -1,5 +1,5 @@ import Foundation -@testable import WalletConnect +@testable import WalletConnectKMS final class KeychainServiceFake: KeychainServiceProtocol { diff --git a/Tests/WalletConnectTests/KeychainStorageTests.swift b/Tests/WalletConnectKMSTests/KeychainStorageTests.swift similarity index 97% rename from Tests/WalletConnectTests/KeychainStorageTests.swift rename to Tests/WalletConnectKMSTests/KeychainStorageTests.swift index d65e2fd37..be375a427 100644 --- a/Tests/WalletConnectTests/KeychainStorageTests.swift +++ b/Tests/WalletConnectKMSTests/KeychainStorageTests.swift @@ -1,6 +1,6 @@ import XCTest import CryptoKit -@testable import WalletConnect +@testable import WalletConnectKMS extension Curve25519.KeyAgreement.PrivateKey: GenericPasswordConvertible {} @@ -14,7 +14,9 @@ final class KeychainStorageTests: XCTestCase { override func setUp() { fakeKeychain = KeychainServiceFake() - sut = KeychainStorage(keychainService: fakeKeychain) + sut = KeychainStorage( + keychainService: fakeKeychain, + serviceIdentifier: "") } override func tearDown() { diff --git a/Tests/WalletConnectTests/Mocks/CryptoStorageProtocolMock.swift b/Tests/WalletConnectTests/Mocks/KeyManagementServiceMock.swift similarity index 94% rename from Tests/WalletConnectTests/Mocks/CryptoStorageProtocolMock.swift rename to Tests/WalletConnectTests/Mocks/KeyManagementServiceMock.swift index 427aa031d..f40d49b67 100644 --- a/Tests/WalletConnectTests/Mocks/CryptoStorageProtocolMock.swift +++ b/Tests/WalletConnectTests/Mocks/KeyManagementServiceMock.swift @@ -1,7 +1,8 @@ import Foundation @testable import WalletConnect +@testable import WalletConnectKMS -final class CryptoStorageProtocolMock: CryptoStorageProtocol { +final class KeyManagementServiceMock: KeyManagementServiceProtocol { func createX25519KeyPair() throws -> AgreementPublicKey { defer { privateKeyStub = AgreementPrivateKey() } @@ -56,7 +57,7 @@ final class CryptoStorageProtocolMock: CryptoStorageProtocol { } } -extension CryptoStorageProtocolMock { +extension KeyManagementServiceMock { func hasPrivateKey(for publicKeyHex: String) -> Bool { privateKeys[publicKeyHex] != nil diff --git a/Tests/WalletConnectTests/Mocks/MockedRelay.swift b/Tests/WalletConnectTests/Mocks/MockedRelay.swift index ff3fdf2bd..20cb9ec22 100644 --- a/Tests/WalletConnectTests/Mocks/MockedRelay.swift +++ b/Tests/WalletConnectTests/Mocks/MockedRelay.swift @@ -3,6 +3,7 @@ import Foundation import Combine import WalletConnectUtils @testable import WalletConnect +@testable import TestingUtils class MockedWCRelay: WalletConnectRelaying { @@ -60,7 +61,25 @@ class MockedWCRelay: WalletConnectRelaying { func sendSubscriptionPayloadOn(topic: String) { let payload = WCRequestSubscriptionPayload(topic: topic, - wcRequest: SerializerTestData.pairingApproveJSONRPCRequest) + wcRequest: pairingApproveJSONRPCRequest) wcRequestPublisherSubject.send(payload) } } + +fileprivate let pairingApproveJSONRPCRequest = WCRequest( + id: 0, + jsonrpc: "2.0", + method: WCRequest.Method.pairingApprove, + params: WCRequest.Params.pairingApprove( + PairingType.ApprovalParams( + relay: RelayProtocolOptions( + protocol: "waku", + params: nil), + responder: PairingParticipant(publicKey: "be9225978b6287a02d259ee0d9d1bcb683082d8386b7fb14b58ac95b93b2ef43"), + expiry: 1632742217, + state: PairingState(metadata: AppMetadata( + name: "iOS", + description: nil, + url: nil, + icons: nil)))) +) diff --git a/Tests/WalletConnectTests/Mocks/MockedJSONRPCSerializer.swift b/Tests/WalletConnectTests/Mocks/SerializerMock.swift similarity index 87% rename from Tests/WalletConnectTests/Mocks/MockedJSONRPCSerializer.swift rename to Tests/WalletConnectTests/Mocks/SerializerMock.swift index fbc8c9da7..b018a2b96 100644 --- a/Tests/WalletConnectTests/Mocks/MockedJSONRPCSerializer.swift +++ b/Tests/WalletConnectTests/Mocks/SerializerMock.swift @@ -2,18 +2,14 @@ import Foundation import WalletConnectUtils +@testable import WalletConnectKMS @testable import WalletConnect -class MockedJSONRPCSerializer: JSONRPCSerializing { - var codec: Codec +class SerializerMock: Serializing { var deserialized: Any! var serialized: String! - init(codec: Codec = MockedCodec()) { - self.codec = codec - } - func serialize(topic: String, encodable: Encodable) throws -> String { try serialize(json: try encodable.json(), agreementKeys: AgreementSecret(sharedSecret: Data(), publicKey: AgreementPrivateKey().publicKey)) } diff --git a/Tests/WalletConnectTests/PairingEngineTests.swift b/Tests/WalletConnectTests/PairingEngineTests.swift index 9223b182b..03754c161 100644 --- a/Tests/WalletConnectTests/PairingEngineTests.swift +++ b/Tests/WalletConnectTests/PairingEngineTests.swift @@ -1,10 +1,11 @@ import XCTest @testable import WalletConnect import TestingUtils +@testable import WalletConnectKMS import WalletConnectUtils func deriveTopic(publicKey: String, privateKey: AgreementPrivateKey) -> String { - try! Crypto.generateAgreementSecret(from: privateKey, peerPublicKey: publicKey).derivedTopic() + try! KeyManagementService.generateAgreementSecret(from: privateKey, peerPublicKey: publicKey).derivedTopic() } final class PairingEngineTests: XCTestCase { @@ -14,7 +15,7 @@ final class PairingEngineTests: XCTestCase { var relayMock: MockedWCRelay! var subscriberMock: MockedSubscriber! var storageMock: PairingSequenceStorageMock! - var cryptoMock: CryptoStorageProtocolMock! + var cryptoMock: KeyManagementServiceMock! var topicGenerator: TopicGenerator! @@ -22,7 +23,7 @@ final class PairingEngineTests: XCTestCase { relayMock = MockedWCRelay() subscriberMock = MockedSubscriber() storageMock = PairingSequenceStorageMock() - cryptoMock = CryptoStorageProtocolMock() + cryptoMock = KeyManagementServiceMock() topicGenerator = TopicGenerator() } @@ -40,7 +41,7 @@ final class PairingEngineTests: XCTestCase { let logger = ConsoleLoggerMock() engine = PairingEngine( relay: relayMock, - crypto: cryptoMock, + kms: cryptoMock, subscriber: subscriberMock, sequencesStore: storageMock, metadata: meta, diff --git a/Tests/WalletConnectTests/SessionEngineTests.swift b/Tests/WalletConnectTests/SessionEngineTests.swift index eb9389bfb..8498d69cf 100644 --- a/Tests/WalletConnectTests/SessionEngineTests.swift +++ b/Tests/WalletConnectTests/SessionEngineTests.swift @@ -1,6 +1,7 @@ import XCTest import WalletConnectUtils import TestingUtils +import WalletConnectKMS @testable import WalletConnect final class SessionEngineTests: XCTestCase { @@ -10,7 +11,7 @@ final class SessionEngineTests: XCTestCase { var relayMock: MockedWCRelay! var subscriberMock: MockedSubscriber! var storageMock: SessionSequenceStorageMock! - var cryptoMock: CryptoStorageProtocolMock! + var cryptoMock: KeyManagementServiceMock! var topicGenerator: TopicGenerator! @@ -20,7 +21,7 @@ final class SessionEngineTests: XCTestCase { relayMock = MockedWCRelay() subscriberMock = MockedSubscriber() storageMock = SessionSequenceStorageMock() - cryptoMock = CryptoStorageProtocolMock() + cryptoMock = KeyManagementServiceMock() topicGenerator = TopicGenerator() } @@ -38,7 +39,7 @@ final class SessionEngineTests: XCTestCase { let logger = ConsoleLoggerMock() engine = SessionEngine( relay: relayMock, - crypto: cryptoMock, + kms: cryptoMock, subscriber: subscriberMock, sequencesStore: storageMock, metadata: metadata, diff --git a/Tests/WalletConnectTests/Stub/AgreementSecret+Stub.swift b/Tests/WalletConnectTests/Stub/AgreementSecret+Stub.swift index 62a9fa0bd..b7161a665 100644 --- a/Tests/WalletConnectTests/Stub/AgreementSecret+Stub.swift +++ b/Tests/WalletConnectTests/Stub/AgreementSecret+Stub.swift @@ -1,5 +1,5 @@ import Foundation -@testable import WalletConnect +@testable import WalletConnectKMS extension AgreementSecret { diff --git a/Tests/WalletConnectTests/Stub/Session+Stub.swift b/Tests/WalletConnectTests/Stub/Session+Stub.swift index a711a2acf..477e3b001 100644 --- a/Tests/WalletConnectTests/Stub/Session+Stub.swift +++ b/Tests/WalletConnectTests/Stub/Session+Stub.swift @@ -1,4 +1,5 @@ import Foundation +import WalletConnectKMS @testable import WalletConnect extension SessionSequence { diff --git a/Tests/WalletConnectTests/Stub/Stubs.swift b/Tests/WalletConnectTests/Stub/Stubs.swift index 11b405f85..84c26beb0 100644 --- a/Tests/WalletConnectTests/Stub/Stubs.swift +++ b/Tests/WalletConnectTests/Stub/Stubs.swift @@ -1,4 +1,5 @@ @testable import WalletConnect +import WalletConnectKMS extension AppMetadata { static func stub() -> AppMetadata { diff --git a/Tests/WalletConnectTests/Stub/WalletConnectURI+Stub.swift b/Tests/WalletConnectTests/Stub/WalletConnectURI+Stub.swift index c027532f7..cd230eaee 100644 --- a/Tests/WalletConnectTests/Stub/WalletConnectURI+Stub.swift +++ b/Tests/WalletConnectTests/Stub/WalletConnectURI+Stub.swift @@ -1,4 +1,5 @@ @testable import WalletConnect +@testable import WalletConnectKMS extension WalletConnectURI { diff --git a/Tests/WalletConnectTests/WCRelayTests.swift b/Tests/WalletConnectTests/WCRelayTests.swift index 50e072d5d..17acb7662 100644 --- a/Tests/WalletConnectTests/WCRelayTests.swift +++ b/Tests/WalletConnectTests/WCRelayTests.swift @@ -2,23 +2,22 @@ import Foundation import Combine import XCTest -import TestingUtils import WalletConnectUtils +@testable import TestingUtils @testable import WalletConnect class WalletConnectRelayTests: XCTestCase { var wcRelay: WalletConnectRelay! var networkRelayer: MockedNetworkRelayer! - var serializer: MockedJSONRPCSerializer! - var crypto: Crypto! + var serializer: SerializerMock! private var publishers = [AnyCancellable]() override func setUp() { let logger = ConsoleLoggerMock() - serializer = MockedJSONRPCSerializer() + serializer = SerializerMock() networkRelayer = MockedNetworkRelayer() - wcRelay = WalletConnectRelay(networkRelayer: networkRelayer, jsonRpcSerializer: serializer, logger: logger, jsonRpcHistory: JsonRpcHistory(logger: logger, keyValueStore: KeyValueStore(defaults: RuntimeKeyValueStorage(), identifier: ""))) + wcRelay = WalletConnectRelay(networkRelayer: networkRelayer, serializer: serializer, logger: logger, jsonRpcHistory: JsonRpcHistory(logger: logger, keyValueStore: KeyValueStore(defaults: RuntimeKeyValueStorage(), identifier: ""))) } override func tearDown() { @@ -33,7 +32,7 @@ class WalletConnectRelayTests: XCTestCase { wcRelay.wcRequestPublisher.sink { (request) in requestExpectation.fulfill() }.store(in: &publishers) - serializer.deserialized = SerializerTestData.pairingApproveJSONRPCRequest + serializer.deserialized = pairingApproveJSONRPCRequest networkRelayer.onMessage?(topic, testPayload) waitForExpectations(timeout: 1.001, handler: nil) } @@ -107,3 +106,21 @@ fileprivate let testPayload = } } """ + +fileprivate let pairingApproveJSONRPCRequest = WCRequest( + id: 0, + jsonrpc: "2.0", + method: WCRequest.Method.pairingApprove, + params: WCRequest.Params.pairingApprove( + PairingType.ApprovalParams( + relay: RelayProtocolOptions( + protocol: "waku", + params: nil), + responder: PairingParticipant(publicKey: "be9225978b6287a02d259ee0d9d1bcb683082d8386b7fb14b58ac95b93b2ef43"), + expiry: 1632742217, + state: PairingState(metadata: AppMetadata( + name: "iOS", + description: nil, + url: nil, + icons: nil)))) +)