From fbd546a794245a36776d6297070d5cc3af3c379d Mon Sep 17 00:00:00 2001 From: Artur Guseinov Date: Thu, 1 Sep 2022 18:28:04 +0300 Subject: [PATCH 1/4] NetworkInteracting moved to package --- Package.swift | 9 +++++++- .../Auth/Services/App/AppPairService.swift | 1 + .../Auth/Services/App/AppRequestService.swift | 3 ++- .../Services/App/AppRespondSubscriber.swift | 5 +++-- .../Common/NetworkingInteractor.swift | 22 +++---------------- .../Services/Wallet/WalletPairService.swift | 1 + .../Wallet/WalletRequestSubscriber.swift | 5 +++-- .../Wallet/WalletRespondService.swift | 3 ++- Sources/Auth/Types/Errors/AuthError.swift | 1 + .../Types/RequestSubscriptionPayload.swift | 7 ------ .../Types/ResponseSubscriptionPayload.swift | 7 ------ .../NetworkInteractor.swift | 21 ++++++++++++++++++ .../Reason.swift | 2 +- .../RequestSubscriptionPayload.swift | 12 ++++++++++ .../ResponseSubscriptionPayload.swift | 12 ++++++++++ .../AuthTests/AppRespondSubscriberTests.swift | 1 + .../Mocks/NetworkingInteractorMock.swift | 1 + .../Stubs/RequestSubscriptionPayload.swift | 3 ++- .../WalletRequestSubscriberTests.swift | 5 +++-- 19 files changed, 77 insertions(+), 44 deletions(-) delete mode 100644 Sources/Auth/Types/RequestSubscriptionPayload.swift delete mode 100644 Sources/Auth/Types/ResponseSubscriptionPayload.swift create mode 100644 Sources/WalletConnectNetworking/NetworkInteractor.swift rename Sources/{Auth/Types/Errors => WalletConnectNetworking}/Reason.swift (75%) create mode 100644 Sources/WalletConnectNetworking/RequestSubscriptionPayload.swift create mode 100644 Sources/WalletConnectNetworking/ResponseSubscriptionPayload.swift diff --git a/Package.swift b/Package.swift index 9c3cd5b68..6e0da39f7 100644 --- a/Package.swift +++ b/Package.swift @@ -21,7 +21,10 @@ let package = Package( targets: ["Auth"]), .library( name: "WalletConnectRouter", - targets: ["WalletConnectRouter"]) + targets: ["WalletConnectRouter"]), + .library( + name: "WalletConnectNetworking", + targets: ["WalletConnectNetworking"]), ], dependencies: [ .package(url: "https://github.com/flypaper0/Web3.swift", .branch("feature/eip-155")) @@ -42,6 +45,7 @@ let package = Package( "WalletConnectUtils", "WalletConnectKMS", "WalletConnectPairing", + "WalletConnectNetworking", .product(name: "Web3", package: "Web3.swift") ], path: "Sources/Auth"), @@ -65,6 +69,9 @@ let package = Package( .target( name: "Commons", dependencies: []), + .target( + name: "WalletConnectNetworking", + dependencies: ["JSONRPC", "WalletConnectKMS"]), .target( name: "WalletConnectRouter", dependencies: []), diff --git a/Sources/Auth/Services/App/AppPairService.swift b/Sources/Auth/Services/App/AppPairService.swift index 1dc9c0cbc..dc05600b0 100644 --- a/Sources/Auth/Services/App/AppPairService.swift +++ b/Sources/Auth/Services/App/AppPairService.swift @@ -1,6 +1,7 @@ import Foundation import WalletConnectKMS import WalletConnectPairing +import WalletConnectNetworking actor AppPairService { private let networkingInteractor: NetworkInteracting diff --git a/Sources/Auth/Services/App/AppRequestService.swift b/Sources/Auth/Services/App/AppRequestService.swift index b3186e77d..9303d7bb8 100644 --- a/Sources/Auth/Services/App/AppRequestService.swift +++ b/Sources/Auth/Services/App/AppRequestService.swift @@ -1,7 +1,8 @@ import Foundation +import JSONRPC +import WalletConnectNetworking import WalletConnectUtils import WalletConnectKMS -import JSONRPC actor AppRequestService { private let networkingInteractor: NetworkInteracting diff --git a/Sources/Auth/Services/App/AppRespondSubscriber.swift b/Sources/Auth/Services/App/AppRespondSubscriber.swift index 3a501b718..16e0ff807 100644 --- a/Sources/Auth/Services/App/AppRespondSubscriber.swift +++ b/Sources/Auth/Services/App/AppRespondSubscriber.swift @@ -1,7 +1,8 @@ -import Combine import Foundation -import WalletConnectUtils +import Combine import JSONRPC +import WalletConnectNetworking +import WalletConnectUtils import WalletConnectPairing class AppRespondSubscriber { diff --git a/Sources/Auth/Services/Common/NetworkingInteractor.swift b/Sources/Auth/Services/Common/NetworkingInteractor.swift index e66e97a77..b1cc7684a 100644 --- a/Sources/Auth/Services/Common/NetworkingInteractor.swift +++ b/Sources/Auth/Services/Common/NetworkingInteractor.swift @@ -1,26 +1,10 @@ import Foundation +import Combine +import JSONRPC +import WalletConnectNetworking import WalletConnectRelay import WalletConnectUtils -import Combine import WalletConnectKMS -import JSONRPC - -protocol NetworkInteracting { - var requestPublisher: AnyPublisher {get} - var responsePublisher: AnyPublisher {get} - func subscribe(topic: String) async throws - func unsubscribe(topic: String) - func request(_ request: RPCRequest, topic: String, tag: Int, envelopeType: Envelope.EnvelopeType) async throws - func requestNetworkAck(_ request: RPCRequest, topic: String, tag: Int) async throws - func respond(topic: String, response: RPCResponse, tag: Int, envelopeType: Envelope.EnvelopeType) async throws - func respondError(topic: String, requestId: RPCID, tag: Int, reason: Reason, envelopeType: Envelope.EnvelopeType) async throws -} - -extension NetworkInteracting { - func request(_ request: RPCRequest, topic: String, tag: Int, envelopeType: Envelope.EnvelopeType = .type0) async throws { - try await self.request(request, topic: topic, tag: tag, envelopeType: envelopeType) - } -} class NetworkingInteractor: NetworkInteracting { private var publishers = Set() diff --git a/Sources/Auth/Services/Wallet/WalletPairService.swift b/Sources/Auth/Services/Wallet/WalletPairService.swift index ef4fc2e28..355de0a29 100644 --- a/Sources/Auth/Services/Wallet/WalletPairService.swift +++ b/Sources/Auth/Services/Wallet/WalletPairService.swift @@ -1,6 +1,7 @@ import Foundation import WalletConnectKMS import WalletConnectPairing +import WalletConnectNetworking actor WalletPairService { enum Errors: Error { diff --git a/Sources/Auth/Services/Wallet/WalletRequestSubscriber.swift b/Sources/Auth/Services/Wallet/WalletRequestSubscriber.swift index 522820187..c54bd3935 100644 --- a/Sources/Auth/Services/Wallet/WalletRequestSubscriber.swift +++ b/Sources/Auth/Services/Wallet/WalletRequestSubscriber.swift @@ -1,7 +1,8 @@ -import Combine import Foundation -import WalletConnectUtils +import Combine import JSONRPC +import WalletConnectNetworking +import WalletConnectUtils import WalletConnectKMS class WalletRequestSubscriber { diff --git a/Sources/Auth/Services/Wallet/WalletRespondService.swift b/Sources/Auth/Services/Wallet/WalletRespondService.swift index 07e01871c..9107f4df3 100644 --- a/Sources/Auth/Services/Wallet/WalletRespondService.swift +++ b/Sources/Auth/Services/Wallet/WalletRespondService.swift @@ -1,7 +1,8 @@ import Foundation -import WalletConnectKMS import JSONRPC +import WalletConnectKMS import WalletConnectUtils +import WalletConnectNetworking actor WalletRespondService { enum Errors: Error { diff --git a/Sources/Auth/Types/Errors/AuthError.swift b/Sources/Auth/Types/Errors/AuthError.swift index 84c43a7d0..f28cab817 100644 --- a/Sources/Auth/Types/Errors/AuthError.swift +++ b/Sources/Auth/Types/Errors/AuthError.swift @@ -1,4 +1,5 @@ import Foundation +import WalletConnectNetworking /// Authentication error public enum AuthError: Codable, Equatable, Error { diff --git a/Sources/Auth/Types/RequestSubscriptionPayload.swift b/Sources/Auth/Types/RequestSubscriptionPayload.swift deleted file mode 100644 index 00a5cdcb4..000000000 --- a/Sources/Auth/Types/RequestSubscriptionPayload.swift +++ /dev/null @@ -1,7 +0,0 @@ -import Foundation -import JSONRPC - -struct RequestSubscriptionPayload: Codable, Equatable { - let topic: String - let request: RPCRequest -} diff --git a/Sources/Auth/Types/ResponseSubscriptionPayload.swift b/Sources/Auth/Types/ResponseSubscriptionPayload.swift deleted file mode 100644 index d6425622f..000000000 --- a/Sources/Auth/Types/ResponseSubscriptionPayload.swift +++ /dev/null @@ -1,7 +0,0 @@ -import Foundation -import JSONRPC - -struct ResponseSubscriptionPayload: Codable, Equatable { - let topic: String - let response: RPCResponse -} diff --git a/Sources/WalletConnectNetworking/NetworkInteractor.swift b/Sources/WalletConnectNetworking/NetworkInteractor.swift new file mode 100644 index 000000000..668448236 --- /dev/null +++ b/Sources/WalletConnectNetworking/NetworkInteractor.swift @@ -0,0 +1,21 @@ +import Foundation +import Combine +import JSONRPC +import WalletConnectKMS + +public protocol NetworkInteracting { + var requestPublisher: AnyPublisher {get} + var responsePublisher: AnyPublisher {get} + func subscribe(topic: String) async throws + func unsubscribe(topic: String) + func request(_ request: RPCRequest, topic: String, tag: Int, envelopeType: Envelope.EnvelopeType) async throws + func requestNetworkAck(_ request: RPCRequest, topic: String, tag: Int) async throws + func respond(topic: String, response: RPCResponse, tag: Int, envelopeType: Envelope.EnvelopeType) async throws + func respondError(topic: String, requestId: RPCID, tag: Int, reason: Reason, envelopeType: Envelope.EnvelopeType) async throws +} + +extension NetworkInteracting { + public func request(_ request: RPCRequest, topic: String, tag: Int, envelopeType: Envelope.EnvelopeType = .type0) async throws { + try await self.request(request, topic: topic, tag: tag, envelopeType: envelopeType) + } +} diff --git a/Sources/Auth/Types/Errors/Reason.swift b/Sources/WalletConnectNetworking/Reason.swift similarity index 75% rename from Sources/Auth/Types/Errors/Reason.swift rename to Sources/WalletConnectNetworking/Reason.swift index 4822fe64c..b9b26694f 100644 --- a/Sources/Auth/Types/Errors/Reason.swift +++ b/Sources/WalletConnectNetworking/Reason.swift @@ -1,6 +1,6 @@ import Foundation -protocol Reason { +public protocol Reason { var code: Int { get } var message: String { get } } diff --git a/Sources/WalletConnectNetworking/RequestSubscriptionPayload.swift b/Sources/WalletConnectNetworking/RequestSubscriptionPayload.swift new file mode 100644 index 000000000..6132f19a2 --- /dev/null +++ b/Sources/WalletConnectNetworking/RequestSubscriptionPayload.swift @@ -0,0 +1,12 @@ +import Foundation +import JSONRPC + +public struct RequestSubscriptionPayload: Codable, Equatable { + public let topic: String + public let request: RPCRequest + + public init(topic: String, request: RPCRequest) { + self.topic = topic + self.request = request + } +} diff --git a/Sources/WalletConnectNetworking/ResponseSubscriptionPayload.swift b/Sources/WalletConnectNetworking/ResponseSubscriptionPayload.swift new file mode 100644 index 000000000..cfe2e6ab2 --- /dev/null +++ b/Sources/WalletConnectNetworking/ResponseSubscriptionPayload.swift @@ -0,0 +1,12 @@ +import Foundation +import JSONRPC + +public struct ResponseSubscriptionPayload: Codable, Equatable { + public let topic: String + public let response: RPCResponse + + public init(topic: String, response: RPCResponse) { + self.topic = topic + self.response = response + } +} diff --git a/Tests/AuthTests/AppRespondSubscriberTests.swift b/Tests/AuthTests/AppRespondSubscriberTests.swift index a5eb20c2f..95f5807db 100644 --- a/Tests/AuthTests/AppRespondSubscriberTests.swift +++ b/Tests/AuthTests/AppRespondSubscriberTests.swift @@ -2,6 +2,7 @@ import Foundation import XCTest @testable import Auth import WalletConnectUtils +import WalletConnectNetworking @testable import WalletConnectKMS @testable import TestingUtils import JSONRPC diff --git a/Tests/AuthTests/Mocks/NetworkingInteractorMock.swift b/Tests/AuthTests/Mocks/NetworkingInteractorMock.swift index 1a9c03790..5c9664d03 100644 --- a/Tests/AuthTests/Mocks/NetworkingInteractorMock.swift +++ b/Tests/AuthTests/Mocks/NetworkingInteractorMock.swift @@ -3,6 +3,7 @@ import Combine @testable import Auth import JSONRPC import WalletConnectKMS +import WalletConnectNetworking struct NetworkingInteractorMock: NetworkInteracting { diff --git a/Tests/AuthTests/Stubs/RequestSubscriptionPayload.swift b/Tests/AuthTests/Stubs/RequestSubscriptionPayload.swift index 48ded537d..156780d42 100644 --- a/Tests/AuthTests/Stubs/RequestSubscriptionPayload.swift +++ b/Tests/AuthTests/Stubs/RequestSubscriptionPayload.swift @@ -1,6 +1,7 @@ import Foundation -@testable import Auth import JSONRPC +import WalletConnectNetworking +@testable import Auth extension RequestSubscriptionPayload { static func stub(id: RPCID) -> RequestSubscriptionPayload { diff --git a/Tests/AuthTests/WalletRequestSubscriberTests.swift b/Tests/AuthTests/WalletRequestSubscriberTests.swift index bce269680..00e7f62ee 100644 --- a/Tests/AuthTests/WalletRequestSubscriberTests.swift +++ b/Tests/AuthTests/WalletRequestSubscriberTests.swift @@ -1,10 +1,11 @@ import Foundation import XCTest -@testable import Auth +import JSONRPC import WalletConnectUtils +import WalletConnectNetworking +@testable import Auth @testable import WalletConnectKMS @testable import TestingUtils -import JSONRPC class WalletRequestSubscriberTests: XCTestCase { var networkingInteractor: NetworkingInteractorMock! From 6c8dcb70334397e3d27a9c8fd6e4d409a1a7ac15 Mon Sep 17 00:00:00 2001 From: Artur Guseinov Date: Thu, 1 Sep 2022 18:41:10 +0300 Subject: [PATCH 2/4] Auth NetworkInteractor moved to package --- Package.swift | 10 ++++--- Sources/Auth/AuthClientFactory.swift | 1 + .../NetworkingInteractor.swift | 30 ++++++++++--------- 3 files changed, 23 insertions(+), 18 deletions(-) rename Sources/{Auth/Services/Common => WalletConnectNetworking}/NetworkingInteractor.swift (82%) diff --git a/Package.swift b/Package.swift index 6e0da39f7..1578731af 100644 --- a/Package.swift +++ b/Package.swift @@ -41,9 +41,6 @@ let package = Package( .target( name: "Auth", dependencies: [ - "WalletConnectRelay", - "WalletConnectUtils", - "WalletConnectKMS", "WalletConnectPairing", "WalletConnectNetworking", .product(name: "Web3", package: "Web3.swift") @@ -71,7 +68,12 @@ let package = Package( dependencies: []), .target( name: "WalletConnectNetworking", - dependencies: ["JSONRPC", "WalletConnectKMS"]), + dependencies: [ + "JSONRPC", + "WalletConnectKMS", + "WalletConnectRelay", + "WalletConnectUtils", + ]), .target( name: "WalletConnectRouter", dependencies: []), diff --git a/Sources/Auth/AuthClientFactory.swift b/Sources/Auth/AuthClientFactory.swift index 3dc48fbea..b084a1846 100644 --- a/Sources/Auth/AuthClientFactory.swift +++ b/Sources/Auth/AuthClientFactory.swift @@ -3,6 +3,7 @@ import WalletConnectRelay import WalletConnectUtils import WalletConnectKMS import WalletConnectPairing +import WalletConnectNetworking public struct AuthClientFactory { diff --git a/Sources/Auth/Services/Common/NetworkingInteractor.swift b/Sources/WalletConnectNetworking/NetworkingInteractor.swift similarity index 82% rename from Sources/Auth/Services/Common/NetworkingInteractor.swift rename to Sources/WalletConnectNetworking/NetworkingInteractor.swift index b1cc7684a..91a664578 100644 --- a/Sources/Auth/Services/Common/NetworkingInteractor.swift +++ b/Sources/WalletConnectNetworking/NetworkingInteractor.swift @@ -1,12 +1,11 @@ import Foundation import Combine import JSONRPC -import WalletConnectNetworking import WalletConnectRelay import WalletConnectUtils import WalletConnectKMS -class NetworkingInteractor: NetworkInteracting { +public class NetworkingInteractor: NetworkInteracting { private var publishers = Set() private let relayClient: RelayClient private let serializer: Serializing @@ -14,21 +13,24 @@ class NetworkingInteractor: NetworkInteracting { private let logger: ConsoleLogging private let requestPublisherSubject = PassthroughSubject() - var requestPublisher: AnyPublisher { + private let responsePublisherSubject = PassthroughSubject() + + public var requestPublisher: AnyPublisher { requestPublisherSubject.eraseToAnyPublisher() } - private let responsePublisherSubject = PassthroughSubject() - var responsePublisher: AnyPublisher { + public var responsePublisher: AnyPublisher { responsePublisherSubject.eraseToAnyPublisher() } - var socketConnectionStatusPublisher: AnyPublisher + public var socketConnectionStatusPublisher: AnyPublisher - init(relayClient: RelayClient, + public init( + relayClient: RelayClient, serializer: Serializing, logger: ConsoleLogging, - rpcHistory: RPCHistory) { + rpcHistory: RPCHistory + ) { self.relayClient = relayClient self.serializer = serializer self.rpcHistory = rpcHistory @@ -40,11 +42,11 @@ class NetworkingInteractor: NetworkInteracting { .store(in: &publishers) } - func subscribe(topic: String) async throws { + public func subscribe(topic: String) async throws { try await relayClient.subscribe(topic: topic) } - func unsubscribe(topic: String) { + public func unsubscribe(topic: String) { relayClient.unsubscribe(topic: topic) { [unowned self] error in if let error = error { logger.error(error) @@ -54,7 +56,7 @@ class NetworkingInteractor: NetworkInteracting { } } - func request(_ request: RPCRequest, topic: String, tag: Int, envelopeType: Envelope.EnvelopeType) async throws { + public func request(_ request: RPCRequest, topic: String, tag: Int, envelopeType: Envelope.EnvelopeType) async throws { try rpcHistory.set(request, forTopic: topic, emmitedBy: .local) let message = try! serializer.serialize(topic: topic, encodable: request, envelopeType: envelopeType) try await relayClient.publish(topic: topic, payload: message, tag: tag) @@ -63,7 +65,7 @@ class NetworkingInteractor: NetworkInteracting { /// Completes with an acknowledgement from the relay network. /// completes with error if networking client was not able to send a message /// TODO - relay client should provide async function - continualion should be removed from here - func requestNetworkAck(_ request: RPCRequest, topic: String, tag: Int) async throws { + public func requestNetworkAck(_ request: RPCRequest, topic: String, tag: Int) async throws { do { try rpcHistory.set(request, forTopic: topic, emmitedBy: .local) let message = try serializer.serialize(topic: topic, encodable: request) @@ -81,13 +83,13 @@ class NetworkingInteractor: NetworkInteracting { } } - func respond(topic: String, response: RPCResponse, tag: Int, envelopeType: Envelope.EnvelopeType) async throws { + public func respond(topic: String, response: RPCResponse, tag: Int, envelopeType: Envelope.EnvelopeType) async throws { try rpcHistory.resolve(response) let message = try! serializer.serialize(topic: topic, encodable: response, envelopeType: envelopeType) try await relayClient.publish(topic: topic, payload: message, tag: tag) } - func respondError(topic: String, requestId: RPCID, tag: Int, reason: Reason, envelopeType: Envelope.EnvelopeType) async throws { + public func respondError(topic: String, requestId: RPCID, tag: Int, reason: Reason, envelopeType: Envelope.EnvelopeType) async throws { let error = JSONRPCError(code: reason.code, message: reason.message) let response = RPCResponse(id: requestId, error: error) let message = try! serializer.serialize(topic: topic, encodable: response, envelopeType: envelopeType) From 8cf76ad1772fad3a1b0fc3dc0e15c225b2a2508d Mon Sep 17 00:00:00 2001 From: Artur Guseinov Date: Thu, 1 Sep 2022 22:24:12 +0300 Subject: [PATCH 3/4] Chat Genaric interactor connected --- .../xcschemes/WalletConnectChat.xcscheme | 77 +++++++++++ Package.swift | 17 +-- Sources/Auth/AuthClientFactory.swift | 3 +- Sources/Chat/ChatClient.swift | 7 +- Sources/Chat/ChatClientFactory.swift | 10 +- Sources/Chat/NetworkingInteractor.swift | 122 ------------------ .../Chat/ProtocolServices/Common/File.swift | 4 +- .../Common/MessagingService.swift | 44 +++---- .../Invitee/InvitationHandlingService.swift | 64 ++++----- .../Invitee/RegistryService.swift | 1 + .../Inviter/InviteService.swift | 56 ++++---- Sources/Chat/Types/ChatError.swift | 15 +++ Sources/Chat/Types/ChatRequestParams.swift | 63 --------- Sources/Chat/Types/ChatResponse.swift | 9 -- .../{InviteParams.swift => Invite.swift} | 8 ++ Sources/Chat/Types/Message.swift | 22 +++- .../Types/RequestSubscriptionPayload.swift | 7 - .../NetworkInteractor.swift | 23 +++- .../NetworkingInteractor.swift | 14 +- .../Mocks/NetworkingInteractorMock.swift | 44 ------- .../Mocks/NetworkingInteractorMock.swift | 50 ------- Tests/ChatTests/RegistryManagerTests.swift | 5 +- .../NetworkingInteractorMock.swift | 58 +++++++++ 23 files changed, 298 insertions(+), 425 deletions(-) create mode 100644 .swiftpm/xcode/xcshareddata/xcschemes/WalletConnectChat.xcscheme delete mode 100644 Sources/Chat/NetworkingInteractor.swift delete mode 100644 Sources/Chat/Types/ChatRequestParams.swift delete mode 100644 Sources/Chat/Types/ChatResponse.swift rename Sources/Chat/Types/{InviteParams.swift => Invite.swift} (71%) delete mode 100644 Sources/Chat/Types/RequestSubscriptionPayload.swift delete mode 100644 Tests/AuthTests/Mocks/NetworkingInteractorMock.swift delete mode 100644 Tests/ChatTests/Mocks/NetworkingInteractorMock.swift create mode 100644 Tests/TestingUtils/NetworkingInteractorMock.swift diff --git a/.swiftpm/xcode/xcshareddata/xcschemes/WalletConnectChat.xcscheme b/.swiftpm/xcode/xcshareddata/xcschemes/WalletConnectChat.xcscheme new file mode 100644 index 000000000..c04003b78 --- /dev/null +++ b/.swiftpm/xcode/xcshareddata/xcschemes/WalletConnectChat.xcscheme @@ -0,0 +1,77 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Package.swift b/Package.swift index 1578731af..a562eca58 100644 --- a/Package.swift +++ b/Package.swift @@ -36,15 +36,11 @@ let package = Package( path: "Sources/WalletConnectSign"), .target( name: "Chat", - dependencies: ["WalletConnectRelay", "WalletConnectUtils", "WalletConnectKMS"], + dependencies: ["WalletConnectNetworking"], path: "Sources/Chat"), .target( name: "Auth", - dependencies: [ - "WalletConnectPairing", - "WalletConnectNetworking", - .product(name: "Web3", package: "Web3.swift") - ], + dependencies: ["WalletConnectPairing", "WalletConnectNetworking", .product(name: "Web3", package: "Web3.swift")], path: "Sources/Auth"), .target( name: "WalletConnectRelay", @@ -68,12 +64,7 @@ let package = Package( dependencies: []), .target( name: "WalletConnectNetworking", - dependencies: [ - "JSONRPC", - "WalletConnectKMS", - "WalletConnectRelay", - "WalletConnectUtils", - ]), + dependencies: ["JSONRPC", "WalletConnectKMS", "WalletConnectRelay", "WalletConnectUtils"]), .target( name: "WalletConnectRouter", dependencies: []), @@ -94,7 +85,7 @@ let package = Package( dependencies: ["WalletConnectKMS", "WalletConnectUtils", "TestingUtils"]), .target( name: "TestingUtils", - dependencies: ["WalletConnectUtils", "WalletConnectKMS", "JSONRPC", "WalletConnectPairing"], + dependencies: ["WalletConnectPairing", "WalletConnectNetworking"], path: "Tests/TestingUtils"), .testTarget( name: "WalletConnectUtilsTests", diff --git a/Sources/Auth/AuthClientFactory.swift b/Sources/Auth/AuthClientFactory.swift index b084a1846..469fa37a6 100644 --- a/Sources/Auth/AuthClientFactory.swift +++ b/Sources/Auth/AuthClientFactory.swift @@ -42,6 +42,7 @@ public struct AuthClientFactory { pendingRequestsProvider: pendingRequestsProvider, cleanupService: cleanupService, logger: logger, - pairingStorage: pairingStore, socketConnectionStatusPublisher: relayClient.socketConnectionStatusPublisher) + pairingStorage: pairingStore, + socketConnectionStatusPublisher: relayClient.socketConnectionStatusPublisher) } } diff --git a/Sources/Chat/ChatClient.swift b/Sources/Chat/ChatClient.swift index 1c44bbeb6..678a3436e 100644 --- a/Sources/Chat/ChatClient.swift +++ b/Sources/Chat/ChatClient.swift @@ -2,6 +2,7 @@ import Foundation import WalletConnectUtils import WalletConnectKMS import WalletConnectRelay +import WalletConnectNetworking import Combine public class ChatClient { @@ -16,7 +17,7 @@ public class ChatClient { private let kms: KeyManagementService private let threadStore: Database private let messagesStore: Database - private let invitePayloadStore: CodableStore<(RequestSubscriptionPayload)> + private let invitePayloadStore: CodableStore public let socketConnectionStatusPublisher: AnyPublisher @@ -47,7 +48,7 @@ public class ChatClient { kms: KeyManagementService, threadStore: Database, messagesStore: Database, - invitePayloadStore: CodableStore<(RequestSubscriptionPayload)>, + invitePayloadStore: CodableStore, socketConnectionStatusPublisher: AnyPublisher ) { self.registry = registry @@ -121,7 +122,7 @@ public class ChatClient { public func getInvites(account: Account) -> [Invite] { var invites = [Invite]() invitePayloadStore.getAll().forEach { - guard case .invite(let invite) = $0.request.params else {return} + guard let invite = try? $0.request.params?.get(Invite.self) else {return} invites.append(invite) } return invites diff --git a/Sources/Chat/ChatClientFactory.swift b/Sources/Chat/ChatClientFactory.swift index 89f4907b1..47ae2dcdd 100644 --- a/Sources/Chat/ChatClientFactory.swift +++ b/Sources/Chat/ChatClientFactory.swift @@ -2,6 +2,7 @@ import Foundation import WalletConnectRelay import WalletConnectUtils import WalletConnectKMS +import WalletConnectNetworking public struct ChatClientFactory { @@ -10,17 +11,18 @@ public struct ChatClientFactory { relayClient: RelayClient, kms: KeyManagementService, logger: ConsoleLogging, - keyValueStorage: KeyValueStorage) -> ChatClient { + keyValueStorage: KeyValueStorage + ) -> ChatClient { let topicToRegistryRecordStore = CodableStore(defaults: keyValueStorage, identifier: StorageDomainIdentifiers.topicToInvitationPubKey.rawValue) let serialiser = Serializer(kms: kms) - let jsonRpcHistory = JsonRpcHistory(logger: logger, keyValueStore: CodableStore(defaults: keyValueStorage, identifier: StorageDomainIdentifiers.jsonRpcHistory.rawValue)) - let networkingInteractor = NetworkingInteractor(relayClient: relayClient, serializer: serialiser, logger: logger, jsonRpcHistory: jsonRpcHistory) + let rpcHistory = RPCHistory(keyValueStore: CodableStore(defaults: keyValueStorage, identifier: StorageDomainIdentifiers.jsonRpcHistory.rawValue)) + let networkingInteractor = NetworkingInteractor(relayClient: relayClient, serializer: serialiser, logger: logger, rpcHistory: rpcHistory) let invitePayloadStore = CodableStore(defaults: keyValueStorage, identifier: StorageDomainIdentifiers.invite.rawValue) let registryService = RegistryService(registry: registry, networkingInteractor: networkingInteractor, kms: kms, logger: logger, topicToRegistryRecordStore: topicToRegistryRecordStore) let threadStore = Database(keyValueStorage: keyValueStorage, identifier: StorageDomainIdentifiers.threads.rawValue) let resubscriptionService = ResubscriptionService(networkingInteractor: networkingInteractor, threadStore: threadStore, logger: logger) let invitationHandlingService = InvitationHandlingService(registry: registry, networkingInteractor: networkingInteractor, kms: kms, logger: logger, topicToRegistryRecordStore: topicToRegistryRecordStore, invitePayloadStore: invitePayloadStore, threadsStore: threadStore) - let inviteService = InviteService(networkingInteractor: networkingInteractor, kms: kms, threadStore: threadStore, logger: logger) + let inviteService = InviteService(networkingInteractor: networkingInteractor, kms: kms, threadStore: threadStore, rpcHistory: rpcHistory, logger: logger) let leaveService = LeaveService() let messagesStore = Database(keyValueStorage: keyValueStorage, identifier: StorageDomainIdentifiers.messages.rawValue) let messagingService = MessagingService(networkingInteractor: networkingInteractor, messagesStore: messagesStore, threadStore: threadStore, logger: logger) diff --git a/Sources/Chat/NetworkingInteractor.swift b/Sources/Chat/NetworkingInteractor.swift deleted file mode 100644 index ee31ec033..000000000 --- a/Sources/Chat/NetworkingInteractor.swift +++ /dev/null @@ -1,122 +0,0 @@ -import Foundation -import Combine -import WalletConnectRelay -import WalletConnectUtils -import WalletConnectKMS - -protocol NetworkInteracting { - var socketConnectionStatusPublisher: AnyPublisher { get } - var requestPublisher: AnyPublisher {get} - var responsePublisher: AnyPublisher {get} - func respondSuccess(payload: RequestSubscriptionPayload) async throws - func subscribe(topic: String) async throws - func request(_ request: JSONRPCRequest, topic: String, envelopeType: Envelope.EnvelopeType) async throws - func respond(topic: String, response: JsonRpcResult, tag: Int) async throws -} - -extension NetworkInteracting { - func request(_ request: JSONRPCRequest, topic: String, envelopeType: Envelope.EnvelopeType = .type0) async throws { - try await self.request(request, topic: topic, envelopeType: envelopeType) - } -} - -class NetworkingInteractor: NetworkInteracting { - enum Error: Swift.Error { - case failedToInitialiseMethodFromRecord - } - private let jsonRpcHistory: JsonRpcHistory - private let serializer: Serializing - private let relayClient: RelayClient - private let logger: ConsoleLogging - var requestPublisher: AnyPublisher { - requestPublisherSubject.eraseToAnyPublisher() - } - private let requestPublisherSubject = PassthroughSubject() - - var responsePublisher: AnyPublisher { - responsePublisherSubject.eraseToAnyPublisher() - } - private let responsePublisherSubject = PassthroughSubject() - var socketConnectionStatusPublisher: AnyPublisher - - private var publishers = Set() - - init(relayClient: RelayClient, - serializer: Serializing, - logger: ConsoleLogging, - jsonRpcHistory: JsonRpcHistory - ) { - self.relayClient = relayClient - self.serializer = serializer - self.jsonRpcHistory = jsonRpcHistory - self.logger = logger - self.socketConnectionStatusPublisher = relayClient.socketConnectionStatusPublisher - - relayClient.messagePublisher.sink { [unowned self] (topic, message) in - manageSubscription(topic, message) - }.store(in: &publishers) - } - - func request(_ request: JSONRPCRequest, topic: String, envelopeType: Envelope.EnvelopeType) async throws { - try jsonRpcHistory.set(topic: topic, request: request) - let message = try! serializer.serialize(topic: topic, encodable: request, envelopeType: envelopeType) - try await relayClient.publish(topic: topic, payload: message, tag: request.params.tag) - } - - func respondSuccess(payload: RequestSubscriptionPayload) async throws { - let response = JSONRPCResponse(id: payload.request.id, result: AnyCodable(true)) - try await respond(topic: payload.topic, response: JsonRpcResult.response(response), tag: payload.request.params.responseTag) - } - - func respond(topic: String, response: JsonRpcResult, tag: Int) async throws { - _ = try jsonRpcHistory.resolve(response: response) - let message = try serializer.serialize(topic: topic, encodable: response.value) - try await relayClient.publish(topic: topic, payload: message, tag: tag, prompt: false) - } - - func subscribe(topic: String) async throws { - try await relayClient.subscribe(topic: topic) - } - - private func manageSubscription(_ topic: String, _ encodedEnvelope: String) { - if let deserializedJsonRpcRequest: JSONRPCRequest = serializer.tryDeserialize(topic: topic, encodedEnvelope: encodedEnvelope) { - handleChatRequest(topic: topic, request: deserializedJsonRpcRequest) - } else if let deserializedJsonRpcResponse: JSONRPCResponse = serializer.tryDeserialize(topic: topic, encodedEnvelope: encodedEnvelope) { - handleJsonRpcResponse(response: deserializedJsonRpcResponse) - } else if let deserializedJsonRpcError: JSONRPCErrorResponse = serializer.tryDeserialize(topic: topic, encodedEnvelope: encodedEnvelope) { - handleJsonRpcErrorResponse(response: deserializedJsonRpcError) - } else { - logger.warn("Networking Interactor - Received unknown object type from networking relay") - } - } - - private func handleChatRequest(topic: String, request: JSONRPCRequest) { - do { - try jsonRpcHistory.set(topic: topic, request: request) - let payload = RequestSubscriptionPayload(topic: topic, request: request) - requestPublisherSubject.send(payload) - } catch { - logger.debug(error) - } - } - - private func handleJsonRpcResponse(response: JSONRPCResponse) { - do { - let record = try jsonRpcHistory.resolve(response: JsonRpcResult.response(response)) - let params = try record.request.params.get(ChatRequestParams.self) - let chatResponse = ChatResponse( - topic: record.topic, - requestMethod: record.request.method, - requestParams: params, - result: JsonRpcResult.response(response)) - responsePublisherSubject.send(chatResponse) - } catch { - logger.debug("Handle json rpc response error: \(error)") - } - } - - private func handleJsonRpcErrorResponse(response: JSONRPCErrorResponse) { - // todo - } - -} diff --git a/Sources/Chat/ProtocolServices/Common/File.swift b/Sources/Chat/ProtocolServices/Common/File.swift index 8bd04f569..e821f03d7 100644 --- a/Sources/Chat/ProtocolServices/Common/File.swift +++ b/Sources/Chat/ProtocolServices/Common/File.swift @@ -1,6 +1,8 @@ import Foundation -import WalletConnectUtils import Combine +import WalletConnectRelay +import WalletConnectUtils +import WalletConnectNetworking class ResubscriptionService { private let networkingInteractor: NetworkInteracting diff --git a/Sources/Chat/ProtocolServices/Common/MessagingService.swift b/Sources/Chat/ProtocolServices/Common/MessagingService.swift index ca774136d..eaeaf061e 100644 --- a/Sources/Chat/ProtocolServices/Common/MessagingService.swift +++ b/Sources/Chat/ProtocolServices/Common/MessagingService.swift @@ -1,6 +1,8 @@ import Foundation -import WalletConnectUtils import Combine +import JSONRPC +import WalletConnectUtils +import WalletConnectNetworking class MessagingService { enum Errors: Error { @@ -31,8 +33,8 @@ class MessagingService { guard let authorAccount = thread?.selfAccount else { throw Errors.threadDoNotExist} let timestamp = Int64(Date().timeIntervalSince1970 * 1000) let message = Message(topic: topic, message: messageString, authorAccount: authorAccount, timestamp: timestamp) - let request = JSONRPCRequest(params: .message(message)) - try await networkingInteractor.request(request, topic: topic, envelopeType: .type0) + let request = RPCRequest(method: Message.method, params: message) + try await networkingInteractor.request(request, topic: topic, tag: Message.tag) Task(priority: .background) { await messagesStore.add(message) onMessage?(message) @@ -41,38 +43,34 @@ class MessagingService { private func setUpResponseHandling() { networkingInteractor.responsePublisher - .sink { [unowned self] response in - switch response.requestParams { - case .message: - handleMessageResponse(response) - default: - return - } + .sink { [unowned self] payload in + logger.debug("Received Message response") }.store(in: &publishers) } private func setUpRequestHandling() { - networkingInteractor.requestPublisher.sink { [unowned self] subscriptionPayload in - switch subscriptionPayload.request.params { - case .message(var message): - message.topic = subscriptionPayload.topic - handleMessage(message, subscriptionPayload) - default: - return + networkingInteractor.requestPublisher.sink { [unowned self] payload in + do { + guard + let requestId = payload.request.id, payload.request.method == Message.method, + var message = try payload.request.params?.get(Message.self) + else { return } + + message.topic = payload.topic + + handleMessage(message, topic: payload.topic, requestId: requestId) + } catch { + logger.debug("Handling message response has failed") } }.store(in: &publishers) } - private func handleMessage(_ message: Message, _ payload: RequestSubscriptionPayload) { + private func handleMessage(_ message: Message, topic: String, requestId: RPCID) { Task(priority: .background) { - try await networkingInteractor.respondSuccess(payload: payload) + try await networkingInteractor.respondSuccess(topic: topic, requestId: requestId, tag: Message.tag) await messagesStore.add(message) logger.debug("Received message") onMessage?(message) } } - - private func handleMessageResponse(_ response: ChatResponse) { - logger.debug("Received Message response") - } } diff --git a/Sources/Chat/ProtocolServices/Invitee/InvitationHandlingService.swift b/Sources/Chat/ProtocolServices/Invitee/InvitationHandlingService.swift index 38021014b..102e9f00a 100644 --- a/Sources/Chat/ProtocolServices/Invitee/InvitationHandlingService.swift +++ b/Sources/Chat/ProtocolServices/Invitee/InvitationHandlingService.swift @@ -1,8 +1,10 @@ import Foundation +import Combine +import JSONRPC import WalletConnectKMS import WalletConnectUtils import WalletConnectRelay -import Combine +import WalletConnectNetworking class InvitationHandlingService { enum Error: Swift.Error { @@ -11,7 +13,7 @@ class InvitationHandlingService { var onInvite: ((Invite) -> Void)? var onNewThread: ((Thread) -> Void)? private let networkingInteractor: NetworkInteracting - private let invitePayloadStore: CodableStore<(RequestSubscriptionPayload)> + private let invitePayloadStore: CodableStore private let topicToRegistryRecordStore: CodableStore private let registry: Registry private let logger: ConsoleLogging @@ -37,27 +39,22 @@ class InvitationHandlingService { } func accept(inviteId: String) async throws { - guard let payload = try invitePayloadStore.get(key: inviteId) else { throw Error.inviteForIdNotFound } let selfThreadPubKey = try kms.createX25519KeyPair() let inviteResponse = InviteResponse(publicKey: selfThreadPubKey.hexRepresentation) - let response = JsonRpcResult.response(JSONRPCResponse(id: payload.request.id, result: AnyCodable(inviteResponse))) - - guard case .invite(let invite) = payload.request.params else {return} + guard let requestId = payload.request.id, let invite = try? payload.request.params?.get(Invite.self) + else { return } - let responseTopic = try getInviteResponseTopic(payload, invite) - - try await networkingInteractor.respond(topic: responseTopic, response: response, tag: payload.request.params.responseTag) + let response = RPCResponse(id: requestId, result: inviteResponse) + let responseTopic = try getInviteResponseTopic(requestTopic: payload.topic, invite: invite) + try await networkingInteractor.respond(topic: responseTopic, response: response, tag: Invite.tag) let threadAgreementKeys = try kms.performKeyAgreement(selfPublicKey: selfThreadPubKey, peerPublicKey: invite.publicKey) - let threadTopic = threadAgreementKeys.derivedTopic() - try kms.setSymmetricKey(threadAgreementKeys.sharedKey, for: threadTopic) - try await networkingInteractor.subscribe(topic: threadTopic) logger.debug("Accepting an invite on topic: \(threadTopic)") @@ -73,47 +70,36 @@ class InvitationHandlingService { } func reject(inviteId: String) async throws { - guard let payload = try invitePayloadStore.get(key: inviteId) else { throw Error.inviteForIdNotFound } - guard case .invite(let invite) = payload.request.params else {return} + guard let requestId = payload.request.id, let invite = try? payload.request.params?.get(Invite.self) + else { return } - let responseTopic = try getInviteResponseTopic(payload, invite) + let responseTopic = try getInviteResponseTopic(requestTopic: payload.topic, invite: invite) - // TODO - error not in specs yet - let error = JSONRPCErrorResponse.Error(code: 0, message: "user rejected") - let response = JsonRpcResult.error(JSONRPCErrorResponse(id: payload.request.id, error: error)) - - try await networkingInteractor.respond(topic: responseTopic, response: response, tag: payload.request.params.responseTag) + try await networkingInteractor.respondError(topic: responseTopic, requestId: requestId, tag: Invite.tag, reason: ChatError.userRejected) invitePayloadStore.delete(forKey: inviteId) } private func setUpRequestHandling() { - networkingInteractor.requestPublisher.sink { [unowned self] subscriptionPayload in - switch subscriptionPayload.request.params { - case .invite(let invite): - do { - try handleInvite(invite, subscriptionPayload) - } catch { - logger.debug("Did not handle invite, error: \(error)") - } - default: - return - } - }.store(in: &publishers) - } + networkingInteractor.requestPublisher.sink { [unowned self] payload in + guard payload.request.method == "wc_chatInvite" + else { return } + + guard let invite = try? payload.request.params?.get(Invite.self) + else { return } - private func handleInvite(_ invite: Invite, _ payload: RequestSubscriptionPayload) throws { - logger.debug("did receive an invite") - invitePayloadStore.set(payload, forKey: invite.publicKey) - onInvite?(invite) + logger.debug("did receive an invite") + invitePayloadStore.set(payload, forKey: invite.publicKey) + onInvite?(invite) + }.store(in: &publishers) } - private func getInviteResponseTopic(_ payload: RequestSubscriptionPayload, _ invite: Invite) throws -> String { + private func getInviteResponseTopic(requestTopic: String, invite: Invite) throws -> String { // todo - remove topicToInvitationPubKeyStore ? - guard let record = try? topicToRegistryRecordStore.get(key: payload.topic) else { + guard let record = try? topicToRegistryRecordStore.get(key: requestTopic) else { logger.debug("PubKey for invitation topic not found") fatalError("todo") } diff --git a/Sources/Chat/ProtocolServices/Invitee/RegistryService.swift b/Sources/Chat/ProtocolServices/Invitee/RegistryService.swift index 33a5241a8..4476f306e 100644 --- a/Sources/Chat/ProtocolServices/Invitee/RegistryService.swift +++ b/Sources/Chat/ProtocolServices/Invitee/RegistryService.swift @@ -1,6 +1,7 @@ import Foundation import WalletConnectUtils import WalletConnectKMS +import WalletConnectNetworking actor RegistryService { let networkingInteractor: NetworkInteracting diff --git a/Sources/Chat/ProtocolServices/Inviter/InviteService.swift b/Sources/Chat/ProtocolServices/Inviter/InviteService.swift index f3a5d32b9..d3051cf2d 100644 --- a/Sources/Chat/ProtocolServices/Inviter/InviteService.swift +++ b/Sources/Chat/ProtocolServices/Inviter/InviteService.swift @@ -1,7 +1,9 @@ import Foundation +import Combine +import JSONRPC import WalletConnectKMS import WalletConnectUtils -import Combine +import WalletConnectNetworking class InviteService { private var publishers = [AnyCancellable]() @@ -9,6 +11,7 @@ class InviteService { private let logger: ConsoleLogging private let kms: KeyManagementService private let threadStore: Database + private let rpcHistory: RPCHistory var onNewThread: ((Thread) -> Void)? var onInvite: ((Invite) -> Void)? @@ -16,11 +19,13 @@ class InviteService { init(networkingInteractor: NetworkInteracting, kms: KeyManagementService, threadStore: Database, + rpcHistory: RPCHistory, logger: ConsoleLogging) { self.kms = kms self.networkingInteractor = networkingInteractor self.logger = logger self.threadStore = threadStore + self.rpcHistory = rpcHistory setUpResponseHandling() } @@ -37,7 +42,7 @@ class InviteService { // overrides on invite toipic try kms.setSymmetricKey(symKeyI.sharedKey, for: inviteTopic) - let request = JSONRPCRequest(params: .invite(invite)) + let request = RPCRequest(method: Invite.method, params: invite) // 2. Proposer subscribes to topic R which is the hash of the derived symKey let responseTopic = symKeyI.derivedTopic() @@ -45,40 +50,35 @@ class InviteService { try kms.setSymmetricKey(symKeyI.sharedKey, for: responseTopic) try await networkingInteractor.subscribe(topic: responseTopic) - try await networkingInteractor.request(request, topic: inviteTopic, envelopeType: .type1(pubKey: selfPubKeyY.rawRepresentation)) + try await networkingInteractor.request(request, topic: inviteTopic, tag: Invite.tag, envelopeType: .type1(pubKey: selfPubKeyY.rawRepresentation)) logger.debug("invite sent on topic: \(inviteTopic)") } private func setUpResponseHandling() { networkingInteractor.responsePublisher - .sink { [unowned self] response in - switch response.requestParams { - case .invite: - handleInviteResponse(response) - default: - return - } - }.store(in: &publishers) - } + .sink { [unowned self] payload in + do { + guard + let requestId = payload.response.id, + let request = rpcHistory.get(recordId: requestId)?.request, + let requestParams = request.params, request.method == Invite.method + else { return } - private func handleInviteResponse(_ response: ChatResponse) { - switch response.result { - case .response(let jsonrpc): - do { - let inviteResponse = try jsonrpc.result.get(InviteResponse.self) - logger.debug("Invite has been accepted") - guard case .invite(let inviteParams) = response.requestParams else { return } - Task(priority: .background) { - try await createThread(selfPubKeyHex: inviteParams.publicKey, peerPubKey: inviteResponse.publicKey, account: inviteParams.account, peerAccount: peerAccount) + guard let inviteResponse = try payload.response.result?.get(InviteResponse.self) + else { return } + + let inviteParams = try requestParams.get(Invite.self) + + logger.debug("Invite has been accepted") + + Task(priority: .background) { + try await createThread(selfPubKeyHex: inviteParams.publicKey, peerPubKey: inviteResponse.publicKey, account: inviteParams.account, peerAccount: peerAccount) + } + } catch { + logger.debug("Handling invite response has failed") } - } catch { - logger.debug("Handling invite response has failed") - } - case .error: - logger.debug("Invite has been rejected") - // TODO - remove keys, clean storage - } + }.store(in: &publishers) } private func createThread(selfPubKeyHex: String, peerPubKey: String, account: Account, peerAccount: Account) async throws { diff --git a/Sources/Chat/Types/ChatError.swift b/Sources/Chat/Types/ChatError.swift index 0672ba16f..edac89e77 100644 --- a/Sources/Chat/Types/ChatError.swift +++ b/Sources/Chat/Types/ChatError.swift @@ -1,6 +1,21 @@ import Foundation +import WalletConnectNetworking enum ChatError: Error { case noInviteForId case recordNotFound + case userRejected +} + +extension ChatError: Reason { + + var code: Int { + // Errors not in specs yet + return 0 + } + + var message: String { + // Errors not in specs yet + return localizedDescription + } } diff --git a/Sources/Chat/Types/ChatRequestParams.swift b/Sources/Chat/Types/ChatRequestParams.swift deleted file mode 100644 index 51b9e512d..000000000 --- a/Sources/Chat/Types/ChatRequestParams.swift +++ /dev/null @@ -1,63 +0,0 @@ -import Foundation -import WalletConnectUtils - -enum ChatRequestParams: Codable, Equatable { - enum Errors: Error { - case decoding - } - case invite(Invite) - case message(Message) - - private enum CodingKeys: String, CodingKey { - case invite - case message - } - - func encode(to encoder: Encoder) throws { - switch self { - case .invite(let invite): - try invite.encode(to: encoder) - case .message(let message): - try message.encode(to: encoder) - } - } - - init(from decoder: Decoder) throws { - if let invite = try? Invite(from: decoder) { - self = .invite(invite) - } else if let massage = try? Message(from: decoder) { - self = .message(massage) - } else { - throw Errors.decoding - } - } -} - -extension ChatRequestParams { - - var tag: Int { - switch self { - case .invite: - return 2000 - case .message: - return 2002 - } - } - - var responseTag: Int { - return tag + 1 - } -} - -extension JSONRPCRequest { - init(id: Int64 = JsonRpcID.generate(), params: T) where T == ChatRequestParams { - var method: String! - switch params { - case .invite: - method = "wc_chatInvite" - case .message: - method = "wc_chatMessage" - } - self.init(id: id, method: method, params: params) - } -} diff --git a/Sources/Chat/Types/ChatResponse.swift b/Sources/Chat/Types/ChatResponse.swift deleted file mode 100644 index 448abb7e8..000000000 --- a/Sources/Chat/Types/ChatResponse.swift +++ /dev/null @@ -1,9 +0,0 @@ -import Foundation -import WalletConnectUtils - -struct ChatResponse: Codable { - let topic: String - let requestMethod: String - let requestParams: ChatRequestParams - let result: JsonRpcResult -} diff --git a/Sources/Chat/Types/InviteParams.swift b/Sources/Chat/Types/Invite.swift similarity index 71% rename from Sources/Chat/Types/InviteParams.swift rename to Sources/Chat/Types/Invite.swift index f5b0f7180..5f69e72e8 100644 --- a/Sources/Chat/Types/InviteParams.swift +++ b/Sources/Chat/Types/Invite.swift @@ -12,4 +12,12 @@ public struct Invite: Codable, Equatable { public let message: String public let account: Account public let publicKey: String + + static var tag: Int { + return 2000 + } + + static var method: String { + return "wc_chatInvite" + } } diff --git a/Sources/Chat/Types/Message.swift b/Sources/Chat/Types/Message.swift index 7325d8a21..09113ed2a 100644 --- a/Sources/Chat/Types/Message.swift +++ b/Sources/Chat/Types/Message.swift @@ -2,13 +2,6 @@ import Foundation import WalletConnectUtils public struct Message: Codable, Equatable { - internal init(topic: String? = nil, message: String, authorAccount: Account, timestamp: Int64) { - self.topic = topic - self.message = message - self.authorAccount = authorAccount - self.timestamp = timestamp - } - public var topic: String? public let message: String public let authorAccount: Account @@ -20,4 +13,19 @@ public struct Message: Codable, Equatable { case authorAccount case timestamp } + + static var tag: Int { + return 2002 + } + + static var method: String { + return "wc_chatMessage" + } + + init(topic: String? = nil, message: String, authorAccount: Account, timestamp: Int64) { + self.topic = topic + self.message = message + self.authorAccount = authorAccount + self.timestamp = timestamp + } } diff --git a/Sources/Chat/Types/RequestSubscriptionPayload.swift b/Sources/Chat/Types/RequestSubscriptionPayload.swift deleted file mode 100644 index 575af574a..000000000 --- a/Sources/Chat/Types/RequestSubscriptionPayload.swift +++ /dev/null @@ -1,7 +0,0 @@ -import Foundation -import WalletConnectUtils - -struct RequestSubscriptionPayload: Codable { - let topic: String - let request: JSONRPCRequest -} diff --git a/Sources/WalletConnectNetworking/NetworkInteractor.swift b/Sources/WalletConnectNetworking/NetworkInteractor.swift index 668448236..fca33ed16 100644 --- a/Sources/WalletConnectNetworking/NetworkInteractor.swift +++ b/Sources/WalletConnectNetworking/NetworkInteractor.swift @@ -2,20 +2,35 @@ import Foundation import Combine import JSONRPC import WalletConnectKMS +import WalletConnectRelay public protocol NetworkInteracting { - var requestPublisher: AnyPublisher {get} - var responsePublisher: AnyPublisher {get} + var socketConnectionStatusPublisher: AnyPublisher { get } + var requestPublisher: AnyPublisher { get } + var responsePublisher: AnyPublisher { get } func subscribe(topic: String) async throws func unsubscribe(topic: String) func request(_ request: RPCRequest, topic: String, tag: Int, envelopeType: Envelope.EnvelopeType) async throws func requestNetworkAck(_ request: RPCRequest, topic: String, tag: Int) async throws func respond(topic: String, response: RPCResponse, tag: Int, envelopeType: Envelope.EnvelopeType) async throws + func respondSuccess(topic: String, requestId: RPCID, tag: Int, envelopeType: Envelope.EnvelopeType) async throws func respondError(topic: String, requestId: RPCID, tag: Int, reason: Reason, envelopeType: Envelope.EnvelopeType) async throws } extension NetworkInteracting { - public func request(_ request: RPCRequest, topic: String, tag: Int, envelopeType: Envelope.EnvelopeType = .type0) async throws { - try await self.request(request, topic: topic, tag: tag, envelopeType: envelopeType) + public func request(_ request: RPCRequest, topic: String, tag: Int) async throws { + try await self.request(request, topic: topic, tag: tag, envelopeType: .type0) + } + + public func respond(topic: String, response: RPCResponse, tag: Int) async throws { + try await self.respond(topic: topic, response: response, tag: tag, envelopeType: .type0) + } + + public func respondSuccess(topic: String, requestId: RPCID, tag: Int) async throws { + try await self.respondSuccess(topic: topic, requestId: requestId, tag: tag, envelopeType: .type0) + } + + public func respondError(topic: String, requestId: RPCID, tag: Int, reason: Reason) async throws { + try await self.respondError(topic: topic, requestId: requestId, tag: tag, reason: reason, envelopeType: .type0) } } diff --git a/Sources/WalletConnectNetworking/NetworkingInteractor.swift b/Sources/WalletConnectNetworking/NetworkingInteractor.swift index 91a664578..cf4f99e46 100644 --- a/Sources/WalletConnectNetworking/NetworkingInteractor.swift +++ b/Sources/WalletConnectNetworking/NetworkingInteractor.swift @@ -27,9 +27,9 @@ public class NetworkingInteractor: NetworkInteracting { public init( relayClient: RelayClient, - serializer: Serializing, - logger: ConsoleLogging, - rpcHistory: RPCHistory + serializer: Serializing, + logger: ConsoleLogging, + rpcHistory: RPCHistory ) { self.relayClient = relayClient self.serializer = serializer @@ -89,11 +89,15 @@ public class NetworkingInteractor: NetworkInteracting { try await relayClient.publish(topic: topic, payload: message, tag: tag) } + public func respondSuccess(topic: String, requestId: RPCID, tag: Int, envelopeType: Envelope.EnvelopeType) async throws { + let response = RPCResponse(id: requestId, result: true) + try await respond(topic: topic, response: response, tag: tag, envelopeType: envelopeType) + } + public func respondError(topic: String, requestId: RPCID, tag: Int, reason: Reason, envelopeType: Envelope.EnvelopeType) async throws { let error = JSONRPCError(code: reason.code, message: reason.message) let response = RPCResponse(id: requestId, error: error) - let message = try! serializer.serialize(topic: topic, encodable: response, envelopeType: envelopeType) - try await relayClient.publish(topic: topic, payload: message, tag: tag) + try await respond(topic: topic, response: response, tag: tag, envelopeType: envelopeType) } private func manageSubscription(_ topic: String, _ encodedEnvelope: String) { diff --git a/Tests/AuthTests/Mocks/NetworkingInteractorMock.swift b/Tests/AuthTests/Mocks/NetworkingInteractorMock.swift deleted file mode 100644 index 5c9664d03..000000000 --- a/Tests/AuthTests/Mocks/NetworkingInteractorMock.swift +++ /dev/null @@ -1,44 +0,0 @@ -import Foundation -import Combine -@testable import Auth -import JSONRPC -import WalletConnectKMS -import WalletConnectNetworking - -struct NetworkingInteractorMock: NetworkInteracting { - - var responsePublisher: AnyPublisher { - responsePublisherSubject.eraseToAnyPublisher() - } - let responsePublisherSubject = PassthroughSubject() - - let requestPublisherSubject = PassthroughSubject() - var requestPublisher: AnyPublisher { - requestPublisherSubject.eraseToAnyPublisher() - } - - func subscribe(topic: String) async throws { - - } - - func unsubscribe(topic: String) { - - } - - func request(_ request: RPCRequest, topic: String, tag: Int, envelopeType: Envelope.EnvelopeType) async throws { - - } - - func respond(topic: String, response: RPCResponse, tag: Int, envelopeType: Envelope.EnvelopeType) async throws { - - } - - func respondError(topic: String, requestId: RPCID, tag: Int, reason: Reason, envelopeType: Envelope.EnvelopeType) async throws { - - } - - func requestNetworkAck(_ request: RPCRequest, topic: String, tag: Int) async throws { - - } - -} diff --git a/Tests/ChatTests/Mocks/NetworkingInteractorMock.swift b/Tests/ChatTests/Mocks/NetworkingInteractorMock.swift deleted file mode 100644 index 030c9d1d9..000000000 --- a/Tests/ChatTests/Mocks/NetworkingInteractorMock.swift +++ /dev/null @@ -1,50 +0,0 @@ -import Foundation -@testable import Chat -import Combine -import WalletConnectUtils -import WalletConnectRelay - -class NetworkingInteractorMock: NetworkInteracting { - - var socketConnectionStatusPublisher: AnyPublisher { - socketConnectionStatusPublisherSubject.eraseToAnyPublisher() - } - let socketConnectionStatusPublisherSubject = PassthroughSubject() - - let responsePublisherSubject = PassthroughSubject() - let requestPublisherSubject = PassthroughSubject() - - var requestPublisher: AnyPublisher { - requestPublisherSubject.eraseToAnyPublisher() - } - - var responsePublisher: AnyPublisher { - responsePublisherSubject.eraseToAnyPublisher() - } - - func requestUnencrypted(_ request: JSONRPCRequest, topic: String) async throws { - - } - - func request(_ request: JSONRPCRequest, topic: String) async throws { - - } - - func respond(topic: String, response: JsonRpcResult, tag: Int) async throws { - - } - - func respondSuccess(payload: RequestSubscriptionPayload) async throws { - - } - - private(set) var subscriptions: [String] = [] - - func subscribe(topic: String) async throws { - subscriptions.append(topic) - } - - func didSubscribe(to topic: String) -> Bool { - subscriptions.contains { $0 == topic } - } -} diff --git a/Tests/ChatTests/RegistryManagerTests.swift b/Tests/ChatTests/RegistryManagerTests.swift index b0ea58338..c9ff87848 100644 --- a/Tests/ChatTests/RegistryManagerTests.swift +++ b/Tests/ChatTests/RegistryManagerTests.swift @@ -2,7 +2,8 @@ import Foundation import XCTest @testable import Chat import WalletConnectUtils -@testable import WalletConnectKMS +import WalletConnectNetworking +import WalletConnectKMS @testable import TestingUtils final class RegistryManagerTests: XCTestCase { @@ -27,7 +28,7 @@ final class RegistryManagerTests: XCTestCase { func testRegister() async { let account = Account("eip155:1:0xab16a96d359ec26a11e2c2b3d8f8b8942d5bfcdb")! - try! await registryManager.register(account: account) + _ = try! await registryManager.register(account: account) XCTAssert(!networkingInteractor.subscriptions.isEmpty, "networkingInteractors subscribes to new topic") let resolved = try! await registry.resolve(account: account) XCTAssertNotNil(resolved, "register account is resolvable") diff --git a/Tests/TestingUtils/NetworkingInteractorMock.swift b/Tests/TestingUtils/NetworkingInteractorMock.swift new file mode 100644 index 000000000..70abbc425 --- /dev/null +++ b/Tests/TestingUtils/NetworkingInteractorMock.swift @@ -0,0 +1,58 @@ +import Foundation +import Combine +import JSONRPC +import WalletConnectRelay +import WalletConnectKMS +import WalletConnectNetworking + +public class NetworkingInteractorMock: NetworkInteracting { + + private(set) var subscriptions: [String] = [] + + public let socketConnectionStatusPublisherSubject = PassthroughSubject() + public var socketConnectionStatusPublisher: AnyPublisher { + socketConnectionStatusPublisherSubject.eraseToAnyPublisher() + } + + public var responsePublisher: AnyPublisher { + responsePublisherSubject.eraseToAnyPublisher() + } + public let responsePublisherSubject = PassthroughSubject() + + public let requestPublisherSubject = PassthroughSubject() + public var requestPublisher: AnyPublisher { + requestPublisherSubject.eraseToAnyPublisher() + } + + public func subscribe(topic: String) async throws { + subscriptions.append(topic) + } + + func didSubscribe(to topic: String) -> Bool { + subscriptions.contains { $0 == topic } + } + + public func unsubscribe(topic: String) { + + } + + public func request(_ request: RPCRequest, topic: String, tag: Int, envelopeType: Envelope.EnvelopeType) async throws { + + } + + public func respond(topic: String, response: RPCResponse, tag: Int, envelopeType: Envelope.EnvelopeType) async throws { + + } + + public func respondSuccess(topic: String, requestId: RPCID, tag: Int, envelopeType: Envelope.EnvelopeType) async throws { + + } + + public func respondError(topic: String, requestId: RPCID, tag: Int, reason: Reason, envelopeType: Envelope.EnvelopeType) async throws { + + } + + public func requestNetworkAck(_ request: RPCRequest, topic: String, tag: Int) async throws { + + } +} From a9f921b5259188f9c6f84f71c47659d0bbc69a16 Mon Sep 17 00:00:00 2001 From: Artur Guseinov Date: Thu, 1 Sep 2022 22:26:55 +0300 Subject: [PATCH 4/4] Showcase build errors --- .../PresentationLayer/Wallet/Wallet/WalletInteractor.swift | 4 ++-- .../PresentationLayer/Wallet/Wallet/WalletPresenter.swift | 7 ++++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/Example/Showcase/Classes/PresentationLayer/Wallet/Wallet/WalletInteractor.swift b/Example/Showcase/Classes/PresentationLayer/Wallet/Wallet/WalletInteractor.swift index bd06b4567..051ba266e 100644 --- a/Example/Showcase/Classes/PresentationLayer/Wallet/Wallet/WalletInteractor.swift +++ b/Example/Showcase/Classes/PresentationLayer/Wallet/Wallet/WalletInteractor.swift @@ -3,8 +3,8 @@ import Auth final class WalletInteractor { - func pair(uri: String) async throws { - try await Auth.instance.pair(uri: WalletConnectURI(string: uri)!) + func pair(uri: WalletConnectURI) async throws { + try await Auth.instance.pair(uri: uri) } var requestPublisher: AnyPublisher { diff --git a/Example/Showcase/Classes/PresentationLayer/Wallet/Wallet/WalletPresenter.swift b/Example/Showcase/Classes/PresentationLayer/Wallet/Wallet/WalletPresenter.swift index 2f631ad65..47a773591 100644 --- a/Example/Showcase/Classes/PresentationLayer/Wallet/Wallet/WalletPresenter.swift +++ b/Example/Showcase/Classes/PresentationLayer/Wallet/Wallet/WalletPresenter.swift @@ -15,13 +15,14 @@ final class WalletPresenter: ObservableObject { } func didPastePairingURI() { - guard let uri = UIPasteboard.general.string else { return } + guard let string = UIPasteboard.general.string, let uri = WalletConnectURI(string: string) else { return } pair(uri: uri) } func didScanPairingURI() { router.presentScan { [unowned self] value in - self.pair(uri: value) + guard let uri = WalletConnectURI(string: value) else { return } + self.pair(uri: uri) self.router.dismiss() } onError: { error in print(error.localizedDescription) @@ -53,7 +54,7 @@ private extension WalletPresenter { }.store(in: &disposeBag) } - func pair(uri: String) { + func pair(uri: WalletConnectURI) { Task(priority: .high) { [unowned self] in try await self.interactor.pair(uri: uri) }