From a79328b02bab1fa700093ea7a6a89a25b76abebf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Vants?= Date: Mon, 9 May 2022 20:13:35 -0300 Subject: [PATCH 1/5] Removed optional from event chainId --- Sources/WalletConnect/Engine/SessionEngine.swift | 2 +- Sources/WalletConnect/Types/Session/SessionType.swift | 2 +- Sources/WalletConnect/WalletConnectClient.swift | 2 +- Tests/IntegrationTests/ClientTest.swift | 6 +++--- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Sources/WalletConnect/Engine/SessionEngine.swift b/Sources/WalletConnect/Engine/SessionEngine.swift index 70d09e162..dad8da9f4 100644 --- a/Sources/WalletConnect/Engine/SessionEngine.swift +++ b/Sources/WalletConnect/Engine/SessionEngine.swift @@ -107,7 +107,7 @@ final class SessionEngine { } } - func emit(topic: String, event: SessionType.EventParams.Event, chainId: Blockchain?, completion: ((Error?)->())?) { + func emit(topic: String, event: SessionType.EventParams.Event, chainId: Blockchain, completion: ((Error?)->())?) { guard let session = sessionStore.getSession(forTopic: topic), session.acknowledged else { logger.debug("Could not find session for topic \(topic)") return diff --git a/Sources/WalletConnect/Types/Session/SessionType.swift b/Sources/WalletConnect/Types/Session/SessionType.swift index a83738e81..6e025be83 100644 --- a/Sources/WalletConnect/Types/Session/SessionType.swift +++ b/Sources/WalletConnect/Types/Session/SessionType.swift @@ -70,7 +70,7 @@ internal enum SessionType { struct EventParams: Codable, Equatable { let event: Event - let chainId: Blockchain? + let chainId: Blockchain struct Event: Codable, Equatable { let name: String diff --git a/Sources/WalletConnect/WalletConnectClient.swift b/Sources/WalletConnect/WalletConnectClient.swift index aaa6c5549..a6ccddeff 100644 --- a/Sources/WalletConnect/WalletConnectClient.swift +++ b/Sources/WalletConnect/WalletConnectClient.swift @@ -259,7 +259,7 @@ public final class WalletConnectClient { /// - topic: Session topic /// - params: Event Parameters /// - completion: calls a handler upon completion - public func emit(topic: String, event: Session.Event, chainId: Blockchain?, completion: ((Error?)->())?) { + public func emit(topic: String, event: Session.Event, chainId: Blockchain, completion: ((Error?)->())?) { sessionEngine.emit(topic: topic, event: event.internalRepresentation(), chainId: chainId, completion: completion) } diff --git a/Tests/IntegrationTests/ClientTest.swift b/Tests/IntegrationTests/ClientTest.swift index bbe156283..debcfc238 100644 --- a/Tests/IntegrationTests/ClientTest.swift +++ b/Tests/IntegrationTests/ClientTest.swift @@ -292,7 +292,7 @@ final class ClientTests: XCTestCase { func testSessionEventSucceeds() async { let proposerReceivesEventExpectation = expectation(description: "Proposer receives event") - let namespace = Namespace(chains: [], methods: [], events: ["type1"]) + let namespace = Namespace(chains: [], methods: [], events: ["type1"]) // TODO: Fix namespace with empty chain array / protocol change let uri = try! await proposer.client.connect(namespaces: [namespace])! try! responder.client.pair(uri: uri) @@ -301,7 +301,7 @@ final class ClientTests: XCTestCase { self.responder.client.approve(proposalId: proposal.id, accounts: [], namespaces: [namespace]) } responder.onSessionSettled = { [unowned self] session in - responder.client.emit(topic: session.topic, event: event, chainId: nil, completion: nil) + responder.client.emit(topic: session.topic, event: event, chainId: Blockchain("eip155:1")!, completion: nil) } proposer.onEventReceived = { event, _ in XCTAssertEqual(event, event) @@ -321,7 +321,7 @@ final class ClientTests: XCTestCase { self.responder.client.approve(proposalId: proposal.id, accounts: [], namespaces: []) } proposer.onSessionSettled = { [unowned self] session in - proposer.client.emit(topic: session.topic, event: event, chainId: nil) { error in + proposer.client.emit(topic: session.topic, event: event, chainId: Blockchain("eip155:1")!) { error in XCTAssertNotNil(error) } } From 6a39525131895d1d3a38ec96531c34c84d36cb96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Vants?= Date: Mon, 9 May 2022 20:39:02 -0300 Subject: [PATCH 2/5] Removed optional from request chainId --- .../WalletConnect/Engine/SessionEngine.swift | 22 +-- .../NetworkInteractor/NetworkInteractor.swift | 2 +- Sources/WalletConnect/Request.swift | 6 +- .../Types/Session/SessionType.swift | 2 +- .../Types/Session/WCSession.swift | 1 + .../SessionEngineTests.swift | 151 +++++++++--------- Tests/WalletConnectTests/Stub/Stubs.swift | 2 +- 7 files changed, 91 insertions(+), 95 deletions(-) diff --git a/Sources/WalletConnect/Engine/SessionEngine.swift b/Sources/WalletConnect/Engine/SessionEngine.swift index dad8da9f4..191e11c8d 100644 --- a/Sources/WalletConnect/Engine/SessionEngine.swift +++ b/Sources/WalletConnect/Engine/SessionEngine.swift @@ -218,20 +218,14 @@ final class SessionEngine { networkingInteractor.respondError(for: payload, reason: .noContextWithTopic(context: .session, topic: topic)) return } - if let chain = request.chainId { - guard session.hasNamespace(for: chain) else { - networkingInteractor.respondError(for: payload, reason: .unauthorizedTargetChain(chain.absoluteString)) - return - } - guard session.hasNamespace(for: chain, method: request.method) else { - networkingInteractor.respondError(for: payload, reason: .unauthorizedMethod(request.method)) - return - } - } else { - guard session.hasNamespace(for: nil, method: request.method) else { - networkingInteractor.respondError(for: payload, reason: .unauthorizedMethod(request.method)) - return - } + let chain = request.chainId + guard session.hasNamespace(for: chain) else { + networkingInteractor.respondError(for: payload, reason: .unauthorizedTargetChain(chain.absoluteString)) + return + } + guard session.hasNamespace(for: chain, method: request.method) else { + networkingInteractor.respondError(for: payload, reason: .unauthorizedMethod(request.method)) + return } onSessionRequest?(request) } diff --git a/Sources/WalletConnect/NetworkInteractor/NetworkInteractor.swift b/Sources/WalletConnect/NetworkInteractor/NetworkInteractor.swift index 46f65ae26..143dc9279 100644 --- a/Sources/WalletConnect/NetworkInteractor/NetworkInteractor.swift +++ b/Sources/WalletConnect/NetworkInteractor/NetworkInteractor.swift @@ -264,6 +264,6 @@ class NetworkInteractor: NetworkInteracting { func getChainId(_ request: WCRequest) -> String? { guard case let .sessionRequest(payload) = request.params else {return nil} - return payload.chainId?.absoluteString + return payload.chainId.absoluteString } } diff --git a/Sources/WalletConnect/Request.swift b/Sources/WalletConnect/Request.swift index 36d83d5f9..b9e7b07f0 100644 --- a/Sources/WalletConnect/Request.swift +++ b/Sources/WalletConnect/Request.swift @@ -6,9 +6,9 @@ public struct Request: Codable, Equatable { public let topic: String public let method: String public let params: AnyCodable - public let chainId: Blockchain? + public let chainId: Blockchain - internal init(id: Int64, topic: String, method: String, params: AnyCodable, chainId: Blockchain?) { + internal init(id: Int64, topic: String, method: String, params: AnyCodable, chainId: Blockchain) { self.id = id self.topic = topic self.method = method @@ -16,7 +16,7 @@ public struct Request: Codable, Equatable { self.chainId = chainId } - public init(topic: String, method: String, params: AnyCodable, chainId: Blockchain?) { + public init(topic: String, method: String, params: AnyCodable, chainId: Blockchain) { self.id = Self.generateId() self.topic = topic self.method = method diff --git a/Sources/WalletConnect/Types/Session/SessionType.swift b/Sources/WalletConnect/Types/Session/SessionType.swift index 6e025be83..76ede5493 100644 --- a/Sources/WalletConnect/Types/Session/SessionType.swift +++ b/Sources/WalletConnect/Types/Session/SessionType.swift @@ -60,7 +60,7 @@ internal enum SessionType { struct RequestParams: Codable, Equatable { let request: Request - let chainId: Blockchain? + let chainId: Blockchain struct Request: Codable, Equatable { let method: String diff --git a/Sources/WalletConnect/Types/Session/WCSession.swift b/Sources/WalletConnect/Types/Session/WCSession.swift index b930d200d..1a620cca1 100644 --- a/Sources/WalletConnect/Types/Session/WCSession.swift +++ b/Sources/WalletConnect/Types/Session/WCSession.swift @@ -69,6 +69,7 @@ struct WCSession: ExpirableSequence { namespaces.contains{$0.chains.contains(chain)} } + // TODO: Remove optional for chain param, it's required now / protocol change func hasNamespace(for chain: Blockchain?, method: String) -> Bool { if let chain = chain { let namespacesIncludingChain = namespaces.filter{$0.chains.contains(chain)} diff --git a/Tests/WalletConnectTests/SessionEngineTests.swift b/Tests/WalletConnectTests/SessionEngineTests.swift index 5ca23eded..4b5b2bd93 100644 --- a/Tests/WalletConnectTests/SessionEngineTests.swift +++ b/Tests/WalletConnectTests/SessionEngineTests.swift @@ -124,49 +124,50 @@ final class SessionEngineTests: XCTestCase { XCTAssertFalse(cryptoMock.hasPrivateKey(for: session.self.publicKey!), "Responder must remove private key") } - func testSessionRequestEmptyNamespaceUnmatchingMethod() { - var didTriggerRequest = false - engine.onSessionRequest = { _ in didTriggerRequest = true } - - let session = WCSession.stub(isSelfController: true) - storageMock.setSession(session) - - let payload = WCRequestSubscriptionPayload.stubRequest(topic: session.topic, method: "someMethod", chainId: nil) - networkingInteractor.wcRequestPublisherSubject.send(payload) - - XCTAssertTrue(networkingInteractor.didRespondError) - XCTAssertFalse(didTriggerRequest) - } - - func testSessionRequestEmptyNamespaceMatchingMethod() { - var didTriggerRequest = false - engine.onSessionRequest = { _ in didTriggerRequest = true } - - var session = WCSession.stub(isSelfController: true) - session.updateNamespaces([Namespace(chains: [], methods: ["someMethod"], events: [])]) - storageMock.setSession(session) - - let payload = WCRequestSubscriptionPayload.stubRequest(topic: session.topic, method: "someMethod", chainId: nil) - networkingInteractor.wcRequestPublisherSubject.send(payload) - - XCTAssertFalse(networkingInteractor.didRespondError) - XCTAssertTrue(didTriggerRequest) - } - - func testSessionRequestUndefinedChainMatchingMethod() { - var didTriggerRequest = false - engine.onSessionRequest = { _ in didTriggerRequest = true } - - var session = WCSession.stub(isSelfController: true) - session.updateNamespaces([Namespace(chains: [Blockchain("eip155:1")!], methods: ["someMethod"], events: [])]) - storageMock.setSession(session) - - let payload = WCRequestSubscriptionPayload.stubRequest(topic: session.topic, method: "someMethod", chainId: nil) - networkingInteractor.wcRequestPublisherSubject.send(payload) - - XCTAssertTrue(networkingInteractor.didRespondError) - XCTAssertFalse(didTriggerRequest) - } + // TODO: Tests with nil chainId are obsolete after protocol change, check planned test before removing +// func testSessionRequestEmptyNamespaceUnmatchingMethod() { +// var didTriggerRequest = false +// engine.onSessionRequest = { _ in didTriggerRequest = true } +// +// let session = WCSession.stub(isSelfController: true) +// storageMock.setSession(session) +// +// let payload = WCRequestSubscriptionPayload.stubRequest(topic: session.topic, method: "someMethod", chainId: nil) +// networkingInteractor.wcRequestPublisherSubject.send(payload) +// +// XCTAssertTrue(networkingInteractor.didRespondError) +// XCTAssertFalse(didTriggerRequest) +// } +// +// func testSessionRequestEmptyNamespaceMatchingMethod() { +// var didTriggerRequest = false +// engine.onSessionRequest = { _ in didTriggerRequest = true } +// +// var session = WCSession.stub(isSelfController: true) +// session.updateNamespaces([Namespace(chains: [], methods: ["someMethod"], events: [])]) +// storageMock.setSession(session) +// +// let payload = WCRequestSubscriptionPayload.stubRequest(topic: session.topic, method: "someMethod", chainId: nil) +// networkingInteractor.wcRequestPublisherSubject.send(payload) +// +// XCTAssertFalse(networkingInteractor.didRespondError) +// XCTAssertTrue(didTriggerRequest) +// } +// +// func testSessionRequestUndefinedChainMatchingMethod() { +// var didTriggerRequest = false +// engine.onSessionRequest = { _ in didTriggerRequest = true } +// +// var session = WCSession.stub(isSelfController: true) +// session.updateNamespaces([Namespace(chains: [Blockchain("eip155:1")!], methods: ["someMethod"], events: [])]) +// storageMock.setSession(session) +// +// let payload = WCRequestSubscriptionPayload.stubRequest(topic: session.topic, method: "someMethod", chainId: nil) +// networkingInteractor.wcRequestPublisherSubject.send(payload) +// +// XCTAssertTrue(networkingInteractor.didRespondError) +// XCTAssertFalse(didTriggerRequest) +// } func testSessionRequestDefinedChainMatchingMethod() { var didTriggerRequest = false @@ -198,38 +199,38 @@ final class SessionEngineTests: XCTestCase { XCTAssertFalse(didTriggerRequest) } - func testSessionRequestEmptyNamespaceDefinedChainMatchingMethod() { - var didTriggerRequest = false - engine.onSessionRequest = { _ in didTriggerRequest = true } - - var session = WCSession.stub(isSelfController: true) - session.updateNamespaces([Namespace(chains: [], methods: ["someMethod"], events: [])]) - storageMock.setSession(session) - - let payload = WCRequestSubscriptionPayload.stubRequest(topic: session.topic, method: "someMethod", chainId: Blockchain("eip155:1")!) - networkingInteractor.wcRequestPublisherSubject.send(payload) - - XCTAssertTrue(networkingInteractor.didRespondError) - XCTAssertFalse(didTriggerRequest) - } - - func testSessionRequestMultiNamespaceUndefinedChainMatchingMethod() { - var didTriggerRequest = false - engine.onSessionRequest = { _ in didTriggerRequest = true } - - var session = WCSession.stub(isSelfController: true) - session.updateNamespaces([ - Namespace(chains: [Blockchain("eip155:1")!], methods: ["someMethod"], events: []), - Namespace(chains: [], methods: ["someMethod"], events: []) - ]) - storageMock.setSession(session) - - let payload = WCRequestSubscriptionPayload.stubRequest(topic: session.topic, method: "someMethod", chainId: nil) - networkingInteractor.wcRequestPublisherSubject.send(payload) - - XCTAssertFalse(networkingInteractor.didRespondError) - XCTAssertTrue(didTriggerRequest) - } +// func testSessionRequestEmptyNamespaceDefinedChainMatchingMethod() { +// var didTriggerRequest = false +// engine.onSessionRequest = { _ in didTriggerRequest = true } +// +// var session = WCSession.stub(isSelfController: true) +// session.updateNamespaces([Namespace(chains: [], methods: ["someMethod"], events: [])]) +// storageMock.setSession(session) +// +// let payload = WCRequestSubscriptionPayload.stubRequest(topic: session.topic, method: "someMethod", chainId: Blockchain("eip155:1")!) +// networkingInteractor.wcRequestPublisherSubject.send(payload) +// +// XCTAssertTrue(networkingInteractor.didRespondError) +// XCTAssertFalse(didTriggerRequest) +// } +// +// func testSessionRequestMultiNamespaceUndefinedChainMatchingMethod() { +// var didTriggerRequest = false +// engine.onSessionRequest = { _ in didTriggerRequest = true } +// +// var session = WCSession.stub(isSelfController: true) +// session.updateNamespaces([ +// Namespace(chains: [Blockchain("eip155:1")!], methods: ["someMethod"], events: []), +// Namespace(chains: [], methods: ["someMethod"], events: []) +// ]) +// storageMock.setSession(session) +// +// let payload = WCRequestSubscriptionPayload.stubRequest(topic: session.topic, method: "someMethod", chainId: nil) +// networkingInteractor.wcRequestPublisherSubject.send(payload) +// +// XCTAssertFalse(networkingInteractor.didRespondError) +// XCTAssertTrue(didTriggerRequest) +// } func testSessionRequestMultiNamespaceDefinedChainMatchingMethod() { var didTriggerRequest = false diff --git a/Tests/WalletConnectTests/Stub/Stubs.swift b/Tests/WalletConnectTests/Stub/Stubs.swift index f3eedd741..6a6970480 100644 --- a/Tests/WalletConnectTests/Stub/Stubs.swift +++ b/Tests/WalletConnectTests/Stub/Stubs.swift @@ -71,7 +71,7 @@ extension WCRequestSubscriptionPayload { return WCRequestSubscriptionPayload(topic: topic, wcRequest: method.asRequest()) } - static func stubRequest(topic: String, method: String, chainId: Blockchain?) -> WCRequestSubscriptionPayload { + static func stubRequest(topic: String, method: String, chainId: Blockchain) -> WCRequestSubscriptionPayload { let params = SessionType.RequestParams( request: SessionType.RequestParams.Request(method: method, params: AnyCodable(EmptyCodable())), chainId: chainId) From a57f0464e3b6c21b406c3e1d430ab071868f8a37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Vants?= Date: Mon, 9 May 2022 21:02:36 -0300 Subject: [PATCH 3/5] Fixed integration test case --- Tests/IntegrationTests/ClientTest.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tests/IntegrationTests/ClientTest.swift b/Tests/IntegrationTests/ClientTest.swift index debcfc238..2d2296360 100644 --- a/Tests/IntegrationTests/ClientTest.swift +++ b/Tests/IntegrationTests/ClientTest.swift @@ -292,7 +292,7 @@ final class ClientTests: XCTestCase { func testSessionEventSucceeds() async { let proposerReceivesEventExpectation = expectation(description: "Proposer receives event") - let namespace = Namespace(chains: [], methods: [], events: ["type1"]) // TODO: Fix namespace with empty chain array / protocol change + let namespace = Namespace(chains: [Blockchain("eip155:1")!], methods: [], events: ["type1"]) // TODO: Fix namespace with empty chain array / protocol change let uri = try! await proposer.client.connect(namespaces: [namespace])! try! responder.client.pair(uri: uri) From d79213843f851683db06436298a091fca9b3a019 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Vants?= Date: Wed, 11 May 2022 00:51:03 -0300 Subject: [PATCH 4/5] Added validation checks for empty namespaces --- .../WalletConnect/Engine/PairingEngine.swift | 6 ++ .../WalletConnect/Engine/SessionEngine.swift | 3 +- .../SessionStateMachineValidating.swift | 13 +-- Sources/WalletConnect/Namespace.swift | 21 +++++ .../WalletConnect/WalletConnectClient.swift | 5 +- .../WalletConnect/WalletConnectError.swift | 3 + Tests/IntegrationTests/ClientTest.swift | 22 ++--- .../SessionEngineTests.swift | 80 +------------------ 8 files changed, 48 insertions(+), 105 deletions(-) diff --git a/Sources/WalletConnect/Engine/PairingEngine.swift b/Sources/WalletConnect/Engine/PairingEngine.swift index af5bbedf9..5aea81af3 100644 --- a/Sources/WalletConnect/Engine/PairingEngine.swift +++ b/Sources/WalletConnect/Engine/PairingEngine.swift @@ -70,6 +70,12 @@ final class PairingEngine { } func propose(pairingTopic: String, namespaces: Set, relay: RelayProtocolOptions, completion: @escaping ((Error?) -> ())) { logger.debug("Propose Session on topic: \(pairingTopic)") + do { + try Namespace.validate(namespaces) + } catch { + completion(error) + return + } let publicKey = try! kms.createX25519KeyPair() let proposer = Participant( publicKey: publicKey.hexRepresentation, diff --git a/Sources/WalletConnect/Engine/SessionEngine.swift b/Sources/WalletConnect/Engine/SessionEngine.swift index 191e11c8d..75e625035 100644 --- a/Sources/WalletConnect/Engine/SessionEngine.swift +++ b/Sources/WalletConnect/Engine/SessionEngine.swift @@ -145,7 +145,8 @@ final class SessionEngine { }.store(in: &publishers) } - func settle(topic: String, proposal: SessionProposal, accounts: Set, namespaces: Set) { + func settle(topic: String, proposal: SessionProposal, accounts: Set, namespaces: Set) throws { + try Namespace.validate(namespaces) let agreementKeys = try! kms.getAgreementSecret(for: topic)! let selfParticipant = Participant(publicKey: agreementKeys.publicKey.hexRepresentation, metadata: metadata) diff --git a/Sources/WalletConnect/Engine/SessionStateMachines/SessionStateMachineValidating.swift b/Sources/WalletConnect/Engine/SessionStateMachines/SessionStateMachineValidating.swift index 0b752f9c6..1099aab0f 100644 --- a/Sources/WalletConnect/Engine/SessionStateMachines/SessionStateMachineValidating.swift +++ b/Sources/WalletConnect/Engine/SessionStateMachines/SessionStateMachineValidating.swift @@ -7,17 +7,6 @@ protocol SessionStateMachineValidating { extension SessionStateMachineValidating { func validateNamespaces(_ namespaces: Set) throws { - for namespace in namespaces { - for method in namespace.methods { - if method.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty { - throw WalletConnectError.invalidMethod - } - } - for event in namespace.events { - if event.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty { - throw WalletConnectError.invalidEvent - } - } - } + try Namespace.validate(namespaces) } } diff --git a/Sources/WalletConnect/Namespace.swift b/Sources/WalletConnect/Namespace.swift index d6a3d22e7..4f8398fda 100644 --- a/Sources/WalletConnect/Namespace.swift +++ b/Sources/WalletConnect/Namespace.swift @@ -10,3 +10,24 @@ public struct Namespace: Codable, Equatable, Hashable { self.events = events } } + +internal extension Namespace { + + static func validate(_ namespaces: Set) throws { + for namespace in namespaces { + guard !namespace.chains.isEmpty else { + throw WalletConnectError.namespaceHasEmptyChains + } + for method in namespace.methods { + if method.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty { + throw WalletConnectError.invalidMethod + } + } + for event in namespace.events { + if event.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty { + throw WalletConnectError.invalidEvent + } + } + } + } +} diff --git a/Sources/WalletConnect/WalletConnectClient.swift b/Sources/WalletConnect/WalletConnectClient.swift index a6ccddeff..f8cc9f1a5 100644 --- a/Sources/WalletConnect/WalletConnectClient.swift +++ b/Sources/WalletConnect/WalletConnectClient.swift @@ -170,10 +170,11 @@ public final class WalletConnectClient { public func approve( proposalId: String, accounts: Set, - namespaces: Set) { + namespaces: Set + ) throws { //TODO - accounts should be validated for matching namespaces guard let (sessionTopic, proposal) = pairingEngine.respondSessionPropose(proposerPubKey: proposalId) else {return} - sessionEngine.settle(topic: sessionTopic, proposal: proposal, accounts: accounts, namespaces: namespaces) + try sessionEngine.settle(topic: sessionTopic, proposal: proposal, accounts: accounts, namespaces: namespaces) } /// For the responder to reject a session proposal. diff --git a/Sources/WalletConnect/WalletConnectError.swift b/Sources/WalletConnect/WalletConnectError.swift index da907252b..eb9d5217d 100644 --- a/Sources/WalletConnect/WalletConnectError.swift +++ b/Sources/WalletConnect/WalletConnectError.swift @@ -6,6 +6,7 @@ enum WalletConnectError: Error { case noSessionMatchingTopic(String) case sessionNotAcknowledged(String) case pairingNotSettled(String) + case namespaceHasEmptyChains case invalidMethod case invalidEvent case invalidUpdateExpiryValue @@ -39,6 +40,8 @@ extension WalletConnectError { return "Pairing is not settled on topic \(topic)." case .invalidUpdateExpiryValue: return "Update expiry time is out of expected range" + case .namespaceHasEmptyChains: + return "Namespace has an empty list of chain IDs." case .invalidMethod: return "Methods set is invalid." case .invalidEvent: diff --git a/Tests/IntegrationTests/ClientTest.swift b/Tests/IntegrationTests/ClientTest.swift index 2d2296360..6cc594f30 100644 --- a/Tests/IntegrationTests/ClientTest.swift +++ b/Tests/IntegrationTests/ClientTest.swift @@ -55,7 +55,7 @@ final class ClientTests: XCTestCase { let uri = try! await proposer.client.connect(namespaces: [Namespace.stub()])! try! responder.client.pair(uri: uri) responder.onSessionProposal = { [unowned self] proposal in - self.responder.client.approve(proposalId: proposal.id, accounts: [account], namespaces: []) + try? self.responder.client.approve(proposalId: proposal.id, accounts: [account], namespaces: []) } responder.onSessionSettled = { sessionSettled in // FIXME: Commented assertion @@ -81,7 +81,7 @@ final class ClientTests: XCTestCase { try! responder.client.pair(uri: uri) responder.onSessionProposal = { [unowned self] proposal in - responder.client.approve(proposalId: proposal.id, accounts: [], namespaces: []) + try? responder.client.approve(proposalId: proposal.id, accounts: [], namespaces: []) } responder.onSessionSettled = { sessionSettled in responderSettlesSessionExpectation.fulfill() @@ -119,7 +119,7 @@ final class ClientTests: XCTestCase { let uri = try! await proposer.client.connect(namespaces: [Namespace.stub()])! _ = try! responder.client.pair(uri: uri) responder.onSessionProposal = {[unowned self] proposal in - self.responder.client.approve(proposalId: proposal.id, accounts: [], namespaces: []) + try? self.responder.client.approve(proposalId: proposal.id, accounts: [], namespaces: []) } proposer.onSessionSettled = {[unowned self] settledSession in Task { @@ -142,7 +142,7 @@ final class ClientTests: XCTestCase { _ = try! responder.client.pair(uri: uri) responder.onSessionProposal = {[unowned self] proposal in - self.responder.client.approve(proposalId: proposal.id, accounts: [], namespaces: proposal.namespaces) + try? self.responder.client.approve(proposalId: proposal.id, accounts: [], namespaces: proposal.namespaces) } proposer.onSessionSettled = {[unowned self] settledSession in let requestParams = Request(id: 0, topic: settledSession.topic, method: method, params: AnyCodable(params), chainId: Blockchain("eip155:1")!) @@ -180,7 +180,7 @@ final class ClientTests: XCTestCase { let uri = try! await proposer.client.connect(namespaces: [Namespace.stub(methods: [method])])! _ = try! responder.client.pair(uri: uri) responder.onSessionProposal = {[unowned self] proposal in - self.responder.client.approve(proposalId: proposal.id, accounts: [], namespaces: proposal.namespaces) + try? self.responder.client.approve(proposalId: proposal.id, accounts: [], namespaces: proposal.namespaces) } proposer.onSessionSettled = {[unowned self] settledSession in let requestParams = Request(id: 0, topic: settledSession.topic, method: method, params: AnyCodable(params), chainId: Blockchain("eip155:1")!) @@ -211,7 +211,7 @@ final class ClientTests: XCTestCase { try! responder.client.pair(uri: uri) responder.onSessionProposal = { [unowned self] proposal in - self.responder.client.approve(proposalId: proposal.id, accounts: [], namespaces: []) + try? self.responder.client.approve(proposalId: proposal.id, accounts: [], namespaces: []) } proposer.onSessionSettled = { [unowned self] sessionSettled in self.proposer.client.ping(topic: sessionSettled.topic) { response in @@ -230,7 +230,7 @@ final class ClientTests: XCTestCase { let uri = try! await proposer.client.connect(namespaces: [Namespace.stub()])! try! responder.client.pair(uri: uri) responder.onSessionProposal = { [unowned self] proposal in - self.responder.client.approve(proposalId: proposal.id, accounts: [account], namespaces: []) + try? self.responder.client.approve(proposalId: proposal.id, accounts: [account], namespaces: []) } responder.onSessionSettled = { [unowned self] sessionSettled in try? responder.client.updateAccounts(topic: sessionSettled.topic, accounts: updateAccounts) @@ -253,7 +253,7 @@ final class ClientTests: XCTestCase { let namespacesToUpdateWith: Set = [Namespace(chains: [Blockchain("eip155:1")!, Blockchain("eip155:137")!], methods: ["xyz"], events: ["abc"])] try! responder.client.pair(uri: uri) responder.onSessionProposal = { [unowned self] proposal in - self.responder.client.approve(proposalId: proposal.id, accounts: [], namespaces: []) + try? self.responder.client.approve(proposalId: proposal.id, accounts: [], namespaces: []) } responder.onSessionSettled = { [unowned self] session in try? responder.client.updateNamespaces(topic: session.topic, namespaces: namespacesToUpdateWith) @@ -275,7 +275,7 @@ final class ClientTests: XCTestCase { let uri = try! await proposer.client.connect(namespaces: [Namespace.stub()])! try! responder.client.pair(uri: uri) responder.onSessionProposal = { [unowned self] proposal in - self.responder.client.approve(proposalId: proposal.id, accounts: [], namespaces: []) + try? self.responder.client.approve(proposalId: proposal.id, accounts: [], namespaces: []) } responder.onSessionSettled = { [unowned self] session in Thread.sleep(forTimeInterval: 1) //sleep because new expiry must be greater than current @@ -298,7 +298,7 @@ final class ClientTests: XCTestCase { try! responder.client.pair(uri: uri) let event = Session.Event(name: "type1", data: AnyCodable("event_data")) responder.onSessionProposal = { [unowned self] proposal in - self.responder.client.approve(proposalId: proposal.id, accounts: [], namespaces: [namespace]) + try? self.responder.client.approve(proposalId: proposal.id, accounts: [], namespaces: [namespace]) } responder.onSessionSettled = { [unowned self] session in responder.client.emit(topic: session.topic, event: event, chainId: Blockchain("eip155:1")!, completion: nil) @@ -318,7 +318,7 @@ final class ClientTests: XCTestCase { try! responder.client.pair(uri: uri) let event = Session.Event(name: "type2", data: AnyCodable("event_data")) responder.onSessionProposal = { [unowned self] proposal in - self.responder.client.approve(proposalId: proposal.id, accounts: [], namespaces: []) + try? self.responder.client.approve(proposalId: proposal.id, accounts: [], namespaces: []) } proposer.onSessionSettled = { [unowned self] session in proposer.client.emit(topic: session.topic, event: event, chainId: Blockchain("eip155:1")!) { error in diff --git a/Tests/WalletConnectTests/SessionEngineTests.swift b/Tests/WalletConnectTests/SessionEngineTests.swift index 4b5b2bd93..639fb33ce 100644 --- a/Tests/WalletConnectTests/SessionEngineTests.swift +++ b/Tests/WalletConnectTests/SessionEngineTests.swift @@ -59,7 +59,7 @@ final class SessionEngineTests: XCTestCase { let proposal = SessionProposal.stub(proposerPubKey: AgreementPrivateKey().publicKey.hexRepresentation) - engine.settle(topic: topicB, proposal: proposal, accounts: [], namespaces: [Namespace.stub()]) + try? engine.settle(topic: topicB, proposal: proposal, accounts: [], namespaces: [Namespace.stub()]) XCTAssertTrue(storageMock.hasSession(forTopic: topicB), "Responder must persist session on topic B") XCTAssert(networkingInteractor.didSubscribe(to: topicB), "Responder must subscribe for topic B") @@ -124,51 +124,6 @@ final class SessionEngineTests: XCTestCase { XCTAssertFalse(cryptoMock.hasPrivateKey(for: session.self.publicKey!), "Responder must remove private key") } - // TODO: Tests with nil chainId are obsolete after protocol change, check planned test before removing -// func testSessionRequestEmptyNamespaceUnmatchingMethod() { -// var didTriggerRequest = false -// engine.onSessionRequest = { _ in didTriggerRequest = true } -// -// let session = WCSession.stub(isSelfController: true) -// storageMock.setSession(session) -// -// let payload = WCRequestSubscriptionPayload.stubRequest(topic: session.topic, method: "someMethod", chainId: nil) -// networkingInteractor.wcRequestPublisherSubject.send(payload) -// -// XCTAssertTrue(networkingInteractor.didRespondError) -// XCTAssertFalse(didTriggerRequest) -// } -// -// func testSessionRequestEmptyNamespaceMatchingMethod() { -// var didTriggerRequest = false -// engine.onSessionRequest = { _ in didTriggerRequest = true } -// -// var session = WCSession.stub(isSelfController: true) -// session.updateNamespaces([Namespace(chains: [], methods: ["someMethod"], events: [])]) -// storageMock.setSession(session) -// -// let payload = WCRequestSubscriptionPayload.stubRequest(topic: session.topic, method: "someMethod", chainId: nil) -// networkingInteractor.wcRequestPublisherSubject.send(payload) -// -// XCTAssertFalse(networkingInteractor.didRespondError) -// XCTAssertTrue(didTriggerRequest) -// } -// -// func testSessionRequestUndefinedChainMatchingMethod() { -// var didTriggerRequest = false -// engine.onSessionRequest = { _ in didTriggerRequest = true } -// -// var session = WCSession.stub(isSelfController: true) -// session.updateNamespaces([Namespace(chains: [Blockchain("eip155:1")!], methods: ["someMethod"], events: [])]) -// storageMock.setSession(session) -// -// let payload = WCRequestSubscriptionPayload.stubRequest(topic: session.topic, method: "someMethod", chainId: nil) -// networkingInteractor.wcRequestPublisherSubject.send(payload) -// -// XCTAssertTrue(networkingInteractor.didRespondError) -// XCTAssertFalse(didTriggerRequest) -// } - func testSessionRequestDefinedChainMatchingMethod() { var didTriggerRequest = false engine.onSessionRequest = { _ in didTriggerRequest = true } @@ -199,39 +154,6 @@ final class SessionEngineTests: XCTestCase { XCTAssertFalse(didTriggerRequest) } -// func testSessionRequestEmptyNamespaceDefinedChainMatchingMethod() { -// var didTriggerRequest = false -// engine.onSessionRequest = { _ in didTriggerRequest = true } -// -// var session = WCSession.stub(isSelfController: true) -// session.updateNamespaces([Namespace(chains: [], methods: ["someMethod"], events: [])]) -// storageMock.setSession(session) -// -// let payload = WCRequestSubscriptionPayload.stubRequest(topic: session.topic, method: "someMethod", chainId: Blockchain("eip155:1")!) -// networkingInteractor.wcRequestPublisherSubject.send(payload) -// -// XCTAssertTrue(networkingInteractor.didRespondError) -// XCTAssertFalse(didTriggerRequest) -// } -// -// func testSessionRequestMultiNamespaceUndefinedChainMatchingMethod() { -// var didTriggerRequest = false -// engine.onSessionRequest = { _ in didTriggerRequest = true } -// -// var session = WCSession.stub(isSelfController: true) -// session.updateNamespaces([ -// Namespace(chains: [Blockchain("eip155:1")!], methods: ["someMethod"], events: []), -// Namespace(chains: [], methods: ["someMethod"], events: []) -// ]) -// storageMock.setSession(session) -// -// let payload = WCRequestSubscriptionPayload.stubRequest(topic: session.topic, method: "someMethod", chainId: nil) -// networkingInteractor.wcRequestPublisherSubject.send(payload) -// -// XCTAssertFalse(networkingInteractor.didRespondError) -// XCTAssertTrue(didTriggerRequest) -// } - func testSessionRequestMultiNamespaceDefinedChainMatchingMethod() { var didTriggerRequest = false engine.onSessionRequest = { _ in didTriggerRequest = true } From ebe89bd7bb4c1f4d8d968ef99e4c24c1823ae2ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Vants?= Date: Wed, 11 May 2022 00:52:16 -0300 Subject: [PATCH 5/5] Fixed build --- Example/ExampleApp/Wallet/WalletViewController.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Example/ExampleApp/Wallet/WalletViewController.swift b/Example/ExampleApp/Wallet/WalletViewController.swift index 08c34778c..8fc54ff81 100644 --- a/Example/ExampleApp/Wallet/WalletViewController.swift +++ b/Example/ExampleApp/Wallet/WalletViewController.swift @@ -158,7 +158,7 @@ extension WalletViewController: ProposalViewControllerDelegate { let proposal = currentProposal! currentProposal = nil let accounts = Set(proposal.namespaces.first?.chains.compactMap { Account($0.absoluteString + ":\(account)") } ?? []) - client.approve(proposalId: proposal.id, accounts: accounts, namespaces: proposal.namespaces) + try! client.approve(proposalId: proposal.id, accounts: accounts, namespaces: proposal.namespaces) } func didRejectSession() {