diff --git a/Example/DApp/SceneDelegate.swift b/Example/DApp/SceneDelegate.swift index faba03264..2586a7fd9 100644 --- a/Example/DApp/SceneDelegate.swift +++ b/Example/DApp/SceneDelegate.swift @@ -24,7 +24,6 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { Web3Modal.configure( projectId: InputConfig.projectId, - chainId: Blockchain("eip155:1")!, metadata: metadata ) diff --git a/Example/ExampleApp.xcodeproj/project.pbxproj b/Example/ExampleApp.xcodeproj/project.pbxproj index c9ffb9c62..4f5a2101c 100644 --- a/Example/ExampleApp.xcodeproj/project.pbxproj +++ b/Example/ExampleApp.xcodeproj/project.pbxproj @@ -55,7 +55,6 @@ A507BE1A29E8032E0038EF70 /* EIP55Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A507BE1929E8032E0038EF70 /* EIP55Tests.swift */; }; A50B6A362B06683800162B01 /* InputConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = C56EE25D293F56D6004840D1 /* InputConfig.swift */; }; A50B6A382B06697B00162B01 /* ProfilingService.swift in Sources */ = {isa = PBXBuildFile; fileRef = A50B6A372B06697B00162B01 /* ProfilingService.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 */; }; @@ -456,7 +455,6 @@ 84FE684528ACDB4700C893FF /* RequestParams.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RequestParams.swift; sourceTree = ""; }; A507BE1929E8032E0038EF70 /* EIP55Tests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EIP55Tests.swift; sourceTree = ""; }; A50B6A372B06697B00162B01 /* ProfilingService.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ProfilingService.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 = ""; }; @@ -859,7 +857,6 @@ 767DC83328997F7600080FA9 /* Helpers */ = { isa = PBXGroup; children = ( - A50C036428AAD32200FE72D3 /* ClientDelegate.swift */, 767DC83428997F8E00080FA9 /* EthSendTransaction.swift */, 84AA01DA28CF0CD7005D48D8 /* XCTest.swift */, ); @@ -2489,7 +2486,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/ExampleApp.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/Example/ExampleApp.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 229e0f8ef..dceba93f5 100644 --- a/Example/ExampleApp.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/Example/ExampleApp.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -168,8 +168,8 @@ "repositoryURL": "https://github.com/WalletConnect/web3modal-swift", "state": { "branch": null, - "revision": "e68c1b1560264965ca13608db44294d301c6404f", - "version": "1.0.9" + "revision": "831410cfd6e68afa7212a5547483fb2d180f0fa7", + "version": "1.0.10" } } ] 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..4cecd7bb0 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,51 @@ 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 { - try await wallet.client.reject(proposalId: proposal.id, reason: .userRejectedChains) // TODO: Review reason + try await wallet.reject(proposalId: proposal.id, reason: .userRejectedChains) // TODO: Review reason 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 +125,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 +151,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 +187,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 +218,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 +237,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 +261,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 +278,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 +368,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 +399,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 +475,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.sessionSettlePublisher.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 +544,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.sessionSettlePublisher.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 +603,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.sessionSettlePublisher.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 +669,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 +735,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..299e6c4b1 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,17 +195,6 @@ public final class SignClient: SignClientProtocol { ) } - /// 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) - } /// For a wallet to approve a session proposal. /// - Parameters: @@ -337,13 +289,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