From 46aac86d4f0762b173a7e16db83e1019fc270393 Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Tue, 7 Jun 2022 11:55:50 +0200 Subject: [PATCH 1/7] Add registry manager --- Sources/Chat/Chat.swift | 20 ++++----- Sources/Chat/Engine.swift | 21 +++------ Sources/Chat/NetworkingInteractor.swift | 14 +++--- Sources/Chat/Registry.swift | 11 +++-- Sources/Chat/RegistryManager.swift | 34 ++++++++++++++ ...ndToEndTests.swift => EndToEndTests.swift} | 6 +-- .../Mocks/NetworkingInteractorMock.swift | 15 +++++++ Tests/ChatTests/RegistryManagerTests.swift | 45 +++++++++++++++++++ .../ApproveEngineTests.swift | 4 +- .../ControllerSessionStateMachineTests.swift | 4 +- .../Mocks/MockedRelay.swift | 2 +- ...onControllerSessionStateMachineTests.swift | 4 +- .../PairEngineTests.swift | 4 +- .../PairingEngineTests.swift | 4 +- 14 files changed, 136 insertions(+), 52 deletions(-) create mode 100644 Sources/Chat/RegistryManager.swift rename Tests/ChatTests/{endToEndTests.swift => EndToEndTests.swift} (94%) create mode 100644 Tests/ChatTests/Mocks/NetworkingInteractorMock.swift create mode 100644 Tests/ChatTests/RegistryManagerTests.swift diff --git a/Sources/Chat/Chat.swift b/Sources/Chat/Chat.swift index 2bf928666..9c4fe4377 100644 --- a/Sources/Chat/Chat.swift +++ b/Sources/Chat/Chat.swift @@ -8,10 +8,10 @@ import Combine class Chat { private var publishers = [AnyCancellable]() - let registry: Registry + let registryManager: RegistryManager let engine: Engine let kms: KeyManagementService - var onConnected: (()->())? + let socketConnectionStatusPublisher: AnyPublisher var newThreadPublisherSubject = PassthroughSubject() @@ -29,13 +29,13 @@ class Chat { kms: KeyManagementService, logger: ConsoleLogging = ConsoleLogger(loggingLevel: .off), keyValueStorage: KeyValueStorage) { - self.registry = registry + let topicToInvitationPubKeyStore = CodableStore(defaults: keyValueStorage, identifier: StorageDomainIdentifiers.topicToInvitationPubKey.rawValue) self.kms = kms let serialiser = Serializer(kms: kms) let networkingInteractor = NetworkingInteractor(relayClient: relayClient, serializer: serialiser) - let topicToInvitationPubKeyStore = CodableStore(defaults: keyValueStorage, identifier: StorageDomainIdentifiers.topicToInvitationPubKey.rawValue) let inviteStore = CodableStore(defaults: keyValueStorage, identifier: StorageDomainIdentifiers.invite.rawValue) + self.registryManager = RegistryManager(registry: registry, networkingInteractor: networkingInteractor, kms: kms, logger: logger, topicToInvitationPubKeyStore: topicToInvitationPubKeyStore) self.engine = Engine(registry: registry, networkingInteractor: networkingInteractor, kms: kms, @@ -47,16 +47,16 @@ class Chat { setUpEnginesCallbacks() } - func register(account: Account) { - engine.register(account: account) + func register(account: Account) async throws { + try await registryManager.register(account: account) } - func invite(account: Account) throws { - try engine.invite(account: account) + func invite(account: Account) async throws { + try await engine.invite(account: account) } - func accept(inviteId: String) throws { - try engine.accept(inviteId: inviteId) + func accept(inviteId: String) async throws { + try await engine.accept(inviteId: inviteId) } func message(threadTopic: String, message: String) { diff --git a/Sources/Chat/Engine.swift b/Sources/Chat/Engine.swift index a2b4a9fda..7d28c9759 100644 --- a/Sources/Chat/Engine.swift +++ b/Sources/Chat/Engine.swift @@ -35,8 +35,8 @@ class Engine { setUpResponseHandling() } - func invite(account: Account) throws { - let peerPubKeyHex = registry.resolve(account: account)! + func invite(account: Account) async throws { + let peerPubKeyHex = try await registry.resolve(account: account)! print("resolved pub key: \(peerPubKeyHex)") let pubKey = try kms.createX25519KeyPair() let invite = Invite(pubKey: pubKey.hexRepresentation, message: "hello") @@ -45,12 +45,12 @@ class Engine { networkingInteractor.requestUnencrypted(request, topic: topic) let agreementKeys = try kms.performKeyAgreement(selfPublicKey: pubKey, peerPublicKey: peerPubKeyHex) let threadTopic = agreementKeys.derivedTopic() - networkingInteractor.subscribe(topic: threadTopic) + try await networkingInteractor.subscribe(topic: threadTopic) logger.debug("invite sent on topic: \(topic)") } - func accept(inviteId: String) throws { + func accept(inviteId: String) async throws { guard let hexPubKey = try topicToInvitationPubKeyStore.get(key: "todo-topic") else { throw ChatError.noPublicKeyForInviteId } @@ -61,20 +61,11 @@ class Engine { logger.debug("accepting an invitation") let agreementKeys = try! kms.performKeyAgreement(selfPublicKey: pubKey, peerPublicKey: invite.pubKey) let topic = agreementKeys.derivedTopic() - networkingInteractor.subscribe(topic: topic) + try await networkingInteractor.subscribe(topic: topic) fatalError("not implemented") } - func register(account: Account) { - let pubKey = try! kms.createX25519KeyPair() - let pubKeyHex = pubKey.hexRepresentation - print("registered pubKey: \(pubKeyHex)") - registry.register(account: account, pubKey: pubKeyHex) - let topic = pubKey.rawRepresentation.sha256().toHexString() - try! topicToInvitationPubKeyStore.set(pubKeyHex, forKey: topic) - networkingInteractor.subscribe(topic: topic) - print("did register and is subscribing on topic: \(topic)") - } + private func handleInvite(_ invite: Invite) { onInvite?(invite) diff --git a/Sources/Chat/NetworkingInteractor.swift b/Sources/Chat/NetworkingInteractor.swift index 27894d172..8cdd1b44c 100644 --- a/Sources/Chat/NetworkingInteractor.swift +++ b/Sources/Chat/NetworkingInteractor.swift @@ -4,7 +4,11 @@ import Combine import WalletConnectRelay import WalletConnectUtils -class NetworkingInteractor { +protocol NetworkInteracting { + func subscribe(topic: String) async throws +} + +class NetworkingInteractor: NetworkInteracting { let relayClient: RelayClient private let serializer: Serializing var requestPublisher: AnyPublisher { @@ -41,12 +45,8 @@ class NetworkingInteractor { } } - func subscribe(topic: String) { - relayClient.subscribe(topic: topic) { [weak self] error in -// if let error = error { -// print(error) -// } - } + func subscribe(topic: String) async throws { + try await relayClient.subscribe(topic: topic) } private func manageSubscription(_ topic: String, _ message: String) { diff --git a/Sources/Chat/Registry.swift b/Sources/Chat/Registry.swift index 57d18b908..ce081d5de 100644 --- a/Sources/Chat/Registry.swift +++ b/Sources/Chat/Registry.swift @@ -3,19 +3,18 @@ import Foundation import WalletConnectUtils protocol Registry { - func register(account: Account, pubKey: String) - func resolve(account: Account) -> String? + func register(account: Account, pubKey: String) async throws + func resolve(account: Account) async throws -> String? } -class KeyValueRegistry: Registry { +actor KeyValueRegistry: Registry { var registryStore: [Account: String] = [:] - func register(account address: Account, pubKey: String) { + func register(account address: Account, pubKey: String) async throws { registryStore[address] = pubKey } - - func resolve(account: Account) -> String? { + func resolve(account: Account) async throws -> String? { return registryStore[account] } } diff --git a/Sources/Chat/RegistryManager.swift b/Sources/Chat/RegistryManager.swift new file mode 100644 index 000000000..a3d323de9 --- /dev/null +++ b/Sources/Chat/RegistryManager.swift @@ -0,0 +1,34 @@ + +import Foundation +import WalletConnectUtils +import WalletConnectKMS + +actor RegistryManager { + let networkingInteractor: NetworkInteracting + let topicToInvitationPubKeyStore: CodableStore + let registry: Registry + let logger: ConsoleLogging + let kms: KeyManagementServiceProtocol + + init(registry: Registry, + networkingInteractor: NetworkInteracting, + kms: KeyManagementServiceProtocol, + logger: ConsoleLogging, + topicToInvitationPubKeyStore: CodableStore) { + self.registry = registry + self.kms = kms + self.networkingInteractor = networkingInteractor + self.logger = logger + self.topicToInvitationPubKeyStore = topicToInvitationPubKeyStore + } + + func register(account: Account) async throws { + let pubKey = try kms.createX25519KeyPair() + let pubKeyHex = pubKey.hexRepresentation + try await registry.register(account: account, pubKey: pubKeyHex) + let topic = pubKey.rawRepresentation.sha256().toHexString() + topicToInvitationPubKeyStore.set(pubKeyHex, forKey: topic) + try await networkingInteractor.subscribe(topic: topic) + logger.debug("Did register an account: \(account) and is subscribing on topic: \(topic)") + } +} diff --git a/Tests/ChatTests/endToEndTests.swift b/Tests/ChatTests/EndToEndTests.swift similarity index 94% rename from Tests/ChatTests/endToEndTests.swift rename to Tests/ChatTests/EndToEndTests.swift index 9aa030bf1..c427b56aa 100644 --- a/Tests/ChatTests/endToEndTests.swift +++ b/Tests/ChatTests/EndToEndTests.swift @@ -53,9 +53,9 @@ final class ChatTests: XCTestCase { await waitClientsConnected() let inviteExpectation = expectation(description: "invitation expectation") let account = Account(chainIdentifier: "eip155:1", address: "0x3627523167367216556273151")! - client1.register(account: account) - try! client2.invite(account: account) - client1.invitePublisher.sink { invite in + try! await client1.register(account: account) + try! await client2.invite(account: account) + client1.invitePublisher.sink { _ in inviteExpectation.fulfill() }.store(in: &publishers) wait(for: [inviteExpectation], timeout: 4) diff --git a/Tests/ChatTests/Mocks/NetworkingInteractorMock.swift b/Tests/ChatTests/Mocks/NetworkingInteractorMock.swift new file mode 100644 index 000000000..30f6e4a50 --- /dev/null +++ b/Tests/ChatTests/Mocks/NetworkingInteractorMock.swift @@ -0,0 +1,15 @@ + +import Foundation +@testable import Chat + +class NetworkingInteractorMock: NetworkInteracting { + 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 new file mode 100644 index 000000000..e75d4ceda --- /dev/null +++ b/Tests/ChatTests/RegistryManagerTests.swift @@ -0,0 +1,45 @@ +import Foundation +import XCTest +@testable import Chat +import WalletConnectUtils +@testable import WalletConnectKMS +@testable import TestingUtils + +final class RegistryManagerTests: XCTestCase { + var registryManager: RegistryManager! + var networkingInteractor: NetworkingInteractorMock! + var topicToInvitationPubKeyStore: CodableStore! + var registry: Registry! + var kms: KeyManagementServiceMock! + + override func setUp() { + registry = KeyValueRegistry() + networkingInteractor = NetworkingInteractorMock() + kms = KeyManagementServiceMock() + topicToInvitationPubKeyStore = CodableStore(defaults: RuntimeKeyValueStorage(), identifier: "") + registryManager = RegistryManager( + registry: registry, + networkingInteractor: networkingInteractor, + kms: kms, + logger: ConsoleLoggerMock(), + topicToInvitationPubKeyStore: topicToInvitationPubKeyStore) + } + + override func tearDown() { + registry = nil + networkingInteractor = nil + kms = nil + topicToInvitationPubKeyStore = nil + registryManager = nil + } + + func testRegister() async { + let account = Account("eip155:1:0xab16a96d359ec26a11e2c2b3d8f8b8942d5bfcdb")! + 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") + XCTAssertFalse(topicToInvitationPubKeyStore.getAll().isEmpty, "stores topic to invitation") + } +} + diff --git a/Tests/WalletConnectSignTests/ApproveEngineTests.swift b/Tests/WalletConnectSignTests/ApproveEngineTests.swift index a0222fb29..d237c49b9 100644 --- a/Tests/WalletConnectSignTests/ApproveEngineTests.swift +++ b/Tests/WalletConnectSignTests/ApproveEngineTests.swift @@ -9,7 +9,7 @@ final class ApproveEngineTests: XCTestCase { var engine: ApproveEngine! var metadata: AppMetadata! - var networkingInteractor: MockedWCRelay! + var networkingInteractor: NetworkingInteractorMock! var cryptoMock: KeyManagementServiceMock! var pairingStorageMock: WCPairingStorageMock! var sessionStorageMock: WCSessionStorageMock! @@ -19,7 +19,7 @@ final class ApproveEngineTests: XCTestCase { override func setUp() { metadata = AppMetadata.stub() - networkingInteractor = MockedWCRelay() + networkingInteractor = NetworkingInteractorMock() cryptoMock = KeyManagementServiceMock() pairingStorageMock = WCPairingStorageMock() sessionStorageMock = WCSessionStorageMock() diff --git a/Tests/WalletConnectSignTests/ControllerSessionStateMachineTests.swift b/Tests/WalletConnectSignTests/ControllerSessionStateMachineTests.swift index 04345ff41..766990cfe 100644 --- a/Tests/WalletConnectSignTests/ControllerSessionStateMachineTests.swift +++ b/Tests/WalletConnectSignTests/ControllerSessionStateMachineTests.swift @@ -7,12 +7,12 @@ import WalletConnectKMS class ControllerSessionStateMachineTests: XCTestCase { var sut: ControllerSessionStateMachine! - var networkingInteractor: MockedWCRelay! + var networkingInteractor: NetworkingInteractorMock! var storageMock: WCSessionStorageMock! var cryptoMock: KeyManagementServiceMock! override func setUp() { - networkingInteractor = MockedWCRelay() + networkingInteractor = NetworkingInteractorMock() storageMock = WCSessionStorageMock() cryptoMock = KeyManagementServiceMock() sut = ControllerSessionStateMachine(networkingInteractor: networkingInteractor, kms: cryptoMock, sessionStore: storageMock, logger: ConsoleLoggerMock()) diff --git a/Tests/WalletConnectSignTests/Mocks/MockedRelay.swift b/Tests/WalletConnectSignTests/Mocks/MockedRelay.swift index 40ca53503..6f5bb3bb9 100644 --- a/Tests/WalletConnectSignTests/Mocks/MockedRelay.swift +++ b/Tests/WalletConnectSignTests/Mocks/MockedRelay.swift @@ -5,7 +5,7 @@ import WalletConnectUtils @testable import WalletConnectSign @testable import TestingUtils -class MockedWCRelay: NetworkInteracting { +class NetworkingInteractorMock: NetworkInteracting { private(set) var subscriptions: [String] = [] private(set) var unsubscriptions: [String] = [] diff --git a/Tests/WalletConnectSignTests/NonControllerSessionStateMachineTests.swift b/Tests/WalletConnectSignTests/NonControllerSessionStateMachineTests.swift index 1f3dfa111..4ab099605 100644 --- a/Tests/WalletConnectSignTests/NonControllerSessionStateMachineTests.swift +++ b/Tests/WalletConnectSignTests/NonControllerSessionStateMachineTests.swift @@ -7,12 +7,12 @@ import WalletConnectKMS class NonControllerSessionStateMachineTests: XCTestCase { var sut: NonControllerSessionStateMachine! - var networkingInteractor: MockedWCRelay! + var networkingInteractor: NetworkingInteractorMock! var storageMock: WCSessionStorageMock! var cryptoMock: KeyManagementServiceMock! override func setUp() { - networkingInteractor = MockedWCRelay() + networkingInteractor = NetworkingInteractorMock() storageMock = WCSessionStorageMock() cryptoMock = KeyManagementServiceMock() sut = NonControllerSessionStateMachine(networkingInteractor: networkingInteractor, kms: cryptoMock, sessionStore: storageMock, logger: ConsoleLoggerMock()) diff --git a/Tests/WalletConnectSignTests/PairEngineTests.swift b/Tests/WalletConnectSignTests/PairEngineTests.swift index f6c85e4b8..b81337ecb 100644 --- a/Tests/WalletConnectSignTests/PairEngineTests.swift +++ b/Tests/WalletConnectSignTests/PairEngineTests.swift @@ -9,7 +9,7 @@ final class PairEngineTests: XCTestCase { var engine: PairEngine! - var networkingInteractor: MockedWCRelay! + var networkingInteractor: NetworkingInteractorMock! var storageMock: WCPairingStorageMock! var cryptoMock: KeyManagementServiceMock! var proposalPayloadsStore: CodableStore! @@ -17,7 +17,7 @@ final class PairEngineTests: XCTestCase { var topicGenerator: TopicGenerator! override func setUp() { - networkingInteractor = MockedWCRelay() + networkingInteractor = NetworkingInteractorMock() storageMock = WCPairingStorageMock() cryptoMock = KeyManagementServiceMock() topicGenerator = TopicGenerator() diff --git a/Tests/WalletConnectSignTests/PairingEngineTests.swift b/Tests/WalletConnectSignTests/PairingEngineTests.swift index bc08fcfdd..ce764b6da 100644 --- a/Tests/WalletConnectSignTests/PairingEngineTests.swift +++ b/Tests/WalletConnectSignTests/PairingEngineTests.swift @@ -15,7 +15,7 @@ final class PairingEngineTests: XCTestCase { var engine: PairingEngine! var approveEngine: ApproveEngine! - var networkingInteractor: MockedWCRelay! + var networkingInteractor: NetworkingInteractorMock! var storageMock: WCPairingStorageMock! var cryptoMock: KeyManagementServiceMock! @@ -23,7 +23,7 @@ final class PairingEngineTests: XCTestCase { var publishers = Set() override func setUp() { - networkingInteractor = MockedWCRelay() + networkingInteractor = NetworkingInteractorMock() storageMock = WCPairingStorageMock() cryptoMock = KeyManagementServiceMock() topicGenerator = TopicGenerator() From ff4834114f48133f8752f0fa2473a9faf021faed Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Tue, 7 Jun 2022 12:28:18 +0200 Subject: [PATCH 2/7] Update api methods --- Sources/Chat/Chat.swift | 16 +++++++++++++--- Sources/Chat/Engine.swift | 2 -- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/Sources/Chat/Chat.swift b/Sources/Chat/Chat.swift index 9c4fe4377..0c49952cf 100644 --- a/Sources/Chat/Chat.swift +++ b/Sources/Chat/Chat.swift @@ -51,15 +51,25 @@ class Chat { try await registryManager.register(account: account) } - func invite(account: Account) async throws { - try await engine.invite(account: account) + func resolve(account: Account) async throws { + + } + + func invite(publicKey: String, oppeningMessage: String) async throws { +// try await engine.invite(account: account) } func accept(inviteId: String) async throws { try await engine.accept(inviteId: inviteId) } - func message(threadTopic: String, message: String) { + func message(topic: String, message: String) { + + } + + /// To Ping peer client + /// - Parameter topic: chat thread topic + func ping(topic: String) { } diff --git a/Sources/Chat/Engine.swift b/Sources/Chat/Engine.swift index 7d28c9759..a4f5ffcfa 100644 --- a/Sources/Chat/Engine.swift +++ b/Sources/Chat/Engine.swift @@ -65,8 +65,6 @@ class Engine { fatalError("not implemented") } - - private func handleInvite(_ invite: Invite) { onInvite?(invite) logger.debug("did receive an invite") From bf6170320b6014da08d6ed5a9ebd71f1c435a7bf Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Tue, 7 Jun 2022 12:38:37 +0200 Subject: [PATCH 3/7] update resolve --- Sources/Chat/Chat.swift | 10 +++++++--- Sources/Chat/Registry.swift | 10 ++++++---- Sources/Chat/Types/ChatError.swift | 1 + 3 files changed, 14 insertions(+), 7 deletions(-) diff --git a/Sources/Chat/Chat.swift b/Sources/Chat/Chat.swift index 0c49952cf..f986d3726 100644 --- a/Sources/Chat/Chat.swift +++ b/Sources/Chat/Chat.swift @@ -8,6 +8,7 @@ import Combine class Chat { private var publishers = [AnyCancellable]() + let registry: Registry let registryManager: RegistryManager let engine: Engine let kms: KeyManagementService @@ -30,7 +31,7 @@ class Chat { logger: ConsoleLogging = ConsoleLogger(loggingLevel: .off), keyValueStorage: KeyValueStorage) { let topicToInvitationPubKeyStore = CodableStore(defaults: keyValueStorage, identifier: StorageDomainIdentifiers.topicToInvitationPubKey.rawValue) - + self.registry = registry self.kms = kms let serialiser = Serializer(kms: kms) let networkingInteractor = NetworkingInteractor(relayClient: relayClient, serializer: serialiser) @@ -51,8 +52,11 @@ class Chat { try await registryManager.register(account: account) } - func resolve(account: Account) async throws { - + /// Queries the default keyserver with a blockchain account + /// - Parameter account: CAIP10 blockachain account + /// - Returns: public key associated with an account in chat's keyserver + func resolve(account: Account) async throws -> String { + try await registry.resolve(account: account) } func invite(publicKey: String, oppeningMessage: String) async throws { diff --git a/Sources/Chat/Registry.swift b/Sources/Chat/Registry.swift index ce081d5de..fb20517e6 100644 --- a/Sources/Chat/Registry.swift +++ b/Sources/Chat/Registry.swift @@ -3,8 +3,8 @@ import Foundation import WalletConnectUtils protocol Registry { - func register(account: Account, pubKey: String) async throws - func resolve(account: Account) async throws -> String? + func register(account: Account, pubKey: String) async throws + func resolve(account: Account) async throws -> String } actor KeyValueRegistry: Registry { @@ -14,7 +14,9 @@ actor KeyValueRegistry: Registry { func register(account address: Account, pubKey: String) async throws { registryStore[address] = pubKey } - func resolve(account: Account) async throws -> String? { - return registryStore[account] + func resolve(account: Account) async throws -> String { + guard let record = registryStore[account] else { throw ChatError.recordNotFound} + return record } } + diff --git a/Sources/Chat/Types/ChatError.swift b/Sources/Chat/Types/ChatError.swift index 3238d4c62..6c3dafbe9 100644 --- a/Sources/Chat/Types/ChatError.swift +++ b/Sources/Chat/Types/ChatError.swift @@ -4,4 +4,5 @@ import Foundation enum ChatError: Error { case noPublicKeyForInviteId case noInviteForId + case recordNotFound } From 57c872dca6ee0ce48a0b2bffb7ecffdc7e0948bc Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Tue, 7 Jun 2022 12:46:37 +0200 Subject: [PATCH 4/7] Add description to api methods --- Sources/Chat/Chat.swift | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/Sources/Chat/Chat.swift b/Sources/Chat/Chat.swift index f986d3726..ad43f3420 100644 --- a/Sources/Chat/Chat.swift +++ b/Sources/Chat/Chat.swift @@ -48,6 +48,9 @@ class Chat { setUpEnginesCallbacks() } + /// Registers a new record on Chat keyserver, + /// record is a blockchain account with a client generated public key + /// - Parameter account: CAIP10 blockchain account func register(account: Account) async throws { try await registryManager.register(account: account) } @@ -59,6 +62,10 @@ class Chat { try await registry.resolve(account: account) } + /// Sends a chat invite with opening message + /// - Parameters: + /// - publicKey: publicKey associated with a peer + /// - oppeningMessage: oppening message for a chat invite func invite(publicKey: String, oppeningMessage: String) async throws { // try await engine.invite(account: account) } @@ -67,6 +74,10 @@ class Chat { try await engine.accept(inviteId: inviteId) } + /// Sends a chat message to an active chat thread + /// - Parameters: + /// - topic: thread topic + /// - message: chat message func message(topic: String, message: String) { } From f30f1f7fdf53e1650fefe38bd8e7e2ed3934538d Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Tue, 7 Jun 2022 12:55:35 +0200 Subject: [PATCH 5/7] update invite method --- Sources/Chat/Chat.swift | 9 +++++---- Sources/Chat/Engine.swift | 12 +++++------- Sources/Chat/RegistryManager.swift | 3 ++- Sources/Chat/Types/ChatRequest.swift | 9 +++++++-- Sources/Chat/Types/Invite.swift | 2 +- Tests/ChatTests/EndToEndTests.swift | 4 ++-- 6 files changed, 22 insertions(+), 17 deletions(-) diff --git a/Sources/Chat/Chat.swift b/Sources/Chat/Chat.swift index ad43f3420..01b5b42e7 100644 --- a/Sources/Chat/Chat.swift +++ b/Sources/Chat/Chat.swift @@ -51,7 +51,8 @@ class Chat { /// Registers a new record on Chat keyserver, /// record is a blockchain account with a client generated public key /// - Parameter account: CAIP10 blockchain account - func register(account: Account) async throws { + /// - Returns: public key + func register(account: Account) async throws -> String { try await registryManager.register(account: account) } @@ -65,9 +66,9 @@ class Chat { /// Sends a chat invite with opening message /// - Parameters: /// - publicKey: publicKey associated with a peer - /// - oppeningMessage: oppening message for a chat invite - func invite(publicKey: String, oppeningMessage: String) async throws { -// try await engine.invite(account: account) + /// - openingMessage: oppening message for a chat invite + func invite(publicKey: String, openingMessage: String) async throws { + try await engine.invite(peerPubKey: publicKey, openingMessage: openingMessage) } func accept(inviteId: String) async throws { diff --git a/Sources/Chat/Engine.swift b/Sources/Chat/Engine.swift index a4f5ffcfa..eaff34169 100644 --- a/Sources/Chat/Engine.swift +++ b/Sources/Chat/Engine.swift @@ -35,15 +35,13 @@ class Engine { setUpResponseHandling() } - func invite(account: Account) async throws { - let peerPubKeyHex = try await registry.resolve(account: account)! - print("resolved pub key: \(peerPubKeyHex)") + func invite(peerPubKey: String, openingMessage: String) async throws { let pubKey = try kms.createX25519KeyPair() - let invite = Invite(pubKey: pubKey.hexRepresentation, message: "hello") - let topic = try AgreementPublicKey(hex: peerPubKeyHex).rawRepresentation.sha256().toHexString() - let request = ChatRequest(method: .invite, params: .invite(invite)) + let invite = Invite(pubKey: pubKey.hexRepresentation, openingMessage: openingMessage) + let topic = try AgreementPublicKey(hex: peerPubKey).rawRepresentation.sha256().toHexString() + let request = ChatRequest(params: .invite(invite)) networkingInteractor.requestUnencrypted(request, topic: topic) - let agreementKeys = try kms.performKeyAgreement(selfPublicKey: pubKey, peerPublicKey: peerPubKeyHex) + let agreementKeys = try kms.performKeyAgreement(selfPublicKey: pubKey, peerPublicKey: peerPubKey) let threadTopic = agreementKeys.derivedTopic() try await networkingInteractor.subscribe(topic: threadTopic) logger.debug("invite sent on topic: \(topic)") diff --git a/Sources/Chat/RegistryManager.swift b/Sources/Chat/RegistryManager.swift index a3d323de9..ff0d84116 100644 --- a/Sources/Chat/RegistryManager.swift +++ b/Sources/Chat/RegistryManager.swift @@ -22,7 +22,7 @@ actor RegistryManager { self.topicToInvitationPubKeyStore = topicToInvitationPubKeyStore } - func register(account: Account) async throws { + func register(account: Account) async throws -> String { let pubKey = try kms.createX25519KeyPair() let pubKeyHex = pubKey.hexRepresentation try await registry.register(account: account, pubKey: pubKeyHex) @@ -30,5 +30,6 @@ actor RegistryManager { topicToInvitationPubKeyStore.set(pubKeyHex, forKey: topic) try await networkingInteractor.subscribe(topic: topic) logger.debug("Did register an account: \(account) and is subscribing on topic: \(topic)") + return pubKeyHex } } diff --git a/Sources/Chat/Types/ChatRequest.swift b/Sources/Chat/Types/ChatRequest.swift index b8f90cd6b..cbbf372a4 100644 --- a/Sources/Chat/Types/ChatRequest.swift +++ b/Sources/Chat/Types/ChatRequest.swift @@ -15,11 +15,16 @@ struct ChatRequest: Codable { case params } - internal init(id: Int64 = generateId(), jsonrpc: String = "2.0", method: Method, params: Params) { + internal init(id: Int64 = generateId(), jsonrpc: String = "2.0", params: Params) { self.id = id self.jsonrpc = jsonrpc - self.method = method self.params = params + switch params { + case .invite(_): + self.method = Method.invite + case .message(_): + self.method = Method.message + } } diff --git a/Sources/Chat/Types/Invite.swift b/Sources/Chat/Types/Invite.swift index a5c50c475..e772538b8 100644 --- a/Sources/Chat/Types/Invite.swift +++ b/Sources/Chat/Types/Invite.swift @@ -4,7 +4,7 @@ import Foundation struct Invite: Codable { let pubKey: String - let message: String + let openingMessage: String var id: String { return pubKey diff --git a/Tests/ChatTests/EndToEndTests.swift b/Tests/ChatTests/EndToEndTests.swift index c427b56aa..e95c447c2 100644 --- a/Tests/ChatTests/EndToEndTests.swift +++ b/Tests/ChatTests/EndToEndTests.swift @@ -53,8 +53,8 @@ final class ChatTests: XCTestCase { await waitClientsConnected() let inviteExpectation = expectation(description: "invitation expectation") let account = Account(chainIdentifier: "eip155:1", address: "0x3627523167367216556273151")! - try! await client1.register(account: account) - try! await client2.invite(account: account) + let pubKey = try! await client1.register(account: account) + try! await client2.invite(publicKey: pubKey, openingMessage: "") client1.invitePublisher.sink { _ in inviteExpectation.fulfill() }.store(in: &publishers) From ce2d6d66d1cd94d7a303e99255506139dd9af375 Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Thu, 9 Jun 2022 11:08:31 +0200 Subject: [PATCH 6/7] remove teardown --- Tests/ChatTests/RegistryManagerTests.swift | 8 -------- 1 file changed, 8 deletions(-) diff --git a/Tests/ChatTests/RegistryManagerTests.swift b/Tests/ChatTests/RegistryManagerTests.swift index e75d4ceda..f68398003 100644 --- a/Tests/ChatTests/RegistryManagerTests.swift +++ b/Tests/ChatTests/RegistryManagerTests.swift @@ -25,14 +25,6 @@ final class RegistryManagerTests: XCTestCase { topicToInvitationPubKeyStore: topicToInvitationPubKeyStore) } - override func tearDown() { - registry = nil - networkingInteractor = nil - kms = nil - topicToInvitationPubKeyStore = nil - registryManager = nil - } - func testRegister() async { let account = Account("eip155:1:0xab16a96d359ec26a11e2c2b3d8f8b8942d5bfcdb")! try! await registryManager.register(account: account) From 2e61a6d59c42ac50be31ce3c1516abc1d3790d4c Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Thu, 9 Jun 2022 11:17:11 +0200 Subject: [PATCH 7/7] make registryStore private --- Sources/Chat/Registry.swift | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Sources/Chat/Registry.swift b/Sources/Chat/Registry.swift index fb20517e6..f01eaa7fc 100644 --- a/Sources/Chat/Registry.swift +++ b/Sources/Chat/Registry.swift @@ -9,11 +9,12 @@ protocol Registry { actor KeyValueRegistry: Registry { - var registryStore: [Account: String] = [:] + private var registryStore: [Account: String] = [:] func register(account address: Account, pubKey: String) async throws { registryStore[address] = pubKey } + func resolve(account: Account) async throws -> String { guard let record = registryStore[account] else { throw ChatError.recordNotFound} return record