From 76d5854d4beecc6f7fa5d863e41fcacb4917916d Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Fri, 3 Nov 2023 13:20:36 +0100 Subject: [PATCH 1/3] refactor tests --- Example/ExampleApp.xcodeproj/project.pbxproj | 4 - .../Sign/Helpers/ClientDelegate.swift | 72 ---- .../Sign/SignClientTests.swift | 344 ++++++++++-------- .../WalletConnectSign/Sign/SignClient.swift | 79 ++-- .../Sign/SignClientProtocol.swift | 1 - 5 files changed, 220 insertions(+), 280 deletions(-) delete mode 100644 Example/IntegrationTests/Sign/Helpers/ClientDelegate.swift diff --git a/Example/ExampleApp.xcodeproj/project.pbxproj b/Example/ExampleApp.xcodeproj/project.pbxproj index 5f3a5bfe7..ab00d8cae 100644 --- a/Example/ExampleApp.xcodeproj/project.pbxproj +++ b/Example/ExampleApp.xcodeproj/project.pbxproj @@ -63,7 +63,6 @@ 84E6B84E29787A8000428BAF /* PNDecryptionService.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = 84E6B84729787A8000428BAF /* PNDecryptionService.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; 84FE684628ACDB4700C893FF /* RequestParams.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84FE684528ACDB4700C893FF /* RequestParams.swift */; }; A507BE1A29E8032E0038EF70 /* EIP55Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A507BE1929E8032E0038EF70 /* EIP55Tests.swift */; }; - A50C036528AAD32200FE72D3 /* ClientDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = A50C036428AAD32200FE72D3 /* ClientDelegate.swift */; }; A50D53C12ABA055700A4FD8B /* NotifyPreferencesModule.swift in Sources */ = {isa = PBXBuildFile; fileRef = A50D53BC2ABA055700A4FD8B /* NotifyPreferencesModule.swift */; }; A50D53C22ABA055700A4FD8B /* NotifyPreferencesPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = A50D53BD2ABA055700A4FD8B /* NotifyPreferencesPresenter.swift */; }; A50D53C32ABA055700A4FD8B /* NotifyPreferencesRouter.swift in Sources */ = {isa = PBXBuildFile; fileRef = A50D53BE2ABA055700A4FD8B /* NotifyPreferencesRouter.swift */; }; @@ -441,7 +440,6 @@ 84F568C32795832A00D0A289 /* EthereumTransaction.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EthereumTransaction.swift; sourceTree = ""; }; 84FE684528ACDB4700C893FF /* RequestParams.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RequestParams.swift; sourceTree = ""; }; A507BE1929E8032E0038EF70 /* EIP55Tests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EIP55Tests.swift; sourceTree = ""; }; - A50C036428AAD32200FE72D3 /* ClientDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ClientDelegate.swift; sourceTree = ""; }; A50D53BC2ABA055700A4FD8B /* NotifyPreferencesModule.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotifyPreferencesModule.swift; sourceTree = ""; }; A50D53BD2ABA055700A4FD8B /* NotifyPreferencesPresenter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotifyPreferencesPresenter.swift; sourceTree = ""; }; A50D53BE2ABA055700A4FD8B /* NotifyPreferencesRouter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotifyPreferencesRouter.swift; sourceTree = ""; }; @@ -818,7 +816,6 @@ 767DC83328997F7600080FA9 /* Helpers */ = { isa = PBXGroup; children = ( - A50C036428AAD32200FE72D3 /* ClientDelegate.swift */, 767DC83428997F8E00080FA9 /* EthSendTransaction.swift */, 84AA01DA28CF0CD7005D48D8 /* XCTest.swift */, ); @@ -2386,7 +2383,6 @@ 84FE684628ACDB4700C893FF /* RequestParams.swift in Sources */, 7694A5262874296A0001257E /* RegistryTests.swift in Sources */, A541959F2934BFEF0035AD19 /* SignerTests.swift in Sources */, - A50C036528AAD32200FE72D3 /* ClientDelegate.swift in Sources */, A5321C2B2A250367006CADC3 /* HistoryTests.swift in Sources */, A58A1ECC29BF458600A82A20 /* ENSResolverTests.swift in Sources */, A5E03DFA286465C700888481 /* SignClientTests.swift in Sources */, diff --git a/Example/IntegrationTests/Sign/Helpers/ClientDelegate.swift b/Example/IntegrationTests/Sign/Helpers/ClientDelegate.swift deleted file mode 100644 index e812661e2..000000000 --- a/Example/IntegrationTests/Sign/Helpers/ClientDelegate.swift +++ /dev/null @@ -1,72 +0,0 @@ -import Foundation -@testable import WalletConnectSign -import Combine - -class ClientDelegate { - - var client: SignClient - var onSessionSettled: ((Session) -> Void)? - var onConnected: (() -> Void)? - var onSessionProposal: ((Session.Proposal) -> Void)? - var onSessionRequest: ((Request) -> Void)? - var onSessionResponse: ((Response) -> Void)? - var onSessionRejected: ((Session.Proposal, Reason) -> Void)? - var onSessionDelete: (() -> Void)? - var onSessionUpdateNamespaces: ((String, [String: SessionNamespace]) -> Void)? - var onSessionExtend: ((String, Date) -> Void)? - var onPing: ((String) -> Void)? - var onEventReceived: ((Session.Event, String) -> Void)? - - private var publishers = Set() - - init(client: SignClient) { - self.client = client - setupSubscriptions() - } - - private func setupSubscriptions() { - client.sessionSettlePublisher.sink { session in - self.onSessionSettled?(session) - }.store(in: &publishers) - - client.socketConnectionStatusPublisher.sink { _ in - self.onConnected?() - }.store(in: &publishers) - - client.sessionProposalPublisher.sink { result in - self.onSessionProposal?(result.proposal) - }.store(in: &publishers) - - client.sessionRequestPublisher.sink { result in - self.onSessionRequest?(result.request) - }.store(in: &publishers) - - client.sessionResponsePublisher.sink { response in - self.onSessionResponse?(response) - }.store(in: &publishers) - - client.sessionRejectionPublisher.sink { (proposal, reason) in - self.onSessionRejected?(proposal, reason) - }.store(in: &publishers) - - client.sessionDeletePublisher.sink { _ in - self.onSessionDelete?() - }.store(in: &publishers) - - client.sessionUpdatePublisher.sink { (topic, namespaces) in - self.onSessionUpdateNamespaces?(topic, namespaces) - }.store(in: &publishers) - - client.sessionEventPublisher.sink { (event, topic, _) in - self.onEventReceived?(event, topic) - }.store(in: &publishers) - - client.sessionExtendPublisher.sink { (topic, date) in - self.onSessionExtend?(topic, date) - }.store(in: &publishers) - - client.pingResponsePublisher.sink { topic in - self.onPing?(topic) - }.store(in: &publishers) - } -} diff --git a/Example/IntegrationTests/Sign/SignClientTests.swift b/Example/IntegrationTests/Sign/SignClientTests.swift index f6e0a9dd8..62519ca80 100644 --- a/Example/IntegrationTests/Sign/SignClientTests.swift +++ b/Example/IntegrationTests/Sign/SignClientTests.swift @@ -6,12 +6,17 @@ import JSONRPC @testable import WalletConnectRelay import WalletConnectPairing import WalletConnectNetworking +import Combine final class SignClientTests: XCTestCase { - var dapp: ClientDelegate! - var wallet: ClientDelegate! + var dapp: SignClient! + var dappPairingClient: PairingClient! + var wallet: SignClient! + var walletPairingClient: PairingClient! + private var publishers = Set() - static private func makeClientDelegate(name: String) -> ClientDelegate { + + static private func makeClients(name: String) -> (PairingClient, SignClient) { let logger = ConsoleLogger(prefix: name, loggingLevel: .debug) let keychain = KeychainStorageMock() let keyValueStorage = RuntimeKeyValueStorage() @@ -48,12 +53,12 @@ final class SignClientTests: XCTestCase { let clientId = try! networkingClient.getClientId() logger.debug("My client id is: \(clientId)") - return ClientDelegate(client: client) + return (pairingClient, client) } override func setUp() async throws { - dapp = Self.makeClientDelegate(name: "🍏P") - wallet = Self.makeClientDelegate(name: "🍎R") + (dappPairingClient, dapp) = Self.makeClients(name: "🍏P") + (walletPairingClient, wallet) = Self.makeClients(name: "🍎R") } override func tearDown() { @@ -67,48 +72,55 @@ final class SignClientTests: XCTestCase { let requiredNamespaces = ProposalNamespace.stubRequired() let sessionNamespaces = SessionNamespace.make(toRespond: requiredNamespaces) - wallet.onSessionProposal = { [unowned self] proposal in + wallet.sessionProposalPublisher.sink { [unowned self] (proposal, _) in Task(priority: .high) { do { - try await wallet.client.approve(proposalId: proposal.id, namespaces: sessionNamespaces) + try await wallet.approve(proposalId: proposal.id, namespaces: sessionNamespaces) } catch { XCTFail("\(error)") } } - } - dapp.onSessionSettled = { _ in + }.store(in: &publishers) + dapp.sessionSettlePublisher.sink { _ in dappSettlementExpectation.fulfill() - } - wallet.onSessionSettled = { _ in + }.store(in: &publishers) + dapp.sessionSettlePublisher.sink { _ in walletSettlementExpectation.fulfill() - } + }.store(in: &publishers) - let uri = try await dapp.client.connect(requiredNamespaces: requiredNamespaces) - try await wallet.client.pair(uri: uri!) + let uri = try! await dappPairingClient.create() + try await dapp.connect(requiredNamespaces: requiredNamespaces, topic: uri.topic) + try await walletPairingClient.pair(uri: uri) wait(for: [dappSettlementExpectation, walletSettlementExpectation], timeout: InputConfig.defaultTimeout) } func testSessionReject() async throws { let sessionRejectExpectation = expectation(description: "Proposer is notified on session rejection") + let requiredNamespaces = ProposalNamespace.stubRequired() class Store { var rejectedProposal: Session.Proposal? } let store = Store() - let uri = try await dapp.client.connect(requiredNamespaces: ProposalNamespace.stubRequired()) - try await wallet.client.pair(uri: uri!) + let uri = try! await dappPairingClient.create() + try await dapp.connect(requiredNamespaces: requiredNamespaces, topic: uri.topic) + try await walletPairingClient.pair(uri: uri) - wallet.onSessionProposal = { [unowned self] proposal in + wallet.sessionProposalPublisher.sink { [unowned self] (proposal, _) in Task(priority: .high) { do { +<<<<<<< HEAD try await wallet.client.reject(proposalId: proposal.id, reason: .userRejectedChains) // TODO: Review reason +======= + try await wallet.rejectSession(proposalId: proposal.id, reason: .userRejectedChains) // TODO: Review reason +>>>>>>> 9f705cc6 (refactor sign client tests) store.rejectedProposal = proposal } catch { XCTFail("\(error)") } } - } - dapp.onSessionRejected = { proposal, _ in + }.store(in: &publishers) + dapp.sessionRejectionPublisher.sink { proposal, _ in XCTAssertEqual(store.rejectedProposal, proposal) sessionRejectExpectation.fulfill() // TODO: Assert reason code - } + }.store(in: &publishers) wait(for: [sessionRejectExpectation], timeout: InputConfig.defaultTimeout) } @@ -117,22 +129,23 @@ final class SignClientTests: XCTestCase { let requiredNamespaces = ProposalNamespace.stubRequired() let sessionNamespaces = SessionNamespace.make(toRespond: requiredNamespaces) - wallet.onSessionProposal = { [unowned self] proposal in + wallet.sessionProposalPublisher.sink { [unowned self] (proposal, _) in Task(priority: .high) { - do { try await wallet.client.approve(proposalId: proposal.id, namespaces: sessionNamespaces) } catch { XCTFail("\(error)") } + do { try await wallet.approve(proposalId: proposal.id, namespaces: sessionNamespaces) } catch { XCTFail("\(error)") } } - } - dapp.onSessionSettled = { [unowned self] settledSession in + }.store(in: &publishers) + dapp.sessionSettlePublisher.sink { [unowned self] settledSession in Task(priority: .high) { - try await dapp.client.disconnect(topic: settledSession.topic) + try await dapp.disconnect(topic: settledSession.topic) } - } - wallet.onSessionDelete = { + }.store(in: &publishers) + wallet.sessionDeletePublisher.sink { _ in sessionDeleteExpectation.fulfill() - } + }.store(in: &publishers) - let uri = try await dapp.client.connect(requiredNamespaces: requiredNamespaces) - try await wallet.client.pair(uri: uri!) + let uri = try! await dappPairingClient.create() + try await dapp.connect(requiredNamespaces: requiredNamespaces, topic: uri.topic) + try await walletPairingClient.pair(uri: uri) wait(for: [sessionDeleteExpectation], timeout: InputConfig.defaultTimeout) } @@ -142,26 +155,27 @@ final class SignClientTests: XCTestCase { let requiredNamespaces = ProposalNamespace.stubRequired() let sessionNamespaces = SessionNamespace.make(toRespond: requiredNamespaces) - wallet.onSessionProposal = { proposal in + wallet.sessionProposalPublisher.sink { [unowned self] (proposal, _) in Task(priority: .high) { - try! await self.wallet.client.approve(proposalId: proposal.id, namespaces: sessionNamespaces) + try! await self.wallet.approve(proposalId: proposal.id, namespaces: sessionNamespaces) } - } + }.store(in: &publishers) - dapp.onSessionSettled = { sessionSettled in + dapp.sessionSettlePublisher.sink { [unowned self] settledSession in Task(priority: .high) { - try! await self.dapp.client.ping(topic: sessionSettled.topic) + try! await dapp.ping(topic: settledSession.topic) } - } + }.store(in: &publishers) - dapp.onPing = { topic in - let session = self.wallet.client.getSessions().first! + dapp.pingResponsePublisher.sink { topic in + let session = self.wallet.getSessions().first! XCTAssertEqual(topic, session.topic) expectation.fulfill() - } + }.store(in: &publishers) - let uri = try await dapp.client.connect(requiredNamespaces: requiredNamespaces)! - try await wallet.client.pair(uri: uri) + let uri = try! await dappPairingClient.create() + try await dapp.connect(requiredNamespaces: requiredNamespaces, topic: uri.topic) + try await walletPairingClient.pair(uri: uri) wait(for: [expectation], timeout: InputConfig.defaultTimeout) } @@ -177,30 +191,30 @@ final class SignClientTests: XCTestCase { let responseParams = "0xdeadbeef" let chain = Blockchain("eip155:1")! - wallet.onSessionProposal = { [unowned self] proposal in + wallet.sessionProposalPublisher.sink { [unowned self] (proposal, _) in Task(priority: .high) { do { - try await wallet.client.approve(proposalId: proposal.id, namespaces: sessionNamespaces) } catch { + try await wallet.approve(proposalId: proposal.id, namespaces: sessionNamespaces) } catch { XCTFail("\(error)") } } - } - dapp.onSessionSettled = { [unowned self] settledSession in + }.store(in: &publishers) + dapp.sessionSettlePublisher.sink { [unowned self] settledSession in Task(priority: .high) { let request = Request(id: RPCID(0), topic: settledSession.topic, method: requestMethod, params: requestParams, chainId: chain, expiry: nil) - try await dapp.client.request(params: request) + try await dapp.request(params: request) } - } - wallet.onSessionRequest = { [unowned self] sessionRequest in + }.store(in: &publishers) + wallet.sessionRequestPublisher.sink { [unowned self] (sessionRequest, _) in let receivedParams = try! sessionRequest.params.get([EthSendTransaction].self) XCTAssertEqual(receivedParams, requestParams) XCTAssertEqual(sessionRequest.method, requestMethod) requestExpectation.fulfill() Task(priority: .high) { - try await wallet.client.respond(topic: sessionRequest.topic, requestId: sessionRequest.id, response: .response(AnyCodable(responseParams))) + try await wallet.respond(topic: sessionRequest.topic, requestId: sessionRequest.id, response: .response(AnyCodable(responseParams))) } - } - dapp.onSessionResponse = { response in + }.store(in: &publishers) + dapp.sessionResponsePublisher.sink { response in switch response.result { case .response(let response): XCTAssertEqual(try! response.get(String.self), responseParams) @@ -208,10 +222,11 @@ final class SignClientTests: XCTestCase { XCTFail() } responseExpectation.fulfill() - } + }.store(in: &publishers) - let uri = try await dapp.client.connect(requiredNamespaces: requiredNamespaces) - try await wallet.client.pair(uri: uri!) + let uri = try! await dappPairingClient.create() + try await dapp.connect(requiredNamespaces: requiredNamespaces, topic: uri.topic) + try await walletPairingClient.pair(uri: uri) wait(for: [requestExpectation, responseExpectation], timeout: InputConfig.defaultTimeout) } @@ -226,23 +241,23 @@ final class SignClientTests: XCTestCase { let chain = Blockchain("eip155:1")! - wallet.onSessionProposal = { [unowned self] proposal in + wallet.sessionProposalPublisher.sink { [unowned self] (proposal, _) in Task(priority: .high) { - try await wallet.client.approve(proposalId: proposal.id, namespaces: sessionNamespaces) + try await wallet.approve(proposalId: proposal.id, namespaces: sessionNamespaces) } - } - dapp.onSessionSettled = { [unowned self] settledSession in + }.store(in: &publishers) + dapp.sessionSettlePublisher.sink { [unowned self] settledSession in Task(priority: .high) { let request = Request(id: RPCID(0), topic: settledSession.topic, method: requestMethod, params: requestParams, chainId: chain, expiry: nil) - try await dapp.client.request(params: request) + try await dapp.request(params: request) } - } - wallet.onSessionRequest = { [unowned self] sessionRequest in + }.store(in: &publishers) + wallet.sessionRequestPublisher.sink { [unowned self] (sessionRequest, _) in Task(priority: .high) { - try await wallet.client.respond(topic: sessionRequest.topic, requestId: sessionRequest.id, response: .error(error)) + try await wallet.respond(topic: sessionRequest.topic, requestId: sessionRequest.id, response: .error(error)) } - } - dapp.onSessionResponse = { response in + }.store(in: &publishers) + dapp.sessionResponsePublisher.sink { response in switch response.result { case .response: XCTFail() @@ -250,14 +265,15 @@ final class SignClientTests: XCTestCase { XCTAssertEqual(error, receivedError) } expectation.fulfill() - } + }.store(in: &publishers) - let uri = try await dapp.client.connect(requiredNamespaces: requiredNamespaces) - try await wallet.client.pair(uri: uri!) + let uri = try! await dappPairingClient.create() + try await dapp.connect(requiredNamespaces: requiredNamespaces, topic: uri.topic) + try await walletPairingClient.pair(uri: uri) wait(for: [expectation], timeout: InputConfig.defaultTimeout) } - func testNewSessionOnExistingPairing() async { + func testNewSessionOnExistingPairing() async throws { let dappSettlementExpectation = expectation(description: "Dapp settles session") dappSettlementExpectation.expectedFulfillmentCount = 2 let walletSettlementExpectation = expectation(description: "Wallet settles session") @@ -266,86 +282,89 @@ final class SignClientTests: XCTestCase { let sessionNamespaces = SessionNamespace.make(toRespond: requiredNamespaces) var initiatedSecondSession = false - wallet.onSessionProposal = { [unowned self] proposal in + wallet.sessionProposalPublisher.sink { [unowned self] (proposal, _) in Task(priority: .high) { do { - try await wallet.client.approve(proposalId: proposal.id, namespaces: sessionNamespaces) + try await wallet.approve(proposalId: proposal.id, namespaces: sessionNamespaces) } catch { XCTFail("\(error)") } } - } - dapp.onSessionSettled = { [unowned self] _ in + }.store(in: &publishers) + dapp.sessionSettlePublisher.sink { [unowned self] _ in dappSettlementExpectation.fulfill() - let pairingTopic = dapp.client.getPairings().first!.topic + let pairingTopic = dappPairingClient.getPairings().first!.topic if !initiatedSecondSession { Task(priority: .high) { - _ = try! await dapp.client.connect(requiredNamespaces: requiredNamespaces, topic: pairingTopic) + _ = try! await dapp.connect(requiredNamespaces: requiredNamespaces, topic: pairingTopic) } initiatedSecondSession = true } - } - wallet.onSessionSettled = { _ in + }.store(in: &publishers) + wallet.sessionSettlePublisher.sink { _ in walletSettlementExpectation.fulfill() - } + }.store(in: &publishers) - let uri = try! await dapp.client.connect(requiredNamespaces: requiredNamespaces) - try! await wallet.client.pair(uri: uri!) + let uri = try! await dappPairingClient.create() + try await dapp.connect(requiredNamespaces: requiredNamespaces, topic: uri.topic) + try await walletPairingClient.pair(uri: uri) wait(for: [dappSettlementExpectation, walletSettlementExpectation], timeout: InputConfig.defaultTimeout) } - func testSuccessfulSessionUpdateNamespaces() async { + func testSuccessfulSessionUpdateNamespaces() async throws { let expectation = expectation(description: "Dapp updates namespaces") let requiredNamespaces = ProposalNamespace.stubRequired() let sessionNamespaces = SessionNamespace.make(toRespond: requiredNamespaces) - wallet.onSessionProposal = { [unowned self] proposal in + wallet.sessionProposalPublisher.sink { [unowned self] (proposal, _) in Task(priority: .high) { - try await wallet.client.approve(proposalId: proposal.id, namespaces: sessionNamespaces) + try await wallet.approve(proposalId: proposal.id, namespaces: sessionNamespaces) } - } - dapp.onSessionSettled = { [unowned self] settledSession in + }.store(in: &publishers) + dapp.sessionSettlePublisher.sink { [unowned self] settledSession in Task(priority: .high) { - try! await wallet.client.update(topic: settledSession.topic, namespaces: sessionNamespaces) + try! await wallet.update(topic: settledSession.topic, namespaces: sessionNamespaces) } - } - dapp.onSessionUpdateNamespaces = { _, _ in + }.store(in: &publishers) + dapp.sessionUpdatePublisher.sink { _, _ in expectation.fulfill() - } - let uri = try! await dapp.client.connect(requiredNamespaces: requiredNamespaces) - try! await wallet.client.pair(uri: uri!) + }.store(in: &publishers) + let uri = try! await dappPairingClient.create() + try await dapp.connect(requiredNamespaces: requiredNamespaces, topic: uri.topic) + try await walletPairingClient.pair(uri: uri) wait(for: [expectation], timeout: InputConfig.defaultTimeout) } - func testSuccessfulSessionExtend() async { + func testSuccessfulSessionExtend() async throws { let expectation = expectation(description: "Dapp extends session") let requiredNamespaces = ProposalNamespace.stubRequired() let sessionNamespaces = SessionNamespace.make(toRespond: requiredNamespaces) - wallet.onSessionProposal = { [unowned self] proposal in + wallet.sessionProposalPublisher.sink { [unowned self] (proposal, _) in Task(priority: .high) { - try await wallet.client.approve(proposalId: proposal.id, namespaces: sessionNamespaces) + try await wallet.approve(proposalId: proposal.id, namespaces: sessionNamespaces) } - } + }.store(in: &publishers) - dapp.onSessionExtend = { _, _ in + dapp.sessionExtendPublisher.sink { _, _ in expectation.fulfill() - } + }.store(in: &publishers) - dapp.onSessionSettled = { [unowned self] settledSession in + dapp.sessionSettlePublisher.sink { [unowned self] settledSession in Task(priority: .high) { - try! await wallet.client.extend(topic: settledSession.topic) + try! await wallet.extend(topic: settledSession.topic) } - } + }.store(in: &publishers) - let uri = try! await dapp.client.connect(requiredNamespaces: requiredNamespaces) - try! await wallet.client.pair(uri: uri!) + let uri = try! await dappPairingClient.create() + try await dapp.connect(requiredNamespaces: requiredNamespaces, topic: uri.topic) + try await walletPairingClient.pair(uri: uri) wait(for: [expectation], timeout: InputConfig.defaultTimeout) } - func testSessionEventSucceeds() async { + func testSessionEventSucceeds() async throws { let expectation = expectation(description: "Dapp receives session event") let requiredNamespaces = ProposalNamespace.stubRequired() @@ -353,29 +372,30 @@ final class SignClientTests: XCTestCase { let event = Session.Event(name: "any", data: AnyCodable("event_data")) let chain = Blockchain("eip155:1")! - wallet.onSessionProposal = { [unowned self] proposal in + wallet.sessionProposalPublisher.sink { [unowned self] (proposal, _) in Task(priority: .high) { - try await wallet.client.approve(proposalId: proposal.id, namespaces: sessionNamespaces) + try await wallet.approve(proposalId: proposal.id, namespaces: sessionNamespaces) } - } + }.store(in: &publishers) - dapp.onEventReceived = { _, _ in + dapp.sessionEventPublisher.sink { _, _, _ in expectation.fulfill() - } + }.store(in: &publishers) - dapp.onSessionSettled = { [unowned self] settledSession in + dapp.sessionSettlePublisher.sink { [unowned self] settledSession in Task(priority: .high) { - try! await wallet.client.emit(topic: settledSession.topic, event: event, chainId: chain) + try! await wallet.emit(topic: settledSession.topic, event: event, chainId: chain) } - } + }.store(in: &publishers) - let uri = try! await dapp.client.connect(requiredNamespaces: requiredNamespaces) - try! await wallet.client.pair(uri: uri!) + let uri = try! await dappPairingClient.create() + try await dapp.connect(requiredNamespaces: requiredNamespaces, topic: uri.topic) + try await walletPairingClient.pair(uri: uri) wait(for: [expectation], timeout: InputConfig.defaultTimeout) } - func testSessionEventFails() async { + func testSessionEventFails() async throws { let expectation = expectation(description: "Dapp receives session event") let requiredNamespaces = ProposalNamespace.stubRequired() @@ -383,21 +403,22 @@ final class SignClientTests: XCTestCase { let event = Session.Event(name: "unknown", data: AnyCodable("event_data")) let chain = Blockchain("eip155:1")! - wallet.onSessionProposal = { [unowned self] proposal in + wallet.sessionProposalPublisher.sink { [unowned self] (proposal, _) in Task(priority: .high) { - try await wallet.client.approve(proposalId: proposal.id, namespaces: sessionNamespaces) + try await wallet.approve(proposalId: proposal.id, namespaces: sessionNamespaces) } - } + }.store(in: &publishers) - dapp.onSessionSettled = { [unowned self] settledSession in + dapp.sessionSettlePublisher.sink { [unowned self] settledSession in Task(priority: .high) { - await XCTAssertThrowsErrorAsync(try await wallet.client.emit(topic: settledSession.topic, event: event, chainId: chain)) + await XCTAssertThrowsErrorAsync(try await wallet.emit(topic: settledSession.topic, event: event, chainId: chain)) expectation.fulfill() } - } + }.store(in: &publishers) - let uri = try! await dapp.client.connect(requiredNamespaces: requiredNamespaces) - try! await wallet.client.pair(uri: uri!) + let uri = try! await dappPairingClient.create() + try await dapp.connect(requiredNamespaces: requiredNamespaces, topic: uri.topic) + try await walletPairingClient.pair(uri: uri) wait(for: [expectation], timeout: InputConfig.defaultTimeout) } @@ -458,24 +479,25 @@ final class SignClientTests: XCTestCase { ] ) - wallet.onSessionProposal = { [unowned self] proposal in + wallet.sessionProposalPublisher.sink { [unowned self] (proposal, _) in Task(priority: .high) { do { - try await wallet.client.approve(proposalId: proposal.id, namespaces: sessionNamespaces) + try await wallet.approve(proposalId: proposal.id, namespaces: sessionNamespaces) } catch { XCTFail("\(error)") } } - } - dapp.onSessionSettled = { _ in + }.store(in: &publishers) + dapp.sessionSettlePublisher.sink { settledSession in dappSettlementExpectation.fulfill() - } - wallet.onSessionSettled = { _ in + }.store(in: &publishers) + wallet.sessionEventPublisher.sink { _ in walletSettlementExpectation.fulfill() - } + }.store(in: &publishers) - let uri = try await dapp.client.connect(requiredNamespaces: requiredNamespaces, optionalNamespaces: optionalNamespaces) - try await wallet.client.pair(uri: uri!) + let uri = try! await dappPairingClient.create() + try await dapp.connect(requiredNamespaces: requiredNamespaces, optionalNamespaces: optionalNamespaces, topic: uri.topic) + try await walletPairingClient.pair(uri: uri) wait(for: [dappSettlementExpectation, walletSettlementExpectation], timeout: InputConfig.defaultTimeout) } @@ -526,24 +548,25 @@ final class SignClientTests: XCTestCase { ] ) - wallet.onSessionProposal = { [unowned self] proposal in + wallet.sessionProposalPublisher.sink { [unowned self] (proposal, _) in Task(priority: .high) { do { - try await wallet.client.approve(proposalId: proposal.id, namespaces: sessionNamespaces) + try await wallet.approve(proposalId: proposal.id, namespaces: sessionNamespaces) } catch { XCTFail("\(error)") } } - } - dapp.onSessionSettled = { _ in + }.store(in: &publishers) + dapp.sessionSettlePublisher.sink { [unowned self] _ in dappSettlementExpectation.fulfill() - } - wallet.onSessionSettled = { _ in + }.store(in: &publishers) + wallet.sessionEventPublisher.sink { _ in walletSettlementExpectation.fulfill() - } + }.store(in: &publishers) - let uri = try await dapp.client.connect(requiredNamespaces: requiredNamespaces, optionalNamespaces: optionalNamespaces) - try await wallet.client.pair(uri: uri!) + let uri = try! await dappPairingClient.create() + try await dapp.connect(requiredNamespaces: requiredNamespaces, optionalNamespaces: optionalNamespaces, topic: uri.topic) + try await walletPairingClient.pair(uri: uri) wait(for: [dappSettlementExpectation, walletSettlementExpectation], timeout: InputConfig.defaultTimeout) } @@ -584,24 +607,25 @@ final class SignClientTests: XCTestCase { ] ) - wallet.onSessionProposal = { [unowned self] proposal in + wallet.sessionProposalPublisher.sink { [unowned self] (proposal, _) in Task(priority: .high) { do { - try await wallet.client.approve(proposalId: proposal.id, namespaces: sessionNamespaces) + try await wallet.approve(proposalId: proposal.id, namespaces: sessionNamespaces) } catch { XCTFail("\(error)") } } - } - dapp.onSessionSettled = { _ in + }.store(in: &publishers) + dapp.sessionSettlePublisher.sink { _ in dappSettlementExpectation.fulfill() - } - wallet.onSessionSettled = { _ in + }.store(in: &publishers) + wallet.sessionEventPublisher.sink { _ in walletSettlementExpectation.fulfill() - } + }.store(in: &publishers) - let uri = try await dapp.client.connect(requiredNamespaces: requiredNamespaces, optionalNamespaces: optionalNamespaces) - try await wallet.client.pair(uri: uri!) + let uri = try! await dappPairingClient.create() + try await dapp.connect(requiredNamespaces: requiredNamespaces, optionalNamespaces: optionalNamespaces, topic: uri.topic) + try await walletPairingClient.pair(uri: uri) wait(for: [dappSettlementExpectation, walletSettlementExpectation], timeout: InputConfig.defaultTimeout) } @@ -649,21 +673,22 @@ final class SignClientTests: XCTestCase { ] ) - wallet.onSessionProposal = { [unowned self] proposal in + wallet.sessionProposalPublisher.sink { [unowned self] (proposal, _) in Task(priority: .high) { do { - try await wallet.client.approve(proposalId: proposal.id, namespaces: sessionNamespaces) + try await wallet.approve(proposalId: proposal.id, namespaces: sessionNamespaces) } catch { settlementFailedExpectation.fulfill() } } - } + }.store(in: &publishers) } catch { settlementFailedExpectation.fulfill() } - let uri = try await dapp.client.connect(requiredNamespaces: requiredNamespaces, optionalNamespaces: optionalNamespaces) - try await wallet.client.pair(uri: uri!) + let uri = try! await dappPairingClient.create() + try await dapp.connect(requiredNamespaces: requiredNamespaces, optionalNamespaces: optionalNamespaces, topic: uri.topic) + try await walletPairingClient.pair(uri: uri) wait(for: [settlementFailedExpectation], timeout: 1) } @@ -714,21 +739,22 @@ final class SignClientTests: XCTestCase { ] ) - wallet.onSessionProposal = { [unowned self] proposal in + wallet.sessionProposalPublisher.sink { [unowned self] (proposal, _) in Task(priority: .high) { do { - try await wallet.client.approve(proposalId: proposal.id, namespaces: sessionNamespaces) + try await wallet.approve(proposalId: proposal.id, namespaces: sessionNamespaces) } catch { settlementFailedExpectation.fulfill() } } - } + }.store(in: &publishers) } catch { settlementFailedExpectation.fulfill() } - let uri = try await dapp.client.connect(requiredNamespaces: requiredNamespaces, optionalNamespaces: optionalNamespaces) - try await wallet.client.pair(uri: uri!) + let uri = try! await dappPairingClient.create() + try await dapp.connect(requiredNamespaces: requiredNamespaces, optionalNamespaces: optionalNamespaces, topic: uri.topic) + try await walletPairingClient.pair(uri: uri) wait(for: [settlementFailedExpectation], timeout: 1) } } diff --git a/Sources/WalletConnectSign/Sign/SignClient.swift b/Sources/WalletConnectSign/Sign/SignClient.swift index 1ea172041..6cd77e69c 100644 --- a/Sources/WalletConnectSign/Sign/SignClient.swift +++ b/Sources/WalletConnectSign/Sign/SignClient.swift @@ -173,43 +173,6 @@ public final class SignClient: SignClientProtocol { // MARK: - Public interface - /// For a dApp to propose a session to a wallet. - /// Function will create pairing and propose session or propose a session on existing pairing. - /// - Parameters: - /// - requiredNamespaces: required namespaces for a session - /// - topic: Optional parameter - use it if you already have an established pairing with peer client. - /// - Returns: Pairing URI that should be shared with responder out of bound. Common way is to present it as a QR code. Pairing URI will be nil if you are going to establish a session on existing Pairing and `topic` function parameter was provided. - @available(*, deprecated, message: "use Pair.instance.create() and connect(requiredNamespaces: [String: ProposalNamespace]): instead") - public func connect( - requiredNamespaces: [String: ProposalNamespace], - optionalNamespaces: [String: ProposalNamespace]? = nil, - sessionProperties: [String: String]? = nil, - topic: String? = nil - ) async throws -> WalletConnectURI? { - logger.debug("Connecting Application") - if let topic = topic { - try pairingClient.validatePairingExistance(topic) - try await appProposeService.propose( - pairingTopic: topic, - namespaces: requiredNamespaces, - optionalNamespaces: optionalNamespaces, - sessionProperties: sessionProperties, - relay: RelayProtocolOptions(protocol: "irn", data: nil) - ) - return nil - } else { - let pairingURI = try await pairingClient.create() - try await appProposeService.propose( - pairingTopic: pairingURI.topic, - namespaces: requiredNamespaces, - optionalNamespaces: optionalNamespaces, - sessionProperties: sessionProperties, - relay: RelayProtocolOptions(protocol: "irn", data: nil) - ) - return pairingURI - } - } - /// For a dApp to propose a session to a wallet. /// Function will propose a session on existing pairing. /// - Parameters: @@ -232,6 +195,7 @@ public final class SignClient: SignClientProtocol { ) } +<<<<<<< HEAD /// For wallet to receive a session proposal from a dApp /// Responder should call this function in order to accept peer's pairing and be able to subscribe for future session proposals. /// - Parameter uri: Pairing URI that is commonly presented as a QR code by a dapp. @@ -244,6 +208,40 @@ public final class SignClient: SignClientProtocol { try await pairingClient.pair(uri: uri) } +======= + //---------------------------------------AUTH----------------------------------- + + public func authenticate(_ params: RequestParams, topic: String) async throws { + try pairingClient.validatePairingExistance(topic) + logger.debug("Requesting Authentication on existing pairing") + try await appRequestService.request(params: params, topic: topic) + } + + + /// For a wallet to respond on authentication request + /// - Parameters: + /// - requestId: authentication request id + /// - signature: CACAO signature of requested message + public func respondSessionAuthenticated(requestId: RPCID, signature: CacaoSignature, account: Account) async throws { + try await walletRespondService.respond(requestId: requestId, signature: signature, account: account) + } + + /// For wallet to reject authentication request + /// - Parameter requestId: authentication request id + public func rejectSession(requestId: RPCID) async throws { + try await walletRespondService.respondError(requestId: requestId) + } + + + /// Query pending authentication requests + /// - Returns: Pending authentication requests + public func getPendingAuthRequests() throws -> [(AuthenticationRequest, VerifyContext?)] { + return try pendingRequestsProvider.getPendingRequests() + } + + //----------------------------------------------------------------------------------- + +>>>>>>> 9f705cc6 (refactor sign client tests) /// For a wallet to approve a session proposal. /// - Parameters: /// - proposalId: Session Proposal id @@ -337,13 +335,6 @@ public final class SignClient: SignClientProtocol { sessionEngine.getSessions() } - /// Query pairings - /// - Returns: All pairings - @available(*, deprecated, message: "use Pair.instance.getPairings(uri: WalletConnectURI): instead") - public func getPairings() -> [Pairing] { - pairingClient.getPairings() - } - /// Query pending requests /// - Returns: Pending requests received from peer with `wc_sessionRequest` protocol method /// - Parameter topic: topic representing session for which you want to get pending requests. If nil, you will receive pending requests for all active sessions. diff --git a/Sources/WalletConnectSign/Sign/SignClientProtocol.swift b/Sources/WalletConnectSign/Sign/SignClientProtocol.swift index 95f56ee76..0d83845b1 100644 --- a/Sources/WalletConnectSign/Sign/SignClientProtocol.swift +++ b/Sources/WalletConnectSign/Sign/SignClientProtocol.swift @@ -20,7 +20,6 @@ public protocol SignClientProtocol { func extend(topic: String) async throws func respond(topic: String, requestId: RPCID, response: RPCResult) async throws func emit(topic: String, event: Session.Event, chainId: Blockchain) async throws - func pair(uri: WalletConnectURI) async throws func disconnect(topic: String) async throws func getSessions() -> [Session] func cleanup() async throws From ad2720061155db771564aa159023a2828789b589 Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Sat, 4 Nov 2023 10:27:56 +0100 Subject: [PATCH 2/3] fix all sign client tests --- Example/IntegrationTests/Sign/SignClientTests.swift | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Example/IntegrationTests/Sign/SignClientTests.swift b/Example/IntegrationTests/Sign/SignClientTests.swift index 62519ca80..6c8cd69a2 100644 --- a/Example/IntegrationTests/Sign/SignClientTests.swift +++ b/Example/IntegrationTests/Sign/SignClientTests.swift @@ -491,7 +491,7 @@ final class SignClientTests: XCTestCase { dapp.sessionSettlePublisher.sink { settledSession in dappSettlementExpectation.fulfill() }.store(in: &publishers) - wallet.sessionEventPublisher.sink { _ in + wallet.sessionSettlePublisher.sink { _ in walletSettlementExpectation.fulfill() }.store(in: &publishers) @@ -560,7 +560,7 @@ final class SignClientTests: XCTestCase { dapp.sessionSettlePublisher.sink { [unowned self] _ in dappSettlementExpectation.fulfill() }.store(in: &publishers) - wallet.sessionEventPublisher.sink { _ in + wallet.sessionSettlePublisher.sink { _ in walletSettlementExpectation.fulfill() }.store(in: &publishers) @@ -619,7 +619,7 @@ final class SignClientTests: XCTestCase { dapp.sessionSettlePublisher.sink { _ in dappSettlementExpectation.fulfill() }.store(in: &publishers) - wallet.sessionEventPublisher.sink { _ in + wallet.sessionSettlePublisher.sink { _ in walletSettlementExpectation.fulfill() }.store(in: &publishers) From 8f01ffb5f98bff35c9b14d5253c4a83860067c2b Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Sat, 4 Nov 2023 10:37:47 +0100 Subject: [PATCH 3/3] resolve conflicts, remove deprecated method --- .../Sign/SignClientTests.swift | 6 +-- .../WalletConnectSign/Sign/SignClient.swift | 46 ------------------- 2 files changed, 1 insertion(+), 51 deletions(-) diff --git a/Example/IntegrationTests/Sign/SignClientTests.swift b/Example/IntegrationTests/Sign/SignClientTests.swift index 6c8cd69a2..4cecd7bb0 100644 --- a/Example/IntegrationTests/Sign/SignClientTests.swift +++ b/Example/IntegrationTests/Sign/SignClientTests.swift @@ -108,11 +108,7 @@ final class SignClientTests: XCTestCase { wallet.sessionProposalPublisher.sink { [unowned self] (proposal, _) in Task(priority: .high) { do { -<<<<<<< HEAD - try await wallet.client.reject(proposalId: proposal.id, reason: .userRejectedChains) // TODO: Review reason -======= - try await wallet.rejectSession(proposalId: proposal.id, reason: .userRejectedChains) // TODO: Review reason ->>>>>>> 9f705cc6 (refactor sign client tests) + try await wallet.reject(proposalId: proposal.id, reason: .userRejectedChains) // TODO: Review reason store.rejectedProposal = proposal } catch { XCTFail("\(error)") } } diff --git a/Sources/WalletConnectSign/Sign/SignClient.swift b/Sources/WalletConnectSign/Sign/SignClient.swift index 6cd77e69c..299e6c4b1 100644 --- a/Sources/WalletConnectSign/Sign/SignClient.swift +++ b/Sources/WalletConnectSign/Sign/SignClient.swift @@ -195,53 +195,7 @@ public final class SignClient: SignClientProtocol { ) } -<<<<<<< HEAD - /// For wallet to receive a session proposal from a dApp - /// Responder should call this function in order to accept peer's pairing and be able to subscribe for future session proposals. - /// - Parameter uri: Pairing URI that is commonly presented as a QR code by a dapp. - /// - /// Should Error: - /// - When URI has invalid format or missing params - /// - When topic is already in use - @available(*, deprecated, message: "use Pair.instance.pair(uri: WalletConnectURI): instead") - public func pair(uri: WalletConnectURI) async throws { - try await pairingClient.pair(uri: uri) - } - -======= - //---------------------------------------AUTH----------------------------------- - - public func authenticate(_ params: RequestParams, topic: String) async throws { - try pairingClient.validatePairingExistance(topic) - logger.debug("Requesting Authentication on existing pairing") - try await appRequestService.request(params: params, topic: topic) - } - - - /// For a wallet to respond on authentication request - /// - Parameters: - /// - requestId: authentication request id - /// - signature: CACAO signature of requested message - public func respondSessionAuthenticated(requestId: RPCID, signature: CacaoSignature, account: Account) async throws { - try await walletRespondService.respond(requestId: requestId, signature: signature, account: account) - } - - /// For wallet to reject authentication request - /// - Parameter requestId: authentication request id - public func rejectSession(requestId: RPCID) async throws { - try await walletRespondService.respondError(requestId: requestId) - } - - - /// Query pending authentication requests - /// - Returns: Pending authentication requests - public func getPendingAuthRequests() throws -> [(AuthenticationRequest, VerifyContext?)] { - return try pendingRequestsProvider.getPendingRequests() - } - - //----------------------------------------------------------------------------------- ->>>>>>> 9f705cc6 (refactor sign client tests) /// For a wallet to approve a session proposal. /// - Parameters: /// - proposalId: Session Proposal id