diff --git a/Example/ExampleApp.xcodeproj/project.pbxproj b/Example/ExampleApp.xcodeproj/project.pbxproj index bafe7c5f1..e23637099 100644 --- a/Example/ExampleApp.xcodeproj/project.pbxproj +++ b/Example/ExampleApp.xcodeproj/project.pbxproj @@ -30,6 +30,7 @@ 8448F1D427E4726F0000B866 /* WalletConnect in Frameworks */ = {isa = PBXBuildFile; productRef = 8448F1D327E4726F0000B866 /* WalletConnect */; }; 84494388278D9C1B00CC26BB /* UIAlertController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84494387278D9C1B00CC26BB /* UIAlertController.swift */; }; 8460DCFC274F98A10081F94C /* RequestViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8460DCFB274F98A10081F94C /* RequestViewController.swift */; }; + 84AA01DB28CF0CD7005D48D8 /* XCTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84AA01DA28CF0CD7005D48D8 /* XCTest.swift */; }; 84CE641F27981DED00142511 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84CE641E27981DED00142511 /* AppDelegate.swift */; }; 84CE642127981DED00142511 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84CE642027981DED00142511 /* SceneDelegate.swift */; }; 84CE642827981DF000142511 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 84CE642727981DF000142511 /* Assets.xcassets */; }; @@ -219,6 +220,7 @@ 76B6E39E2807A3B6004DF775 /* WalletViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WalletViewController.swift; sourceTree = ""; }; 84494387278D9C1B00CC26BB /* UIAlertController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIAlertController.swift; sourceTree = ""; }; 8460DCFB274F98A10081F94C /* RequestViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RequestViewController.swift; sourceTree = ""; }; + 84AA01DA28CF0CD7005D48D8 /* XCTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = XCTest.swift; sourceTree = ""; }; 84CE641C27981DED00142511 /* DApp.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = DApp.app; sourceTree = BUILT_PRODUCTS_DIR; }; 84CE641E27981DED00142511 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 84CE642027981DED00142511 /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; }; @@ -503,6 +505,7 @@ children = ( A50C036428AAD32200FE72D3 /* ClientDelegate.swift */, 767DC83428997F8E00080FA9 /* EthSendTransaction.swift */, + 84AA01DA28CF0CD7005D48D8 /* XCTest.swift */, ); path = Helpers; sourceTree = ""; @@ -1462,6 +1465,7 @@ A501AC2728C8E59800CEAA42 /* URLConfig.swift in Sources */, A5E03DFA286465C700888481 /* SignClientTests.swift in Sources */, A5E03E0F28646D8A00888481 /* WebSocketFactory.swift in Sources */, + 84AA01DB28CF0CD7005D48D8 /* XCTest.swift in Sources */, A5E03E1128646F8000888481 /* KeychainStorageMock.swift in Sources */, A5E03DFD286465D100888481 /* Stubs.swift in Sources */, ); diff --git a/Example/ExampleApp/SceneDelegate.swift b/Example/ExampleApp/SceneDelegate.swift index 7439651a2..ba57b9ff4 100644 --- a/Example/ExampleApp/SceneDelegate.swift +++ b/Example/ExampleApp/SceneDelegate.swift @@ -25,10 +25,11 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { Relay.configure(projectId: "3ca2919724fbfa5456a25194e369a8b4", socketFactory: SocketFactory()) Sign.configure(metadata: metadata) - +#if DEBUG if CommandLine.arguments.contains("-cleanInstall") { try? Sign.instance.cleanup() } +#endif guard let windowScene = (scene as? UIWindowScene) else { return } window = UIWindow(windowScene: windowScene) @@ -43,8 +44,9 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { } let wcUri = incomingURL.absoluteString.deletingPrefix("https://walletconnect.com/wc?uri=") let vc = ((window!.rootViewController as! UINavigationController).viewControllers[0] as! WalletViewController) + Task(priority: .high) {try? await Sign.instance.pair(uri: WalletConnectURI(string: wcUri)!)} vc.onClientConnected = { - Task { + Task(priority: .high) { do { try await Sign.instance.pair(uri: WalletConnectURI(string: wcUri)!) } catch { diff --git a/Example/ExampleApp/SessionProposal/Proposal.swift b/Example/ExampleApp/SessionProposal/Proposal.swift index 7e37e1500..654509aab 100644 --- a/Example/ExampleApp/SessionProposal/Proposal.swift +++ b/Example/ExampleApp/SessionProposal/Proposal.swift @@ -17,7 +17,7 @@ struct Proposal { self.proposerName = proposal.proposer.name self.proposerDescription = proposal.proposer.description self.proposerURL = proposal.proposer.url - self.iconURL = proposal.proposer.icons.first! + self.iconURL = proposal.proposer.icons.first ?? "https://avatars.githubusercontent.com/u/37784886" self.permissions = [ Namespace( chains: ["eip155:1"], diff --git a/Example/IntegrationTests/Relay/RelayClientEndToEndTests.swift b/Example/IntegrationTests/Relay/RelayClientEndToEndTests.swift index 4e4252a19..d456d69dc 100644 --- a/Example/IntegrationTests/Relay/RelayClientEndToEndTests.swift +++ b/Example/IntegrationTests/Relay/RelayClientEndToEndTests.swift @@ -98,9 +98,8 @@ final class RelayClientEndToEndTests: XCTestCase { XCTAssertEqual(subscriptionATopic, randomTopic) XCTAssertEqual(subscriptionBTopic, randomTopic) - // TODO - uncomment lines when request rebound is resolved -// XCTAssertEqual(subscriptionBPayload, payloadA) -// XCTAssertEqual(subscriptionAPayload, payloadB) + XCTAssertEqual(subscriptionBPayload, payloadA) + XCTAssertEqual(subscriptionAPayload, payloadB) } } diff --git a/Example/IntegrationTests/Sign/Helpers/XCTest.swift b/Example/IntegrationTests/Sign/Helpers/XCTest.swift new file mode 100644 index 000000000..3a1831bc5 --- /dev/null +++ b/Example/IntegrationTests/Sign/Helpers/XCTest.swift @@ -0,0 +1,19 @@ +import Foundation +import XCTest + +extension XCTest { + public func XCTAssertThrowsErrorAsync( + _ expression: @autoclosure () async throws -> T, + _ message: @autoclosure () -> String = "", + file: StaticString = #filePath, + line: UInt = #line, + _ errorHandler: (_ error: Error) -> Void = { _ in } + ) async { + do { + _ = try await expression() + XCTFail(message(), file: file, line: line) + } catch { + errorHandler(error) + } + } +} diff --git a/Example/IntegrationTests/Sign/SignClientTests.swift b/Example/IntegrationTests/Sign/SignClientTests.swift index 2e4ce354f..e00529b0b 100644 --- a/Example/IntegrationTests/Sign/SignClientTests.swift +++ b/Example/IntegrationTests/Sign/SignClientTests.swift @@ -6,7 +6,7 @@ import WalletConnectUtils final class SignClientTests: XCTestCase { - let defaultTimeout: TimeInterval = 5 + let defaultTimeout: TimeInterval = 8 var dapp: ClientDelegate! var wallet: ClientDelegate! @@ -242,140 +242,172 @@ final class SignClientTests: XCTestCase { wait(for: [expectation], timeout: defaultTimeout) } -// -// func testNewSessionOnExistingPairing() async { -// await waitClientsConnected() -// let proposerSettlesSessionExpectation = expectation(description: "Proposer settles session") -// proposerSettlesSessionExpectation.expectedFulfillmentCount = 2 -// let responderSettlesSessionExpectation = expectation(description: "Responder settles session") -// responderSettlesSessionExpectation.expectedFulfillmentCount = 2 -// var initiatedSecondSession = false -// let uri = try! await proposer.client.connect(namespaces: [Namespace.stub()])! -// -// try! await responder.client.pair(uri: uri) -// -// responder.onSessionProposal = { [unowned self] proposal in -// try? responder.client.approve(proposalId: proposal.id, accounts: [], namespaces: []) -// } -// responder.onSessionSettled = { sessionSettled in -// responderSettlesSessionExpectation.fulfill() -// } -// proposer.onSessionSettled = { [unowned self] sessionSettled in -// proposerSettlesSessionExpectation.fulfill() -// let pairingTopic = proposer.client.getSettledPairings().first!.topic -// if !initiatedSecondSession { -// Task { -// let _ = try! await proposer.client.connect(namespaces: [Namespace.stub()], topic: pairingTopic) -// } -// initiatedSecondSession = true -// } -// } -// wait(for: [proposerSettlesSessionExpectation, responderSettlesSessionExpectation], timeout: defaultTimeout) -// } -// -// func testSessionPing() async { -// await waitClientsConnected() -// let proposerReceivesPingResponseExpectation = expectation(description: "Proposer receives ping response") -// let uri = try! await proposer.client.connect(namespaces: [Namespace.stub()])! -// -// try! await responder.client.pair(uri: uri) -// responder.onSessionProposal = { [unowned self] proposal in -// 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 -// XCTAssertTrue(response.isSuccess) -// proposerReceivesPingResponseExpectation.fulfill() -// } -// } -// wait(for: [proposerReceivesPingResponseExpectation], timeout: defaultTimeout) -// } -// -// func testSuccessfulSessionUpdateNamespaces() async { -// await waitClientsConnected() -// let proposerSessionUpdateExpectation = expectation(description: "Proposer updates session methods on responder request") -// let responderSessionUpdateExpectation = expectation(description: "Responder updates session methods on proposer response") -// let uri = try! await proposer.client.connect(namespaces: [Namespace.stub()])! -// let namespacesToUpdateWith: Set = [Namespace(chains: [Blockchain("eip155:1")!, Blockchain("eip155:137")!], methods: ["xyz"], events: ["abc"])] -// try! await responder.client.pair(uri: uri) -// responder.onSessionProposal = { [unowned self] proposal in -// 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) -// } -// proposer.onSessionUpdateNamespaces = { topic, namespaces in -// XCTAssertEqual(namespaces, namespacesToUpdateWith) -// proposerSessionUpdateExpectation.fulfill() -// } -// responder.onSessionUpdateNamespaces = { topic, namespaces in -// XCTAssertEqual(namespaces, namespacesToUpdateWith) -// responderSessionUpdateExpectation.fulfill() -// } -// wait(for: [proposerSessionUpdateExpectation, responderSessionUpdateExpectation], timeout: defaultTimeout) -// } -// -// func testSuccessfulSessionUpdateExpiry() async { -// await waitClientsConnected() -// let proposerSessionUpdateExpectation = expectation(description: "Proposer updates session expiry on responder request") -// let responderSessionUpdateExpectation = expectation(description: "Responder updates session expiry on proposer response") -// let uri = try! await proposer.client.connect(namespaces: [Namespace.stub()])! -// try! await responder.client.pair(uri: uri) -// responder.onSessionProposal = { [unowned self] proposal in -// 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 -// try? responder.client.updateExpiry(topic: session.topic) -// } -// proposer.onSessionUpdateExpiry = { _, _ in -// proposerSessionUpdateExpectation.fulfill() -// } -// responder.onSessionUpdateExpiry = { _, _ in -// responderSessionUpdateExpectation.fulfill() -// } -// wait(for: [proposerSessionUpdateExpectation, responderSessionUpdateExpectation], timeout: defaultTimeout) -// } -// -// func testSessionEventSucceeds() async { -// await waitClientsConnected() -// let proposerReceivesEventExpectation = expectation(description: "Proposer receives event") -// 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! await responder.client.pair(uri: uri) -// let event = Session.Event(name: "type1", data: AnyCodable("event_data")) -// responder.onSessionProposal = { [unowned self] proposal in -// try? self.responder.client.approve(proposalId: proposal.id, accounts: [], namespaces: [namespace]) -// } -// responder.onSessionSettled = { [unowned self] session in -// Task{try? await responder.client.emit(topic: session.topic, event: event, chainId: Blockchain("eip155:1")!)} -// } -// proposer.onEventReceived = { event, _ in -// XCTAssertEqual(event, event) -// proposerReceivesEventExpectation.fulfill() -// } -// wait(for: [proposerReceivesEventExpectation], timeout: defaultTimeout) -// } -// -// func testSessionEventFails() async { -// await waitClientsConnected() -// let proposerReceivesEventExpectation = expectation(description: "Proposer receives event") -// proposerReceivesEventExpectation.isInverted = true -// let uri = try! await proposer.client.connect(namespaces: [Namespace.stub()])! -// -// try! await responder.client.pair(uri: uri) -// let event = Session.Event(name: "type2", data: AnyCodable("event_data")) -// responder.onSessionProposal = { [unowned self] proposal in -// try? self.responder.client.approve(proposalId: proposal.id, accounts: [], namespaces: []) -// } -// proposer.onSessionSettled = { [unowned self] session in -// Task {await XCTAssertThrowsErrorAsync(try await proposer.client.emit(topic: session.topic, event: event, chainId: Blockchain("eip155:1")!))} -// } -// responder.onEventReceived = { _, _ in -// XCTFail() -// proposerReceivesEventExpectation.fulfill() -// } -// wait(for: [proposerReceivesEventExpectation], timeout: defaultTimeout) -// } + + func testNewSessionOnExistingPairing() async { + let dappSettlementExpectation = expectation(description: "Dapp settles session") + dappSettlementExpectation.expectedFulfillmentCount = 2 + let walletSettlementExpectation = expectation(description: "Wallet settles session") + walletSettlementExpectation.expectedFulfillmentCount = 2 + let requiredNamespaces = ProposalNamespace.stubRequired() + let sessionNamespaces = SessionNamespace.make(toRespond: requiredNamespaces) + var initiatedSecondSession = false + + wallet.onSessionProposal = { [unowned self] proposal in + Task(priority: .high) { + do { + try await wallet.client.approve(proposalId: proposal.id, namespaces: sessionNamespaces) + } catch { + XCTFail("\(error)") + } + } + } + dapp.onSessionSettled = { [unowned self] _ in + dappSettlementExpectation.fulfill() + let pairingTopic = dapp.client.getPairings().first!.topic + if !initiatedSecondSession { + Task(priority: .high) { + let _ = try! await dapp.client.connect(requiredNamespaces: requiredNamespaces, topic: pairingTopic) + } + initiatedSecondSession = true + } + } + wallet.onSessionSettled = { _ in + walletSettlementExpectation.fulfill() + } + + let uri = try! await dapp.client.connect(requiredNamespaces: requiredNamespaces) + try! await wallet.client.pair(uri: uri!) + wait(for: [dappSettlementExpectation, walletSettlementExpectation], timeout: defaultTimeout) + + } + + func testSessionPing() async { + let expectation = expectation(description: "Dapp receives ping response") + let requiredNamespaces = ProposalNamespace.stubRequired() + let sessionNamespaces = SessionNamespace.make(toRespond: requiredNamespaces) + + wallet.onSessionProposal = { [unowned self] proposal in + Task(priority: .high) { + try await wallet.client.approve(proposalId: proposal.id, namespaces: sessionNamespaces) + } + } + dapp.onSessionSettled = { [unowned self] settledSession in + dapp.client.ping(topic: settledSession.topic) {_ in + expectation.fulfill() + } + } + let uri = try! await dapp.client.connect(requiredNamespaces: requiredNamespaces) + try! await wallet.client.pair(uri: uri!) + wait(for: [expectation], timeout: defaultTimeout) + } + + + func testSuccessfulSessionUpdateNamespaces() async { + let expectation = expectation(description: "Dapp updates namespaces") + let requiredNamespaces = ProposalNamespace.stubRequired() + let sessionNamespaces = SessionNamespace.make(toRespond: requiredNamespaces) + + wallet.onSessionProposal = { [unowned self] proposal in + Task(priority: .high) { + try await wallet.client.approve(proposalId: proposal.id, namespaces: sessionNamespaces) + } + } + dapp.onSessionSettled = { [unowned self] settledSession in + Task(priority: .high) { + try! await wallet.client.update(topic: settledSession.topic, namespaces: sessionNamespaces) + } + } + dapp.onSessionUpdateNamespaces = { _, _ in + expectation.fulfill() + } + let uri = try! await dapp.client.connect(requiredNamespaces: requiredNamespaces) + try! await wallet.client.pair(uri: uri!) + wait(for: [expectation], timeout: defaultTimeout) + } + + + func testSuccessfulSessionExtend() async { + let expectation = expectation(description: "Dapp extends session") + + let requiredNamespaces = ProposalNamespace.stubRequired() + let sessionNamespaces = SessionNamespace.make(toRespond: requiredNamespaces) + + wallet.onSessionProposal = { [unowned self] proposal in + Task(priority: .high) { + try await wallet.client.approve(proposalId: proposal.id, namespaces: sessionNamespaces) + } + } + + dapp.onSessionExtend = { _, _ in + expectation.fulfill() + } + + dapp.onSessionSettled = { [unowned self] settledSession in + Task(priority: .high) { + try! await wallet.client.extend(topic: settledSession.topic) + } + } + + let uri = try! await dapp.client.connect(requiredNamespaces: requiredNamespaces) + try! await wallet.client.pair(uri: uri!) + + wait(for: [expectation], timeout: defaultTimeout) + } + + func testSessionEventSucceeds() async { + let expectation = expectation(description: "Dapp receives session event") + + let requiredNamespaces = ProposalNamespace.stubRequired() + let sessionNamespaces = SessionNamespace.make(toRespond: requiredNamespaces) + let event = Session.Event(name: "any", data: AnyCodable("event_data")) + let chain = Blockchain("eip155:1")! + + wallet.onSessionProposal = { [unowned self] proposal in + Task(priority: .high) { + try await wallet.client.approve(proposalId: proposal.id, namespaces: sessionNamespaces) + } + } + + dapp.onEventReceived = { _, _ in + expectation.fulfill() + } + + dapp.onSessionSettled = { [unowned self] settledSession in + Task(priority: .high) { + try! await wallet.client.emit(topic: settledSession.topic, event: event, chainId: chain) + } + } + + let uri = try! await dapp.client.connect(requiredNamespaces: requiredNamespaces) + try! await wallet.client.pair(uri: uri!) + + wait(for: [expectation], timeout: defaultTimeout) + } + + func testSessionEventFails() async { + let expectation = expectation(description: "Dapp receives session event") + + let requiredNamespaces = ProposalNamespace.stubRequired() + let sessionNamespaces = SessionNamespace.make(toRespond: requiredNamespaces) + let event = Session.Event(name: "unknown", data: AnyCodable("event_data")) + let chain = Blockchain("eip155:1")! + + wallet.onSessionProposal = { [unowned self] proposal in + Task(priority: .high) { + try await wallet.client.approve(proposalId: proposal.id, namespaces: sessionNamespaces) + } + } + + dapp.onSessionSettled = { [unowned self] settledSession in + Task(priority: .high) { + await XCTAssertThrowsErrorAsync(try await wallet.client.emit(topic: settledSession.topic, event: event, chainId: chain)) + expectation.fulfill() + } + } + + let uri = try! await dapp.client.connect(requiredNamespaces: requiredNamespaces) + try! await wallet.client.pair(uri: uri!) + + wait(for: [expectation], timeout: defaultTimeout) + } } diff --git a/Example/IntegrationTests/Stubs/Stubs.swift b/Example/IntegrationTests/Stubs/Stubs.swift index d4f1f9eda..e58668423 100644 --- a/Example/IntegrationTests/Stubs/Stubs.swift +++ b/Example/IntegrationTests/Stubs/Stubs.swift @@ -6,7 +6,7 @@ extension ProposalNamespace { "eip155": ProposalNamespace( chains: [Blockchain("eip155:1")!], methods: ["personal_sign", "eth_sendTransaction"], - events: []) + events: ["any"]) ] } } diff --git a/Sources/Auth/Services/Wallet/WalletPairService.swift b/Sources/Auth/Services/Wallet/WalletPairService.swift index 355de0a29..7868c01a4 100644 --- a/Sources/Auth/Services/Wallet/WalletPairService.swift +++ b/Sources/Auth/Services/Wallet/WalletPairService.swift @@ -25,11 +25,11 @@ actor WalletPairService { throw Errors.pairingAlreadyExist } var pairing = WCPairing(uri: uri) - try await networkingInteractor.subscribe(topic: pairing.topic) let symKey = try SymmetricKey(hex: uri.symKey) try kms.setSymmetricKey(symKey, for: pairing.topic) pairing.activate() pairingStorage.setPairing(pairing) + try await networkingInteractor.subscribe(topic: pairing.topic) } func hasPairing(for topic: String) -> Bool { diff --git a/Sources/WalletConnectRelay/EnvironmentInfo.swift b/Sources/WalletConnectRelay/EnvironmentInfo.swift index 9e5f873ef..e00872260 100644 --- a/Sources/WalletConnectRelay/EnvironmentInfo.swift +++ b/Sources/WalletConnectRelay/EnvironmentInfo.swift @@ -18,7 +18,7 @@ enum EnvironmentInfo { } static var sdkVersion: String { - "v0.10.2-rc.0" + "v0.10.3-rc.0" } static var operatingSystem: String { diff --git a/Sources/WalletConnectRelay/RelayClient.swift b/Sources/WalletConnectRelay/RelayClient.swift index b6aef67c0..94ab8ceab 100644 --- a/Sources/WalletConnectRelay/RelayClient.swift +++ b/Sources/WalletConnectRelay/RelayClient.swift @@ -242,8 +242,8 @@ public final class RelayClient { if let request = tryDecode(RPCRequest.self, from: payload) { if let params = try? request.params?.get(Subscription.Params.self) { do { - try rpcHistory.set(request, forTopic: params.data.topic, emmitedBy: .remote) try acknowledgeRequest(request) + try rpcHistory.set(request, forTopic: params.data.topic, emmitedBy: .remote) messagePublisherSubject.send((params.data.topic, params.data.message)) } catch { logger.error("[RelayClient] RPC History 'set()' error: \(error)") @@ -278,11 +278,16 @@ public final class RelayClient { private func acknowledgeRequest(_ request: RPCRequest) throws { let response = RPCResponse(matchingRequest: request, result: true) - try rpcHistory.resolve(response) let message = try response.asJSONEncodedString() - dispatcher.send(message) { [weak self] in + dispatcher.send(message) { [unowned self] in if let error = $0 { - self?.logger.debug("Failed to dispatch response: \(response), error: \(error)") + logger.debug("Failed to dispatch response: \(response), error: \(error)") + } else { + do { + try rpcHistory.resolve(response) + } catch { + logger.debug(error) + } } } } diff --git a/Sources/WalletConnectSign/Engine/Controller/ControllerSessionStateMachine.swift b/Sources/WalletConnectSign/Engine/Controller/ControllerSessionStateMachine.swift index 146f750af..b76b63d50 100644 --- a/Sources/WalletConnectSign/Engine/Controller/ControllerSessionStateMachine.swift +++ b/Sources/WalletConnectSign/Engine/Controller/ControllerSessionStateMachine.swift @@ -29,7 +29,7 @@ final class ControllerSessionStateMachine { func update(topic: String, namespaces: [String: SessionNamespace]) async throws { let session = try getSession(for: topic) - try validateControlledAcknowledged(session) + try validateController(session) try Namespace.validate(namespaces) logger.debug("Controller will update methods") sessionStore.setSession(session) @@ -38,7 +38,7 @@ final class ControllerSessionStateMachine { func extend(topic: String, by ttl: Int64) async throws { var session = try getSession(for: topic) - try validateControlledAcknowledged(session) + try validateController(session) try session.updateExpiry(by: ttl) let newExpiry = Int64(session.expiryDate.timeIntervalSince1970 ) sessionStore.setSession(session) @@ -101,10 +101,7 @@ final class ControllerSessionStateMachine { } } - private func validateControlledAcknowledged(_ session: WCSession) throws { - guard session.acknowledged else { - throw WalletConnectError.sessionNotAcknowledged(session.topic) - } + private func validateController(_ session: WCSession) throws { guard session.selfIsController else { throw WalletConnectError.unauthorizedNonControllerCall } diff --git a/Sources/WalletConnectSign/Engine/Controller/PairEngine.swift b/Sources/WalletConnectSign/Engine/Controller/PairEngine.swift index 969d4302b..9ad8956b7 100644 --- a/Sources/WalletConnectSign/Engine/Controller/PairEngine.swift +++ b/Sources/WalletConnectSign/Engine/Controller/PairEngine.swift @@ -20,11 +20,11 @@ actor PairEngine { throw WalletConnectError.pairingAlreadyExist } var pairing = WCPairing(uri: uri) - try await networkingInteractor.subscribe(topic: pairing.topic) let symKey = try SymmetricKey(hex: uri.symKey) try kms.setSymmetricKey(symKey, for: pairing.topic) pairing.activate() pairingStore.setPairing(pairing) + try await networkingInteractor.subscribe(topic: pairing.topic) } func hasPairing(for topic: String) -> Bool { diff --git a/Sources/WalletConnectSign/Types/Session/WCSession.swift b/Sources/WalletConnectSign/Types/Session/WCSession.swift index cb0771d43..c53855dc0 100644 --- a/Sources/WalletConnectSign/Types/Session/WCSession.swift +++ b/Sources/WalletConnectSign/Types/Session/WCSession.swift @@ -172,7 +172,7 @@ struct WCSession: SequenceObject, Equatable { mutating func updateExpiry(to expiry: Int64) throws { let newExpiryDate = Date(timeIntervalSince1970: TimeInterval(expiry)) let maxExpiryDate = Date(timeIntervalSinceNow: TimeInterval(WCSession.defaultTimeToLive)) - guard newExpiryDate > expiryDate && newExpiryDate <= maxExpiryDate else { + guard newExpiryDate >= expiryDate && newExpiryDate <= maxExpiryDate else { throw WalletConnectError.invalidUpdateExpiryValue } self.expiryDate = newExpiryDate diff --git a/Tests/WalletConnectSignTests/ControllerSessionStateMachineTests.swift b/Tests/WalletConnectSignTests/ControllerSessionStateMachineTests.swift index a4b5e4665..539b335ec 100644 --- a/Tests/WalletConnectSignTests/ControllerSessionStateMachineTests.swift +++ b/Tests/WalletConnectSignTests/ControllerSessionStateMachineTests.swift @@ -43,14 +43,6 @@ class ControllerSessionStateMachineTests: XCTestCase { } } - func testUpdateNamespacesErrorSessionNotAcknowledged() async { - let session = WCSession.stub(acknowledged: false) - storageMock.setSession(session) - await XCTAssertThrowsErrorAsync( try await sut.update(topic: session.topic, namespaces: SessionNamespace.stubDictionary())) { error in - XCTAssertTrue(error.isSessionNotAcknowledgedError) - } - } - // func testUpdateNamespacesErrorInvalidMethod() { // let session = WCSession.stub(isSelfController: true) // storageMock.setSession(session) diff --git a/Tests/WalletConnectSignTests/Helpers/Error+Extension.swift b/Tests/WalletConnectSignTests/Helpers/Error+Extension.swift index 378a2abe9..9a37db06c 100644 --- a/Tests/WalletConnectSignTests/Helpers/Error+Extension.swift +++ b/Tests/WalletConnectSignTests/Helpers/Error+Extension.swift @@ -19,11 +19,6 @@ extension Error { return true } - var isSessionNotAcknowledgedError: Bool { - guard case .sessionNotAcknowledged = wcError else { return false } - return true - } - var isInvalidMethodError: Bool { guard case .invalidMethod = wcError else { return false } return true